summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/Makefile.am1
-rw-r--r--apps/ktcachecheck/Makefile.am12
-rw-r--r--apps/ktcachecheck/cachecheck.cpp102
-rw-r--r--apps/ktcachecheck/cachechecker.cpp110
-rw-r--r--apps/ktcachecheck/cachechecker.h61
-rw-r--r--apps/ktcachecheck/multicachechecker.cpp143
-rw-r--r--apps/ktcachecheck/multicachechecker.h44
-rw-r--r--apps/ktcachecheck/singlecachechecker.cpp110
-rw-r--r--apps/ktcachecheck/singlecachechecker.h43
-rw-r--r--apps/ktorrent/Makefile.am65
-rw-r--r--apps/ktorrent/README81
-rw-r--r--apps/ktorrent/addpeerwidget.cpp111
-rw-r--r--apps/ktorrent/addpeerwidget.h93
-rw-r--r--apps/ktorrent/addpeerwidgetbase.ui164
-rw-r--r--apps/ktorrent/advancedpref.ui656
-rw-r--r--apps/ktorrent/custom_widgets.cw68
-rw-r--r--apps/ktorrent/dcopinterface.h69
-rw-r--r--apps/ktorrent/downloadpref.ui735
-rw-r--r--apps/ktorrent/fileselectdlg.cpp297
-rw-r--r--apps/ktorrent/fileselectdlg.h84
-rw-r--r--apps/ktorrent/fileselectdlgbase.ui384
-rw-r--r--apps/ktorrent/filterbar.cpp126
-rw-r--r--apps/ktorrent/filterbar.h70
-rw-r--r--apps/ktorrent/generalpref.ui475
-rw-r--r--apps/ktorrent/groups/Makefile.am15
-rw-r--r--apps/ktorrent/groups/activedownloadsgroup.cpp49
-rw-r--r--apps/ktorrent/groups/activedownloadsgroup.h45
-rw-r--r--apps/ktorrent/groups/activegroup.cpp49
-rw-r--r--apps/ktorrent/groups/activegroup.h45
-rw-r--r--apps/ktorrent/groups/activeuploadsgroup.cpp50
-rw-r--r--apps/ktorrent/groups/activeuploadsgroup.h45
-rw-r--r--apps/ktorrent/groups/allgroup.cpp41
-rw-r--r--apps/ktorrent/groups/allgroup.h43
-rw-r--r--apps/ktorrent/groups/downloadgroup.cpp45
-rw-r--r--apps/ktorrent/groups/downloadgroup.h43
-rw-r--r--apps/ktorrent/groups/group.cpp61
-rw-r--r--apps/ktorrent/groups/group.h133
-rw-r--r--apps/ktorrent/groups/groupmanager.cpp221
-rw-r--r--apps/ktorrent/groups/groupmanager.h132
-rw-r--r--apps/ktorrent/groups/groupview.cpp360
-rw-r--r--apps/ktorrent/groups/groupview.h125
-rw-r--r--apps/ktorrent/groups/inactivedownloadsgroup.cpp50
-rw-r--r--apps/ktorrent/groups/inactivedownloadsgroup.h45
-rw-r--r--apps/ktorrent/groups/inactivegroup.cpp49
-rw-r--r--apps/ktorrent/groups/inactivegroup.h45
-rw-r--r--apps/ktorrent/groups/inactiveuploadsgroup.cpp50
-rw-r--r--apps/ktorrent/groups/inactiveuploadsgroup.h45
-rw-r--r--apps/ktorrent/groups/queueddownloadsgroup.cpp47
-rw-r--r--apps/ktorrent/groups/queueddownloadsgroup.h44
-rw-r--r--apps/ktorrent/groups/queueduploadsgroup.cpp47
-rw-r--r--apps/ktorrent/groups/queueduploadsgroup.h44
-rw-r--r--apps/ktorrent/groups/torrentdrag.cpp37
-rw-r--r--apps/ktorrent/groups/torrentdrag.h43
-rw-r--r--apps/ktorrent/groups/torrentgroup.cpp147
-rw-r--r--apps/ktorrent/groups/torrentgroup.h56
-rw-r--r--apps/ktorrent/groups/uploadgroup.cpp45
-rw-r--r--apps/ktorrent/groups/uploadgroup.h43
-rw-r--r--apps/ktorrent/groups/userdownloadsgroup.cpp47
-rw-r--r--apps/ktorrent/groups/userdownloadsgroup.h44
-rw-r--r--apps/ktorrent/groups/useruploadsgroup.cpp47
-rw-r--r--apps/ktorrent/groups/useruploadsgroup.h44
-rw-r--r--apps/ktorrent/hi128-app-ktorrent.pngbin0 -> 26977 bytes
-rw-r--r--apps/ktorrent/hi128-mime-torrent.pngbin0 -> 18661 bytes
-rw-r--r--apps/ktorrent/hi16-app-ktorrent.pngbin0 -> 3734 bytes
-rw-r--r--apps/ktorrent/hi16-mime-torrent.pngbin0 -> 863 bytes
-rw-r--r--apps/ktorrent/hi22-action-ktencrypted.pngbin0 -> 653 bytes
-rw-r--r--apps/ktorrent/hi22-action-ktremove.pngbin0 -> 1526 bytes
-rw-r--r--apps/ktorrent/hi22-action-ktstart.pngbin0 -> 1232 bytes
-rw-r--r--apps/ktorrent/hi22-action-ktstart_all.pngbin0 -> 1399 bytes
-rw-r--r--apps/ktorrent/hi22-action-ktstop.pngbin0 -> 963 bytes
-rw-r--r--apps/ktorrent/hi22-action-ktstop_all.pngbin0 -> 1128 bytes
-rw-r--r--apps/ktorrent/hi22-app-ktorrent.pngbin0 -> 4369 bytes
-rw-r--r--apps/ktorrent/hi22-mime-torrent.pngbin0 -> 1344 bytes
-rw-r--r--apps/ktorrent/hi32-app-ktorrent.pngbin0 -> 5646 bytes
-rw-r--r--apps/ktorrent/hi32-mime-torrent.pngbin0 -> 2064 bytes
-rw-r--r--apps/ktorrent/hi48-action-ktplugins.pngbin0 -> 3101 bytes
-rw-r--r--apps/ktorrent/hi48-app-ktorrent.pngbin0 -> 8190 bytes
-rw-r--r--apps/ktorrent/hi48-mime-torrent.pngbin0 -> 3790 bytes
-rw-r--r--apps/ktorrent/hi64-action-ktinfowidget.pngbin0 -> 1776 bytes
-rw-r--r--apps/ktorrent/hi64-action-ktqueuemanager.pngbin0 -> 5596 bytes
-rw-r--r--apps/ktorrent/hi64-action-ktupnp.pngbin0 -> 5209 bytes
-rw-r--r--apps/ktorrent/hi64-app-ktorrent.pngbin0 -> 11144 bytes
-rw-r--r--apps/ktorrent/hi64-filesys-ktprefdownloads.pngbin0 -> 6781 bytes
-rw-r--r--apps/ktorrent/hi64-mime-torrent.pngbin0 -> 6005 bytes
-rw-r--r--apps/ktorrent/hisc-app-ktorrent.svgzbin0 -> 6674 bytes
-rw-r--r--apps/ktorrent/hisc-mime-torrent.svgzbin0 -> 10113 bytes
-rw-r--r--apps/ktorrent/ipfilterwidget.cpp194
-rw-r--r--apps/ktorrent/ipfilterwidget.h48
-rw-r--r--apps/ktorrent/ipfilterwidgetbase.ui368
-rw-r--r--apps/ktorrent/ktorrent.cpp1017
-rw-r--r--apps/ktorrent/ktorrent.desktop85
-rw-r--r--apps/ktorrent/ktorrent.h238
-rw-r--r--apps/ktorrent/ktorrent.lsm16
-rw-r--r--apps/ktorrent/ktorrentapp.cpp80
-rw-r--r--apps/ktorrent/ktorrentapp.h38
-rw-r--r--apps/ktorrent/ktorrentcore.cpp1145
-rw-r--r--apps/ktorrent/ktorrentcore.h357
-rw-r--r--apps/ktorrent/ktorrentdcop.cpp254
-rw-r--r--apps/ktorrent/ktorrentdcop.h75
-rw-r--r--apps/ktorrent/ktorrentplugin.desktop33
-rw-r--r--apps/ktorrent/ktorrentui.rc44
-rw-r--r--apps/ktorrent/ktorrentview.cpp912
-rw-r--r--apps/ktorrent/ktorrentview.h216
-rw-r--r--apps/ktorrent/ktorrentviewitem.cpp354
-rw-r--r--apps/ktorrent/ktorrentviewitem.h58
-rw-r--r--apps/ktorrent/ktorrentviewmenu.cpp217
-rw-r--r--apps/ktorrent/ktorrentviewmenu.h76
-rw-r--r--apps/ktorrent/leaktrace.cpp295
-rw-r--r--apps/ktorrent/main.cpp201
-rw-r--r--apps/ktorrent/newui/Makefile.am8
-rw-r--r--apps/ktorrent/newui/button.cpp351
-rw-r--r--apps/ktorrent/newui/button.h108
-rw-r--r--apps/ktorrent/newui/buttonbar.cpp346
-rw-r--r--apps/ktorrent/newui/buttonbar.h112
-rw-r--r--apps/ktorrent/newui/comdefs.h30
-rw-r--r--apps/ktorrent/newui/ddockwindow.cpp418
-rw-r--r--apps/ktorrent/newui/ddockwindow.h116
-rw-r--r--apps/ktorrent/newui/dmainwindow.cpp320
-rw-r--r--apps/ktorrent/newui/dmainwindow.h113
-rw-r--r--apps/ktorrent/newui/docksplitter.cpp175
-rw-r--r--apps/ktorrent/newui/docksplitter.h62
-rw-r--r--apps/ktorrent/newui/dtabwidget.cpp111
-rw-r--r--apps/ktorrent/newui/dtabwidget.h58
-rw-r--r--apps/ktorrent/pastedialog.cpp62
-rw-r--r--apps/ktorrent/pastedialog.h44
-rw-r--r--apps/ktorrent/pastedlgbase.ui142
-rw-r--r--apps/ktorrent/pref.cpp508
-rw-r--r--apps/ktorrent/pref.h121
-rw-r--r--apps/ktorrent/queuedialog.cpp391
-rw-r--r--apps/ktorrent/queuedialog.h83
-rw-r--r--apps/ktorrent/queuedlg.ui726
-rw-r--r--apps/ktorrent/scandialog.cpp202
-rw-r--r--apps/ktorrent/scandialog.h87
-rw-r--r--apps/ktorrent/scandlgbase.ui193
-rw-r--r--apps/ktorrent/speedlimitsdlg.cpp63
-rw-r--r--apps/ktorrent/speedlimitsdlg.h47
-rw-r--r--apps/ktorrent/speedlimitsdlgbase.ui196
-rw-r--r--apps/ktorrent/torrentcreatordlg.cpp152
-rw-r--r--apps/ktorrent/torrentcreatordlg.h39
-rw-r--r--apps/ktorrent/torrentcreatordlgbase.ui533
-rw-r--r--apps/ktorrent/trayhoverpopup.cpp136
-rw-r--r--apps/ktorrent/trayhoverpopup.h71
-rw-r--r--apps/ktorrent/trayicon.cpp380
-rw-r--r--apps/ktorrent/trayicon.h141
-rw-r--r--apps/ktorrent/viewmanager.cpp265
-rw-r--r--apps/ktorrent/viewmanager.h114
-rw-r--r--apps/ktorrent/x-bittorrent.desktop39
-rw-r--r--apps/kttorinfo/Makefile.am10
-rw-r--r--apps/kttorinfo/main.cpp54
-rw-r--r--apps/ktupnptest/Makefile.am9
-rw-r--r--apps/ktupnptest/main.cpp98
-rw-r--r--apps/ktupnptest/mainwidget.ui76
-rw-r--r--apps/ktupnptest/upnptestapp.cpp87
-rw-r--r--apps/ktupnptest/upnptestapp.h58
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>&amp;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>&lt;b&gt;KTorrent algorithm:&lt;/b&gt; Default algorithm using combination of other algorithms based on our tests.&lt;br&gt;
+&lt;b&gt;Current speed algorithm:&lt;/b&gt; Simplest algorithm - BytesLeft/CurrentSpeed&lt;br&gt;
+&lt;b&gt;Global average speed algorithm:&lt;/b&gt; BytesLeft/AverageSpeed&lt;br&gt;
+&lt;b&gt;Window of X algorithm:&lt;/b&gt; ET calculated from X speed samples&lt;br&gt;
+&lt;b&gt;Moving average algorithm:&lt;/b&gt; 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>&lt;b&gt;KTorrent algorithm:&lt;/b&gt; Default algorithm using combination of other algorithms based on our tests.&lt;br&gt;
+&lt;b&gt;Current speed algorithm:&lt;/b&gt; Simplest algorithm - BytesLeft/CurrentSpeed&lt;br&gt;
+&lt;b&gt;Global average speed algorithm:&lt;/b&gt; BytesLeft/AverageSpeed&lt;br&gt;
+&lt;b&gt;Window of X algorithm:&lt;/b&gt; ET calculated from X speed samples&lt;br&gt;
+&lt;b&gt;Moving average algorithm:&lt;/b&gt; 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&amp;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&amp;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 &amp;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&amp;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&amp;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>&amp;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>&amp;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 &amp;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 &amp;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>&amp;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>&amp;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>&lt;b&gt;D&lt;/b&gt;istributed &lt;b&gt;H&lt;/b&gt;ash &lt;b&gt;T&lt;/b&gt;able protocol.&lt;br&gt;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>&amp;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&amp;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&amp;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 &amp;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>&amp;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
new file mode 100644
index 0000000..6cb2185
--- /dev/null
+++ b/apps/ktorrent/hi128-app-ktorrent.png
Binary files differ
diff --git a/apps/ktorrent/hi128-mime-torrent.png b/apps/ktorrent/hi128-mime-torrent.png
new file mode 100644
index 0000000..a7b8d7d
--- /dev/null
+++ b/apps/ktorrent/hi128-mime-torrent.png
Binary files differ
diff --git a/apps/ktorrent/hi16-app-ktorrent.png b/apps/ktorrent/hi16-app-ktorrent.png
new file mode 100644
index 0000000..da8aac9
--- /dev/null
+++ b/apps/ktorrent/hi16-app-ktorrent.png
Binary files differ
diff --git a/apps/ktorrent/hi16-mime-torrent.png b/apps/ktorrent/hi16-mime-torrent.png
new file mode 100644
index 0000000..f1eceaf
--- /dev/null
+++ b/apps/ktorrent/hi16-mime-torrent.png
Binary files differ
diff --git a/apps/ktorrent/hi22-action-ktencrypted.png b/apps/ktorrent/hi22-action-ktencrypted.png
new file mode 100644
index 0000000..d3a0020
--- /dev/null
+++ b/apps/ktorrent/hi22-action-ktencrypted.png
Binary files differ
diff --git a/apps/ktorrent/hi22-action-ktremove.png b/apps/ktorrent/hi22-action-ktremove.png
new file mode 100644
index 0000000..3da332f
--- /dev/null
+++ b/apps/ktorrent/hi22-action-ktremove.png
Binary files differ
diff --git a/apps/ktorrent/hi22-action-ktstart.png b/apps/ktorrent/hi22-action-ktstart.png
new file mode 100644
index 0000000..c7995a0
--- /dev/null
+++ b/apps/ktorrent/hi22-action-ktstart.png
Binary files differ
diff --git a/apps/ktorrent/hi22-action-ktstart_all.png b/apps/ktorrent/hi22-action-ktstart_all.png
new file mode 100644
index 0000000..1c55069
--- /dev/null
+++ b/apps/ktorrent/hi22-action-ktstart_all.png
Binary files differ
diff --git a/apps/ktorrent/hi22-action-ktstop.png b/apps/ktorrent/hi22-action-ktstop.png
new file mode 100644
index 0000000..5b59e46
--- /dev/null
+++ b/apps/ktorrent/hi22-action-ktstop.png
Binary files differ
diff --git a/apps/ktorrent/hi22-action-ktstop_all.png b/apps/ktorrent/hi22-action-ktstop_all.png
new file mode 100644
index 0000000..8086b69
--- /dev/null
+++ b/apps/ktorrent/hi22-action-ktstop_all.png
Binary files differ
diff --git a/apps/ktorrent/hi22-app-ktorrent.png b/apps/ktorrent/hi22-app-ktorrent.png
new file mode 100644
index 0000000..b0f3804
--- /dev/null
+++ b/apps/ktorrent/hi22-app-ktorrent.png
Binary files differ
diff --git a/apps/ktorrent/hi22-mime-torrent.png b/apps/ktorrent/hi22-mime-torrent.png
new file mode 100644
index 0000000..240a3c6
--- /dev/null
+++ b/apps/ktorrent/hi22-mime-torrent.png
Binary files differ
diff --git a/apps/ktorrent/hi32-app-ktorrent.png b/apps/ktorrent/hi32-app-ktorrent.png
new file mode 100644
index 0000000..661dc97
--- /dev/null
+++ b/apps/ktorrent/hi32-app-ktorrent.png
Binary files differ
diff --git a/apps/ktorrent/hi32-mime-torrent.png b/apps/ktorrent/hi32-mime-torrent.png
new file mode 100644
index 0000000..265c104
--- /dev/null
+++ b/apps/ktorrent/hi32-mime-torrent.png
Binary files differ
diff --git a/apps/ktorrent/hi48-action-ktplugins.png b/apps/ktorrent/hi48-action-ktplugins.png
new file mode 100644
index 0000000..ed3ead1
--- /dev/null
+++ b/apps/ktorrent/hi48-action-ktplugins.png
Binary files differ
diff --git a/apps/ktorrent/hi48-app-ktorrent.png b/apps/ktorrent/hi48-app-ktorrent.png
new file mode 100644
index 0000000..f35e53e
--- /dev/null
+++ b/apps/ktorrent/hi48-app-ktorrent.png
Binary files differ
diff --git a/apps/ktorrent/hi48-mime-torrent.png b/apps/ktorrent/hi48-mime-torrent.png
new file mode 100644
index 0000000..e158dfa
--- /dev/null
+++ b/apps/ktorrent/hi48-mime-torrent.png
Binary files differ
diff --git a/apps/ktorrent/hi64-action-ktinfowidget.png b/apps/ktorrent/hi64-action-ktinfowidget.png
new file mode 100644
index 0000000..1d49e5c
--- /dev/null
+++ b/apps/ktorrent/hi64-action-ktinfowidget.png
Binary files differ
diff --git a/apps/ktorrent/hi64-action-ktqueuemanager.png b/apps/ktorrent/hi64-action-ktqueuemanager.png
new file mode 100644
index 0000000..d829460
--- /dev/null
+++ b/apps/ktorrent/hi64-action-ktqueuemanager.png
Binary files differ
diff --git a/apps/ktorrent/hi64-action-ktupnp.png b/apps/ktorrent/hi64-action-ktupnp.png
new file mode 100644
index 0000000..1adb895
--- /dev/null
+++ b/apps/ktorrent/hi64-action-ktupnp.png
Binary files differ
diff --git a/apps/ktorrent/hi64-app-ktorrent.png b/apps/ktorrent/hi64-app-ktorrent.png
new file mode 100644
index 0000000..9d04f33
--- /dev/null
+++ b/apps/ktorrent/hi64-app-ktorrent.png
Binary files differ
diff --git a/apps/ktorrent/hi64-filesys-ktprefdownloads.png b/apps/ktorrent/hi64-filesys-ktprefdownloads.png
new file mode 100644
index 0000000..efd92f5
--- /dev/null
+++ b/apps/ktorrent/hi64-filesys-ktprefdownloads.png
Binary files differ
diff --git a/apps/ktorrent/hi64-mime-torrent.png b/apps/ktorrent/hi64-mime-torrent.png
new file mode 100644
index 0000000..fb1187e
--- /dev/null
+++ b/apps/ktorrent/hi64-mime-torrent.png
Binary files differ
diff --git a/apps/ktorrent/hisc-app-ktorrent.svgz b/apps/ktorrent/hisc-app-ktorrent.svgz
new file mode 100644
index 0000000..3d068d8
--- /dev/null
+++ b/apps/ktorrent/hisc-app-ktorrent.svgz
Binary files differ
diff --git a/apps/ktorrent/hisc-mime-torrent.svgz b/apps/ktorrent/hisc-mime-torrent.svgz
new file mode 100644
index 0000000..beb7c28
--- /dev/null
+++ b/apps/ktorrent/hisc-mime-torrent.svgz
Binary files differ
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&amp;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>&amp;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 &amp;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>&amp;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>&amp;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>&amp;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>&amp;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&amp;K</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>btnCancel</cstring>
+ </property>
+ <property name="text">
+ <string>C&amp;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&amp;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&amp;ove up</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>btnMoveDown</cstring>
+ </property>
+ <property name="text">
+ <string>Move dow&amp;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 &amp;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>&amp;QM Controlled</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>btnDequeue</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;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>&amp;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>&amp;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>&amp;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&amp;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&amp;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&amp;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>&amp;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&amp;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&amp;)</signal>
+ <receiver>TorrentCreatorDlgBase</receiver>
+ <slot>m_node_textChanged(const QString&amp;)</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&amp;)</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