1/* This file is part of the KDE project
2
3 Copyright (C) 2002 by Patrick Charbonnier <pch@freeshell.org>
4 Based On Caitoo v.0.7.3 (c) 1998 - 2000, Matej Koss
5 Copyright (C) 2002 Carsten Pfeiffer <pfeiffer@kde.org>
6 Copyright (C) 2006 - 2008 Urs Wolfer <uwolfer @ kde.org>
7 Copyright (C) 2006 Dario Massarin <nekkar@libero.it>
8 Copyright (C) 2008 - 2011 Lukas Appelhans <l.appelhans@gmx.de>
9 Copyright (C) 2009 - 2010 Matthias Fuchs <mat69@gmx.net>
10
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
15*/
16
17#include "mainwindow.h"
18
19#include "core/kget.h"
20#include "core/transferhandler.h"
21#include "core/transfergrouphandler.h"
22#include "core/transfertreemodel.h"
23#include "core/transfertreeselectionmodel.h"
24#include "settings.h"
25#include "conf/autopastemodel.h"
26#include "conf/preferencesdialog.h"
27#include "ui/viewscontainer.h"
28#include "ui/tray.h"
29#include "ui/droptarget.h"
30#include "ui/newtransferdialog.h"
31#include "ui/history/transferhistory.h"
32#include "ui/groupsettingsdialog.h"
33#include "ui/transfersettingsdialog.h"
34#include "ui/linkview/kget_linkview.h"
35#include "ui/metalinkcreator/metalinkcreator.h"
36#include "extensions/webinterface/httpserver.h"
37#ifdef DO_KGET_TEST
38 #include "tests/testkget.h"
39#endif
40
41#include <kapplication.h>
42#include <kstandarddirs.h>
43#include <KInputDialog>
44#include <kmessagebox.h>
45#include <knotifyconfigwidget.h>
46#include <kfiledialog.h>
47#include <ktoolinvocation.h>
48#include <kmenubar.h>
49#include <kiconloader.h>
50#include <kstandardaction.h>
51#include <klocale.h>
52#include <kicon.h>
53#include <kactionmenu.h>
54#include <KSelectAction>
55#include <krun.h>
56#include <kicondialog.h>
57#include "core/verifier.h"
58#include <QClipboard>
59#include <QTimer>
60#include <QtTest/QtTest>
61
62MainWindow::MainWindow(bool showMainwindow, bool startWithoutAnimation, bool doTesting, QWidget *parent)
63 : KXmlGuiWindow( parent ),
64 m_drop(0),
65 m_dock(0),
66 clipboardTimer(0),
67 m_startWithoutAnimation(startWithoutAnimation),
68 m_doTesting(doTesting),
69 m_webinterface(0)
70{
71 // do not quit the app when it has been minimized to system tray and a new transfer dialog
72 // gets opened and closed again.
73 qApp->setQuitOnLastWindowClosed(false);
74 setAttribute(Qt::WA_DeleteOnClose, false);
75
76 // create the model
77 m_kget = KGet::self( this );
78
79 m_viewsContainer = new ViewsContainer(this);
80
81 // create actions
82 setupActions();
83
84 setupGUI(ToolBar | Keys | Save | Create);
85
86 setCentralWidget(m_viewsContainer);
87
88 // restore position, size and visibility
89 move( Settings::mainPosition() );
90 setPlainCaption(i18n("KGet"));
91
92 init();
93
94 if ( Settings::showMain() && showMainwindow)
95 show();
96 else
97 hide();
98}
99
100MainWindow::~MainWindow()
101{
102 //Save the user's transfers
103 KGet::save();
104
105 slotSaveMyself();
106 // reset konqueror integration (necessary if user enabled / disabled temporarily integration from tray)
107 slotKonquerorIntegration( Settings::konquerorIntegration() );
108 // the following call saves options set in above dtors
109 Settings::self()->writeConfig();
110
111 delete m_drop;
112 delete m_kget;
113}
114
115QSize MainWindow::sizeHint() const
116{
117 return QSize(738, 380);
118}
119
120int MainWindow::transfersPercent()
121{
122 int percent = 0;
123 int activeTransfers = 0;
124 foreach (const TransferHandler *handler, KGet::allTransfers()) {
125 if (handler->status() == Job::Running) {
126 activeTransfers ++;
127 percent += handler->percent();
128 }
129 }
130
131 if (activeTransfers > 0) {
132 return percent/activeTransfers;
133 }
134 else {
135 return -1;
136 }
137}
138
139void MainWindow::setupActions()
140{
141 KAction *newDownloadAction = actionCollection()->addAction("new_download");
142 newDownloadAction->setText(i18n("&New Download..."));
143 newDownloadAction->setIcon(KIcon("document-new"));
144 newDownloadAction->setShortcuts(KShortcut("Ctrl+N"));
145 newDownloadAction->setHelpText(i18n("Opens a dialog to add a transfer to the list"));
146 connect(newDownloadAction, SIGNAL(triggered()), SLOT(slotNewTransfer()));
147
148 KAction *openAction = actionCollection()->addAction("import_transfers");
149 openAction->setText(i18n("&Import Transfers..."));
150 openAction->setIcon(KIcon("document-open"));
151 openAction->setShortcuts(KShortcut("Ctrl+I"));
152 openAction->setHelpText(i18n("Imports a list of transfers"));
153 connect(openAction, SIGNAL(triggered()), SLOT(slotImportTransfers()));
154
155 KAction *exportAction = actionCollection()->addAction("export_transfers");
156 exportAction->setText(i18n("&Export Transfers List..."));
157 exportAction->setIcon(KIcon("document-export"));
158 exportAction->setShortcuts(KShortcut("Ctrl+E"));
159 exportAction->setHelpText(i18n("Exports the current transfers into a file"));
160 connect(exportAction, SIGNAL(triggered()), SLOT(slotExportTransfers()));
161
162 KAction *createMetalinkAction = actionCollection()->addAction("create_metalink");
163 createMetalinkAction->setText(i18n("&Create a Metalink..."));
164 createMetalinkAction->setIcon(KIcon("journal-new"));
165 createMetalinkAction->setHelpText(i18n("Creates or modifies a metalink and saves it on disk"));
166 connect(createMetalinkAction, SIGNAL(triggered()), SLOT(slotCreateMetalink()));
167
168 KAction *priorityTop = actionCollection()->addAction("priority_top");
169 priorityTop->setText(i18n("Top Priority"));
170 priorityTop->setIcon(KIcon("arrow-up-double"));
171 priorityTop->setShortcuts(KShortcut("Ctrl+PgUp"));
172 priorityTop->setHelpText(i18n("Download selected transfer first"));
173 connect(priorityTop, SIGNAL(triggered()), this, SLOT(slotPriorityTop()));
174
175 KAction *priorityBottom = actionCollection()->addAction("priority_bottom");
176 priorityBottom->setText(i18n("Least Priority"));
177 priorityBottom->setIcon(KIcon("arrow-down-double"));
178 priorityBottom->setShortcuts(KShortcut("Ctrl+PgDown"));
179 priorityBottom->setHelpText(i18n("Download selected transfer last"));
180 connect(priorityBottom, SIGNAL(triggered()), this, SLOT(slotPriorityBottom()));
181
182 KAction *priorityUp = actionCollection()->addAction("priority_up");
183 priorityUp->setText(i18n("Increase Priority"));
184 priorityUp->setIcon(KIcon("arrow-up"));
185 priorityUp->setShortcuts(KShortcut("Ctrl+Up"));
186 priorityUp->setHelpText(i18n("Increase priority for selected transfer"));
187 connect(priorityUp, SIGNAL(triggered()), this, SLOT(slotPriorityUp()));
188
189 KAction *priorityDown = actionCollection()->addAction("priority_down");
190 priorityDown->setText(i18n("Decrease Priority"));
191 priorityDown->setIcon(KIcon("arrow-down"));
192 priorityDown->setShortcuts(KShortcut("Ctrl+Down"));
193 priorityDown->setHelpText(i18n("Decrease priority for selected transfer"));
194 connect(priorityDown, SIGNAL(triggered()), this, SLOT(slotPriorityDown()));
195
196 //FIXME: Not needed maybe because the normal delete already deletes groups?
197 KAction *deleteGroupAction = actionCollection()->addAction("delete_groups");
198 deleteGroupAction->setText(i18n("Delete Group"));
199 deleteGroupAction->setIcon(KIcon("edit-delete"));
200 deleteGroupAction->setHelpText(i18n("Delete selected group"));
201 connect(deleteGroupAction, SIGNAL(triggered()), SLOT(slotDeleteGroup()));
202
203 KAction *renameGroupAction = actionCollection()->addAction("rename_groups");
204 renameGroupAction->setText(i18n("Rename Group..."));
205 renameGroupAction->setIcon(KIcon("edit-rename"));
206 connect(renameGroupAction, SIGNAL(triggered()), SLOT(slotRenameGroup()));
207
208 KAction *setIconGroupAction = actionCollection()->addAction("seticon_groups");
209 setIconGroupAction->setText(i18n("Set Icon..."));
210 setIconGroupAction->setIcon(KIcon("preferences-desktop-icons"));
211 setIconGroupAction->setHelpText(i18n("Select a custom icon for the selected group"));
212 connect(setIconGroupAction, SIGNAL(triggered()), SLOT(slotSetIconGroup()));
213
214 m_autoPasteAction = new KToggleAction(KIcon("edit-paste"),
215 i18n("Auto-Paste Mode"), actionCollection());
216 actionCollection()->addAction("auto_paste", m_autoPasteAction);
217 m_autoPasteAction->setChecked(Settings::autoPaste());
218 m_autoPasteAction->setWhatsThis(i18n("<b>Auto paste</b> button toggles the auto-paste mode "
219 "on and off.\nWhen set, KGet will periodically scan "
220 "the clipboard for URLs and paste them automatically."));
221 connect(m_autoPasteAction, SIGNAL(triggered()), SLOT(slotToggleAutoPaste()));
222
223 m_konquerorIntegration = new KToggleAction(KIcon("konqueror"),
224 i18n("Use KGet as Konqueror Download Manager"), actionCollection());
225 actionCollection()->addAction("konqueror_integration", m_konquerorIntegration);
226 connect(m_konquerorIntegration, SIGNAL(triggered(bool)), SLOT(slotTrayKonquerorIntegration(bool)));
227 m_konquerorIntegration->setChecked(Settings::konquerorIntegration());
228
229 // local - Destroys all sub-windows and exits
230 KStandardAction::quit(this, SLOT(slotQuit()), actionCollection());
231 // local - Standard configure actions
232 KStandardAction::preferences(this, SLOT(slotPreferences()), actionCollection());
233
234 KStandardAction::configureNotifications(this, SLOT(slotConfigureNotifications()), actionCollection());
235 m_menubarAction = KStandardAction::showMenubar(this, SLOT(slotShowMenubar()), actionCollection());
236 m_menubarAction->setChecked(!menuBar()->isHidden());
237
238 // Transfer related actions
239 actionCollection()->addAction(KStandardAction::SelectAll, "select_all", m_viewsContainer, SLOT(selectAll()));
240
241 KAction *deleteSelectedAction = actionCollection()->addAction("delete_selected_download");
242 deleteSelectedAction->setText(i18nc("delete selected transfer item", "Remove Selected"));
243 deleteSelectedAction->setIcon(KIcon("edit-delete"));
244 deleteSelectedAction->setShortcuts(KShortcut("Del"));
245 deleteSelectedAction->setHelpText(i18n("Removes selected transfer and deletes files from disk if it's not finished"));
246 connect(deleteSelectedAction, SIGNAL(triggered()), SLOT(slotDeleteSelected()));
247
248 KAction *deleteAllFinishedAction = actionCollection()->addAction("delete_all_finished");
249 deleteAllFinishedAction->setText(i18nc("delete all finished transfers", "Remove All Finished"));
250 deleteAllFinishedAction->setIcon(KIcon("edit-clear-list"));
251 deleteAllFinishedAction->setHelpText(i18n("Removes all finished transfers and leaves all files on disk"));
252 connect(deleteAllFinishedAction, SIGNAL(triggered()), SLOT(slotDeleteFinished()));
253
254 KAction *deleteSelectedIncludingFilesAction = actionCollection()->addAction("delete_selected_download_including_files");
255 deleteSelectedIncludingFilesAction->setText(i18nc("delete selected transfer item and files", "Remove Selected and Delete Files"));
256 deleteSelectedIncludingFilesAction->setIcon(KIcon("edit-delete"));
257 deleteSelectedIncludingFilesAction->setHelpText(i18n("Removes selected transfer and deletes files from disk in any case"));
258 connect(deleteSelectedIncludingFilesAction, SIGNAL(triggered()), SLOT(slotDeleteSelectedIncludingFiles()));
259
260 KAction *redownloadSelectedAction = actionCollection()->addAction("redownload_selected_download");
261 redownloadSelectedAction->setText(i18nc("redownload selected transfer item", "Redownload Selected"));
262 redownloadSelectedAction->setIcon(KIcon("view-refresh"));
263 connect(redownloadSelectedAction, SIGNAL(triggered()), SLOT(slotRedownloadSelected()));
264
265 KAction *startAllAction = actionCollection()->addAction("start_all_download");
266 startAllAction->setText(i18n("Start All"));
267 startAllAction->setIcon(KIcon("media-seek-forward"));
268 startAllAction->setShortcuts(KShortcut("Ctrl+R"));
269 startAllAction->setHelpText(i18n("Starts / resumes all transfers"));
270 connect(startAllAction, SIGNAL(triggered()), SLOT(slotStartAllDownload()));
271
272 KAction *startSelectedAction = actionCollection()->addAction("start_selected_download");
273 startSelectedAction->setText(i18n("Start Selected"));
274 startSelectedAction->setIcon(KIcon("media-playback-start"));
275 startSelectedAction->setHelpText(i18n("Starts / resumes selected transfer"));
276 connect(startSelectedAction, SIGNAL(triggered()), SLOT(slotStartSelectedDownload()));
277
278 KAction *stopAllAction = actionCollection()->addAction("stop_all_download");
279 stopAllAction->setText(i18n("Pause All"));
280 stopAllAction->setIcon(KIcon("media-playback-pause"));
281 stopAllAction->setShortcuts(KShortcut("Ctrl+P"));
282 stopAllAction->setHelpText(i18n("Pauses all transfers"));
283 connect(stopAllAction, SIGNAL(triggered()), SLOT(slotStopAllDownload()));
284
285 KAction *stopSelectedAction = actionCollection()->addAction("stop_selected_download");
286 stopSelectedAction->setText(i18n("Stop Selected"));
287 stopSelectedAction->setIcon(KIcon("media-playback-pause"));
288 stopSelectedAction->setHelpText(i18n("Pauses selected transfer"));
289 connect(stopSelectedAction, SIGNAL(triggered()), SLOT(slotStopSelectedDownload()));
290
291 KActionMenu *startActionMenu = new KActionMenu(KIcon("media-playback-start"), i18n("Start"),
292 actionCollection());
293 actionCollection()->addAction("start_menu", startActionMenu);
294 startActionMenu->setDelayed(true);
295 startActionMenu->addAction(startSelectedAction);
296 startActionMenu->addAction(startAllAction);
297 connect(startActionMenu, SIGNAL(triggered()), SLOT(slotStartDownload()));
298
299 KActionMenu *stopActionMenu = new KActionMenu(KIcon("media-playback-pause"), i18n("Pause"),
300 actionCollection());
301 actionCollection()->addAction("stop_menu", stopActionMenu);
302 stopActionMenu->setDelayed(true);
303 stopActionMenu->addAction(stopSelectedAction);
304 stopActionMenu->addAction(stopAllAction);
305 connect(stopActionMenu, SIGNAL(triggered()), SLOT(slotStopDownload()));
306
307 KAction *openDestAction = actionCollection()->addAction("transfer_open_dest");
308 openDestAction->setText(i18n("Open Destination"));
309 openDestAction->setIcon(KIcon("document-open"));
310 connect(openDestAction, SIGNAL(triggered()), SLOT(slotTransfersOpenDest()));
311
312 KAction *openFileAction = actionCollection()->addAction("transfer_open_file");
313 openFileAction->setText(i18n("Open File"));
314 openFileAction->setIcon(KIcon("document-open"));
315 connect(openFileAction, SIGNAL(triggered()), SLOT(slotTransfersOpenFile()));
316
317 KAction *showDetailsAction = new KToggleAction(KIcon("document-properties"), i18n("Show Details"), actionCollection());
318 actionCollection()->addAction("transfer_show_details", showDetailsAction);
319 connect(showDetailsAction, SIGNAL(triggered()), SLOT(slotTransfersShowDetails()));
320
321 KAction *copyUrlAction = actionCollection()->addAction("transfer_copy_source_url");
322 copyUrlAction->setText(i18n("Copy URL to Clipboard"));
323 copyUrlAction->setIcon(KIcon("edit-copy"));
324 connect(copyUrlAction, SIGNAL(triggered()), SLOT(slotTransfersCopySourceUrl()));
325
326 KAction *transferHistoryAction = actionCollection()->addAction("transfer_history");
327 transferHistoryAction->setText(i18n("&Transfer History"));
328 transferHistoryAction->setIcon(KIcon("view-history"));
329 transferHistoryAction->setShortcuts(KShortcut("Ctrl+H"));
330 connect(transferHistoryAction, SIGNAL(triggered()), SLOT(slotTransferHistory()));
331
332 KAction *transferGroupSettingsAction = actionCollection()->addAction("transfer_group_settings");
333 transferGroupSettingsAction->setText(i18n("&Group Settings"));
334 transferGroupSettingsAction->setIcon(KIcon("preferences-system"));
335 transferGroupSettingsAction->setShortcuts(KShortcut("Ctrl+G"));
336 connect(transferGroupSettingsAction, SIGNAL(triggered()), SLOT(slotTransferGroupSettings()));
337
338 KAction *transferSettingsAction = actionCollection()->addAction("transfer_settings");
339 transferSettingsAction->setText(i18n("&Transfer Settings"));
340 transferSettingsAction->setIcon(KIcon("preferences-system"));
341 transferSettingsAction->setShortcuts(KShortcut("Ctrl+T"));
342 connect(transferSettingsAction, SIGNAL(triggered()), SLOT(slotTransferSettings()));
343
344 KAction *listLinksAction = actionCollection()->addAction("import_links");
345 listLinksAction->setText(i18n("Import &Links..."));
346 listLinksAction->setIcon(KIcon("view-list-text"));
347 listLinksAction->setShortcuts(KShortcut("Ctrl+L"));
348 connect(listLinksAction, SIGNAL(triggered()), SLOT(slotShowListLinks()));
349
350 //create the download finished actions which can be displayed in the toolbar
351 KSelectAction *downloadFinishedActions = new KSelectAction(i18n("After downloads finished action"), this);//TODO maybe with name??
352 actionCollection()->addAction("download_finished_actions", downloadFinishedActions);
353 downloadFinishedActions->setHelpText(i18n("Choose an action that is executed after all downloads have been finished."));
354
355 KAction *noAction = downloadFinishedActions->addAction(i18n("No Action"));
356 connect(noAction, SIGNAL(triggered()), SLOT(slotDownloadFinishedActions()));
357 downloadFinishedActions->addAction(noAction);
358
359 KAction *quitAction = downloadFinishedActions->addAction(i18n("Quit KGet"));
360 quitAction->setData(KGet::Quit);
361 connect(quitAction, SIGNAL(triggered()), SLOT(slotDownloadFinishedActions()));
362 downloadFinishedActions->addAction(quitAction);
363
364#ifdef HAVE_KWORKSPACE
365 KAction *shutdownAction = downloadFinishedActions->addAction(i18n("Turn Off Computer"));
366 shutdownAction->setData(KGet::Shutdown);
367 connect(shutdownAction, SIGNAL(triggered()), SLOT(slotDownloadFinishedActions()));
368 downloadFinishedActions->addAction(shutdownAction);
369
370 KAction *hibernateAction = downloadFinishedActions->addAction(i18n("Hibernate Computer"));
371 hibernateAction->setData(KGet::Hibernate);
372 connect(hibernateAction, SIGNAL(triggered()), SLOT(slotDownloadFinishedActions()));
373 downloadFinishedActions->addAction(hibernateAction);
374
375 KAction *suspendAction = downloadFinishedActions->addAction(i18n("Suspend Computer"));
376 suspendAction->setData(KGet::Suspend);
377 connect(suspendAction, SIGNAL(triggered()), SLOT(slotDownloadFinishedActions()));
378 downloadFinishedActions->addAction(suspendAction);
379#endif
380
381 if (Settings::afterFinishActionEnabled()) {
382 downloadFinishedActions->setCurrentItem(Settings::afterFinishAction() + 1);
383 } else {
384 downloadFinishedActions->setCurrentItem(0);
385 }
386}
387
388void MainWindow::slotDownloadFinishedActions()
389{
390 KAction *action = static_cast<KAction*>(QObject::sender());
391 bool ok;
392 const int type = action->data().toInt(&ok);
393 if (ok) {
394 Settings::self()->setAfterFinishAction(type);
395 }
396
397 //only after finish actions have a number assigned
398 Settings::self()->setAfterFinishActionEnabled(ok);
399 Settings::self()->writeConfig();
400 slotNewConfig();
401}
402
403void MainWindow::init()
404{
405 //Here we import the user's transfers.
406 KGet::load( KStandardDirs::locateLocal("appdata", "transfers.kgt") );
407
408 if(Settings::enableSystemTray()) {
409 m_dock = new Tray(this);
410 }
411
412 // enable dropping
413 setAcceptDrops(true);
414
415 // enable hide toolbar
416 setStandardToolBarMenuEnabled(true);
417
418 // session management stuff
419 connect(kapp, SIGNAL(saveYourself()), SLOT(slotSaveMyself()));
420
421 // set auto-resume in kioslaverc (is there a cleaner way?)
422 KConfig cfg("kioslaverc", KConfig::NoGlobals);
423 cfg.group(QString()).writeEntry("AutoResume", true);
424 cfg.sync();
425
426 // DropTarget
427 m_drop = new DropTarget(this);
428
429 if (Settings::firstRun()) {
430 if (KMessageBox::questionYesNoCancel(this ,i18n("This is the first time you have run KGet.\n"
431 "Would you like to enable KGet as the download manager for Konqueror?"),
432 i18n("Konqueror Integration"), KGuiItem(i18n("Enable")),
433 KGuiItem(i18n("Do Not Enable")))
434 == KMessageBox::Yes) {
435 Settings::setKonquerorIntegration(true);
436 m_konquerorIntegration->setChecked(Settings::konquerorIntegration());
437 slotKonquerorIntegration(true);
438 }
439
440 m_drop->setDropTargetVisible(false);
441
442 // reset the FirstRun config option
443 Settings::setFirstRun(false);
444 }
445
446 if (Settings::showDropTarget() && !m_startWithoutAnimation)
447 m_drop->setDropTargetVisible(true);
448
449 //auto paste stuff
450 lastClipboard = QApplication::clipboard()->text( QClipboard::Clipboard ).trimmed();
451 clipboardTimer = new QTimer(this);
452 connect(clipboardTimer, SIGNAL(timeout()), SLOT(slotCheckClipboard()));
453 if ( Settings::autoPaste() )
454 clipboardTimer->start(1000);
455
456 if (Settings::webinterfaceEnabled())
457 m_webinterface = new HttpServer(this);
458
459 if (Settings::speedLimit())
460 {
461 KGet::setGlobalDownloadLimit(Settings::globalDownloadLimit());
462 KGet::setGlobalUploadLimit(Settings::globalUploadLimit());
463 }
464 else
465 {
466 KGet::setGlobalDownloadLimit(0);
467 KGet::setGlobalUploadLimit(0);
468 }
469
470 connect(KGet::model(), SIGNAL(transfersAddedEvent(QList<TransferHandler*>)), this, SLOT(slotUpdateTitlePercent()));
471 connect(KGet::model(), SIGNAL(transfersRemovedEvent(QList<TransferHandler*>)), this, SLOT(slotUpdateTitlePercent()));
472 connect(KGet::model(), SIGNAL(transfersChangedEvent(QMap<TransferHandler*,Transfer::ChangesFlags>)),
473 SLOT(slotTransfersChanged(QMap<TransferHandler*,Transfer::ChangesFlags>)));
474 connect(KGet::model(), SIGNAL(groupsChangedEvent(QMap<TransferGroupHandler*,TransferGroup::ChangesFlags>)),
475 SLOT(slotGroupsChanged(QMap<TransferGroupHandler*,TransferGroup::ChangesFlags>)));
476
477#ifdef DO_KGET_TEST
478 if (m_doTesting)
479 {
480 // Unit testing
481 TestKGet unitTest;
482 QTest::qExec(&unitTest);
483 }
484#endif
485}
486
487void MainWindow::slotToggleDropTarget()
488{
489 m_drop->setDropTargetVisible(!m_drop->isVisible());
490}
491
492void MainWindow::slotNewTransfer()
493{
494 NewTransferDialogHandler::showNewTransferDialog(KUrl());
495}
496
497void MainWindow::slotImportTransfers()
498{
499 QString filename = KFileDialog::getOpenFileName(KUrl(),
500 "*.kgt *.metalink *.meta4 *.torrent|" + i18n("All Openable Files") +
501 " (*.kgt *.metalink *.meta4 *.torrent)", this, i18n("Open File"));
502
503 if(filename.endsWith(QLatin1String(".kgt")))
504 {
505 KGet::load(filename);
506 return;
507 }
508
509 if(!filename.isEmpty())
510 KGet::addTransfer( KUrl( filename ) );
511}
512
513void MainWindow::slotUpdateTitlePercent()
514{
515 int percent = transfersPercent();
516 if (percent != -1) {
517 setPlainCaption(i18nc("window title including overall download progress in percent", "KGet - %1%", percent));
518 } else {
519 setPlainCaption(i18n("KGet"));
520 }
521}
522
523void MainWindow::slotTransfersChanged(QMap<TransferHandler*, Transfer::ChangesFlags> transfers)
524{
525 QMapIterator<TransferHandler*, Transfer::ChangesFlags> it(transfers);
526
527 //QList<TransferHandler *> finishedTransfers;
528 bool update = false;
529
530 while (it.hasNext()) {
531 it.next();
532
533 //TransferHandler * transfer = it.key();
534 Transfer::ChangesFlags transferFlags = it.value();
535
536 if (transferFlags & Transfer::Tc_Percent || transferFlags & Transfer::Tc_Status) {
537 update = true;
538 break;
539 }
540
541// kDebug(5001) << it.key() << ": " << it.value() << endl;
542 }
543
544 if (update)
545 slotUpdateTitlePercent();
546}
547
548void MainWindow::slotGroupsChanged(QMap<TransferGroupHandler*, TransferGroup::ChangesFlags> groups)
549{
550 bool update = false;
551 foreach (const TransferGroup::ChangesFlags &groupFlags, groups)
552 {
553 if (groupFlags & TransferGroup::Gc_Percent)
554 {
555 update = true;
556 break;
557 }
558 }
559 if (update)
560 slotUpdateTitlePercent();
561}
562
563void MainWindow::slotQuit()
564{
565 if (KGet::schedulerRunning()) {
566 if (KMessageBox::warningYesNo(this,
567 i18n("Some transfers are still running.\n"
568 "Are you sure you want to close KGet?"),
569 i18n("Confirm Quit"),
570 KStandardGuiItem::quit(), KStandardGuiItem::cancel(),
571 "ExitWithActiveTransfers") != KMessageBox::Yes)
572 return;
573 }
574
575 Settings::self()->writeConfig();
576 qApp->quit();
577}
578
579void MainWindow::slotPreferences()
580{
581 //never reuse the preference dialog, to make sure its settings are always reloaded
582 PreferencesDialog * dialog = new PreferencesDialog( this, Settings::self() );
583 dialog->setAttribute(Qt::WA_DeleteOnClose);
584
585 // keep us informed when the user changes settings
586 connect( dialog, SIGNAL(settingsChanged(QString)),
587 this, SLOT(slotNewConfig()) );
588
589 dialog->show();
590}
591
592void MainWindow::slotExportTransfers()
593{
594 const QString filename = KFileDialog::getSaveFileName
595 (KUrl(),
596 "*.kgt|" + i18n("KGet Transfer List") + " (*.kgt)\n*.txt|" + i18n("Text File") + " (*.txt)",
597 this,
598 i18n("Export Transfers")
599 );
600
601 if (!filename.isEmpty()) {
602 const bool plain = !filename.endsWith("kgt");
603 KGet::save(filename, plain);
604 }
605}
606
607void MainWindow::slotCreateMetalink()
608{
609 MetalinkCreator *dialog = new MetalinkCreator(this);
610 dialog->setAttribute(Qt::WA_DeleteOnClose);
611 dialog->show();
612}
613
614void MainWindow::slotDeleteGroup()
615{
616 QList<TransferGroupHandler*> groups = KGet::selectedTransferGroups();
617 if (groups.count() != KGet::allTransferGroups().count()) {
618 KGet::delGroups(groups);
619 }
620}
621
622void MainWindow::slotRenameGroup()
623{
624 bool ok = true;
625 QString groupName;
626
627 foreach(TransferGroupHandler * it, KGet::selectedTransferGroups())
628 {
629 groupName = KInputDialog::getText(i18n("Enter Group Name"),
630 i18n("Group name:"), it->name(), &ok, this);
631 if(ok)
632 it->setName(groupName);
633 }
634}
635
636void MainWindow::slotSetIconGroup()
637{
638 KIconDialog dialog(this);
639 QString iconName = dialog.getIcon();
640 TransferTreeSelectionModel *selModel = KGet::selectionModel();
641
642 QModelIndexList indexList = selModel->selectedRows();
643
644 if (!iconName.isEmpty())
645 {
646 foreach (TransferGroupHandler *group, KGet::selectedTransferGroups())
647 {
648 group->setIconName(iconName);
649 }
650 }
651 //emit dataChanged(indexList.first(),indexList.last());
652}
653
654void MainWindow::slotStartDownload()
655{
656 if (KGet::selectedTransfers().size() == 0 && KGet::selectedTransferGroups().size() == 0) {
657 slotStartAllDownload();
658 } else {
659 slotStartSelectedDownload();
660 }
661}
662
663void MainWindow::slotStartAllDownload()
664{
665 KGet::setSchedulerRunning(true);
666}
667
668void MainWindow::slotStartSelectedDownload()
669{
670 KGet::setSuspendScheduler(true);
671 foreach (TransferHandler *transfer, KGet::selectedTransfers()) {
672 transfer->start();
673 }
674 foreach (TransferGroupHandler *group, KGet::selectedTransferGroups()) {
675 group->start();
676 }
677 KGet::setSuspendScheduler(false);
678}
679
680void MainWindow::slotStopDownload()
681{
682 if (KGet::selectedTransfers().size() == 0 && KGet::selectedTransferGroups().size() == 0) {
683 slotStopAllDownload();
684 } else {
685 slotStopSelectedDownload();
686 }
687}
688
689void MainWindow::slotStopAllDownload()
690{
691 KGet::setSchedulerRunning(false);
692
693 // This line ensures that each transfer is stopped. In the handler class
694 // the policy of the transfer will be correctly setted to None
695 foreach (TransferHandler * it, KGet::allTransfers())
696 it->stop();
697}
698
699void MainWindow::slotStopSelectedDownload()
700{
701 KGet::setSuspendScheduler(true);
702 foreach (TransferHandler *transfer, KGet::selectedTransfers()) {
703 transfer->stop();
704 }
705 foreach (TransferGroupHandler *group, KGet::selectedTransferGroups()) {
706 group->stop();
707 }
708 KGet::setSuspendScheduler(false);
709}
710
711void MainWindow::slotDeleteSelected()
712{
713 foreach (TransferHandler * it, KGet::selectedTransfers())
714 {
715 if (it->status() != Job::Finished && it->status() != Job::FinishedKeepAlive) {
716 if (KMessageBox::warningYesNo(this,
717 i18np("Are you sure you want to delete the selected transfer?",
718 "Are you sure you want to delete the selected transfers?", KGet::selectedTransfers().count()),
719 i18n("Confirm transfer delete"),
720 KStandardGuiItem::remove(), KStandardGuiItem::cancel()) == KMessageBox::No)
721 {
722 return;
723 }
724 break;
725 }
726 }
727
728 const QList<TransferHandler*> selectedTransfers = KGet::selectedTransfers();
729 if (!selectedTransfers.isEmpty()) {
730 foreach (TransferHandler *it, selectedTransfers) {
731 m_viewsContainer->closeTransferDetails(it);//TODO make it take QList?
732 }
733 KGet::delTransfers(KGet::selectedTransfers());
734 } else {
735 //no transfers selected, delete groups if any are selected
736 slotDeleteGroup();
737 }
738}
739
740void MainWindow::slotDeleteSelectedIncludingFiles()
741{
742 const QList<TransferHandler*> selectedTransfers = KGet::selectedTransfers();
743
744 if (!selectedTransfers.isEmpty()) {
745 if (KMessageBox::warningYesNo(this,
746 i18np("Are you sure you want to delete the selected transfer including files?",
747 "Are you sure you want to delete the selected transfers including files?", selectedTransfers.count()),
748 i18n("Confirm transfer delete"),
749 KStandardGuiItem::remove(), KStandardGuiItem::cancel()) == KMessageBox::No) {
750 return;
751 }
752 foreach (TransferHandler *it, selectedTransfers) {
753 m_viewsContainer->closeTransferDetails(it);//TODO make it take QList?
754 }
755 KGet::delTransfers(KGet::selectedTransfers(), KGet::DeleteFiles);
756 } else {
757 //no transfers selected, delete groups if any are selected
758 slotDeleteGroup();
759 }
760}
761
762void MainWindow::slotRedownloadSelected()
763{
764 foreach(TransferHandler * it, KGet::selectedTransfers())
765 {
766 KGet::redownloadTransfer(it);
767 }
768}
769
770void MainWindow::slotPriorityTop()
771{
772 QList<TransferHandler*> selected = KGet::selectedTransfers();
773 TransferHandler *after = 0;
774 TransferGroupHandler *group = 0;
775 foreach (TransferHandler *transfer, selected) {
776 if (!transfer) {
777 continue;
778 }
779
780 //previous transfer was not of the same group, so after has to be reset as the group
781 if (!group || (group != transfer->group())) {
782 after = 0;
783 group = transfer->group();
784 }
785 KGet::model()->moveTransfer(transfer, group, after);
786 after = transfer;
787 }
788}
789
790void MainWindow::slotPriorityBottom()
791{
792 QList<TransferHandler*> selected = KGet::selectedTransfers();
793 QList<TransferHandler*> groupTransfers;
794 TransferHandler *after = 0;
795 TransferGroupHandler *group = 0;
796 foreach (TransferHandler *transfer, selected) {
797 if (!transfer) {
798 continue;
799 }
800
801 //previous transfer was not of the same group, so after has to be reset as the group
802 if (!group || (group != transfer->group())) {
803 group = transfer->group();
804 groupTransfers = group->transfers();
805 if (groupTransfers.isEmpty()) {
806 after = 0;
807 } else {
808 after = groupTransfers.last();
809 }
810 }
811
812 KGet::model()->moveTransfer(transfer, group, after);
813 after = transfer;
814 }
815}
816
817void MainWindow::slotPriorityUp()
818{
819 QList<TransferHandler*> selected = KGet::selectedTransfers();
820 QList<TransferHandler*> groupTransfers;
821 TransferHandler *after = 0;
822 int newIndex = -1;
823 TransferGroupHandler *group = 0;
824 foreach (TransferHandler *transfer, selected) {
825 if (!transfer) {
826 continue;
827 }
828
829 //previous transfer was not of the same group, so group has to be reset
830 if (!group || (group != transfer->group())) {
831 group = transfer->group();
832 groupTransfers = group->transfers();
833 }
834
835 after = 0;
836 if (!groupTransfers.isEmpty()) {
837 int index = groupTransfers.indexOf(transfer);
838
839 //do not move higher than the first place
840 if (index > 0) {
841 //if only Transfers at the top are select do not change their order
842 if ((index - 1) != newIndex) {
843 newIndex = index - 1;
844 if (newIndex - 1 >= 0) {
845 after = groupTransfers[newIndex - 1];
846 }
847
848 //keep the list with the actual movements synchronised
849 groupTransfers.move(index, newIndex);
850
851 KGet::model()->moveTransfer(transfer, group, after);
852 } else {
853 newIndex = index;
854 }
855 } else {
856 newIndex = 0;
857 }
858 }
859 }
860}
861
862void MainWindow::slotPriorityDown()
863{
864 QList<TransferHandler*> selected = KGet::selectedTransfers();
865 QList<TransferHandler*> groupTransfers;
866 int newIndex = -1;
867 TransferGroupHandler *group = 0;
868 for (int i = selected.count() - 1; i >= 0; --i) {
869 TransferHandler *transfer = selected[i];
870 if (!transfer) {
871 continue;
872 }
873
874 //previous transfer was not of the same group, so group has to be reset
875 if (!group || (group != transfer->group())) {
876 group = transfer->group();
877 groupTransfers = group->transfers();
878 }
879
880 if (!groupTransfers.isEmpty()) {
881 int index = groupTransfers.indexOf(transfer);
882
883 //do not move lower than the last place
884 if ((index != -1) && (index + 1 < groupTransfers.count())) {
885 //if only Transfers at the top are select do not change their order
886 if ((index + 1) != newIndex) {
887 newIndex = index + 1;
888 TransferHandler *after = groupTransfers[newIndex];
889
890
891 //keep the list with the actual movements synchronised
892 groupTransfers.move(index, newIndex);
893
894 KGet::model()->moveTransfer(transfer, group, after);
895 } else {
896 newIndex = index;
897 }
898 } else {
899 newIndex = index;
900 }
901 }
902 }
903}
904
905void MainWindow::slotTransfersOpenDest()
906{
907 QStringList openedDirs;
908 foreach(TransferHandler * it, KGet::selectedTransfers())
909 {
910 QString directory = it->dest().directory();
911 if( !openedDirs.contains( directory ) )
912 {
913 new KRun(directory, this, 0, true, false);
914 openedDirs.append( directory );
915 }
916 }
917}
918
919void MainWindow::slotTransfersOpenFile()
920{
921 foreach(TransferHandler * it, KGet::selectedTransfers())
922 {
923 new KRun(it->dest(), this, 0, true, false);
924 }
925}
926
927void MainWindow::slotTransfersShowDetails()
928{
929 foreach(TransferHandler * it, KGet::selectedTransfers())
930 {
931 m_viewsContainer->showTransferDetails(it);
932 }
933}
934
935void MainWindow::slotTransfersCopySourceUrl()
936{
937 foreach(TransferHandler * it, KGet::selectedTransfers())
938 {
939 QString sourceurl = it->source().url();
940 QClipboard *cb = QApplication::clipboard();
941 cb->setText(sourceurl, QClipboard::Selection);
942 cb->setText(sourceurl, QClipboard::Clipboard);
943 }
944}
945
946void MainWindow::slotDeleteFinished()
947{
948 foreach(TransferHandler * it, KGet::finishedTransfers()) {
949 m_viewsContainer->closeTransferDetails(it);
950 }
951 KGet::delTransfers(KGet::finishedTransfers());
952}
953
954void MainWindow::slotConfigureNotifications()
955{
956 KNotifyConfigWidget::configure(this);
957}
958
959
960void MainWindow::slotSaveMyself()
961{
962 // save last parameters ..
963 Settings::setMainPosition( pos() );
964 // .. and write config to disk
965 Settings::self()->writeConfig();
966}
967
968void MainWindow::slotNewToolbarConfig()
969{
970 createGUI();
971}
972
973void MainWindow::slotNewConfig()
974{
975 // Update here properties modified in the config dialog and not
976 // parsed often by the code. When clicking Ok or Apply of
977 // PreferencesDialog, this function is called.
978
979 if (m_drop)
980 m_drop->setDropTargetVisible(Settings::showDropTarget(), false);
981
982 if (Settings::enableSystemTray() && !m_dock) {
983 m_dock = new Tray(this);
984 } else if (!Settings::enableSystemTray() && m_dock) {
985 setVisible(true);
986 delete m_dock;
987 m_dock = 0;
988 }
989
990 slotKonquerorIntegration(Settings::konquerorIntegration());
991 m_konquerorIntegration->setChecked(Settings::konquerorIntegration());
992
993 if (clipboardTimer) {
994 if (Settings::autoPaste())
995 clipboardTimer->start(1000);
996 else
997 clipboardTimer->stop();
998 }
999 m_autoPasteAction->setChecked(Settings::autoPaste());
1000
1001 if (Settings::webinterfaceEnabled() && !m_webinterface) {
1002 m_webinterface = new HttpServer(this);
1003 } else if (m_webinterface && !Settings::webinterfaceEnabled()) {
1004 delete m_webinterface;
1005 m_webinterface = 0;
1006 } else if (m_webinterface) {
1007 m_webinterface->settingsChanged();
1008 }
1009
1010 if (Settings::speedLimit())
1011 {
1012 KGet::setGlobalDownloadLimit(Settings::globalDownloadLimit());
1013 KGet::setGlobalUploadLimit(Settings::globalUploadLimit());
1014 }
1015 else
1016 {
1017 KGet::setGlobalDownloadLimit(0);
1018 KGet::setGlobalUploadLimit(0);
1019 }
1020
1021 KGet::settingsChanged();
1022}
1023
1024void MainWindow::slotToggleAutoPaste()
1025{
1026 bool autoPaste = !Settings::autoPaste();
1027 Settings::setAutoPaste( autoPaste );
1028
1029 if (autoPaste)
1030 clipboardTimer->start(1000);
1031 else
1032 clipboardTimer->stop();
1033 m_autoPasteAction->setChecked(autoPaste);
1034}
1035
1036void MainWindow::slotCheckClipboard()
1037{
1038 const QString clipData = QApplication::clipboard()->text( QClipboard::Clipboard ).trimmed();
1039
1040 if (clipData != lastClipboard) {
1041 lastClipboard = clipData;
1042 if (lastClipboard.isEmpty())
1043 return;
1044
1045 const KUrl url = KUrl(lastClipboard);
1046 if (url.isValid() && !url.protocol().isEmpty() && url.hasPath() && url.hasHost() && !url.isLocalFile()) {
1047 bool add = false;
1048 const QString urlString = url.url();
1049
1050 //check the combined whitelist and blacklist
1051 const QList<int> types = Settings::autoPasteTypes();
1052 const QList<int> syntaxes = Settings::autoPastePatternSyntaxes();
1053 const QStringList patterns = Settings::autoPastePatterns();
1054 const Qt::CaseSensitivity cs = (Settings::autoPasteCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive);
1055 for (int i = 0; i < types.count(); ++i) {
1056 const QRegExp::PatternSyntax syntax = (syntaxes[i] == AutoPasteModel::Wildcard ? QRegExp::Wildcard : QRegExp::RegExp2);
1057 QRegExp rx(patterns[i], cs, syntax);
1058 if (rx.exactMatch(urlString)) {
1059 add = (types[i] == AutoPasteModel::Include);
1060 break;
1061 }
1062 }
1063
1064 if (add) {
1065 KGet::addTransfer(url);
1066 }
1067 }
1068 }
1069}
1070
1071void MainWindow::slotTrayKonquerorIntegration(bool enable)
1072{
1073 slotKonquerorIntegration(enable);
1074 if (!enable && Settings::konquerorIntegration())
1075 {
1076 KGet::showNotification(this, "notification",
1077 i18n("KGet has been temporarily disabled as download manager for Konqueror. "
1078 "If you want to disable it forever, go to Settings->Advanced and disable \"Use "
1079 "as download manager for Konqueror\"."),
1080 "dialog-info");
1081 /*KMessageBox::information(this,
1082 i18n("KGet has been temporarily disabled as download manager for Konqueror. "
1083 "If you want to disable it forever, go to Settings->Advanced and disable \"Use "
1084 "as download manager for Konqueror\"."),
1085 i18n("Konqueror Integration disabled"),
1086 "KonquerorIntegrationDisabled");*/
1087 }
1088}
1089
1090void MainWindow::slotKonquerorIntegration(bool konquerorIntegration)
1091{
1092 KConfig cfgKonqueror("konquerorrc", KConfig::NoGlobals);
1093 cfgKonqueror.group("HTML Settings").writeEntry("DownloadManager",
1094 QString(konquerorIntegration ? "kget" : QString()));
1095 cfgKonqueror.sync();
1096}
1097
1098void MainWindow::slotShowMenubar()
1099{
1100 if (m_menubarAction->isChecked())
1101 menuBar()->show();
1102 else
1103 menuBar()->hide();
1104}
1105
1106void MainWindow::setSystemTrayDownloading(bool running)
1107{
1108 kDebug(5001);
1109
1110 if (m_dock)
1111 m_dock->setDownloading(running);
1112}
1113
1114void MainWindow::slotTransferHistory()
1115{
1116 TransferHistory *history = new TransferHistory();
1117 history->exec();
1118}
1119
1120void MainWindow::slotTransferGroupSettings()
1121{
1122 kDebug(5001);
1123 QList<TransferGroupHandler*> list = KGet::selectedTransferGroups();
1124 foreach(TransferGroupHandler* group, list)
1125 {
1126 QPointer<GroupSettingsDialog> settings = new GroupSettingsDialog(this, group);
1127 settings->exec();
1128 delete settings;
1129 }
1130}
1131
1132void MainWindow::slotTransferSettings()
1133{
1134 kDebug(5001);
1135 QList<TransferHandler*> list = KGet::selectedTransfers();
1136 foreach(TransferHandler* transfer, list)
1137 {
1138 QPointer<TransferSettingsDialog> settings = new TransferSettingsDialog(this, transfer);
1139 settings->exec();
1140 delete settings;
1141 }
1142}
1143
1144/** slots for link list **/
1145void MainWindow::slotShowListLinks()
1146{
1147 KGetLinkView *link_view = new KGetLinkView(this);
1148 link_view->importUrl();
1149 link_view->show();
1150}
1151
1152void MainWindow::slotImportUrl(const QString &url)
1153{
1154 KGetLinkView *link_view = new KGetLinkView(this);
1155 link_view->importUrl(url);
1156 link_view->show();
1157}
1158
1159/** widget events **/
1160void MainWindow::closeEvent( QCloseEvent * e )
1161{
1162 // if the event comes from out the application (close event) we decide between close or hide
1163 // if the event comes from the application (system shutdown) we say goodbye
1164 if(e->spontaneous()) {
1165 e->ignore();
1166 if(!Settings::enableSystemTray())
1167 slotQuit();
1168 else
1169 hide();
1170 }
1171}
1172
1173void MainWindow::hideEvent(QHideEvent *)
1174{
1175 Settings::setShowMain(false);
1176}
1177
1178void MainWindow::showEvent(QShowEvent *)
1179{
1180 Settings::setShowMain(true);
1181}
1182
1183void MainWindow::dragEnterEvent(QDragEnterEvent * event)
1184{
1185 event->setAccepted(KUrl::List::canDecode(event->mimeData())
1186 || event->mimeData()->hasText());
1187}
1188
1189void MainWindow::dropEvent(QDropEvent * event)
1190{
1191 KUrl::List list = KUrl::List::fromMimeData(event->mimeData());
1192
1193 if (!list.isEmpty())
1194 {
1195 if (list.count() == 1 && list.first().url().endsWith(QLatin1String(".kgt")))
1196 {
1197 int msgBoxResult = KMessageBox::questionYesNoCancel(this, i18n("The dropped file is a KGet Transfer List"), "KGet",
1198 KGuiItem(i18n("&Download"), KIcon("document-save")),
1199 KGuiItem(i18n("&Load transfer list"), KIcon("list-add")), KStandardGuiItem::cancel());
1200
1201 if (msgBoxResult == 3) //Download
1202 NewTransferDialogHandler::showNewTransferDialog(list.first().url());
1203 if (msgBoxResult == 4) //Load
1204 KGet::load(list.first().url());
1205 }
1206 else
1207 {
1208 if (list.count() == 1)
1209 NewTransferDialogHandler::showNewTransferDialog(list.first().url());
1210 else
1211 NewTransferDialogHandler::showNewTransferDialog(list);
1212 }
1213 }
1214 else
1215 {
1216 NewTransferDialogHandler::showNewTransferDialog(KUrl());
1217 }
1218}
1219
1220#include "mainwindow.moc"
1221