diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 02:37:40 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 02:37:40 +0000 |
commit | 9ad5c7b5e23b4940e7a3ea3ca3a6fb77e6a8fab0 (patch) | |
tree | d088b5210e77d9fa91d954d8550e00e372b47378 /apps | |
download | ktorrent-9ad5c7b5e23b4940e7a3ea3ca3a6fb77e6a8fab0.tar.gz ktorrent-9ad5c7b5e23b4940e7a3ea3ca3a6fb77e6a8fab0.zip |
Updated to final KDE3 ktorrent release (2.2.6)
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/ktorrent@1077377 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'apps')
154 files changed, 20401 insertions, 0 deletions
diff --git a/apps/Makefile.am b/apps/Makefile.am new file mode 100644 index 0000000..09a6602 --- /dev/null +++ b/apps/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = ktorrent ktcachecheck kttorinfo ktupnptest diff --git a/apps/ktcachecheck/Makefile.am b/apps/ktcachecheck/Makefile.am new file mode 100644 index 0000000..19f89d4 --- /dev/null +++ b/apps/ktcachecheck/Makefile.am @@ -0,0 +1,12 @@ +INCLUDES = -I$(srcdir)/../../libktorrent $(all_includes) +METASOURCES = AUTO + +bin_PROGRAMS = ktcachecheck + +ktcachecheck_SOURCES = cachecheck.cpp cachechecker.cpp singlecachechecker.cpp \ + multicachechecker.cpp +ktcachecheck_LDFLAGS = $(KDE_RPATH) $(all_libraries) +ktcachecheck_LDADD = $(LIB_KPARTS) ../../libktorrent/libktorrent.la \ + $(LIB_KFILE) $(LIB_KIO) +noinst_HEADERS = cachechecker.h singlecachechecker.h multicachechecker.h +KDE_CXXFLAGS = $(USE_EXCEPTIONS) $(USE_RTTI) diff --git a/apps/ktcachecheck/cachecheck.cpp b/apps/ktcachecheck/cachecheck.cpp new file mode 100644 index 0000000..0a143c5 --- /dev/null +++ b/apps/ktcachecheck/cachecheck.cpp @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <iostream> +#include <stdlib.h> +#include <util/log.h> +#include <util/error.h> +#include <util/functions.h> +#include <torrent/globals.h> +#include <torrent/torrent.h> +#include "singlecachechecker.h" +#include "multicachechecker.h" + + +using namespace bt; +using namespace ktdebug; + +void Help() +{ + Out() << "Usage : cachecheck <directory_containing_cache>" << endl; + Out() << "OR cachecheck <torrent> <cache_file_or_dir> <index_file>" << endl; + exit(0); +} + +int main(int argc,char** argv) +{ + Globals::instance().setDebugMode(true); + Globals::instance().initLog("cachecheck.log"); + CacheChecker* cc = 0; + try + { + Torrent tor; + QString tor_file,cache,index; + + if (argc == 2) + { + QString cache_dir = argv[1]; + if (!cache_dir.endsWith(bt::DirSeparator())) + cache_dir += bt::DirSeparator(); + + tor_file = cache_dir + "torrent"; + cache = cache_dir + "cache"; + index = cache_dir + "index"; + } + else if (argc == 4) + { + tor_file = argv[1]; + cache = argv[2]; + index = argv[3]; + } + else + { + Help(); + } + + + Out() << "Loading torrent : " << tor_file << " ... " << endl; + tor.load(tor_file,false); + if (tor.isMultiFile()) + cc = new MultiCacheChecker(tor); + else + cc = new SingleCacheChecker(tor); + + cc->check(cache,index); + if (cc->foundFailedChunks()) + { + std::string str; + std::cout << "Found failed chunks, fix index file ? (y/n) "; + std::cin >> str; + if (str == "y" || str == "Y") + { + Out() << "Fixing index file ..." << endl; + cc->fixIndex(); + Out() << "Finished !" << endl; + } + } + } + catch (Error & e) + { + Out() << "Error : " << e.toString() << endl; + } + + delete cc; + Globals::cleanup(); + return 0; +} diff --git a/apps/ktcachecheck/cachechecker.cpp b/apps/ktcachecheck/cachechecker.cpp new file mode 100644 index 0000000..6cdf3e5 --- /dev/null +++ b/apps/ktcachecheck/cachechecker.cpp @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <klocale.h> +#include <util/log.h> +#include <util/file.h> +#include <util/error.h> +#include <util/array.h> +#include <torrent/globals.h> +#include <torrent/torrent.h> +#include <torrent/chunkmanager.h> +#include "cachechecker.h" + +using namespace bt; + +namespace ktdebug +{ + + CacheChecker::CacheChecker(bt::Torrent & tor) : tor(tor) + {} + + + CacheChecker::~CacheChecker() + {} + + void CacheChecker::loadIndex(const QString & index_file) + { + this->index_file = index_file; + File fptr; + if (!fptr.open(index_file,"rb")) + throw Error(i18n("Cannot open index file %1 : %2").arg(index_file).arg(fptr.errorString())); + + if (fptr.seek(File::END,0) != 0) + { + fptr.seek(File::BEGIN,0); + + while (!fptr.eof()) + { + NewChunkHeader hdr; + fptr.read(&hdr,sizeof(NewChunkHeader)); + downloaded_chunks.insert(hdr.index); + } + } + } + + struct ChunkHeader + { + unsigned int index; // the Chunks index + unsigned int deprecated; // offset in cache file + }; + + + void CacheChecker::fixIndex() + { + if (failed_chunks.size() == 0 && extra_chunks.size() == 0) + return; + + File fptr; + if (!fptr.open(index_file,"wb")) + throw Error(i18n("Cannot open index file %1 : %2").arg(index_file).arg(fptr.errorString())); + + std::set<bt::Uint32>::iterator i; + // first remove failed chunks from downloaded + if (failed_chunks.size() > 0) + { + i = failed_chunks.begin(); + while (i != failed_chunks.end()) + { + downloaded_chunks.erase(*i); + i++; + } + } + + // add extra chunks to download + if (extra_chunks.size() > 0) + { + i = extra_chunks.begin(); + while (i != extra_chunks.end()) + { + downloaded_chunks.insert(*i); + i++; + } + } + + // write remaining chunks + i = downloaded_chunks.begin(); + while (i != downloaded_chunks.end()) + { + ChunkHeader ch = {*i,0}; + fptr.write(&ch,sizeof(ChunkHeader)); + i++; + } + } +} diff --git a/apps/ktcachecheck/cachechecker.h b/apps/ktcachecheck/cachechecker.h new file mode 100644 index 0000000..def3e6d --- /dev/null +++ b/apps/ktcachecheck/cachechecker.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 DEBUGCACHECHECKER_H +#define DEBUGCACHECHECKER_H + +#include <set> +#include <qstring.h> +#include <util/functions.h> + +namespace bt +{ + class Torrent; +} + +namespace ktdebug +{ + + /** + * @author Joris Guisson + */ + class CacheChecker + { + public: + CacheChecker(bt::Torrent & tor); + virtual ~CacheChecker(); + + void loadIndex(const QString & index_file); + void fixIndex(); + bool foundFailedChunks() const {return failed_chunks.size() > 0;} + bool foundExtraChunks() const {return extra_chunks.size() > 0;} + + virtual void check(const QString & cache,const QString & index) = 0; + protected: + bt::Torrent & tor; + QString index_file; + std::set<bt::Uint32> downloaded_chunks; + std::set<bt::Uint32> failed_chunks; + std::set<bt::Uint32> extra_chunks; + }; + + +} + +#endif diff --git a/apps/ktcachecheck/multicachechecker.cpp b/apps/ktcachecheck/multicachechecker.cpp new file mode 100644 index 0000000..df80535 --- /dev/null +++ b/apps/ktcachecheck/multicachechecker.cpp @@ -0,0 +1,143 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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/log.h> +#include <util/file.h> +#include <util/error.h> +#include <util/array.h> +#include <util/functions.h> +#include <torrent/globals.h> +#include <torrent/torrent.h> +#include <torrent/chunkmanager.h> +#include "multicachechecker.h" + +using namespace bt; + +namespace ktdebug +{ + + MultiCacheChecker::MultiCacheChecker(bt::Torrent& tor): CacheChecker(tor) + {} + + + MultiCacheChecker::~MultiCacheChecker() + {} + + + void MultiCacheChecker::check(const QString& cache_dir, const QString& index) + { + loadIndex(index); + QString cache = cache_dir; + if (!cache.endsWith(bt::DirSeparator())) + cache += bt::DirSeparator(); + + Uint32 num_chunks = tor.getNumChunks(); + Uint64 curr_file_off = 0; + Uint32 curr_file = 0; + Uint64 chunk_size = tor.getChunkSize(); + + Array<Uint8> buf((Uint32)tor.getChunkSize()); + Uint32 num_ok = 0,num_not_ok = 0,num_not_downloaded = 0,extra_ok = 0; + + for (Uint32 i = 0;i < num_chunks;i++) + { + if (i % 100 == 0) + Out() << "Checked " << i << " chunks" << endl; + + + + Uint64 size = chunk_size; + if (i == tor.getNumChunks() - 1 && tor.getFileLength() % chunk_size != 0) + size = tor.getFileLength() % chunk_size; + + //Out() << "Loading chunk (size = " << size << ")" << endl; + Uint64 bytes_offset = 0; + while (bytes_offset < size) + { + TorrentFile & tf = tor.getFile(curr_file); +// Out() << "Current file : " << tf.getPath() << " (" << curr_file << ")" << endl; + Uint64 to_read = size - bytes_offset; +// Out() << "to_read = " << to_read << endl; + if (to_read <= tf.getSize() - curr_file_off) + { + // we can read the chunk from this file + File fptr; + if (!fptr.open(cache + tf.getPath(),"rb")) + throw Error(QString("Cannot open %1 : %2").arg(cache + tf.getPath()).arg(fptr.errorString())); + + fptr.seek(File::BEGIN,curr_file_off); + fptr.read(buf + bytes_offset,to_read); + bytes_offset += to_read; + curr_file_off += to_read; + } + else + { + + // read partially the data which can be read + to_read = tf.getSize() - curr_file_off; +// Out() << "Partially reading " << to_read << endl; + File fptr; + if (!fptr.open(cache + tf.getPath(),"rb")) + throw Error(QString("Cannot open %1 : %2").arg(cache + tf.getPath()).arg(fptr.errorString())); + + fptr.seek(File::BEGIN,curr_file_off); + fptr.read(buf + bytes_offset,to_read); + bytes_offset += to_read; + // update curr_file and offset + curr_file++; + curr_file_off = 0; + } + } // end file reading while + + // calculate hash and check it + SHA1Hash h = SHA1Hash::generate(buf,size); + if (h != tor.getHash(i)) + { + if (downloaded_chunks.count(i) == 0) + { + num_not_downloaded++; + continue; + } + Out() << "Chunk " << i << " Failed :" << endl; + Out() << "\tShould be : " << tor.getHash(i).toString() << endl; + Out() << "\tIs : " << h.toString() << endl; + num_not_ok++; + failed_chunks.insert(i); + } + else + { + if (downloaded_chunks.count(i) == 0) + { + extra_ok++; + extra_chunks.insert(i); + continue; + } + num_ok++; + } + } + + Out() << "Cache Check Summary" << endl; + Out() << "===================" << endl; + Out() << "Extra Chunks : " << extra_ok << endl; + Out() << "Chunks OK : " << num_ok << endl; + Out() << "Chunks Not Downloaded : " << num_not_downloaded << endl; + Out() << "Chunks Failed : " << num_not_ok << endl; + } + +} diff --git a/apps/ktcachecheck/multicachechecker.h b/apps/ktcachecheck/multicachechecker.h new file mode 100644 index 0000000..1df95f5 --- /dev/null +++ b/apps/ktcachecheck/multicachechecker.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 DEBUGMULTICACHECHECKER_H +#define DEBUGMULTICACHECHECKER_H + +#include "cachechecker.h" + +namespace ktdebug +{ + + /** + @author Joris Guisson + */ + class MultiCacheChecker : public CacheChecker + { + public: + MultiCacheChecker(bt::Torrent& tor); + + ~MultiCacheChecker(); + + virtual void check(const QString& cache, const QString& index); + + }; + +} + +#endif diff --git a/apps/ktcachecheck/singlecachechecker.cpp b/apps/ktcachecheck/singlecachechecker.cpp new file mode 100644 index 0000000..822c28a --- /dev/null +++ b/apps/ktcachecheck/singlecachechecker.cpp @@ -0,0 +1,110 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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/log.h> +#include <util/file.h> +#include <util/error.h> +#include <util/array.h> +#include <util/functions.h> +#include <torrent/globals.h> +#include <torrent/torrent.h> +#include <torrent/chunkmanager.h> +#include "singlecachechecker.h" + +using namespace bt; + +namespace ktdebug +{ + + SingleCacheChecker::SingleCacheChecker(bt::Torrent& tor): CacheChecker(tor) + {} + + + SingleCacheChecker::~SingleCacheChecker() + {} + + + void SingleCacheChecker::check(const QString& cache, const QString& index) + { + loadIndex(index); + Uint32 num_chunks = tor.getNumChunks(); + File fptr; + if (!fptr.open(cache,"rb")) + { + throw Error(QString("Cannot open file : %1 : %2") + .arg(cache).arg( fptr.errorString())); + } + + Uint32 num_ok = 0,num_not_ok = 0,num_not_downloaded = 0,extra_ok = 0; + + Array<Uint8> buf((Uint32)tor.getChunkSize()); + for (Uint32 i = 0;i < num_chunks;i++) + { + if (i % 100 == 0) + Out(SYS_GEN|LOG_DEBUG) << "Checked " << i << " chunks" << endl; + // Out() << "Chunk " << i << " : "; + if (!fptr.eof()) + { + Uint32 size = i == num_chunks - 1 && tor.getFileLength() % tor.getChunkSize() > 0 ? + tor.getFileLength() % tor.getChunkSize() : (Uint32)tor.getChunkSize(); + fptr.seek(File::BEGIN,(Int64)i*tor.getChunkSize()); + fptr.read(buf,size); + SHA1Hash h = SHA1Hash::generate(buf,size); + bool ok = (h == tor.getHash(i)); + if (ok) + { + if (downloaded_chunks.count(i) == 0) + { + extra_ok++; + extra_chunks.insert(i); + continue; + } + num_ok++; + // Out() << "OK" << endl; + } + else + { + if (downloaded_chunks.count(i) == 0) + { + num_not_downloaded++; + continue; + } + Out() << "Chunk " << i << " Failed :" << endl; + Out() << "\tShould be : " << tor.getHash(i).toString() << endl; + Out() << "\tIs : " << h.toString() << endl; + num_not_ok++; + failed_chunks.insert(i); + } + + } + else + { + num_not_downloaded++; + //Out() << "Not Downloaded" << endl; + } + } + Out() << "Cache Check Summary" << endl; + Out() << "===================" << endl; + Out() << "Extra Chunks : " << extra_ok << endl; + Out() << "Chunks OK : " << num_ok << endl; + Out() << "Chunks Not Downloaded : " << num_not_downloaded << endl; + Out() << "Chunks Failed : " << num_not_ok << endl; + } + +} diff --git a/apps/ktcachecheck/singlecachechecker.h b/apps/ktcachecheck/singlecachechecker.h new file mode 100644 index 0000000..2d7b178 --- /dev/null +++ b/apps/ktcachecheck/singlecachechecker.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 DEBUGSINGLECACHECHECKER_H +#define DEBUGSINGLECACHECHECKER_H + +#include "cachechecker.h" + +namespace ktdebug +{ + + /** + @author Joris Guisson + */ + class SingleCacheChecker : public CacheChecker + { + public: + SingleCacheChecker(bt::Torrent& tor); + virtual ~SingleCacheChecker(); + + virtual void check(const QString& cache, const QString& index); + + }; + +} + +#endif diff --git a/apps/ktorrent/Makefile.am b/apps/ktorrent/Makefile.am new file mode 100644 index 0000000..d9b91ae --- /dev/null +++ b/apps/ktorrent/Makefile.am @@ -0,0 +1,65 @@ +## Makefile.am for ktorrent +SUBDIRS = groups newui +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +bin_PROGRAMS = ktorrent + + + +# set the include path for X, qt and KDE +INCLUDES = -I$(top_builddir)/ktorrent/libktorrent -I$(top_builddir)/libktorrent/ -I$(srcdir)/../../libktorrent \ + $(all_includes) + +# the library search path. +ktorrent_LDFLAGS = $(KDE_RPATH) $(all_libraries) + +# the libraries to link against. +ktorrent_LDADD = ../../apps/ktorrent/newui/libnewui.la $(LIB_KFILE) \ + $(LIB_KIO) $(LIB_KPARTS) ../../apps/ktorrent/groups/libgroups.la \ + ../../libktorrent/libktorrent.la + +# which sources should be compiled for ktorrent +ktorrent_SOURCES = addpeerwidget.cpp addpeerwidget.h addpeerwidgetbase.ui \ + advancedpref.ui dcopinterface.skel downloadpref.ui fileselectdlg.cpp \ + fileselectdlgbase.ui generalpref.ui ipfilterwidget.cpp ipfilterwidgetbase.ui ktorrent.cpp \ + ktorrentapp.cpp ktorrentcore.cpp ktorrentdcop.cpp ktorrentview.cpp ktorrentviewitem.cpp \ + ktorrentviewmenu.cpp leaktrace.cpp main.cpp pastedialog.cpp pastedlgbase.ui pref.cpp \ + queuedialog.cpp queuedialog.h queuedlg.ui scandialog.cpp scandlgbase.ui \ + speedlimitsdlg.cpp speedlimitsdlgbase.ui torrentcreatordlg.cpp torrentcreatordlg.h \ + torrentcreatordlgbase.ui trayhoverpopup.cpp trayicon.cpp viewmanager.cpp filterbar.cpp + +xdg_apps_DATA = ktorrent.desktop + + +# these are the headers for your project +noinst_HEADERS = dcopinterface.h fileselectdlg.h ipfilterwidget.h ktorrent.h \ + ktorrentcore.h ktorrentdcop.h ktorrentview.h ktorrentviewitem.h ktorrentviewmenu.h \ + pastedialog.h pref.h scandialog.h speedlimitsdlg.h trayhoverpopup.h trayicon.h \ + viewmanager.h + +# client stuff + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/ktorrent.pot + +# this is where the XML-GUI resource file goes +rcdir = $(kde_datadir)/ktorrent +rc_DATA = ktorrentui.rc + +KDE_ICON= torrent ktorrent + +appicondir = $(kde_datadir)/ktorrent/icons +appicon_ICON = ktencrypted ktremove ktstart_all ktstart ktstop_all ktstop ktplugins ktinfowidget ktqueuemanager ktupnp ktprefdownloads + +kde_servicetypes_DATA = ktorrentplugin.desktop +EXTRA_DIST = ktorrentplugin.desktop + +if ENABLE_TORRENT_MIMETYPE +mimedir = $(kde_mimedir)/application +mime_DATA = x-bittorrent.desktop +endif + +KDE_CXXFLAGS = $(USE_EXCEPTIONS) $(USE_RTTI) diff --git a/apps/ktorrent/README b/apps/ktorrent/README new file mode 100644 index 0000000..f04a563 --- /dev/null +++ b/apps/ktorrent/README @@ -0,0 +1,81 @@ +----------------------------------------------- +Kde application framework template quickstart +Author: Thomas Nagy +Date: 2004-03-22 +----------------------------------------------- + +This README file explains you basic things for starting with +this application template. + + +** Building and installing ** + +* Build the configure script by "make -f Makefile.cvs" + +* To clean, use "make clean", and to clean everything +(remove the makefiles, etc), use "make distclean" + +* To distribute your program, try "make dist". +This will make a compact tarball archive of your release with the +necessary scripts inside. + +* Modifying the auto-tools scripts +for automake scripts there is an excellent tutorial there : +http://developer.kde.org/documentation/other/makefile_am_howto.html + +* Simplify your life : install the project in your home directory for +testing purposes. +./configure --prefix=/home/user/dummyfolder/ +In the end when you finished the development you can +rm -rf /home/user/dummyfolder/ +without fear. + + +** Technologies ** + +* Build the menus of your application easily +kde applications now use an xml file (*ui.rc file) to build the menus. +This allow a great customization of the application. However, when +programming the menu is shown only after a "make install" + +For more details, consult : +http://devel-home.kde.org/~larrosa/tutorial/p9.html +http://developer.kde.org/documentation/tutorials/xmlui/preface.html + +* Use KConfig XT to create your configuration dialogs and make +them more maintainable. + +For more details, consult : +http://developer.kde.org/documentation/tutorials/kconfigxt/kconfigxt.html + +* With KParts, you can embed other kde components in your program, or make your program +embeddable in other apps. For example, the kmplayer kpart can be called to play videos +in your app. + +For more details, consult : +http://www-106.ibm.com/developerworks/library/l-kparts/ +http://developer.kde.org/documentation/tutorials/dot/writing-plugins.html +http://developer.kde.org/documentation/tutorials/developing-a-plugin-structure/index.html + +* With dcop, you can control your app from other applications +Make sure to include K_DCOP and a kdcop: section in your .h file +http://developer.kde.org/documentation/tutorials/dot/dcopiface/dcop-interface.html + + +** Documentation ** + +* For the translations : +1. Download a patched gettext which can be found at: + http://public.kde.planetmirror.com/pub/kde/devel/gettext-kde/ +2. Install that gettext in ~/bin/ +3. cd ~/yourproject, export PATH=~/bin:$PATH, export +KDEDIR=/where_your_KDE3_is +4. make -f admin/Makefile.common package-messages +5. make package-messages +6. Translate the po files (not the pot!!) with kbabel or xemacs + +* Do not forget to write the documentation for your kde app +edit the documentation template index.docbook in doc/ + + + diff --git a/apps/ktorrent/addpeerwidget.cpp b/apps/ktorrent/addpeerwidget.cpp new file mode 100644 index 0000000..20c27c3 --- /dev/null +++ b/apps/ktorrent/addpeerwidget.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "addpeerwidget.h" + +#include <util/constants.h> +#include <interfaces/torrentinterface.h> + +#include <klocale.h> +#include <ksqueezedtextlabel.h> +#include <klineedit.h> +#include <knuminput.h> +#include <kmessagebox.h> + +#include <qstring.h> +#include <qstringlist.h> +#include <qregexp.h> +#include <qvalidator.h> + +using namespace kt; +using bt::Uint16; + +//PeerSource + +ManualPeerSource::ManualPeerSource() +{} + +void ManualPeerSource::start() +{} + +void ManualPeerSource::stop(bt::WaitJob* ) +{} + +ManualPeerSource::~ ManualPeerSource() +{} + +void ManualPeerSource::signalPeersReady() +{ + peersReady(this); +} + + +//AddPeerWidget + +AddPeerWidget::AddPeerWidget(kt::TorrentInterface* tc, QWidget *parent, const char *name) + :AddPeerWidgetBase(parent, name), m_tc(tc) +{ + if(!tc) + { + //oops, something went wrong... + m_status->setText(i18n("Torrent does not exist. Report this bug to KTorrent developers.")); + m_ip->setEnabled(false); + m_port->setEnabled(false); + return; + } + + m_peerSource = new ManualPeerSource(); + + //Register this peer source with ps manager. + m_tc->addPeerSource(m_peerSource); +} + +AddPeerWidget::~ AddPeerWidget() +{ + //Unregister this peer source with ps manager. + m_tc->removePeerSource(m_peerSource); + + delete m_peerSource; +} + +void AddPeerWidget::btnAdd_clicked() +{ + int var=0; + + QRegExp rx("[0-9]{1,3}(.[0-9]{1,3}){3,3}"); + QRegExpValidator v( rx,0); + + QString ip = m_ip->text(); + + if(v.validate( ip, var ) == QValidator::Acceptable) + { + m_peerSource->addPeer(ip, m_port->value()); + + m_peerSource->signalPeersReady(); + + m_status->setText(i18n("Potential peer added.")); + } + else + { + KMessageBox::sorry(0, i18n("Malformed IP address.")); + m_status->setText(""); + } +} + +#include "addpeerwidget.moc" diff --git a/apps/ktorrent/addpeerwidget.h b/apps/ktorrent/addpeerwidget.h new file mode 100644 index 0000000..74a7488 --- /dev/null +++ b/apps/ktorrent/addpeerwidget.h @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 ADDPEERWIDGET_H +#define ADDPEERWIDGET_H + +#include "addpeerwidgetbase.h" + +#include <qobject.h> +#include <interfaces/peersource.h> + +namespace kt +{ + class TorrentInterface; +} + +namespace bt +{ + class WaitJob; +} + +/** + * @author Ivan Vasic <ivasic@gmail.com> + * @brief PeerSource to allow peers to be added manually. + * + * Start/Stop() do nothing. Use this class only to manually add peers. + */ +class ManualPeerSource: public kt::PeerSource +{ + Q_OBJECT + + public: + ManualPeerSource(); + virtual ~ManualPeerSource(); + + /** + * @brief Emits peersReady signal. + * Use this when there are peers available in this peer source. + */ + void signalPeersReady(); + + public slots: + + /** + * Start gathering peers. + * Had to be defined but won't be used here. + */ + void start(); + + /** + * Stop gathering peers. + * Had to be defined but won't be used here. + */ + void stop(bt::WaitJob* wjob = 0); +}; + + +/** + * @author Ivan Vasic <ivasic@gmail.com> + * @brief GUI dialog for adding peers. + */ +class AddPeerWidget: public AddPeerWidgetBase +{ + Q_OBJECT + public: + AddPeerWidget(kt::TorrentInterface* tc, QWidget *parent = 0, const char *name = 0); + ~AddPeerWidget(); + + public slots: + virtual void btnAdd_clicked(); + + private: + ManualPeerSource* m_peerSource; + kt::TorrentInterface* m_tc; +}; + +#endif diff --git a/apps/ktorrent/addpeerwidgetbase.ui b/apps/ktorrent/addpeerwidgetbase.ui new file mode 100644 index 0000000..c4cbc6f --- /dev/null +++ b/apps/ktorrent/addpeerwidgetbase.ui @@ -0,0 +1,164 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>AddPeerWidgetBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>AddPeerWidgetBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>380</width> + <height>89</height> + </rect> + </property> + <property name="caption"> + <string>Add potential peer</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout10</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Peer IP:</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>m_ip</cstring> + </property> + <property name="text"> + <string>127.0.0.1</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Port:</string> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>m_port</cstring> + </property> + <property name="value"> + <number>6881</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="maxValue"> + <number>65535</number> + </property> + </widget> + </hbox> + </widget> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget" row="2" column="0"> + <property name="name"> + <cstring>layout11</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KSqueezedTextLabel"> + <property name="name"> + <cstring>m_status</cstring> + </property> + <property name="text"> + <string>Enter peer IP and port.</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnAdd</cstring> + </property> + <property name="text"> + <string>Add</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="stdItem" stdset="0"> + <number>27</number> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnClose</cstring> + </property> + <property name="text"> + <string>&Close</string> + </property> + <property name="stdItem" stdset="0"> + <number>13</number> + </property> + </widget> + </hbox> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>btnClose</sender> + <signal>clicked()</signal> + <receiver>AddPeerWidgetBase</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>btnAdd</sender> + <signal>clicked()</signal> + <receiver>AddPeerWidgetBase</receiver> + <slot>btnAdd_clicked()</slot> + </connection> +</connections> +<tabstops> + <tabstop>btnClose</tabstop> + <tabstop>m_ip</tabstop> + <tabstop>m_port</tabstop> + <tabstop>btnAdd</tabstop> +</tabstops> +<slots> + <slot>btnAdd_clicked()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>ksqueezedtextlabel.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/advancedpref.ui b/apps/ktorrent/advancedpref.ui new file mode 100644 index 0000000..bf4573e --- /dev/null +++ b/apps/ktorrent/advancedpref.ui @@ -0,0 +1,656 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>AdvancedPref</class> +<widget class="QWidget"> + <property name="name"> + <cstring>AdvancedPref</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>743</width> + <height>683</height> + </rect> + </property> + <property name="caption"> + <string>Advanced Preferences</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox4</cstring> + </property> + <property name="title"> + <string>Advanced Options</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout15</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_5</cstring> + </property> + <property name="text"> + <string>Time left estimation algorithm:</string> + </property> + <property name="toolTip" stdset="0"> + <string><b>KTorrent algorithm:</b> Default algorithm using combination of other algorithms based on our tests.<br> +<b>Current speed algorithm:</b> Simplest algorithm - BytesLeft/CurrentSpeed<br> +<b>Global average speed algorithm:</b> BytesLeft/AverageSpeed<br> +<b>Window of X algorithm:</b> ET calculated from X speed samples<br> +<b>Moving average algorithm:</b> Moving average speed calculated from X samples</string> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>KTorrent</string> + </property> + </item> + <item> + <property name="text"> + <string>Current speed</string> + </property> + </item> + <item> + <property name="text"> + <string>Global average speed</string> + </property> + </item> + <item> + <property name="text"> + <string>Window of X</string> + </property> + </item> + <item> + <property name="text"> + <string>Moving average</string> + </property> + </item> + <property name="name"> + <cstring>eta</cstring> + </property> + <property name="toolTip" stdset="0"> + <string><b>KTorrent algorithm:</b> Default algorithm using combination of other algorithms based on our tests.<br> +<b>Current speed algorithm:</b> Simplest algorithm - BytesLeft/CurrentSpeed<br> +<b>Global average speed algorithm:</b> BytesLeft/AverageSpeed<br> +<b>Window of X algorithm:</b> ET calculated from X speed samples<br> +<b>Moving average algorithm:</b> Moving average speed calculated from X samples</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>(takes effect after restart)</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer8</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>148</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>prealloc_disabled</cstring> + </property> + <property name="text"> + <string>Disa&ble diskspace preallocation</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout25</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>full_prealloc</cstring> + </property> + <property name="text"> + <string>F&ully preallocate diskspace (avoids fragmentation)</string> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Basic (slow)</string> + </property> + </item> + <item> + <property name="text"> + <string>Filesystem specific</string> + </property> + </item> + <property name="name"> + <cstring>full_prealloc_method</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Performance</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>Memory usage:</string> + </property> + </widget> + <widget class="KComboBox"> + <item> + <property name="text"> + <string>Low</string> + </property> + </item> + <item> + <property name="text"> + <string>Medium</string> + </property> + </item> + <item> + <property name="text"> + <string>High</string> + </property> + </item> + <property name="name"> + <cstring>mem_usage</cstring> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>111</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5_2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_3_2</cstring> + </property> + <property name="text"> + <string>GUI update interval:</string> + </property> + </widget> + <widget class="KComboBox"> + <item> + <property name="text"> + <string>500ms</string> + </property> + </item> + <item> + <property name="text"> + <string>1s</string> + </property> + </item> + <item> + <property name="text"> + <string>2s</string> + </property> + </item> + <item> + <property name="text"> + <string>5s</string> + </property> + </item> + <property name="name"> + <cstring>gui_interval</cstring> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2_2_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>111</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_6</cstring> + </property> + <property name="text"> + <string>Fast CPU</string> + </property> + </widget> + <widget class="QSlider"> + <property name="name"> + <cstring>cpu_usage</cstring> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="maxValue"> + <number>50</number> + </property> + <property name="value"> + <number>3</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>Below</enum> + </property> + <property name="tickInterval"> + <number>1</number> + </property> + <property name="toolTip" stdset="0"> + <string></string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2_2</cstring> + </property> + <property name="text"> + <string>Slow CPU</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Data Checking</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>no_recheck</cstring> + </property> + <property name="text"> + <string>During uploading, do &not recheck chunks bigger than</string> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>recheck_size</cstring> + </property> + <property name="value"> + <number>512</number> + </property> + <property name="minValue"> + <number>16</number> + </property> + <property name="maxValue"> + <number>8192</number> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>KB</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout10</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>auto_recheck</cstring> + </property> + <property name="text"> + <string>Do a data integrit&y check after</string> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>num_corrupted</cstring> + </property> + <property name="value"> + <number>3</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>corrupted chunks</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>41</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Networking</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout33</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout32</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1_7</cstring> + </property> + <property name="text"> + <string>Maximum number of connection setups:</string> + </property> + </widget> + <widget class="KIntNumInput" row="1" column="1"> + <property name="name"> + <cstring>max_con_setups</cstring> + </property> + <property name="value"> + <number>50</number> + </property> + <property name="minValue"> + <number>10</number> + </property> + <property name="maxValue"> + <number>200</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>DSCP for IP packets:</string> + </property> + </widget> + <widget class="KIntNumInput" row="0" column="1"> + <property name="name"> + <cstring>dscp</cstring> + </property> + <property name="value"> + <number>0</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + <property name="maxValue"> + <number>63</number> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>383</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>do_not_use_kde_proxy</cstring> + </property> + <property name="text"> + <string>Do not use the KDE pro&xy settings for HTTP tracker connections</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="text"> + <string>HTTP tracker proxy:</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>http_proxy</cstring> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer7_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>81</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>30</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<connections> + <connection> + <sender>full_prealloc</sender> + <signal>toggled(bool)</signal> + <receiver>full_prealloc_method</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcombobox.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/custom_widgets.cw b/apps/ktorrent/custom_widgets.cw new file mode 100644 index 0000000..9e8426d --- /dev/null +++ b/apps/ktorrent/custom_widgets.cw @@ -0,0 +1,68 @@ +<!DOCTYPE CW><CW> +<customwidgets> + <customwidget> + <class>PeerView</class> + <header location="local">peerview.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap> + <data format="PNG" length="1125">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042c49444154388db5954f6c14551cc73fefcd7476b65bdaae4bb78bb5502a14d404e4801c88182d1c4c2c693da847400f9c24c68b878684238660e2b1e01f12c19493012ef2478c814412d354a46017a8a564bb6da5bbedccee767776e63d0ffb073751d483bfe49799974c3eeffb7ebf37df9fd05a530b2184040cc0042420aaf9a4d0d554800f045a6b256ae0e1e1e1d6bebebe838ee31c48a7d39b5cd7fd075e251cc7617272f2ded8d8d819cff33e0316819259537aead4a9839d5dd6d1784f91f55b0a94830242088404d304292bef68a89f520802a598fecddaa04f1a876f5c250c7c0a64cdeac686e33807e23d45e6b297c8b877f1831542614550b6599835c83c2a81b6786a75134faf2f1169f12997350881d9021d0903e06de0745d3160a6d3e94dbd5b0a64dcbb94b5831d0e3375ab892b1772dcf9790528543f8dd0d367b36768153b5e31503a0f1aecb004580b44ffac58baae8b1714f0833c7638cc8dab303a320f4822ab4c7a37c69196203de3319d5ce1c4d13c733331dedc67a129a154fd128401ab0616d55a130ac3d42d93d1913940d13fd0c9ee0183685c60da01c5421bd72f7a8c8efccef9afd374267ad93d642365be0636a0d28ec7600941d9e6f23917f0e97f23ce5bef35d19ec863da0ed9059b2be70bec196c66dfa10ec0e49b338f7017258651bf95021035c595429bb0903248fe52a2b5b595dd7b4d945cc2340cdca536be389ee3f67886c5798f773fe8e0dac508c989659277a2180da4ca4ff07821058b8b251445d63d6b13ed1098a6417e39cac85197dbe31962ab9bd9f1f22a226d45366f6d0620fdb08c900d281af6110284b20085b414861d905d88f2e52739ee8cbb8022143259d3dd84691730aa2d52da441a8de0c6958068870022a41e9629ad3473fd3b8fdbe319dadb9b4924da994d2d716c7896fbe35152f78b48245d6b2da4507faf582be8eaf159b721cc837b05ae7debb1f79d08cb8b515edad942a22bc4b1c33eb3d34b1c797f06af90a72d16e2f96d9a74aa11dca8586b222d01af0fb60070f6c402d72f15d97f28c6f6d7027a5f5ce6c3233dc4e2ede496b278be4fff608cee8d3e1add806aeca51094cbb06397c1ecc328e746537c7e3ccdb5cb1136bf60635882d4d41c6ec6836ab37efa214f72208ed9f4d7cdd38ee310280542e38b1c43fb6de26b3672e1ec3cc99bcb246f66a938a3241ab3e91f7c861fbf77710b1e5e49915bae974203ba0e9e9c9cbc373d6d6d305a040a89c2a77f50b27d5782bbbf7acccf28349235dd16cf6dd374f7295e1de8a45c02d37499182b01cc0201a085d61a2144d8b2ac8fb6ed340e77240c4261890e04c250185262546d534a032154b59e0ad394e41c98182bf268ce6721ed9f064e0253356f6da2e24c1f030f783c15fe6da680af8021602bd051532ca9b8521488559f61aa86c29343578fbf0264a94c906c7d3409214c20043457a116ff6de6795578012889ff6b98fe016ea0ce1c6a2573410000000049454e44ae426082</data> + </pixmap> + </customwidget> + <customwidget> + <class>ChunkDownloadView</class> + <header location="local">chunkdownloadview.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap> + <data format="PNG" length="1125">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042c49444154388db5954f6c14551cc73fefcd7476b65bdaae4bb78bb5502a14d404e4801c88182d1c4c2c693da847400f9c24c68b878684238660e2b1e01f12c19493012ef2478c814412d354a46017a8a564bb6da5bbedccee767776e63d0ffb073751d483bfe49799974c3eeffb7ebf37df9fd05a530b2184040cc0042420aaf9a4d0d554800f045a6b256ae0e1e1e1d6bebebe838ee31c48a7d39b5cd7fd075e251cc7617272f2ded8d8d819cff33e0316819259537aead4a9839d5dd6d1784f91f55b0a94830242088404d304292bef68a89f520802a598fecddaa04f1a876f5c250c7c0a64cdeac686e33807e23d45e6b297c8b877f1831542614550b6599835c83c2a81b6786a75134faf2f1169f12997350881d9021d0903e06de0745d3160a6d3e94dbd5b0a64dcbb94b5831d0e3375ab892b1772dcf9790528543f8dd0d367b36768153b5e31503a0f1aecb004580b44ffac58baae8b1714f0833c7638cc8dab303a320f4822ab4c7a37c69196203de3319d5ce1c4d13c733331dedc67a129a154fd128401ab0616d55a130ac3d42d93d1913940d13fd0c9ee0183685c60da01c5421bd72f7a8c8efccef9afd374267ad93d642365be0636a0d28ec7600941d9e6f23917f0e97f23ce5bef35d19ec863da0ed9059b2be70bec196c66dfa10ec0e49b338f7017258651bf95021035c595429bb0903248fe52a2b5b595dd7b4d945cc2340cdca536be389ee3f67886c5798f773fe8e0dac508c989659277a2180da4ca4ff07821058b8b251445d63d6b13ed1098a6417e39cac85197dbe31962ab9bd9f1f22a226d45366f6d0620fdb08c900d281af6110284b20085b414861d905d88f2e52739ee8cbb8022143259d3dd84691730aa2d52da441a8de0c6958068870022a41e9629ad3473fd3b8fdbe319dadb9b4924da994d2d716c7896fbe35152f78b48245d6b2da4507faf582be8eaf159b721cc837b05ae7debb1f79d08cb8b515edad942a22bc4b1c33eb3d34b1c797f06af90a72d16e2f96d9a74aa11dca8586b222d01af0fb60070f6c402d72f15d97f28c6f6d7027a5f5ce6c3233dc4e2ede496b278be4fff608cee8d3e1add806aeca51094cbb06397c1ecc328e746537c7e3ccdb5cb1136bf60635882d4d41c6ec6836ab37efa214f72208ed9f4d7cdd38ee310280542e38b1c43fb6de26b3672e1ec3cc99bcb246f66a938a3241ab3e91f7c861fbf77710b1e5e49915bae974203ba0e9e9c9cbc373d6d6d305a040a89c2a77f50b27d5782bbbf7acccf28349235dd16cf6dd374f7295e1de8a45c02d37499182b01cc0201a085d61a2144d8b2ac8fb6ed340e77240c4261890e04c250185262546d534a032154b59e0ad394e41c98182bf268ce6721ed9f064e0253356f6da2e24c1f030f783c15fe6da680af8021602bd051532ca9b8521488559f61aa86c29343578fbf0264a94c906c7d3409214c20043457a116ff6de6795578012889ff6b98fe016ea0ce1c6a2573410000000049454e44ae426082</data> + </pixmap> + </customwidget> + <customwidget> + <class>DownloadedChunkBar</class> + <header location="local">downloadedchunkbar.h</header> + <sizehint> + <width>-1</width> + <height>20</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap> + <data format="PNG" length="1125">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042c49444154388db5954f6c14551cc73fefcd7476b65bdaae4bb78bb5502a14d404e4801c88182d1c4c2c693da847400f9c24c68b878684238660e2b1e01f12c19493012ef2478c814412d354a46017a8a564bb6da5bbedccee767776e63d0ffb073751d483bfe49799974c3eeffb7ebf37df9fd05a530b2184040cc0042420aaf9a4d0d554800f045a6b256ae0e1e1e1d6bebebe838ee31c48a7d39b5cd7fd075e251cc7617272f2ded8d8d819cff33e0316819259537aead4a9839d5dd6d1784f91f55b0a94830242088404d304292bef68a89f520802a598fecddaa04f1a876f5c250c7c0a64cdeac686e33807e23d45e6b297c8b877f1831542614550b6599835c83c2a81b6786a75134faf2f1169f12997350881d9021d0903e06de0745d3160a6d3e94dbd5b0a64dcbb94b5831d0e3375ab892b1772dcf9790528543f8dd0d367b36768153b5e31503a0f1aecb004580b44ffac58baae8b1714f0833c7638cc8dab303a320f4822ab4c7a37c69196203de3319d5ce1c4d13c733331dedc67a129a154fd128401ab0616d55a130ac3d42d93d1913940d13fd0c9ee0183685c60da01c5421bd72f7a8c8efccef9afd374267ad93d642365be0636a0d28ec7600941d9e6f23917f0e97f23ce5bef35d19ec863da0ed9059b2be70bec196c66dfa10ec0e49b338f7017258651bf95021035c595429bb0903248fe52a2b5b595dd7b4d945cc2340cdca536be389ee3f67886c5798f773fe8e0dac508c989659277a2180da4ca4ff07821058b8b251445d63d6b13ed1098a6417e39cac85197dbe31962ab9bd9f1f22a226d45366f6d0620fdb08c900d281af6110284b20085b414861d905d88f2e52739ee8cbb8022143259d3dd84691730aa2d52da441a8de0c6958068870022a41e9629ad3473fd3b8fdbe319dadb9b4924da994d2d716c7896fbe35152f78b48245d6b2da4507faf582be8eaf159b721cc837b05ae7debb1f79d08cb8b515edad942a22bc4b1c33eb3d34b1c797f06af90a72d16e2f96d9a74aa11dca8586b222d01af0fb60070f6c402d72f15d97f28c6f6d7027a5f5ce6c3233dc4e2ede496b278be4fff608cee8d3e1add806aeca51094cbb06397c1ecc328e746537c7e3ccdb5cb1136bf60635882d4d41c6ec6836ab37efa214f72208ed9f4d7cdd38ee310280542e38b1c43fb6de26b3672e1ec3cc99bcb246f66a938a3241ab3e91f7c861fbf77710b1e5e49915bae974203ba0e9e9c9cbc373d6d6d305a040a89c2a77f50b27d5782bbbf7acccf28349235dd16cf6dd374f7295e1de8a45c02d37499182b01cc0201a085d61a2144d8b2ac8fb6ed340e77240c4261890e04c250185262546d534a032154b59e0ad394e41c98182bf268ce6721ed9f064e0253356f6da2e24c1f030f783c15fe6da680af8021602bd051532ca9b8521488559f61aa86c29343578fbf0264a94c906c7d3409214c20043457a116ff6de6795578012889ff6b98fe016ea0ce1c6a2573410000000049454e44ae426082</data> + </pixmap> + </customwidget> + <customwidget> + <class>AvailabilityChunkBar</class> + <header location="local">availabilitychunkbar.h</header> + <sizehint> + <width>-1</width> + <height>20</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap> + <data format="PNG" length="1125">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042c49444154388db5954f6c14551cc73fefcd7476b65bdaae4bb78bb5502a14d404e4801c88182d1c4c2c693da847400f9c24c68b878684238660e2b1e01f12c19493012ef2478c814412d354a46017a8a564bb6da5bbedccee767776e63d0ffb073751d483bfe49799974c3eeffb7ebf37df9fd05a530b2184040cc0042420aaf9a4d0d554800f045a6b256ae0e1e1e1d6bebebe838ee31c48a7d39b5cd7fd075e251cc7617272f2ded8d8d819cff33e0316819259537aead4a9839d5dd6d1784f91f55b0a94830242088404d304292bef68a89f520802a598fecddaa04f1a876f5c250c7c0a64cdeac686e33807e23d45e6b297c8b877f1831542614550b6599835c83c2a81b6786a75134faf2f1169f12997350881d9021d0903e06de0745d3160a6d3e94dbd5b0a64dcbb94b5831d0e3375ab892b1772dcf9790528543f8dd0d367b36768153b5e31503a0f1aecb004580b44ffac58baae8b1714f0833c7638cc8dab303a320f4822ab4c7a37c69196203de3319d5ce1c4d13c733331dedc67a129a154fd128401ab0616d55a130ac3d42d93d1913940d13fd0c9ee0183685c60da01c5421bd72f7a8c8efccef9afd374267ad93d642365be0636a0d28ec7600941d9e6f23917f0e97f23ce5bef35d19ec863da0ed9059b2be70bec196c66dfa10ec0e49b338f7017258651bf95021035c595429bb0903248fe52a2b5b595dd7b4d945cc2340cdca536be389ee3f67886c5798f773fe8e0dac508c989659277a2180da4ca4ff07821058b8b251445d63d6b13ed1098a6417e39cac85197dbe31962ab9bd9f1f22a226d45366f6d0620fdb08c900d281af6110284b20085b414861d905d88f2e52739ee8cbb8022143259d3dd84691730aa2d52da441a8de0c6958068870022a41e9629ad3473fd3b8fdbe319dadb9b4924da994d2d716c7896fbe35152f78b48245d6b2da4507faf582be8eaf159b721cc837b05ae7debb1f79d08cb8b515edad942a22bc4b1c33eb3d34b1c797f06af90a72d16e2f96d9a74aa11dca8586b222d01af0fb60070f6c402d72f15d97f28c6f6d7027a5f5ce6c3233dc4e2ede496b278be4fff608cee8d3e1add806aeca51094cbb06397c1ecc328e746537c7e3ccdb5cb1136bf60635882d4d41c6ec6836ab37efa214f72208ed9f4d7cdd38ee310280542e38b1c43fb6de26b3672e1ec3cc99bcb246f66a938a3241ab3e91f7c861fbf77710b1e5e49915bae974203ba0e9e9c9cbc373d6d6d305a040a89c2a77f50b27d5782bbbf7acccf28349235dd16cf6dd374f7295e1de8a45c02d37499182b01cc0201a085d61a2144d8b2ac8fb6ed340e77240c4261890e04c250185262546d534a032154b59e0ad394e41c98182bf268ce6721ed9f064e0253356f6da2e24c1f030f783c15fe6da680af8021602bd051532ca9b8521488559f61aa86c29343578fbf0264a94c906c7d3409214c20043457a116ff6de6795578012889ff6b98fe016ea0ce1c6a2573410000000049454e44ae426082</data> + </pixmap> + </customwidget> +</customwidgets> +</CW> diff --git a/apps/ktorrent/dcopinterface.h b/apps/ktorrent/dcopinterface.h new file mode 100644 index 0000000..5dd7df5 --- /dev/null +++ b/apps/ktorrent/dcopinterface.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 DCOPINTERFACE_H +#define DCOPINTERFACE_H + +#include <dcopobject.h> + +/** +@author Joris Guisson +*/ +class DCOPInterface : virtual public DCOPObject +{ + K_DCOP +k_dcop: + virtual void startAll(int type = 3) = 0; + virtual void stopAll(int type = 3) = 0; + virtual void setMaxDownloads(int max) = 0; + virtual void setMaxSeeds(int max) = 0; + virtual void setKeepSeeding(bool ks) = 0; + virtual void setMaxUploadSpeed(int kbytes_per_sec) = 0; + virtual void setMaxDownloadSpeed(int kbytes_per_sec) = 0; + virtual void setMaxConnectionsPerDownload(int max) = 0; + virtual void setShowSysTrayIcon(bool yes) = 0; + virtual bool changeDataDir(const QString & new_dir) = 0; + virtual void openTorrent(const QString & file) = 0; + virtual void openTorrentSilently(const QString & file) = 0; + virtual QValueList<int> getTorrentNumbers(int type = 3) = 0; + virtual QCStringList getTorrentInfo(int tornumber) = 0; + virtual int getFileCount(int tornumber) = 0; + virtual QCStringList getInfo() = 0; + virtual QCStringList getFileNames(int tornumber) = 0; + virtual QValueList<int> getFilePriorities(int tornumber) = 0; + virtual void setFilePriority(int tornumber, int index, int priority) = 0; + virtual void start(int tornumber) = 0; + virtual void stop(int tornumber, bool user) = 0; + virtual void remove(int tornumber, bool del_data) = 0; + virtual void announce(int tornumber) = 0; + virtual QCString dataDir() = 0; + virtual int maxDownloads() = 0; + virtual int maxSeeds() = 0; + virtual int maxConnections() = 0; + virtual int maxUploadRate() = 0; + virtual int maxDownloadRate() = 0; + virtual bool keepSeeding() = 0; + virtual bool showSystemTrayIcon() = 0; + virtual QValueList<int> intSettings() = 0; + virtual bool isBlockedIP(QString ip) = 0; + virtual void openTorrentSilentlyDir(const QString & file, const QString & savedir) = 0; +}; + + +#endif diff --git a/apps/ktorrent/downloadpref.ui b/apps/ktorrent/downloadpref.ui new file mode 100644 index 0000000..c87383b --- /dev/null +++ b/apps/ktorrent/downloadpref.ui @@ -0,0 +1,735 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>DownloadPref</class> +<widget class="QWidget"> + <property name="name"> + <cstring>DownloadPref</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>575</width> + <height>706</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Queue Manager</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout49</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout42</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout16</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Maximum downloads:</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_5</cstring> + </property> + <property name="text"> + <string>Maximum seeds:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_8</cstring> + </property> + <property name="text"> + <string>Start download on low disk space :</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_9</cstring> + </property> + <property name="text"> + <string>Minimum disk space:</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout46</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>max_downloads</cstring> + </property> + <property name="value"> + <number>2</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>max_seeds</cstring> + </property> + <property name="value"> + <number>2</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Don't start</string> + </property> + </item> + <item> + <property name="text"> + <string>Always ask</string> + </property> + </item> + <item> + <property name="text"> + <string>Force start</string> + </property> + </item> + <property name="name"> + <cstring>cmbDiskSpace</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout45</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSpinBox"> + <property name="name"> + <cstring>intMinDiskSpace</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxValue"> + <number>10000</number> + </property> + <property name="minValue"> + <number>10</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>MB</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout48</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout14</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>(0 is no limit)</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_3</cstring> + </property> + <property name="text"> + <string>(0 is no limit)</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer36</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>191</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer> + <property name="name"> + <cstring>spacer17</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>207</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> + </widget> + </hbox> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Preferences</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout42</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="text"> + <string>Maximum download rate:</string> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Port:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1_7</cstring> + </property> + <property name="text"> + <string>Global connection limit:</string> + </property> + </widget> + <widget class="QLabel" row="8" column="0"> + <property name="name"> + <cstring>textLabel2_3</cstring> + </property> + <property name="text"> + <string>Max seed time:</string> + </property> + </widget> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout18</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Maximum connections per torrent:</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer8_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLabel" row="6" column="0"> + <property name="name"> + <cstring>textLabel1_6</cstring> + </property> + <property name="text"> + <string>Number of upload slots:</string> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>UDP tracker port:</string> + </property> + </widget> + <widget class="QLabel" row="7" column="0"> + <property name="name"> + <cstring>textLabel1_6_2</cstring> + </property> + <property name="text"> + <string>Max share ratio:</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Maximum upload rate:</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout41</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>max_conns</cstring> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>max_total_conns</cstring> + </property> + <property name="value"> + <number>800</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>max_upload_rate</cstring> + </property> + <property name="value"> + <number>5</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>max_download_rate</cstring> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>port</cstring> + </property> + <property name="value"> + <number>6881</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="maxValue"> + <number>65535</number> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>udp_tracker_port</cstring> + </property> + <property name="value"> + <number>4444</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="maxValue"> + <number>65535</number> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>num_upload_slots</cstring> + </property> + <property name="value"> + <number>2</number> + </property> + <property name="minValue"> + <number>2</number> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="referencePoint"> + <number>2</number> + </property> + </widget> + <widget class="KDoubleSpinBox"> + <property name="name"> + <cstring>num_max_ratio</cstring> + </property> + <property name="maxValue"> + <number>1000</number> + </property> + <property name="precision"> + <number>2</number> + </property> + </widget> + <widget class="KDoubleSpinBox"> + <property name="name"> + <cstring>max_seed_time</cstring> + </property> + <property name="maxValue"> + <number>1e+07</number> + </property> + <property name="lineStep"> + <number>0.05</number> + </property> + <property name="precision"> + <number>2</number> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout40</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_2</cstring> + </property> + <property name="text"> + <string>(0 is no limit)</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_2_2</cstring> + </property> + <property name="text"> + <string>(0 is no limit)</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>KB/sec (0 is no limit)</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4_2</cstring> + </property> + <property name="text"> + <string>KB/sec (0 is no limit)</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>208</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>208</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer> + <property name="name"> + <cstring>spacer8</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>208</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_2_2_2</cstring> + </property> + <property name="text"> + <string>(0 is no limit)</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3_2</cstring> + </property> + <property name="text"> + <string>Hours (0 is no limit)</string> + </property> + </widget> + </vbox> + </widget> + </hbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>keep_seeding</cstring> + </property> + <property name="text"> + <string>&Keep seeding after download is finished</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Attention</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KActiveLabel"> + <property name="name"> + <cstring>kActiveLabel1</cstring> + </property> + <property name="text"> + <string>The above ports must also be forwarded if you are behind a router. The UPnP plugin can do this for you.</string> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>kactivelabel.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/fileselectdlg.cpp b/apps/ktorrent/fileselectdlg.cpp new file mode 100644 index 0000000..5704b41 --- /dev/null +++ b/apps/ktorrent/fileselectdlg.cpp @@ -0,0 +1,297 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <klocale.h> +#include <kmessagebox.h> +#include <klistview.h> +#include <kstdguiitem.h> +#include <kpushbutton.h> +#include <kurlrequester.h> +#include <kiconloader.h> +#include <kmimetype.h> +#include <kurl.h> + +#include <qlabel.h> +#include <qstring.h> +#include <qbuttongroup.h> +#include <qcombobox.h> +#include <qcheckbox.h> +#include <qdir.h> + +#include <interfaces/torrentfileinterface.h> +#include <interfaces/torrentinterface.h> +#include "fileselectdlg.h" +#include <interfaces/filetreediritem.h> +#include <interfaces/filetreeitem.h> +#include <interfaces/functions.h> +#include <settings.h> +#include <util/functions.h> +#include <util/fileops.h> + +#include <groups/group.h> +#include <groups/groupmanager.h> + +using namespace kt; + +FileSelectDlg::FileSelectDlg(GroupManager* gm, bool* user, bool* start, QWidget* parent, const char* name, bool modal, WFlags fl) + : FileSelectDlgBase(parent, name, modal, fl), m_gman(gm), m_user(user), m_start(start) +{ + root = 0; + connect(m_select_all, SIGNAL(clicked()), this, SLOT(selectAll())); + connect(m_select_none, SIGNAL(clicked()), this, SLOT(selectNone())); + connect(m_invert_selection, SIGNAL(clicked()), this, SLOT(invertSelection())); + connect(m_ok, SIGNAL(clicked()), this, SLOT(accept())); + connect(m_cancel, SIGNAL(clicked()), this, SLOT(reject())); + connect(m_downloadLocation, SIGNAL(textChanged (const QString &)), this, SLOT(updateSizeLabels())); + + m_downloadLocation->setMode(KFile::Directory); +} + +FileSelectDlg::~FileSelectDlg() + +{} + +int FileSelectDlg::execute(kt::TorrentInterface* tc) +{ + this->tc = tc; + + if (tc) + { + populateFields(); + + if(tc->getStats().multi_file_torrent) + setupMultifileTorrent(); + else + setupSinglefileTorrent(); + + return exec(); + } + + return QDialog::Rejected; +} + +void FileSelectDlg::reject() +{ + QDialog::reject(); +} + +void FileSelectDlg::accept() +{ + QStringList pe_ex; + + QString dn = m_downloadLocation->url(); + if (!dn.endsWith(bt::DirSeparator())) + dn += bt::DirSeparator(); + + for (Uint32 i = 0;i < tc->getNumFiles();i++) + { + kt::TorrentFileInterface & file = tc->getTorrentFile(i); + + // check for preexsting files + QString path = dn + tc->getStats().torrent_name + bt::DirSeparator() + file.getPath(); + if (bt::Exists(path)) + file.setPreExisting(true); + + if (file.doNotDownload() && file.isPreExistingFile()) + { + // we have excluded a preexsting file + pe_ex.append(file.getPath()); + } + } + + if (pe_ex.count() > 0) + { + QString msg = i18n("You have deselected the following existing files. " + "You will lose all data in these files, are you sure you want to do this ?"); + // better ask the user if (s)he wants to delete the already existing data + int ret = KMessageBox::warningYesNoList(0, msg, pe_ex, QString::null, + KGuiItem(i18n("Yes, delete the files")), + KGuiItem(i18n("No, keep the files"))); + + if (ret == KMessageBox::No) + { + for (Uint32 i = 0;i < tc->getNumFiles();i++) + { + kt::TorrentFileInterface & file = tc->getTorrentFile(i); + + if (file.doNotDownload() && file.isPreExistingFile()) + file.setDoNotDownload(false); + } + } + } + + for (Uint32 i = 0;i < tc->getNumFiles();i++) + { + kt::TorrentFileInterface & file = tc->getTorrentFile(i); + file.setEmitDownloadStatusChanged(true); + // we don't need to emit the downloadStatusChanged signal, + // because tc->createFiles() in ktorrentcore.cpp will take care of everything + } + + //Setup custom download location + QString ddir = tc->getDataDir(); + if (!ddir.endsWith(bt::DirSeparator())) + ddir += bt::DirSeparator(); + + if (dn != ddir) // only change when absolutely necessary + tc->changeOutputDir(dn, false); + + //Make it user controlled if needed + *m_user = m_chkUserControlled->isChecked(); + *m_start = m_chkUserControlled->isChecked() && m_chkStartTorrent->isChecked(); + + //Now add torrent to selected group + if(m_cmbGroups->currentItem() != 0) + { + QString groupName = m_cmbGroups->currentText(); + + Group* group = m_gman->find(groupName); + if(group) + { + group->addTorrent(tc); + } + } + + // update the last save directory + Settings::setLastSaveDir(dn); + QDialog::accept(); +} + +void FileSelectDlg::selectAll() +{ + if (root) + root->setAllChecked(true); +} + +void FileSelectDlg::selectNone() +{ + if (root) + root->setAllChecked(false); +} + +void FileSelectDlg::invertSelection() +{ + if (root) + root->invertChecked(); +} + +void FileSelectDlg::updateSizeLabels() +{ + //calculate free disk space + + KURL sdir = KURL(m_downloadLocation -> url()); + while( sdir.isValid() && sdir.isLocalFile() && (!sdir.isEmpty()) && (! QDir(sdir.path()).exists()) ) + { + sdir = sdir.upURL(); + } + + Uint64 bytes_free = 0; + if (!FreeDiskSpace(sdir.path(),bytes_free)) + { + FreeDiskSpace(tc->getDataDir(),bytes_free); + } + + Uint64 bytes_to_download = 0; + if (root) + bytes_to_download = root->bytesToDownload(); + else + bytes_to_download = tc->getStats().total_bytes; + + lblFree->setText(kt::BytesToString(bytes_free)); + lblRequired->setText(kt::BytesToString(bytes_to_download)); + + if (bytes_to_download > bytes_free) + lblStatus->setText("<font color=\"#ff0000\">" + kt::BytesToString(-1*(long long)(bytes_free - bytes_to_download)) + i18n(" short!")); + else + lblStatus->setText(kt::BytesToString(bytes_free - bytes_to_download)); +} + +void FileSelectDlg::treeItemChanged() +{ + updateSizeLabels(); +} + +void FileSelectDlg::setupMultifileTorrent() +{ + m_file_view->clear(); + root = new kt::FileTreeDirItem(m_file_view, tc->getStats().torrent_name, this); + + for (Uint32 i = 0;i < tc->getNumFiles();i++) + { + kt::TorrentFileInterface & file = tc->getTorrentFile(i); + file.setEmitDownloadStatusChanged(false); + root->insert(file.getPath(), file); + } + + root->setOpen(true); + m_file_view->setRootIsDecorated(true); + + updateSizeLabels(); +} + +void FileSelectDlg::setupSinglefileTorrent() +{ + m_file_view->clear(); + KListViewItem* single_root = new KListViewItem(m_file_view); + single_root->setText(0,tc->getStats().torrent_name); + single_root->setText(1,BytesToString(tc->getStats().total_bytes)); + single_root->setText(2,i18n("Yes")); + single_root->setPixmap(0,KMimeType::findByPath(tc->getStats().torrent_name)->pixmap(KIcon::Small)); + root = 0; + updateSizeLabels(); + m_select_all->setEnabled(false); + m_select_none->setEnabled(false); + m_invert_selection->setEnabled(false); +} + +void FileSelectDlg::populateFields() +{ + QString dir = Settings::saveDir(); + if (!Settings::useSaveDir() || dir.isNull()) + { + dir = Settings::lastSaveDir(); + if (dir.isNull()) + dir = QDir::homeDirPath(); + } + + m_downloadLocation->setURL(dir); + loadGroups(); +} + +void FileSelectDlg::loadGroups() +{ + GroupManager::iterator it = m_gman->begin(); + + QStringList grps; + + //First default group + grps << i18n("All Torrents"); + + //now custom ones + while(it != m_gman->end()) + { + grps << it->first; + ++it; + } + + m_cmbGroups->insertStringList(grps); +} + +#include "fileselectdlg.moc" + diff --git a/apps/ktorrent/fileselectdlg.h b/apps/ktorrent/fileselectdlg.h new file mode 100644 index 0000000..9ae2b8f --- /dev/null +++ b/apps/ktorrent/fileselectdlg.h @@ -0,0 +1,84 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 FILESELECTDLG_H +#define FILESELECTDLG_H + +#include <interfaces/filetreediritem.h> +#include "fileselectdlgbase.h" + + + +namespace kt +{ + + class TorrentInterface; + class FileTreeDirItem; + class GroupManager; +} + +/** + * @author Joris Guisson + * + * Dialog to select which files to download from a multifile torrent. + */ + +class FileSelectDlg : public FileSelectDlgBase, public kt::FileTreeRootListener +{ + Q_OBJECT + + kt::TorrentInterface* tc; + kt::FileTreeDirItem* root; + + kt::GroupManager* m_gman; + + bool* m_user; + bool* m_start; + + public: + FileSelectDlg(kt::GroupManager* gm, bool* user, bool* start, QWidget* parent = 0, const char* name = 0, + bool modal = true, WFlags fl = 0); + + virtual ~FileSelectDlg(); + int execute(kt::TorrentInterface* tc); + + void loadGroups(); + + void populateFields(); + + void setupMultifileTorrent(); + void setupSinglefileTorrent(); + + protected slots: + virtual void reject(); + virtual void accept(); + void selectAll(); + void selectNone(); + void invertSelection(); + + private: + virtual void treeItemChanged(); + + private slots: + void updateSizeLabels(); +}; + +#endif + diff --git a/apps/ktorrent/fileselectdlgbase.ui b/apps/ktorrent/fileselectdlgbase.ui new file mode 100644 index 0000000..5d9ed14 --- /dev/null +++ b/apps/ktorrent/fileselectdlgbase.ui @@ -0,0 +1,384 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>FileSelectDlgBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>FileSelectDlgBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>491</width> + <height>500</height> + </rect> + </property> + <property name="caption"> + <string>Select Which Files You Want to Download</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Download to:</string> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>m_downloadLocation</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Group:</string> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>m_cmbGroups</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_chkUserControlled</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&User controlled</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_chkStartTorrent</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Start torrent</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QButtonGroup" row="2" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>pnlFiles</cstring> + </property> + <property name="title"> + <string>Files</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KListView" row="0" column="0" rowspan="4" colspan="1"> + <column> + <property name="text"> + <string>File</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Size</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Download</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_file_view</cstring> + </property> + <property name="fullWidth"> + <bool>true</bool> + </property> + </widget> + <widget class="KPushButton" row="0" column="1"> + <property name="name"> + <cstring>m_select_all</cstring> + </property> + <property name="text"> + <string>Select &All</string> + </property> + </widget> + <widget class="KPushButton" row="1" column="1"> + <property name="name"> + <cstring>m_select_none</cstring> + </property> + <property name="text"> + <string>Select &None</string> + </property> + </widget> + <widget class="KPushButton" row="2" column="1"> + <property name="name"> + <cstring>m_invert_selection</cstring> + </property> + <property name="text"> + <string>Invert Selection</string> + </property> + </widget> + <spacer row="3" column="1"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>135</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget class="QGroupBox" row="3" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Disk space</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="0" column="2"> + <property name="name"> + <cstring>spacer9</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Preferred</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout33</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Required disk space:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Free disk space:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel6</cstring> + </property> + <property name="text"> + <string>After download:</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="0" column="1"> + <property name="name"> + <cstring>layout34</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblRequired</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>lblFree</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>lblStatus</cstring> + </property> + </widget> + </vbox> + </widget> + </grid> + </widget> + <spacer row="4" column="0"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>220</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton" row="4" column="1"> + <property name="name"> + <cstring>m_ok</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + <property name="stdItem" stdset="0"> + <number>1</number> + </property> + </widget> + <widget class="KPushButton" row="4" column="2"> + <property name="name"> + <cstring>m_cancel</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="stdItem" stdset="0"> + <number>2</number> + </property> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>m_chkUserControlled</sender> + <signal>toggled(bool)</signal> + <receiver>m_chkStartTorrent</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>m_ok</tabstop> + <tabstop>m_cancel</tabstop> + <tabstop>m_downloadLocation</tabstop> + <tabstop>m_cmbGroups</tabstop> + <tabstop>m_chkUserControlled</tabstop> + <tabstop>m_chkStartTorrent</tabstop> + <tabstop>m_file_view</tabstop> + <tabstop>m_select_all</tabstop> + <tabstop>m_select_none</tabstop> + <tabstop>m_invert_selection</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>klistview.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/filterbar.cpp b/apps/ktorrent/filterbar.cpp new file mode 100644 index 0000000..c40488d --- /dev/null +++ b/apps/ktorrent/filterbar.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + * Copyright (C) 2007 by Lukasz Fibinger <lucke@o2.pl> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 "filterbar.h" + +#include <qlabel.h> +#include <qlayout.h> +#include <qcheckbox.h> + +#include <kdialog.h> +#include <klocale.h> +#include <kpushbutton.h> +#include <ktoolbarbutton.h> +#include <klineedit.h> +#include <kiconloader.h> +#include <kconfig.h> +#include <interfaces/torrentinterface.h> + + + +FilterBar::FilterBar(QWidget *parent, const char *name) : + QWidget(parent, name) +{ + const int gap = 3; + + QVBoxLayout* foo = new QVBoxLayout(this); + foo->addSpacing(gap); + + QHBoxLayout* layout = new QHBoxLayout(foo); + layout->addSpacing(gap); + + m_close = new KToolBarButton("fileclose",0,this); + connect(m_close,SIGNAL(clicked()),this,SLOT(hide())); + layout->addWidget(m_close); + + m_filter = new QLabel(i18n("Find:"), this); + layout->addWidget(m_filter); + layout->addSpacing(KDialog::spacingHint()); + + m_filterInput = new KLineEdit(this); + layout->addWidget(m_filterInput); + + m_clear = new KPushButton(this); + m_clear->setIconSet(SmallIcon("clear_left")); + m_clear->setFlat(true); + layout->addWidget(m_clear); + layout->addSpacing(gap); + + m_case_sensitive = new QCheckBox(i18n("Case sensitive"),this); + m_case_sensitive->setChecked(true); + layout->addWidget(m_case_sensitive); + layout->addItem(new QSpacerItem(10,10,QSizePolicy::Expanding)); + + connect(m_filterInput, SIGNAL(textChanged(const QString&)), + this, SLOT(slotChangeFilter(const QString&))); + connect(m_clear, SIGNAL(clicked()), m_filterInput, SLOT(clear())); +} + +FilterBar::~FilterBar() +{ +} + +void FilterBar::saveSettings(KConfig* cfg) +{ + cfg->writeEntry("filter_bar_hidden",isHidden()); + cfg->writeEntry("filter_bar_text",m_name_filter); + cfg->writeEntry("filter_bar_case_sensitive",m_case_sensitive->isChecked()); +} + +void FilterBar::loadSettings(KConfig* cfg) +{ + setHidden(cfg->readBoolEntry("filter_bar_hidden",true)); + m_case_sensitive->setChecked(cfg->readBoolEntry("filter_bar_case_sensitive",true)); + m_name_filter = cfg->readEntry("filter_bar_text",QString::null); + m_filterInput->setText(m_name_filter); +} + +bool FilterBar::matchesFilter(kt::TorrentInterface* tc) +{ + bool cs = m_case_sensitive->isChecked(); + if (m_name_filter.length() == 0) + return true; + else + return tc->getStats().torrent_name.contains(m_name_filter,cs); +} + +void FilterBar::slotChangeFilter(const QString& nameFilter) +{ + m_name_filter = nameFilter; +} + +void FilterBar::keyPressEvent(QKeyEvent* event) +{ + if ((event->key() == Qt::Key_Escape)) + { + m_filterInput->clear(); + m_name_filter = QString::null; + //hide(); + } + else + QWidget::keyPressEvent(event); +} + +void FilterBar::hideEvent(QHideEvent* event) +{ + m_filterInput->releaseKeyboard(); + QWidget::hideEvent(event); +} + +#include "filterbar.moc" diff --git a/apps/ktorrent/filterbar.h b/apps/ktorrent/filterbar.h new file mode 100644 index 0000000..4e7e913 --- /dev/null +++ b/apps/ktorrent/filterbar.h @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 2007 by Lukasz Fibinger <lucke@o2.pl> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You 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 FILTERBAR_H +#define FILTERBAR_H + +#include <qwidget.h> + +class QLabel; +class QCheckBox; +class KConfig; +class KLineEdit; +class KPushButton; +class KToolBarButton; + +namespace kt +{ + class TorrentInterface; +} + +/** + * Provides a filterbar allowing to show only select items + * + * based on dolphin's one (made by Gregor Kališnik) + */ +class FilterBar : public QWidget +{ + Q_OBJECT + +public: + FilterBar ( QWidget *parent = 0, const char *name = 0 ); + virtual ~FilterBar(); + + bool matchesFilter(kt::TorrentInterface* tc); + void saveSettings(KConfig* cfg); + void loadSettings(KConfig* cfg); + +private slots: + void slotChangeFilter(const QString& nameFilter); + +protected: + virtual void keyPressEvent ( QKeyEvent* event ); + virtual void hideEvent(QHideEvent* event); + +private: + QLabel* m_filter; + KLineEdit* m_filterInput; + KPushButton* m_clear; + QCheckBox* m_case_sensitive; + KToolBarButton* m_close; + QString m_name_filter; +}; + +#endif diff --git a/apps/ktorrent/generalpref.ui b/apps/ktorrent/generalpref.ui new file mode 100644 index 0000000..e8ffe7d --- /dev/null +++ b/apps/ktorrent/generalpref.ui @@ -0,0 +1,475 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>GeneralPref</class> +<widget class="QWidget"> + <property name="name"> + <cstring>GeneralPref</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>603</width> + <height>657</height> + </rect> + </property> + <property name="caption"> + <string>General Options</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="5" column="0"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>50</height> + </size> + </property> + </spacer> + <widget class="QGroupBox" row="4" column="0"> + <property name="name"> + <cstring>groupBox5</cstring> + </property> + <property name="title"> + <string>Encryption</string> + </property> + <property name="toolTip" stdset="0"> + <string></string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>use_encryption</cstring> + </property> + <property name="text"> + <string>Use protocol encryption</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Protocol encryption is used to prevent ISP's from slowing down bittorrent connections.</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>allow_unencrypted</cstring> + </property> + <property name="text"> + <string>Allow unencrypted connections</string> + </property> + <property name="toolTip" stdset="0"> + <string>If unchecked, you'll be able to connect only to clients supporting encryption.</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QGroupBox" row="3" column="0"> + <property name="name"> + <cstring>groupBox4</cstring> + </property> + <property name="title"> + <string>DHT</string> + </property> + <property name="toolTip" stdset="0"> + <string><b>D</b>istributed <b>H</b>ash <b>T</b>able protocol.<br>Decentralized peers exchange protocol. See manual for more info.</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>use_dht</cstring> + </property> + <property name="text"> + <string>&Use DHT to get additional peers</string> + </property> + <property name="toolTip" stdset="0"> + <string></string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>dht_port_label</cstring> + </property> + <property name="text"> + <string>UDP port for DHT communication:</string> + </property> + </widget> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>dht_port</cstring> + </property> + <property name="maxValue"> + <number>65535</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="value"> + <number>6881</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QGroupBox" row="2" column="0"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Custom IP</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>custom_ip_check</cstring> + </property> + <property name="text"> + <string>Se&nd the tracker a custom IP address or hostname</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>custom_ip_label</cstring> + </property> + <property name="text"> + <string>Custom IP address or hostname:</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>custom_ip</cstring> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox3_2</cstring> + </property> + <property name="title"> + <string>System Tray Icon</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox" row="0" column="0"> + <property name="name"> + <cstring>show_systray_icon</cstring> + </property> + <property name="text"> + <string>Show s&ystem tray icon</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>show_speedbar</cstring> + </property> + <property name="text"> + <string>Show speed &bar in tray icon</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>show_popups</cstring> + </property> + <property name="text"> + <string>Show system tray popup messages</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QLayoutWidget" row="0" column="1" rowspan="2" colspan="1"> + <property name="name"> + <cstring>layout13</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1_3_2_2_2_2</cstring> + </property> + <property name="text"> + <string>Upload bandwidth (in KB/sec):</string> + </property> + </widget> + <widget class="KIntSpinBox" row="1" column="1"> + <property name="name"> + <cstring>uploadBandwidth</cstring> + </property> + <property name="buttonSymbols"> + <enum>UpDownArrows</enum> + </property> + <property name="maxValue"> + <number>1000000</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="value"> + <number>500</number> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1_3_2_2_2</cstring> + </property> + <property name="text"> + <string>Download bandwidth (in KB/sec):</string> + </property> + </widget> + <widget class="KIntSpinBox" row="0" column="1"> + <property name="name"> + <cstring>downloadBandwidth</cstring> + </property> + <property name="buttonSymbols"> + <enum>UpDownArrows</enum> + </property> + <property name="maxValue"> + <number>1000000</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="value"> + <number>500</number> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Folders</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>layout24</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Folder to store temporary files:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>temp_dir</cstring> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>temp_dir</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>checkCompletedDir</cstring> + </property> + <property name="text"> + <string>Move completed downloads to:</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>autosave_downloads_check</cstring> + </property> + <property name="text"> + <string>&Automatically save downloads to:</string> + </property> + </widget> + <widget class="QLayoutWidget" row="1" column="1" rowspan="3" colspan="1"> + <property name="name"> + <cstring>layout14</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KURLRequester"> + <property name="name"> + <cstring>autosave_location</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>urlCompletedDir</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>urlTorrentDir</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </vbox> + </widget> + <widget class="QCheckBox" row="3" column="0"> + <property name="name"> + <cstring>checkTorrentDir</cstring> + </property> + <property name="text"> + <string>Copy .torrent files to:</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>show_speedbar</sender> + <signal>toggled(bool)</signal> + <receiver>textLabel1_3_2_2_2</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>show_speedbar</sender> + <signal>toggled(bool)</signal> + <receiver>textLabel1_3_2_2_2_2</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>show_speedbar</sender> + <signal>toggled(bool)</signal> + <receiver>downloadBandwidth</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>show_speedbar</sender> + <signal>toggled(bool)</signal> + <receiver>uploadBandwidth</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkCompletedDir</sender> + <signal>toggled(bool)</signal> + <receiver>urlCompletedDir</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>autosave_downloads_check</sender> + <signal>toggled(bool)</signal> + <receiver>autosave_location</receiver> + <slot>setEnabled(bool)</slot> + </connection> + <connection> + <sender>checkTorrentDir</sender> + <signal>toggled(bool)</signal> + <receiver>urlTorrentDir</receiver> + <slot>setEnabled(bool)</slot> + </connection> +</connections> +<tabstops> + <tabstop>autosave_downloads_check</tabstop> + <tabstop>show_systray_icon</tabstop> +</tabstops> +<pixmapinproject/> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/groups/Makefile.am b/apps/ktorrent/groups/Makefile.am new file mode 100644 index 0000000..c1c3308 --- /dev/null +++ b/apps/ktorrent/groups/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I$(srcdir)/../../../libktorrent $(all_includes) +METASOURCES = AUTO +libgroups_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libgroups.la +noinst_HEADERS = activedownloadsgroup.h activegroup.h activeuploadsgroup.h \ + allgroup.h downloadgroup.h group.h groupmanager.h groupview.h \ + inactivedownloadsgroup.h inactivegroup.h inactiveuploadsgroup.h queueddownloadsgroup.h \ + queueduploadsgroup.h torrentdrag.h torrentgroup.h uploadgroup.h userdownloadsgroup.h \ + useruploadsgroup.h +libgroups_la_SOURCES = activedownloadsgroup.cpp activegroup.cpp \ + activeuploadsgroup.cpp allgroup.cpp downloadgroup.cpp group.cpp groupmanager.cpp groupview.cpp \ + inactivedownloadsgroup.cpp inactivegroup.cpp inactiveuploadsgroup.cpp queueddownloadsgroup.cpp \ + queueduploadsgroup.cpp torrentdrag.cpp torrentgroup.cpp uploadgroup.cpp userdownloadsgroup.cpp \ + useruploadsgroup.cpp +KDE_CXXFLAGS = $(USE_EXCEPTIONS) $(USE_RTTI) diff --git a/apps/ktorrent/groups/activedownloadsgroup.cpp b/apps/ktorrent/groups/activedownloadsgroup.cpp new file mode 100644 index 0000000..e4dd02f --- /dev/null +++ b/apps/ktorrent/groups/activedownloadsgroup.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "activedownloadsgroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + ActiveDownloadsGroup::ActiveDownloadsGroup() + : Group(i18n("Active downloads"),DOWNLOADS_ONLY_GROUP) + { + setIconByName("down"); + } + + + ActiveDownloadsGroup::~ActiveDownloadsGroup() + {} + +} + +bool kt::ActiveDownloadsGroup::isMember(TorrentInterface * tor) +{ + if (!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + + return s.running && !s.completed; +} + + diff --git a/apps/ktorrent/groups/activedownloadsgroup.h b/apps/ktorrent/groups/activedownloadsgroup.h new file mode 100644 index 0000000..de62493 --- /dev/null +++ b/apps/ktorrent/groups/activedownloadsgroup.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 ACTIVEDOWNLOADSGROUP_H +#define ACTIVEDOWNLOADSGROUP_H + +#include "group.h" + +namespace kt +{ + class TorrentInterface; + + /** + * Group for active downloads. + * @author Ivan Vasic <ivasic@gmail.com> + */ + + class ActiveDownloadsGroup : public Group + { + + public: + ActiveDownloadsGroup(); + virtual ~ActiveDownloadsGroup(); + + virtual bool isMember(TorrentInterface* tor); + + }; +} +#endif diff --git a/apps/ktorrent/groups/activegroup.cpp b/apps/ktorrent/groups/activegroup.cpp new file mode 100644 index 0000000..48a60ae --- /dev/null +++ b/apps/ktorrent/groups/activegroup.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "activegroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + +ActiveGroup::ActiveGroup() + : Group(i18n("Active torrents"),MIXED_GROUP) +{ + setIconByName("metacontact_online"); +} + + +ActiveGroup::~ActiveGroup() +{} + +} + +bool kt::ActiveGroup::isMember(TorrentInterface * tor) +{ + if(!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + return s.running; +} + + diff --git a/apps/ktorrent/groups/activegroup.h b/apps/ktorrent/groups/activegroup.h new file mode 100644 index 0000000..73e2aef --- /dev/null +++ b/apps/ktorrent/groups/activegroup.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 ACTIVEGROUP_H +#define ACTIVEGROUP_H + +#include "group.h" + +namespace kt +{ + class TorrentInterface; + + /** + * Group for active torrents. + * @author Ivan Vasic <ivasic@gmail.com> + */ + + class ActiveGroup : public Group + { + + public: + ActiveGroup(); + virtual ~ActiveGroup(); + + virtual bool isMember(TorrentInterface* tor); + + }; +} +#endif diff --git a/apps/ktorrent/groups/activeuploadsgroup.cpp b/apps/ktorrent/groups/activeuploadsgroup.cpp new file mode 100644 index 0000000..aa50e97 --- /dev/null +++ b/apps/ktorrent/groups/activeuploadsgroup.cpp @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "activeuploadsgroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + + ActiveUploadsGroup::ActiveUploadsGroup() + : Group(i18n("Active uploads"), UPLOADS_ONLY_GROUP) + { + setIconByName("up"); + } + + + ActiveUploadsGroup::~ActiveUploadsGroup() + {} + +} + +bool kt::ActiveUploadsGroup::isMember(TorrentInterface * tor) +{ + if (!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + + return s.running && s.completed; +} + + diff --git a/apps/ktorrent/groups/activeuploadsgroup.h b/apps/ktorrent/groups/activeuploadsgroup.h new file mode 100644 index 0000000..02fd468 --- /dev/null +++ b/apps/ktorrent/groups/activeuploadsgroup.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 ACTIVEUPLOADSGROUP_H +#define ACTIVEUPLOADSGROUP_H + +#include "group.h" + +namespace kt +{ + class TorrentInterface; + + /** + * Group for active uploads. + * @author Ivan Vasic <ivasic@gmail.com> + */ + + class ActiveUploadsGroup : public Group + { + + public: + ActiveUploadsGroup(); + virtual ~ActiveUploadsGroup(); + + virtual bool isMember(TorrentInterface* tor); + + }; +} +#endif diff --git a/apps/ktorrent/groups/allgroup.cpp b/apps/ktorrent/groups/allgroup.cpp new file mode 100644 index 0000000..eba5391 --- /dev/null +++ b/apps/ktorrent/groups/allgroup.cpp @@ -0,0 +1,41 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <klocale.h> +#include "allgroup.h" + +namespace kt +{ + + AllGroup::AllGroup() : Group(i18n("All Torrents"),MIXED_GROUP) + { + setIconByName("folder"); + } + + + AllGroup::~AllGroup() + {} + + + bool AllGroup::isMember(TorrentInterface* tor) + { + return tor != 0; + } + +} diff --git a/apps/ktorrent/groups/allgroup.h b/apps/ktorrent/groups/allgroup.h new file mode 100644 index 0000000..399691b --- /dev/null +++ b/apps/ktorrent/groups/allgroup.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTALLGROUP_H +#define KTALLGROUP_H + +#include <group.h> + +namespace kt +{ + + /** + @author Joris Guisson <joris.guisson@gmail.com> + */ + class AllGroup : public Group + { + public: + AllGroup(); + virtual ~AllGroup(); + + virtual bool isMember(TorrentInterface* tor); + + }; + +} + +#endif diff --git a/apps/ktorrent/groups/downloadgroup.cpp b/apps/ktorrent/groups/downloadgroup.cpp new file mode 100644 index 0000000..085eb77 --- /dev/null +++ b/apps/ktorrent/groups/downloadgroup.cpp @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <klocale.h> +#include <interfaces/torrentinterface.h> +#include "downloadgroup.h" + +namespace kt +{ + + DownloadGroup::DownloadGroup() : Group(i18n("Downloads"),DOWNLOADS_ONLY_GROUP) + { + setIconByName("down"); + } + + + DownloadGroup::~DownloadGroup() + {} + + + bool DownloadGroup::isMember(TorrentInterface* tor) + { + if (!tor) + return false; + + return !tor->getStats().completed; + } + +} diff --git a/apps/ktorrent/groups/downloadgroup.h b/apps/ktorrent/groups/downloadgroup.h new file mode 100644 index 0000000..959f74b --- /dev/null +++ b/apps/ktorrent/groups/downloadgroup.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTDOWNLOADGROUP_H +#define KTDOWNLOADGROUP_H + +#include <group.h> + +namespace kt +{ + + /** + @author Joris Guisson <joris.guisson@gmail.com> + */ + class DownloadGroup : public Group + { + public: + DownloadGroup(); + virtual ~DownloadGroup(); + + virtual bool isMember(TorrentInterface* tor); + + }; + +} + +#endif diff --git a/apps/ktorrent/groups/group.cpp b/apps/ktorrent/groups/group.cpp new file mode 100644 index 0000000..b8441a7 --- /dev/null +++ b/apps/ktorrent/groups/group.cpp @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <kiconloader.h> +#include <kglobal.h> +#include "group.h" + +namespace kt +{ + + Group::Group(const QString & name,int flags) : name(name),flags(flags) + {} + + + Group::~Group() + {} + + void Group::save(bt::BEncoder*) + { + } + + void Group::load(bt::BDictNode* ) + { + } + + void Group::setIconByName(const QString & in) + { + icon_name = in; + icon = KGlobal::iconLoader()->loadIcon(in,KIcon::Small); + } + + void Group::rename(const QString & nn) + { + name = nn; + } + + void Group::torrentRemoved(TorrentInterface* ) + {} + + void Group::removeTorrent(TorrentInterface* ) + {} + + void Group::addTorrent(TorrentInterface* ) + {} +} diff --git a/apps/ktorrent/groups/group.h b/apps/ktorrent/groups/group.h new file mode 100644 index 0000000..e1fa7ab --- /dev/null +++ b/apps/ktorrent/groups/group.h @@ -0,0 +1,133 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTGROUP_H +#define KTGROUP_H + +#include <qstring.h> +#include <qpixmap.h> + +namespace bt +{ + class BEncoder; + class BDictNode; +} + +namespace kt +{ + class TorrentInterface; + + /** + * @author Joris Guisson <joris.guisson@gmail.com> + * + * Base class for all groups. Subclasses should only implement the + * isMember function, but can also provide save and load + * functionality. + */ + class Group + { + protected: + QString name; + QPixmap icon; + QString icon_name; + int flags; + public: + enum Properties + { + UPLOADS_ONLY_GROUP = 1, + DOWNLOADS_ONLY_GROUP = 2, + MIXED_GROUP = 3, + CUSTOM_GROUP = 4 + }; + /** + * Create a new group. + * @param name The name of the group + * @param flags Properties of the group + */ + Group(const QString & name,int flags); + virtual ~Group(); + + /// See if this is a standard group. + bool isStandardGroup() const {return !(flags & CUSTOM_GROUP);} + + /// Get the group flags + int groupFlags() const {return flags;} + + /** + * Rename the group. + * @param nn The new name + */ + void rename(const QString & nn); + + /** + * Set the group icon by name. + * @param in The icon name + */ + void setIconByName(const QString & in); + + /// Get the name of the group + const QString & groupName() const {return name;} + + /// Get the icon of the group + const QPixmap & groupIcon() const {return icon;} + + /** + * Save the torrents.The torrents should be save in a bencoded file. + * @param enc The BEncoder + */ + virtual void save(bt::BEncoder* enc); + + + /** + * Load the torrents of the group from a BDictNode. + * @param n The BDictNode + */ + virtual void load(bt::BDictNode* n); + + + /** + * Test if a torrent is a member of this group. + * @param tor The torrent + */ + virtual bool isMember(TorrentInterface* tor) = 0; + + /** + * The torrent has been removed and is about to be deleted. + * Subclasses should make sure that they don't have dangling + * pointers to this torrent. + * @param tor The torrent + */ + virtual void torrentRemoved(TorrentInterface* tor); + + /** + * Subclasses should implement this, if they want to have torrents added to them. + * @param tor The torrent + */ + virtual void addTorrent(TorrentInterface* tor); + + /** + * Subclasses should implement this, if they want to have torrents removed from them. + * @param tor The torrent + */ + virtual void removeTorrent(TorrentInterface* tor); + }; + +} + +#endif diff --git a/apps/ktorrent/groups/groupmanager.cpp b/apps/ktorrent/groups/groupmanager.cpp new file mode 100644 index 0000000..b6a84c4 --- /dev/null +++ b/apps/ktorrent/groups/groupmanager.cpp @@ -0,0 +1,221 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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/log.h> +#include <util/file.h> +#include <util/fileops.h> +#include <util/error.h> +#include <torrent/bnode.h> +#include <torrent/bdecoder.h> +#include <torrent/bencoder.h> +#include "groupmanager.h" +#include "torrentgroup.h" +#include "allgroup.h" +#include "downloadgroup.h" +#include "uploadgroup.h" +#include "torrentgroup.h" +#include "queueddownloadsgroup.h" +#include "queueduploadsgroup.h" +#include "userdownloadsgroup.h" +#include "useruploadsgroup.h" +#include "inactivegroup.h" +#include "inactivedownloadsgroup.h" +#include "inactiveuploadsgroup.h" +#include "activegroup.h" +#include "activedownloadsgroup.h" +#include "activeuploadsgroup.h" + +using namespace bt; + +namespace kt +{ + + GroupManager::GroupManager() + { + setAutoDelete(true); + default_groups.setAutoDelete(true); + + Group* g = new AllGroup(); + default_groups.insert(g->groupName(),g); + + g = new UploadGroup(); + default_groups.insert(g->groupName(),g); + + g = new DownloadGroup(); + default_groups.insert(g->groupName(),g); + + g = new QueuedDownloadsGroup(); + default_groups.insert(g->groupName(),g); + + g = new QueuedUploadsGroup(); + default_groups.insert(g->groupName(),g); + + g = new UserDownloadsGroup(); + default_groups.insert(g->groupName(),g); + + g = new UserUploadsGroup(); + default_groups.insert(g->groupName(),g); + + g = new ActiveGroup(); + default_groups.insert(g->groupName(),g); + + g = new ActiveUploadsGroup(); + default_groups.insert(g->groupName(),g); + + g = new ActiveDownloadsGroup(); + default_groups.insert(g->groupName(),g); + + g = new InactiveGroup(); + default_groups.insert(g->groupName(),g); + + g = new InactiveUploadsGroup(); + default_groups.insert(g->groupName(),g); + + g = new InactiveDownloadsGroup(); + default_groups.insert(g->groupName(),g); + } + + + GroupManager::~GroupManager() + { + } + + + Group* GroupManager::newGroup(const QString & name) + { + if (find(name)) + return 0; + + Group* g = new TorrentGroup(name); + insert(name,g); + return g; + } + + bool GroupManager::canRemove(const Group* g) const + { + return default_groups.find(g->groupName()) == 0; + } + + + void GroupManager::saveGroups(const QString & fn) + { + bt::File fptr; + if (!fptr.open(fn,"wb")) + { + bt::Out() << "Cannot open " << fn << " : " << fptr.errorString() << bt::endl; + return; + } + + try + { + bt::BEncoder enc(&fptr); + + enc.beginList(); + for (iterator i = begin();i != end();i++) + { + i->second->save(&enc); + } + enc.end(); + } + catch (bt::Error & err) + { + bt::Out() << "Error : " << err.toString() << endl; + return; + } + } + + + + void GroupManager::loadGroups(const QString & fn) + { + bt::File fptr; + if (!fptr.open(fn,"rb")) + { + bt::Out() << "Cannot open " << fn << " : " << fptr.errorString() << bt::endl; + return; + } + try + { + Uint32 fs = bt::FileSize(fn); + QByteArray data(fs); + fptr.read(data.data(),fs); + + BDecoder dec(data,false); + bt::BNode* n = dec.decode(); + if (!n || n->getType() != bt::BNode::LIST) + throw bt::Error("groups file corrupt"); + + BListNode* ln = (BListNode*)n; + for (Uint32 i = 0;i < ln->getNumChildren();i++) + { + BDictNode* dn = ln->getDict(i); + if (!dn) + continue; + + TorrentGroup* g = new TorrentGroup("dummy"); + + try + { + g->load(dn); + } + catch (...) + { + delete g; + throw; + } + + if (!find(g->groupName())) + insert(g->groupName(),g); + else + delete g; + } + } + catch (bt::Error & err) + { + bt::Out() << "Error : " << err.toString() << endl; + return; + } + } + + void GroupManager::torrentRemoved(TorrentInterface* ti) + { + for (iterator i = begin(); i != end();i++) + { + i->second->torrentRemoved(ti); + } + } + + void GroupManager::renameGroup(const QString & old_name,const QString & new_name) + { + Group* g = find(old_name); + if (!g) + return; + + setAutoDelete(false); + erase(old_name); + g->rename(new_name); + insert(new_name,g); + setAutoDelete(true); + } + + Group* GroupManager::findDefault(const QString & name) + { + return default_groups.find(name); + } +} diff --git a/apps/ktorrent/groups/groupmanager.h b/apps/ktorrent/groups/groupmanager.h new file mode 100644 index 0000000..d988b70 --- /dev/null +++ b/apps/ktorrent/groups/groupmanager.h @@ -0,0 +1,132 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTGROUPMANAGER_H +#define KTGROUPMANAGER_H + +#include <qstring.h> +#include <klocale.h> +#include <util/ptrmap.h> + + +namespace kt +{ + class Group; + class TorrentInterface; + + /** + * @author Joris Guisson <joris.guisson@gmail.com> + * + * Manages all user created groups and the standard groups. + */ + class GroupManager : public bt::PtrMap<QString,Group> + { + bt::PtrMap<QString,Group> default_groups; + + public: + GroupManager(); + virtual ~GroupManager(); + + /** + * Create a new user created group. + * @param name Name of the group + * @return Pointer to the group or NULL, if another group already exists with the same name. + */ + Group* newGroup(const QString & name); + + /// Get the group off all torrents + Group* allGroup() {return findDefault(i18n("All Torrents"));} + + /// Get the group of downloads + Group* downloadGroup() {return findDefault(i18n("Downloads"));} + + /// Get the group of seeds + Group* uploadGroup() {return findDefault(i18n("Uploads"));} + + /// Get the group of queued downloads + Group* queuedDownloadsGroup() { return findDefault(i18n("Queued downloads")); } + + /// Get the group of queued seeds + Group* queuedUploadsGroup() { return findDefault(i18n("Queued uploads")); } + + /// Get the group of user controlled downloads + Group* userDownloadsGroup() { return findDefault(i18n("User downloads")); } + + /// Get the group of user controlled seeds + Group* userUploadsGroup() { return findDefault(i18n("User uploads")); } + + /// Get the group of inactive torrents + Group* inactiveGroup() { return findDefault(i18n("Inactive torrents")); } + + /// Get the group of inactive downloads + Group* inactiveDownloadsGroup() { return findDefault(i18n("Inactive downloads")); } + + /// Get the group of inactive uploads + Group* inactiveUploadsGroup() { return findDefault(i18n("Inactive uploads")); } + + /// Get the group of inactive torrents + Group* activeGroup() { return findDefault(i18n("Active torrents")); } + + /// Get the group of inactive downloads + Group* activeDownloadsGroup() { return findDefault(i18n("Active downloads")); } + + /// Get the group of inactive uploads + Group* activeUploadsGroup() { return findDefault(i18n("Active uploads")); } + + /// Find a default group by the given name + Group* findDefault(const QString & name); + + /** + * Save the groups to a file. + * @param fn The filename + */ + void saveGroups(const QString & fn); + + /** + * Load the groups from a file + * @param fn The filename + */ + void loadGroups(const QString & fn); + + /** + * See if we can remove a group. + * @param g The group + * @return true on any user created group, false on the standard ones + */ + bool canRemove(const Group* g) const; + + /** + * A torrent has been removed. This function checks all groups and + * removes the torrent from it. + * @param ti The torrent + */ + void torrentRemoved(TorrentInterface* ti); + + /** + * Rename a group. + * @param old_name The old name + * @param new_name The new name + */ + void renameGroup(const QString & old_name,const QString & new_name); + + }; + +} + +#endif diff --git a/apps/ktorrent/groups/groupview.cpp b/apps/ktorrent/groups/groupview.cpp new file mode 100644 index 0000000..3d0751f --- /dev/null +++ b/apps/ktorrent/groups/groupview.cpp @@ -0,0 +1,360 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <klocale.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kpopupmenu.h> +#include <kaction.h> +#include <kmessagebox.h> +#include <kinputdialog.h> +#include <kstandarddirs.h> +#include <kpopupmenu.h> +#include <qheader.h> +#include <util/log.h> +#include <interfaces/torrentinterface.h> +#include "groupview.h" +#include "group.h" +#include "groupmanager.h" +#include "torrentgroup.h" +#include "../viewmanager.h" +#include "../ktorrentview.h" + + +using namespace bt; + +namespace kt +{ + GroupViewItem::GroupViewItem(GroupView* parent,Group* g) : KListViewItem(parent),gview(parent) + { + setText(0,g->groupName()); + setPixmap(0,g->groupIcon()); + } + + GroupViewItem::GroupViewItem(GroupView* gview,KListViewItem* parent,Group* g) : KListViewItem(parent),gview(gview) + { + setText(0,g->groupName()); + setPixmap(0,g->groupIcon()); + } + + GroupViewItem::~GroupViewItem() + { + } + + int GroupViewItem::compare(QListViewItem* i,int ,bool ) const + { + if (text(1).isNull() && i->text(1).isNull()) + return QString::compare(text(0),i->text(0)); + else + return QString::compare(text(1),i->text(1)); + } + + GroupView::GroupView(ViewManager* view,KActionCollection* col,QWidget *parent, const char *name) + : KListView(parent, name),view(view),custom_root(0) + { + setFullWidth(true); + setRootIsDecorated(true); + setAcceptDrops(true); + setDropHighlighter(true); + setDropVisualizer(true); + addColumn(i18n("Groups")); + header()->hide(); + + gman = new GroupManager(); + + current = gman->allGroup(); + + connect(this,SIGNAL(clicked(QListViewItem*)),this,SLOT(onExecuted( QListViewItem* ))); + connect(this,SIGNAL(contextMenu(KListView*,QListViewItem*,const QPoint & )), + this,SLOT(showContextMenu( KListView*, QListViewItem*, const QPoint& ))); + connect(this,SIGNAL(dropped(QDropEvent*,QListViewItem*)), + this,SLOT(onDropped( QDropEvent*, QListViewItem* ))); + + current_item = 0; + menu = 0; + createMenu(col); + save_file = KGlobal::dirs()->saveLocation("data","ktorrent") + "groups"; + GroupViewItem* all = addGroup(gman->allGroup(),0); + GroupViewItem* dwnld = addGroup(gman->downloadGroup(),all); + GroupViewItem* upld = addGroup(gman->uploadGroup(),all); + GroupViewItem* inactive = addGroup(gman->inactiveGroup(), all); + GroupViewItem* active = addGroup(gman->activeGroup(), all); + addGroup(gman->queuedDownloadsGroup(), dwnld); + addGroup(gman->queuedUploadsGroup(), upld); + addGroup(gman->userDownloadsGroup(), dwnld); + addGroup(gman->userUploadsGroup(), upld); + addGroup(gman->inactiveDownloadsGroup(), inactive); + addGroup(gman->inactiveUploadsGroup(), inactive); + addGroup(gman->activeDownloadsGroup(), active); + addGroup(gman->activeUploadsGroup(), active); + + custom_root = new KListViewItem(all,i18n("Custom Groups")); + custom_root->setPixmap(0,KGlobal::iconLoader()->loadIcon("folder",KIcon::Small)); + setOpen(custom_root,true); + } + + + GroupView::~GroupView() + { + delete gman; + } + + void GroupView::saveGroups() + { + gman->saveGroups(save_file); + } + + void GroupView::loadGroups() + { + // load the groups from the groups file + gman->loadGroups(save_file); + for (GroupManager::iterator i = gman->begin();i != gman->end();i++) + { + addGroup(i->second,custom_root); + } + sort(); + } + + void GroupView::createMenu(KActionCollection* col) + { + menu = new KPopupMenu(this); + + new_group = new KAction(i18n("New Group"),"filenew",0, + this, SLOT(addGroup()),col, "New Group"); + + edit_group = new KAction(i18n("Edit Name"),"edit",0, + this, SLOT(editGroupName()),col,"Edit Group Name"); + + remove_group = new KAction(i18n("Remove Group"),"remove",0, + this, SLOT(removeGroup()),col,"Remove Group"); + + open_in_new_tab = new KAction(i18n("Open Tab"),"fileopen",0, + this,SLOT(openView()),col,"Open Tab"); + + open_in_new_tab->plug(menu); + menu->insertSeparator(); + new_group->plug(menu); + edit_group->plug(menu); + remove_group->plug(menu); + } + + void GroupView::addGroup() + { + QString name = KInputDialog::getText(QString::null,i18n("Please enter the group name.")); + + if (name.isNull() || name.length() == 0) + return; + + if (gman->find(name)) + { + KMessageBox::error(this,i18n("The group %1 already exists.").arg(name)); + return; + } + + addGroup(gman->newGroup(name),custom_root); + saveGroups(); + sort(); + } + + void GroupView::removeGroup() + { + if (!current_item) + return; + + Group* g = groups.find(current_item); + if (!g) + return; + + groupRemoved(g); + if (g == current) + { + current = gman->allGroup(); + currentGroupChanged(current); + } + + groups.erase(current_item); + gman->erase(g->groupName()); + delete current_item; + current_item = 0; + saveGroups(); + } + + void GroupView::editGroupName() + { + if (!current_item) + return; + + Group* g = groups.find(current_item); + if (!g) + return; + + QString name = KInputDialog::getText(QString::null,i18n("Please enter the new group name."),g->groupName()); + + if (name.isNull() || name.length() == 0) + return; + + if (g->groupName() == name) + return; + + if (gman->find(name)) + { + KMessageBox::error(this,i18n("The group %1 already exists.").arg(name)); + } + else + { + gman->renameGroup(g->groupName(),name); + current_item->setText(0,name); + groupRenamed(g); + saveGroups(); + sort(); + } + } + + GroupViewItem* GroupView::addGroup(Group* g,KListViewItem* parent) + { + GroupViewItem* li = 0; + if (parent) + { + li = new GroupViewItem(this,parent,g); + } + else + { + li = new GroupViewItem(this,g); + li->setText(1,g->groupName()); + } + + groups.insert(li,g); + if (custom_root && custom_root->childCount() == 1 && custom_root == parent) + setOpen(custom_root,true); + + return li; + } + + void GroupView::showContextMenu(KListView* ,QListViewItem* item,const QPoint & p) + { + current_item = dynamic_cast<GroupViewItem*>(item); + + Group* g = 0; + if (current_item) + g = groups.find(current_item); + + if (!g ||!gman->canRemove(g)) + { + edit_group->setEnabled(false); + remove_group->setEnabled(false); + } + else + { + edit_group->setEnabled(true); + remove_group->setEnabled(true); + } + + open_in_new_tab->setEnabled(g != 0); + + menu->popup(p); + } + + void GroupView::onExecuted(QListViewItem* item) + { + if (!item) return; + + GroupViewItem* li = dynamic_cast<GroupViewItem*>(item); + if (!li) + return; + + Group* g = groups.find(li); + if (g) + { + current = g; + currentGroupChanged(g); + } + } + + void GroupView::onDropped(QDropEvent* e,QListViewItem *after) + { + GroupViewItem* li = dynamic_cast<GroupViewItem*>(after); + if (!li) + return; + + TorrentGroup* g = dynamic_cast<TorrentGroup*>(groups.find(li)); + if (g) + { + QValueList<TorrentInterface*> sel; + view->getSelection(sel); + QValueList<TorrentInterface*>::iterator i = sel.begin(); + while (i != sel.end()) + { + g->add(*i); + i++; + } + saveGroups(); + } + } + + bool GroupView::acceptDrag(QDropEvent* event) const + { + return event->provides("application/x-ktorrent-drag-object"); + } + + void GroupView::onTorrentRemoved(kt::TorrentInterface* tc) + { + gman->torrentRemoved(tc); + saveGroups(); + } + + void GroupView::updateGroupsSubMenu(KPopupMenu* gsm) + { + gsm->clear(); + for (GroupManager::iterator i = gman->begin();i != gman->end();i++) + { + gsm->insertItem(i->first); + } + } + + void GroupView::onGroupsSubMenuItemActivated(KTorrentView* v,const QString & group) + { + Group* g = gman->find(group); + if (g) + { + v->addSelectionToGroup(g); + saveGroups(); + } + } + + const Group* GroupView::findGroup(const QString & name) const + { + Group* g = gman->find(name); + if (!g) + g = gman->findDefault(name); + + return g; + } + + void GroupView::openView() + { + if (!current_item) + return; + + Group* g = groups.find(current_item); + if (g) + openNewTab(g); + } +} + +#include "groupview.moc" diff --git a/apps/ktorrent/groups/groupview.h b/apps/ktorrent/groups/groupview.h new file mode 100644 index 0000000..de5befb --- /dev/null +++ b/apps/ktorrent/groups/groupview.h @@ -0,0 +1,125 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTGROUPVIEW_H +#define KTGROUPVIEW_H + +#include <klistview.h> +#include <util/ptrmap.h> + +class KPopupMenu; +class KActionCollection; +class ViewManager; +class KTorrentView; + +namespace kt +{ + class Group; + class GroupView; + class GroupManager; + class TorrentInterface; + + class GroupViewItem : public KListViewItem + { + Group* g; + GroupView* gview; + public: + GroupViewItem(GroupView* parent,Group* g); + GroupViewItem(GroupView* gview,KListViewItem* parent,Group* g); + virtual ~GroupViewItem(); + + virtual int compare(QListViewItem* i,int col,bool ascending) const; + }; + + /** + @author Joris Guisson <joris.guisson@gmail.com> + */ + class GroupView : public KListView + { + Q_OBJECT + public: + GroupView(ViewManager* view,KActionCollection* col,QWidget *parent = 0, const char *name = 0); + virtual ~GroupView(); + + /// Get the current group + Group* currentGroup() {return current;} + + /// Save all groups + void saveGroups(); + + /// Load groups + void loadGroups(); + + /// Find a group by its name + const Group* findGroup(const QString & name) const; + + GroupManager* groupManager() const { return gman; } + + public slots: + void onTorrentRemoved(kt::TorrentInterface* tc); + + /// Update a groups sub menu + void updateGroupsSubMenu(KPopupMenu* gsm); + + /// An item was activated in the groups sub menu of a KTorrentView + void onGroupsSubMenuItemActivated(KTorrentView* v,const QString & group); + + private slots: + void onExecuted(QListViewItem* item); + void showContextMenu(KListView* ,QListViewItem* item,const QPoint & p); + void addGroup(); + void removeGroup(); + void editGroupName(); + void onDropped(QDropEvent* e,QListViewItem *after); + virtual bool acceptDrag(QDropEvent* event) const; + void openView(); + + + signals: + void currentGroupChanged(kt::Group* g); + void groupRenamed(kt::Group* g); + void openNewTab(kt::Group* g); + void groupRemoved(kt::Group* g); + + private: + void createMenu(KActionCollection* col); + GroupViewItem* addGroup(Group* g,KListViewItem* parent); + + private: + ViewManager* view; + KListViewItem* custom_root; + bt::PtrMap<GroupViewItem*,Group> groups; + GroupManager* gman; + QString save_file; + + Group* current; + + GroupViewItem* current_item; + KPopupMenu* menu; + KAction* new_group; + KAction* edit_group; + KAction* remove_group; + KAction* open_in_new_tab; + + friend class GroupViewItem; + }; + +} + +#endif diff --git a/apps/ktorrent/groups/inactivedownloadsgroup.cpp b/apps/ktorrent/groups/inactivedownloadsgroup.cpp new file mode 100644 index 0000000..b383160 --- /dev/null +++ b/apps/ktorrent/groups/inactivedownloadsgroup.cpp @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "inactivedownloadsgroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + + InactiveDownloadsGroup::InactiveDownloadsGroup() + : Group(i18n("Inactive downloads"), DOWNLOADS_ONLY_GROUP) + { + setIconByName("down"); + } + + + InactiveDownloadsGroup::~InactiveDownloadsGroup() + {} + +} + +bool kt::InactiveDownloadsGroup::isMember(TorrentInterface * tor) +{ + if (!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + + return !s.running && !s.completed; +} + + diff --git a/apps/ktorrent/groups/inactivedownloadsgroup.h b/apps/ktorrent/groups/inactivedownloadsgroup.h new file mode 100644 index 0000000..4b80ca6 --- /dev/null +++ b/apps/ktorrent/groups/inactivedownloadsgroup.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 INACTIVEDOWNLOADSGROUP_H +#define INACTIVEDOWNLOADSGROUP_H + +#include "group.h" + +namespace kt +{ + class TorrentInterface; + + /** + * Group for inactive downloads. + * @author Ivan Vasic <ivasic@gmail.com> + */ + + class InactiveDownloadsGroup : public Group + { + + public: + InactiveDownloadsGroup(); + virtual ~InactiveDownloadsGroup(); + + virtual bool isMember(TorrentInterface* tor); + + }; +} +#endif diff --git a/apps/ktorrent/groups/inactivegroup.cpp b/apps/ktorrent/groups/inactivegroup.cpp new file mode 100644 index 0000000..3270697 --- /dev/null +++ b/apps/ktorrent/groups/inactivegroup.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "inactivegroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + +InactiveGroup::InactiveGroup() + : Group(i18n("Inactive torrents"),MIXED_GROUP) +{ + setIconByName("metacontact_offline"); +} + + +InactiveGroup::~InactiveGroup() +{} + +} + +bool kt::InactiveGroup::isMember(TorrentInterface * tor) +{ + if(!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + return !s.running; +} + + diff --git a/apps/ktorrent/groups/inactivegroup.h b/apps/ktorrent/groups/inactivegroup.h new file mode 100644 index 0000000..027138f --- /dev/null +++ b/apps/ktorrent/groups/inactivegroup.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 INACTIVEGROUP_H +#define INACTIVEGROUP_H + +#include "group.h" + +namespace kt +{ + class TorrentInterface; + + /** + * Group for inactive torrents. + * @author Ivan Vasic <ivasic@gmail.com> + */ + + class InactiveGroup : public Group + { + + public: + InactiveGroup(); + virtual ~InactiveGroup(); + + virtual bool isMember(TorrentInterface* tor); + + }; +} +#endif diff --git a/apps/ktorrent/groups/inactiveuploadsgroup.cpp b/apps/ktorrent/groups/inactiveuploadsgroup.cpp new file mode 100644 index 0000000..8110a1a --- /dev/null +++ b/apps/ktorrent/groups/inactiveuploadsgroup.cpp @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "inactiveuploadsgroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + + InactiveUploadsGroup::InactiveUploadsGroup() + : Group(i18n("Inactive uploads"), UPLOADS_ONLY_GROUP) + { + setIconByName("up"); + } + + + InactiveUploadsGroup::~InactiveUploadsGroup() + {} + +} + +bool kt::InactiveUploadsGroup::isMember(TorrentInterface * tor) +{ + if (!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + + return !s.running && s.completed; +} + + diff --git a/apps/ktorrent/groups/inactiveuploadsgroup.h b/apps/ktorrent/groups/inactiveuploadsgroup.h new file mode 100644 index 0000000..78e1840 --- /dev/null +++ b/apps/ktorrent/groups/inactiveuploadsgroup.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 INACTIVEUPLOADSGROUP_H +#define INACTIVEUPLOADSGROUP_H + +#include "group.h" + +namespace kt +{ + class TorrentInterface; + + /** + * Group for inactive uploads. + * @author Ivan Vasic <ivasic@gmail.com> + */ + + class InactiveUploadsGroup : public Group + { + + public: + InactiveUploadsGroup(); + virtual ~InactiveUploadsGroup(); + + virtual bool isMember(TorrentInterface* tor); + + }; +} +#endif diff --git a/apps/ktorrent/groups/queueddownloadsgroup.cpp b/apps/ktorrent/groups/queueddownloadsgroup.cpp new file mode 100644 index 0000000..c182472 --- /dev/null +++ b/apps/ktorrent/groups/queueddownloadsgroup.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "queueddownloadsgroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + + QueuedDownloadsGroup::QueuedDownloadsGroup() + : Group(i18n("Queued downloads"),DOWNLOADS_ONLY_GROUP) + { + setIconByName("ktqueuemanager"); + } + + + QueuedDownloadsGroup::~QueuedDownloadsGroup() + {} +} + +bool kt::QueuedDownloadsGroup::isMember(TorrentInterface* tor) +{ + if(!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + + return !s.user_controlled && !s.completed; +} diff --git a/apps/ktorrent/groups/queueddownloadsgroup.h b/apps/ktorrent/groups/queueddownloadsgroup.h new file mode 100644 index 0000000..3e436a5 --- /dev/null +++ b/apps/ktorrent/groups/queueddownloadsgroup.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTQUEUEDDOWNLOADSGROUP_H +#define KTQUEUEDDOWNLOADSGROUP_H + +#include <group.h> + +namespace kt +{ + class TorrentInterface; + + /** + * Torrents that are queued and in downloading phase. + * @author Ivan Vasic <ivasic@gmail.com> + */ + class QueuedDownloadsGroup : public Group + { + public: + QueuedDownloadsGroup(); + virtual ~QueuedDownloadsGroup(); + + virtual bool isMember(TorrentInterface* tor); + }; + +} + +#endif diff --git a/apps/ktorrent/groups/queueduploadsgroup.cpp b/apps/ktorrent/groups/queueduploadsgroup.cpp new file mode 100644 index 0000000..8c346a4 --- /dev/null +++ b/apps/ktorrent/groups/queueduploadsgroup.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "queueduploadsgroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + + QueuedUploadsGroup::QueuedUploadsGroup() + : Group(i18n("Queued uploads"),UPLOADS_ONLY_GROUP) + { + setIconByName("ktqueuemanager"); + } + + + QueuedUploadsGroup::~QueuedUploadsGroup() + {} +} + +bool kt::QueuedUploadsGroup::isMember(TorrentInterface* tor) +{ + if(!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + + return !s.user_controlled && s.completed; +} diff --git a/apps/ktorrent/groups/queueduploadsgroup.h b/apps/ktorrent/groups/queueduploadsgroup.h new file mode 100644 index 0000000..675da62 --- /dev/null +++ b/apps/ktorrent/groups/queueduploadsgroup.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTQUEUEDUPLOADSGROUP_H +#define KTQUEUEDUPLOADSGROUP_H + +#include <group.h> + +namespace kt +{ + class TorrentInterface; + + /** + * Torrents that are queued and in seeding phase. + * @author Ivan Vasic <ivasic@gmail.com> + */ + class QueuedUploadsGroup : public Group + { + public: + QueuedUploadsGroup(); + virtual ~QueuedUploadsGroup(); + + virtual bool isMember(TorrentInterface* tor); + }; + +} + +#endif diff --git a/apps/ktorrent/groups/torrentdrag.cpp b/apps/ktorrent/groups/torrentdrag.cpp new file mode 100644 index 0000000..fc7b366 --- /dev/null +++ b/apps/ktorrent/groups/torrentdrag.cpp @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <kiconloader.h> +#include <kglobal.h> +#include "torrentdrag.h" + +namespace kt +{ + + TorrentDrag::TorrentDrag(QWidget* src, const char *name) : QStoredDrag("application/x-ktorrent-drag-object",src, name) + { + setPixmap(KGlobal::iconLoader()->loadIcon("player_playlist",KIcon::Small)); + } + + + TorrentDrag::~TorrentDrag() + {} + +} +#include "torrentdrag.moc" diff --git a/apps/ktorrent/groups/torrentdrag.h b/apps/ktorrent/groups/torrentdrag.h new file mode 100644 index 0000000..a926347 --- /dev/null +++ b/apps/ktorrent/groups/torrentdrag.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTTORRENTDRAG_H +#define KTTORRENTDRAG_H + +#include <qdragobject.h> + +namespace kt +{ + + + /** + @author Joris Guisson <joris.guisson@gmail.com> + */ + class TorrentDrag : public QStoredDrag + { + Q_OBJECT + public: + TorrentDrag(QWidget* src,const char *name = 0); + virtual ~TorrentDrag(); + + }; + +} + +#endif diff --git a/apps/ktorrent/groups/torrentgroup.cpp b/apps/ktorrent/groups/torrentgroup.cpp new file mode 100644 index 0000000..efb09a9 --- /dev/null +++ b/apps/ktorrent/groups/torrentgroup.cpp @@ -0,0 +1,147 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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/log.h> +#include <util/error.h> +#include <util/sha1hash.h> +#include <torrent/bencoder.h> +#include <torrent/bnode.h> +#include <interfaces/torrentinterface.h> +#include "torrentgroup.h" + +using namespace bt; + +namespace kt +{ + + TorrentGroup::TorrentGroup(const QString& name): Group(name,MIXED_GROUP|CUSTOM_GROUP) + { + setIconByName("player_playlist"); + } + + + TorrentGroup::~TorrentGroup() + {} + + + bool TorrentGroup::isMember(TorrentInterface* tor) + { + if (torrents.count(tor) > 0) + return true; + + + if (!hashes.empty()) + { + if (hashes.count(tor->getInfoHash())) + { + /* bt::Out(SYS_GEN|LOG_DEBUG) << + QString("TG %1 : Torrent %2 from hashes list").arg(groupName()).arg(tor->getStats().torrent_name) << endl; + */ + hashes.erase(tor->getInfoHash()); + torrents.insert(tor); + return true; + } + } + return false; + } + + void TorrentGroup::add(TorrentInterface* tor) + { + torrents.insert(tor); + } + + void TorrentGroup::remove(TorrentInterface* tor) + { + torrents.erase(tor); + } + + void TorrentGroup::save(bt::BEncoder* enc) + { + enc->beginDict(); + enc->write("name"); enc->write(name.local8Bit()); + enc->write("icon"); enc->write(icon_name.local8Bit()); + enc->write("hashes"); enc->beginList(); + std::set<TorrentInterface*>::iterator i = torrents.begin(); + while (i != torrents.end()) + { + TorrentInterface* tc = *i; + // write the info hash, because that will be unique for each torrent + const bt::SHA1Hash & h = tc->getInfoHash(); + enc->write(h.getData(),20); + i++; + } + std::set<bt::SHA1Hash>::iterator j = hashes.begin(); + while (j != hashes.end()) + { + enc->write(j->getData(),20); + j++; + } + enc->end(); + enc->end(); + } + + void TorrentGroup::load(bt::BDictNode* dn) + { + BValueNode* vn = dn->getValue("name"); + if (!vn || vn->data().getType() != bt::Value::STRING) + throw bt::Error("invalid or missing name"); + + QByteArray tmp = vn->data().toByteArray(); + name = QString::fromLocal8Bit(tmp.data(),tmp.size()); + + vn = dn->getValue("icon"); + if (!vn || vn->data().getType() != bt::Value::STRING) + throw bt::Error("invalid or missing icon"); + + tmp = vn->data().toByteArray(); + setIconByName(QString::fromLocal8Bit(tmp.data(),tmp.size())); + + BListNode* ln = dn->getList("hashes"); + if (!ln) + return; + + for (Uint32 i = 0;i < ln->getNumChildren();i++) + { + vn = ln->getValue(i); + if (!vn || vn->data().getType() != bt::Value::STRING) + continue; + + QByteArray ba = vn->data().toByteArray(); + if (ba.size() != 20) + continue; + + hashes.insert(SHA1Hash((const Uint8*)ba.data())); + } + } + + void TorrentGroup::torrentRemoved(TorrentInterface* tor) + { + torrents.erase(tor); + } + + void TorrentGroup::removeTorrent(TorrentInterface* tor) + { + torrents.erase(tor); + } + + void TorrentGroup::addTorrent(TorrentInterface* tor) + { + torrents.insert(tor); + } +} diff --git a/apps/ktorrent/groups/torrentgroup.h b/apps/ktorrent/groups/torrentgroup.h new file mode 100644 index 0000000..40989fd --- /dev/null +++ b/apps/ktorrent/groups/torrentgroup.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTTORRENTGROUP_H +#define KTTORRENTGROUP_H + +#include <set> +#include <group.h> +#include <util/sha1hash.h> + + +namespace kt +{ + class TorrentInterface; + + /** + @author Joris Guisson <joris.guisson@gmail.com> + */ + class TorrentGroup : public Group + { + std::set<TorrentInterface*> torrents; + std::set<bt::SHA1Hash> hashes; + public: + TorrentGroup(const QString& name); + virtual ~TorrentGroup(); + + virtual bool isMember(TorrentInterface* tor); + virtual void save(bt::BEncoder* enc); + virtual void load(bt::BDictNode* n); + virtual void torrentRemoved(TorrentInterface* tor); + virtual void removeTorrent(TorrentInterface* tor); + virtual void addTorrent(TorrentInterface* tor); + + void add(TorrentInterface* tor); + void remove(TorrentInterface* tor); + }; + +} + +#endif diff --git a/apps/ktorrent/groups/uploadgroup.cpp b/apps/ktorrent/groups/uploadgroup.cpp new file mode 100644 index 0000000..9baca6d --- /dev/null +++ b/apps/ktorrent/groups/uploadgroup.cpp @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <klocale.h> +#include <interfaces/torrentinterface.h> +#include "uploadgroup.h" + +namespace kt +{ + + UploadGroup::UploadGroup() : Group(i18n("Uploads"),UPLOADS_ONLY_GROUP) + { + setIconByName("up"); + } + + + UploadGroup::~UploadGroup() + {} + + + bool UploadGroup::isMember(TorrentInterface* tor) + { + if (!tor) + return false; + + return tor->getStats().completed; + } + +} diff --git a/apps/ktorrent/groups/uploadgroup.h b/apps/ktorrent/groups/uploadgroup.h new file mode 100644 index 0000000..f90a5bd --- /dev/null +++ b/apps/ktorrent/groups/uploadgroup.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTUPLOADGROUP_H +#define KTUPLOADGROUP_H + +#include <group.h> + +namespace kt +{ + + /** + @author Joris Guisson <joris.guisson@gmail.com> + */ + class UploadGroup : public Group + { + public: + UploadGroup(); + virtual ~UploadGroup(); + + virtual bool isMember(TorrentInterface* tor); + + }; + +} + +#endif diff --git a/apps/ktorrent/groups/userdownloadsgroup.cpp b/apps/ktorrent/groups/userdownloadsgroup.cpp new file mode 100644 index 0000000..6a4960b --- /dev/null +++ b/apps/ktorrent/groups/userdownloadsgroup.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "userdownloadsgroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + + UserDownloadsGroup::UserDownloadsGroup() + : Group(i18n("User downloads"),DOWNLOADS_ONLY_GROUP) + { + setIconByName("userconfig"); + } + + + UserDownloadsGroup::~UserDownloadsGroup() + {} +} + +bool kt::UserDownloadsGroup::isMember(TorrentInterface* tor) +{ + if(!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + + return s.user_controlled && !s.completed; +} diff --git a/apps/ktorrent/groups/userdownloadsgroup.h b/apps/ktorrent/groups/userdownloadsgroup.h new file mode 100644 index 0000000..a77e7ac --- /dev/null +++ b/apps/ktorrent/groups/userdownloadsgroup.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTUSERDOWNLOADSGROUP_H +#define KTUSERDOWNLOADSGROUP_H + +#include <group.h> + +namespace kt +{ + class TorrentInterface; + + /** + * Torrents that are user controlled and in downloading phase. + * @author Ivan Vasic <ivasic@gmail.com> + */ + class UserDownloadsGroup : public Group + { + public: + UserDownloadsGroup(); + virtual ~UserDownloadsGroup(); + + virtual bool isMember(TorrentInterface* tor); + }; + +} + +#endif diff --git a/apps/ktorrent/groups/useruploadsgroup.cpp b/apps/ktorrent/groups/useruploadsgroup.cpp new file mode 100644 index 0000000..d0e78bd --- /dev/null +++ b/apps/ktorrent/groups/useruploadsgroup.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "useruploadsgroup.h" + +#include <klocale.h> +#include <interfaces/torrentinterface.h> + +namespace kt +{ + + UserUploadsGroup::UserUploadsGroup() + : Group(i18n("User uploads"),UPLOADS_ONLY_GROUP) + { + setIconByName("userconfig"); + } + + + UserUploadsGroup::~UserUploadsGroup() + {} +} + +bool kt::UserUploadsGroup::isMember(TorrentInterface* tor) +{ + if(!tor) + return false; + + const kt::TorrentStats& s = tor->getStats(); + + return s.user_controlled && s.completed; +} diff --git a/apps/ktorrent/groups/useruploadsgroup.h b/apps/ktorrent/groups/useruploadsgroup.h new file mode 100644 index 0000000..9286c88 --- /dev/null +++ b/apps/ktorrent/groups/useruploadsgroup.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTUSERUPLOADSGROUP_H +#define KTUSERUPLOADSGROUP_H + +#include <group.h> + +namespace kt +{ + class TorrentInterface; + + /** + * Torrents that are user controlled and in seeding phase. + * @author Ivan Vasic <ivasic@gmail.com> + */ + class UserUploadsGroup : public Group + { + public: + UserUploadsGroup(); + virtual ~UserUploadsGroup(); + + virtual bool isMember(TorrentInterface* tor); + }; + +} + +#endif diff --git a/apps/ktorrent/hi128-app-ktorrent.png b/apps/ktorrent/hi128-app-ktorrent.png Binary files differnew file mode 100644 index 0000000..6cb2185 --- /dev/null +++ b/apps/ktorrent/hi128-app-ktorrent.png diff --git a/apps/ktorrent/hi128-mime-torrent.png b/apps/ktorrent/hi128-mime-torrent.png Binary files differnew file mode 100644 index 0000000..a7b8d7d --- /dev/null +++ b/apps/ktorrent/hi128-mime-torrent.png diff --git a/apps/ktorrent/hi16-app-ktorrent.png b/apps/ktorrent/hi16-app-ktorrent.png Binary files differnew file mode 100644 index 0000000..da8aac9 --- /dev/null +++ b/apps/ktorrent/hi16-app-ktorrent.png diff --git a/apps/ktorrent/hi16-mime-torrent.png b/apps/ktorrent/hi16-mime-torrent.png Binary files differnew file mode 100644 index 0000000..f1eceaf --- /dev/null +++ b/apps/ktorrent/hi16-mime-torrent.png diff --git a/apps/ktorrent/hi22-action-ktencrypted.png b/apps/ktorrent/hi22-action-ktencrypted.png Binary files differnew file mode 100644 index 0000000..d3a0020 --- /dev/null +++ b/apps/ktorrent/hi22-action-ktencrypted.png diff --git a/apps/ktorrent/hi22-action-ktremove.png b/apps/ktorrent/hi22-action-ktremove.png Binary files differnew file mode 100644 index 0000000..3da332f --- /dev/null +++ b/apps/ktorrent/hi22-action-ktremove.png diff --git a/apps/ktorrent/hi22-action-ktstart.png b/apps/ktorrent/hi22-action-ktstart.png Binary files differnew file mode 100644 index 0000000..c7995a0 --- /dev/null +++ b/apps/ktorrent/hi22-action-ktstart.png diff --git a/apps/ktorrent/hi22-action-ktstart_all.png b/apps/ktorrent/hi22-action-ktstart_all.png Binary files differnew file mode 100644 index 0000000..1c55069 --- /dev/null +++ b/apps/ktorrent/hi22-action-ktstart_all.png diff --git a/apps/ktorrent/hi22-action-ktstop.png b/apps/ktorrent/hi22-action-ktstop.png Binary files differnew file mode 100644 index 0000000..5b59e46 --- /dev/null +++ b/apps/ktorrent/hi22-action-ktstop.png diff --git a/apps/ktorrent/hi22-action-ktstop_all.png b/apps/ktorrent/hi22-action-ktstop_all.png Binary files differnew file mode 100644 index 0000000..8086b69 --- /dev/null +++ b/apps/ktorrent/hi22-action-ktstop_all.png diff --git a/apps/ktorrent/hi22-app-ktorrent.png b/apps/ktorrent/hi22-app-ktorrent.png Binary files differnew file mode 100644 index 0000000..b0f3804 --- /dev/null +++ b/apps/ktorrent/hi22-app-ktorrent.png diff --git a/apps/ktorrent/hi22-mime-torrent.png b/apps/ktorrent/hi22-mime-torrent.png Binary files differnew file mode 100644 index 0000000..240a3c6 --- /dev/null +++ b/apps/ktorrent/hi22-mime-torrent.png diff --git a/apps/ktorrent/hi32-app-ktorrent.png b/apps/ktorrent/hi32-app-ktorrent.png Binary files differnew file mode 100644 index 0000000..661dc97 --- /dev/null +++ b/apps/ktorrent/hi32-app-ktorrent.png diff --git a/apps/ktorrent/hi32-mime-torrent.png b/apps/ktorrent/hi32-mime-torrent.png Binary files differnew file mode 100644 index 0000000..265c104 --- /dev/null +++ b/apps/ktorrent/hi32-mime-torrent.png diff --git a/apps/ktorrent/hi48-action-ktplugins.png b/apps/ktorrent/hi48-action-ktplugins.png Binary files differnew file mode 100644 index 0000000..ed3ead1 --- /dev/null +++ b/apps/ktorrent/hi48-action-ktplugins.png diff --git a/apps/ktorrent/hi48-app-ktorrent.png b/apps/ktorrent/hi48-app-ktorrent.png Binary files differnew file mode 100644 index 0000000..f35e53e --- /dev/null +++ b/apps/ktorrent/hi48-app-ktorrent.png diff --git a/apps/ktorrent/hi48-mime-torrent.png b/apps/ktorrent/hi48-mime-torrent.png Binary files differnew file mode 100644 index 0000000..e158dfa --- /dev/null +++ b/apps/ktorrent/hi48-mime-torrent.png diff --git a/apps/ktorrent/hi64-action-ktinfowidget.png b/apps/ktorrent/hi64-action-ktinfowidget.png Binary files differnew file mode 100644 index 0000000..1d49e5c --- /dev/null +++ b/apps/ktorrent/hi64-action-ktinfowidget.png diff --git a/apps/ktorrent/hi64-action-ktqueuemanager.png b/apps/ktorrent/hi64-action-ktqueuemanager.png Binary files differnew file mode 100644 index 0000000..d829460 --- /dev/null +++ b/apps/ktorrent/hi64-action-ktqueuemanager.png diff --git a/apps/ktorrent/hi64-action-ktupnp.png b/apps/ktorrent/hi64-action-ktupnp.png Binary files differnew file mode 100644 index 0000000..1adb895 --- /dev/null +++ b/apps/ktorrent/hi64-action-ktupnp.png diff --git a/apps/ktorrent/hi64-app-ktorrent.png b/apps/ktorrent/hi64-app-ktorrent.png Binary files differnew file mode 100644 index 0000000..9d04f33 --- /dev/null +++ b/apps/ktorrent/hi64-app-ktorrent.png diff --git a/apps/ktorrent/hi64-filesys-ktprefdownloads.png b/apps/ktorrent/hi64-filesys-ktprefdownloads.png Binary files differnew file mode 100644 index 0000000..efd92f5 --- /dev/null +++ b/apps/ktorrent/hi64-filesys-ktprefdownloads.png diff --git a/apps/ktorrent/hi64-mime-torrent.png b/apps/ktorrent/hi64-mime-torrent.png Binary files differnew file mode 100644 index 0000000..fb1187e --- /dev/null +++ b/apps/ktorrent/hi64-mime-torrent.png diff --git a/apps/ktorrent/hisc-app-ktorrent.svgz b/apps/ktorrent/hisc-app-ktorrent.svgz Binary files differnew file mode 100644 index 0000000..3d068d8 --- /dev/null +++ b/apps/ktorrent/hisc-app-ktorrent.svgz diff --git a/apps/ktorrent/hisc-mime-torrent.svgz b/apps/ktorrent/hisc-mime-torrent.svgz Binary files differnew file mode 100644 index 0000000..beb7c28 --- /dev/null +++ b/apps/ktorrent/hisc-mime-torrent.svgz diff --git a/apps/ktorrent/ipfilterwidget.cpp b/apps/ktorrent/ipfilterwidget.cpp new file mode 100644 index 0000000..ec32117 --- /dev/null +++ b/apps/ktorrent/ipfilterwidget.cpp @@ -0,0 +1,194 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "ipfilterwidget.h" + +#include <torrent/ipblocklist.h> +#include <torrent/globals.h> +#include <util/log.h> +#include <util/constants.h> + +#include <qstring.h> +#include <qstringlist.h> +#include <qregexp.h> +#include <qvalidator.h> + +#include <klistview.h> +#include <klineedit.h> +#include <ksocketaddress.h> +#include <kfiledialog.h> +#include <klocale.h> +#include <kmessagebox.h> + +#define MAX_RANGES 500 + +using namespace bt; + +IPFilterWidget::IPFilterWidget(QWidget *parent, const char *name) + :BlacklistWidgetBase(parent, name) +{ + IPBlocklist& ipfilter = IPBlocklist::instance(); + QStringList* blocklist = ipfilter.getBlocklist(); + + for (QStringList::Iterator it = blocklist->begin(); it != blocklist->end(); ++it) + { + new KListViewItem(lstPeers, *it); + } + + delete blocklist; +} + +void IPFilterWidget::btnAdd_clicked() +{ + int var=0; + + QRegExp rx("([*]|[0-9]{1,3}).([*]|[0-9]{1,3}).([*]|[0-9]{1,3}).([*]|[0-9]{1,3})"); + QRegExpValidator v( rx,0); + + QString ip = peerIP->text(); + + if(v.validate( ip, var ) == QValidator::Acceptable) + { + if(lstPeers->findItem(ip, 0) == 0) + new KListViewItem(lstPeers, ip); + } + else + KMessageBox::sorry(0, i18n("You must enter IP in format 'XXX.XXX.XXX.XXX'. You can also use wildcards for ranges like '127.0.0.*'.")); +} + +void IPFilterWidget::btnRemove_clicked() +{ + if(lstPeers->currentItem()) + delete lstPeers->currentItem(); +} + +void IPFilterWidget::btnClear_clicked() +{ + lstPeers->clear(); +} + +void IPFilterWidget::btnOpen_clicked() +{ + QString lf = KFileDialog::getOpenFileName(QString::null, "*.txt|",this,i18n("Choose a file")); + + if(lf.isEmpty()) + return; + + btnClear_clicked(); + + loadFilter(lf); +} + +void IPFilterWidget::btnSave_clicked() +{ + QString sf = KFileDialog::getSaveFileName(QString::null,"*.txt|",this,i18n("Choose a filename to save under")); + + if(sf.isEmpty()) + return; + + saveFilter(sf); +} + +void IPFilterWidget::btnOk_clicked() +{ + btnApply_clicked(); + this->accept(); +} + +void IPFilterWidget::btnApply_clicked() +{ + IPBlocklist& ipfilter = IPBlocklist::instance(); + + int count = 0; + + QStringList* peers = new QStringList(); + + QListViewItemIterator it(lstPeers); + while (it.current()) + { + *peers << it.current()->text(0); + ++it; + ++count; + } + + ipfilter.setBlocklist(peers); + + delete peers; + + Out(SYS_IPF|LOG_NOTICE) << "Loaded " << count << " blocked IP ranges." << endl; +} + +void IPFilterWidget::saveFilter(QString& fn) +{ + QFile fptr(fn); + + if (!fptr.open(IO_WriteOnly)) + { + Out(SYS_GEN|LOG_NOTICE) << QString("Could not open file %1 for writing.").arg(fn) << endl; + return; + } + + QTextStream out(&fptr); + + QListViewItemIterator it(lstPeers); + while (it.current()) + { + out << it.current()->text(0) << ::endl; + ++it; + } + + fptr.close(); +} + +void IPFilterWidget::loadFilter(QString& fn) +{ + QFile dat(fn); + dat.open(IO_ReadOnly); + + QTextStream stream( &dat ); + QString line; + + QRegExp rx("([*]|[0-9]{1,3}).([*]|[0-9]{1,3}).([*]|[0-9]{1,3}).([*]|[0-9]{1,3})"); + QRegExpValidator v( rx,0); + + + int i=0; + int var=0; + bool err = false; + + while ( !stream.atEnd() && i < MAX_RANGES ) + { + line = stream.readLine(); + if ( v.validate( line, var ) != QValidator::Acceptable ) + { + err = true; + continue; + } + + new KListViewItem(lstPeers, line); + ++i; + } + + if(err) + Out(SYS_IPF|LOG_NOTICE) << "Some lines could not be loaded. Check your filter file..." << endl; + + dat.close(); +} + +#include "ipfilterwidget.moc" diff --git a/apps/ktorrent/ipfilterwidget.h b/apps/ktorrent/ipfilterwidget.h new file mode 100644 index 0000000..29d5a04 --- /dev/null +++ b/apps/ktorrent/ipfilterwidget.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 IPFILTERWIDGET_H +#define IPFILTERWIDGET_H + +#include "ipfilterwidgetbase.h" + +/** + * @author Ivan Vasic <ivasic@gmail.com> + * @brief Integrated IPFilter GUI class. + * Used to show, add and remove banned peers from blacklist. + */ +class IPFilterWidget: public BlacklistWidgetBase +{ + Q_OBJECT + public: + IPFilterWidget(QWidget *parent = 0, const char *name = 0); + + virtual void btnApply_clicked(); + virtual void btnOk_clicked(); + virtual void btnSave_clicked(); + virtual void btnOpen_clicked(); + virtual void btnClear_clicked(); + virtual void btnRemove_clicked(); + virtual void btnAdd_clicked(); + + void saveFilter(QString& fn); + void loadFilter(QString& fn); +}; + +#endif diff --git a/apps/ktorrent/ipfilterwidgetbase.ui b/apps/ktorrent/ipfilterwidgetbase.ui new file mode 100644 index 0000000..b41fb68 --- /dev/null +++ b/apps/ktorrent/ipfilterwidgetbase.ui @@ -0,0 +1,368 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>BlacklistWidgetBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>BlacklistWidgetBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>490</width> + <height>437</height> + </rect> + </property> + <property name="caption"> + <string>KTorrent Blacklist</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="resizeMode"> + <enum>Minimum</enum> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Note: Blacklist applies to current session only. Use save/open to save your entries or use IPFilter plugin (PeerGuardian).</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Banned Peers</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KListView" row="2" column="0"> + <column> + <property name="text"> + <string>Peer IP address</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>lstPeers</cstring> + </property> + <property name="fullWidth"> + <bool>true</bool> + </property> + </widget> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer5_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Add peer:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>kLineEdit1</cstring> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>peerIP</cstring> + </property> + <property name="text"> + <string>127.0.0.1</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="0" column="1" rowspan="3" colspan="1"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnAdd</cstring> + </property> + <property name="text"> + <string>Add</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="stdItem" stdset="0"> + <number>27</number> + </property> + <property name="toolTip" stdset="0"> + <string>Adds a peer to blacklist</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnRemove</cstring> + </property> + <property name="text"> + <string>Remove</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="stdItem" stdset="0"> + <number>28</number> + </property> + <property name="toolTip" stdset="0"> + <string>Removes selected peer from blacklist</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnClear</cstring> + </property> + <property name="text"> + <string>C&lear</string> + </property> + <property name="stdItem" stdset="0"> + <number>10</number> + </property> + <property name="toolTip" stdset="0"> + <string>Clears this list</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnOpen</cstring> + </property> + <property name="text"> + <string>&Open...</string> + </property> + <property name="stdItem" stdset="0"> + <number>18</number> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnSave</cstring> + </property> + <property name="text"> + <string>Save &As...</string> + </property> + <property name="stdItem" stdset="0"> + <number>8</number> + </property> + <property name="toolTip" stdset="0"> + <string>Save this blacklist to use with KTorrent IPFilter plugin</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>30</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnOk</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="stdItem" stdset="0"> + <number>1</number> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnApply</cstring> + </property> + <property name="text"> + <string>&Apply</string> + </property> + <property name="stdItem" stdset="0"> + <number>9</number> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnCancel</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="stdItem" stdset="0"> + <number>2</number> + </property> + </widget> + </vbox> + </widget> + </grid> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>btnCancel</sender> + <signal>clicked()</signal> + <receiver>BlacklistWidgetBase</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>btnAdd</sender> + <signal>clicked()</signal> + <receiver>BlacklistWidgetBase</receiver> + <slot>btnAdd_clicked()</slot> + </connection> + <connection> + <sender>btnRemove</sender> + <signal>clicked()</signal> + <receiver>BlacklistWidgetBase</receiver> + <slot>btnRemove_clicked()</slot> + </connection> + <connection> + <sender>btnClear</sender> + <signal>clicked()</signal> + <receiver>BlacklistWidgetBase</receiver> + <slot>btnClear_clicked()</slot> + </connection> + <connection> + <sender>btnOpen</sender> + <signal>clicked()</signal> + <receiver>BlacklistWidgetBase</receiver> + <slot>btnOpen_clicked()</slot> + </connection> + <connection> + <sender>btnSave</sender> + <signal>clicked()</signal> + <receiver>BlacklistWidgetBase</receiver> + <slot>btnSave_clicked()</slot> + </connection> + <connection> + <sender>btnOk</sender> + <signal>clicked()</signal> + <receiver>BlacklistWidgetBase</receiver> + <slot>btnOk_clicked()</slot> + </connection> + <connection> + <sender>btnApply</sender> + <signal>clicked()</signal> + <receiver>BlacklistWidgetBase</receiver> + <slot>btnApply_clicked()</slot> + </connection> +</connections> +<tabstops> + <tabstop>btnOk</tabstop> + <tabstop>btnApply</tabstop> + <tabstop>btnCancel</tabstop> + <tabstop>lstPeers</tabstop> + <tabstop>btnRemove</tabstop> + <tabstop>btnClear</tabstop> + <tabstop>btnOpen</tabstop> + <tabstop>btnSave</tabstop> + <tabstop>peerIP</tabstop> + <tabstop>btnAdd</tabstop> +</tabstops> +<slots> + <slot>btnAdd_clicked()</slot> + <slot>btnRemove_clicked()</slot> + <slot>btnClear_clicked()</slot> + <slot>btnOpen_clicked()</slot> + <slot>btnSave_clicked()</slot> + <slot>btnOk_clicked()</slot> + <slot>btnApply_clicked()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klistview.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/ktorrent.cpp b/apps/ktorrent/ktorrent.cpp new file mode 100644 index 0000000..50b6e7f --- /dev/null +++ b/apps/ktorrent/ktorrent.cpp @@ -0,0 +1,1017 @@ +/*************************************************************************** + * Copyright (C) 2005 by * + * Joris Guisson <joris.guisson@gmail.com> * + * Ivan Vasic <ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <qdragobject.h> +#include <qsplitter.h> +#include <qvbox.h> +#include <qlabel.h> +#include <qtooltip.h> +#include <qtoolbutton.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kiconloader.h> +#include <kdeversion.h> +#include <kmenubar.h> +#include <kstatusbar.h> +#include <kkeydialog.h> +#include <kaccel.h> +#include <kstandarddirs.h> +#include <kio/netaccess.h> +#include <kfiledialog.h> +#include <kconfig.h> +#include <kurl.h> +#include <kurldrag.h> +#include <kprogress.h> +#include <kpopupmenu.h> +#include <ktabwidget.h> +#include <kedittoolbar.h> +#include <ksqueezedtextlabel.h> +#include <kpushbutton.h> + +#include <kstdaccel.h> +#include <kaction.h> +#include <kstdaction.h> + +#include <interfaces/torrentinterface.h> +#include <torrent/peermanager.h> +#include <torrent/chunkmanager.h> +#include <torrent/uploadcap.h> +#include <torrent/downloadcap.h> +#include <util/error.h> +#include <torrent/serverauthenticate.h> +#include <torrent/globals.h> +#include <torrent/tracker.h> +#include <torrent/downloader.h> +#include <torrent/choker.h> +#include <torrent/server.h> +#include <torrent/downloadcap.h> +#include <torrent/udptrackersocket.h> +#include <net/socketmonitor.h> +#include <util/log.h> +#include <util/fileops.h> +#include <kademlia/dhtbase.h> + +#include "ktorrentcore.h" +#include "ktorrentview.h" +#include "ktorrent.h" +#include "pref.h" +#include "settings.h" +#include "trayicon.h" +#include "ktorrentdcop.h" +#include "torrentcreatordlg.h" +#include "pastedialog.h" +#include "queuedialog.h" +#include "ipfilterwidget.h" +#include <util/functions.h> +#include <interfaces/functions.h> +#include <interfaces/plugin.h> +#include <interfaces/prefpageinterface.h> +#include <newui/dtabwidget.h> +#include <pluginmanager.h> +#include <groups/group.h> +#include <groups/groupview.h> +#include <groups/groupmanager.h> +#include <mse/streamsocket.h> +#include "viewmanager.h" +#include "ktorrentviewitem.h" + + + +namespace kt +{ + QString DataDir(); +} + +#include <util/profiler.h> + + + +using namespace bt; +using namespace kt; + +KTorrent::KTorrent() + : DMainWindow(0,"KTorrent"),m_group_view(0), + m_view_man(0), m_systray_icon(0),m_status_prog(0) +{ + setHidden(true); + //setToolviewStyle(KMdi::TextAndIcon); + connect(this,SIGNAL(widgetChanged(QWidget*)),this,SLOT(currentTabChanged(QWidget*))); + + m_view_man = new ViewManager(this); + m_group_view = new kt::GroupView(m_view_man,actionCollection()); + connect(m_group_view,SIGNAL(openNewTab(kt::Group*)),this,SLOT(openView(kt::Group*))); + + + m_pref = new KTorrentPreferences(*this); + + m_core = new KTorrentCore(this); + m_core->setGroupManager(m_group_view->groupManager()); + + m_systray_icon = new TrayIcon(m_core, this); + + m_group_view->loadGroups(); + m_view_man->restoreViewState(KGlobal::config(),this); + + QToolButton* tb = new QToolButton(m_activeTabWidget); + tb->setIconSet(SmallIcon("tab_new")); + tb->adjustSize(); + connect(tb,SIGNAL(clicked()),this,SLOT(openDefaultView())); + m_activeTabWidget->setCornerWidget(tb, TopLeft); + + connect(m_group_view,SIGNAL(currentGroupChanged( kt::Group* )), + this,SLOT(groupChanged(kt::Group*))); + + connect(m_group_view,SIGNAL(groupRenamed(kt::Group*)), + this,SLOT(groupRenamed(kt::Group*))); + + connect(m_group_view,SIGNAL(groupRemoved(kt::Group*)), + this,SLOT(groupRemoved(kt::Group*))); + + connect(m_core,SIGNAL(torrentAdded(kt::TorrentInterface* )), + m_view_man,SLOT(addTorrent(kt::TorrentInterface* ))); + + connect(m_core,SIGNAL(torrentRemoved(kt::TorrentInterface* )), + m_view_man,SLOT(removeTorrent(kt::TorrentInterface* ))); + + connect(m_core, SIGNAL(torrentRemoved( kt::TorrentInterface* )), + m_group_view, SLOT(onTorrentRemoved( kt::TorrentInterface* ))); + + m_statusInfo = new KSqueezedTextLabel(this); + m_statusSpeed = new QLabel(this); + m_statusTransfer = new QLabel(this); + m_statusDHT = new QLabel(this); + m_statusFirewall = new QLabel(this); + m_statusFirewall->setPixmap(SmallIcon("messagebox_warning")); + QToolTip::add(m_statusFirewall,i18n("No incoming connections (possibly firewalled)")); + + statusBar()->addWidget(m_statusFirewall); + statusBar()->addWidget(m_statusInfo,1); + statusBar()->addWidget(m_statusDHT); + statusBar()->addWidget(m_statusSpeed); + statusBar()->addWidget(m_statusTransfer); + + m_statusFirewall->hide(); + + setupActions(); + currentTorrentChanged(0); + + m_dcop = new KTorrentDCOP(this); + + setStandardToolBarMenuEnabled(true); + + QToolTip::add(m_statusInfo, i18n("Info")); + QToolTip::add(m_statusTransfer, i18n("Data transferred during the current session")); + QToolTip::add(m_statusSpeed, i18n("Current speed of all torrents combined")); + + //first apply settings.. + applySettings(false); + //then load stuff from core + m_core->loadTorrents(); + m_core->loadPlugins(); + + connect(&m_gui_update_timer, SIGNAL(timeout()), this, SLOT(updatedStats())); + //Apply GUI update interval + int val = 500; + switch(Settings::guiUpdateInterval()) + { + case 1: + val = 1000; + break; + case 2: + val = 2000; + break; + case 3: + val = 5000; + break; + default: + val = 500; + } + m_gui_update_timer.start(val); + + statusBar()->show(); + + addToolWidget(m_group_view,"player_playlist",i18n("Groups"),DOCK_LEFT); + + setAutoSaveSettings("WindowStatus",true); + KGlobal::config()->setGroup("WindowStatus"); + bool hidden_on_exit = KGlobal::config()->readBoolEntry("hidden_on_exit",false); + if (Settings::showSystemTrayIcon()) + { + if (hidden_on_exit) + { + Out(SYS_GEN|LOG_DEBUG) << "Starting minimized" << endl; + hide(); + } + else + { + show(); + } + } + else + { + show(); + } + + bool menubar_hidden = KGlobal::config()->readBoolEntry("menubar_hidden",false); + menuBar()->setHidden(menubar_hidden); + m_menubarAction->setChecked(!menubar_hidden); + + bool statusbar_hidden = KGlobal::config()->readBoolEntry("statusbar_hidden",false); + statusBar()->setHidden(statusbar_hidden); + m_statusbarAction->setChecked(!statusbar_hidden); + + MaximizeLimits(); + connect(&m_status_msg_expire,SIGNAL(timeout()),this,SLOT(statusBarMsgExpired())); + + m_view_man->updateActions(); +} + +KTorrent::~KTorrent() +{ + delete m_dcop; + delete m_core; + delete m_pref; + delete m_statusInfo; + delete m_statusTransfer; + delete m_statusSpeed; + delete m_statusFirewall; +} + +void KTorrent::openView(kt::Group* g) +{ + if (!g) + return; + + KTorrentView* v = m_view_man->newView(); + v->setCurrentGroup((Group*)g); + v->setupViewColumns(); + + addTabPage(v,g->groupIcon(),v->caption(),m_view_man); + + connect(v,SIGNAL(currentChanged(kt::TorrentInterface* )), + this,SLOT(currentTorrentChanged(kt::TorrentInterface* ))); + + connect(v,SIGNAL(wantToRemove(kt::TorrentInterface*,bool )), + m_core,SLOT(remove(kt::TorrentInterface*,bool ))); + + connect(v->listView(),SIGNAL(dropped(QDropEvent*,QListViewItem*)), + this,SLOT(urlDropped(QDropEvent*,QListViewItem*))); + + connect(v,SIGNAL(wantToStart( kt::TorrentInterface* )), + m_core,SLOT(start( kt::TorrentInterface* ))); + + connect(v,SIGNAL(wantToStop( kt::TorrentInterface*, bool )), + m_core,SLOT(stop( kt::TorrentInterface*, bool ))); + + connect(v,SIGNAL(needsDataCheck( kt::TorrentInterface* )), + m_core,SLOT(doDataCheck( kt::TorrentInterface* ))); + + connect(v,SIGNAL(updateActions( int )), + this,SLOT(onUpdateActions( int ))); + + //connect Core queue() with queue() from KTView. + connect(v, SIGNAL(queue( kt::TorrentInterface* )), + m_core, SLOT(queue( kt::TorrentInterface* ))); + + connect(v,SIGNAL(updateGroupsSubMenu(KPopupMenu*)), + m_group_view,SLOT(updateGroupsSubMenu(KPopupMenu*))); + + connect(v,SIGNAL(groupsSubMenuItemActivated(KTorrentView*, const QString&)), + m_group_view,SLOT(onGroupsSubMenuItemActivated(KTorrentView*, const QString&))); + + if (m_core) + { + QueueManager* qman = m_core->getQueueManager(); + QueueManager::iterator i = qman->begin(); + while (i != qman->end()) + { + v->addTorrent(*i); + i++; + } + } +} + +void KTorrent::openView(const QString & group_name) +{ + const kt::Group* g = m_group_view->findGroup(group_name); + if (g) + openView((kt::Group*)g); +} + +void KTorrent::groupChanged(kt::Group* g) +{ + KTorrentView* v = m_view_man->getCurrentView(); + if (v) + { + m_activeTabWidget->changeTab(v,g->groupName()); + v->setIcon(g->groupIcon()); + v->setCurrentGroup(g); + } +} + +void KTorrent::groupRenamed(kt::Group* g) +{ + m_view_man->groupRenamed(g,m_activeTabWidget); +} + +void KTorrent::groupRemoved(kt::Group* g) +{ + kt::Group* allg = m_group_view->groupManager()->allGroup(); + m_view_man->groupRemoved(g,m_activeTabWidget,this,allg); +} + +void KTorrent::addTabPage(QWidget* page,const QIconSet & icon, + const QString & caption,kt::CloseTabListener* ctl) +{ + addWidget(page,caption); + page->setIcon(icon.pixmap(QIconSet::Small,QIconSet::Active)); + m_tab_map[page] = ctl; + currentTabChanged(page); +} + +void KTorrent::addTabPage(QWidget* page,const QPixmap & icon, + const QString & caption,kt::CloseTabListener* ctl) +{ + addWidget(page,caption); + page->setIcon(icon); + m_tab_map[page] = ctl; + currentTabChanged(page); +} + + +void KTorrent::removeTabPage(QWidget* page) +{ + if (!m_tab_map.contains(page)) + return; + + m_tab_map.erase(page); + page->reparent(0,QPoint()); + removeWidget(page); +} + +void KTorrent::addPrefPage(PrefPageInterface* page) +{ + m_pref->addPrefPage(page); +} + +void KTorrent::removePrefPage(PrefPageInterface* page) +{ + m_pref->removePrefPage(page); +} + +void KTorrent::applySettings(bool change_port) +{ + m_core->setMaxDownloads(Settings::maxDownloads()); + m_core->setMaxSeeds(Settings::maxSeeds()); + PeerManager::setMaxConnections(Settings::maxConnections()); + PeerManager::setMaxTotalConnections(Settings::maxTotalConnections()); + net::SocketMonitor::setDownloadCap(Settings::maxDownloadRate()*1024); + net::SocketMonitor::setUploadCap(Settings::maxUploadRate()*1024); + net::SocketMonitor::setSleepTime(Settings::cpuUsage()); + m_core->setKeepSeeding(Settings::keepSeeding()); + mse::StreamSocket::setTOS(Settings::dSCP() << 2); + mse::StreamSocket::setMaxConnecting(Settings::maxConnectingSockets()); + if (Settings::allwaysDoUploadDataCheck()) + ChunkManager::setMaxChunkSizeForDataCheck(0); + else + ChunkManager::setMaxChunkSizeForDataCheck(Settings::maxSizeForUploadDataCheck() * 1024); + + if (Settings::showSystemTrayIcon()) + { + m_systray_icon->show(); + m_set_max_upload_rate->update(); + m_set_max_download_rate->update(); + } + else + { + m_systray_icon->hide(); + } + + m_core->changeDataDir(Settings::tempDir()); + UDPTrackerSocket::setPort(Settings::udpTrackerPort()); + if (change_port) + m_core->changePort(Settings::port()); + + if (Settings::useExternalIP()) + Tracker::setCustomIP(Settings::externalIP()); + else + Tracker::setCustomIP(QString::null); + + Downloader::setMemoryUsage(Settings::memoryUsage()); + Choker::setNumUploadSlots(Settings::numUploadSlots()); + + //Apply GUI update interval + int val = 500; + switch(Settings::guiUpdateInterval()) + { + case 1: + val = 1000; + break; + case 2: + val = 2000; + break; + case 3: + val = 5000; + break; + default: + val = 500; + } + m_gui_update_timer.changeInterval(val); + + //update QM + m_core->getQueueManager()->orderQueue(); + dht::DHTBase & ht = Globals::instance().getDHT(); + if (Settings::dhtSupport() && !ht.isRunning()) + { + ht.start(kt::DataDir() + "dht_table",kt::DataDir() + "dht_key",Settings::dhtPort()); + } + else if (!Settings::dhtSupport() && ht.isRunning()) + { + ht.stop(); + } + else if (Settings::dhtSupport() && ht.getPort() != Settings::dhtPort()) + { + Out(SYS_GEN|LOG_NOTICE) << "Restarting DHT with new port " << Settings::dhtPort() << endl; + ht.stop(); + ht.start(kt::DataDir() + "dht_table",kt::DataDir() + "dht_key",Settings::dhtPort()); + } + + if (Settings::useEncryption()) + { + Globals::instance().getServer().enableEncryption(Settings::allowUnencryptedConnections()); + } + else + { + Globals::instance().getServer().disableEncryption(); + } +} + +void KTorrent::load(const KURL& url) +{ + m_core->load(url); +} + +void KTorrent::loadSilently(const KURL& url) +{ + m_core->loadSilently(url); +} + +void KTorrent::onUpdateActions(int flags) +{ + m_start->setEnabled(flags & KTorrentView::START); + m_stop->setEnabled(flags & KTorrentView::STOP); + m_remove->setEnabled(flags & KTorrentView::REMOVE); + m_queueaction->setEnabled(flags & KTorrentView::REMOVE); + m_datacheck->setEnabled(flags & KTorrentView::SCAN); + m_startall->setEnabled(flags & KTorrentView::START_ALL); + m_stopall->setEnabled(flags & KTorrentView::STOP_ALL); +} + +void KTorrent::currentTorrentChanged(kt::TorrentInterface* tc) +{ + notifyViewListeners(tc); +} + + +void KTorrent::setupActions() +{ + KStdAction::openNew(this,SLOT(fileNew()),actionCollection()); + KStdAction::open(this, SLOT(fileOpen()), actionCollection()); + KStdAction::quit(kapp, SLOT(quit()), actionCollection()); + + KStdAction::paste(kapp,SLOT(paste()),actionCollection()); + + m_statusbarAction = KStdAction::showStatusbar(this, SLOT(optionsShowStatusbar()), actionCollection()); + m_menubarAction = KStdAction::showMenubar(this, SLOT(optionsShowMenubar()), actionCollection()); + + KStdAction::keyBindings(this, SLOT(optionsConfigureKeys()), actionCollection()); + KStdAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), actionCollection()); + + KAction* pref = KStdAction::preferences(this, SLOT(optionsPreferences()), actionCollection()); + + m_start = new KAction( + i18n("to start", "Start"), "ktstart",0,this, SLOT(startDownload()), + actionCollection(), "Start"); + + m_stop = new KAction( + i18n("to stop", "Stop"), "ktstop",0,this, SLOT(stopDownload()), + actionCollection(), "Stop"); + + m_remove = new KAction( + i18n("Remove"), "ktremove",0,this, SLOT(removeDownload()), + actionCollection(), "Remove"); + + m_startall = new KAction( + i18n("to start all", "Start All"), "ktstart_all",0,this, SLOT(startAllDownloadsCurrentView()), + actionCollection(), "Start all"); + + m_startall_systray = new KAction(i18n("to start all", "Start All"), "ktstart_all",0,this, SLOT(startAllDownloads()),actionCollection()); + + m_stopall = new KAction( + i18n("to stop all", "Stop All"), "ktstop_all",0,this, SLOT(stopAllDownloadsCurrentView()), + actionCollection(), "Stop all"); + + m_stopall_systray = new KAction(i18n("to stop all", "Stop All"), "ktstop_all",0,this, SLOT(stopAllDownloads()),actionCollection()); + + m_pasteurl = new KAction( + i18n("to paste torrent URL", "Paste Torrent URL..."), "ktstart",0,this, SLOT(torrentPaste()), + actionCollection(), "paste_url"); + + m_queuemgr = new KAction( + i18n("to open Queue Manager", "Open Queue Manager..."), + "ktqueuemanager", 0, this, SLOT(queueManagerShow()), + actionCollection(), "Queue manager"); + + m_queueaction = new KAction( + i18n("Enqueue/Dequeue"), + "player_playlist", 0, m_view_man, SLOT(queueAction()), + actionCollection(), "queue_action"); + + m_ipfilter = new KAction( + i18n("IPFilter"), + "filter", 0, this, SLOT(showIPFilter()), + actionCollection(), "ipfilter_action"); + + m_datacheck = new KAction( + i18n("Check Data Integrity"), + QString::null,0,m_view_man,SLOT(checkDataIntegrity()),actionCollection(),"check_data"); + + m_find = KStdAction::find(this,SLOT(find()),actionCollection()); + + //Plug actions to systemtray context menu + m_startall_systray->plug(m_systray_icon->contextMenu()); + m_stopall_systray->plug(m_systray_icon->contextMenu()); + m_systray_icon->contextMenu()->insertSeparator(); + m_pasteurl->plug(m_systray_icon->contextMenu()); + m_systray_icon->contextMenu()->insertSeparator(); + + m_set_max_upload_rate = new SetMaxRate(m_core, 0, this); + m_systray_icon->contextMenu()->insertItem(i18n("Set max upload rate"),m_set_max_upload_rate); + + m_set_max_download_rate = new SetMaxRate(m_core, 1, this); + m_systray_icon->contextMenu()->insertItem(i18n("Set max download rate"),m_set_max_download_rate); + + pref->plug(m_systray_icon->contextMenu()); + + createGUI(0); +} + + + +bool KTorrent::queryClose() +{ + if (Settings::showSystemTrayIcon() && !KApplication::kApplication()->sessionSaving()) + { + hide(); + return false; + } + else + { + return true; + } +} + +bool KTorrent::queryExit() +{ + // stop timers to prevent update + m_gui_update_timer.stop(); + + KGlobal::config()->setGroup("WindowStatus"); + KGlobal::config()->writeEntry("hidden_on_exit",this->isHidden()); + KGlobal::config()->writeEntry("menubar_hidden",menuBar()->isHidden()); + KGlobal::config()->writeEntry("statusbar_hidden",statusBar()->isHidden()); + m_view_man->saveViewState(KGlobal::config()); + saveSettings(); + hide(); + m_systray_icon->hide(); // hide system tray icon upon exit + m_core->onExit(); + if (Globals::instance().getDHT().isRunning()) + Globals::instance().getDHT().stop(); + return true; +} + + +void KTorrent::fileNew() +{ + TorrentCreatorDlg dlg(m_core,this); + + dlg.show(); + dlg.exec(); +} + +void KTorrent::fileOpen() +{ + QString filter = "*.torrent|" + i18n("Torrent Files") + "\n*|" + i18n("All Files"); + KURL url = KFileDialog::getOpenURL(QString::null, filter, this, i18n("Open Location")); + + if (url.isValid()) + load(url); +} + +void KTorrent::torrentPaste() +{ + PasteDialog dlg(m_core,this); + dlg.exec(); +} + +void KTorrent::queueManagerShow() +{ + QueueDialog dlg(m_core->getQueueManager(), this); + dlg.exec(); +} + +void KTorrent::startDownload() +{ + m_view_man->startDownloads(); + TorrentInterface* tc = m_view_man->getCurrentTC(); + currentTorrentChanged(tc); +} + +void KTorrent::startAllDownloadsCurrentView() +{ + m_view_man->startAllDownloads(); +} + +void KTorrent::startAllDownloads() +{ + m_core->startAll(3); +} + +void KTorrent::stopDownload() +{ + m_view_man->stopDownloads(); + TorrentInterface* tc = m_view_man->getCurrentTC(); + currentTorrentChanged(tc); +} + +void KTorrent::stopAllDownloads() +{ + m_core->stopAll(3); +} + +void KTorrent::stopAllDownloadsCurrentView() +{ + m_view_man->stopAllDownloads(); +} + +void KTorrent::removeDownload() +{ + m_view_man->removeDownloads(); + currentTorrentChanged(m_view_man->getCurrentTC()); +} + +void KTorrent::optionsShowStatusbar() +{ + // this is all very cut and paste code for showing/hiding the + // statusbar + if (m_statusbarAction->isChecked()) + statusBar()->show(); + else + statusBar()->hide(); +} + +void KTorrent::optionsShowMenubar() +{ + // this is all very cut and paste code for showing/hiding the + // menubar + if (m_menubarAction->isChecked()) + menuBar()->show(); + else + menuBar()->hide(); +} + +void KTorrent::optionsConfigureKeys() +{ + KKeyDialog::configure(actionCollection()); +} + +void KTorrent::optionsConfigureToolbars() +{ + // use the standard toolbar editor +#if defined(KDE_MAKE_VERSION) +# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,0) + saveMainWindowSettings(KGlobal::config(), autoSaveGroup()); +# else + saveMainWindowSettings(KGlobal::config()); +# endif +#else + saveMainWindowSettings(KGlobal::config()); +#endif + KEditToolbar dlg(factory()); + connect(&dlg,SIGNAL(newToolbarConfig()),this,SLOT(newToolbarConfig())); + dlg.exec(); +} + +void KTorrent::newToolbarConfig() +{ + // this slot is called when user clicks "Ok" or "Apply" in the toolbar editor. + // recreate our GUI, and re-apply the settings (e.g. "text under icons", etc.) + createGUI(0); + +#if defined(KDE_MAKE_VERSION) +# if KDE_VERSION >= KDE_MAKE_VERSION(3,1,0) + applyMainWindowSettings(KGlobal::config(), autoSaveGroup()); +# else + applyMainWindowSettings(KGlobal::config()); +# endif +#else + applyMainWindowSettings(KGlobal::config()); +#endif +} + +void KTorrent::optionsPreferences() +{ + // popup some sort of preference dialog, here + m_pref->updateData(); + m_pref->exec(); +} + +void KTorrent::changeStatusbar(const QString& text) +{ + // display the text on the statusbar + //statusBar()->message(text); + m_statusInfo->setText(text); + m_status_msg_expire.stop(); + m_status_msg_expire.start(5000,true); +} + +void KTorrent::changeCaption(const QString& text) +{ + // display the text on the caption + setCaption(text); +} + +void KTorrent::saveProperties(KConfig* ) +{ +} + +void KTorrent::readProperties(KConfig*) +{ +} + +void KTorrent::urlDropped(QDropEvent* event,QListViewItem*) +{ + KURL::List urls; + + if (KURLDrag::decode(event, urls) && !urls.isEmpty()) + { + for (KURL::List::iterator i = urls.begin();i != urls.end();i++) + load(*i); + } +} + +void KTorrent::updatedStats() +{ + m_startall_systray->setEnabled(m_core->getNumTorrentsNotRunning() > 0); + m_stopall_systray->setEnabled(m_core->getNumTorrentsRunning() > 0); + + CurrentStats stats = this->m_core->getStats(); + + //m_statusInfo->setText(i18n("Some info here e.g. connected/disconnected")); + QString tmp = i18n("Speed down: %1 / up: %2") + .arg(KBytesPerSecToString((double)stats.download_speed/1024.0)) + .arg(KBytesPerSecToString((double)stats.upload_speed/1024.0)); + + m_statusSpeed->setText(tmp); + + QString tmp1 = i18n("Transferred down: %1 / up: %2") + .arg(BytesToString(stats.bytes_downloaded)) + .arg(BytesToString(stats.bytes_uploaded)); + m_statusTransfer->setText(tmp1); + + if (ServerAuthenticate::isFirewalled() && m_core->getNumTorrentsRunning() > 0) + m_statusFirewall->show(); + else + m_statusFirewall->hide(); + + m_view_man->update(); + + m_systray_icon->updateStats(stats,Settings::showSpeedBarInTrayIcon(),Settings::downloadBandwidth(), Settings::uploadBandwidth()); + + m_core->getPluginManager().updateGuiPlugins(); + + + if (Globals::instance().getDHT().isRunning()) + { + const dht::Stats & s = Globals::instance().getDHT().getStats(); + m_statusDHT->setText(i18n("DHT: %1 nodes, %2 tasks") + .arg(s.num_peers).arg(s.num_tasks)); + } + else + m_statusDHT->setText(i18n("DHT: off")); +} + +void KTorrent::mergePluginGui(Plugin* p) +{ + if (!p) return; + guiFactory()->addClient(p); +} + +void KTorrent::removePluginGui(Plugin* p) +{ + if (!p) return; + guiFactory()->removeClient(p); +} + +void KTorrent::addWidgetInView(QWidget* w,Position pos) +{ +} + +void KTorrent::removeWidgetFromView(QWidget* w) +{ +} + +void KTorrent::addWidgetBelowView(QWidget* w,const QString & icon,const QString & caption) +{ + addToolWidget(w,icon,caption,DOCK_BOTTOM); +} + +void KTorrent::removeWidgetBelowView(QWidget* w) +{ + removeToolWidget(w); +} + +void KTorrent::addToolWidget(QWidget* w,const QString & icon,const QString & caption,ToolDock dock) +{ + if (!w) return; + + + if (!icon.isNull()) + w->setIcon(KGlobal::iconLoader()->loadIcon(icon,KIcon::Small)); + + switch (dock) + { + case DOCK_BOTTOM: + addDockWidget(DDockWindow::Bottom,w,caption); + break; + + case DOCK_LEFT: + addDockWidget(DDockWindow::Left,w,caption); + break; + + case DOCK_RIGHT: + default: + addDockWidget(DDockWindow::Right,w,caption); + break; + } +} + +void KTorrent::removeToolWidget(QWidget* w) +{ + if (!w) return; + + removeDockWidget(w); + w->reparent(0,QPoint()); +} + +const TorrentInterface* KTorrent::getCurrentTorrent() const +{ + return m_view_man->getCurrentTC(); +} + +QString KTorrent::getStatusInfo() +{ + return m_statusInfo->text(); +} + +QString KTorrent::getStatusTransfer() +{ + return m_statusTransfer->text(); +} + +QString KTorrent::getStatusSpeed() +{ + return m_statusSpeed->text(); +} + +QString KTorrent::getStatusDHT() +{ + return m_statusDHT->text(); +} + +QString KTorrent::getStatusFirewall() +{ + return m_statusFirewall->text(); +} + +QCStringList KTorrent::getTorrentInfo(kt::TorrentInterface* tc) +{ + return KTorrentViewItem::getTorrentInfo(tc); +} + +void KTorrent::showIPFilter() +{ + IPFilterWidget ipf(this); + ipf.exec(); +} + + +void KTorrent::closeTab() +{ + QWidget* w = m_currentWidget; + if (!w) + return; + + CloseTabListener* ctl = m_tab_map[w]; + if (ctl) + { + ctl->tabCloseRequest(this,w); + currentTabChanged(m_activeTabWidget->currentPage()); + } +} + +void KTorrent::currentTabChanged(QWidget* w) +{ + m_view_man->onCurrentTabChanged(w); + currentTorrentChanged(m_view_man->getCurrentTC()); + if (!m_activeTabWidget || !w) + return; + + bool close_allowed = false; + CloseTabListener* ctl = m_tab_map[w]; + if (ctl) + close_allowed = ctl->closeAllowed(w); + + m_activeTabWidget->closeButton()->setEnabled(close_allowed); +} + +void KTorrent::openDefaultView() +{ + openView(i18n("All Torrents")); +} + +KToolBar* KTorrent::addToolBar(const char* name) +{ + return toolBar(name); +} + +void KTorrent::removeToolBar(KToolBar* tb) +{ + delete tb; +} + +void KTorrent::loadSilentlyDir(const KURL& url, const KURL& savedir) +{ + m_core->loadSilentlyDir(url, savedir); +} + +KProgress* KTorrent::addProgressBarToStatusBar() +{ + if (m_status_prog) + return 0; + + KStatusBar* sb = statusBar(); + m_status_prog = new KProgress(100,sb); + m_status_prog->setValue(0); + sb->addWidget(m_status_prog); + m_status_prog->show(); + return m_status_prog; +} + +void KTorrent::removeProgressBarFromStatusBar(KProgress* p) +{ + if (m_status_prog != p) + return; + + KStatusBar* sb = statusBar(); + sb->removeWidget(p); + delete p; + m_status_prog = 0; +} + +void KTorrent::statusBarMsgExpired() +{ + m_statusInfo->clear(); +} + +void KTorrent::find() +{ + KTorrentView* v = m_view_man->getCurrentView(); + if (v) + v->toggleFilterBar(); +} + +#include "ktorrent.moc" + diff --git a/apps/ktorrent/ktorrent.desktop b/apps/ktorrent/ktorrent.desktop new file mode 100644 index 0000000..ba48aae --- /dev/null +++ b/apps/ktorrent/ktorrent.desktop @@ -0,0 +1,85 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=KTorrent +Name[sv]=Ktorrent +Name[xx]=xxKTorrentxx +GenericName=BitTorrent Client +GenericName[ar]=زبون BitTorrent +GenericName[bg]=Бит Торент клиент +GenericName[br]=Kliant BitTorrent +GenericName[ca]=Client de BitTorrent +GenericName[cs]=BitTorrent klient +GenericName[da]=BitTorrent klient +GenericName[de]=BitTorrent-Programm +GenericName[el]=Πελάτης BitTorrent +GenericName[es]=Cliente de BitTorrent +GenericName[et]=BitTorrenti klient +GenericName[fa]=کارخواه BitTorrent +GenericName[fr]=Client BitTorrent +GenericName[gl]=Cliente BitTorrent +GenericName[it]=Client BitTorrent +GenericName[ja]=BitTorrent クライアント +GenericName[ka]=BitTorrent-ის კლიენტი +GenericName[lt]=BitTorrent klientas +GenericName[ms]=Klien BitTorrent +GenericName[nb]=BitTorrent-klient +GenericName[nds]=Bittorrent-Programm +GenericName[nl]=BitTorrent-cliënt +GenericName[pa]=BitTorrent ਕਲਾਂਇਟ +GenericName[pl]=Klient BitTorrenta +GenericName[pt]=Cliente de BitTorrent +GenericName[pt_BR]=Cliente BitTorrent +GenericName[ru]=Клиент BitTorrent +GenericName[sk]=BitTorrent Klient +GenericName[sr]=BitTorrent клијент +GenericName[sr@Latn]=BitTorrent klijent +GenericName[sv]=BitTorrent-klient +GenericName[tr]=BitTorrent İstemcisi +GenericName[uk]=Клієнт BitTorrent +GenericName[xx]=xxBitTorrent Clientxx +GenericName[zh_CN]=BitTorrent 客户端 +GenericName[zh_TW]=BitTorrent 客戶端程式 +Exec=ktorrent %i %m -caption "%c" %u +Icon=ktorrent +Type=Application +DocPath=ktorrent/index.html +MimeType=application/x-bittorrent;application/x-torrent; +X-DCOP-ServiceType=Unique +Comment=A BitTorrent program for KDE +Comment[ar]=برنامِج BitTorrent لِــ KDE +Comment[bg]=Бит Торент клиент за KDE +Comment[br]=Ur programm BitTorrent evit KDE +Comment[ca]=Un programa de BitTorrent per KDE +Comment[cs]=BitTorrent pro KDE +Comment[da]=Et BitTorrent program for KDE +Comment[de]=Ein BitTorrent-Programm für KDE +Comment[el]=Μία εφαρμογή BitTorrent για το KDE +Comment[es]=Un programa de BitTorrent para KDE +Comment[et]=KDE BitTorrenti rakendus +Comment[fa]=یک برنامۀ BitTorrent برای KDE +Comment[fr]=Un programme BitTorrent pour KDE +Comment[gl]=Programa de BitTorrent para KDE +Comment[it]=Un programma BitTorrent per KDE +Comment[ja]=KDE のための BitTorrent プログラム +Comment[ka]=BitTorrent-ის პროგრამა KDE-თვის +Comment[lt]=BitTorrent programa skirta KDE aplinkai +Comment[ms]=Program BitTorrent untuk KDE +Comment[nb]=Et BitTorrent-program for KDE +Comment[nds]=En Bittorrent-Programm för KDE +Comment[nl]=Een BitTorrent-programma voor KDE +Comment[pa]=KDE ਲਈ BitTorrent ਕਾਰਜ +Comment[pl]=Program BitTorrent dla KDE +Comment[pt]=Um programa de BitTorrent para o KDE +Comment[pt_BR]=Um programa BitTorrent para o KDE +Comment[ru]=Клиент BitTorrent для KDE +Comment[sk]=BitTorrent klient pre KDE +Comment[sr]=BitTorrent програм за KDE +Comment[sr@Latn]=BitTorrent program za KDE +Comment[sv]=Ett BitTorrent-program för KDE +Comment[tr]=KDE için BitTorrent uygulaması +Comment[uk]=Програма BitTorrent для KDE +Comment[xx]=xxA BitTorrent program for KDExx +Comment[zh_CN]=一个 KDE 的 BitTorrent 程序 +Comment[zh_TW]=KDE 的 BitTorrent 程式 +Terminal=false +Categories=Qt;KDE;Network;FileTransfer; diff --git a/apps/ktorrent/ktorrent.h b/apps/ktorrent/ktorrent.h new file mode 100644 index 0000000..8821f50 --- /dev/null +++ b/apps/ktorrent/ktorrent.h @@ -0,0 +1,238 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 _KTORRENT_H_ +#define _KTORRENT_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <kapplication.h> +#include <newui/dmainwindow.h> +#include <qtimer.h> +#include <interfaces/guiinterface.h> + +typedef QValueList<QCString> QCStringList; + +class KAction; +class KToggleAction; +class KURL; +class KTorrentCore; +class KTorrentView; +class TrayIcon; +class SetMaxRate; +class KTorrentDCOP; +class QLabel; +class QListViewItem; +class KTorrentPreferences; +class ViewManager; + + +namespace kt +{ + class TorrentInterface; + class Group; + class GroupView; +} + + +/** + * This class serves as the main window for KTorrent. It handles the + * menus, toolbars, and status bars. + * + * @short Main window class + * @author Joris Guisson <joris.guisson@gmail.com> + * @version 0.1 + */ +class KTorrent : public DMainWindow, public kt::GUIInterface +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + KTorrent(); + + /** + * Default Destructor + */ + virtual ~KTorrent(); + + /// Open a view with the given group + void openView(const QString & group_name); + + /// Get the core + KTorrentCore & getCore() {return *m_core;} + + /** + * Apply the settings. + * @param change_port Wether or not to change the server port + */ + void applySettings(bool change_port = true); + + virtual void addTabPage(QWidget* page,const QIconSet & icon, + const QString & caption,kt::CloseTabListener* ctl = 0); + virtual void addTabPage(QWidget* page,const QPixmap & icon, + const QString & caption,kt::CloseTabListener* ctl = 0); + virtual void removeTabPage(QWidget* page); + virtual void addPrefPage(kt::PrefPageInterface* page); + virtual void removePrefPage(kt::PrefPageInterface* page); + virtual void mergePluginGui(kt::Plugin* p); + virtual void removePluginGui(kt::Plugin* p); + virtual void addWidgetBelowView(QWidget* w,const QString & icon,const QString & caption); + virtual void removeWidgetBelowView(QWidget* w); + virtual void addToolWidget(QWidget* w,const QString & icon,const QString & caption,ToolDock dock); + virtual void removeToolWidget(QWidget* w); + virtual const kt::TorrentInterface* getCurrentTorrent() const; + virtual KToolBar* addToolBar(const char* name); + virtual void removeToolBar(KToolBar* tb); + virtual KProgress* addProgressBarToStatusBar(); + virtual void removeProgressBarFromStatusBar(KProgress* p); + + QString getStatusInfo(); + QString getStatusTransfer(); + QString getStatusSpeed(); + QString getStatusDHT(); + QString getStatusFirewall(); + QCStringList getTorrentInfo(kt::TorrentInterface* tc); + +public slots: + /** + * Use this method to load whatever file/URL you have + */ + void load(const KURL& url); + + /** + * Does the same as load, but doesn't ask any questions + */ + void loadSilently(const KURL& url); + + /** + * Does the same as loadSilently, except accepts a directory to + * save to + */ + void loadSilentlyDir(const KURL& url, const KURL& savedir); + + /// Open a view with the given group + void openView(kt::Group* g); + +protected: + /** + * This function is called when it is time for the app to save its + * properties for session management purposes. + */ + void saveProperties(KConfig *); + + /** + * This function is called when this app is restored. The KConfig + * object points to the session management config file that was saved + * with @ref saveProperties + */ + void readProperties(KConfig *); + + +private slots: + void fileOpen(); + void fileNew(); + void torrentPaste(); + void startDownload(); + void startAllDownloadsCurrentView(); + void startAllDownloads(); + void stopDownload(); + void stopAllDownloadsCurrentView(); + void stopAllDownloads(); + void showIPFilter(); + void removeDownload(); + void queueManagerShow(); + void optionsShowStatusbar(); + void optionsShowMenubar(); + void optionsConfigureKeys(); + void optionsConfigureToolbars(); + void optionsPreferences(); + void newToolbarConfig(); + void changeStatusbar(const QString& text); + void changeCaption(const QString& text); + void currentTorrentChanged(kt::TorrentInterface* tc); + void updatedStats(); + void urlDropped(QDropEvent*,QListViewItem*); + void onUpdateActions(int flags); + void groupChanged(kt::Group* g); + void groupRenamed(kt::Group* g); + void groupRemoved(kt::Group* g); + void currentTabChanged(QWidget* w); + void openDefaultView(); + void statusBarMsgExpired(); + void find(); + +private: + void setupAccel(); + void setupActions(); + bool queryClose(); + bool queryExit(); + + + virtual void addWidgetInView(QWidget* w,kt::Position pos); + virtual void removeWidgetFromView(QWidget* w); + virtual void closeTab(); + +private: + kt::GroupView* m_group_view; + ViewManager* m_view_man; + KToggleAction *m_statusbarAction; + KToggleAction* m_menubarAction; + + KTorrentCore* m_core; + TrayIcon* m_systray_icon; + SetMaxRate* m_set_max_upload_rate; + SetMaxRate* m_set_max_download_rate; + + KTorrentDCOP* m_dcop; + QTimer m_gui_update_timer; + QTimer m_status_msg_expire; + KTorrentPreferences* m_pref; + + QMap<QWidget*,kt::CloseTabListener*> m_tab_map; + + QLabel* m_statusInfo; + QLabel* m_statusTransfer; + QLabel* m_statusSpeed; + QLabel* m_statusDHT; + QLabel* m_statusFirewall; + + KAction* m_start; + KAction* m_stop; + KAction* m_remove; + KAction* m_startall; + KAction* m_startall_systray; + KAction* m_stopall; + KAction* m_stopall_systray; + KAction* m_pasteurl; + KAction* m_queuemgr; + KAction* m_queueaction; + KAction* m_datacheck; + KAction* m_ipfilter; + KAction* m_find; + + KProgress* m_status_prog; +}; + +#endif // _KTORRENT_H_ diff --git a/apps/ktorrent/ktorrent.lsm b/apps/ktorrent/ktorrent.lsm new file mode 100644 index 0000000..285eb74 --- /dev/null +++ b/apps/ktorrent/ktorrent.lsm @@ -0,0 +1,16 @@ +Begin3 +Title: KTorrent -- Some description +Version: 0.1 +Entered-date: +Description: +Keywords: KDE Qt +Author: Joris Guisson <joris.guisson@gmail.com> +Maintained-by: Joris Guisson <joris.guisson@gmail.com> +Home-page: +Alternate-site: +Primary-site: ftp://ftp.kde.org/pub/kde/unstable/apps/utils + xxxxxx ktorrent-0.1.tar.gz + xxx ktorrent-0.1.lsm +Platform: Linux. Needs KDE +Copying-policy: Custom +End diff --git a/apps/ktorrent/ktorrentapp.cpp b/apps/ktorrent/ktorrentapp.cpp new file mode 100644 index 0000000..591848f --- /dev/null +++ b/apps/ktorrent/ktorrentapp.cpp @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (C) 2005 by Adam Treat * + * treat@kde.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "ktorrentapp.h" + +#include <kglobal.h> +#include <kstartupinfo.h> +#include <kcmdlineargs.h> +#include <kstandarddirs.h> +#include <dcopclient.h> + +#include <util/log.h> +#include <torrent/globals.h> +#include <util/functions.h> + +#include "ktorrent.h" + +KTorrentApp::KTorrentApp() + : KUniqueApplication() +{} + +KTorrentApp::~KTorrentApp() +{} + +int KTorrentApp::newInstance() +{ + // register ourselves as a dcop client + if (!dcopClient()->isRegistered() ) + dcopClient()->registerAs(name(), false); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + bt::Globals::instance().setDebugMode(args->isSet("debug")); + + QString data_dir = KGlobal::dirs()->saveLocation("data","ktorrent"); + if (!data_dir.endsWith(bt::DirSeparator())) + data_dir += bt::DirSeparator(); + bt::Globals::instance().initLog(data_dir + "log"); + + if (!mainWidget()) + { + KTorrent *widget = new KTorrent(); + setMainWidget(widget); + } + else + KStartupInfo::setNewStartupId( mainWidget(), kapp->startupId()); + + + KTorrent *widget = ::qt_cast<KTorrent*>( mainWidget() ); + + for (int i = 0; i < args->count(); i++) + { + if (args->isSet("silent")) + widget->loadSilently(args->url(i)); + else + widget->load(args->url(i)); + } + + args->clear(); + return 0; +} + +#include "ktorrentapp.moc" + diff --git a/apps/ktorrent/ktorrentapp.h b/apps/ktorrent/ktorrentapp.h new file mode 100644 index 0000000..db6048d --- /dev/null +++ b/apps/ktorrent/ktorrentapp.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * Copyright (C) 2005 by Adam Treat * + * treat@kde.org * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 _KTORRENTAPP_H_ +#define _KTORRENTAPP_H_ + +#include "dcopinterface.h" +#include <kuniqueapplication.h> + +class KTorrentApp : public KUniqueApplication +{ + Q_OBJECT +public: + KTorrentApp(); + virtual ~KTorrentApp(); + + virtual int newInstance(); +}; + +#endif // _KTORRENTAPP_H_ + diff --git a/apps/ktorrent/ktorrentcore.cpp b/apps/ktorrent/ktorrentcore.cpp new file mode 100644 index 0000000..1760fce --- /dev/null +++ b/apps/ktorrent/ktorrentcore.cpp @@ -0,0 +1,1145 @@ +/*************************************************************************** + * Copyright (C) 2005 by * + * Joris Guisson <joris.guisson@gmail.com> * + * Ivan Vasic <ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <unistd.h> +#include <qdir.h> +#include <klocale.h> +#include <kglobal.h> +#include <kfiledialog.h> +#include <kprogress.h> +#include <kmessagebox.h> +#include <kstandarddirs.h> +#include <kapplication.h> +#include <kio/job.h> +#include <kio/netaccess.h> +#include <qregexp.h> + +#include <util/log.h> +#include <torrent/torrentcontrol.h> +#include <torrent/globals.h> +#include <util/error.h> +#include <util/fileops.h> +#include <util/waitjob.h> +#include <torrent/torrentcreator.h> +#include <torrent/server.h> +#include <torrent/authenticationmonitor.h> +#include <util/functions.h> +#include <torrent/ipblocklist.h> +#include <kademlia/dhtbase.h> +#include <torrent/torrentfile.h> + +#include "pluginmanager.h" +#include <torrent/queuemanager.h> + +#include "ktorrentcore.h" +#include "settings.h" +#include "functions.h" +#include "fileselectdlg.h" +#include "scandialog.h" + + +#include <util/profiler.h> + + +using namespace bt; +using namespace kt; + +const Uint32 CORE_UPDATE_INTERVAL = 250; + + + +KTorrentCore::KTorrentCore(kt::GUIInterface* gui) : max_downloads(0),keep_seeding(true),pman(0) +{ + UpdateCurrentTime(); + + qman = new QueueManager(); + connect(qman, SIGNAL(lowDiskSpace(kt::TorrentInterface*,bool)), this, SLOT(onLowDiskSpace(kt::TorrentInterface*,bool))); + + + data_dir = Settings::tempDir(); + bool dd_not_exist = !bt::Exists(data_dir); + if (data_dir == QString::null || dd_not_exist) + { + data_dir = KGlobal::dirs()->saveLocation("data","ktorrent"); + if (dd_not_exist) + { + Settings::setTempDir(data_dir); + Settings::writeConfig(); + } + } + + removed_bytes_up = removed_bytes_down = 0; + + if (!data_dir.endsWith(bt::DirSeparator())) + data_dir += bt::DirSeparator(); + // downloads.setAutoDelete(true); + + connect(&update_timer,SIGNAL(timeout()),this,SLOT(update())); + update_timer.start(CORE_UPDATE_INTERVAL); + + Uint16 port = Settings::port(); + if (port == 0) + { + port = 6881; + Settings::setPort(6881); + } + Uint16 i = 0; + do + { + Globals::instance().initServer(port + i); + i++; + } + while (!Globals::instance().getServer().isOK() && i < 10); + + if (Globals::instance().getServer().isOK()) + { + if (port != port + i - 1) + KMessageBox::information(0, + i18n("Specified port (%1) is unavailable or in" + " use by another application. KTorrent is now using port %2.") + .arg(port).arg(port + i - 1)); + + Out(SYS_GEN|LOG_NOTICE) << "Bound to port " << (port + i - 1) << endl; + } + else + { + KMessageBox::error(0, + i18n("KTorrent is unable to accept connections because the ports %1 to %2 are " + "already in use by another program.").arg(port).arg(port + i - 1)); + Out(SYS_GEN|LOG_IMPORTANT) << "Cannot find free port" << endl; + } + + + pman = new kt::PluginManager(this,gui); +} + + +KTorrentCore::~KTorrentCore() +{ + delete qman; + delete pman; +} + +void KTorrentCore::loadPlugins() +{ + pman->loadConfigFile(KGlobal::dirs()->saveLocation("data","ktorrent") + "plugins"); + pman->loadPluginList(); +} + +bool KTorrentCore::init(TorrentControl* tc,bool silently) +{ + connectSignals(tc); + qman->append(tc); + + bool user = false; + bool start_torrent = false; + + if (!silently) + { + FileSelectDlg dlg(gman, &user, &start_torrent); + + if (dlg.execute(tc) != QDialog::Accepted) + { + remove(tc,false); + return false; + } + } + + try + { + tc->createFiles(); + } + catch (bt::Error & err) + { + // if we can't create files, just remove the torrent + KMessageBox::error(0,err.toString()); + remove(tc,false); + return false; + } + + if (tc->hasExistingFiles()) + { + ScanDialog* scan_dlg = new ScanDialog(this,true); + scan_dlg->show(); + scan_dlg->execute(tc,true); + } + + tc->setPreallocateDiskSpace(true); + + if(Settings::maxRatio()>0) + tc->setMaxShareRatio(Settings::maxRatio()); + + if (Settings::maxSeedTime() > 0) + tc->setMaxSeedTime(Settings::maxSeedTime()); + + torrentAdded(tc); + qman->torrentAdded(tc, user, start_torrent); + + + //now copy torrent file to user specified dir if needed + if(Settings::useTorrentCopyDir()) + { + QString torFile = tc->getTorDir(); + + if(!torFile.endsWith("/")) + torFile += "/"; + + torFile += "torrent"; + + QString destination = Settings::torrentCopyDir(); + + if(!destination.endsWith("/")) + destination += "/"; + + destination += tc->getStats().torrent_name + ".torrent"; + + try + { + bt::CopyFile(torFile, destination, TRUE); + } + catch(bt::Error& err) + { + Out(SYS_GEN|LOG_IMPORTANT) << "Could not copy torrent file to " << destination << endl; + } + } + + return true; +} + +bool KTorrentCore::load(const QByteArray & data,const QString & dir,bool silently, const KURL& url) +{ + QString tdir = findNewTorrentDir(); + TorrentControl* tc = 0; + try + { + Out(SYS_GEN|LOG_NOTICE) << "Loading torrent from data " << endl; + tc = new TorrentControl(); + tc->init(qman, data, tdir, dir, + Settings::useSaveDir() ? Settings::saveDir() : QString()); + + if(!init(tc,silently)) + loadingFinished(url, false, true); + else + loadingFinished(url, true, false); + + return true; + } + catch (bt::Error & err) + { + KMessageBox::error(0,err.toString()); + delete tc; + tc = 0; + // delete tdir if necesarry + if (bt::Exists(tdir)) + bt::Delete(tdir,true); + + loadingFinished(url, false, false); + + return false; + } +} + +bool KTorrentCore::load(const QString & target,const QString & dir,bool silently) +{ + QString tdir = findNewTorrentDir(); + TorrentControl* tc = 0; + try + { + Out(SYS_GEN|LOG_NOTICE) << "Loading file " << target << endl; + tc = new TorrentControl(); + tc->init(qman, target, tdir, dir, + Settings::useSaveDir() ? Settings::saveDir() : QString()); + + init(tc,silently); + return true; + } + catch (bt::Error & err) + { + KMessageBox::error(0,err.toString()); + delete tc; + tc = 0; + // delete tdir if necesarry + if (bt::Exists(tdir)) + bt::Delete(tdir,true); + return false; + } +} + +void KTorrentCore::downloadFinished(KIO::Job *job) +{ + KIO::StoredTransferJob* j = (KIO::StoredTransferJob*)job; + int err = j->error(); + if (err == KIO::ERR_USER_CANCELED) + { + loadingFinished(j->url(),false,true); + return; + } + + if (err) + { + loadingFinished(j->url(),false,false); + j->showErrorDialog(0); + } + else + { + // load in the file (target is always local) + QString dir = Settings::saveDir(); + if (!Settings::useSaveDir() || dir.isNull()) + dir = QDir::homeDirPath(); + + if (dir != QString::null && load(j->data(),dir,false, j->url())) + loadingFinished(j->url(),true,false); + else + loadingFinished(j->url(),false,true); + } +} + +void KTorrentCore::load(const KURL& url) +{ + if (url.isLocalFile()) + { + QString path = url.path(); + QString dir = Settings::saveDir(); + if (!Settings::useSaveDir() || dir.isNull()) + dir = QDir::homeDirPath(); + + if (dir != QString::null && load(path,dir,false)) + loadingFinished(url,true,false); + else + loadingFinished(url,false,true); + } + else + { + KIO::Job* j = KIO::storedGet(url,false,true); + connect(j,SIGNAL(result(KIO::Job*)),this,SLOT(downloadFinished( KIO::Job* ))); + } +} + +void KTorrentCore::downloadFinishedSilently(KIO::Job *job) +{ + KIO::StoredTransferJob* j = (KIO::StoredTransferJob*)job; + int err = j->error(); + if (err == KIO::ERR_USER_CANCELED) + { + loadingFinished(j->url(),false,true); + } + else if (err) + { + loadingFinished(j->url(),false,false); + } + else + { + QString dir; + if (custom_save_locations.contains(j)) + { + // we have a custom save location so save to that + dir = custom_save_locations[j].path(); + custom_save_locations.erase(j); + } + else if (!Settings::useSaveDir()) + { + // incase save dir is not set, use home director + Out(SYS_GEN|LOG_NOTICE) << "Cannot load " << j->url() << " silently, default save location not set !" << endl; + Out(SYS_GEN|LOG_NOTICE) << "Using home directory instead !" << endl; + dir = QDir::homeDirPath(); + } + else + { + dir = Settings::saveDir(); + } + + + if (dir != QString::null && load(j->data(),dir,true,j->url())) + loadingFinished(j->url(),true,false); + else + loadingFinished(j->url(),false,false); + } +} + +void KTorrentCore::loadSilently(const KURL& url) +{ + if (url.isLocalFile()) + { + QString path = url.path(); + QString dir = Settings::saveDir(); + if (!Settings::useSaveDir() || dir.isNull()) + { + Out(SYS_GEN|LOG_NOTICE) << "Cannot load " << path << " silently, default save location not set !" << endl; + Out(SYS_GEN|LOG_NOTICE) << "Using home directory instead !" << endl; + dir = QDir::homeDirPath(); + } + + if (dir != QString::null && load(path,dir,true)) + loadingFinished(url,true,false); + else + loadingFinished(url,false,true); + } + else + { + // download to a random file in tmp + KIO::Job* j = KIO::storedGet(url,false,true); + connect(j,SIGNAL(result(KIO::Job*)),this,SLOT(downloadFinishedSilently( KIO::Job* ))); + } +} + +void KTorrentCore::loadSilentlyDir(const KURL& url, const KURL& savedir) +{ + if (url.isLocalFile()) + { + QString path = url.path(); + QString dir = savedir.path(); + QFileInfo fi(dir); + if (!fi.exists() || !fi.isWritable() || !fi.isDir()) + { + Out(SYS_GEN|LOG_NOTICE) << "Cannot load " << path << " silently, destination directory is not OK ! Using default save directory." << endl; + dir = Settings::saveDir(); + if (!Settings::useSaveDir()) + { + Out(SYS_GEN|LOG_NOTICE) << "Default save directory not set, using home directory !" << endl; + dir = QDir::homeDirPath(); + } + } + + if (dir != QString::null && load(path,dir,true)) + loadingFinished(url,true,false); + else + loadingFinished(url,false,true); + } + else + { + // download to a random file in tmp + KIO::Job* j = KIO::storedGet(url,false,true); + custom_save_locations.insert(j,savedir); // keep track of save location + connect(j,SIGNAL(result(KIO::Job*)),this,SLOT(downloadFinishedSilently( KIO::Job* ))); + } +} + +void KTorrentCore::start(kt::TorrentInterface* tc) +{ + kt::TorrentStartResponse reason = qman->start(tc); + switch (reason) + { + // we can return, the question to ignore the limits will have informed the user + case MAX_SHARE_RATIO_REACHED: + case START_OK: // start OK is normal + case BUSY_WITH_DATA_CHECK: // checking data, so let the torrent be + case USER_CANCELED: + return; + case NOT_ENOUGH_DISKSPACE: + case QM_LIMITS_REACHED: + canNotStart(tc,reason); + break; + } +} + +void KTorrentCore::stop(TorrentInterface* tc, bool user) +{ + qman->stop(tc, user); +} + +int KTorrentCore::getNumRunning(bool onlyDownloads, bool onlySeeds) const +{ + return qman->getNumRunning(onlyDownloads, onlySeeds); +} + +QString KTorrentCore::findNewTorrentDir() const +{ + int i = 0; + while (true) + { + QDir d; + QString dir = data_dir + QString("tor%1/").arg(i); + if (!d.exists(dir)) + { + return dir; + } + i++; + } + return QString::null; +} + +void KTorrentCore::loadExistingTorrent(const QString & tor_dir) +{ + TorrentControl* tc = 0; + + QString idir = tor_dir; + if (!idir.endsWith(bt::DirSeparator())) + idir += bt::DirSeparator(); + + if (!bt::Exists(idir + "torrent")) + return; + + try + { + tc = new TorrentControl(); + tc->init(qman,idir + "torrent",idir,QString::null, + Settings::useSaveDir() ? Settings::saveDir() : QString()); + + qman->append(tc); + connectSignals(tc); + if (tc->getStats().autostart && tc->getStats().user_controlled) + start(tc); + torrentAdded(tc); + } + catch (bt::Error & err) + { + KMessageBox::error(0,err.toString()); + delete tc; + } +} + +void KTorrentCore::loadTorrents() +{ + QDir dir(data_dir); + QStringList sl = dir.entryList("tor*",QDir::Dirs); + for (Uint32 i = 0;i < sl.count();i++) + { + + QString idir = data_dir + *sl.at(i); + if (!idir.endsWith(DirSeparator())) + idir.append(DirSeparator()); + + Out(SYS_GEN|LOG_NOTICE) << "Loading " << idir << endl; + loadExistingTorrent(idir); + } + qman->orderQueue(); +} + +void KTorrentCore::remove(TorrentInterface* tc,bool data_to) +{ + try + { + const TorrentStats & s = tc->getStats(); + removed_bytes_up += s.session_bytes_uploaded; + removed_bytes_down += s.session_bytes_downloaded; + stop(tc); + + QString dir = tc->getTorDir(); + + try + { + if (data_to) + tc->deleteDataFiles(); + } + catch (Error & e) + { + KMessageBox::error(0,e.toString()); + } + + torrentRemoved(tc); + qman->torrentRemoved(tc); + + bt::Delete(dir,false); + } + catch (Error & e) + { + KMessageBox::error(0,e.toString()); + } +} + +void KTorrentCore::setMaxDownloads(int max) +{ + qman->setMaxDownloads(max); +} + +void KTorrentCore::setMaxSeeds(int max) +{ + qman->setMaxSeeds(max); +} + +void KTorrentCore::torrentFinished(kt::TorrentInterface* tc) +{ + if (!keep_seeding) + tc->stop(false); + + finished(tc); + qman->torrentFinished(tc); +} + +void KTorrentCore::setKeepSeeding(bool ks) +{ + keep_seeding = ks; + qman->setKeepSeeding(ks); +} + +void KTorrentCore::onExit() +{ + // stop timer to prevent updates during wait + update_timer.stop(); + // stop all authentications going on + AuthenticationMonitor::instance().clear(); + // shutdown the server + Globals::instance().shutdownServer(); + + WaitJob* job = new WaitJob(5000); + qman->onExit(job); + // wait for completion of stopped events + if (job->needToWait()) + WaitJob::execute(job); + else + delete job; + + pman->unloadAll(false); + qman->clear(); +} + +bool KTorrentCore::changeDataDir(const QString & new_dir) +{ + try + { + update_timer.stop(); + // do nothing if new and old dir are the same + if (KURL(data_dir) == KURL(new_dir) || data_dir == (new_dir + bt::DirSeparator())) + { + update_timer.start(CORE_UPDATE_INTERVAL); + return true; + } + + // safety check + if (!bt::Exists(new_dir)) + bt::MakeDir(new_dir); + + + // make sure new_dir ends with a / + QString nd = new_dir; + if (!nd.endsWith(DirSeparator())) + nd += DirSeparator(); + + Out() << "Switching to datadir " << nd << endl; + + qman->setPausedState(true); + + QPtrList<kt::TorrentInterface> succes; + + QPtrList<kt::TorrentInterface>::iterator i = qman->begin(); + while (i != qman->end()) + { + kt::TorrentInterface* tc = *i; + if (!tc->changeDataDir(nd)) + { + // failure time to roll back all the succesfull tc's + rollback(succes); + // set back the old data_dir in Settings + Settings::setTempDir(data_dir); + Settings::self()->writeConfig(); + qman->setPausedState(false); + update_timer.start(CORE_UPDATE_INTERVAL); + return false; + } + else + { + succes.append(tc); + } + i++; + } + data_dir = nd; + qman->setPausedState(false); + update_timer.start(CORE_UPDATE_INTERVAL); + return true; + } + catch (bt::Error & e) + { + Out(SYS_GEN|LOG_IMPORTANT) << "Error : " << e.toString() << endl; + update_timer.start(CORE_UPDATE_INTERVAL); + return false; + } +} + +void KTorrentCore::rollback(const QPtrList<kt::TorrentInterface> & succes) +{ + Out() << "Error, rolling back" << endl; + update_timer.stop(); + QPtrList<kt::TorrentInterface> ::const_iterator i = succes.begin(); + while (i != succes.end()) + { + (*i)->rollback(); + i++; + } + update_timer.start(CORE_UPDATE_INTERVAL); +} + +void KTorrentCore::startAll(int type) +{ + qman->startall(type); +} + +void KTorrentCore::stopAll(int type) +{ + qman->stopall(type); +} + +void KTorrentCore::update() +{ + bt::UpdateCurrentTime(); + AuthenticationMonitor::instance().update(); + + QPtrList<kt::TorrentInterface>::iterator i = qman->begin(); + //Uint32 down_speed = 0; + while (i != qman->end()) + { + bool finished = false; + kt::TorrentInterface* tc = *i; + if (tc->isCheckingData(finished)) + { + if (finished) + tc->afterDataCheck(); + } + else if (tc->getStats().running) + { + // see if we need to do a auto data check + if (Settings::autoRecheck() && tc->getStats().num_corrupted_chunks >= Settings::maxCorruptedBeforeRecheck()) + { + Out(SYS_GEN|LOG_IMPORTANT) << "Doing an automatic data check on " + << tc->getStats().torrent_name << endl; + + ScanDialog* scan_dlg = new ScanDialog(this,false); + scan_dlg->show(); + scan_dlg->execute(tc,true); + } + else + { + tc->update(); + } + } + i++; + } +} + +void KTorrentCore::makeTorrent(const QString & file,const QStringList & trackers, + int chunk_size,const QString & name, + const QString & comments,bool seed, + const QString & output_file,bool priv_tor,KProgress* prog, bool decentralized) +{ + QString tdir; + try + { + if (chunk_size < 0) + chunk_size = 256; + + bt::TorrentCreator mktor(file,trackers,chunk_size,name,comments,priv_tor, decentralized); + prog->setTotalSteps(mktor.getNumChunks()); + Uint32 ns = 0; + while (!mktor.calculateHash()) + { + prog->setProgress(ns); + ns++; + if (ns % 10 == 0) + KApplication::kApplication()->processEvents(); + } + + mktor.saveTorrent(output_file); + tdir = findNewTorrentDir(); + kt::TorrentInterface* tc = mktor.makeTC(tdir); + if (tc) + { + connectSignals(tc); + qman->append(tc); + if (seed) + start(tc); + torrentAdded(tc); + } + } + catch (bt::Error & e) + { + // cleanup if necessary + if (bt::Exists(tdir)) + bt::Delete(tdir,true); + + // Show error message + KMessageBox::error(0, + i18n("Cannot create torrent: %1").arg(e.toString()), + i18n("Error")); + } +} + +CurrentStats KTorrentCore::getStats() +{ + CurrentStats stats; + Uint64 bytes_dl = 0, bytes_ul = 0; + Uint32 speed_dl = 0, speed_ul = 0; + + + for ( QPtrList<kt::TorrentInterface>::iterator i = qman->begin(); i != qman->end(); ++i ) + { + kt::TorrentInterface* tc = *i; + const TorrentStats & s = tc->getStats(); + speed_dl += s.download_rate; + speed_ul += s.upload_rate; + bytes_dl += s.session_bytes_downloaded; + bytes_ul += s.session_bytes_uploaded; + } + stats.download_speed = speed_dl; + stats.upload_speed = speed_ul; + stats.bytes_downloaded = bytes_dl + removed_bytes_down; + stats.bytes_uploaded = bytes_ul + removed_bytes_up; + + return stats; +} + +bool KTorrentCore::changePort(Uint16 port) +{ + if (getNumTorrentsRunning() == 0) + { + Globals::instance().getServer().changePort(port); + return true; + } + else + { + return false; + } +} + +void KTorrentCore::slotStoppedByError(kt::TorrentInterface* tc, QString msg) +{ + emit torrentStoppedByError(tc, msg); +} + +Uint32 KTorrentCore::getNumTorrentsRunning() const +{ + return qman->getNumRunning(); +} + +Uint32 KTorrentCore::getNumTorrentsNotRunning() const +{ + return qman->count() - qman->getNumRunning(); +} + +int KTorrentCore::countSeeds() const +{ + return qman->countSeeds(); +} + +int KTorrentCore::countDownloads() const +{ + return qman->countDownloads(); +} + +void KTorrentCore::addBlockedIP(QString& ip) +{ + IPBlocklist& filter = IPBlocklist::instance(); + filter.addRange(ip); +} + +void KTorrentCore::removeBlockedIP(QString& ip) +{ + IPBlocklist& filter = IPBlocklist::instance(); + filter.removeRange(ip); +} + +bt::QueueManager* KTorrentCore::getQueueManager() +{ + return this->qman; +} + +void KTorrentCore::torrentSeedAutoStopped( kt::TorrentInterface * tc,kt::AutoStopReason reason ) +{ + qman->startNext(); + if (reason == kt::MAX_RATIO_REACHED) + maxShareRatioReached(tc); + else + maxSeedTimeReached(tc); +} + +int KTorrentCore::getMaxUploadSpeed() +{ + return Settings::maxUploadRate(); +} + +int KTorrentCore::getMaxDownloadSpeed() +{ + return Settings::maxDownloadRate(); +} + +void KTorrentCore::setMaxUploadSpeed(int v) +{ + return Settings::setMaxUploadRate(v); +} + +void KTorrentCore::setMaxDownloadSpeed(int v) +{ + return Settings::setMaxDownloadRate(v); +} + +void KTorrentCore::setPausedState(bool pause) +{ + qman->setPausedState(pause); +} + +void KTorrentCore::queue(kt::TorrentInterface* tc) +{ + qman->queue(tc); +} + +TorrentInterface* KTorrentCore::getTorFromNumber(int tornumber) +{ + QString tordir = data_dir + "tor" + QString("%1").arg(tornumber) + "/"; + Out() << "tordir " << tordir << endl; + QPtrList<TorrentInterface>::iterator i = qman->begin(); + while(i != qman->end()) + { + TorrentInterface* tc = *i; + QString td = tc->getTorDir(); + if(td == tordir) + return tc; + i++; + } + TorrentInterface* nullinterface = 0; + return nullinterface; +} + +QValueList<int> KTorrentCore::getTorrentNumbers(int type = 3) +{ + QValueList<int> tornums; + QPtrList<TorrentInterface>::iterator i = qman->begin(); + while(i != qman->end()) + { + TorrentInterface* tc = *i; + if((type == 1 && tc->getStats().completed) || + (type == 2 && !(tc->getStats().completed))) + { + Out() << "Skipping a torrent" << endl; + i++; + continue; + } + QString td = tc->getTorDir(); + Out() << td << endl; + td = td.remove(0, td.length() - 6); + td = td.remove(QRegExp("[^0-9]*")); + Out() << td << endl; + tornums.append(td.toInt()); + i++; + } + return tornums; +} + +Uint32 KTorrentCore::getFileCount(int tornumber) +{ + kt::TorrentInterface* tc = getTorFromNumber(tornumber); + if(tc) + return tc->getNumFiles(); + else + return 0; +} + +QCStringList KTorrentCore::getFileNames(int tornumber) +{ + QCStringList filenames; + kt::TorrentInterface* tc = getTorFromNumber(tornumber); + if(!tc || tc->getNumFiles() == 0) + return filenames; + for(Uint32 i = 0; i < tc->getNumFiles(); i++) + { + QCString filename = tc->getTorrentFile(i).getPath().ascii(); + filenames.append(filename); + } + + return filenames; +} + +QValueList<int> KTorrentCore::getFilePriorities(int tornumber) +{ + QValueList<int> priorities; + kt::TorrentInterface* tc = getTorFromNumber(tornumber); + if(!tc || tc->getNumFiles() == 0) + return priorities; + + for(Uint32 i = 0; i < tc->getNumFiles(); i++) + { + bt::Priority priority = tc->getTorrentFile(i).getPriority(); + int newpriority; + switch(priority) + { + case bt::FIRST_PRIORITY: + newpriority = 3; + break; + case bt::LAST_PRIORITY: + newpriority = 1; + break; + case bt::EXCLUDED: + newpriority = 0; + break; + default: + newpriority = 2; + break; + } + priorities.append(newpriority); + } + return priorities; +} + +void KTorrentCore::setFilePriority(kt::TorrentInterface* tc, Uint32 index, + int priority) +{ + bt::Priority newpriority; + switch(priority) + { + case 3: + newpriority = bt::FIRST_PRIORITY; + break; + case 1: + newpriority = bt::LAST_PRIORITY; + break; + case 0: + newpriority = bt::EXCLUDED; + break; + default: + newpriority = bt::NORMAL_PRIORITY; + break; + } + + tc->getTorrentFile(index).setPriority(newpriority); +} + +void KTorrentCore::announceByTorNum(int tornumber) +{ + kt::TorrentInterface* tc = getTorFromNumber(tornumber); + if(tc) + tc->updateTracker(); +} + +void KTorrentCore::aboutToBeStarted(kt::TorrentInterface* tc,bool & ret) +{ + ret = true; + + QStringList missing; + if (!tc->hasMissingFiles(missing)) + return; + + + if (tc->getStats().multi_file_torrent) + { + QString msg = i18n("Several data files of the torrent \"%1\" are missing, do you want to recreate them, or do you want to not download them?").arg(tc->getStats().torrent_name); + + int ret = KMessageBox::warningYesNoCancelList(0,msg,missing,QString::null, + KGuiItem(i18n("Recreate")),KGuiItem(i18n("Do Not Download"))); + if (ret == KMessageBox::Yes) + { + try + { + // recreate them + tc->recreateMissingFiles(); + } + catch (bt::Error & e) + { + KMessageBox::error(0,i18n("Cannot recreate missing files: %1").arg(e.toString())); + tc->handleError(i18n("Data files are missing")); + ret = false; + } + } + else if (ret == KMessageBox::No) + { + try + { + // mark them as do not download + tc->dndMissingFiles(); + } + catch (bt::Error & e) + { + KMessageBox::error(0,i18n("Cannot deselect missing files: %1").arg(e.toString())); + tc->handleError(i18n("Data files are missing")); + ret = false; + } + } + else + { + tc->handleError(i18n("Data files are missing")); + ret = false; + } + } + else + { + QString msg = i18n("The file where the data is saved of the torrent \"%1\" is missing, do you want to recreate it?").arg(tc->getStats().torrent_name); + int ret = KMessageBox::warningYesNo(0,msg, i18n("Recreate"),KGuiItem(i18n("Recreate")),KGuiItem(i18n("Do Not Recreate"))); + if (ret == KMessageBox::Yes) + { + try + { + tc->recreateMissingFiles(); + } + catch (bt::Error & e) + { + KMessageBox::error(0,i18n("Cannot recreate data file: %1").arg(e.toString())); + tc->handleError(i18n("Data file is missing")); + ret = false; + } + } + else + { + tc->handleError(i18n("Data file is missing")); + ret = false; + } + } + +} + +void KTorrentCore::emitCorruptedData(kt::TorrentInterface* tc) +{ + corruptedData(tc); + +} + +void KTorrentCore::connectSignals(kt::TorrentInterface* tc) +{ + connect(tc,SIGNAL(finished(kt::TorrentInterface*)), + this,SLOT(torrentFinished(kt::TorrentInterface* ))); + connect(tc, SIGNAL(stoppedByError(kt::TorrentInterface*, QString )), + this, SLOT(slotStoppedByError(kt::TorrentInterface*, QString ))); + connect(tc, SIGNAL(seedingAutoStopped(kt::TorrentInterface*, kt::AutoStopReason)), + this, SLOT(torrentSeedAutoStopped(kt::TorrentInterface*, kt::AutoStopReason))); + connect(tc,SIGNAL(aboutToBeStarted( kt::TorrentInterface*,bool & )), + this, SLOT(aboutToBeStarted( kt::TorrentInterface*,bool & ))); + connect(tc,SIGNAL(corruptedDataFound( kt::TorrentInterface* )), + this, SLOT(emitCorruptedData( kt::TorrentInterface* ))); + connect(qman, SIGNAL(queuingNotPossible(kt::TorrentInterface*)), + this, SLOT(enqueueTorrentOverMaxRatio( kt::TorrentInterface* ))); + connect(qman, SIGNAL(lowDiskSpace(kt::TorrentInterface*, bool)), + this, SLOT(onLowDiskSpace(kt::TorrentInterface*, bool))); + +} + +float KTorrentCore::getGlobalMaxShareRatio() const +{ + return Settings::maxRatio(); +} + +void KTorrentCore::enqueueTorrentOverMaxRatio(kt::TorrentInterface* tc) +{ + emit queuingNotPossible(tc); +} + + +void KTorrentCore::doDataCheck(kt::TorrentInterface* tc) +{ + bool dummy = false; + if (tc->isCheckingData(dummy)) + return; + + ScanDialog* scan_dlg = new ScanDialog(this,false); + scan_dlg->setCaption(i18n("Checking Data Integrity")); + scan_dlg->show(); + scan_dlg->execute(tc,false); +} + +void KTorrentCore::onLowDiskSpace(kt::TorrentInterface * tc, bool stopped) +{ + emit lowDiskSpace(tc, stopped); +} + +#include "ktorrentcore.moc" diff --git a/apps/ktorrent/ktorrentcore.h b/apps/ktorrent/ktorrentcore.h new file mode 100644 index 0000000..e0ed362 --- /dev/null +++ b/apps/ktorrent/ktorrentcore.h @@ -0,0 +1,357 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTORRENTCORE_H +#define KTORRENTCORE_H + +#include <qmap.h> +#include <qtimer.h> +#include <qcstring.h> +#include <util/constants.h> +#include <interfaces/coreinterface.h> + +typedef QValueList<QCString> QCStringList; + +namespace bt +{ + class Server; + class QueueManager; + class TorrentControl; +} + +namespace KIO +{ + class Job; +} + +namespace kt +{ + class Plugin; + class PluginManager; + class GUIInterface; + class TorrentInterface; + class GroupManager; +} + + + + +class KProgress; + +/** + * @author Joris Guisson + * @brief Keeps track of all TorrentInterface objects + * + * This class keeps track of all TorrentInterface objects. + */ +class KTorrentCore : public kt::CoreInterface +{ + Q_OBJECT +public: + KTorrentCore(kt::GUIInterface* gui); + virtual ~KTorrentCore(); + + + kt::PluginManager & getPluginManager() {return *pman;} + const kt::PluginManager & getPluginManager() const {return *pman;} + + /** + * Load all torrents from the data dir. + */ + void loadTorrents(); + + /** + * Load an existing torrent, which has already a properly set up torX dir. + * @param tor_dir The torX dir + */ + void loadExistingTorrent(const QString & tor_dir); + + /** + * Set the maximum number of simultanious downloads. + * @param max The max num (0 == no limit) + */ + void setMaxDownloads(int max); + + /** + * Set the maximum number of simultaneous seeds. + * @param max The max num (0 == no limit) + */ + void setMaxSeeds(int max); + + /** + * Set wether or not we should keep seeding after + * a download has finished. + * @param ks Keep seeding yes or no + */ + void setKeepSeeding(bool ks); + + /** + * Change the data dir. This involves copying + * all data from the old dir to the new. + * This can offcourse go horribly wrong, therefore + * if it doesn't succeed it returns false + * and leaves everything where it supposed to be. + * @param new_dir The new directory + */ + bool changeDataDir(const QString & new_dir); + + /** + * Save active torrents on exit. + */ + void onExit(); + + /** + * Start all, takes into account the maximum number of downloads. + * @param type Wether to start all downloads or seeds. 1=Downloads, 2=Seeds, 3=All + */ + void startAll(int type); + + /** + * Stop all torrents. + * @param type Wether to start all downloads or seeds. 1=Downloads, 2=Seeds, 3=All + */ + void stopAll(int type); + + /** + * Make a torrent file + * @param file The file or dir to make a torrent of + * @param trackers A list of trackers + * @param chunk_size The size of each chunk (in KB) + * @param name The torrents name (usually filename) + * @param comments The comments + * @param seed Wether or not to start seeding or not + * @param output_file File to store the torrent file + * @param priv_tor Is this a private torrent + * @param prog Progress bar to update + */ + void makeTorrent(const QString & file,const QStringList & trackers, + int chunk_size,const QString & name,const QString & comments, + bool seed,const QString & output_file,bool priv_tor,KProgress* prog, bool decentralized); + + CurrentStats getStats(); + + /** + * Switch the port when no torrents are running. + * @param port The new port + * @return true if we can, false if there are torrents running + */ + bool changePort(bt::Uint16 port); + + /// Get the number of torrents running (including seeding torrents). + bt::Uint32 getNumTorrentsRunning() const; + + /// Get the number of torrents not running. + bt::Uint32 getNumTorrentsNotRunning() const; + + ///Inserts blocked IP range into IPBlocklist + void addBlockedIP(QString& ip); + + ///Removes blocked IP range from IPBlocklist + void removeBlockedIP(QString& ip); + + /** + * Find the next free torX dir. + * @return Path to the dir (including the torX part) + */ + QString findNewTorrentDir() const; + + /** + * Load plugins. + */ + void loadPlugins(); + + virtual void load(const KURL& url); + virtual void loadSilently(const KURL& url); + virtual void loadSilentlyDir(const KURL& url, const KURL& savedir); + virtual float getGlobalMaxShareRatio() const; + + + bt::QueueManager* getQueueManager(); + + kt::GroupManager* getGroupManager() const { return gman; } + void setGroupManager(kt::GroupManager* g) { gman = g; } + + ///Gets the number of torrents running + int getNumRunning(bool onlyDownloads = true, bool onlySeeds = false) const; + ///Gets the number of torrents that are in state 'download' - total + int countDownloads() const; + ///Gets the number of torrents that are in state 'seed' - total + int countSeeds() const; + + int getMaxDownloadSpeed(); + int getMaxUploadSpeed(); + void setMaxDownloadSpeed(int v); + void setMaxUploadSpeed(int v); + + void setPausedState(bool pause); + + kt::TorrentInterface* getTorFromNumber(int tornumber); + QValueList<int> getTorrentNumbers(int type); + unsigned int getFileCount(int tornumber); + QCStringList getFileNames(int tornumber); + QValueList<int> getFilePriorities(int tornumber); + void setFilePriority(kt::TorrentInterface* tc, bt::Uint32 index, int priority); + void announceByTorNum(int tornumber); + + +public slots: + /** + * Load a torrent file. Pops up an error dialog + * if something goes wrong. + * @param file The torrent file (always a local file) + * @param dir Directory to save the data + * @param silently Wether or not to do this silently + */ + bool load(const QString & file,const QString & dir,bool silently); + + /** + * Load a torrent file. Pops up an error dialog + * if something goes wrong. + * @param data Byte array of the torrent file + * @param dir Directory to save the data + * @param silently Wether or not to do this silently + */ + bool load(const QByteArray & data,const QString & dir,bool silently, const KURL& url); + + /** + * Remove a download.This will delete all temp + * data from this TorrentInterface And delete the + * TorrentInterface itself. It can also potentially + * start a new download (when one is waiting to be downloaded). + * @param tc + * @param data_to + */ + void remove(kt::TorrentInterface* tc,bool data_to); + + /** + * Update all torrents. + */ + void update(); + + /** + * Start a torrent, takes into account the maximum number of downloads. + * @param tc The TorrentInterface + */ + void start(kt::TorrentInterface* tc); + + /** + * Stop a torrent, may start another download if it hasn't been started. + * @param tc The TorrentInterface + */ + void stop(kt::TorrentInterface* tc, bool user = false); + + /** + * Enqueue/Dequeue function. Places a torrent in queue. + * If the torrent is already in queue this will remove it from queue. + * @param tc TorrentControl pointer. + */ + void queue(kt::TorrentInterface* tc); + + /** + * A torrent is about to be started. We will do some file checks upon this signal. + * @param tc The TorrentInterface + */ + void aboutToBeStarted(kt::TorrentInterface* tc,bool & ret); + + /** + * User tried to enqueue a torrent that has reached max share ratio. + * Emits appropriate signal. + */ + void enqueueTorrentOverMaxRatio(kt::TorrentInterface* tc); + + /** + * Do a data check on a torrent + * @param tc + */ + void doDataCheck(kt::TorrentInterface* tc); + + ///Fires when disk space is running low + void onLowDiskSpace(kt::TorrentInterface* tc, bool stopped); + +signals: + /** + * TorrentCore torrents have beed updated. Stats are changed. + **/ + void statsUpdated(); + + /** + * Emitted when a torrent has reached it's max share ratio. + * @param tc The torrent + */ + void maxShareRatioReached(kt::TorrentInterface* tc); + + /** + * Emitted when a torrent has reached it's max seed time + * @param tc The torrent + */ + void maxSeedTimeReached(kt::TorrentInterface* tc); + + /** + * Corrupted data has been detected. + * @param tc The torrent with the corrupted data + */ + void corruptedData(kt::TorrentInterface* tc); + + /** + * User tried to enqueue a torrent that has reached max share ratio. It's not possible. + * Signal should be connected to SysTray slot which shows appropriate KPassivePopup info. + * @param tc The torrent in question. + */ + void queuingNotPossible(kt::TorrentInterface* tc); + + /** + * Emitted when a torrent cannot be started + * @param tc The torrent + * @param reason The reason + */ + void canNotStart(kt::TorrentInterface* tc,kt::TorrentStartResponse reason); + + /** + * Diskspace is running low. + * Signal should be connected to SysTray slot which shows appropriate KPassivePopup info. + * @param tc The torrent in question. + */ + void lowDiskSpace(kt::TorrentInterface* tc, bool stopped); + +private: + void rollback(const QPtrList<kt::TorrentInterface> & success); + void connectSignals(kt::TorrentInterface* tc); + bool init(bt::TorrentControl* tc,bool silently); + +private slots: + void torrentFinished(kt::TorrentInterface* tc); + void slotStoppedByError(kt::TorrentInterface* tc, QString msg); + void torrentSeedAutoStopped(kt::TorrentInterface* tc,kt::AutoStopReason reason); + void downloadFinished(KIO::Job *job); + void downloadFinishedSilently(KIO::Job *job); + void emitCorruptedData(kt::TorrentInterface* tc); + +private: + QString data_dir; + int max_downloads; + bool keep_seeding; + QTimer update_timer; + bt::Uint64 removed_bytes_up,removed_bytes_down; + kt::PluginManager* pman; + bt::QueueManager* qman; + kt::GroupManager* gman; + QMap<KIO::Job*,KURL> custom_save_locations; // map to store save locations +}; + +#endif diff --git a/apps/ktorrent/ktorrentdcop.cpp b/apps/ktorrent/ktorrentdcop.cpp new file mode 100644 index 0000000..592f74d --- /dev/null +++ b/apps/ktorrent/ktorrentdcop.cpp @@ -0,0 +1,254 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <kurl.h> +#include "ktorrentdcop.h" +#include "ktorrent.h" +#include "ktorrentcore.h" +#include "settings.h" +#include <torrent/ipblocklist.h> + +KTorrentDCOP::KTorrentDCOP(KTorrent* app) + : DCOPObject("KTorrent"),app(app) +{} + + +KTorrentDCOP::~KTorrentDCOP() +{} + + +bool KTorrentDCOP::changeDataDir(const QString& new_dir) +{ + Settings::setTempDir(new_dir); + Settings::writeConfig(); + return app->getCore().changeDataDir(new_dir); +} + +void KTorrentDCOP::openTorrent(const QString& file) +{ + app->load(KURL::fromPathOrURL(file)); +} + +void KTorrentDCOP::openTorrentSilently(const QString & file) +{ + app->loadSilently(KURL::fromPathOrURL(file)); +} + +void KTorrentDCOP::setKeepSeeding(bool ks) +{ + Settings::setKeepSeeding(ks); + Settings::writeConfig(); + app->applySettings(); +} + +void KTorrentDCOP::setMaxConnectionsPerDownload(int max) +{ + Settings::setMaxConnections(max); + Settings::writeConfig(); + app->applySettings(); +} + +void KTorrentDCOP::setMaxDownloads(int max) +{ + Settings::setMaxDownloads(max); + Settings::writeConfig(); + app->applySettings(); +} + +void KTorrentDCOP::setMaxSeeds(int max) +{ + Settings::setMaxSeeds(max); + Settings::writeConfig(); + app->applySettings(); +} + +void KTorrentDCOP::setMaxUploadSpeed(int kbytes_per_sec) +{ + Settings::setMaxUploadRate(kbytes_per_sec); + Settings::writeConfig(); + app->applySettings(); +} + +void KTorrentDCOP::setMaxDownloadSpeed(int kbytes_per_sec) +{ + Settings::setMaxDownloadRate(kbytes_per_sec); + Settings::writeConfig(); + app->applySettings(); +} + +void KTorrentDCOP::setShowSysTrayIcon(bool yes) +{ + Settings::setShowSystemTrayIcon(yes); + Settings::writeConfig(); + app->applySettings(); +} + +void KTorrentDCOP::startAll(int type) +{ + app->getCore().startAll(type); +} + +void KTorrentDCOP::stopAll(int type) +{ + app->getCore().stopAll(type); +} + +void KTorrentDCOP::start(int tornumber) +{ + kt::TorrentInterface* tc = app->getCore().getTorFromNumber(tornumber); + if(tc) + app->getCore().start(tc); +} + +void KTorrentDCOP::stop(int tornumber, bool user) +{ + kt::TorrentInterface* tc = app->getCore().getTorFromNumber(tornumber); + if(tc) + app->getCore().stop(tc, user); +} + +QValueList<int> KTorrentDCOP::getTorrentNumbers(int type) +{ + return app->getCore().getTorrentNumbers(type); +} + +QCStringList KTorrentDCOP::getTorrentInfo(int tornumber) +{ + QCStringList torrentinfo; + kt::TorrentInterface* tc = app->getCore().getTorFromNumber(tornumber); + if(tc) + torrentinfo = app->getTorrentInfo(tc); + return torrentinfo; +} + + +QCStringList KTorrentDCOP::getInfo() +{ + QCStringList info; + QString thisinfo = app->getStatusInfo(); + info.append(thisinfo.ascii()); + thisinfo = app->getStatusTransfer(); + info.append(thisinfo.ascii()); + thisinfo = app->getStatusSpeed(); + info.append(thisinfo.ascii()); + thisinfo = app->getStatusDHT(); + info.append(thisinfo.ascii()); + return info; +} + +int KTorrentDCOP::getFileCount(int tornumber) +{ + return app->getCore().getFileCount(tornumber); +} + +QCStringList KTorrentDCOP::getFileNames(int tornumber) +{ + return app->getCore().getFileNames(tornumber); +} + +QValueList<int> KTorrentDCOP::getFilePriorities(int tornumber) +{ + return app->getCore().getFilePriorities(tornumber); +} + +void KTorrentDCOP::setFilePriority(int tornumber, + int index, int priority) +{ + kt::TorrentInterface* tc = app->getCore().getTorFromNumber(tornumber); + if(tc) + app->getCore().setFilePriority(tc, index, priority); +} + +void KTorrentDCOP::remove(int tornumber, bool del_data) +{ + kt::TorrentInterface* tc = app->getCore().getTorFromNumber(tornumber); + if(tc) + app->getCore().remove(tc, del_data); +} + +void KTorrentDCOP::announce(int tornumber) +{ + app->getCore().announceByTorNum(tornumber); +} + +QCString KTorrentDCOP::dataDir() +{ + QCString dir = Settings::tempDir().ascii(); + return dir; +} + +int KTorrentDCOP::maxDownloads() +{ + return Settings::maxDownloads(); +} + +int KTorrentDCOP::maxSeeds() +{ + return Settings::maxSeeds(); +} + +int KTorrentDCOP::maxConnections() +{ + return Settings::maxConnections(); +} + +int KTorrentDCOP::maxUploadRate() +{ + return Settings::maxUploadRate(); +} + +int KTorrentDCOP::maxDownloadRate() +{ + return Settings::maxDownloadRate(); +} + +bool KTorrentDCOP::keepSeeding() +{ + return Settings::keepSeeding(); +} + +bool KTorrentDCOP::showSystemTrayIcon() +{ + return Settings::showSystemTrayIcon(); +} + +QValueList<int> KTorrentDCOP::intSettings() +{ + QValueList<int> intsettings; + intsettings.append(Settings::maxDownloads()); + intsettings.append(Settings::maxSeeds()); + intsettings.append(Settings::maxConnections()); + intsettings.append(Settings::maxUploadRate()); + intsettings.append(Settings::maxDownloadRate()); + intsettings.append((int)Settings::keepSeeding()); + intsettings.append((int)Settings::showSystemTrayIcon()); + return intsettings; +} + +bool KTorrentDCOP::isBlockedIP(QString ip) +{ + return bt::IPBlocklist::instance().isBlocked(ip); +} + +void KTorrentDCOP::openTorrentSilentlyDir(const QString & file, const QString & savedir) +{ + app->loadSilentlyDir(KURL::fromPathOrURL(file), KURL::fromPathOrURL(savedir)); +} + +#include "ktorrentdcop.moc" diff --git a/apps/ktorrent/ktorrentdcop.h b/apps/ktorrent/ktorrentdcop.h new file mode 100644 index 0000000..287e191 --- /dev/null +++ b/apps/ktorrent/ktorrentdcop.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTORRENTDCOP_H +#define KTORRENTDCOP_H + +#include "dcopinterface.h" + +class KTorrent; + +/** +@author Joris Guisson +*/ +class KTorrentDCOP : public QObject,virtual public DCOPInterface +{ + Q_OBJECT + KTorrent* app; +public: + KTorrentDCOP(KTorrent* app); + ~KTorrentDCOP(); + + virtual bool changeDataDir(const QString& new_dir); + virtual void openTorrent(const QString& file); + virtual void openTorrentSilently(const QString & file); + virtual void setKeepSeeding(bool ks); + virtual void setMaxConnectionsPerDownload(int max); + virtual void setMaxDownloads(int max); + virtual void setMaxSeeds(int max); + virtual void setMaxUploadSpeed(int kbytes_per_sec); + virtual void setMaxDownloadSpeed(int kbytes_per_sec); + virtual void setShowSysTrayIcon(bool yes); + virtual void startAll(int type = 3); + virtual void stopAll(int type = 3); + virtual QValueList<int> getTorrentNumbers(int type = 3); + virtual QCStringList getTorrentInfo(int tornumber); + virtual int getFileCount(int tornumber); + virtual QCStringList getInfo(); + virtual QCStringList getFileNames(int tornumber); + virtual QValueList<int> getFilePriorities(int tornumber); + virtual void setFilePriority(int tornumber, int index, int priority); + virtual void start(int tornumber); + virtual void stop(int tornumber, bool user); + virtual void remove(int tornumber, bool del_data); + virtual void announce(int tornumber); + virtual QCString dataDir(); + virtual int maxDownloads(); + virtual int maxSeeds(); + virtual int maxConnections(); + virtual int maxUploadRate(); + virtual int maxDownloadRate(); + virtual bool keepSeeding(); + virtual bool showSystemTrayIcon(); + virtual QValueList<int> intSettings(); + virtual bool isBlockedIP(QString ip); + virtual void openTorrentSilentlyDir(const QString & file, const QString & savedir); + +}; + +#endif diff --git a/apps/ktorrent/ktorrentplugin.desktop b/apps/ktorrent/ktorrentplugin.desktop new file mode 100644 index 0000000..40cfe9c --- /dev/null +++ b/apps/ktorrent/ktorrentplugin.desktop @@ -0,0 +1,33 @@ +[Desktop Entry] +Type=ServiceType +X-KDE-ServiceType=KTorrent/Plugin +Name=KTorrent Plugin +Name[ar]=قابس KTorrent +Name[bg]=Приставка за KTorrent +Name[br]=Lugent KTorrent +Name[ca]=Connector KTorrent +Name[cs]=KTorrent modul +Name[da]=KTorrent-plugin +Name[de]=KTorrent-Modul +Name[el]=Πρόσθετο KTorrent +Name[es]=Complemento de KTorrent +Name[et]=KTorrenti plugin +Name[fa]=وصلۀ KTorrent +Name[gl]=Plugin KTorrent +Name[it]=Plugin KTorrent +Name[ja]=KTorrent プラグイン +Name[ka]=KTorrent-ის მოდული +Name[nb]=KTorrent-modul +Name[nds]=KTorrent-Moduul +Name[nl]=KTorrent-plugin +Name[pl]=Wtyczka KTorrent +Name[pt]='Plugin' do KTorrent +Name[pt_BR]=Plugin KTorrent +Name[sr]=KTorrent прикључак +Name[sr@Latn]=KTorrent priključak +Name[sv]=Ktorrent-insticksprogram +Name[tr]=KTorrent Eklentisi +Name[uk]=Втулок KTorrent +Name[xx]=xxKTorrent Pluginxx +Name[zh_CN]=KTorrent 插件 +Name[zh_TW]=KTorrent 外掛程式 diff --git a/apps/ktorrent/ktorrentui.rc b/apps/ktorrent/ktorrentui.rc new file mode 100644 index 0000000..a5845a1 --- /dev/null +++ b/apps/ktorrent/ktorrentui.rc @@ -0,0 +1,44 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="ktorrent" version="1"> +<MenuBar> + <Menu name="file"><text>&File</text> + <Action name="paste_url"/> + <Action name="ipfilter_action"/> + <Merge/> + </Menu> + <Menu name="Downloads"><text>Downloads</text> + <Action name="Start" /> + <Action name="Stop" /> + <Action name="Remove" /> + <Separator/> + <Action name="Start all"/> + <Action name="Stop all"/> + <Separator/> + <Action name="check_data"/> + <Separator/> + <Action name="queue_action"/> + <Action name="Queue manager"/> + </Menu> +</MenuBar> + +<ToolBar name="mainToolBar" noMerge="1"><text>Main Toolbar</text> + <Action name="file_new"/> + <Action name="file_open"/> + <Action name="file_save"/> + <Separator/> + <Action name="edit_copy"/> + <Action name="edit_paste"/> + <Separator/> + <Action name="ipfilter_action"/> +</ToolBar> +<ToolBar name="DownloadToolBar" noMerge="1"><text>Download Toolbar</text> + <Action name="Start"/> + <Action name="Stop"/> + <Action name="Remove"/> + <Action name="Start all"/> + <Action name="Stop all"/> + <Action name="queue_action"/> + <Separator/> + <Action name="Queue manager"/> +</ToolBar> +</kpartgui> diff --git a/apps/ktorrent/ktorrentview.cpp b/apps/ktorrent/ktorrentview.cpp new file mode 100644 index 0000000..d1b41c5 --- /dev/null +++ b/apps/ktorrent/ktorrentview.cpp @@ -0,0 +1,912 @@ +/*************************************************************************** + * Copyright (C) 2005,2006 by * + * Joris Guisson <joris.guisson@gmail.com> * + * Ivan Vasic <ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <klocale.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kpopupmenu.h> +#include <krun.h> +#include <kurl.h> +#include <kurldrag.h> +#include <kmessagebox.h> +#include <kstdguiitem.h> +#include <kfiledialog.h> + +#include <interfaces/torrentinterface.h> +#include <torrent/globals.h> +#include <util/log.h> +#include <util/functions.h> + +#include <groups/group.h> +#include <groups/torrentdrag.h> + +#include <qcursor.h> +#include <qheader.h> +#include <qvaluelist.h> +#include <qlayout.h> + +#include "ktorrentview.h" +#include "ktorrentviewitem.h" +#include "settings.h" +#include "scandialog.h" +#include "addpeerwidget.h" +#include "ktorrentviewmenu.h" +#include "speedlimitsdlg.h" +#include "filterbar.h" + +using namespace bt; +using namespace kt; + + +TorrentView::TorrentView(KTorrentView* parent) : KListView(parent),ktview(parent) +{} + +TorrentView::~TorrentView() +{} + +bool TorrentView::eventFilter(QObject* watched, QEvent* e) +{ + if((QHeader*)watched == header()) + { + switch(e->type()) + { + case QEvent::MouseButtonPress: + { + if(static_cast<QMouseEvent *>(e)->button() == RightButton) + ktview->m_headerMenu->popup(QCursor::pos()); + + break; + } + default: + break; + } + } + + return KListView::eventFilter(watched, e); +} + +KTorrentView::KTorrentView(QWidget *parent) + : QWidget(parent),menu(0),current_group(0),running(0),total(0),view(0),filter_bar(0) +{ + QVBoxLayout* layout = new QVBoxLayout(this); + layout->setAutoAdd(true); + view = new TorrentView(this); + filter_bar = new FilterBar(this); + filter_bar->setHidden(true); + + setupColumns(); + + connect(view,SIGNAL(executed(QListViewItem* )), + this,SLOT(onExecuted(QListViewItem* ))); + + connect(view,SIGNAL(currentChanged(QListViewItem* )), + this,SLOT(onExecuted(QListViewItem* ))); + + connect(view,SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint& )), + this,SLOT(showContextMenu(KListView*, QListViewItem*, const QPoint& ))); + + connect(view,SIGNAL(selectionChanged()),this,SLOT(onSelectionChanged())); + + menu = new KTorrentViewMenu(this); + connect(menu,SIGNAL(groupItemActivated(const QString&)),this,SLOT(gsmItemActived(const QString&))); + + connect(m_headerMenu, SIGNAL(activated(int)), this, SLOT(onColumnVisibilityChange( int ))); + + view->setFrameShape(QFrame::NoFrame); +} + +KTorrentView::~KTorrentView() +{ +} + +void KTorrentView::insertColumn(QString label, Qt::AlignmentFlags align) +{ + m_headerMenu->insertItem(label); + + int ind = view->addColumn(label); + view->setColumnAlignment(ind, align); +} + +void KTorrentView::setupColumns() +{ + //Header menu + m_headerMenu = new KPopupMenu(view); + m_headerMenu->setCheckable(true); + m_headerMenu->insertTitle(i18n("Visible columns")); + + insertColumn(i18n("File"), Qt::AlignLeft); + insertColumn(i18n("Status"), Qt::AlignLeft); + insertColumn(i18n("Downloaded"), Qt::AlignRight); + insertColumn(i18n("Size"), Qt::AlignRight); + insertColumn(i18n("Uploaded"), Qt::AlignRight); + insertColumn(i18n("Down Speed"), Qt::AlignRight); + insertColumn(i18n("Up Speed"), Qt::AlignRight); + insertColumn(i18n("Time Left"), Qt::AlignCenter); + insertColumn(i18n("Seeders"), Qt::AlignRight); + insertColumn(i18n("Leechers"), Qt::AlignRight); + insertColumn(i18n("% Complete"), Qt::AlignRight); + insertColumn(i18n("Share Ratio"), Qt::AlignRight); + insertColumn(i18n("Time Downloaded"), Qt::AlignRight); + insertColumn(i18n("Time Seeded"), Qt::AlignRight); + + view->setAllColumnsShowFocus(true); + view->setShowSortIndicator(true); + view->setAcceptDrops(true); + view->setSelectionMode(QListView::Extended); + for (Uint32 i = 0;i < (Uint32)view->columns();i++) + { + view->setColumnWidth(i, 100); + view->setColumnWidthMode(i,QListView::Manual); + } +} + +void KTorrentView::setCurrentGroup(Group* group) +{ + if (current_group == group) + return; + + current_group = group; + + running = 0; + total = 0; + // go over the current items, if they still match keep them, else remove them + // add new itesm if necessary + QMap<TorrentInterface*,KTorrentViewItem*>::iterator i = items.begin(); + while (i != items.end()) + { + KTorrentViewItem* tvi = i.data(); + TorrentInterface* tc = i.key(); + if (current_group && !current_group->isMember(tc)) + { + if (tvi) + { + delete tvi; + i.data() = 0; + } + } + else if (!tvi) + { + tvi = new KTorrentViewItem(this,tc); + i.data() = tvi; + } + + if (i.data()) + { + total++; + if (tc->getStats().running) + running++; + } + + i++; + } + + if (current_group) + setCaption(QString("%1 %2/%3").arg(current_group->groupName()).arg(running).arg(total)); + else + setCaption(i18n("All Torrents %1/%2").arg(running).arg(total)); + + onSelectionChanged(); + onExecuted(view->currentItem()); +} + +void KTorrentView::saveSettings(KConfig* cfg,int idx) +{ + QString group = QString("KTorrentView-%1").arg(idx); + view->saveLayout(cfg,group); + cfg->setGroup(group); + filter_bar->saveSettings(cfg); +} + + +void KTorrentView::loadSettings(KConfig* cfg,int idx) +{ + QString group = QString("KTorrentView-%1").arg(idx); + view->restoreLayout(cfg,group); + view->setDragEnabled(true); + + for(int i=0; i < view->columns();++i) + { + bool visible = columnVisible(i); + + m_headerMenu->setItemChecked(m_headerMenu->idAt(i+1), visible); + view->header()->setResizeEnabled(visible, i); + } + cfg->setGroup(group); + filter_bar->loadSettings(cfg); +} + + +int KTorrentView::getNumRunning() +{ + int num = 0; + QMap<TorrentInterface*,KTorrentViewItem*>::iterator i = items.begin(); + while (i != items.end()) + { + KTorrentViewItem* tvi = i.data(); + if (tvi) + { + TorrentInterface* tc = tvi->getTC(); + num += tc->getStats().running ? 1 : 0; + } + i++; + } + return num; +} + +bool KTorrentView::startDownload(kt::TorrentInterface* tc) +{ + if (tc && !tc->getStats().running) + { + wantToStart(tc); + if (!tc->getStats().running && !tc->getStats().stopped_by_error) + { + if (tc->getStats().completed) + { + if (!tc->overMaxRatio() && !tc->overMaxSeedTime()) + return false; + } + else + return false; + } + } + return true; +} + +void KTorrentView::stopDownload(kt::TorrentInterface* tc) +{ + if (tc && tc->getStats().running) + { + wantToStop(tc,true); + } +} + +void KTorrentView::showStartError() +{ + QString err = i18n("Cannot start more than 1 download, ", + "Cannot start more than %n downloads, ",Settings::maxDownloads()); + + err += i18n("and 1 seed. ","and %n seeds. ",Settings::maxSeeds()); + err += i18n("Go to Settings -> Configure KTorrent, if you want to change the limits."); + KMessageBox::error(this,err); +} + +void KTorrentView::startDownloads() +{ + bool err = false; + + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + if (!startDownload(tc)) + err = true;; + } + + /* + if (err) + { + showStartError(); + } + */ + // make sure toolbuttons get updated + onSelectionChanged(); +} + +void KTorrentView::stopDownloads() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + stopDownload(kvi->getTC()); + } + + // make sure toolbuttons get updated + onSelectionChanged(); +} + +void KTorrentView::startAllDownloads() +{ + bool err = false; + QMap<TorrentInterface*,KTorrentViewItem*>::iterator i = items.begin(); + while (i != items.end()) + { + KTorrentViewItem* tvi = i.data(); + if (tvi && !startDownload(tvi->getTC())) + err = true; + + i++; + } + /* + if (err) + { + showStartError(); + } + */ + onSelectionChanged(); +} + +void KTorrentView::stopAllDownloads() +{ + QMap<TorrentInterface*,KTorrentViewItem*>::iterator i = items.begin(); + while (i != items.end()) + { + KTorrentViewItem* tvi = i.data(); + if (tvi) + stopDownload(tvi->getTC()); + + i++; + } + onSelectionChanged(); +} + +void KTorrentView::removeDownloads() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + bool dummy = false; + if (tc && !tc->isCheckingData(dummy)) + { + const TorrentStats & s = tc->getStats(); + bool data_to = false; + if (!s.completed) + { + QString msg = i18n("The torrent %1 has not finished downloading, " + "do you want to delete the incomplete data, too?").arg(s.torrent_name); + int ret = KMessageBox::questionYesNoCancel( + this,msg,i18n("Remove Download"), + i18n("Delete Data"),i18n("Keep Data")); + if (ret == KMessageBox::Cancel) + return; + else if (ret == KMessageBox::Yes) + data_to = true; + } + wantToRemove(tc,data_to); + } + } + + // make sure toolbuttons get updated + onSelectionChanged(); +} + +void KTorrentView::removeDownloadsAndData() +{ + QString msg = i18n("You will lose all the downloaded data. Are you sure you want to do this?"); + // TODO: replace i18n("Remove") by KStdGuiItem::remove() in KDE4 + if (KMessageBox::warningYesNo(this,msg, i18n("Remove Torrent"), i18n("&Remove"), + KStdGuiItem::cancel()) == KMessageBox::No) + return; + + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + if (tc) + wantToRemove(tc,true); + } + + // make sure toolbuttons get updated + onSelectionChanged(); +} + +void KTorrentView::manualAnnounce() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + if (tc && tc->getStats().running) + tc->updateTracker(); + } +} + +void KTorrentView::previewFiles() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + if (tc && tc->readyForPreview() && !tc->getStats().multi_file_torrent) + { + QFileInfo fi(tc->getTorDir()+"cache"); + new KRun(KURL::fromPathOrURL(fi.readLink()), 0, true, true); + } + } +} + +TorrentInterface* KTorrentView::getCurrentTC() +{ + KTorrentViewItem* tvi = dynamic_cast<KTorrentViewItem*>(view->currentItem()); + if (tvi) + return tvi->getTC(); + else + return 0; +} + +void KTorrentView::onExecuted(QListViewItem* item) +{ + KTorrentViewItem* tvi = dynamic_cast<KTorrentViewItem*>(item); + if (tvi) + { + torrentClicked(tvi->getTC()); + currentChanged(tvi->getTC()); + } + else + { + currentChanged(0); + } +} + +void KTorrentView::showContextMenu(KListView* ,QListViewItem*,const QPoint & p) +{ + updateGroupsSubMenu(menu->getGroupsSubMenu()); + menu->show(p); +} + +void KTorrentView::addTorrent(TorrentInterface* tc) +{ + if (current_group && !current_group->isMember(tc)) + { + items.insert(tc,0); + } + else + { + KTorrentViewItem* tvi = new KTorrentViewItem(this,tc); + items.insert(tc,tvi); + tvi->update(); + if (items.count() == 1) + currentChanged(tc); + } +} + +void KTorrentView::removeTorrent(TorrentInterface* tc) +{ + QMap<kt::TorrentInterface*,KTorrentViewItem*>::iterator i = items.find(tc); + if (i != items.end()) + { + KTorrentViewItem* tvi = i.data(); + items.erase(i); + delete tvi; + tvi = dynamic_cast<KTorrentViewItem*>(view->currentItem()); + if (tvi) + currentChanged(tvi->getTC()); + else + currentChanged(0); + } +} + + +void KTorrentView::update() +{ + Uint32 r = 0; + Uint32 t = 0; + + QMap<kt::TorrentInterface*,KTorrentViewItem*>::iterator i = items.begin(); + while (i != items.end()) + { + bool count = true; + KTorrentViewItem* tvi = i.data(); + if (tvi) + tvi->update(); + // check if the torrent still is part of the group + kt::TorrentInterface* ti = i.key(); + + bool member = (current_group->isMember(ti) && filter_bar->matchesFilter(ti)); + + if (tvi && current_group && !member) + { + // torrent is no longer a member of this group so remove it from the view + delete tvi; + i.data() = 0; + count = false; + } + else if (!tvi && (!current_group || member)) + { + tvi = new KTorrentViewItem(this,ti); + i.data() = tvi; + } + + if (i.data()) + { + t++; + if (ti->getStats().running) + r++; + } + + i++; + } + + if (running != r || total != t) + { + running = r; + total = t; + + if (current_group) + setCaption(QString("%1 %2/%3").arg(current_group->groupName()).arg(running).arg(total)); + else + setCaption(i18n("All Torrents %1/%2").arg(running).arg(total)); + onSelectionChanged(); + } + + view->sort(); +} + +bool KTorrentView::acceptDrag(QDropEvent* event) const +{ + // accept uri drops only + return KURLDrag::canDecode(event); +} + +void KTorrentView::onSelectionChanged() +{ + int flags = 0; + + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + bool dummy; + if (tc && !tc->isCheckingData(dummy)) + { + const TorrentStats & s = tc->getStats(); + if (!s.running) + flags |= START; + else + flags |= STOP; + + if (flags & (START|STOP)) + break; + } + } + + if (sel.count() > 0) + flags |= REMOVE; + + if (sel.count() == 1) + flags |= SCAN; + + if (running > 0) + flags |= STOP_ALL; + + if (running == 0 && total > 0) + flags |= START_ALL; + + updateActions(flags); +} + +void KTorrentView::queueSlot() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + bool dummy; + if (tc && !tc->isCheckingData(dummy)) + emit queue(tc); + } +} + + +void KTorrentView::checkDataIntegrity() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + if (sel.count() == 0) + return; + + bool dummy = false; + KTorrentViewItem* kvi = (KTorrentViewItem*)sel.first(); + TorrentInterface* tc = kvi->getTC(); + if (!tc->isCheckingData(dummy)) + { + needsDataCheck(tc); + } + else + { + KMessageBox::error(0,i18n("You are already checking the data of the torrent %1 !").arg(tc->getStats().torrent_name)); + } +} + +QDragObject* KTorrentView::dragObject() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + if (sel.count() == 0) + return 0; + + return new TorrentDrag(this); +} + +void KTorrentView::getSelection(QValueList<kt::TorrentInterface*> & sel) +{ + QPtrList<QListViewItem> s = view->selectedItems(); + if (s.count() == 0) + return; + + QPtrList<QListViewItem>::iterator i = s.begin(); + while (i != s.end()) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*i; + TorrentInterface* tc = kvi->getTC(); + sel.append(tc); + i++; + } +} + +void KTorrentView::removeFromGroup() +{ + QPtrList<QListViewItem> s = view->selectedItems(); + if (s.count() == 0 || !current_group || current_group->isStandardGroup()) + return; + + QPtrList<QListViewItem>::iterator i = s.begin(); + while (i != s.end()) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*i; + TorrentInterface* tc = kvi->getTC(); + current_group->removeTorrent(tc); + delete kvi; + items[tc] = 0; + i++; + } +} + +void KTorrentView::addSelectionToGroup(kt::Group* g) +{ + QPtrList<QListViewItem> s = view->selectedItems(); + if (s.count() == 0 || !g) + return; + + QPtrList<QListViewItem>::iterator i = s.begin(); + while (i != s.end()) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*i; + TorrentInterface* tc = kvi->getTC(); + g->addTorrent(tc); + i++; + } +} + +void KTorrentView::showAddPeersWidget() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + bool dummy; + if (tc && !tc->isCheckingData(dummy)) + { + AddPeerWidget dlg(tc, this); + dlg.exec(); + } + } +} + +void KTorrentView::openOutputDirectory() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + if (tc) + { + if(tc->getStats().multi_file_torrent) + new KRun(KURL::fromPathOrURL(tc->getStats().output_path), 0, true, true); + else + new KRun(KURL::fromPathOrURL(tc->getDataDir()), 0, true, true); + } + } +} + +void KTorrentView::openTorXDirectory() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + if (tc) + { + new KRun(KURL::fromPathOrURL(tc->getTorDir()), 0, true, true); + } + } +} + +void KTorrentView::setDownloadLocationSlot() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + if (tc) + { + QString dn; + dn = KFileDialog::getExistingDirectory(tc->getStats().output_path, this, i18n("Choose download location for %1").arg(tc->getStats().torrent_name)); + + if(dn.isNull() || dn.isEmpty()) + continue; + + if(!dn.endsWith(bt::DirSeparator())) + dn += bt::DirSeparator(); + + if(!dn.isEmpty()) + tc->changeOutputDir(dn); + } + } +} + +void KTorrentView::dhtSlot() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + bool dummy; + if (tc && !tc->isCheckingData(dummy)) + { + bool on = tc->isFeatureEnabled(kt::DHT_FEATURE); + tc->setFeatureEnabled(kt::DHT_FEATURE,!on); + } + } +} + +void KTorrentView::utPexSlot() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + bool dummy; + if (tc && !tc->isCheckingData(dummy)) + { + bool on = tc->isFeatureEnabled(kt::UT_PEX_FEATURE); + tc->setFeatureEnabled(kt::UT_PEX_FEATURE,!on); + } + } +} + +void KTorrentView::speedLimits() +{ + QPtrList<QListViewItem> sel = view->selectedItems(); + if (sel.count() != 1) + return; + + KTorrentViewItem* kvi = (KTorrentViewItem*)sel.first(); + TorrentInterface* tc = kvi->getTC(); + SpeedLimitsDlg dlg(tc,0); + dlg.show(); + dlg.exec(); +} + + +void KTorrentView::columnHide(int index) +{ + view->hideColumn(index); + view->header()->setResizeEnabled(FALSE, index); +} + +void KTorrentView::columnShow(int index) +{ + view->setColumnWidth(index, 100); + view->header()->setResizeEnabled(TRUE, index); +} + +bool KTorrentView::columnVisible(int index) +{ + if (index < view->columns() && index >= 0) + return view->columnWidth(index) != 0; + else + return true; +} + +void KTorrentView::onColumnVisibilityChange(int id) +{ + int mid = m_headerMenu->indexOf(id) - 1; + if(mid == -1) + return; + + bool visible = !columnVisible(mid); + + m_headerMenu->setItemChecked(id, visible); + + if(visible) + columnShow(mid); + else + columnHide(mid); +} + +void KTorrentView::gsmItemActived(const QString & group) +{ + groupsSubMenuItemActivated(this,group); +} + +void KTorrentView::updateCaption() +{ + Uint32 r = 0; + Uint32 t = 0; + QMap<kt::TorrentInterface*,KTorrentViewItem*>::iterator i = items.begin(); + while (i != items.end()) + { + if (!current_group || current_group->isMember(i.key())) + { + t++; + if (i.key()->getStats().running) + r++; + } + + i++; + } + + if (running != r || total != t) + { + running = r; + total = t; + + if (current_group) + setCaption(QString("%1 %2/%3").arg(current_group->groupName()).arg(running).arg(total)); + else + setCaption(i18n("All Torrents %1/%2").arg(running).arg(total)); + } +} + +void KTorrentView::setupViewColumns() +{ + if (current_group->groupFlags() == kt::Group::UPLOADS_ONLY_GROUP) + { + // we are an uploads group so lets hide, downloaded, percentage, download speed and time left + columnHide(2); // Downloaded + columnHide(5); // Down speed + columnHide(7); // Time left + columnHide(10); // Percentage + } + else if (current_group->groupFlags() == kt::Group::DOWNLOADS_ONLY_GROUP) + { + columnHide(13); // Seed time is not necessary for a download + } + + // make sure menu is OK + for(int i=0; i< view->columns();++i) + { + bool visible = columnVisible(i); + m_headerMenu->setItemChecked(m_headerMenu->idAt(i+1), visible); + view->header()->setResizeEnabled(visible, i); + } +} + + + +void KTorrentView::toggleFilterBar() +{ + filter_bar->setHidden(!filter_bar->isHidden()); +} + +#include "ktorrentview.moc" diff --git a/apps/ktorrent/ktorrentview.h b/apps/ktorrent/ktorrentview.h new file mode 100644 index 0000000..218b0b0 --- /dev/null +++ b/apps/ktorrent/ktorrentview.h @@ -0,0 +1,216 @@ +/*************************************************************************** + * Copyright (C) 2005 by * + * Joris Guisson <joris.guisson@gmail.com> * + * Ivan Vasic <ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 _KTORRENTVIEW_H_ +#define _KTORRENTVIEW_H_ + +#include <klistview.h> + +typedef QValueList<QCString> QCStringList; + +class KURL; +class KTorrentViewItem; +class KPopupMenu; +class KTorrentCore; +class KTorrentViewMenu; +class KTorrentView; +class ScanDialog; +class QString; +class FilterBar; + +namespace kt +{ + class TorrentInterface; + class Group; +} + +using namespace bt; + +class TorrentView : public KListView +{ +public: + TorrentView(KTorrentView* parent); + virtual ~TorrentView(); + + virtual bool eventFilter(QObject* watched, QEvent* e); + +private: + KTorrentView* ktview; +}; + + + + +/** + * List view which shows information about torrents. + */ +class KTorrentView : public QWidget +{ + Q_OBJECT +public: + enum ActionEnableFlags + { + START = 1, + STOP = 2, + START_ALL = 4, + STOP_ALL = 8, + REMOVE = 16, + SCAN = 32 + }; + + /** + * Default constructor + */ + KTorrentView(QWidget *parent); + + /** + * Destructor + */ + virtual ~KTorrentView(); + + /// Update the caption, so the correct number of running torrents is shown in the tab + void updateCaption(); + + /// Trigger an updateActions signal + void updateActions() {onSelectionChanged();} + + /// Get the current group + const kt::Group* getCurrentGroup() const {return current_group;} + + /// Get the current TorrentInterface object + kt::TorrentInterface* getCurrentTC(); + + /// Save the views settings + void saveSettings(KConfig* cfg,int idx); + + /// Load the views settings + void loadSettings(KConfig* cfg,int idx); + + /** + * Put the current selection in a list. + * @param sel The list to put it in + */ + void getSelection(QValueList<kt::TorrentInterface*> & sel); + + /** + * Add the current selection to a group. + * @param g The group + */ + void addSelectionToGroup(kt::Group* g); + + /** + * Is column visible? + */ + bool columnVisible(int index); + + /** + * Setup the view columns, based upon the current group + * This will hide some columns for uploads only groups. + */ + void setupViewColumns(); + + QPtrList<QListViewItem> selectedItems() {return view->selectedItems();} + + KListView* listView() {return view;} + + /** + * Toggle the visibility of the filter bar + */ + void toggleFilterBar(); + +public slots: + void setCurrentGroup(kt::Group* group); + void addTorrent(kt::TorrentInterface* tc); + void removeTorrent(kt::TorrentInterface* tc); + void update(); + void startDownloads(); + void stopDownloads(); + void startAllDownloads(); + void stopAllDownloads(); + void manualAnnounce(); + void previewFiles(); + void removeDownloads(); + void removeDownloadsAndData(); + void onSelectionChanged(); + void queueSlot(); + void checkDataIntegrity(); + void removeFromGroup(); + void showAddPeersWidget(); + void openOutputDirectory(); + void openTorXDirectory(); + void setDownloadLocationSlot(); + void dhtSlot(); + void utPexSlot(); + void speedLimits(); + +private slots: + void onExecuted(QListViewItem* item); + void showContextMenu(KListView* ,QListViewItem* item,const QPoint & p); + void onColumnVisibilityChange(int); + void gsmItemActived(const QString & group); + + +signals: + void torrentClicked(kt::TorrentInterface* tc); + void currentChanged(kt::TorrentInterface* tc); + void wantToRemove(kt::TorrentInterface* tc,bool data_to); + void wantToStop(kt::TorrentInterface* tc,bool user); + void wantToStart(kt::TorrentInterface* tc); + void viewChange(kt::TorrentInterface* tc); + + /** + * Emit that actions need to be updated + * @param flags OR of ActionEnableFlags + */ + void updateActions(int flags); + void queue(kt::TorrentInterface* tc); + void needsDataCheck(kt::TorrentInterface* tc); + void updateGroupsSubMenu(KPopupMenu* gsm); + void groupsSubMenuItemActivated(KTorrentView* v,const QString & group); + +private: + bool acceptDrag(QDropEvent* event) const; + int getNumRunning(); + bool startDownload(kt::TorrentInterface* tc); + void stopDownload(kt::TorrentInterface* tc); + void showStartError(); + virtual QDragObject* dragObject(); + void setupColumns(); + void insertColumn(QString label, Qt::AlignmentFlags); + void columnHide(int index); + void columnShow(int index); + + +private: + QMap<kt::TorrentInterface*,KTorrentViewItem*> items; + KTorrentViewMenu* menu; + KPopupMenu* m_headerMenu; + kt::Group* current_group; + Uint32 running; + Uint32 total; + TorrentView* view; + FilterBar* filter_bar; + + friend class TorrentView; +}; + +#endif // _KTORRENTVIEW_H_ diff --git a/apps/ktorrent/ktorrentviewitem.cpp b/apps/ktorrent/ktorrentviewitem.cpp new file mode 100644 index 0000000..d00e2f7 --- /dev/null +++ b/apps/ktorrent/ktorrentviewitem.cpp @@ -0,0 +1,354 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <klocale.h> +#include <kglobal.h> +#include <interfaces/torrentinterface.h> +#include <qdatetime.h> +#include <qpainter.h> +#include <math.h> +#include <interfaces/functions.h> +#include "ktorrentview.h" +#include "ktorrentviewitem.h" + +using namespace bt; +using namespace kt; +/* +static QString StatusToString(TorrentInterface* tc,TorrentStatus s) +{ + switch (s) + { + case kt::NOT_STARTED : + return i18n("Not started"); + case kt::COMPLETE : + return i18n("Completed"); + case kt::SEEDING : + return i18n("Seeding"); + case kt::DOWNLOADING: + return i18n("Downloading"); + case kt::STALLED: + return i18n("Stalled"); + case kt::STOPPED: + return i18n("Stopped"); + case kt::ERROR : + return i18n("Error: ") + tc->getShortErrorMessage(); + case kt::ALLOCATING_DISKSPACE: + return i18n("Allocating diskspace"); + } + return QString::null; +} +*/ + +static QColor StatusToColor(TorrentStatus s,const QColorGroup & cg) +{ + QColor green(40,205,40); + QColor yellow(255,174,0); + switch (s) + { + case kt::SEEDING : + case kt::DOWNLOADING: + case kt::ALLOCATING_DISKSPACE : + return green; + case kt::STALLED: + case kt::CHECKING_DATA: + return yellow; + case kt::ERROR : + return Qt::red; + case kt::NOT_STARTED : + case kt::STOPPED: + case kt::QUEUED: + case kt::DOWNLOAD_COMPLETE : + case kt::SEEDING_COMPLETE : + default: + return cg.text(); + } + return cg.text(); +} + +static QColor ratioToColor(float ratio) +{ + QColor green(40,205,40); + return ratio > 0.8 ? green : Qt::red; +} + +static double Percentage(const TorrentStats & s) +{ + if (s.bytes_left_to_download == 0) + { + return 100.0; + } + else + { + if (s.total_bytes_to_download == 0) + { + return 100.0; + } + else + { + double perc = 100.0 - ((double)s.bytes_left_to_download / s.total_bytes_to_download) * 100.0; + if (perc > 100.0) + perc = 100.0; + else if (perc > 99.9) + perc = 99.9; + else if (perc < 0.0) + perc = 0.0; + + return perc; + } + } +} + + + +KTorrentViewItem::KTorrentViewItem(KTorrentView* parent,TorrentInterface* tc) + : KListViewItem(parent->listView()),tc(tc) +{ + m_parent = parent; + update(); +} + + +KTorrentViewItem::~KTorrentViewItem() +{} + +QCStringList KTorrentViewItem::getTorrentInfo(kt::TorrentInterface* tc) +{ + QCStringList info; + const TorrentStats & s = tc->getStats(); + info.append(s.torrent_name.local8Bit()); + info.append(tc->statusToString().local8Bit()); + info.append(BytesToString(s.bytes_downloaded).local8Bit()); + info.append(BytesToString(s.total_bytes_to_download).local8Bit()); + info.append(BytesToString(s.bytes_uploaded).local8Bit()); + if (s.bytes_left_to_download == 0) + info.append(KBytesPerSecToString(0).local8Bit()); + else + info.append(KBytesPerSecToString(s.download_rate / 1024.0).local8Bit()); + + info.append(KBytesPerSecToString(s.upload_rate / 1024.0).local8Bit()); + if (s.bytes_left_to_download == 0) + { + info.append(QCString("")); + } + else if (s.running) + { + Uint32 secs = tc->getETA(); + if(secs == -1) + info.append(i18n("infinity").local8Bit()); + else + info.append(DurationToString(secs).local8Bit()); + } + else + { + info.append(i18n("infinity").local8Bit()); + } + + info.append(QString::number(s.num_peers).local8Bit()); + info.append(QString(KGlobal::locale()->formatNumber(Percentage(s),2) + " %").local8Bit()); + info.append(KGlobal::locale()->formatNumber(kt::ShareRatio(s),2).local8Bit()); + info.append(QString::number(s.seeders_connected_to).local8Bit()); + info.append(QString::number(s.leechers_connected_to).local8Bit()); + return info; +} + +void KTorrentViewItem::update() +{ + const TorrentStats & s = tc->getStats(); + + if(m_parent->columnVisible(0)) + setText(0,s.torrent_name); + + if(m_parent->columnVisible(1)) + setText(1,tc->statusToString()); + + if(m_parent->columnVisible(2)) + { + Uint64 nb = /*s.bytes_downloaded > s.total_bytes ? s.total_bytes : */s.bytes_downloaded; + setText(2,BytesToString(nb)); + } + + if(m_parent->columnVisible(3)) + setText(3,BytesToString(s.total_bytes_to_download)); + + if(m_parent->columnVisible(4)) + setText(4,BytesToString(s.bytes_uploaded)); + + if(m_parent->columnVisible(5)) + { + if (s.download_rate >= 103) // lowest "visible" speed, all below will be 0,0 Kb/s + { + if (s.bytes_left_to_download == 0) + setText(5,KBytesPerSecToString(0)); + else + setText(5,KBytesPerSecToString(s.download_rate / 1024.0)); + } + else + setText(5, ""); + } + + if(m_parent->columnVisible(6)) + { + if (s.upload_rate >= 103) // lowest "visible" speed, all below will be 0,0 Kb/s + setText(6,KBytesPerSecToString(s.upload_rate / 1024.0)); + else + setText(6, ""); + } + + if(m_parent->columnVisible(7)) + { + if (s.bytes_left_to_download == 0) + { + setText(7,QString::null); + eta = -1; + } + else if (s.running) + { + Uint32 secs = tc->getETA(); + if(secs == -1) + { + setText(7,QString("%1").arg(QChar(0x221E))); + eta = -2; + } + else + { + eta = secs; + setText(7,DurationToString(secs)); + } + } + else + { + setText(7,QString("%1").arg(QChar(0x221E))); + eta = -2; + } + } + if(m_parent->columnVisible(8)) + setText(8,QString::number(s.num_peers)); + + if(m_parent->columnVisible(8)) + { + setText(8,QString("%1 (%2)").arg(QString::number(s.seeders_connected_to)).arg(QString::number(s.seeders_total))); + } + + if(m_parent->columnVisible(9)) + { + setText(9,QString("%1 (%2)").arg(QString::number(s.leechers_connected_to)).arg(QString::number(s.leechers_total))); + } + + if(m_parent->columnVisible(10)) + { + setText(10,i18n("%1 %").arg(KGlobal::locale()->formatNumber(Percentage(s),2))); + } + + if(m_parent->columnVisible(11)) + { + float ratio = kt::ShareRatio(s); + setText(11,QString("%1").arg(KGlobal::locale()->formatNumber(ratio,2))); + } + + if (m_parent->columnVisible(12)) + { + Uint32 secs = tc->getRunningTimeDL(); + setText(12,secs > 0 ? DurationToString(secs) : ""); + } + + if (m_parent->columnVisible(13)) + { + Uint32 secs = tc->getRunningTimeUL() - tc->getRunningTimeDL(); + setText(13,secs > 0 ? DurationToString(secs) : ""); + } +} + + + +int KTorrentViewItem::compare(QListViewItem * i,int col,bool) const +{ + KTorrentViewItem* other = (KTorrentViewItem*)i; + TorrentInterface* otc = other->tc; + const TorrentStats & s = tc->getStats(); + const TorrentStats & os = otc->getStats(); + switch (col) + { + case 0: return QString::compare(s.torrent_name,os.torrent_name); + case 1: return QString::compare(tc->statusToString(),otc->statusToString()); + case 2: return CompareVal(s.bytes_downloaded,os.bytes_downloaded); + case 3: return CompareVal(s.total_bytes_to_download,os.total_bytes_to_download); + case 4: return CompareVal(s.bytes_uploaded,os.bytes_uploaded); + case 5: return CompareVal(s.download_rate,os.download_rate); + case 6: return CompareVal(s.upload_rate,os.upload_rate); + case 7: + if (eta == other->eta) + return 0; + else if (eta >= 0 && other->eta >= 0) + return CompareVal(eta,other->eta); + else if (eta == -1) // finsihed is minux one + return -1; + else if (other->eta == -1) + return 1; + else if (eta == -2) // infinity is minus 2 + return 1; + else if (other->eta == -2) + return -1; + else + return CompareVal(eta,other->eta); + case 8: return CompareVal(s.seeders_total,os.seeders_total); + case 9: return CompareVal(s.leechers_total,os.leechers_total); + case 10: + { + double perc = s.total_bytes_to_download == 0 ? 100.0 : ((double)s.bytes_downloaded / s.total_bytes_to_download) * 100.0; + if (perc > 100.0) + perc = 100.0; + double operc = os.total_bytes_to_download == 0 ? 100.0 : ((double)os.bytes_downloaded / os.total_bytes_to_download) * 100.0; + if (operc > 100.0) + operc = 100.0; + return CompareVal(perc,operc); + } + case 11: + { + float r1 = kt::ShareRatio(s); + float r2 = kt::ShareRatio(os); + return CompareVal(r1,r2); + } + case 12: + return CompareVal(tc->getRunningTimeDL(),otc->getRunningTimeDL()); + case 13: + { + Uint32 t = tc->getRunningTimeUL() - tc->getRunningTimeDL(); + Uint32 ot = otc->getRunningTimeUL() - otc->getRunningTimeDL(); + return CompareVal(t,ot); + } + } + + return 0; +} + +void KTorrentViewItem::paintCell(QPainter* p,const QColorGroup & cg, + int column,int width,int align) +{ + QColorGroup _cg( cg ); + QColor c = _cg.text(); + + if (column == 1) + _cg.setColor(QColorGroup::Text, StatusToColor(tc->getStats().status,cg)); + + if (column == 11) + _cg.setColor(QColorGroup::Text, ratioToColor(kt::ShareRatio(tc->getStats()))); + + + KListViewItem::paintCell(p,_cg,column,width,align); +} diff --git a/apps/ktorrent/ktorrentviewitem.h b/apps/ktorrent/ktorrentviewitem.h new file mode 100644 index 0000000..a49e868 --- /dev/null +++ b/apps/ktorrent/ktorrentviewitem.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTORRENTVIEWITEM_H +#define KTORRENTVIEWITEM_H + +#include <klistview.h> +#include <dcopclient.h> +#include <util/constants.h> + +namespace kt +{ + class TorrentInterface; +} + +class KTorrentView; + +/** + * @author Joris Guisson +*/ +class KTorrentViewItem : public KListViewItem +{ + kt::TorrentInterface* tc; + bt::Int64 eta; +public: + KTorrentViewItem(KTorrentView* parent,kt::TorrentInterface* tc); + virtual ~KTorrentViewItem(); + + kt::TorrentInterface* getTC() {return tc;} + void update(); + + static QCStringList getTorrentInfo(kt::TorrentInterface* tc); + +private: + int compare(QListViewItem * i,int col,bool ascending) const; + void paintCell(QPainter* p,const QColorGroup & cg,int column,int width,int align); + + KTorrentView* m_parent; + +}; + +#endif diff --git a/apps/ktorrent/ktorrentviewmenu.cpp b/apps/ktorrent/ktorrentviewmenu.cpp new file mode 100644 index 0000000..6ddafb2 --- /dev/null +++ b/apps/ktorrent/ktorrentviewmenu.cpp @@ -0,0 +1,217 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <kglobal.h> +#include <klocale.h> +#include <kiconloader.h> +#include <interfaces/torrentinterface.h> +#include <groups/group.h> +#include "ktorrentviewmenu.h" +#include "ktorrentviewitem.h" +#include "ktorrentview.h" + +using namespace kt; + +KTorrentViewMenu::KTorrentViewMenu (KTorrentView *parent, const char *name ) + : KPopupMenu ( parent, name ),view(parent) +{ + KIconLoader* iload = KGlobal::iconLoader(); + + stop_id = insertItem( + iload->loadIconSet("ktstop",KIcon::Small),i18n("to stop", "Stop"), + parent,SLOT(stopDownloads())); + + start_id = insertItem( + iload->loadIconSet("ktstart",KIcon::Small),i18n("to start", "Start"), + parent,SLOT(startDownloads())); + + remove_id = insertItem( + iload->loadIconSet("ktremove",KIcon::Small),i18n("Remove Torrent"), + parent,SLOT(removeDownloads())); + + remove_all_id = insertItem( + iload->loadIconSet("ktremove",KIcon::Small),i18n("Remove Torrent and Data"), + parent,SLOT(removeDownloadsAndData())); + + queue_id = insertItem( + iload->loadIconSet("player_playlist",KIcon::Small),i18n("Enqueue/Dequeue"), + parent,SLOT(queueSlot())); + + insertSeparator(); + + add_peer_id = insertItem( + iload->loadIconSet("add", KIcon::Small), i18n("Add Peers"), + parent, SLOT(showAddPeersWidget())); + + peer_sources_menu = new KPopupMenu(this); + peer_sources_id = insertItem(i18n("Additional Peer Sources"), peer_sources_menu); + peer_sources_menu->insertTitle(i18n("Torrent Peer Sources:")); + peer_sources_menu->setCheckable(true); + dht_id = peer_sources_menu->insertItem(i18n("DHT"), parent, SLOT(dhtSlot())); + ut_pex_id = peer_sources_menu->insertItem(i18n("Peer Exchange"), parent, SLOT(utPexSlot())); + + insertSeparator(); + + announce_id = insertItem( + iload->loadIconSet("apply",KIcon::Small),i18n("Manual Announce"), + parent,SLOT(manualAnnounce())); + + preview_id = insertItem( + iload->loadIconSet("frame_image",KIcon::Small),i18n("Preview"), + parent, SLOT(previewFiles())); + + insertSeparator(); + dirs_sub_menu = new KPopupMenu(this); + dirs_id = insertItem(i18n("Open Directory"), dirs_sub_menu); + outputdir_id = dirs_sub_menu->insertItem(iload->loadIconSet("folder",KIcon::Small), i18n("Data Directory"), + parent, SLOT(openOutputDirectory())); + torxdir_id = dirs_sub_menu->insertItem(iload->loadIconSet("folder",KIcon::Small), i18n("Temporary Directory"), + parent, SLOT(openTorXDirectory())); + + downloaddir_id = insertItem(i18n("Set Download Location"), parent, SLOT(setDownloadLocationSlot())); + + insertSeparator(); + remove_from_group_id = insertItem(i18n("Remove From Group"),parent, SLOT(removeFromGroup())); + groups_sub_menu = new KPopupMenu(this); + + add_to_group_id = insertItem(i18n("Add to Group"),groups_sub_menu); + + insertSeparator(); + scan_id = insertItem(i18n("Check Data Integrity"),parent, SLOT(checkDataIntegrity())); + + connect(groups_sub_menu,SIGNAL(activated(int)),this,SLOT(gsmItemActived(int))); + + traffic_lim_id = insertItem(i18n("Speed Limits"),parent,SLOT(speedLimits())); +} + + +KTorrentViewMenu::~KTorrentViewMenu() +{} + +void KTorrentViewMenu::gsmItemActived(int id) +{ + groupItemActivated(groups_sub_menu->text(id).remove('&')); +} + +void KTorrentViewMenu::show(const QPoint & p) +{ + bool en_start = false; + bool en_stop = false; + bool en_remove = false; + bool en_prev = false; + bool en_announce = false; + bool en_add_peer = false; + bool en_dirs = false; + bool en_peer_sources = false; + bool dummy = false; + + QPtrList<QListViewItem> sel = view->selectedItems(); + for (QPtrList<QListViewItem>::iterator itr = sel.begin(); itr != sel.end();itr++) + { + KTorrentViewItem* kvi = (KTorrentViewItem*)*itr; + TorrentInterface* tc = kvi->getTC(); + if (tc) + { + const TorrentStats & s = tc->getStats(); + + if (tc->readyForPreview() && !s.multi_file_torrent) + en_prev = true; + + if (!tc->isCheckingData(dummy)) + en_remove = true; + + if (!s.running) + { + if (!tc->isCheckingData(dummy)) + { + en_start = true; + } + } + else + { + if (!tc->isCheckingData(dummy)) + { + en_stop = true; + if (tc->announceAllowed()) + en_announce = true; + } + } + + if (!s.priv_torrent && !tc->isCheckingData(dummy)) + { + en_add_peer = true; + en_peer_sources = true; + } + } + } + + en_add_peer = en_add_peer && en_stop; + + setItemEnabled(start_id,en_start); + setItemEnabled(stop_id,en_stop); + setItemEnabled(remove_id,en_remove); + setItemEnabled(remove_all_id,en_remove); + setItemEnabled(preview_id,en_prev); + setItemEnabled(add_peer_id, en_add_peer); + setItemEnabled(announce_id,en_announce); + setItemEnabled(queue_id, en_remove); + + const kt::Group* current_group = view->getCurrentGroup(); + setItemEnabled(remove_from_group_id,current_group && !current_group->isStandardGroup()); + setItemEnabled(add_to_group_id,groups_sub_menu->count() > 0); + + if (sel.count() == 1) + { + //enable directories + en_dirs = true; + + KTorrentViewItem* kvi = (KTorrentViewItem*)sel.getFirst(); + TorrentInterface* tc = kvi->getTC(); + // no data check when we are preallocating diskspace + if (tc->getStats().status == kt::ALLOCATING_DISKSPACE || tc->isCheckingData(dummy)) + setItemEnabled(scan_id, false); + else + setItemEnabled(scan_id, true); + + //enable additional peer sources if torrent is not private + setItemEnabled(peer_sources_id, en_peer_sources); + + if (en_peer_sources) + { + peer_sources_menu->setItemChecked(dht_id, tc->isFeatureEnabled(kt::DHT_FEATURE)); + peer_sources_menu->setItemChecked(ut_pex_id, tc->isFeatureEnabled(kt::UT_PEX_FEATURE)); + } + } + else + { + setItemEnabled(scan_id,false); + + //disable peer source + setItemEnabled(peer_sources_id, false); + } + + setItemEnabled(dirs_id, en_dirs); + setItemEnabled(traffic_lim_id,sel.count() == 1); + setItemEnabled(add_to_group_id,sel.count() > 0); + setItemEnabled(downloaddir_id,sel.count() > 0); + + popup(p); +} + +#include "ktorrentviewmenu.moc" diff --git a/apps/ktorrent/ktorrentviewmenu.h b/apps/ktorrent/ktorrentviewmenu.h new file mode 100644 index 0000000..b1827e2 --- /dev/null +++ b/apps/ktorrent/ktorrentviewmenu.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 KTORRENTVIEWMENU_H +#define KTORRENTVIEWMENU_H + +#include <kpopupmenu.h> + +class KTorrentView; + +/** + @author Joris Guisson <joris.guisson@gmail.com> +*/ +class KTorrentViewMenu : public KPopupMenu +{ + Q_OBJECT +public: + KTorrentViewMenu(KTorrentView *parent, const char *name = 0 ); + virtual ~KTorrentViewMenu(); + + /// Show the menu at the given point + void show(const QPoint & p); + + /// Get the group sub menu + KPopupMenu* getGroupsSubMenu() {return groups_sub_menu;} + +public slots: + void gsmItemActived(int id); + +signals: + /// A item in the groups sub menu has been activated + void groupItemActivated(const QString & group); + +private: + KTorrentView* view; + KPopupMenu* groups_sub_menu; + KPopupMenu* dirs_sub_menu; + KPopupMenu* peer_sources_menu; + int stop_id; + int start_id; + int remove_id; + int remove_all_id; + int preview_id; + int announce_id; + int queue_id; + int scan_id; + int remove_from_group_id; + int add_to_group_id; + int add_peer_id; + int dirs_id; + int outputdir_id; + int torxdir_id; + int downloaddir_id; + int peer_sources_id; + int dht_id; + int ut_pex_id; + int traffic_lim_id; +}; + +#endif diff --git a/apps/ktorrent/leaktrace.cpp b/apps/ktorrent/leaktrace.cpp new file mode 100644 index 0000000..76439ce --- /dev/null +++ b/apps/ktorrent/leaktrace.cpp @@ -0,0 +1,295 @@ +#ifdef KT_LEAKTRACE + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include <util/constants.h> + +/* + * prime number for the address lookup hash table. + * if you have _really_ many memory allocations, use a + * higher value, like 343051 for instance. + */ +#define SOME_PRIME 35323 +#define ADDR_HASH(addr) ((unsigned long) addr % SOME_PRIME) + +using namespace bt; + +struct MemAlloc +{ + void* ptr; + size_t size; + void* alloc_addr; // addr of function which did the allocation + MemAlloc* left; + MemAlloc* right; +}; + +struct MemAllocTree +{ + Uint32 num_buckets; + Uint32 count; + Uint64 bytes; + pthread_mutex_t mutex; + MemAlloc* buckets[SOME_PRIME]; +}; + +static MemAllocTree mtree = {0,0,0,PTHREAD_MUTEX_INITIALIZER}; +static bool print_status_done = false; + +static void InsertIntoTree(MemAlloc* cnode,MemAlloc* target) +{ + if (target->ptr < cnode->ptr) + { + if (!cnode->left) + cnode->left = target; + else + InsertIntoTree(cnode->left,target); + } + else + { + if (!cnode->right) + cnode->right = target; + else + InsertIntoTree(cnode->right,target); + } +} + +static void PrintTree(MemAlloc* ma) +{ + if (!ma) + return; + + printf("\t0x%p 0x%p %i bytes\n",ma->alloc_addr,ma->ptr,ma->size); + PrintTree(ma->left); + PrintTree(ma->right); +} + +static void PrintTreeToFile(FILE* fptr,MemAlloc* ma) +{ + if (!ma) + return; + + fprintf(fptr, "L %10p %9ld # %p\n",ma->alloc_addr,ma->size,ma->ptr); + PrintTreeToFile(fptr,ma->left); + PrintTreeToFile(fptr,ma->right); +} + +static void WriteLeakReport() +{ + FILE* report = fopen("leak.out","wt"); + if (!report) + { + printf("Cannot write report !!!!!!!!\n"); + return; + } + + + for (Uint32 b = 0;b < SOME_PRIME;b++) + PrintTreeToFile(report,mtree.buckets[b]); + fclose(report); +} + +static void PrintStatus() +{ + if (mtree.count == 0) + { + printf("No memory leaks detected !!!\n"); + } + else + { + printf("LeakTrace results : \n"); + for (Uint32 b = 0;b < SOME_PRIME;b++) + PrintTree(mtree.buckets[b]); + printf("====================\n"); + printf("Total : %i leaks, %li bytes leaked\n",mtree.count,mtree.bytes); + } + WriteLeakReport(); + print_status_done = true; +} + + + +static void RegisterAlloc(void* ptr,Uint32 size) +{ + MemAlloc* ma = (MemAlloc*)malloc(sizeof(MemAlloc)); + ma->left = ma->right = 0; + ma->size = size; + ma->alloc_addr = __builtin_return_address(1); + ma->ptr = ptr; + if (mtree.num_buckets == 0) + { + // init buckets + for (Uint32 b = 0;b < SOME_PRIME;b++) + mtree.buckets[b] = 0; + mtree.num_buckets = SOME_PRIME; + atexit(PrintStatus); + } + + // hash the address + Uint32 b = ADDR_HASH(ptr); + if (!mtree.buckets[b]) + { + mtree.count++; + mtree.bytes += size; + mtree.buckets[b] = ma; + } + else + { + // walk the tree and insert it + InsertIntoTree(mtree.buckets[b],ma); + mtree.count++; + mtree.bytes += size; + } +} + +static void DeregisterAlloc(void* ptr) +{ + if (print_status_done) + printf("PrintStatus already happened !!!!!!!!!!\n"); + Uint32 b = ADDR_HASH(ptr); + + MemAlloc* p = mtree.buckets[b]; + MemAlloc* prev = 0; + while (p && p->ptr != ptr) + { + prev = p; + if (ptr < p->ptr) + p = p->left; + else if (ptr > p->ptr) + p = p->right; + } + + if (!p) + return; + + if (!prev) + { + // it's the root + mtree.count--; + mtree.bytes -= p->size; + free(p); + mtree.buckets[b] = 0; + } + else + { + // first update some additional info + mtree.count--; + mtree.bytes -= p->size; + + if (!p->left && !p->right) + { + // no children so just free p + if (prev->left == p) + { + free(prev->left); + prev->left = 0; + } + else + { + free(prev->right); + prev->right = 0; + } + } + else if (p->left && !p->right) + { + // one child of p is zero, so just attach + // the child of p to prev + if (prev->left == p) + prev->left = p->left; + else + prev->right = p->left; + free(p); + } + else if (!p->left && p->right) + { + // one child of p is zero, so just attach + // the child of p to prev + if (prev->left == p) + prev->left = p->right; + else + prev->right = p->right; + free(p); + } + else + { + // both children exist + if (prev->left == p) + { + // attach the left child of p + prev->left = p->left; + InsertIntoTree(prev,p->right); + } + else + { + // attach the right child of p + prev->right = p->right; + InsertIntoTree(prev,p->left); + } + + free(p); + } + } + +} + + +void* operator new(size_t size) +{ + void* ptr = malloc(size); + if (!ptr) + { + printf("PANIC : memory allocation failed !\n"); + exit(-1); + } + + + pthread_mutex_lock(&mtree.mutex); + RegisterAlloc(ptr,size); + pthread_mutex_unlock(&mtree.mutex); + return ptr; +} + + +void* operator new[] (size_t size) +{ + void* ptr = malloc(size); + if (!ptr) + { + printf("PANIC : memory allocation failed !\n"); + exit(-1); + } + + pthread_mutex_lock(&mtree.mutex); + RegisterAlloc(ptr,size); + pthread_mutex_unlock(&mtree.mutex); + return ptr; +} + + +void operator delete (void *ptr) +{ + if (!ptr) + return; + + + pthread_mutex_lock(&mtree.mutex); + DeregisterAlloc(ptr); + pthread_mutex_unlock(&mtree.mutex); + free(ptr); +} + + +void operator delete[] (void *ptr) +{ + if (!ptr) + return; + + pthread_mutex_lock(&mtree.mutex); + DeregisterAlloc(ptr); + pthread_mutex_unlock(&mtree.mutex); + free(ptr); +} + +#endif // KT_LEAKTRACE diff --git a/apps/ktorrent/main.cpp b/apps/ktorrent/main.cpp new file mode 100644 index 0000000..77a99a5 --- /dev/null +++ b/apps/ktorrent/main.cpp @@ -0,0 +1,201 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 HAVE_CONFIG_H +#include <config.h> +#endif + +#include <signal.h> +#include <klocale.h> +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> + +#include <stdlib.h> + +#include "ktorrentapp.h" + +#include <qapplication.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <errno.h> +#include <fcntl.h> +#include <util/error.h> +#include <util/log.h> +#include <torrent/globals.h> +#include <util/fileops.h> +#include <ktversion.h> +#include <functions.h> +#include <qfile.h> +#include <qdir.h> + +using namespace bt; + + + +void StupidWarningMessagesFromQt( QtMsgType type, const char *msg ) +{ + switch ( type ) + { + case QtDebugMsg: + // printf("Qt: Debug: %s\n",msg); + break; + case QtWarningMsg: + printf("Qt: Warning: %s\n",msg); + break; + case QtFatalMsg: + printf("Qt: Fatal : %s\n",msg); + abort(); // deliberately core dump + break; + } +} + + + +static const char description[] = + I18N_NOOP("A BitTorrent program for KDE"); + + +bool GrabPIDLock() +{ + // create a lock file in /tmp/ with the user id of the current user included in the name + QString pid_file = QString("/tmp/.ktorrent_%1.lock").arg(getuid()); + + int fd = open(QFile::encodeName(pid_file),O_RDWR|O_CREAT,0640); + if (fd < 0) + { + fprintf(stderr,"Failed to open KT lock file %s : %s\n",pid_file.ascii(),strerror(errno)); + return false; + } + + if (lockf(fd,F_TLOCK,0)<0) + { + fprintf(stderr,"Failed to get lock on %s : %s\n",pid_file.ascii(),strerror(errno)); + return false; + } + + char str[20]; + sprintf(str,"%d\n",getpid()); + write(fd,str,strlen(str)); /* record pid to lockfile */ + + // leave file open, so nobody else can lock it until KT exists + return true; +} + + +static KCmdLineOptions options[] = +{ + { "debug", I18N_NOOP("Debug mode"), 0 }, + { "silent", I18N_NOOP("Silently save torrent given on URL"), 0 }, + { "+[URL]", I18N_NOOP( "Document to open" ), 0 }, + KCmdLineLastOption +}; + +int main(int argc, char **argv) +{ + // ignore SIGPIPE's + signal(SIGPIPE,SIG_IGN); + signal(SIGXFSZ,SIG_IGN); + qInstallMsgHandler( StupidWarningMessagesFromQt ); + KAboutData about("ktorrent", I18N_NOOP("KTorrent"), kt::VERSION_STRING, description, + KAboutData::License_GPL, "(C) 2005 -2008 Joris Guisson and Ivan Vasic", 0, + "http://www.ktorrent.org/"); + about.addAuthor("Joris Guisson", 0, "joris.guisson@gmail.com" ); + about.addAuthor("Ivan Vasic",0,"ivasic@gmail.com"); + about.addAuthor("Alan Jones",I18N_NOOP("RSS Plugin"),"skyphyr@gmail.com"); + about.addAuthor("Diego R. Brogna",I18N_NOOP("Webinterface Plugin"),"dierbro@gmail.com"); + about.addAuthor("Krzysztof Kundzicz",I18N_NOOP("Statistics Plugin"),"athantor@gmail.com"); + + about.addCredit("Mladen Babic", + I18N_NOOP("Application icon and a couple of others"),"bmladen@EUnet.yu"); + about.addCredit("The-Error",I18N_NOOP("The downloads icon"),"zotrix@eunet.yu"); + about.addCredit("Adam Treat", 0, "treat@kde.org" ); + about.addCredit("Danny Allen", + I18N_NOOP("1.0 application icon"), + "danny@dannyallen.co.uk"); + about.addCredit("Vincent Wagelaar",0,"vincent@ricardis.tudelft.nl"); + about.addCredit("Knut Morten Johansson",0,"knut@johansson.com"); + about.addCredit("Felix Berger", + I18N_NOOP("ChunkBar's tooltip and IWFileTreeItem sorting"), + "bflat1@gmx.net"); + about.addCredit("Andreas Kling",0,"kling@impul.se"); + about.addCredit("Felipe Sateler",0,"fsateler@gmail.com"); + about.addCredit("Maxmind", I18N_NOOP("Country locator for InfoWidget plugin (This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/). "),0, "http://www.maxmind.com/"); + about.addCredit("http://flags.blogpotato.de/",I18N_NOOP("Country flags"),0); + about.addCredit("Adam Forsyth",I18N_NOOP("File prioritization"),"agforsyth@gmail.com"); + about.addCredit("Thomas Bernard",I18N_NOOP("Miniupnp was used as an example for our own UPnP implementation"),0,"http://miniupnp.free.fr/"); + about.addCredit("Diego Rosario Brogna",I18N_NOOP("Global max share ratio patch"),0,"dierbro@gmail.com"); + about.addCredit("Lesly Weyts",I18N_NOOP("Zeroconf enhancements"),0,0); + about.addCredit("Kevin Andre",I18N_NOOP("Zeroconf enhancements"),0,"http://users.edpnet.be/hyperquantum/"); + about.addCredit("Dagur Valberg Johannsson",I18N_NOOP("Coldmilk webgui"),"dagurval@pvv.ntnu.no"); + about.addCredit("Alexander Dymo",I18N_NOOP("IDEAl code from KDevelop"),"adymo@kdevelop.org"); + about.addCredit("Scott Wolchok",I18N_NOOP("Conversion speed improvement in ipfilter plugin"),"swolchok@umich.edu"); + about.addCredit("Bryan Burns of Juniper Networks",I18N_NOOP("Discovered 2 security vulnerabilities (both are fixed)"),0); + about.addCredit("Goten Xiao",I18N_NOOP("Patch to load silently with a save location"),0); + about.addCredit("Rapsys",I18N_NOOP("Fixes in PHP code of webinterface"),0); + about.addCredit("Athantor",I18N_NOOP("XFS specific disk preallocation"),0); + about.addCredit("twisted_fall",I18N_NOOP("Patch to not show very low speeds"),"twisted.fall@gmail.com"); + about.addCredit("Lucke",I18N_NOOP("Patch to show potentially firewalled status"),0); + about.addCredit("Modestas Vainius",I18N_NOOP("Several patches"),"modestas@vainius.eu"); + about.addCredit("Stefan Monov",I18N_NOOP("Patch to hide the menubar"),"logixoul@gmail.com"); + about.addCredit("The_Kernel",I18N_NOOP("Patch to modify file priorities in the webgui"),"kernja@cs.earlham.edu"); + about.addCredit("Rafał Miłecki",I18N_NOOP("Several webgui patches"),"zajec5@gmail.com"); + about.addCredit("Lukasz Fibinger",I18N_NOOP("Filterbar patch"),"lucke@o2.pl"); + about.addCredit("Jindrich Makovicka",I18N_NOOP("Non threaded fileview update patch"),"makovick@gmail.com"); + about.addCredit("swolchok",I18N_NOOP("Optimization to SHA1 hash generation"),"evilsporkman@gmail.com"); + about.addCredit("Markus Brueffer",I18N_NOOP("Patch to fix free diskspace calculation on FreeBSD"),"markus@brueffer.de"); + about.addCredit("caruccio",I18N_NOOP("Patch to load torrents silently from the command line"),"mateus@caruccio.com"); + + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions(options); + + KTorrentApp::addCmdLineOptions(); + if (!KTorrentApp::start()) + { + fprintf(stderr, "ktorrent is already running!\n"); + return 0; + } + + // need to grab lock after the fork call in start, otherwise this will not work properly + if (!GrabPIDLock()) + { + fprintf(stderr, "ktorrent is already running!\n"); + return 0; + } + + try + { + KTorrentApp app; + app.exec(); + } + catch (bt::Error & e) + { + fprintf(stderr, "Aborted by error : %s\n",e.toString().ascii()); + } + Globals::cleanup(); + +// printf("\n\nObjects alive = %i\n\n",(unsigned int)Object::numAlive()); + return 0; +} + + diff --git a/apps/ktorrent/newui/Makefile.am b/apps/ktorrent/newui/Makefile.am new file mode 100644 index 0000000..bd136f3 --- /dev/null +++ b/apps/ktorrent/newui/Makefile.am @@ -0,0 +1,8 @@ +INCLUDES = -I$(srcdir)/../../libktorrent -I$(top_builddir)/ktorrent/libktorrent \ + -I$(top_builddir)/libktorrent/ $(all_includes) +METASOURCES = AUTO +noinst_LTLIBRARIES = libnewui.la +libnewui_la_LDFLAGS = $(all_libraries) +libnewui_la_SOURCES = button.cpp button.h buttonbar.cpp buttonbar.h comdefs.h \ + ddockwindow.cpp ddockwindow.h dmainwindow.cpp dmainwindow.h docksplitter.cpp \ + docksplitter.h dtabwidget.cpp dtabwidget.h diff --git a/apps/ktorrent/newui/button.cpp b/apps/ktorrent/newui/button.cpp new file mode 100644 index 0000000..d133064 --- /dev/null +++ b/apps/ktorrent/newui/button.cpp @@ -0,0 +1,351 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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 "button.h" + +#include <qpainter.h> +#include <qtooltip.h> +#include <qstyle.h> +#include <qapplication.h> +#include <qregexp.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <kxmlguiclient.h> +#include <kaction.h> +#include <kpopupmenu.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kapplication.h> +#include <kconfig.h> + +#include "buttonbar.h" + +namespace Ideal { + +Button::Button(ButtonBar *parent, const QString text, const QIconSet &icon, + const QString &description) + :QPushButton(icon, text, parent), m_buttonBar(parent), m_description(description), + m_place(parent->place()), m_realText(text), m_realIconSet(icon) +{ + hide(); + setFlat(true); + setToggleButton(true); + setFocusPolicy(NoFocus); + setDescription(m_description); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + resize(sizeHint()); + fixDimensions(Ideal::Bottom); + + QToolTip::add(this, m_realText); + + m_assignAccelAction = new KAction(i18n("Assign Accelerator..."), 0, + this, SLOT(assignAccel()), this); + m_clearAccelAction = new KAction(i18n("Clear Accelerator"), 0, + this, SLOT(clearAccel()), this); + + KConfig *config = kapp->config(); + config->setGroup("UI"); + QString accel = config->readEntry(QString("button_%1").arg(text), ""); + if (!accel.isEmpty()) + setRealText(QString("&%1 %2").arg(accel).arg(m_realText)); +} + +Button::~Button() +{ +// m_buttonBar->removeButton(this); + KConfig *config = kapp->config(); + config->setGroup("UI"); + + QRegExp r("^&([0-9])\\s.*"); + QRegExp r2("^&[0-9]\\s"); + if (r.search(m_realText) > -1) + { + QString text = m_realText; + if (text.contains(r2)) + text.remove(r2); + config->writeEntry(QString("button_%1").arg(text), r.cap(1)); + } + else + { + config->writeEntry(QString("button_%1").arg(m_realText), ""); + } +} + +void Button::setDescription(const QString &description) +{ + m_description = description; + QToolTip::remove(this); + QToolTip::add(this, m_description); +} + +QString Button::description() const +{ + return m_description; +} + +void Button::drawButton(QPainter *p) +{ + QRect r = rect(); + QSize sh = r.size(); + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + sh.setHeight(r.width()); + sh.setWidth(r.height()); + break; + } + + QStyle::SFlags flags = QStyle::Style_Default; + if (isEnabled()) + flags |= QStyle::Style_Enabled; + if (hasFocus()) + flags |= QStyle::Style_HasFocus; + if (isDown()) + flags |= QStyle::Style_Down; + if (isOn()) + flags |= QStyle::Style_On; + if (! isFlat() && ! isDown()) + flags |= QStyle::Style_Raised; + if (isDefault()) + flags |= QStyle::Style_ButtonDefault; + + QPixmap pm(sh.width(), sh.height()); + pm.fill(eraseColor()); + QPainter p2(&pm); + + style().drawControl(QStyle::CE_PushButton,&p2,this, QRect(0,0,pm.width(),pm.height()), colorGroup(),flags); + + style().drawControl(QStyle::CE_PushButtonLabel, &p2, this, + QRect(0,0,pm.width(),pm.height()), + colorGroup(), flags, QStyleOption()); + + switch (m_place) + { + case Ideal::Left: + p->rotate(-90); + p->drawPixmap(1-pm.width(), 0, pm); + break; + case Ideal::Right: + p->rotate(90); + p->drawPixmap(0, 1-pm.height(), pm); + break; + default: + p->drawPixmap(0, 0, pm); + break; + } +} + +void Button::drawButtonLabel(QPainter */*p*/) +{ +} + +ButtonMode Button::mode() +{ + return m_buttonBar->mode(); +} + +void Button::setPlace(Ideal::Place place) +{ + Place oldPlace = m_place; + m_place = place; + fixDimensions(oldPlace); +} + +void Button::fixDimensions(Place oldPlace) +{ + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + if ((oldPlace == Ideal::Bottom) || (oldPlace == Ideal::Top)) + { + setFixedWidth(height()); + setMinimumHeight(sizeHint().width()); + setMaximumHeight(32767); + } + break; + case Ideal::Top: + case Ideal::Bottom: + if ((oldPlace == Ideal::Left) || (oldPlace == Ideal::Right)) + { + setFixedHeight(width()); + setMinimumWidth(sizeHint().height()); + setMaximumWidth(32767); + } + break; + } +} + +QSize Button::sizeHint() const +{ + return sizeHint(text()); +} + +QSize Button::sizeHint(const QString &text) const +{ + constPolish(); + int w = 0, h = 0; + + if ( iconSet() && !iconSet()->isNull() && (m_buttonBar->mode() != Text) ) { + int iw = iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4; + int ih = iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).height(); + w += iw; + h = QMAX( h, ih ); + } + if ( isMenuButton() ) + w += style().pixelMetric(QStyle::PM_MenuButtonIndicator, this); + if ( pixmap() ) { + QPixmap *pm = (QPixmap *)pixmap(); + w += pm->width(); + h += pm->height(); + } else if (m_buttonBar->mode() != Icons) { + QString s( text ); + bool empty = s.isEmpty(); + if ( empty ) + s = QString::fromLatin1("XXXX"); + QFontMetrics fm = fontMetrics(); + QSize sz = fm.size( ShowPrefix, s ); + if(!empty || !w) + w += sz.width(); + if(!empty || !h) + h = QMAX(h, sz.height()); + } + + return (style().sizeFromContents(QStyle::CT_ToolButton, this, QSize(w, h)). + expandedTo(QApplication::globalStrut())); +} + +void Button::updateSize() +{ + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + setMinimumHeight(sizeHint().width()); + resize(sizeHint().height(), sizeHint().width()); + break; + case Ideal::Top: + case Ideal::Bottom: + resize(sizeHint().width(), sizeHint().height()); + break; + } +} + +QString Button::realText() const +{ + return m_realText; +} + +void Button::setMode(Ideal::ButtonMode mode) +{ + switch (mode) + { + case Text: + disableIconSet(); + enableText(); + break; + case IconsAndText: + enableIconSet(); + enableText(); + break; + case Icons: + disableText(); + enableIconSet(); + break; + } +} + +void Button::enableIconSet() +{ + if (!iconSet()) + { + if (m_realIconSet.isNull()) + m_realIconSet = SmallIcon("file_new"); + setIconSet(m_realIconSet); + } +} + +void Button::disableIconSet() +{ + setIconSet(QIconSet()); +} + +void Button::disableText() +{ + if (text().length() > 0) + setText(""); +} + +void Button::enableText() +{ + setText(m_realText); +} + +void Button::contextMenuEvent(QContextMenuEvent *e) +{ +/* QPopupMenu menu; + + m_assignAccelAction->plug(&menu); + if (m_realText.contains(QRegExp("^&[0-9]\\s"))) + m_clearAccelAction->plug(&menu); + + emit contextMenu( &menu ); + + menu.exec(e->globalPos()); + */ +} + +void Button::assignAccel() +{ + bool ok; + int num = KInputDialog::getInteger(i18n("Change Button Number"), i18n("New accelerator number:"), 1, 0, 10, 1, &ok, this); + if (ok) + { + QString text = realTextWithoutAccel(); + text = QString("&%1 %2").arg(num).arg(text); + setRealText(text); + } +} + +void Button::setRealText(const QString &text) +{ + m_realText = text; + setText(text); + updateSize(); +} + +void Button::clearAccel() +{ + setRealText(realTextWithoutAccel()); +} + +QString Button::realTextWithoutAccel() const +{ + QString text = m_realText; + QRegExp r("^&[0-9]\\s"); + if (text.contains(r)) + text.remove(r); + return text; +} + +} + +#include "button.moc" diff --git a/apps/ktorrent/newui/button.h b/apps/ktorrent/newui/button.h new file mode 100644 index 0000000..a7afbcf --- /dev/null +++ b/apps/ktorrent/newui/button.h @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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. * + ***************************************************************************/ +#ifndef IDEALBUTTON_H +#define IDEALBUTTON_H + +#include <qpushbutton.h> +#include <qiconset.h> + +#include "comdefs.h" + +class KAction; + +namespace Ideal { + +class ButtonBar; + +/** +@short A button to place onto the ButtonBar + +A QPushButton derivative with a size of a QToolBar. Button can be rotated +(placed onto different places in ideal mode). +*/ +class Button : public QPushButton { + Q_OBJECT +public: + Button(ButtonBar *parent, const QString text, const QIconSet &icon = QIconSet(), + const QString &description = QString::null); + + /**Sets the description used as a tooltip.*/ + void setDescription(const QString &description); + /**Returns the description.*/ + QString description() const; + + /**Sets the place of a button.*/ + void setPlace(Ideal::Place place); + /**Sets the mode of a button.*/ + void setMode(Ideal::ButtonMode mode); + + QSize sizeHint() const; + QSize sizeHint(const QString &text) const; + + /**Updates size of a widget. Used after squeezing button's text.*/ + void updateSize(); + + /**Returns the real (i.e. not squeezed) text of a button.*/ + QString realText() const; + QString realTextWithoutAccel() const; + void setRealText(const QString &text); + +protected: + ButtonMode mode(); + + virtual void drawButton(QPainter *p); + virtual void drawButtonLabel(QPainter *p); + + virtual void contextMenuEvent(QContextMenuEvent *e); + +protected slots: + void assignAccel(); + void clearAccel(); + +signals: + void contextMenu(QPopupMenu*); + +private: + virtual ~Button(); + + void fixDimensions(Place oldPlace); + + void enableIconSet(); + void disableIconSet(); + void enableText(); + void disableText(); + + ButtonBar *m_buttonBar; + + QString m_description; + Place m_place; + + QString m_realText; + QIconSet m_realIconSet; + + KAction *m_assignAccelAction; + KAction *m_clearAccelAction; + +friend class ButtonBar; +}; + +} + +#endif diff --git a/apps/ktorrent/newui/buttonbar.cpp b/apps/ktorrent/newui/buttonbar.cpp new file mode 100644 index 0000000..8f60dab --- /dev/null +++ b/apps/ktorrent/newui/buttonbar.cpp @@ -0,0 +1,346 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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 "buttonbar.h" + +#include <qlayout.h> + +#include <kdebug.h> +#include <kconfig.h> +#include <kstringhandler.h> +#include <klocale.h> + +#include "button.h" + +namespace Ideal { + +//ButtonLayout class + +ButtonLayout::ButtonLayout(ButtonBar *parent, Direction d, int margin, int spacing, const char *name) + :QBoxLayout(parent, d, margin, spacing, name), m_buttonBar(parent) +{ +} + +QSize ButtonLayout::minimumSize() const +{ + QSize size = QBoxLayout::minimumSize(); + + if (!m_buttonBar->autoResize()) + return size; + + switch (m_buttonBar->place()) + { + case Ideal::Left: + case Ideal::Right: + return QSize(size.width(),0); + break; + case Ideal::Top: + case Ideal::Bottom: + return QSize(0,size.height()); + } + return QBoxLayout::minimumSize(); +} + + + +//ButtonBar class + + +ButtonBar::ButtonBar(Place place, ButtonMode mode, QWidget *parent, const char *name) + :QWidget(parent, name), m_place(place), l(0), m_shrinked(false), m_autoResize(true) +{ + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + l = new ButtonLayout(this, QBoxLayout::TopToBottom, 0, 0); + break; + case Ideal::Top: + case Ideal::Bottom: + l = new ButtonLayout(this, QBoxLayout::LeftToRight, 0, 0); + break; + } + + l->setResizeMode(QLayout::Minimum); + setMode(mode); + + l->insertStretch(-1); +} + +ButtonBar::~ButtonBar() +{ +} + +void ButtonBar::addButton(Button *button) +{ + int buttonCount = m_buttons.count(); + + button->setMode(m_mode); + m_buttons.append(button); + l->insertWidget(buttonCount, button); + button->show(); + fixDimensions(); +} + +void ButtonBar::removeButton(Button *button) +{ + m_buttons.remove(button); + l->remove(button); + delete button; +} + +void ButtonBar::setMode(ButtonMode mode) +{ + m_mode = mode; + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + (*it)->setMode(mode); +} + +ButtonMode ButtonBar::mode() const +{ + return m_mode; +} + +Place ButtonBar::place() const +{ + return m_place; +} + +void ButtonBar::fixDimensions() +{ + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + setFixedWidth(sizeHint().width()); + setMinimumHeight(sizeHint().height()); + setMaximumHeight(32767); + break; + case Ideal::Top: + case Ideal::Bottom: + setFixedHeight(sizeHint().height()); + setMinimumWidth(sizeHint().width()); + setMaximumWidth(32767); + break; + } +} + +void ButtonBar::setButtonsPlace(Ideal::Place place) +{ + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + (*it)->setPlace(place); +} + +void ButtonBar::resizeEvent(QResizeEvent *ev) +{ + int preferredDimension = 0; + int actualDimension = 0; + int oldDimension = 0; + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + preferredDimension = l->QBoxLayout::minimumSize().height(); + actualDimension = size().height(); + oldDimension = ev->oldSize().height(); + break; + case Ideal::Top: + case Ideal::Bottom: + preferredDimension = l->QBoxLayout::minimumSize().width(); + actualDimension = size().width(); + oldDimension = ev->oldSize().width(); + break; + } + + if (preferredDimension > actualDimension) + shrink(preferredDimension, actualDimension); + else if (m_shrinked && (originalDimension() < actualDimension)) + unshrink(); + else if (m_shrinked && actualDimension > oldDimension) + deshrink(preferredDimension, actualDimension); + + QWidget::resizeEvent(ev); +} + +void ButtonBar::shrink(int preferredDimension, int actualDimension) +{ + if (!preferredDimension) + return; + + m_shrinked = true; + + uint textLength = 0; + QValueList<uint> texts; + uint maxLength = 0; + for (ButtonList::const_iterator it = m_buttons.constBegin(); it != m_buttons.constEnd(); ++it) + { + uint length = (*it)->text().length(); + maxLength = length > maxLength ? length : maxLength ; + texts.append(length); + textLength += length; + } + + uint newPreferredLength = actualDimension * textLength / preferredDimension; + + uint newMaxLength = maxLength; + uint newTextLength; + do { + newMaxLength -= 1; + newTextLength = 0; + for (QValueList<uint>::iterator it = texts.begin(); it != texts.end(); ++it) + { + if (*it > newMaxLength) + *it = newMaxLength; + newTextLength += *it; + } + } while (newTextLength > newPreferredLength); + + int i = 0; + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + { + (*it)->setText(KStringHandler::rsqueeze((*it)->realText(), texts[i++])); + (*it)->updateSize(); + } +} + +void ButtonBar::deshrink(int preferredDimension, int actualDimension) +{ + if (!preferredDimension) + return; + + m_shrinked = true; + + uint textLength = 0; + QValueList<uint> texts; + uint maxLength = 0; + for (ButtonList::const_iterator it = m_buttons.constBegin(); it != m_buttons.constEnd(); ++it) + { + uint length = (*it)->text().length(); + maxLength = length > maxLength ? length : maxLength ; + texts.append(length); + textLength += length; + } + + uint newPreferredLength = actualDimension * textLength / preferredDimension; + + if (newPreferredLength <= textLength) + return; + + uint newTextLength; + uint prevTextLength = 0; + do { + newTextLength = 0; + int i = 0; + for (QValueList<uint>::iterator it = texts.begin(); it != texts.end(); ++it, i++) + { + if (m_buttons[i]->text().contains("...")) + (*it)++; + newTextLength += *it; + } + if (newTextLength == prevTextLength) + break; + prevTextLength = newTextLength; + } while (newTextLength < newPreferredLength); + + int i = 0; + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + { + if (texts[i] >= (*it)->realText().length()) + (*it)->setText((*it)->realText()); + else + (*it)->setText(KStringHandler::rsqueeze((*it)->realText(), texts[i])); + (*it)->updateSize(); + ++i; + } +} + +void ButtonBar::unshrink() +{ + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + { + (*it)->setText((*it)->realText()); + (*it)->updateSize(); + } + m_shrinked = false; +} + +int ButtonBar::originalDimension() +{ + int size = 0; + for (ButtonList::const_iterator it = m_buttons.constBegin(); it != m_buttons.constEnd(); ++it) + { + size += (*it)->sizeHint((*it)->realText()).width(); + } + return size; +} + +bool ButtonBar::autoResize() const +{ + return m_autoResize; +} + +void ButtonBar::setAutoResize(bool b) +{ + m_autoResize = b; +} + +Button *ButtonBar::firstButton() +{ + if (!m_buttons.isEmpty()) + return m_buttons.first(); + return 0; +} + +Button *ButtonBar::nextTo(Button *button) +{ + ButtonList::iterator it = m_buttons.find(button); + Button *next = 0; + if ((*it) == m_buttons.last()) + next = m_buttons.first(); + else + { + it++; + next = *it; + } + if (next->isVisible()) + return next; + else + return nextTo(next); +} + +Button *ButtonBar::prevTo(Button *button) +{ + ButtonList::iterator it = m_buttons.find(button); + Button *prev = 0; + if (it == m_buttons.begin()) + prev = m_buttons.last(); + else + { + it--; + prev = *it; + } + if (prev->isVisible()) + return prev; + else + return prevTo(prev); +} + +} + +#include "buttonbar.moc" diff --git a/apps/ktorrent/newui/buttonbar.h b/apps/ktorrent/newui/buttonbar.h new file mode 100644 index 0000000..5f5a7e3 --- /dev/null +++ b/apps/ktorrent/newui/buttonbar.h @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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. * + ***************************************************************************/ +#ifndef IDEALBUTTONBAR_H +#define IDEALBUTTONBAR_H + +#include <qwidget.h> +#include <qvaluelist.h> + +#include "comdefs.h" + +#include <qlayout.h> + +namespace Ideal { + +class Button; +class ButtonBar; + +/**@short A layout for a ButtonBar class. + +Overrides minimumSize method to allow shrinking button bar buttons.*/ +class ButtonLayout: public QBoxLayout{ +public: + ButtonLayout(ButtonBar *parent, Direction d, int margin = 0, int spacing = -1, const char * name = 0); + + virtual QSize minimumSize() const; + +private: + ButtonBar *m_buttonBar; +}; + +/** +@short A bar with tool buttons. + +Looks like a toolbar but has another behaviour. It is suitable for +placing on the left(right, bottom, top) corners of a window as a bar with slider. +*/ +class ButtonBar : public QWidget { + Q_OBJECT +public: + ButtonBar(Place place, ButtonMode mode = IconsAndText, + QWidget *parent = 0, const char *name = 0); + virtual ~ButtonBar(); + + /**Adds a button to the bar.*/ + virtual void addButton(Button *button); + /**Removes a button from the bar and deletes the button.*/ + virtual void removeButton(Button *button); + + /**Sets the mode.*/ + void setMode(ButtonMode mode); + /**@returns the mode.*/ + ButtonMode mode() const; + + /**@returns the place.*/ + Place place() const; + + bool autoResize() const; + void setAutoResize(bool b); + + /**Shrinks the button bar so all buttons are visible. Shrinking is done by + reducing the amount of text shown on buttons. Button icon size is a minimum size + of a button. If a button does not have an icon, it displays "...".*/ + virtual void shrink(int preferredDimension, int actualDimension); + virtual void deshrink(int preferredDimension, int actualDimension); + /**Restores the size of button bar buttons.*/ + virtual void unshrink(); + + Button *firstButton(); + Button *nextTo(Button *button); + Button *prevTo(Button *button); + +protected: + virtual void resizeEvent ( QResizeEvent *ev ); + + int originalDimension(); + +private: + void fixDimensions(); + void setButtonsPlace(Ideal::Place place); + + typedef QValueList<Button*> ButtonList; + ButtonList m_buttons; + + ButtonMode m_mode; + Place m_place; + + ButtonLayout *l; + + bool m_shrinked; + bool m_autoResize; +}; + +} + +#endif diff --git a/apps/ktorrent/newui/comdefs.h b/apps/ktorrent/newui/comdefs.h new file mode 100644 index 0000000..8233f12 --- /dev/null +++ b/apps/ktorrent/newui/comdefs.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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. * + ***************************************************************************/ +#ifndef COMDEFS_H +#define COMDEFS_H + +namespace Ideal { + + enum Place { Left=1, Right=2, Top=4, Bottom=8 }; + enum ButtonMode { Text, IconsAndText, Icons }; + +} + +#endif diff --git a/apps/ktorrent/newui/ddockwindow.cpp b/apps/ktorrent/newui/ddockwindow.cpp new file mode 100644 index 0000000..9edfc7c --- /dev/null +++ b/apps/ktorrent/newui/ddockwindow.cpp @@ -0,0 +1,418 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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 "ddockwindow.h" + +#include <qtoolbutton.h> +#include <qlayout.h> +#include <qstyle.h> +#include <qwidgetstack.h> +#include <qimage.h> +#include <qapplication.h> +#include <qpopupmenu.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kcombobox.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kapplication.h> + +#include "buttonbar.h" +#include "button.h" +#include "dmainwindow.h" + +DDockWindow::DDockWindow(DMainWindow *parent, Position position) + :QDockWindow(QDockWindow::InDock, parent), m_position(position), m_visible(false), + m_mainWindow(parent), m_doNotCloseActiveWidget(false), m_toggledButton(0), m_lastContextMenuButton(0) +{ + setMovingEnabled(false); + setResizeEnabled(true); + + Ideal::Place place = Ideal::Left; + switch (position) { + case DDockWindow::Bottom: + m_name = "BottomToolWindow"; + place = Ideal::Bottom; + m_internalLayout = new QVBoxLayout(boxLayout(), 0); + m_internalLayout->setDirection(QBoxLayout::BottomToTop); + break; + case DDockWindow::Left: + m_name = "LeftToolWindow"; + place = Ideal::Left; + m_internalLayout = new QHBoxLayout(boxLayout(), 0); + m_internalLayout->setDirection(QBoxLayout::LeftToRight); + break; + case DDockWindow::Right: + m_name = "RightToolWindow"; + place = Ideal::Right; + m_internalLayout = new QHBoxLayout(boxLayout(), 0); + m_internalLayout->setDirection(QBoxLayout::RightToLeft); + break; + } + + KConfig *config = kapp->config(); + config->setGroup("UI"); + int mode = config->readNumEntry("MDIStyle", 3); + Ideal::ButtonMode buttonMode = Ideal::Text; + if (mode == 0) + buttonMode = Ideal::Icons; + else if (mode == 1) + buttonMode = Ideal::Text; + else if (mode == 3) + buttonMode = Ideal::IconsAndText; + + m_bar = new Ideal::ButtonBar(place, buttonMode, this); + m_internalLayout->addWidget(m_bar); + + m_widgetStack = new QWidgetStack(this); + m_internalLayout->addWidget(m_widgetStack); + + m_moveToDockLeft = new KAction( i18n("Move to left dock"), 0, this, SLOT(moveToDockLeft()), this ); + m_moveToDockRight = new KAction( i18n("Move to right dock"), 0, this, SLOT(moveToDockRight()), this ); + m_moveToDockBottom = new KAction( i18n("Move to bottom dock"), 0, this, SLOT(moveToDockBottom()), this ); + + setVisible(m_visible); + + loadSettings(); +} + +DDockWindow::~DDockWindow() +{ +//done in DMainWindow now +// saveSettings(); +} + +void DDockWindow::setVisible(bool v) +{ + //write dock width to the config file + KConfig *config = kapp->config(); + QString group = QString("%1").arg(m_name); + config->setGroup(group); + + if (m_visible) + config->writeEntry("ViewWidth", m_position == DDockWindow::Bottom ? height() : width() ); + setResizeEnabled(v); + setVerticallyStretchable(true); + setHorizontallyStretchable(true); + v ? m_widgetStack->show() : m_widgetStack->hide(); + m_visible = v; + + m_internalLayout->invalidate(); + if (!m_visible) + { + if (m_position == DDockWindow::Bottom) + setFixedExtentHeight(m_internalLayout->sizeHint().height()); + else + setFixedExtentWidth(m_internalLayout->sizeHint().width()); + emit hidden(); + } + else + { + //restore widget size from the config + int size = 0; + if (m_position == DDockWindow::Bottom) + { + size = config->readNumEntry("ViewWidth", m_internalLayout->minimumSize().height()); + setFixedExtentHeight(size); + } + else + { + size = config->readNumEntry("ViewWidth", m_internalLayout->minimumSize().width()); + setFixedExtentWidth(size); + } + } +} + +void DDockWindow::loadSettings() +{ +} + +void DDockWindow::saveSettings() +{ + KConfig *config = kapp->config(); + QString group = QString("%1").arg(m_name); + int invisibleWidth = 0; + config->setGroup(group); + if (config->hasKey("ViewWidth")) + invisibleWidth = config->readNumEntry("ViewWidth"); + config->deleteEntry("ViewWidth"); + config->deleteEntry("ViewLastWidget"); + if (m_toggledButton && m_visible) + { + config->writeEntry("ViewWidth", m_position == DDockWindow::Bottom ? height() : width()); + config->writeEntry("ViewLastWidget", m_toggledButton->realTextWithoutAccel()); + } + else if (invisibleWidth != 0) + config->writeEntry("ViewWidth", invisibleWidth); +} + +QWidget *DDockWindow::currentWidget() const +{ + return m_widgetStack->visibleWidget(); +} + +void DDockWindow::addWidget(const QString &title, QWidget *widget, bool skipActivation) +{ + kdDebug(9000) << k_funcinfo << endl; + QPixmap *pm = const_cast<QPixmap*>(widget->icon()); + Ideal::Button *button; + if (pm != 0) + { + //force 16pt for now + if (pm->height() > 16) + { + QImage img = pm->convertToImage(); + img = img.smoothScale(16, 16); + pm->convertFromImage(img); + } + button = new Ideal::Button(m_bar, title, *pm); + } + else + button = new Ideal::Button(m_bar, title); + m_widgets[button] = widget; + m_buttons[widget] = button; + m_bar->addButton(button); + + m_widgetStack->addWidget(widget); + connect(button, SIGNAL(clicked()), this, SLOT(selectWidget())); + connect(button, SIGNAL(contextMenu(QPopupMenu*)), this, SLOT(contextMenu(QPopupMenu*)) ); + + if (!skipActivation) + { + //if the widget was selected last time the dock is deleted + //we need to show it + KConfig *config = kapp->config(); + QString group = QString("%1").arg(m_name); + config->setGroup(group); + if (config->readEntry("ViewLastWidget") == title) + { + kdDebug(9000) << k_funcinfo << " : activating last widget " << title << endl; + button->setOn(true); + selectWidget(button); + } + } +} + +void DDockWindow::raiseWidget(QWidget *widget) +{ + kdDebug(9000) << k_funcinfo << endl; + + if ( !widget ) return; + + Ideal::Button *button = m_buttons[widget]; + if ((button != 0) && (!button->isOn())) + { + button->setOn(true); + selectWidget(button); + } +} + +void DDockWindow::lowerWidget(QWidget * widget) +{ + kdDebug(9000) << k_funcinfo << endl; + + if ( !widget ) return; + + Ideal::Button *button = m_buttons[widget]; + if ((button != 0) && (button->isOn())) + { + button->setOn(false); + selectWidget(button); + } +} + +void DDockWindow::removeWidget(QWidget *widget) +{ + kdDebug(9000) << k_funcinfo << endl; + if (m_widgetStack->id(widget) == -1) + return; //not in dock + + bool changeVisibility = false; + if (m_widgetStack->visibleWidget() == widget) + changeVisibility = true; + + Ideal::Button *button = m_buttons[widget]; + if (button) + m_bar->removeButton(button); + m_widgets.remove(button); + m_buttons.remove(widget); + m_widgetStack->removeWidget(widget); + + if (changeVisibility) + { + m_toggledButton = 0; + setVisible(false); + } +} + +void DDockWindow::selectWidget(Ideal::Button *button) +{ + bool special = m_doNotCloseActiveWidget; + m_doNotCloseActiveWidget = false; + kdDebug(9000) << k_funcinfo << endl; + if (m_toggledButton == button) + { + if (special && m_visible && (!isActive())) + { + //special processing for keyboard navigation events + m_toggledButton->setOn(true); + m_widgets[button]->setFocus(); + } + else + { + m_widgets[button]->setFocus(); + setVisible(!m_visible); + } + return; + } + + if (m_toggledButton) + m_toggledButton->setOn(false); + m_toggledButton = button; + setVisible(true); + m_widgetStack->raiseWidget(m_widgets[button]); + m_widgets[button]->setFocus(); +} + +void DDockWindow::selectWidget() +{ + selectWidget((Ideal::Button*)sender()); +} + +void DDockWindow::hideWidget(QWidget *widget) +{ + Ideal::Button *button = m_buttons[widget]; + if (button != 0) + { + button->setOn(false); + button->hide(); + } + widget->hide(); + if (button == m_toggledButton) + setVisible(false); +} + +void DDockWindow::showWidget(QWidget *widget) +{ + Ideal::Button *button = m_buttons[widget]; + if (button != 0) + button->show(); +// widget->show(); +} + +void DDockWindow::setMovingEnabled(bool) +{ + //some operations on KMainWindow cause moving to be enabled + //but we always don't want DDockWindow instances to be movable + QDockWindow::setMovingEnabled(false); +} + +void DDockWindow::selectLastWidget() +{ + m_doNotCloseActiveWidget = true; + if (m_toggledButton) + m_toggledButton->animateClick(); + else if (Ideal::Button *button = m_bar->firstButton()) + button->animateClick(); +} + +bool DDockWindow::isActive() +{ + if (m_toggledButton) + { + QWidget *w = qApp->focusWidget(); + if (!w) + return false; + QWidget *toolWidget = m_widgets[m_toggledButton]; + if (toolWidget == w) + return true; + else + { + do { + w = (QWidget*)w->parent(); + if (w && (w == toolWidget)) return true; + } while (w); + } + } + return false; +} + +void DDockWindow::selectNextWidget() +{ + if (!m_toggledButton) + return; + Ideal::Button *b = m_bar->nextTo(m_toggledButton); + if (b) + b->animateClick(); +} + +void DDockWindow::selectPrevWidget() +{ + if (!m_toggledButton) + return; + Ideal::Button *b = m_bar->prevTo(m_toggledButton); + if (b) + b->animateClick(); +} + +void DDockWindow::contextMenu(QPopupMenu * menu) +{ + m_lastContextMenuButton = static_cast<Ideal::Button*>( const_cast<QObject*>( sender() ) ); + + menu->insertSeparator(); + + if ( position() != DDockWindow::Left ) + m_moveToDockLeft->plug( menu ); + if ( position()!= DDockWindow::Right ) + m_moveToDockRight->plug( menu ); + if ( position() != DDockWindow::Bottom ) + m_moveToDockBottom->plug( menu ); +} + +void DDockWindow::moveToDockLeft() +{ + moveToDock( DDockWindow::Left ); +} + +void DDockWindow::moveToDockRight() +{ + moveToDock( DDockWindow::Right ); +} + +void DDockWindow::moveToDockBottom() +{ + moveToDock( DDockWindow::Bottom ); +} + +void DDockWindow::moveToDock(DDockWindow::Position position ) +{ + if ( m_widgets.contains( m_lastContextMenuButton ) ) + { + mainWindow()->moveWidget( position, m_widgets[ m_lastContextMenuButton ], m_lastContextMenuButton->realTextWithoutAccel() ); + } +} + +bool DDockWindow::hasWidgets() const +{ + return m_widgets.count() > 0; +} + +#include "ddockwindow.moc" diff --git a/apps/ktorrent/newui/ddockwindow.h b/apps/ktorrent/newui/ddockwindow.h new file mode 100644 index 0000000..d0cc655 --- /dev/null +++ b/apps/ktorrent/newui/ddockwindow.h @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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. * + ***************************************************************************/ +#ifndef DDOCKWINDOW_H +#define DDOCKWINDOW_H + +#include <qdockwindow.h> +#include <qvaluelist.h> + +class QBoxLayout; +class QToolButton; +class QWidgetStack; +class QPopupMenu; + +class KComboBox; +class KAction; + +class DMainWindow; + +namespace Ideal { + class Button; + class ButtonBar; +} + +class DDockWindow : public QDockWindow { + Q_OBJECT +public: + enum Position { Bottom, Left, Right }; + + DDockWindow(DMainWindow *parent, Position position); + virtual ~DDockWindow(); + + virtual void setVisible(bool v); + bool visible() const { return m_visible; } + Position position() const { return m_position; } + + virtual void addWidget(const QString &title, QWidget *widget, bool skipActivation = false); + virtual void raiseWidget(QWidget *widget); + virtual void lowerWidget(QWidget *widget); + /**Removes the widget from dock. Does not delete it.*/ + virtual void removeWidget(QWidget *widget); + + virtual void hideWidget(QWidget *widget); + virtual void showWidget(QWidget *widget); + + virtual QWidget *currentWidget() const; + + virtual void setMovingEnabled(bool b); + + virtual void saveSettings(); + + DMainWindow *mainWindow() const { return m_mainWindow; } + + virtual void selectLastWidget(); + virtual void selectNextWidget(); + virtual void selectPrevWidget(); + + bool isActive(); + /// Check if this dock has any widgets + bool hasWidgets() const; + +signals: + void hidden(); + +private slots: + void selectWidget(); + void selectWidget(Ideal::Button *button); + void contextMenu(QPopupMenu*); + void moveToDockLeft(); + void moveToDockRight(); + void moveToDockBottom(); + void moveToDock(DDockWindow::Position); + +protected: + virtual void loadSettings(); + + Ideal::ButtonBar *m_bar; + QWidgetStack *m_widgetStack; + + QMap<Ideal::Button*, QWidget*> m_widgets; + QMap<QWidget*, Ideal::Button*> m_buttons; + +private: + Position m_position; + bool m_visible; + QString m_name; + DMainWindow *m_mainWindow; + bool m_doNotCloseActiveWidget; + + Ideal::Button *m_toggledButton; + Ideal::Button *m_lastContextMenuButton; + QBoxLayout *m_internalLayout; + + + KAction * m_moveToDockLeft; + KAction * m_moveToDockRight; + KAction * m_moveToDockBottom; +}; + +#endif diff --git a/apps/ktorrent/newui/dmainwindow.cpp b/apps/ktorrent/newui/dmainwindow.cpp new file mode 100644 index 0000000..ff24980 --- /dev/null +++ b/apps/ktorrent/newui/dmainwindow.cpp @@ -0,0 +1,320 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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 "dmainwindow.h" + +#include <kdebug.h> +#include <kapplication.h> +#include <kconfig.h> +#include <kiconloader.h> + +#include <qtoolbutton.h> + +#include "dtabwidget.h" +#include "docksplitter.h" + +DMainWindow::DMainWindow(QWidget *parent, const char *name) + :KParts::MainWindow(parent, name), m_firstRemoved(false), m_currentWidget(0) +{ + loadSettings(); + createToolWindows(); + m_central = new Ideal::DockSplitter(Qt::Horizontal, this); + m_activeTabWidget = createTab(); + m_central->addDock(0, 0, m_activeTabWidget); + setCentralWidget(m_central); +} + +void DMainWindow::loadSettings() +{ + KConfig *config = kapp->config(); + config->setGroup("UI"); + m_openTabAfterCurrent = config->readBoolEntry("OpenNewTabAfterCurrent", true); + m_showIconsOnTabs = config->readBoolEntry("ShowTabIcons", false); +} + +void DMainWindow::saveSettings() +{ + m_leftDock->saveSettings(); + m_rightDock->saveSettings(); + m_bottomDock->saveSettings(); +} + +DMainWindow::~DMainWindow() +{ +/* for (QValueList<QWidget*>::iterator it = m_widgets.begin(); it != m_widgets.end(); ++it) + removeWidget(*it);*/ +} + +DDockWindow *DMainWindow::toolWindow(DDockWindow::Position position) const +{ + switch (position) { + case DDockWindow::Bottom: return m_bottomDock; + case DDockWindow::Left: return m_leftDock; + case DDockWindow::Right: return m_rightDock; + } + return 0; +} + +void DMainWindow::createToolWindows() +{ + m_bottomDock = new DDockWindow(this, DDockWindow::Bottom); + moveDockWindow(m_bottomDock, Qt::DockBottom); + m_leftDock = new DDockWindow(this, DDockWindow::Left); + moveDockWindow(m_leftDock, Qt::DockLeft); + m_rightDock = new DDockWindow(this, DDockWindow::Right); + moveDockWindow(m_rightDock, Qt::DockRight); + + // hide all docks until we add stuff to it + m_bottomDock->hide(); + m_leftDock->hide(); + m_rightDock->hide(); +} + +void DMainWindow::addWidget(QWidget *widget, const QString &title) +{ +// invalidateActiveTabWidget(); + if (m_firstRemoved && m_activeTabWidget == m_tabs.first()) + { + m_central->addDock(0, 0, m_activeTabWidget); + m_firstRemoved = false; + } + + addWidget(m_activeTabWidget, widget, title); +} + +void DMainWindow::addWidget(DTabWidget *tab, QWidget *widget, const QString &title) +{ + static QPixmap emptyPixmap; + + int idx = -1; + if (m_openTabAfterCurrent && (tab->count() > 0)) + idx = tab->currentPageIndex() + 1; + if (m_showIconsOnTabs) + { + const QPixmap *pixmap = widget->icon(); + const QIconSet &icons = (pixmap && (pixmap->size().height() <= 16)) ? *(pixmap) : SmallIcon("kdevelop"); + tab->insertTab(widget, icons, title, idx); + } + else + tab->insertTab(widget, emptyPixmap, title, idx); + m_widgets.append(widget); + m_widgetTabs[widget] = tab; + widget->installEventFilter(this); + tab->showPage(widget); +} + +void DMainWindow::removeWidget(QWidget *widget) +{ + if (!m_widgets.contains(widget)) + return; //not a widget in main window + + if (m_widgetTabs.contains(widget)) + { + DTabWidget *tab = m_widgetTabs[widget]; + if (tab->indexOf(widget) >= 0) + { + tab->removePage(widget); + widget->reparent(0,QPoint(0,0),false); + if (tab->count() == 0) + { + if (tab->closeButton()) + tab->closeButton()->hide(); + //remove and delete tabwidget if it is not the first one + if (tab != m_tabs.first()) + { + QPair<uint, uint> idx = m_central->indexOf(tab); + m_tabs.remove(tab); + m_activeTabWidget = m_tabs.first(); + m_central->removeDock(idx.first, idx.second, true); + } + //only temporarily remove the first tabwidget + else + { + m_central->removeDock(0, 0, false); + m_firstRemoved = true; + } + //focus smth in m_activeTabWidget + if (m_activeTabWidget) + { + if (m_activeTabWidget->currentPage()) + { + m_activeTabWidget->currentPage()->setFocus(); + } + } + } + } + } + + m_widgets.remove(widget); + m_widgetTabs.remove(widget); + if (m_activeTabWidget && m_activeTabWidget->currentPage()) + { + //a hack to please multibuffer and actually switch the active part + QFocusEvent ev(QEvent::FocusIn); + QApplication::sendEvent(m_activeTabWidget->currentPage(), &ev); + } +} + +DTabWidget *DMainWindow::splitHorizontal() +{ + m_activeTabWidget = createTab(); + m_central->addDock(m_central->numRows(), 0, m_activeTabWidget); + return m_activeTabWidget; +} + +DTabWidget *DMainWindow::splitVertical() +{ +// invalidateActiveTabWidget(); + int row = m_central->indexOf(m_activeTabWidget).first; + m_activeTabWidget = createTab(); + m_central->addDock(row, m_central->numCols(row), m_activeTabWidget); + return m_activeTabWidget; +} + +void DMainWindow::invalidateActiveTabWidget() +{ +/* QWidget *focused = m_central->focusWidget(); + kdDebug(9000) << "invalidate: " << focused << endl; + if (focused == 0) + return; + if (!m_widgets.contains(focused)) + { + kdDebug(9000) << " focused is not in m_widgets" << endl; + return; + } + if (m_widgetTabs.contains(focused)) + { + kdDebug(9000) << " focused is in m_widgets and m_widgetTabs" << endl; + DTabWidget *tab = m_widgetTabs[focused]; + if (tab->indexOf(focused) >= 0) + m_activeTabWidget = tab; + kdDebug(9000) << " tab: " << tab << endl; + }*/ +} + +DTabWidget *DMainWindow::createTab() +{ + DTabWidget *tab = new DTabWidget(m_central); + m_tabs.append(tab); + if (tab->closeButton()) + connect(tab->closeButton(), SIGNAL(clicked()), this, SLOT(closeTab())); + connect(tab, SIGNAL(closeRequest(QWidget*)), this, SLOT(closeTab(QWidget*))); + connect(tab, SIGNAL(contextMenu(QWidget*,const QPoint &)), + this, SLOT(tabContext(QWidget*,const QPoint &))); + return tab; +} + +bool DMainWindow::eventFilter(QObject *obj, QEvent *ev) +{ + QWidget *w = (QWidget*)obj; + if (!m_widgets.contains(w)) + return KParts::MainWindow::eventFilter(obj, ev); + + if ((m_currentWidget != w) && (ev->type() == QEvent::FocusIn)) + { + m_currentWidget = w; + emit widgetChanged(w); + } + else if (ev->type() == QEvent::IconChange) + { + if (m_widgetTabs.contains(w)) + { + DTabWidget *tab = m_widgetTabs[w]; + tab->setTabIconSet(w, w->icon() ? (*(w->icon())) : QPixmap()); + } + } + else if (ev->type() == QEvent::CaptionChange) + { + kdDebug(9000) << "caption change" << endl; + DTabWidget *tab = m_widgetTabs[w]; + tab->changeTab(w, w->caption()); + } + + return KParts::MainWindow::eventFilter(obj, ev); +} + +void DMainWindow::closeTab() +{ + //nothing to do here, should be reimplemented +} + +void DMainWindow::tabContext(QWidget *, const QPoint &) +{ + //nothing to do here, should be reimplemented +} + +void DMainWindow::closeTab(QWidget *) +{ + //nothing to do here, should be reimplemented +} + +void DMainWindow::moveWidget(DDockWindow::Position position, QWidget * view, const QString & title) +{ + if (m_docks.contains(view)) + { + toolWindow(m_docks[view])->removeWidget(view); + + toolWindow(position)->addWidget( title, view, true ); + m_docks[view] = position; + } +} + +void DMainWindow::addDockWidget(DDockWindow::Position position, QWidget *view, const QString &title) +{ + DDockWindow* dock = toolWindow(position); + dock->addWidget(title, view); + m_docks[view] = position; + connect(view, SIGNAL(destroyed()), this, SLOT(widgetDestroyed())); + if (dock->isHidden()) + dock->show(); +} + +void DMainWindow::removeDockWidget(QWidget *view) +{ + DDockWindow* dock = toolWindow(m_docks[view]); + dock->removeWidget(view); + m_docks.remove(view); + if (!dock->hasWidgets()) + dock->hide(); +} + +bool DMainWindow::hasDockWidget(QWidget *view) +{ + return m_docks.contains(view); +} + +DDockWindow::Position DMainWindow::dockWidgetPosition(QWidget *view) +{ + return m_docks[view]; +} + +void DMainWindow::widgetDestroyed() +{ + QWidget *w = static_cast<QWidget*>(const_cast<QObject*>(sender())); + + if (m_docks.contains(w)) + { + kdError() << "Widget destroyed before being removed from UI!" << endl; + m_docks.remove(w); + } +} + +#include "dmainwindow.moc" + +// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/apps/ktorrent/newui/dmainwindow.h b/apps/ktorrent/newui/dmainwindow.h new file mode 100644 index 0000000..326d0c0 --- /dev/null +++ b/apps/ktorrent/newui/dmainwindow.h @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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. * + ***************************************************************************/ +#ifndef DMAINWINDOW_H +#define DMAINWINDOW_H + +#include <kxmlguiclient.h> +#include <kparts/mainwindow.h> + +#include "ddockwindow.h" + +class DTabWidget; +namespace Ideal { + class DockSplitter; +} + +/**Main window which provides simplified IDEA mode.*/ +class DMainWindow: public KParts::MainWindow { + Q_OBJECT +public: + DMainWindow(QWidget *parent = 0, const char *name = 0); + virtual ~DMainWindow(); + + /**@return The tool window in given @p position.*/ + DDockWindow *toolWindow(DDockWindow::Position position) const; + + /**Adds a tabbed widget into the active (focused) tab widget. + If @p widget is null then only tab is created.*/ + virtual void addWidget(QWidget *widget, const QString &title); + virtual void addWidget(DTabWidget *tab, QWidget *widget, const QString &title); + /**Removes widget. Does not delete it.*/ + virtual void removeWidget(QWidget *widget); + /**Moves a widget from an existing dockposition to a new position**/ + virtual void moveWidget(DDockWindow::Position newPosition, QWidget *widget, const QString & title); + + /**Adds a dock widget into given position.*/ + virtual void addDockWidget(DDockWindow::Position position, QWidget *view, const QString &title); + /**Removes a dock widget.*/ + virtual void removeDockWidget(QWidget *view); + + virtual void saveSettings(); + + bool hasDockWidget(QWidget *view); + DDockWindow::Position dockWidgetPosition(QWidget *view); + +public slots: + DTabWidget *splitHorizontal(); + DTabWidget *splitVertical(); + +protected slots: + /**This does nothing. Reimplement in subclass to close the tab + when corner close button is pressed.*/ + virtual void closeTab(); + /**This does nothing. Reimplement in subclass to close the tab + when hover close button is pressed.*/ + virtual void closeTab(QWidget*); + /**This does nothing. Reimplement in subclass to show tab context menu.*/ + virtual void tabContext(QWidget*,const QPoint &); + + void widgetDestroyed(); + +signals: + void widgetChanged(QWidget *); + +protected: + bool eventFilter(QObject *obj, QEvent *ev); + + virtual void loadSettings(); + + virtual void createToolWindows(); + virtual DTabWidget *createTab(); + + DDockWindow *m_leftDock; + DDockWindow *m_rightDock; + DDockWindow *m_bottomDock; + + QMap<QWidget*, DDockWindow::Position> m_docks; + + Ideal::DockSplitter *m_central; + DTabWidget *m_activeTabWidget; + + QValueList<DTabWidget*> m_tabs; + + bool m_openTabAfterCurrent; + bool m_showIconsOnTabs; + bool m_firstRemoved; + + QValueList<QWidget*> m_widgets; + QMap<QWidget*, DTabWidget*> m_widgetTabs; + QWidget *m_currentWidget; + +private slots: + void invalidateActiveTabWidget(); + +}; + +#endif diff --git a/apps/ktorrent/newui/docksplitter.cpp b/apps/ktorrent/newui/docksplitter.cpp new file mode 100644 index 0000000..46212f6 --- /dev/null +++ b/apps/ktorrent/newui/docksplitter.cpp @@ -0,0 +1,175 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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 "docksplitter.h" + +#include <kdebug.h> + +namespace Ideal { + +DockSplitter::DockSplitter(Orientation orientation, QWidget *parent, const char *name) + :QSplitter(parent, name), m_orientation(orientation) +{ + switch (m_orientation) + { + case Horizontal: + setOrientation(Vertical); + break; + case Vertical: + setOrientation(Horizontal); + break; + } + setOpaqueResize(true); + appendSplitter(); +} + +DockSplitter::~DockSplitter() +{ +} + +void DockSplitter::addDock(uint row, uint col, QWidget *dock) +{ + if (m_docks.count() <= row) + for (uint i = m_docks.count(); i <= row ; ++i) + m_docks.append(QValueList<QWidget*>()); + + if (m_docks[row].count() <= col) + { + for (uint i = m_docks[row].count(); i <= col ; ++i) + m_docks[row].append(0); + m_docks[row][col] = dock; + } + else if (m_docks[row][col] == 0) + m_docks[row][col] = dock; + else + m_docks[row].insert(m_docks[row].at(col), dock); + + if (m_splitters.count() <= row) + createSplitters(row); + QSplitter *splitter = m_splitters[row]; + + dock->reparent(splitter, QPoint(0,0), true); + if (col < m_docks[row].count()-1) + shiftWidgets(splitter, row, col+1); +} + +void DockSplitter::appendSplitter() +{ + switch (m_orientation) + { + case Horizontal: + m_splitters.append(new QSplitter(Horizontal, this)); + break; + case Vertical: + m_splitters.append(new QSplitter(Vertical, this)); + break; + } + m_splitters[m_splitters.size()-1]->setOpaqueResize(true); + m_splitters[m_splitters.size()-1]->show(); +} + +void DockSplitter::createSplitters(uint index) +{ + kdDebug(9000) << "DockSplitter::createSplitters index = " << index << " count = " << m_splitters.count() << endl; + for (uint i = m_splitters.count(); i <= index; ++i) + { + kdDebug(9000) << " appendSplitter..." << endl; + appendSplitter(); + } +} + +void DockSplitter::removeDock(uint row, uint col, bool alsoDelete) +{ + if ((row >= m_docks.count()) || (col >= m_docks[row].count())) + return; + + QWidget *w = m_docks[row][col]; + m_docks[row].remove(m_docks[row].at(col)); + + if (alsoDelete) + { + delete w; + w = 0; + } + else + { + w->reparent(0, QPoint(0,0), false); + w->hide(); + } + + m_splitters[row]->setMinimumSize(m_splitters[row]->minimumSizeHint()); + + if (isRowEmpty(row)) + { + m_docks.remove(m_docks.at(row)); + delete m_splitters[row]; + m_splitters[row] = 0; + m_splitters.remove(m_splitters.at(row)); + } +} + +bool DockSplitter::isRowEmpty(int row) +{ + if (m_docks[row].count() == 0) + return true; + for (uint i = 0; i < m_docks[row].count(); ++i) + if (m_docks[row][i] != 0) + return false; + return true; +} + +void DockSplitter::shiftWidgets(QSplitter *splitter, uint row, uint fromCol) +{ + kdDebug(9000) << "shiftWidgets: row=" << row << " from col=" << fromCol << endl; + kdDebug(9000) << "row size is: " << m_docks[row].count() << endl; + + for (uint i = fromCol; i < m_docks[row].count(); ++i) + { + kdDebug(9000) << "move from " << i << " to last" << endl; + if (m_docks[row][i]) + splitter->moveToLast(m_docks[row][i]); + else + kdDebug(9000) << "m_docks[" << row << "][" << i << "] is 0" << endl; + } +} + +int DockSplitter::numRows() const +{ + return m_docks.count(); +} + +int DockSplitter::numCols(int row) const +{ + if (row < numRows()) + return m_docks[row].count(); + return 0; +} + +QPair<uint, uint> DockSplitter::indexOf(QWidget *dock) +{ + for (uint i = 0; i < m_docks.count(); ++i) + for (uint j = 0; j < m_docks[i].count(); ++j) + if (dock == m_docks[i][j]) + return qMakePair(i, j); + return qMakePair(0u, 0u); +} + +} + +#include "docksplitter.moc" diff --git a/apps/ktorrent/newui/docksplitter.h b/apps/ktorrent/newui/docksplitter.h new file mode 100644 index 0000000..214ad52 --- /dev/null +++ b/apps/ktorrent/newui/docksplitter.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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. * + ***************************************************************************/ +#ifndef IDEALDOCKSPLITTER_H +#define IDEALDOCKSPLITTER_H + +#include <qsplitter.h> +#include <qvaluelist.h> + +namespace Ideal { + +class DockWidget; + +/** +@short Splitter for docks +*/ +class DockSplitter: public QSplitter { + Q_OBJECT +public: + DockSplitter(Orientation orientation, QWidget *parent = 0, const char *name = 0); + ~DockSplitter(); + + void addDock(uint row, uint col, QWidget *dock); + void removeDock(uint row, uint col, bool alsoDelete = false); + + QPair<uint, uint> indexOf(QWidget *dock); + + int numRows() const; + int numCols(int row) const; + +protected: + void appendSplitter(); + void createSplitters(uint index); + void shiftWidgets(QSplitter *splitter, uint row, uint fromCol); + + bool isRowEmpty(int row); + +private: + Orientation m_orientation; + QValueList<QSplitter*> m_splitters; + QValueList<QValueList<QWidget*> > m_docks; +}; + +} + +#endif diff --git a/apps/ktorrent/newui/dtabwidget.cpp b/apps/ktorrent/newui/dtabwidget.cpp new file mode 100644 index 0000000..2bfd188 --- /dev/null +++ b/apps/ktorrent/newui/dtabwidget.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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 "dtabwidget.h" + +#include <qtoolbutton.h> +#include <qtabbar.h> + +#include <kconfig.h> +#include <kiconloader.h> +#include <kapplication.h> + +DTabWidget::DTabWidget(QWidget *parent, const char *name) + :KTabWidget(parent, name), m_closeButton(0) +{ + setFocusPolicy(NoFocus); + setMargin(0); + + loadSettings(); + + if (!m_tabBarShown) + tabBar()->hide(); + else { + m_closeButton = new QToolButton(this); + m_closeButton->setIconSet(SmallIconSet("tab_remove")); + m_closeButton->adjustSize(); + m_closeButton->hide(); + setCornerWidget(m_closeButton, TopRight); + + if (m_closeOnHover) + setHoverCloseButton(true); + + setTabReorderingEnabled(true); + } + + connect(this, SIGNAL(currentChanged(QWidget*)), this, SLOT(setFocus(QWidget*))); +// connect(this, SIGNAL(currentChanged(QWidget*)), this, SLOT(updateHistory(QWidget*))); +} + +void DTabWidget::loadSettings() +{ + /* + KConfig *config = kapp->config(); + config->setGroup("UI"); +// m_tabBarShown = config->readBoolEntry("TabBarShown", true); + m_tabBarShown = ! config->readNumEntry("TabWidgetVisibility", 0); + m_closeOnHover = config->readBoolEntry("CloseOnHover", false); + m_closeButtonShown = config->readBoolEntry("ShowCloseTabsButton", true); + //we do not delay hover close buttons - that looks and feels ugly + setHoverCloseButtonDelayed(false); + */ + m_tabBarShown = true; + m_closeOnHover = false; + m_closeButtonShown = true; +} + +void DTabWidget::saveSettings() +{ +} + +QToolButton *DTabWidget::closeButton() const +{ + return m_closeButton; +} + +void DTabWidget::setFocus(QWidget *w) +{ + if (w) + w->setFocus(); +} + +void DTabWidget::insertTab(QWidget *child, const QString &label, int index) +{ + if (m_closeButton && m_closeButtonShown) + m_closeButton->show(); + KTabWidget::insertTab(child, label, index); + if (index != -1) tabBar()->repaint(); +} + +void DTabWidget::insertTab(QWidget *child, const QIconSet &iconset, + const QString &label, int index) +{ + if (m_closeButton && m_closeButtonShown) + m_closeButton->show(); + KTabWidget::insertTab(child, iconset, label, index); + if (index != -1) tabBar()->repaint(); +} + +/*void DTabWidget::updateHistory(QWidget *w) +{ + if (m_history.top() != w) + m_history.push(w); +}*/ + +#include "dtabwidget.moc" diff --git a/apps/ktorrent/newui/dtabwidget.h b/apps/ktorrent/newui/dtabwidget.h new file mode 100644 index 0000000..4f51e47 --- /dev/null +++ b/apps/ktorrent/newui/dtabwidget.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * 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 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. * + ***************************************************************************/ +#ifndef DTABWIDGET_H +#define DTABWIDGET_H + +#include <ktabwidget.h> + +class QToolButton; + +class DTabWidget: public KTabWidget { + Q_OBJECT +public: + DTabWidget(QWidget *parent=0, const char *name=0); + + /**@return The close button at the top right corner. + May be 0 if the configuration do not allow close buttons or the tabbar.*/ + QToolButton *closeButton() const; + + virtual void insertTab(QWidget *child, const QString &label, int index = -1 ); + virtual void insertTab(QWidget *child, const QIconSet &iconset, + const QString &label, int index = -1); + +protected: + virtual void loadSettings(); + virtual void saveSettings(); + +private slots: + void setFocus(QWidget *w); +// void updateHistory(QWidget *w); + +private: + bool m_tabBarShown; + bool m_closeOnHover; + bool m_closeButtonShown; + + QToolButton *m_closeButton; +// QValueStack<QWidget*> *m_history; + +}; + +#endif diff --git a/apps/ktorrent/pastedialog.cpp b/apps/ktorrent/pastedialog.cpp new file mode 100644 index 0000000..aa0095a --- /dev/null +++ b/apps/ktorrent/pastedialog.cpp @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@gmail.com * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "pastedialog.h" +#include "ktorrentcore.h" +#include <kpushbutton.h> +#include <kstdguiitem.h> +#include <qclipboard.h> +#include <qapplication.h> +#include <kurl.h> +#include <klineedit.h> +#include <kmessagebox.h> +#include <klocale.h> + +PasteDialog::PasteDialog(KTorrentCore* core, QWidget *parent, const char *name) + :PasteDlgBase(parent, name) +{ + m_core = core; + QClipboard *cb = QApplication::clipboard(); + QString text = cb->text(QClipboard::Clipboard); + KURL url = KURL::fromPathOrURL(text); + if ( url.isValid() ) + m_url->setText(url.url()); + + btnOK->setGuiItem(KStdGuiItem::ok()); + btnCancel->setGuiItem(KStdGuiItem::cancel()); +} + +void PasteDialog::btnOK_clicked() +{ + KURL url = KURL::fromPathOrURL(m_url->text()); + if ( url.isValid() ) + { + m_core->load(url); + QDialog::accept(); + } + else + { + KMessageBox::error(this,i18n("Malformed URL.")); + } +} + + + +#include "pastedialog.moc" diff --git a/apps/ktorrent/pastedialog.h b/apps/ktorrent/pastedialog.h new file mode 100644 index 0000000..83b783d --- /dev/null +++ b/apps/ktorrent/pastedialog.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@gmail.com * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 PASTEDIALOG_H +#define PASTEDIALOG_H + +#include "pastedlgbase.h" +class KTorrentCore; + +/** + * @author Ivan Vasic + * @brief Torrent URL paste dialog + **/ +class PasteDialog: public PasteDlgBase +{ + Q_OBJECT +public slots: + virtual void btnOK_clicked(); + + public: + PasteDialog(KTorrentCore* core, QWidget *parent = 0, const char *name = 0); + + private: + KTorrentCore* m_core; +}; + +#endif diff --git a/apps/ktorrent/pastedlgbase.ui b/apps/ktorrent/pastedlgbase.ui new file mode 100644 index 0000000..0d3b813 --- /dev/null +++ b/apps/ktorrent/pastedlgbase.ui @@ -0,0 +1,142 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>PasteDlgBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>PasteDlgBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>467</width> + <height>84</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>4</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="caption"> + <string>Paste URL</string> + </property> + <property name="modal"> + <bool>true</bool> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>URL:</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>m_url</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>400</width> + <height>0</height> + </size> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>297</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnOK</cstring> + </property> + <property name="text"> + <string>O&K</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnCancel</cstring> + </property> + <property name="text"> + <string>C&ancel</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>btnOK</sender> + <signal>clicked()</signal> + <receiver>PasteDlgBase</receiver> + <slot>btnOK_clicked()</slot> + </connection> + <connection> + <sender>btnCancel</sender> + <signal>clicked()</signal> + <receiver>PasteDlgBase</receiver> + <slot>reject()</slot> + </connection> +</connections> +<slots> + <slot>btnOK_clicked()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/pref.cpp b/apps/ktorrent/pref.cpp new file mode 100644 index 0000000..c1937f6 --- /dev/null +++ b/apps/ktorrent/pref.cpp @@ -0,0 +1,508 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <klocale.h> +#include <kstandarddirs.h> +#include <kactivelabel.h> +#include <kglobal.h> +#include <kcombobox.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qcheckbox.h> +#include <knuminput.h> +#include <kurlrequester.h> +#include <kurl.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <klineedit.h> +#include <qlistview.h> +#include <torrent/globals.h> +#include <util/functions.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <qdir.h> +#include <qslider.h> +#include <kresolver.h> + +#include "downloadpref.h" +#include "generalpref.h" +#include "pref.h" +#include "downloadpref.h" +#include "advancedpref.h" +#include "settings.h" +#include "ktorrent.h" + + +using namespace bt; + +using namespace KNetwork; + + +KTorrentPreferences::KTorrentPreferences(KTorrent & ktor) + : KDialogBase(IconList, i18n("Preferences"), Ok | Apply | Cancel, Ok), ktor(ktor) +{ + validation_err = false; + enableButtonSeparator(true); + + page_one = new DownloadPrefPage(); + page_two = new GeneralPrefPage(); + page_three = new AdvancedPrefPage(); + addPrefPage(page_one); + addPrefPage(page_two); + addPrefPage(page_three); +} + +KTorrentPreferences::~KTorrentPreferences() +{ + delete page_one; + delete page_two; + delete page_three; +} + +void KTorrentPreferences::slotOk() +{ + slotApply(); + + if (!validation_err) + accept(); +} + +void KTorrentPreferences::slotApply() +{ + validation_err = false; + QMap<kt::PrefPageInterface*, QFrame*>::iterator i = pages.begin(); + + while (i != pages.end()) + { + kt::PrefPageInterface* p = i.key(); + + if (!p->apply()) + { + validation_err = true; + return; + } + + i++; + } + + Settings::writeConfig(); + + ktor.applySettings(true); +} + +void KTorrentPreferences::updateData() +{ + QMap<kt::PrefPageInterface*, QFrame*>::iterator i = pages.begin(); + + while (i != pages.end()) + { + kt::PrefPageInterface* p = i.key(); + p->updateData(); + i++; + } +} + +void KTorrentPreferences::addPrefPage(kt::PrefPageInterface* prefInterface) +{ + QFrame* frame = addPage(prefInterface->getItemName(), prefInterface->getHeader(), prefInterface->getPixmap()); + QVBoxLayout* vbox = new QVBoxLayout(frame); + vbox->setAutoAdd(true); + prefInterface->createWidget(frame); + + pages.insert(prefInterface, frame); +} + +void KTorrentPreferences::removePrefPage(kt::PrefPageInterface* pp) +{ + if (!pages.contains(pp)) + return; + + QFrame* fr = pages[pp]; + + pages.remove(pp); + + pp->deleteWidget(); + + delete fr; +} + +/////////////////////////////////////////////////////// + +DownloadPrefPage::DownloadPrefPage() : kt::PrefPageInterface(i18n("Downloads"), i18n("Download Options"), KGlobal::iconLoader()->loadIcon("down", KIcon::NoGroup)), dp(0) +{} + +DownloadPrefPage::~ DownloadPrefPage() +{ + delete dp; +} + +void DownloadPrefPage::createWidget(QWidget* parent) +{ + dp = new DownloadPref(parent); + updateData(); +} + +bool DownloadPrefPage::apply() +{ + Settings::setMaxDownloads(dp->max_downloads->value()); + Settings::setMaxSeeds(dp->max_seeds->value()); + Settings::setStartDownloadsOnLowDiskSpace(dp->cmbDiskSpace->currentItem()); + Settings::setMaxConnections(dp->max_conns->value()); + Settings::setMaxTotalConnections(dp->max_total_conns->value()); + Settings::setMaxUploadRate(dp->max_upload_rate->value()); + Settings::setMaxDownloadRate(dp->max_download_rate->value()); + Settings::setMaxRatio(dp->num_max_ratio->value()); + Settings::setKeepSeeding(dp->keep_seeding->isChecked()); + Settings::setPort(dp->port->value()); + Settings::setNumUploadSlots(dp->num_upload_slots->value()); + Settings::setMinDiskSpace(dp->intMinDiskSpace->value()); + Settings::setMaxSeedTime(dp->max_seed_time->value()); + + if (Settings::dhtSupport() && dp->udp_tracker_port->value() == Settings::dhtPort()) + { + QString msg = i18n("The DHT port needs to be different from the UDP tracker port!"); + KMessageBox::error(0, msg, i18n("Error")); + return false; + } + + Settings::setUdpTrackerPort(dp->udp_tracker_port->value()); + + return true; +} + +void DownloadPrefPage::updateData() +{ + //setMinimumSize(400,400); + dp->max_downloads->setValue(Settings::maxDownloads()); + dp->max_seeds->setValue(Settings::maxSeeds()); + dp->cmbDiskSpace->setCurrentItem(Settings::startDownloadsOnLowDiskSpace()); + dp->max_conns->setValue(Settings::maxConnections()); + dp->max_total_conns->setValue(Settings::maxTotalConnections()); + dp->max_upload_rate->setValue(Settings::maxUploadRate()); + dp->max_download_rate->setValue(Settings::maxDownloadRate()); + dp->num_max_ratio->setValue(Settings::maxRatio()); + dp->keep_seeding->setChecked(Settings::keepSeeding()); + dp->udp_tracker_port->setValue(Settings::udpTrackerPort()); + dp->port->setValue(Settings::port()); + dp->num_upload_slots->setValue(Settings::numUploadSlots()); + dp->intMinDiskSpace->setValue(Settings::minDiskSpace()); + dp->max_seed_time->setValue(Settings::maxSeedTime()); +} + +void DownloadPrefPage::deleteWidget() +{ + delete dp; + dp = 0; +} + +////////////////////////////////////// +GeneralPrefPage::GeneralPrefPage() : + kt::PrefPageInterface(i18n("General"), i18n("General Options"), + KGlobal::iconLoader()->loadIcon("package_settings", KIcon::NoGroup)), gp(0) +{} + +GeneralPrefPage::~GeneralPrefPage() +{ + delete gp; +} + +void GeneralPrefPage::createWidget(QWidget* parent) +{ + gp = new GeneralPref(parent); + updateData(); + connect(gp->custom_ip_check, SIGNAL(toggled(bool)), + this, SLOT(customIPChecked(bool))); + connect(gp->use_dht, SIGNAL(toggled(bool)), + this, SLOT(dhtChecked(bool))); + connect(gp->use_encryption, SIGNAL(toggled(bool)), + this, SLOT(useEncryptionChecked(bool))); +} + +bool GeneralPrefPage::apply() +{ + Settings::setShowSystemTrayIcon(gp->show_systray_icon->isChecked()); + Settings::setShowSpeedBarInTrayIcon(gp->show_speedbar->isChecked()); + Settings::setDownloadBandwidth(gp->downloadBandwidth->value()); + Settings::setUploadBandwidth(gp->uploadBandwidth->value()); + Settings::setShowPopups(gp->show_popups->isChecked()); + QString ourl = Settings::tempDir(); + + KURLRequester* u = gp->temp_dir; + + if (ourl != u->url()) + { + Settings::setTempDir(u->url()); + } + + Settings::setSaveDir(gp->autosave_location->url()); + + bool useSaveDir = gp->autosave_downloads_check->isChecked(); + Settings::setUseSaveDir(useSaveDir); + + //check completed dir + Settings::setCompletedDir(gp->urlCompletedDir->url()); + + bool useCompletedDir = gp->checkCompletedDir->isChecked(); + Settings::setUseCompletedDir(useCompletedDir); + + //.torrent copy dir + bool useTorrentCopyDir = gp->checkTorrentDir->isChecked(); + Settings::setUseTorrentCopyDir(useTorrentCopyDir); + Settings::setTorrentCopyDir(gp->urlTorrentDir->url()); + + bool useExternalIP = gp->custom_ip_check->isChecked(); + + Settings::setUseExternalIP(useExternalIP); + QString externalIP = gp->custom_ip->text(); + Settings::setExternalIP(externalIP); + + if (useExternalIP) + { + + KResolverResults res = KResolver::resolve(externalIP, QString::null); + + if (res.error()) + { + QString err = KResolver::errorString(res.error()); + QString msg = i18n("Cannot lookup %1: %2\n" + "Please provide a valid IP address or hostname.").arg(externalIP).arg(err); + KMessageBox::error(0, msg, i18n("Error")); + return false; + } + } + + + + if (gp->use_dht->isChecked() && gp->dht_port->value() == Settings::udpTrackerPort()) + { + QString msg = i18n("The DHT port needs to be different from the UDP tracker port!"); + KMessageBox::error(0, msg, i18n("Error")); + return false; + } + + Settings::setDhtSupport(gp->use_dht->isChecked()); + + Settings::setDhtPort(gp->dht_port->value()); + Settings::setUseEncryption(gp->use_encryption->isChecked()); + Settings::setAllowUnencryptedConnections(gp->allow_unencrypted->isChecked()); + return true; +} + +void GeneralPrefPage::useEncryptionChecked(bool on) +{ + gp->allow_unencrypted->setEnabled(on); +} + +void GeneralPrefPage::autosaveChecked(bool on) +{ + gp->autosave_location->setEnabled(on); +} + +void GeneralPrefPage::customIPChecked(bool on) +{ + gp->custom_ip->setEnabled(on); + gp->custom_ip_label->setEnabled(on); +} + +void GeneralPrefPage::dhtChecked(bool on) +{ + gp->dht_port->setEnabled(on); + gp->dht_port_label->setEnabled(on); +} + +void GeneralPrefPage::updateData() +{ + gp->show_systray_icon->setChecked(Settings::showSystemTrayIcon()); + gp->show_speedbar->setChecked(Settings::showSpeedBarInTrayIcon()); + gp->downloadBandwidth->setValue(Settings::downloadBandwidth()); + gp->uploadBandwidth->setValue(Settings::uploadBandwidth()); + gp->show_popups->setChecked(Settings::showPopups()); + KURLRequester* u = gp->temp_dir; + u->fileDialog()->setMode(KFile::Directory); + + if (Settings::tempDir() == QString::null) + { + QString data_dir = KGlobal::dirs()->saveLocation("data", "ktorrent"); + + if (!data_dir.endsWith(bt::DirSeparator())) + data_dir += bt::DirSeparator(); + + u->setURL(data_dir); + } + else + { + u->setURL(Settings::tempDir()); + } + + u = gp->autosave_location; + + u->fileDialog()->setMode(KFile::Directory); + + bool useSaveDir = Settings::useSaveDir(); + QString saveDir = Settings::saveDir(); + + gp->autosave_downloads_check->setChecked(useSaveDir); + u->setEnabled(useSaveDir); + + u->setURL(!saveDir.isEmpty() ? saveDir : QDir::homeDirPath()); + + + //completed dir + u = gp->urlCompletedDir; + u->fileDialog()->setMode(KFile::Directory); + bool useCompletedDir = Settings::useCompletedDir(); + QString completedDir = Settings::completedDir(); + gp->checkCompletedDir->setChecked(useCompletedDir); + u->setEnabled(useCompletedDir); + u->setURL(!completedDir.isEmpty() ? completedDir : QDir::homeDirPath()); + + //copy .torrent dir + u = gp->urlTorrentDir; + u->fileDialog()->setMode(KFile::Directory); + bool useTorrentDir = Settings::useTorrentCopyDir(); + QString torrentDir = Settings::torrentCopyDir(); + gp->checkTorrentDir->setChecked(useTorrentDir); + u->setEnabled(useTorrentDir); + u->setURL(!torrentDir.isEmpty() ? torrentDir : QDir::homeDirPath()); + + + gp->custom_ip->setText(Settings::externalIP()); + + bool useExternalIP = Settings::useExternalIP(); + gp->custom_ip_check->setChecked(useExternalIP); + gp->custom_ip->setEnabled(useExternalIP); + gp->custom_ip_label->setEnabled(useExternalIP); + + gp->use_dht->setChecked(Settings::dhtSupport()); + gp->dht_port->setValue(Settings::dhtPort()); + gp->dht_port->setEnabled(Settings::dhtSupport()); + gp->dht_port_label->setEnabled(Settings::dhtSupport()); + + gp->use_encryption->setChecked(Settings::useEncryption()); + gp->allow_unencrypted->setChecked(Settings::allowUnencryptedConnections()); + gp->allow_unencrypted->setEnabled(Settings::useEncryption()); +} + +void GeneralPrefPage::deleteWidget() +{ + delete gp; + gp = 0; +} + +///////////////////////////////// + +AdvancedPrefPage::AdvancedPrefPage() : + kt::PrefPageInterface(i18n("Advanced"), i18n("Advanced Options"), + KGlobal::iconLoader()->loadIcon("package_settings", KIcon::NoGroup)), ap(0) +{} + +AdvancedPrefPage::~AdvancedPrefPage() +{ + delete ap; +} + +bool AdvancedPrefPage::apply() +{ + Settings::setMemoryUsage(ap->mem_usage->currentItem()); + Settings::setGuiUpdateInterval(ap->gui_interval->currentItem()); + Settings::setDSCP(ap->dscp->value()); + Settings::setAllwaysDoUploadDataCheck(!ap->no_recheck->isChecked()); + Settings::setMaxSizeForUploadDataCheck(ap->recheck_size->value()); + Settings::setAutoRecheck(ap->auto_recheck->isChecked()); + Settings::setMaxCorruptedBeforeRecheck(ap->num_corrupted->value()); + Settings::setDoNotUseKDEProxy(ap->do_not_use_kde_proxy->isChecked()); + Settings::setHttpTrackerProxy(ap->http_proxy->text()); + Settings::setEta(ap->eta->currentItem()); + Settings::setFullDiskPrealloc(ap->full_prealloc->isChecked()); + Settings::setFullDiskPreallocMethod(ap->full_prealloc_method->currentItem()); + Settings::setCpuUsage(ap->cpu_usage->value()); + Settings::setDiskPrealloc(!ap->prealloc_disabled->isChecked()); + Settings::setMaxConnectingSockets(ap->max_con_setups->value()); + return true; +} + +void AdvancedPrefPage::updateData() +{ + ap->mem_usage->setCurrentItem(Settings::memoryUsage()); + ap->gui_interval->setCurrentItem(Settings::guiUpdateInterval()); + ap->dscp->setValue(Settings::dSCP()); + ap->no_recheck->setChecked(!Settings::allwaysDoUploadDataCheck()); + ap->recheck_size->setEnabled(!Settings::allwaysDoUploadDataCheck()); + ap->recheck_size->setValue(Settings::maxSizeForUploadDataCheck()); + ap->auto_recheck->setChecked(Settings::autoRecheck()); + ap->num_corrupted->setValue(Settings::maxCorruptedBeforeRecheck()); + ap->num_corrupted->setEnabled(Settings::autoRecheck()); + ap->do_not_use_kde_proxy->setChecked(Settings::doNotUseKDEProxy()); + ap->http_proxy->setText(Settings::httpTrackerProxy()); + ap->http_proxy->setEnabled(Settings::doNotUseKDEProxy()); + ap->eta->setCurrentItem(Settings::eta()); + ap->full_prealloc->setChecked(Settings::fullDiskPrealloc()); + ap->full_prealloc_method->setCurrentItem(Settings::fullDiskPreallocMethod()); + ap->cpu_usage->setValue(Settings::cpuUsage()); + ap->prealloc_disabled->setChecked(!Settings::diskPrealloc()); + ap->max_con_setups->setValue(Settings::maxConnectingSockets()); +} + +void AdvancedPrefPage::createWidget(QWidget* parent) +{ + ap = new AdvancedPref(parent); + updateData(); + connect(ap->no_recheck, SIGNAL(toggled(bool)), + this, SLOT(noDataCheckChecked(bool))); + connect(ap->auto_recheck, SIGNAL(toggled(bool)), + this, SLOT(autoRecheckChecked(bool))); + connect(ap->do_not_use_kde_proxy, SIGNAL(toggled(bool)), + this, SLOT(doNotUseKDEProxyChecked(bool))); + connect(ap->prealloc_disabled,SIGNAL(toggled(bool)), + this,SLOT(preallocDisabledChecked(bool))); + + preallocDisabledChecked(ap->prealloc_disabled->isChecked()); +} + +void AdvancedPrefPage::deleteWidget() +{ + delete ap; + ap = 0; +} + +void AdvancedPrefPage::noDataCheckChecked(bool on) +{ + ap->recheck_size->setEnabled(on); +} + +void AdvancedPrefPage::autoRecheckChecked(bool on) +{ + ap->num_corrupted->setEnabled(on); +} + +void AdvancedPrefPage::doNotUseKDEProxyChecked(bool on) +{ + ap->http_proxy->setEnabled(on); +} + +void AdvancedPrefPage::preallocDisabledChecked(bool on) +{ + ap->full_prealloc->setEnabled(!on); + if (!on && ap->full_prealloc->isChecked()) + ap->full_prealloc_method->setEnabled(true); + else + ap->full_prealloc_method->setEnabled(false); +} + +#include "pref.moc" diff --git a/apps/ktorrent/pref.h b/apps/ktorrent/pref.h new file mode 100644 index 0000000..f8852cd --- /dev/null +++ b/apps/ktorrent/pref.h @@ -0,0 +1,121 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 _KTORRENTPREF_H_ +#define _KTORRENTPREF_H_ + +#include <kdialogbase.h> +#include <qframe.h> +#include <qmap.h> +#include <interfaces/prefpageinterface.h> + + +class DownloadPref; +class GeneralPref; +class AdvancedPref; +class KTorrent; +class QListViewItem; + + +class DownloadPrefPage : public kt::PrefPageInterface +{ + DownloadPref* dp; +public: + DownloadPrefPage(); + virtual ~DownloadPrefPage(); + + virtual bool apply(); + virtual void updateData(); + virtual void createWidget(QWidget* parent); + virtual void deleteWidget(); +}; + +class GeneralPrefPage : public QObject,public kt::PrefPageInterface +{ + Q_OBJECT + GeneralPref* gp; +public: + GeneralPrefPage(); + virtual ~GeneralPrefPage(); + + virtual bool apply(); + virtual void updateData(); + virtual void createWidget(QWidget* parent); + virtual void deleteWidget(); + +private slots: + void autosaveChecked(bool on); + void customIPChecked(bool on); + void dhtChecked(bool on); + void useEncryptionChecked(bool on); +}; + +class AdvancedPrefPage : public QObject,public kt::PrefPageInterface +{ + Q_OBJECT + + AdvancedPref* ap; +public: + AdvancedPrefPage(); + virtual ~AdvancedPrefPage(); + + virtual bool apply(); + virtual void updateData(); + virtual void createWidget(QWidget* parent); + virtual void deleteWidget(); + +private slots: + void noDataCheckChecked(bool on); + void autoRecheckChecked(bool on); + void doNotUseKDEProxyChecked(bool on); + void preallocDisabledChecked(bool on); +}; + + +class KTorrentPreferences : public KDialogBase +{ + Q_OBJECT +public: + KTorrentPreferences(KTorrent & ktor); + virtual ~KTorrentPreferences(); + + void updateData(); + void addPrefPage(kt::PrefPageInterface* prefInterface); + void removePrefPage(kt::PrefPageInterface* prefInterface); +private: + virtual void slotOk(); + virtual void slotApply(); + + +private: + KTorrent & ktor; + DownloadPrefPage* page_one; + GeneralPrefPage* page_two; + AdvancedPrefPage* page_three; + QMap<kt::PrefPageInterface*,QFrame*> pages; + bool validation_err; +}; + + + + + +#endif // _KTORRENTPREF_H_ diff --git a/apps/ktorrent/queuedialog.cpp b/apps/ktorrent/queuedialog.cpp new file mode 100644 index 0000000..11a7b95 --- /dev/null +++ b/apps/ktorrent/queuedialog.cpp @@ -0,0 +1,391 @@ +/*************************************************************************** + * Copyright (C) 2005 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 "queuedialog.h" +#include <interfaces/torrentinterface.h> +#include <interfaces/functions.h> +#include <torrent/queuemanager.h> + +#include <qlistview.h> +#include <qstring.h> +#include <qmessagebox.h> +#include <qptrlist.h> +#include <qlabel.h> +#include <qtabwidget.h> +#include <qgroupbox.h> +#include <qpushbutton.h> +#include <qlayout.h> + +#include <klocale.h> +#include <kglobal.h> +#include <kurl.h> +#include <kiconloader.h> +#include <ksqueezedtextlabel.h> +#include <ktabwidget.h> +#include <kpushbutton.h> +#include <kiconloader.h> + +using namespace bt; +using namespace kt; + +QueueItem::QueueItem(kt::TorrentInterface* t, QListView* parent) + :QListViewItem(parent), tc(t) +{ + setPriority(tc->getPriority()); + setText(0, QString(tc->getStats().torrent_name)); +} + +int QueueItem::compare(QListViewItem *i, int , bool ) const +{ + QueueItem* it = (QueueItem*) i; + if(it->getPriority() == torrentPriority) + { + const TorrentInterface* ti = it->getTC(); + QString name1 = tc->getStats().torrent_name; + QString name2 = ti->getStats().torrent_name; + return name1.compare(name2); + } + + return it->getPriority() < torrentPriority ? -1 : 1; +} + +void QueueItem::setPriority(int p) +{ + torrentPriority = p; + + if(p==0) + setText(1, i18n("User")); + else + setText(1, i18n("Queue Manager")); +} + +void QueueItem::setTorrentPriority(int p) +{ + tc->setPriority(p); +} + +void QueueItem::paintCell(QPainter* p,const QColorGroup & cg,int column,int width,int align) +{ + QColorGroup colorGrp( cg ); + QColor txt = colorGrp.text(); + + //if (column == 1) + if(torrentPriority == 0) + colorGrp.setColor(QColorGroup::Text, Qt::gray); + else + colorGrp.setColor(QColorGroup::Text, txt); + + + QListViewItem::paintCell(p,colorGrp,column,width,align); +} + +QueueDialog::QueueDialog(bt::QueueManager* qm, QWidget *parent, const char *name) + :QueueDlg(parent, name) +{ + KIconLoader* iload = KGlobal::iconLoader(); + + m_tabs->setTabIconSet(m_tabs->page(0), iload->loadIconSet("down", KIcon::Small)); + m_tabs->setTabIconSet(m_tabs->page(1), iload->loadIconSet("up", KIcon::Small)); + + logo->setPixmap(iload->loadIcon("ktqueuemanager", KIcon::Desktop)); + + connect(downloadList, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(downloadList_currentChanged( QListViewItem* ))); + connect(seedList, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(seedList_currentChanged( QListViewItem* ))); + + if(downloadList->firstChild()) + downloadList->setCurrentItem(downloadList->firstChild()); + + if(seedList->firstChild()) + seedList->setCurrentItem(seedList->firstChild()); + + btnMoveUp->setPixmap(iload->loadIcon("up", KIcon::Small)); + btnMoveDown->setPixmap(iload->loadIcon("down", KIcon::Small)); + + this->qman = qm; + + QPtrList<kt::TorrentInterface>::iterator it = qman->begin(); + for( ; it != qman->end(); ++it) + { + TorrentInterface* tc = *it; + TorrentStatus ts = tc->getStats().status; + + if(ts == kt::SEEDING || ts == kt::DOWNLOAD_COMPLETE || + ts == kt::SEEDING_COMPLETE || tc->getStats().completed) + { + QueueItem* item = new QueueItem(tc, seedList); + seedList->insertItem(item); + } + else + { + QueueItem* item = new QueueItem(tc, downloadList); + downloadList->insertItem(item); + } + } +} + +void QueueDialog::btnMoveUp_clicked() +{ + QueueItem* current = (QueueItem*) getCurrentList()->selectedItem(); + if(current == 0) + return; + + if(current->getPriority() == 0) + return; + + QueueItem* previous = (QueueItem*) current->itemAbove(); + if(previous == 0) + return; + else + { + int tmp = previous->getPriority(); + previous->setPriority(current->getPriority()); + current->setPriority(tmp); + getCurrentList()->sort(); + } +} + +void QueueDialog::btnMoveDown_clicked() +{ + QueueItem* current = (QueueItem*) getCurrentList()->selectedItem(); + if(current == 0) + return; + + if(current->getPriority() == 0) + return; + + QueueItem* previous = (QueueItem*) current->itemBelow(); + if(previous == 0) + return; + else + { + int tmp = previous->getPriority(); + if(tmp == 0) + return; + previous->setPriority(current->getPriority()); + current->setPriority(tmp); + getCurrentList()->sort(); + } +} + +void QueueDialog::btnClose_clicked() +{ + this->close(); +} + +void QueueDialog::btnEnqueue_clicked() +{ + enqueue(); +} + +void QueueDialog::btnDequeue_clicked() +{ + QueueItem* current = (QueueItem*) getCurrentList()->selectedItem(); + if(current == 0) + return; + if(current->getPriority() == 0) + return; + + current->setPriority(0); + getCurrentList()->sort(); +} + +void QueueDialog::enqueue(QueueItem* curr) +{ + QueueItem* current = curr == 0 ? (QueueItem*) getCurrentList()->selectedItem() : curr; + if(current == 0) + return; + if(current->getPriority() != 0) + return; + + QueueItem* item = (QueueItem*) getCurrentList()->firstChild(); + if(item == 0) + return; + + while(item != 0) + { + if(item->getPriority() != 0) + item->setPriority(item->getPriority() + 1); + item = (QueueItem*) item->itemBelow(); + } + + current->setPriority(1); + getCurrentList()->sort(); +} + +void QueueDialog::writeQueue() +{ + downloadList->sort(); + seedList->sort(); + + int p = 0; + + QueueItem* item = (QueueItem*) downloadList->lastItem(); + if(item != 0) + { + while(item != 0) + { + if(item->getPriority() != 0) + item->setTorrentPriority(++p); + else + item->setTorrentPriority(0); + item = (QueueItem*) item->itemAbove(); + } + } + + item = (QueueItem*) seedList->lastItem(); + if(item == 0) + { + qman->orderQueue(); + return; + } + + p = 0; + + while(item != 0) + { + if(item->getPriority() != 0) + item->setTorrentPriority(++p); + else + item->setTorrentPriority(0); + item = (QueueItem*) item->itemAbove(); + } + qman->orderQueue(); +} + +void QueueDialog::btnApply_clicked() +{ + writeQueue(); +} + +void QueueDialog::btnOk_clicked() +{ + writeQueue(); + this->close(); +} + +QListView* QueueDialog::getCurrentList() +{ + return m_tabs->currentPageIndex() == 0 ? downloadList : seedList; +} + +void QueueDialog::downloadList_currentChanged(QListViewItem* item) +{ + if(!item) + { + dlStatus->clear(); + dlTracker->clear(); + dlRatio->clear(); + dlDHT->clear(); + return; + } + + const TorrentInterface* tc = ((QueueItem*)item)->getTC(); + TorrentStats s = tc->getStats(); + + dlStatus->setText(tc->statusToString()); + dlTracker->setText(tc->getTrackersList()->getTrackerURL().prettyURL()); + dlRatio->setText(QString("%1").arg((float)s.bytes_uploaded / s.bytes_downloaded,0,'f',2)); + dlBytes->setText(BytesToString(s.bytes_left_to_download)); + dlDHT->setText(s.priv_torrent ? i18n("No (private torrent)") : i18n("Yes")); +} + +void QueueDialog::seedList_currentChanged(QListViewItem* item) +{ + if(!item) + { + ulStatus->clear(); + ulTracker->clear(); + ulRatio->clear(); + ulDHT->clear(); + return; + } + + const TorrentInterface* tc = ((QueueItem*)item)->getTC(); + TorrentStats s = tc->getStats(); + + ulStatus->setText(tc->statusToString()); + ulTracker->setText(tc->getTrackersList()->getTrackerURL().prettyURL()); + ulRatio->setText(QString("%1").arg((float)s.bytes_uploaded / s.bytes_downloaded,0,'f',2)); + ulBytes->setText(BytesToString(s.bytes_uploaded)); + ulDHT->setText(s.priv_torrent ? i18n("No (private torrent)") : i18n("Yes")); +} + +void QueueDialog::btnMoveTop_clicked() +{ + QueueItem* current = (QueueItem*) getCurrentList()->selectedItem(); + if(current == 0) + return; + + if(current->getPriority() == 0) + return; + + QueueItem* previous = (QueueItem*) current->itemAbove(); + + if(previous == 0) + return; + + int p = previous->getPriority(); + + while(previous != 0) + { + p = previous->getPriority(); + previous->setPriority(p - 1); + + previous = (QueueItem*) previous->itemAbove(); + } + + current->setPriority(p); + getCurrentList()->sort(); +} + +void QueueDialog::btnMoveBottom_clicked() +{ + QueueItem* current = (QueueItem*) getCurrentList()->selectedItem(); + if(current == 0) + return; + + if(current->getPriority() == 0) + return; + + QueueItem* previous = (QueueItem*) current->itemBelow(); + + if(previous == 0) + return; + + if(previous->getPriority() == 0) + return; + + int p = previous->getPriority(); + + while(previous != 0 && previous->getPriority() != 0) + { + p = previous->getPriority(); + previous->setPriority(p + 1); + + previous = (QueueItem*) previous->itemBelow(); + } + + current->setPriority(p); + getCurrentList()->sort(); +} + + + +#include "queuedialog.moc" + diff --git a/apps/ktorrent/queuedialog.h b/apps/ktorrent/queuedialog.h new file mode 100644 index 0000000..e282867 --- /dev/null +++ b/apps/ktorrent/queuedialog.h @@ -0,0 +1,83 @@ +/*************************************************************************** + * Copyright (C) 2005 by Ivan Vasić * + * ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 QUEUEDIALOG_H +#define QUEUEDIALOG_H + +#include "queuedlg.h" +#include <interfaces/torrentinterface.h> +#include <torrent/queuemanager.h> + +#include <qlistview.h> +#include <qstring.h> + +class QueueItem: public QListViewItem +{ + public: + QueueItem(kt::TorrentInterface* t, QListView* parent); + + int getPriority() { return torrentPriority; } + void setPriority(int p); + int compare(QListViewItem *i, int col, bool ascending ) const; + + void setTorrentPriority(int p); + + const kt::TorrentInterface* getTC() { return tc; } + + private: + //void updatePriorities(QueueItem* to, bool from_end, int val); + void paintCell(QPainter* p,const QColorGroup & cg,int column,int width,int align); + + kt::TorrentInterface* tc; + int torrentPriority; +}; + +class QueueDialog: public QueueDlg +{ + Q_OBJECT + public: + QueueDialog(bt::QueueManager* qm, QWidget *parent = 0, const char *name = 0); + public slots: + virtual void btnMoveUp_clicked(); + virtual void btnClose_clicked(); + virtual void btnMoveDown_clicked(); + virtual void btnDequeue_clicked(); + virtual void btnEnqueue_clicked(); + virtual void btnApply_clicked(); + virtual void btnOk_clicked(); + virtual void seedList_currentChanged(QListViewItem*); + virtual void downloadList_currentChanged(QListViewItem*); + virtual void btnMoveBottom_clicked(); + virtual void btnMoveTop_clicked(); + + + private: + ///Enqueue item curr + void enqueue(QueueItem* curr = 0); + + ///Writes the queue order into QueueManager + void writeQueue(); + + ///Gets the pointer to currently visible torrentList (download or seed) + QListView* getCurrentList(); + + bt::QueueManager* qman; +}; + +#endif diff --git a/apps/ktorrent/queuedlg.ui b/apps/ktorrent/queuedlg.ui new file mode 100644 index 0000000..3ffbe23 --- /dev/null +++ b/apps/ktorrent/queuedlg.ui @@ -0,0 +1,726 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>QueueDlg</class> +<widget class="QDialog"> + <property name="name"> + <cstring>QueueDlg</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>631</width> + <height>482</height> + </rect> + </property> + <property name="caption"> + <string>KT Queue Dialog</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTabWidget" row="0" column="0"> + <property name="name"> + <cstring>m_tabs</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Downloads</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>InfoDownload</cstring> + </property> + <property name="title"> + <string>Info</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout25</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Status:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Tracker:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="text"> + <string>DHT:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Share ratio:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Bytes left:</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="0" column="1"> + <property name="name"> + <cstring>layout26</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>dlStatus</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KSqueezedTextLabel"> + <property name="name"> + <cstring>dlTracker</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>dlDHT</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>dlRatio</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>dlBytes</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </vbox> + </widget> + </grid> + </widget> + <widget class="QListView" row="0" column="0"> + <column> + <property name="text"> + <string>Torrent</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Controlled by</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>downloadList</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>AllColumns</enum> + </property> + </widget> + </grid> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>tab</cstring> + </property> + <attribute name="title"> + <string>Upload&s</string> + </attribute> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QListView" row="0" column="0"> + <column> + <property name="text"> + <string>Torrent</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Controlled by</string> + </property> + <property name="clickable"> + <bool>false</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>seedList</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>AllColumns</enum> + </property> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>InfoSeed</cstring> + </property> + <property name="title"> + <string>Info</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout15</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Status:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Tracker:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_4_2</cstring> + </property> + <property name="text"> + <string>DHT:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>4</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Share ratio:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>Uploaded:</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="0" column="1"> + <property name="name"> + <cstring>layout27</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>ulStatus</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="KSqueezedTextLabel"> + <property name="name"> + <cstring>ulTracker</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>ulDHT</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>ulRatio</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>ulBytes</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </vbox> + </widget> + </grid> + </widget> + </grid> + </widget> + </widget> + <widget class="QLayoutWidget" row="0" column="1"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout49</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer28</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Preferred</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>logo</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer29</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Preferred</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>30</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnMoveUp</cstring> + </property> + <property name="text"> + <string>M&ove up</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnMoveDown</cstring> + </property> + <property name="text"> + <string>Move dow&n</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnMoveTop</cstring> + </property> + <property name="text"> + <string>Move to top</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnMoveBottom</cstring> + </property> + <property name="text"> + <string>Move to &bottom</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Preferred</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnEnqueue</cstring> + </property> + <property name="text"> + <string>&QM Controlled</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnDequeue</cstring> + </property> + <property name="text"> + <string>&User Controlled</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnOk</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="stdItem" stdset="0"> + <number>1</number> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnApply</cstring> + </property> + <property name="text"> + <string>&Apply</string> + </property> + <property name="stdItem" stdset="0"> + <number>9</number> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnClose</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="stdItem" stdset="0"> + <number>2</number> + </property> + </widget> + </vbox> + </widget> + </grid> +</widget> +<images> + <image name="image0"> + <data format="XPM.GZ" length="4833">789c8597596f23470e80dfe75718c3b7c182e9eabb11ec834fc9873cbeaf601fc86ec9966df994cfc5fef794483633934d10c836fcb9582cde55fee5dbd2d9de68e9db2f5f9ee7349fb64bed153d2d7deb5e66b38fdffef3efff7ef99aa64b8baf2c5b4abffeebcb57dc5c6a9720499290640b8613e110ff22eb941b07657e7256f90be742e4a7c6a9ed076791c7a1732efbd784d3f817615a71167db0e55c0a17ce95c88f8ced3c7e74d6f306cea29fd159f583b3e8a75367d18f5bce8df0b63389be67e3ccfcd97716fd78e22cfaf1d459edefedcbedbc63e75af4cf85b33edeb8616cfef1b5b39eb7e72cf6c28b7166fb53678df7b5b3fadf388b3d503a8b3d40c6b9eaa35767d9cf37c6a5e53f73d6f3769d55bedf5f2789ac6bfcf2de1fda33ce4cdfbb716eeb6fce1acf1de3c2f2bbe7acf573605cdafe2b67f5efd359f20bb97165febe38b3c453fd2bfa7cd0a67165fea97c9db416ff1de3b1e9d77a6d12567bf8c159ed9d1ab7969fc2b8d378e2ba304579c93769bd719457fd524f2184cae221f51bd250a8fd3c35ae4cfec1b8b6fa06e3c6eaffc859d651f215b2d0c7efdab8327b969d459e9e8d7bfd57c68df587c43be4c1e20b685c1b9f0b17c1e283cfce927f96f911ca40d63fcbce7afebd31eb3a91b3fa37376ead9e64dea5759606a94f546eb23499883d9bc69932bef4acf22cf594725c1f8bfca9b3c8d3aa711e82c82bb73de3817111a4fe2171d67e1a1b97ba8e87ce5a8f12bfb48b2cfae8ceb85206894f9666135bff2e5c45d6fae894a3393a3f5be13aaeb7729eca4ff2d6ce3f5b701ef2b1c95f0aa7715dfb4de657519675d0fc8d8c9ba0f527f12faab234fd8fc695f1ab716dfa3f84ebb2089dec5f779678d381711d74beae398b7f540b3751bfd6e39ab1c9033b6bbd07e326687dcb3c2da8ecf47cfa301e9bbe37e389c94b3c0a2edba0f5f361dc194b3c8b36eed77acf9c453fab7f6d95587e6e8d83c957c25dc9668fdc5fc538b2c6e3a6e754e7adcc836252b6a9d69bccffb2ad535d67e98fb2ab538befaab3e8439947e5b84e82f6ffa17165f1bd7096fcc1ccb8b67a981b375a0f20f92d2775b078493dd54c75aaef0de9dfba75167fea2eb2f683dc5771388d753fbe396b7fca7c6b52ea2c5e57ce621fcbfdd26464f1812767ed8f63e3ced665de34c464fe9e1bb3d5b3f45bc3dca67a7fc9fba7697b46a9bf66cc13cb8fcc8b66c2960f3832b6f3988dad1e2828b799c53371d6f9766b9c5b7f4afe286983f5c3aeb3be177ace6c1ecc9cb51f6a678def8a7169f351fca710f5a93d9db3d64febacf9981aa76a2f5e3b6b7d5d1af7f6df3aebfb67e4acf93f72d6f972675cd83c7d77d67cac3bebfdfce9acf7eb87b3c66b665cdabc5feed9f44bfd51caade59395dbc4fc3f33cecc9f9b9e35bf786fdccfffc459e7ffc059eb7fe2acefcfd459df13dbceda5f4367bddffed8affdf0665c243a6f769c351f6367f51f7ad6fcefcf9dd57e72567fd959e3dd3a6bbc3b677daf34ce6affadb3dadbdb57263a5f46ce7adf8e9dd5dededfbe5e2f9cb5de5b678df7bb71a5fa59f767dccf77cd57d6f7136c185b7e79d359f3159cf53df7e8acf19e19f7f57ee5acef9b0d67f5b733b6fa844b63f38f07ceea9fcc3fca5b9bef58199b3dbce5acefa53567bd6fee8c73d54f95b3fa3b34b6fcc3b3b3f6dba1b3f6afe6a788fb6bad9f1f3f08f19b90b18ddff0f3dafefc2fe4bb284948f1b7f1e2e73fca4ff012af708ad77883b77f2f8f33bc8b9aeff1011ff1099f718e2ff88a6ff88e1ff8196da33fc92fe30aaee21aaee3060e70889bb885dbb88323dc8d7a407df941be8dd2dfa3ec5e94dac7033cc4233cc6133cc5333cc78bffb327c18029669863812556d1ef1a9ba8168080a1850ec608daaf30814bb882296ec035dc486426700b33b8837b78c0213cc2133ce367af3f7a93c01c5e700b5ee10d6fe11d093ee01396610556f104d6601d36a2d77abf0da2f41036610bb6b1841d18c12e7c873dd887033884233886133885b318297d3fc558e114cee1021208d1e01432c8a180122aa8e3c5190f2322c63bb507995aea62bc37698c9f34a14bba822d9ad235ddd02dcde80e87744f0f7fc823d1233de1363d634d737aa1577aa3ebf8047ba70ffaa4655aa1555aa375b37f0c298e6923ca0fb0a1212cd3266dd136edd08876e93bedd13e1dd0211d997e88f6031dd3099d624e67744e17f15f8b40296594cb273ef61632aa5ff34515d5d43032707c19449fd6e993db283b8217ee62fc0630fa31bf1cdf037c493bb1724ef98a162d30e56bcae185467cc3b731dfa0f935f919dff13daef1033ff2133fc77d039e73d41da55ff90d268b8afba17ea27d30a18edff9833f7999577895d7a88421aff31b6fc0e04ff5c6314acc031ef2266cc4c7ce036ff12ca66a10ff75d95eacfd2ccf3b0bfd38e651ac93f7d83b77f84e47d1e6f1222e0bf9c5ef3ff7a3f690766f4ffd0490aa85affffbf5cbef985d44a8</data> + </image> +</images> +<connections> + <connection> + <sender>btnMoveUp</sender> + <signal>clicked()</signal> + <receiver>QueueDlg</receiver> + <slot>btnMoveUp_clicked()</slot> + </connection> + <connection> + <sender>btnMoveDown</sender> + <signal>clicked()</signal> + <receiver>QueueDlg</receiver> + <slot>btnMoveDown_clicked()</slot> + </connection> + <connection> + <sender>btnEnqueue</sender> + <signal>clicked()</signal> + <receiver>QueueDlg</receiver> + <slot>btnEnqueue_clicked()</slot> + </connection> + <connection> + <sender>btnDequeue</sender> + <signal>clicked()</signal> + <receiver>QueueDlg</receiver> + <slot>btnDequeue_clicked()</slot> + </connection> + <connection> + <sender>downloadList</sender> + <signal>currentChanged(QListViewItem*)</signal> + <receiver>QueueDlg</receiver> + <slot>downloadList_currentChanged(QListViewItem*)</slot> + </connection> + <connection> + <sender>seedList</sender> + <signal>currentChanged(QListViewItem*)</signal> + <receiver>QueueDlg</receiver> + <slot>seedList_currentChanged(QListViewItem*)</slot> + </connection> + <connection> + <sender>btnOk</sender> + <signal>clicked()</signal> + <receiver>QueueDlg</receiver> + <slot>btnOk_clicked()</slot> + </connection> + <connection> + <sender>btnApply</sender> + <signal>clicked()</signal> + <receiver>QueueDlg</receiver> + <slot>btnApply_clicked()</slot> + </connection> + <connection> + <sender>btnClose</sender> + <signal>clicked()</signal> + <receiver>QueueDlg</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>btnMoveTop</sender> + <signal>clicked()</signal> + <receiver>QueueDlg</receiver> + <slot>btnMoveTop_clicked()</slot> + </connection> + <connection> + <sender>btnMoveBottom</sender> + <signal>clicked()</signal> + <receiver>QueueDlg</receiver> + <slot>btnMoveBottom_clicked()</slot> + </connection> +</connections> +<tabstops> + <tabstop>btnOk</tabstop> + <tabstop>btnApply</tabstop> + <tabstop>btnClose</tabstop> + <tabstop>m_tabs</tabstop> + <tabstop>downloadList</tabstop> + <tabstop>btnMoveUp</tabstop> + <tabstop>btnMoveDown</tabstop> + <tabstop>btnEnqueue</tabstop> + <tabstop>btnDequeue</tabstop> + <tabstop>seedList</tabstop> +</tabstops> +<slots> + <slot>btnMoveUp_clicked()</slot> + <slot>btnMoveDown_clicked()</slot> + <slot>btnEnqueue_clicked()</slot> + <slot>btnDequeue_clicked()</slot> + <slot>downloadList_currentChanged(QListViewItem*)</slot> + <slot>seedList_currentChanged(QListViewItem*)</slot> + <slot>btnOk_clicked()</slot> + <slot>btnApply_clicked()</slot> + <slot>btnClose_clicked()</slot> + <slot>btnMoveTop_clicked()</slot> + <slot>btnMoveBottom_clicked()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>ksqueezedtextlabel.h</includehint> + <includehint>ksqueezedtextlabel.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/scandialog.cpp b/apps/ktorrent/scandialog.cpp new file mode 100644 index 0000000..cf04a47 --- /dev/null +++ b/apps/ktorrent/scandialog.cpp @@ -0,0 +1,202 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <qlabel.h> +#include <klocale.h> +#include <kprogress.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> +#include <kmessagebox.h> +#include <util/error.h> +#include <torrent/queuemanager.h> +#include <torrent/torrentcontrol.h> + +#include "scandialog.h" +#include "ktorrentcore.h" + +using namespace bt; +using namespace kt; + + + +ScanDialog::ScanDialog(KTorrentCore* core,bool auto_import, + QWidget* parent, const char* name, bool modal, WFlags fl) + : ScanDlgBase(parent,name, modal,fl),DataCheckerListener(auto_import),mutex(true),core(core) +{ + m_cancel->setGuiItem(KStdGuiItem::cancel()); + connect(m_cancel,SIGNAL(clicked()),this,SLOT(onCancelPressed())); + connect(&timer,SIGNAL(timeout()),this,SLOT(update())); + tc = 0; + silently = false; + restart = false; + qm_controlled = false; + scanning = false; + num_chunks = 0; + total_chunks = 0; + num_downloaded = 0; + num_failed = 0; +} + +ScanDialog::~ScanDialog() +{ +} + +void ScanDialog::scan() +{ + try + { + tc->startDataCheck(this,auto_import); + timer.start(500); + scanning = true; + } + catch (bt::Error & err) + { + KMessageBox::error(0,i18n("Error scanning data: %1").arg(err.toString())); + } + +} + +void ScanDialog::execute(kt::TorrentInterface* tc,bool silently) +{ + m_torrent_label->setText(i18n("Scanning data of <b>%1</b> :").arg(tc->getStats().torrent_name)); + adjustSize(); + m_cancel->setEnabled(true); + this->silently = silently; + this->tc = tc; + num_chunks = 0; + total_chunks = 0; + num_downloaded = 0; + num_failed = 0; + if (auto_import || tc->getStats().running) + restart = true; + + qm_controlled = !tc->getStats().user_controlled; + qm_priority = tc->getPriority(); + + if (tc->getStats().running) + { + if (qm_controlled) + core->getQueueManager()->stop(tc,true); + else + tc->stop(true); + } + + + scan(); +} + +void ScanDialog::finished() +{ + QMutexLocker lock(&mutex); + scanning = false; + timer.stop(); + progress(100,100); + update(); + if (!isStopped()) + { + if (restart) + { + if (!qm_controlled) + tc->start(); + else + { + tc->setPriority(qm_priority); + core->getQueueManager()->orderQueue(); + } + } + + if (silently) + accept(); + else + { + // cancel now becomes a close button + m_cancel->setGuiItem(KStdGuiItem::close()); + disconnect(m_cancel,SIGNAL(clicked()),this,SLOT(onCancelPressed())); + connect(m_cancel,SIGNAL(clicked()),this,SLOT(accept())); + } + } + else + { + if (restart) + { + if (!qm_controlled) + tc->start(); + else + { + tc->setPriority(qm_priority); + core->getQueueManager()->orderQueue(); + } + } + + QDialog::reject(); + } +} + +void ScanDialog::progress(bt::Uint32 num,bt::Uint32 total) +{ + QMutexLocker lock(&mutex); + num_chunks = num; + total_chunks = total; + +} + +void ScanDialog::update() +{ + QMutexLocker lock(&mutex); + m_progress->setTotalSteps(total_chunks); + m_progress->setProgress(num_chunks); + m_chunks_found->setText(QString::number(num_downloaded)); + m_chunks_failed->setText(QString::number(num_failed)); +} + +void ScanDialog::status(bt::Uint32 failed,bt::Uint32 downloaded) +{ + QMutexLocker lock(&mutex); + num_failed = failed; + num_downloaded = downloaded; +} + +void ScanDialog::reject() +{ + if (scanning) + stop(); + else + QDialog::reject(); +} + +void ScanDialog::onCancelPressed() +{ + stop(); +} + +void ScanDialog::accept() +{ + QDialog::accept(); +} + +void ScanDialog::closeEvent(QCloseEvent* e) +{ + if (scanning) + reject(); + else + accept(); +} + +#include "scandialog.moc" + diff --git a/apps/ktorrent/scandialog.h b/apps/ktorrent/scandialog.h new file mode 100644 index 0000000..26271b8 --- /dev/null +++ b/apps/ktorrent/scandialog.h @@ -0,0 +1,87 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 SCANDIALOG_H +#define SCANDIALOG_H + +#include <qmutex.h> +#include <qtimer.h> +#include <datachecker/datacheckerlistener.h> +#include "scandlgbase.h" + + +namespace kt +{ + class TorrentInterface; +} + +class KTorrentCore; + +class ScanDialog : public ScanDlgBase, public bt::DataCheckerListener +{ + Q_OBJECT +public: + ScanDialog(KTorrentCore* core,bool auto_import,QWidget* parent = 0, const char* name = 0, bool modal = false, WFlags fl = WDestructiveClose ); + virtual ~ScanDialog(); + + /// Starts the scan thread + void execute(kt::TorrentInterface* tc,bool silently); + +protected: + /// Update progress info, runs in scan thread + virtual void progress(bt::Uint32 num,bt::Uint32 total); + + /// Update status info, runs in scan thread + virtual void status(bt::Uint32 num_failed,bt::Uint32 num_downloaded); + + /// Scan finished, runs in app thread + virtual void finished(); + + /// Handle the close event + virtual void closeEvent(QCloseEvent* e); + + +protected slots: + virtual void reject(); + virtual void accept(); + void onCancelPressed(); + /// Updates the GUI in app thread + void update(); + void scan(); + +private: + kt::TorrentInterface* tc; + QMutex mutex; + QTimer timer; + bt::Uint32 num_chunks; + bt::Uint32 total_chunks; + bt::Uint32 num_downloaded; + bt::Uint32 num_failed; + bool silently; + bool restart; + bool qm_controlled; + int qm_priority; + bool scanning; + KTorrentCore* core; +}; + + +#endif + diff --git a/apps/ktorrent/scandlgbase.ui b/apps/ktorrent/scandlgbase.ui new file mode 100644 index 0000000..6a1b374 --- /dev/null +++ b/apps/ktorrent/scandlgbase.ui @@ -0,0 +1,193 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>ScanDlgBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>ScanDlgBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>441</width> + <height>182</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>Scanning data</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="resizeMode"> + <enum>Minimum</enum> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_torrent_label</cstring> + </property> + <property name="text"> + <string>Scanning data of torrent :</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Number of chunks found :</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Number of chunks failed / not downloaded :</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_chunks_found</cstring> + </property> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="frameShape"> + <enum>Box</enum> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>m_chunks_failed</cstring> + </property> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + <property name="frameShape"> + <enum>Box</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + </widget> + </vbox> + </widget> + </hbox> + </widget> + <widget class="KProgress"> + <property name="name"> + <cstring>m_progress</cstring> + </property> + </widget> + <widget class="Line"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>181</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>m_cancel</cstring> + </property> + <property name="text"> + <string>C&ancel</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kprogress.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/speedlimitsdlg.cpp b/apps/ktorrent/speedlimitsdlg.cpp new file mode 100644 index 0000000..d208b06 --- /dev/null +++ b/apps/ktorrent/speedlimitsdlg.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <qlabel.h> +#include <klocale.h> +#include <knuminput.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> +#include <util/constants.h> +#include <interfaces/torrentinterface.h> + +#include "speedlimitsdlg.h" + +using namespace bt; +using namespace kt; + +SpeedLimitsDlg::SpeedLimitsDlg(kt::TorrentInterface* ti,QWidget* parent, const char* name) + : SpeedLimitsDlgBase(parent,name,true,0),tor(ti) +{ + m_main_caption->setText(i18n("Speed limits for <b>%1</b>:").arg(tor->getStats().torrent_name)); + Uint32 up,down; + tor->getTrafficLimits(up,down); + m_upload_rate->setValue(up / 1024); + m_upload_rate->setMinValue(0); + m_download_rate->setValue(down / 1024); + m_download_rate->setMinValue(0); + m_ok->setGuiItem(KStdGuiItem::ok()); + m_cancel->setGuiItem(KStdGuiItem::cancel()); + adjustSize(); +} + +SpeedLimitsDlg::~SpeedLimitsDlg() +{} + + +void SpeedLimitsDlg::accept() +{ + Uint32 up = m_upload_rate->value() * 1024; + Uint32 down = m_download_rate->value() * 1024; + tor->setTrafficLimits(up,down); + QDialog::accept(); +} + + + +#include "speedlimitsdlg.moc" + diff --git a/apps/ktorrent/speedlimitsdlg.h b/apps/ktorrent/speedlimitsdlg.h new file mode 100644 index 0000000..3e31a4a --- /dev/null +++ b/apps/ktorrent/speedlimitsdlg.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 SPEEDLIMITSDLG_H +#define SPEEDLIMITSDLG_H + +#include "speedlimitsdlgbase.h" + +namespace kt +{ + class TorrentInterface; +} + +class SpeedLimitsDlg : public SpeedLimitsDlgBase +{ + Q_OBJECT + + kt::TorrentInterface* tor; +public: + SpeedLimitsDlg(kt::TorrentInterface* ti,QWidget* parent = 0, const char* name = 0); + virtual ~SpeedLimitsDlg(); + + +protected slots: + virtual void accept(); + +}; + +#endif + diff --git a/apps/ktorrent/speedlimitsdlgbase.ui b/apps/ktorrent/speedlimitsdlgbase.ui new file mode 100644 index 0000000..cd1bbf4 --- /dev/null +++ b/apps/ktorrent/speedlimitsdlgbase.ui @@ -0,0 +1,196 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>SpeedLimitsDlgBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>SpeedLimitsDlgBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>362</width> + <height>150</height> + </rect> + </property> + <property name="caption"> + <string>Speed Limits</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>m_main_caption</cstring> + </property> + <property name="text"> + <string>Set the speed limits for torrent</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Max upload rate:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Max download rate:</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>m_upload_rate</cstring> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>m_download_rate</cstring> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>KB/s (0 is no limit)</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel4_2</cstring> + </property> + <property name="text"> + <string>KB/s (0 is no limit)</string> + </property> + </widget> + </vbox> + </widget> + </hbox> + </widget> + <widget class="Line"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>121</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>m_ok</cstring> + </property> + <property name="text"> + <string>OK</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>m_cancel</cstring> + </property> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>m_cancel</sender> + <signal>clicked()</signal> + <receiver>SpeedLimitsDlgBase</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>m_ok</sender> + <signal>clicked()</signal> + <receiver>SpeedLimitsDlgBase</receiver> + <slot>accept()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/torrentcreatordlg.cpp b/apps/ktorrent/torrentcreatordlg.cpp new file mode 100644 index 0000000..d47086f --- /dev/null +++ b/apps/ktorrent/torrentcreatordlg.cpp @@ -0,0 +1,152 @@ +// +// C++ Implementation: $MODULE$ +// +// Description: +// +// +// Author: Joris Guisson <joris.guisson@gmail.com>, (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include <qcheckbox.h> +#include <qstringlist.h> +#include <qmap.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kcombobox.h> +#include <klineedit.h> +#include <kurlrequester.h> +#include <keditlistbox.h> +#include <kpushbutton.h> +#include <kfiledialog.h> +#include <kprogress.h> +#include <klistview.h> +#include <knuminput.h> +#include "torrentcreatordlg.h" +#include "ktorrentcore.h" +#include <torrent/globals.h> +#include <kademlia/dhtbase.h> + +TorrentCreatorDlg::TorrentCreatorDlg(KTorrentCore* core,QWidget *parent, const char *name) + :TorrentCreatorDlgBase(parent, name),core(core) +{ + KURLRequester* r = m_file_or_dir; + r->fileDialog()->setMode( + KFile::ExistingOnly|KFile::Directory|KFile::File|KFile::LocalOnly); + + KComboBox* cb = m_chunk_size; + cb->setCurrentItem(3); + + connect(m_create_btn,SIGNAL(clicked()),this,SLOT(onCreate())); + connect(m_cancel_btn,SIGNAL(clicked()),this,SLOT(reject())); + + m_nodes->setHidden(true); + + QMap<QString, int> n = bt::Globals::instance().getDHT().getClosestGoodNodes(10); + + for(QMap<QString, int>::iterator it = n.begin(); it!=n.end(); ++it) + new QListViewItem(m_nodeList, it.key(), QString("%1").arg(it.data())); +} + +TorrentCreatorDlg::~TorrentCreatorDlg() +{ +} + +void TorrentCreatorDlg::onCreate() +{ + KURLRequester* r = m_file_or_dir; + KComboBox* cb = m_chunk_size; + KEditListBox* eb = m_trackers; + + if (r->url().length() == 0) + { + errorMsg(i18n("You must select a file or a folder.")); + return; + } + + if (eb->items().count() == 0 && !m_decentralized->isChecked()) + { + //errorMsg(i18n("You must add at least one tracker.")); + QString msg = i18n("You have not added a tracker, " + "are you sure you want to create this torrent ?"); + if (KMessageBox::warningYesNo(this,msg) == KMessageBox::No) + return; + } + + if (m_nodeList->childCount() == 0 && m_decentralized->isChecked()) + { + errorMsg(i18n("You must add at least one node.")); + return; + } + + QString url = r->url(); + int chunk_size = cb->currentText().toInt(); + QString name = KURL::fromPathOrURL(r->url()).fileName(); + + QStringList trackers; + + if(m_decentralized->isChecked()) + { + for(int i=0; i<m_nodeList->childCount(); ++i) + trackers.append(m_nodeList->itemAtIndex(i)->text(0) + "," + m_nodeList->itemAtIndex(i)->text(1)); + } + else + trackers = eb->items(); + + QString s = KFileDialog::getSaveFileName( + QString::null,"*.torrent|" + i18n("Torrent Files (*.torrent)"), + 0,i18n("Choose File to Save Torrent")); + + if (s.isNull()) + return; + + if (!s.endsWith(".torrent")) + s += ".torrent"; + + KProgressDialog* dlg = new KProgressDialog(this,0); + dlg->setLabel(i18n("Creating %1...").arg(s)); + dlg->setModal(true); + dlg->setAllowCancel(false); + dlg->show(); + core->makeTorrent( + url,trackers,chunk_size, + name,m_comments->text(), + m_start_seeding->isChecked(),s, + m_private->isChecked(), + dlg->progressBar(), + m_decentralized->isChecked()); + delete dlg; + accept(); +} + +void TorrentCreatorDlg::errorMsg(const QString & text) +{ + KMessageBox::error(this,text,i18n("Error")); +} + +void TorrentCreatorDlg::btnRemoveNode_clicked() +{ + QListViewItem* item = m_nodeList->currentItem(); + if(!item) + return; + + m_nodeList->removeItem(item); +} + +void TorrentCreatorDlg::btnAddNode_clicked() +{ + new QListViewItem(m_nodeList, m_node->text(), QString("%1").arg(m_port->value())); +} + +void TorrentCreatorDlg::m_nodeList_selectionChanged(QListViewItem*) +{ + btnRemoveNode->setEnabled(m_nodeList->selectedItem()!=0); +} + +void TorrentCreatorDlg::m_node_textChanged(const QString& txt) +{ + btnAddNode->setEnabled(!txt.isEmpty()); +} + +#include "torrentcreatordlg.moc" diff --git a/apps/ktorrent/torrentcreatordlg.h b/apps/ktorrent/torrentcreatordlg.h new file mode 100644 index 0000000..3dec45d --- /dev/null +++ b/apps/ktorrent/torrentcreatordlg.h @@ -0,0 +1,39 @@ +// +// C++ Interface: $MODULE$ +// +// Description: +// +// +// Author: Joris Guisson <joris.guisson@gmail.com>, (C) 2005 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef TORENTCREATORDLG_H +#define TORENTCREATORDLG_H + +#include "torrentcreatordlgbase.h" + +class KTorrentCore; + +class TorrentCreatorDlg: public TorrentCreatorDlgBase +{ + Q_OBJECT +public: + TorrentCreatorDlg(KTorrentCore* core,QWidget *parent = 0, const char *name = 0); + virtual ~TorrentCreatorDlg(); + +public slots: + void onCreate(); + virtual void btnAddNode_clicked(); + virtual void btnRemoveNode_clicked(); + virtual void m_nodeList_selectionChanged(QListViewItem*); + virtual void m_node_textChanged(const QString&); +private: + void errorMsg(const QString & text); + +private: + KTorrentCore* core; +}; + +#endif diff --git a/apps/ktorrent/torrentcreatordlgbase.ui b/apps/ktorrent/torrentcreatordlgbase.ui new file mode 100644 index 0000000..fb253f4 --- /dev/null +++ b/apps/ktorrent/torrentcreatordlgbase.ui @@ -0,0 +1,533 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>TorrentCreatorDlgBase</class> +<widget class="QDialog"> + <property name="name"> + <cstring>TorrentCreatorDlgBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>503</width> + <height>669</height> + </rect> + </property> + <property name="caption"> + <string>Create Torrent</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>The file or folder of which you want to create a torrent:</string> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>m_file_or_dir</cstring> + </property> + </widget> + </vbox> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>m_label1</cstring> + </property> + <property name="text"> + <string>You must add at least one tracker or node.</string> + </property> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>File Options</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Size of each chunk:</string> + </property> + </widget> + <widget class="KComboBox"> + <item> + <property name="text"> + <string>32</string> + </property> + </item> + <item> + <property name="text"> + <string>64</string> + </property> + </item> + <item> + <property name="text"> + <string>128</string> + </property> + </item> + <item> + <property name="text"> + <string>256</string> + </property> + </item> + <item> + <property name="text"> + <string>512</string> + </property> + </item> + <item> + <property name="text"> + <string>1024</string> + </property> + </item> + <item> + <property name="text"> + <string>2048</string> + </property> + </item> + <item> + <property name="text"> + <string>4096</string> + </property> + </item> + <item> + <property name="text"> + <string>8192</string> + </property> + </item> + <property name="name"> + <cstring>m_chunk_size</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>KB</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QCheckBox" row="1" column="0"> + <property name="name"> + <cstring>m_start_seeding</cstring> + </property> + <property name="text"> + <string>Start seedin&g the torrent</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox" row="3" column="0"> + <property name="name"> + <cstring>m_decentralized</cstring> + </property> + <property name="text"> + <string>Decentrali&zed (DHT only)</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="0"> + <property name="name"> + <cstring>m_private</cstring> + </property> + <property name="text"> + <string>Private torrent (DHT not allowed)</string> + </property> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget" row="5" column="0"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2_2</cstring> + </property> + <property name="text"> + <string>Comments:</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>m_comments</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="6" column="0"> + <property name="name"> + <cstring>Layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <spacer> + <property name="name"> + <cstring>Horizontal Spacing2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>m_create_btn</cstring> + </property> + <property name="text"> + <string>&Create</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>m_cancel_btn</cstring> + </property> + <property name="text"> + <string>Ca&ncel</string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="KEditListBox" row="3" column="0"> + <property name="name"> + <cstring>m_trackers</cstring> + </property> + <property name="title"> + <string>Trackers</string> + </property> + </widget> + <widget class="QGroupBox" row="4" column="0"> + <property name="name"> + <cstring>m_nodes</cstring> + </property> + <property name="title"> + <string>DHT nodes</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton" row="2" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>btnRemoveNode</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Remove</string> + </property> + <property name="stdItem" stdset="0"> + <number>28</number> + </property> + </widget> + <widget class="KPushButton" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>btnAddNode</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Add</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="stdItem" stdset="0"> + <number>27</number> + </property> + </widget> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Node:</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>m_node</cstring> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_2</cstring> + </property> + <property name="text"> + <string>Port:</string> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>m_port</cstring> + </property> + <property name="value"> + <number>6882</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + <property name="maxValue"> + <number>65535</number> + </property> + </widget> + </hbox> + </widget> + <spacer row="0" column="1"> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Maximum</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KListView" row="1" column="0" rowspan="3" colspan="1"> + <column> + <property name="text"> + <string>IP or hostname</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Port</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_nodeList</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>AllColumns</enum> + </property> + </widget> + <spacer row="3" column="2"> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="4" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string>NOTE: Some known good DHT nodes are already inserted. You should probably insert your own IP address and port too if you plan to seed this torrent.</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>m_private</sender> + <signal>toggled(bool)</signal> + <receiver>m_decentralized</receiver> + <slot>setDisabled(bool)</slot> + </connection> + <connection> + <sender>m_decentralized</sender> + <signal>toggled(bool)</signal> + <receiver>m_private</receiver> + <slot>setDisabled(bool)</slot> + </connection> + <connection> + <sender>m_decentralized</sender> + <signal>toggled(bool)</signal> + <receiver>m_trackers</receiver> + <slot>setHidden(bool)</slot> + </connection> + <connection> + <sender>m_decentralized</sender> + <signal>toggled(bool)</signal> + <receiver>m_nodes</receiver> + <slot>setShown(bool)</slot> + </connection> + <connection> + <sender>btnRemoveNode</sender> + <signal>clicked()</signal> + <receiver>TorrentCreatorDlgBase</receiver> + <slot>btnRemoveNode_clicked()</slot> + </connection> + <connection> + <sender>btnAddNode</sender> + <signal>clicked()</signal> + <receiver>TorrentCreatorDlgBase</receiver> + <slot>btnAddNode_clicked()</slot> + </connection> + <connection> + <sender>m_node</sender> + <signal>textChanged(const QString&)</signal> + <receiver>TorrentCreatorDlgBase</receiver> + <slot>m_node_textChanged(const QString&)</slot> + </connection> + <connection> + <sender>m_nodeList</sender> + <signal>selectionChanged(QListViewItem*)</signal> + <receiver>TorrentCreatorDlgBase</receiver> + <slot>m_nodeList_selectionChanged(QListViewItem*)</slot> + </connection> +</connections> +<tabstops> + <tabstop>m_file_or_dir</tabstop> + <tabstop>m_chunk_size</tabstop> + <tabstop>m_start_seeding</tabstop> + <tabstop>m_private</tabstop> + <tabstop>m_decentralized</tabstop> + <tabstop>m_node</tabstop> + <tabstop>m_port</tabstop> + <tabstop>btnAddNode</tabstop> + <tabstop>btnRemoveNode</tabstop> + <tabstop>m_comments</tabstop> + <tabstop>m_create_btn</tabstop> + <tabstop>m_cancel_btn</tabstop> +</tabstops> +<slots> + <slot>btnRemoveNode_clicked()</slot> + <slot>btnAddNode_clicked()</slot> + <slot>m_node_textChanged(const QString&)</slot> + <slot>m_nodeList_selectionChanged(QListViewItem*)</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>keditlistbox.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>klistview.h</includehint> +</includehints> +</UI> diff --git a/apps/ktorrent/trayhoverpopup.cpp b/apps/ktorrent/trayhoverpopup.cpp new file mode 100644 index 0000000..196eb63 --- /dev/null +++ b/apps/ktorrent/trayhoverpopup.cpp @@ -0,0 +1,136 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <qvbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qtooltip.h> +#include <qpixmap.h> +#include <kdialog.h> +#include <util/log.h> +#include "trayhoverpopup.h" + +using namespace bt; + +TrayHoverPopup::TrayHoverPopup(const QPixmap & pix,QWidget *parent, const char *name ) + : KPassivePopup(KPassivePopup::Boxed,parent,name),pix(pix) +{ + setTimeout(0); + setAutoDelete(false); + connect(&hover_timer,SIGNAL(timeout()),this,SLOT(onHoverTimeout())); + connect(&show_timer,SIGNAL(timeout()),this,SLOT(onShowTimeout())); + create(); + setPalette(QToolTip::palette()); + setLineWidth(1); + context_menu_shown = false; + cursor_over_icon = false; +} + + +TrayHoverPopup::~TrayHoverPopup() +{} + +void TrayHoverPopup::contextMenuAboutToShow() +{ + context_menu_shown = true; + if (isShown()) + { + hide(); + hover_timer.stop(); + } +} + +void TrayHoverPopup::contextMenuAboutToHide() +{ + context_menu_shown = false; +} + + +void TrayHoverPopup::enterEvent() +{ + cursor_over_icon = true; + if (isHidden() && !context_menu_shown) + { + // start the show timer + show_timer.start(1000,true); + } + else + hover_timer.stop(); // stop timeout +} + +void TrayHoverPopup::leaveEvent() +{ + cursor_over_icon = false; + // to avoid problems with a quick succession of enter and leave events, because the cursor + // is on the edge, use a timer to expire the popup + // in enterEvent we will stop the timer + if (isShown()) + hover_timer.start(200,true); +} + +void TrayHoverPopup::onHoverTimeout() +{ + hide(); + show_timer.stop(); +} + +void TrayHoverPopup::onShowTimeout() +{ + if (!context_menu_shown && cursor_over_icon) + show(); +} + +void TrayHoverPopup::updateText(const QString & msg) +{ + text->setText(msg); +} + +void TrayHoverPopup::create() +{ + QVBox *vb = new QVBox(this); + vb->setSpacing(KDialog::spacingHint()); + + QHBox *hb=0; + if (!pix.isNull()) + { + hb = new QHBox(vb); + hb->setMargin(0); + hb->setSpacing(KDialog::spacingHint()); + QLabel* pix_lbl = new QLabel(hb,"title_icon"); + pix_lbl->setPixmap(pix); + pix_lbl->setAlignment(AlignLeft); + } + + + QLabel* title = new QLabel("KTorrent", hb ? hb : vb, "title_label" ); + QFont fnt = title->font(); + fnt.setBold( true ); + title->setFont( fnt ); + title->setAlignment( Qt::AlignHCenter ); + if ( hb ) + hb->setStretchFactor(title, 10 ); // enforce centering + + // text will be filled later + text = new QLabel( "Dummy", vb, "msg_label" ); + text->setAlignment( AlignLeft ); + setView(vb); +} + + +#include "trayhoverpopup.moc" diff --git a/apps/ktorrent/trayhoverpopup.h b/apps/ktorrent/trayhoverpopup.h new file mode 100644 index 0000000..3da5985 --- /dev/null +++ b/apps/ktorrent/trayhoverpopup.h @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 TRAYHOVERPOPUP_H +#define TRAYHOVERPOPUP_H + +#include <qtimer.h> +#include <kpassivepopup.h> + +class QLabel; +class QPixmap; + +/** + @author Joris Guisson <joris.guisson@gmail.com> + + This is the passive popup which is shown when the mouse cursor is hovered over the tray icon +*/ +class TrayHoverPopup : public KPassivePopup +{ + Q_OBJECT +public: + TrayHoverPopup(const QPixmap & pix,QWidget *parent = 0, const char *name = 0 ); + virtual ~TrayHoverPopup(); + + /// Cursor entered system tray icon + void enterEvent(); + + /// Cursor left system tray icon + void leaveEvent(); + + /// Update the text which is shown + void updateText(const QString & msg); + +public slots: + void contextMenuAboutToShow(); + void contextMenuAboutToHide(); + +private: + void create(); + +private slots: + void onHoverTimeout(); + void onShowTimeout(); + + +private: + const QPixmap & pix; + QTimer hover_timer; + QTimer show_timer; + QLabel* text; + bool context_menu_shown; + bool cursor_over_icon; +}; + +#endif diff --git a/apps/ktorrent/trayicon.cpp b/apps/ktorrent/trayicon.cpp new file mode 100644 index 0000000..e7cf9c5 --- /dev/null +++ b/apps/ktorrent/trayicon.cpp @@ -0,0 +1,380 @@ +/*************************************************************************** + * Copyright (C) 2005 by * + * Joris Guisson <joris.guisson@gmail.com> * + * Ivan Vasic <ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <kpopupmenu.h> +#include <klocale.h> +#include <kapplication.h> +#include "ktorrent.h" +#include "trayicon.h" +#include <qtooltip.h> +#include <kpassivepopup.h> +#include <interfaces/torrentinterface.h> +#include "ktorrentcore.h" +#include <interfaces/functions.h> +#include <net/socketmonitor.h> +#include <util/log.h> +#include "trayhoverpopup.h" + + +using namespace bt; +using namespace kt; + +TrayIcon::TrayIcon( KTorrentCore* tc, QWidget *parent, const char *name) + : KSystemTray(parent, name) +{ + m_core = tc; + m_kt_pix = loadIcon("ktorrent"); + setPixmap(m_kt_pix); + paint=new QPainter( this ); + drawContents ( paint ); + previousDownloadHeight=0; + previousUploadHeight=0; + + m_hover_popup = new TrayHoverPopup(m_kt_pix,this); + + connect(this,SIGNAL(quitSelected()),kapp,SLOT(quit())); + connect(m_core, SIGNAL(finished(kt::TorrentInterface* )), + this, SLOT(finished(kt::TorrentInterface* ))); + connect(m_core,SIGNAL(torrentStoppedByError(kt::TorrentInterface*, QString )), + this,SLOT(torrentStoppedByError(kt::TorrentInterface*, QString ))); + connect(m_core,SIGNAL(maxShareRatioReached( kt::TorrentInterface* )), + this,SLOT(maxShareRatioReached( kt::TorrentInterface* ))); + connect(m_core,SIGNAL(maxSeedTimeReached(kt::TorrentInterface*)), + this, SLOT(maxSeedTimeReached(kt::TorrentInterface*))); + connect(m_core,SIGNAL(corruptedData( kt::TorrentInterface* )), + this,SLOT(corruptedData( kt::TorrentInterface* ))); + connect(m_core, SIGNAL(queuingNotPossible( kt::TorrentInterface* )), + this, SLOT(queuingNotPossible( kt::TorrentInterface* ))); + connect(m_core,SIGNAL(canNotStart(kt::TorrentInterface*, kt::TorrentStartResponse)), + this,SLOT(canNotStart(kt::TorrentInterface*, kt::TorrentStartResponse))); + connect(m_core, SIGNAL(lowDiskSpace(kt::TorrentInterface*, bool)), + this, SLOT(lowDiskSpace(kt::TorrentInterface*, bool))); + + connect(this->contextMenu(),SIGNAL(aboutToShow()),m_hover_popup,SLOT(contextMenuAboutToShow())); + connect(this->contextMenu(),SIGNAL(aboutToHide()),m_hover_popup,SLOT(contextMenuAboutToHide())); +} + +TrayIcon::~TrayIcon() +{} + +void TrayIcon::enterEvent(QEvent* ev) +{ + KSystemTray::enterEvent(ev); + m_hover_popup->enterEvent(); +} + +void TrayIcon::leaveEvent(QEvent* ) +{ + m_hover_popup->leaveEvent(); +} + +void TrayIcon::updateStats(const CurrentStats stats, bool showBars,int downloadBandwidth, int uploadBandwidth ) +{ + QString tip = i18n("<table cellpadding='2' cellspacing='2' align='center'><tr><td><b>Speed:</b></td><td></td></tr><tr><td>Download: <font color='#1c9a1c'>%1</font></td><td>Upload: <font color='#990000'>%2</font></td></tr><tr><td><b>Transfer:</b></td><td></td></tr><tr><td>Download: <font color='#1c9a1c'>%3</font></td><td>Upload: <font color='#990000'>%4</font></td></tr></table>") + .arg(KBytesPerSecToString((double)stats.download_speed/1024.0)) + .arg(KBytesPerSecToString((double)stats.upload_speed/1024.0)) + .arg(BytesToString(stats.bytes_downloaded)) + .arg(BytesToString(stats.bytes_uploaded)); + m_hover_popup->updateText(tip); + + if(showBars) + drawSpeedBar(stats.download_speed/1024,stats.upload_speed/1024, downloadBandwidth, uploadBandwidth); + else if (previousDownloadHeight > 0 || previousUploadHeight > 0) + { + repaint(); // clear the bars if they are disabled + previousDownloadHeight = previousUploadHeight = 0; + } +} + +void TrayIcon::drawSpeedBar(int downloadSpeed, int uploadSpeed, int downloadBandwidth, int uploadBandwidth ) +{ + //check if need repaint + if (uploadBandwidth == 0) + uploadBandwidth = 1; + if (downloadBandwidth == 0) + downloadBandwidth = 1; + + int DownloadHeight=((downloadSpeed*pixmap()->height())/downloadBandwidth); + int UploadHeight=((uploadSpeed*pixmap()->height())/uploadBandwidth); + if(previousDownloadHeight==DownloadHeight && previousUploadHeight==UploadHeight) + return; + + repaint (); + + QBrush brushD(green); + QBrush brushU(red); + paint->fillRect(0,pixmap()->height(),2,-DownloadHeight,brushD); + paint->fillRect(pixmap()->width()-2,pixmap()->height(),2,-UploadHeight,brushU); + + previousDownloadHeight=DownloadHeight; + previousUploadHeight=UploadHeight; +} + +void TrayIcon::showPassivePopup(const QString & msg,const QString & title) +{ + KPassivePopup* p = KPassivePopup::message(KPassivePopup::Boxed,title,msg,m_kt_pix, this); + p->setPalette(QToolTip::palette()); + p->setLineWidth(1); +} + + +void TrayIcon::finished(TorrentInterface* tc) +{ + if (!Settings::showPopups()) + return; + + const TorrentStats & s = tc->getStats(); + double speed_up = (double)s.bytes_uploaded / 1024.0; + double speed_down = (double)(s.bytes_downloaded - s.imported_bytes)/ 1024.0; + + QString msg = i18n("<b>%1</b> has completed downloading." + "<br>Average speed: %2 DL / %3 UL.") + .arg(s.torrent_name) + .arg(KBytesPerSecToString(speed_down / tc->getRunningTimeDL())) + .arg(KBytesPerSecToString(speed_up / tc->getRunningTimeUL())); + + showPassivePopup(msg,i18n("Download completed")); +} + +void TrayIcon::maxShareRatioReached(kt::TorrentInterface* tc) +{ + if (!Settings::showPopups()) + return; + + const TorrentStats & s = tc->getStats(); + KLocale* loc = KGlobal::locale(); + double speed_up = (double)s.bytes_uploaded / 1024.0; + + QString msg = i18n("<b>%1</b> has reached its maximum share ratio of %2 and has been stopped." + "<br>Uploaded %3 at an average speed of %4.") + .arg(s.torrent_name) + .arg(loc->formatNumber(s.max_share_ratio,2)) + .arg(BytesToString(s.bytes_uploaded)) + .arg(KBytesPerSecToString(speed_up / tc->getRunningTimeUL())); + + showPassivePopup(msg,i18n("Seeding completed")); +} + +void TrayIcon::maxSeedTimeReached(kt::TorrentInterface* tc) +{ + if (!Settings::showPopups()) + return; + + const TorrentStats & s = tc->getStats(); + KLocale* loc = KGlobal::locale(); + double speed_up = (double)s.bytes_uploaded / 1024.0; + + QString msg = i18n("<b>%1</b> has reached its maximum seed time of %2 hours and has been stopped." + "<br>Uploaded %3 at an average speed of %4.") + .arg(s.torrent_name) + .arg(loc->formatNumber(s.max_seed_time,2)) + .arg(BytesToString(s.bytes_uploaded)) + .arg(KBytesPerSecToString(speed_up / tc->getRunningTimeUL())); + + showPassivePopup(msg,i18n("Seeding completed")); +} + +void TrayIcon::torrentStoppedByError(kt::TorrentInterface* tc, QString msg) +{ + if (!Settings::showPopups()) + return; + + const TorrentStats & s = tc->getStats(); + QString err_msg = i18n("<b>%1</b> has been stopped with the following error: <br>%2") + .arg(s.torrent_name).arg(msg); + + showPassivePopup(err_msg,i18n("Error")); +} + +void TrayIcon::corruptedData(kt::TorrentInterface* tc) +{ + if (!Settings::showPopups()) + return; + + const TorrentStats & s = tc->getStats(); + QString err_msg = i18n("Corrupted data has been found in the torrent <b>%1</b>" + "<br>It would be a good idea to do a data integrity check on the torrent.") + .arg(s.torrent_name); + showPassivePopup(err_msg,i18n("Error")); +} + +void TrayIcon::queuingNotPossible(kt::TorrentInterface* tc) +{ + if (!Settings::showPopups()) + return; + + const TorrentStats & s = tc->getStats(); + + QString msg; + KLocale* loc = KGlobal::locale(); + + if (tc->overMaxRatio()) + msg = i18n("<b>%1</b> has reached its maximum share ratio of %2 and cannot be enqueued. Remove the limit manually if you want to continue seeding.") + .arg(s.torrent_name).arg(loc->formatNumber(s.max_share_ratio,2)); + else + msg = i18n("<b>%1</b> has reached its maximum seed time of %2 hours and cannot be enqueued. Remove the limit manually if you want to continue seeding.") + .arg(s.torrent_name).arg(loc->formatNumber(s.max_seed_time,2)); + + showPassivePopup(msg,i18n("Torrent cannot be enqueued.")); +} + +void TrayIcon::canNotStart(kt::TorrentInterface* tc,kt::TorrentStartResponse reason) +{ + if (!Settings::showPopups()) + return; + + QString msg = i18n("Cannot start <b>%1</b> : <br>").arg(tc->getStats().torrent_name); + switch (reason) + { + case kt::QM_LIMITS_REACHED: + if (tc->getStats().bytes_left_to_download == 0) + { + // is a seeder + msg += i18n("Cannot seed more than 1 torrent. <br>", + "Cannot seed more than %n torrents. <br>",Settings::maxSeeds()); + } + else + { + msg += i18n("Cannot download more than 1 torrent. <br>", + "Cannot download more than %n torrents. <br>",Settings::maxDownloads()); + } + msg += i18n("Go to Settings -> Configure KTorrent, if you want to change the limits."); + showPassivePopup(msg,i18n("Torrent cannot be started")); + break; + case kt::NOT_ENOUGH_DISKSPACE: + msg += i18n("There is not enough diskspace available."); + showPassivePopup(msg,i18n("Torrent cannot be started")); + break; + default: + break; + } +} + +void TrayIcon::lowDiskSpace(kt::TorrentInterface * tc, bool stopped) +{ + if (!Settings::showPopups()) + return; + + const TorrentStats & s = tc->getStats(); + + QString msg = i18n("Your disk is running out of space.<br /><b>%1</b> is being downloaded to '%2'.").arg(s.torrent_name).arg(tc->getDataDir()); + + if(stopped) + msg.prepend(i18n("Torrent has been stopped.<br />")); + + showPassivePopup(msg,i18n("Device running out of space")); +} + +SetMaxRate::SetMaxRate( KTorrentCore* tc, int t, QWidget *parent, const char *name):KPopupMenu(parent, name) +{ + m_core = tc; + type=t; + makeMenu(); + connect(this,SIGNAL(activated (int)),this,SLOT(rateSelected(int ))); +} +void SetMaxRate::makeMenu() +{ + + int rate=(type==0) ? m_core->getMaxUploadSpeed() : m_core->getMaxDownloadSpeed(); + int maxBandwidth=(rate > 0) ? rate : (type==0) ? 0 : 20 ; + int delta = 0; + int maxBandwidthRounded; + + setCheckable(true); + insertTitle(i18n("Speed limit in KB/s")); + + if(rate == 0) + setItemChecked(insertItem(i18n("Unlimited")), true); + else + insertItem(i18n("Unlimited")); + + if((maxBandwidth%5)>=3) + maxBandwidthRounded=maxBandwidth + 5 - (maxBandwidth%5); + else + maxBandwidthRounded=maxBandwidth - (maxBandwidth%5); + + for (int i = 0; i < 15; i++) + { + QValueList<int> valuePair; + if (delta == 0) + valuePair.append(maxBandwidth); + else + { + if((maxBandwidth%5)!=0) + { + valuePair.append(maxBandwidthRounded - delta); + valuePair.append(maxBandwidthRounded + delta); + } + else + { + valuePair.append(maxBandwidth - delta); + valuePair.append(maxBandwidth + delta); + } + } + + for (int j = 0; j < (int)valuePair.count(); j++) + { + if (valuePair[j] >= 1) + { + if(rate == valuePair[j] && j==0) + { + setItemChecked(insertItem(QString("%1").arg(valuePair[j]),-1, (j == 0) ? 2 : count()), true); + } + else + insertItem(QString("%1").arg(valuePair[j]),-1, (j == 0) ? 2 : count()); + } + } + + delta += (delta >= 50) ? 50 : (delta >= 20) ? 10 : 5; + + } +} +void SetMaxRate::update() +{ + clear(); + makeMenu(); +} + +void SetMaxRate::rateSelected(int id) +{ + int rate; + QString ratestr = text(id).remove('&'); + if (ratestr.contains(i18n("Unlimited"))) + rate = 0; + else + rate = ratestr.toInt(); + + if(type==0) + { + m_core->setMaxUploadSpeed(rate); + net::SocketMonitor::setUploadCap( Settings::maxUploadRate() * 1024); + } + else + { + m_core->setMaxDownloadSpeed(rate); + net::SocketMonitor::setDownloadCap(Settings::maxDownloadRate()*1024); + } + Settings::writeConfig(); + + update(); +} + + +#include "trayicon.moc" diff --git a/apps/ktorrent/trayicon.h b/apps/ktorrent/trayicon.h new file mode 100644 index 0000000..0c1af44 --- /dev/null +++ b/apps/ktorrent/trayicon.h @@ -0,0 +1,141 @@ +/*************************************************************************** + * Copyright (C) 2005 by * + * Joris Guisson <joris.guisson@gmail.com> * + * Ivan Vasic <ivasic@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 TRAYICON_H +#define TRAYICON_H + + +#include <ksystemtray.h> +#include <kpopupmenu.h> +#include <qpainter.h> + +#include "ktorrentcore.h" +#include "settings.h" +#include "interfaces/torrentinterface.h" +#include <util/constants.h> + +using namespace bt; +class QString; +class TrayHoverPopup; + +struct TrayStats +{ + bt::Uint32 download_speed; + bt::Uint32 upload_speed; + bt::Uint64 bytes_downloaded; + bt::Uint64 bytes_uploaded; +}; + +/** + * @author Joris Guisson + * @author Ivan Vasic +*/ +class TrayIcon : public KSystemTray +{ + Q_OBJECT +public: + TrayIcon(KTorrentCore* tc, QWidget *parent = 0, const char *name = 0); + virtual ~TrayIcon(); + + /// Update stats for system tray icon + void updateStats(const CurrentStats stats, bool showBars=false, int downloadBandwidth=0, int uploadBandwidth=0); + +private: + void drawSpeedBar(int downloadSpeed, int uploadSpeed, int downloadBandwidth, int uploadBandwidth); + void showPassivePopup(const QString & msg,const QString & titile); + virtual void enterEvent(QEvent* ev); + virtual void leaveEvent(QEvent* ev); + +private slots: + /** + * Show a passive popup, that the torrent has stopped downloading. + * @param tc The torrent + */ + void finished(kt::TorrentInterface* tc); + + /** + * Show a passive popup that a torrent has reached it's max share ratio. + * @param tc The torrent + */ + void maxShareRatioReached(kt::TorrentInterface* tc); + + /** + * Show a passive popup that a torrent has reached it's max seed time + * @param tc The torrent + */ + void maxSeedTimeReached(kt::TorrentInterface* tc); + + /** + * Show a passive popup when a torrent has been stopped by an error. + * @param tc The torrent + * @param msg Error message + */ + void torrentStoppedByError(kt::TorrentInterface* tc, QString msg); + + /** + * Corrupted data has been found. + * @param tc The torrent + */ + void corruptedData(kt::TorrentInterface* tc); + + /** + * User tried to enqueue a torrent that has reached max share ratio or max seed time + * Show passive popup message. + */ + void queuingNotPossible(kt::TorrentInterface* tc); + + /** + * We failed to start a torrent + * @param tc The torrent + * @param reason The reason it failed + */ + void canNotStart(kt::TorrentInterface* tc,kt::TorrentStartResponse reason); + + ///Shows passive popup message + void lowDiskSpace(kt::TorrentInterface* tc, bool stopped); + +private: + KTorrentCore* m_core; + QPainter *paint; + int previousDownloadHeight; + int previousUploadHeight; + TrayHoverPopup* m_hover_popup; + QPixmap m_kt_pix; +}; + +class SetMaxRate : public KPopupMenu +{ + Q_OBJECT + public: + SetMaxRate(KTorrentCore* tc, int t, QWidget *parent=0, const char *name=0); // type: 0 Upload; 1 Download + ~SetMaxRate() + {} + ; + + void update(); + private: + KTorrentCore* m_core; + int type; + void makeMenu(); + private slots: + void rateSelected(int id); +}; + +#endif diff --git a/apps/ktorrent/viewmanager.cpp b/apps/ktorrent/viewmanager.cpp new file mode 100644 index 0000000..17c2782 --- /dev/null +++ b/apps/ktorrent/viewmanager.cpp @@ -0,0 +1,265 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <kconfig.h> +#include <klocale.h> +#include <ktabwidget.h> +#include <interfaces/torrentinterface.h> +#include <groups/group.h> +#include "viewmanager.h" +#include "ktorrentview.h" +#include "ktorrent.h" + +typedef QValueList<KTorrentView*>::iterator ViewItr; + +ViewManager::ViewManager ( QObject *parent, const char *name ) + : QObject ( parent, name ),current(0) +{} + + +ViewManager::~ViewManager() +{} + +KTorrentView* ViewManager::newView() +{ + KTorrentView* v = new KTorrentView(0); + views.append(v); + return v; +} + +void ViewManager::saveViewState(KConfig* cfg) +{ + QStringList cv; + int idx = 0; + for (ViewItr i = views.begin();i != views.end();i++) + { + cv.append((*i)->getCurrentGroup()->groupName()); + (*i)->saveSettings(cfg,idx++); + } + cfg->setGroup("ViewManager"); + cfg->writeEntry("current_views",cv); +} + +void ViewManager::restoreViewState(KConfig* cfg,KTorrent* ktor) +{ + QStringList def; + def.append(i18n("Downloads")); + def.append(i18n("Uploads")); + + cfg->setGroup("ViewManager"); + + QStringList to_load = cfg->readListEntry("current_views",def); + if (to_load.empty()) + to_load = def; + + for (QStringList::iterator i = to_load.begin();i != to_load.end();i++) + { + ktor->openView(*i); + } + + if (views.count() == 0) + { + // no view open, so open default ones + for (QStringList::iterator i = def.begin();i != def.end();i++) + ktor->openView(*i); + } + + // load status for each view + int idx = 0; + for (ViewItr i = views.begin();i != views.end();i++) + { + (*i)->loadSettings(cfg,idx++); + } +} + +void ViewManager::updateActions() +{ + if (current) + current->updateActions(); +} + +void ViewManager::addTorrent(kt::TorrentInterface* tc) +{ + for (ViewItr i = views.begin();i != views.end();i++) + { + (*i)->addTorrent(tc); + } +} + +void ViewManager::removeTorrent(kt::TorrentInterface* tc) +{ + for (ViewItr i = views.begin();i != views.end();i++) + { + (*i)->removeTorrent(tc); + } +} + +void ViewManager::startDownloads() +{ + if (current) + current->startDownloads(); +} + +void ViewManager::stopDownloads() +{ + if (current) + current->stopDownloads(); +} + +void ViewManager::startAllDownloads() +{ + if (current) + current->startAllDownloads(); +} + +void ViewManager::stopAllDownloads() +{ + if (current) + current->stopAllDownloads(); +} + +void ViewManager::removeDownloads() +{ + if (current) + current->removeDownloads(); +} + +kt::TorrentInterface* ViewManager::getCurrentTC() +{ + return current ? current->getCurrentTC() : 0; +} + +void ViewManager::update() +{ + // update the caption of each view if necessary + for (ViewItr i = views.begin();i != views.end();i++) + { + if (*i != current) + { + KTorrentView* w = *i; + w->updateCaption(); + } + } + + if (current) + current->update(); +} + +void ViewManager::queueAction() +{ + if (current) + current->queueSlot(); +} + +void ViewManager::checkDataIntegrity() +{ + if (current) + current->checkDataIntegrity(); +} + +void ViewManager::getSelection(QValueList<kt::TorrentInterface*> & sel) +{ + if (current) + current->getSelection(sel); +} + +void ViewManager::onCurrentTabChanged(QWidget* w) +{ + KTorrentView* old = current; + current = 0; + for (ViewItr i = views.begin();i != views.end() && !current;i++) + { + if (w == *i) + current = *i; + } + + if (!current) + current = old; + else + { + current->update(); + current->updateActions(); + } +} + +bool ViewManager::closeAllowed(QWidget* ) +{ + return views.count() > 1; +} + +void ViewManager::tabCloseRequest(kt::GUIInterface* gui,QWidget* tab) +{ + for (ViewItr i = views.begin();i != views.end();i++) + { + if (tab == *i) + { + if (current == *i) + current = 0; + + gui->removeTabPage(tab); + delete tab; + views.erase(i); + break; + } + } +} + +void ViewManager::groupRenamed(kt::Group* g,KTabWidget* mtw) +{ + for (ViewItr i = views.begin();i != views.end();i++) + { + KTorrentView* v = *i; + if (v->getCurrentGroup() == g) + { + mtw->changeTab(v,g->groupName()); + v->setIcon(g->groupIcon()); + v->setCurrentGroup(g); + } + } +} + +void ViewManager::groupRemoved(kt::Group* g,KTabWidget* mtw,kt::GUIInterface* gui,kt::Group* all_group) +{ + for (ViewItr i = views.begin();i != views.end();) + { + KTorrentView* v = *i; + if (v->getCurrentGroup() == g) + { + if (views.count() > 1) + { + // close the tab + gui->removeTabPage(v); + delete v; + i = views.erase(i); + } + else + { + mtw->changeTab(v,all_group->groupName()); + v->setIcon(all_group->groupIcon()); + v->setCurrentGroup(all_group); + i++; + } + } + else + i++; + } +} + + +#include "viewmanager.moc" diff --git a/apps/ktorrent/viewmanager.h b/apps/ktorrent/viewmanager.h new file mode 100644 index 0000000..d008c62 --- /dev/null +++ b/apps/ktorrent/viewmanager.h @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 VIEWMANAGER_H +#define VIEWMANAGER_H + +#include <qobject.h> +#include <qvaluelist.h> +#include <interfaces/guiinterface.h> + +class KConfig; +class KTabWidget; +class KTorrentView; +class KTorrent; + +/** + @author Joris Guisson <joris.guisson@gmail.com> +*/ +class ViewManager : public QObject, public kt::CloseTabListener +{ + Q_OBJECT +public: + ViewManager(QObject *parent = 0, const char *name = 0); + virtual ~ViewManager(); + + /// Create a new view + KTorrentView* newView(); + + /// Save all views + void saveViewState(KConfig* cfg); + + /// Restore all views from configuration + void restoreViewState(KConfig* cfg,KTorrent* ktor); + + /// Start all selected downloads in the current view + void startDownloads(); + + /// Stop all selected downloads in the current view + void stopDownloads(); + + /// Start all downloads in the current view + void startAllDownloads(); + + /// Stop all downloads in the current view + void stopAllDownloads(); + + /// Get the current torrent in the current view + kt::TorrentInterface* getCurrentTC(); + + /// Remove selected downloads in the current view + void removeDownloads(); + + /// Update the current view + void update(); + + /** + * Put the current selection of the current view in a list. + * @param sel The list to put it in + */ + void getSelection(QValueList<kt::TorrentInterface*> & sel); + + /// Get the current view + KTorrentView* getCurrentView() {return current;} + + virtual bool closeAllowed(QWidget* tab); + virtual void tabCloseRequest(kt::GUIInterface* gui,QWidget* tab); + + /// A group was renamed, modify all view which where showing this group + void groupRenamed(kt::Group* g,KTabWidget* mtw); + + /// A group has been removed, close any tab showing it (in case it is the last tab, switch to All Torrents) + void groupRemoved(kt::Group* g,KTabWidget* mtw,kt::GUIInterface* gui,kt::Group* all_group); + + /// Call updateActions on the current view + void updateActions(); + +public slots: + /// Add a torrent to all views + void addTorrent(kt::TorrentInterface* tc); + + /// Remove a torernt from all views + void removeTorrent(kt::TorrentInterface* tc); + + /// Enqueue/Dequeue selected torrents in current view + void queueAction(); + + /// Check data integrity of current torrent + void checkDataIntegrity(); + + /// The current tab has changed + void onCurrentTabChanged(QWidget* w); + +private: + QValueList<KTorrentView*> views; + KTorrentView* current; +}; + +#endif diff --git a/apps/ktorrent/x-bittorrent.desktop b/apps/ktorrent/x-bittorrent.desktop new file mode 100644 index 0000000..2db2de8 --- /dev/null +++ b/apps/ktorrent/x-bittorrent.desktop @@ -0,0 +1,39 @@ +[Desktop Entry] +Encoding=UTF-8 +Comment=BitTorrent Download +Comment[ar]=تنزيل BitTorrent +Comment[bg]=Сваляне на Бит Торент +Comment[ca]=Una baixada BitTorrent +Comment[cs]=Stažení BitTorrent +Comment[cy]=Lawrlwythiad BitTorrent +Comment[da]=BitTorrent-download +Comment[de]=BitTorrent-Herunterladevorgang +Comment[el]=Λήψη BitTorrent +Comment[es]=Descarga de BitTorrent +Comment[et]=BitTorrenti allalaadimine +Comment[fa]=بارگیری BitTorrent +Comment[gl]=Descarga de BitTorrent +Comment[it]=Scaricamento BitTorrent +Comment[ja]=BitTorrent ダウンロード +Comment[ka]=BitTorrent-ით ჩამოტვირვა +Comment[nb]=BitTorrent-nedlasting +Comment[nds]=Bittorrent-Daalladen +Comment[nl]=BitTorrent-download +Comment[pl]=Pobieranie plików BitTorrent +Comment[pt]=Transferência do BitTorrent +Comment[pt_BR]=Um programa BitTorrent para download +Comment[sk]=Sťahovanie BitTorrent +Comment[sr]=BitTorrent преузимање +Comment[sr@Latn]=BitTorrent preuzimanje +Comment[sv]=BitTorrent-nerladdning +Comment[tr]=BitTorrent İndirme +Comment[uk]=Звантаження BitTorrent +Comment[xx]=xxBitTorrent Downloadxx +Comment[zh_CN]=BitTorrent 下载 +Comment[zh_TW]=BitTorrent 下載 +Hidden=false +MimeType=application/x-bittorrent +Icon=torrent +Type=MimeType +Patterns=*.torrent;*.tor +X-KDE-AutoEmbed=false diff --git a/apps/kttorinfo/Makefile.am b/apps/kttorinfo/Makefile.am new file mode 100644 index 0000000..01e34c3 --- /dev/null +++ b/apps/kttorinfo/Makefile.am @@ -0,0 +1,10 @@ +INCLUDES = -I$(srcdir)/../../libktorrent $(all_includes) +METASOURCES = AUTO + +bin_PROGRAMS = kttorinfo +kttorinfo_SOURCES = main.cpp +kttorinfo_LDFLAGS = $(KDE_RPATH) $(all_libraries) +kttorinfo_LDADD = ../../libktorrent/libktorrent.la $(LIB_KPARTS) $(LIB_KFILE) \ + $(LIB_KIO) + +KDE_CXXFLAGS = $(USE_EXCEPTIONS) $(USE_RTTI) diff --git a/apps/kttorinfo/main.cpp b/apps/kttorinfo/main.cpp new file mode 100644 index 0000000..e33a763 --- /dev/null +++ b/apps/kttorinfo/main.cpp @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <stdlib.h> +#include <qstring.h> +#include <util/log.h> +#include <util/error.h> +#include <torrent/globals.h> +#include <torrent/torrent.h> + +using namespace bt; + +void help() +{ + Out() << "Usage : kttorinfo <torrent>" << endl; + exit(0); +} + +int main(int argc,char** argv) +{ + Globals::instance().setDebugMode(true); + Globals::instance().initLog("kttorinfo.log"); + if (argc < 2) + help(); + + try + { + Torrent tor; + tor.load(argv[1],false); + tor.debugPrintInfo(); + } + catch (Error & e) + { + Out() << "Error : " << e.toString() << endl; + } + Globals::cleanup(); + return 0; +} diff --git a/apps/ktupnptest/Makefile.am b/apps/ktupnptest/Makefile.am new file mode 100644 index 0000000..95cfa6e --- /dev/null +++ b/apps/ktupnptest/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I$(srcdir)/../../libktorrent -I$(srcdir)/../.. $(all_includes) +METASOURCES = AUTO +bin_PROGRAMS = ktupnptest + +ktupnptest_SOURCES = main.cpp upnptestapp.cpp mainwidget.ui +ktupnptest_LDADD = ../../plugins/upnp/libktupnp.la \ + ../../libktorrent/libktorrent.la +noinst_HEADERS = upnptestapp.h +KDE_CXXFLAGS = $(USE_EXCEPTIONS) $(USE_RTTI) diff --git a/apps/ktupnptest/main.cpp b/apps/ktupnptest/main.cpp new file mode 100644 index 0000000..c2629ef --- /dev/null +++ b/apps/ktupnptest/main.cpp @@ -0,0 +1,98 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <stdio.h> +#include <stdlib.h> +#include <klocale.h> +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <libktorrent/functions.h> + + +#include "upnptestapp.h" + +using namespace kt; +using namespace bt; + +static const char description[] = + I18N_NOOP("A KDE KPart Application"); + +static const char version[] = "1.3dev"; + +static KCmdLineOptions options[] = +{ +// { "+[URL]", I18N_NOOP( "Document to open" ), 0 }, + KCmdLineLastOption +}; + + + + +int main(int argc,char** argv) +{ + Globals::instance().setDebugMode(true); + KAboutData about("ktupnptest", I18N_NOOP("KTUPnPTest"), version, description, + KAboutData::License_GPL, "(C) 2005 Joris Guisson", 0, + "http://ktorrent.org/"); + KCmdLineArgs::init(argc, argv,&about); + KCmdLineArgs::addCmdLineOptions( options ); + KApplication app; + Globals::instance().initLog(kt::DataDir() + "ktupnptest.log"); + UPnPTestApp* mwnd = new UPnPTestApp(); + + app.setMainWidget(mwnd); + mwnd->show(); + app.exec(); + Globals::cleanup(); + return 0; + + /* + if (argc >= 2) + { + kt::UPnPRouter router(QString::null,"http://foobar.com"); + kt::UPnPDescriptionParser dp; + + if (!dp.parse(argv[1],&router)) + { + Out() << "Cannot parse " << QString(argv[1]) << endl; + } + else + { + Out() << "Succesfully parsed the UPnP contents" << endl; + router.debugPrintData(); + } + } + + + Out() << "Doing second test" << endl; + UPnPMCastSocket mcast; + UPnPRouter* r = mcast.parseResponse(QCString(test_ps)); + if (r) + { + Out() << "Succesfully parsed test_ps" << endl; + delete r; + } + else + { + Out() << "Failed to parse test_ps" << endl; + } + */ + +} diff --git a/apps/ktupnptest/mainwidget.ui b/apps/ktupnptest/mainwidget.ui new file mode 100644 index 0000000..cb375f8 --- /dev/null +++ b/apps/ktupnptest/mainwidget.ui @@ -0,0 +1,76 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>MainWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>MainWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>480</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTextBrowser"> + <property name="name"> + <cstring>output</cstring> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>61</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>test_btn</cstring> + </property> + <property name="text"> + <string>Test</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>close_btn</cstring> + </property> + <property name="text"> + <string>Close</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/apps/ktupnptest/upnptestapp.cpp b/apps/ktupnptest/upnptestapp.cpp new file mode 100644 index 0000000..d50b314 --- /dev/null +++ b/apps/ktupnptest/upnptestapp.cpp @@ -0,0 +1,87 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 <kpushbutton.h> +#include <klocale.h> +#include <kapplication.h> +#include <kmessagebox.h> +#include <qtextbrowser.h> +#include <util/error.h> +#include "upnptestapp.h" +#include "mainwidget.h" + +using namespace bt; +using namespace kt; + +UPnPTestApp::UPnPTestApp(QWidget *parent, const char *name) + : KMainWindow(parent, name) +{ + sock = new UPnPMCastSocket(true); + connect(sock,SIGNAL(discovered( UPnPRouter* )),this,SLOT(discovered( UPnPRouter* ))); + mwnd = new MainWidget(this); + setCentralWidget(mwnd); + connect(mwnd->test_btn,SIGNAL(clicked()),this,SLOT(onTestBtn())); + connect(mwnd->close_btn,SIGNAL(clicked()),this,SLOT(onCloseBtn())); + bt::Log & lg = bt::Globals::instance().getLog(0); + lg.addMonitor(this); + Out() << "UPnPTestApp started up !" << endl; +} + + +UPnPTestApp::~UPnPTestApp() +{ + sock->deleteLater(); +} + +void UPnPTestApp::discovered(kt::UPnPRouter* router) +{ + try + { + router->forward(net::Port(9999,net::TCP,false)); + } + catch (Error & e) + { + KMessageBox::error(this,e.toString()); + } +} + +void UPnPTestApp::onTestBtn() +{ + sock->discover(); +} + +void UPnPTestApp::onCloseBtn() +{ + kapp->quit(); +} + +bool UPnPTestApp::queryExit() +{ + bt::Log & lg = bt::Globals::instance().getLog(0); + lg.removeMonitor(this); + return true; +} + +void UPnPTestApp::message(const QString& line, unsigned int arg) +{ + mwnd->output->append(line); +} + + +#include "upnptestapp.moc" diff --git a/apps/ktupnptest/upnptestapp.h b/apps/ktupnptest/upnptestapp.h new file mode 100644 index 0000000..6554687 --- /dev/null +++ b/apps/ktupnptest/upnptestapp.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2005 by Joris Guisson * + * joris.guisson@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 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public 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 UPNPTESTAPP_H +#define UPNPTESTAPP_H + +#include <kmainwindow.h> +#include <libktorrent/util/log.h> +#include <libktorrent/torrent/globals.h> +#include <plugins/upnp/upnprouter.h> +#include <plugins/upnp/upnpdescriptionparser.h> +#include <plugins/upnp/upnpmcastsocket.h> +#include <interfaces/logmonitorinterface.h> + +class MainWidget; + +using kt::UPnPRouter; + +/** + @author Joris Guisson <joris.guisson@gmail.com> +*/ +class UPnPTestApp : public KMainWindow, public kt::LogMonitorInterface +{ + Q_OBJECT +public: + UPnPTestApp(QWidget *parent = 0, const char *name = 0); + virtual ~UPnPTestApp(); + + virtual void message(const QString& line, unsigned int arg); + bool queryExit(); + +private slots: + void discovered(UPnPRouter* router); + void onTestBtn(); + void onCloseBtn(); + +private: + kt::UPnPMCastSocket* sock; + MainWidget* mwnd; +}; + +#endif |