WebUI: Add missing icons
[qBittorrent.git] / src / webui / www / private / scripts / mocha-init.js
blobc19cc545ec9b930c9aeefafcbc65b3d5506ed7a0
1 /*
2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2008 Christophe Dumez <chris@qbittorrent.org>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * In addition, as a special exception, the copyright holders give permission to
20 * link this program with the OpenSSL project's "OpenSSL" library (or with
21 * modified versions of it that use the same license as the "OpenSSL" library),
22 * and distribute the linked executables. You must obey the GNU General Public
23 * License in all respects for all of the code used other than "OpenSSL". If you
24 * modify file(s), you may extend this exception to your version of the file(s),
25 * but you are not obligated to do so. If you do not wish to do so, delete this
26 * exception statement from your version.
29 /* -----------------------------------------------------------------
31 ATTACH MOCHA LINK EVENTS
32 Notes: Here is where you define your windows and the events that open them.
33 If you are not using links to run Mocha methods you can remove this function.
35 If you need to add link events to links within windows you are creating, do
36 it in the onContentLoaded function of the new window.
38 ----------------------------------------------------------------- */
39 "use strict";
41 const LocalPreferences = new window.qBittorrent.LocalPreferences.LocalPreferencesClass();
43 let saveWindowSize = function() {};
44 let loadWindowWidth = function() {};
45 let loadWindowHeight = function() {};
46 let showDownloadPage = function() {};
47 let globalUploadLimitFN = function() {};
48 let uploadLimitFN = function() {};
49 let shareRatioFN = function() {};
50 let toggleSequentialDownloadFN = function() {};
51 let toggleFirstLastPiecePrioFN = function() {};
52 let setSuperSeedingFN = function() {};
53 let setForceStartFN = function() {};
54 let globalDownloadLimitFN = function() {};
55 let StatisticsLinkFN = function() {};
56 let downloadLimitFN = function() {};
57 let deleteFN = function() {};
58 let stopFN = function() {};
59 let startFN = function() {};
60 let autoTorrentManagementFN = function() {};
61 let recheckFN = function() {};
62 let reannounceFN = function() {};
63 let setLocationFN = function() {};
64 let renameFN = function() {};
65 let renameFilesFN = function() {};
66 let torrentNewCategoryFN = function() {};
67 let torrentSetCategoryFN = function() {};
68 let createCategoryFN = function() {};
69 let createSubcategoryFN = function() {};
70 let editCategoryFN = function() {};
71 let removeCategoryFN = function() {};
72 let deleteUnusedCategoriesFN = function() {};
73 let startTorrentsByCategoryFN = function() {};
74 let stopTorrentsByCategoryFN = function() {};
75 let deleteTorrentsByCategoryFN = function() {};
76 let torrentAddTagsFN = function() {};
77 let torrentSetTagsFN = function() {};
78 let torrentRemoveAllTagsFN = function() {};
79 let createTagFN = function() {};
80 let removeTagFN = function() {};
81 let deleteUnusedTagsFN = function() {};
82 let startTorrentsByTagFN = function() {};
83 let stopTorrentsByTagFN = function() {};
84 let deleteTorrentsByTagFN = function() {};
85 let startTorrentsByTrackerFN = function() {};
86 let stopTorrentsByTrackerFN = function() {};
87 let deleteTorrentsByTrackerFN = function() {};
88 let copyNameFN = function() {};
89 let copyInfohashFN = function(policy) {};
90 let copyMagnetLinkFN = function() {};
91 let copyIdFN = function() {};
92 let copyCommentFN = function() {};
93 let setQueuePositionFN = function() {};
94 let exportTorrentFN = function() {};
96 const initializeWindows = function() {
97 saveWindowSize = function(windowId) {
98 const size = $(windowId).getSize();
99 LocalPreferences.set("window_" + windowId + "_width", size.x);
100 LocalPreferences.set("window_" + windowId + "_height", size.y);
103 loadWindowWidth = function(windowId, defaultValue) {
104 return LocalPreferences.get("window_" + windowId + "_width", defaultValue);
107 loadWindowHeight = function(windowId, defaultValue) {
108 return LocalPreferences.get("window_" + windowId + "_height", defaultValue);
111 function addClickEvent(el, fn) {
112 ["Link", "Button"].each((item) => {
113 if ($(el + item))
114 $(el + item).addEventListener("click", fn);
118 addClickEvent("download", (e) => {
119 e.preventDefault();
120 e.stopPropagation();
121 showDownloadPage();
124 showDownloadPage = function(urls) {
125 const id = "downloadPage";
126 const contentUri = new URI("download.html");
128 if (urls && (urls.length > 0))
129 contentUri.setData("urls", urls.map(encodeURIComponent).join("|"));
131 new MochaUI.Window({
132 id: id,
133 icon: "images/qbittorrent-tray.svg",
134 title: "QBT_TR(Download from URLs)QBT_TR[CONTEXT=downloadFromURL]",
135 loadMethod: "iframe",
136 contentURL: contentUri.toString(),
137 addClass: "windowFrame", // fixes iframe scrolling on iOS Safari
138 scrollbars: true,
139 maximizable: false,
140 closable: true,
141 paddingVertical: 0,
142 paddingHorizontal: 0,
143 width: loadWindowWidth(id, 500),
144 height: loadWindowHeight(id, 600),
145 onResize: function() {
146 saveWindowSize(id);
149 updateMainData();
152 addClickEvent("preferences", (e) => {
153 e.preventDefault();
154 e.stopPropagation();
156 const id = "preferencesPage";
157 new MochaUI.Window({
158 id: id,
159 icon: "images/qbittorrent-tray.svg",
160 title: "QBT_TR(Options)QBT_TR[CONTEXT=OptionsDialog]",
161 loadMethod: "xhr",
162 toolbar: true,
163 contentURL: new URI("views/preferences.html").toString(),
164 require: {
165 css: ["css/Tabs.css"]
167 toolbarURL: "views/preferencesToolbar.html",
168 maximizable: false,
169 closable: true,
170 paddingVertical: 0,
171 paddingHorizontal: 0,
172 width: loadWindowWidth(id, 700),
173 height: loadWindowHeight(id, 600),
174 onResize: function() {
175 saveWindowSize(id);
180 addClickEvent("upload", (e) => {
181 e.preventDefault();
182 e.stopPropagation();
184 const id = "uploadPage";
185 new MochaUI.Window({
186 id: id,
187 icon: "images/qbittorrent-tray.svg",
188 title: "QBT_TR(Upload local torrent)QBT_TR[CONTEXT=HttpServer]",
189 loadMethod: "iframe",
190 contentURL: new URI("upload.html").toString(),
191 addClass: "windowFrame", // fixes iframe scrolling on iOS Safari
192 scrollbars: true,
193 maximizable: false,
194 paddingVertical: 0,
195 paddingHorizontal: 0,
196 width: loadWindowWidth(id, 500),
197 height: loadWindowHeight(id, 460),
198 onResize: function() {
199 saveWindowSize(id);
202 updateMainData();
205 globalUploadLimitFN = function() {
206 new MochaUI.Window({
207 id: "uploadLimitPage",
208 icon: "images/qbittorrent-tray.svg",
209 title: "QBT_TR(Global Upload Speed Limit)QBT_TR[CONTEXT=MainWindow]",
210 loadMethod: "iframe",
211 contentURL: new URI("uploadlimit.html").setData("hashes", "global").toString(),
212 scrollbars: false,
213 resizable: false,
214 maximizable: false,
215 paddingVertical: 0,
216 paddingHorizontal: 0,
217 width: 424,
218 height: 80
222 uploadLimitFN = function() {
223 const hashes = torrentsTable.selectedRowsIds();
224 if (hashes.length) {
225 new MochaUI.Window({
226 id: "uploadLimitPage",
227 icon: "images/qbittorrent-tray.svg",
228 title: "QBT_TR(Torrent Upload Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]",
229 loadMethod: "iframe",
230 contentURL: new URI("uploadlimit.html").setData("hashes", hashes.join("|")).toString(),
231 scrollbars: false,
232 resizable: false,
233 maximizable: false,
234 paddingVertical: 0,
235 paddingHorizontal: 0,
236 width: 424,
237 height: 80
242 shareRatioFN = function() {
243 const hashes = torrentsTable.selectedRowsIds();
244 if (hashes.length) {
245 let shareRatio = null;
246 let torrentsHaveSameShareRatio = true;
248 // check if all selected torrents have same share ratio
249 for (let i = 0; i < hashes.length; ++i) {
250 const hash = hashes[i];
251 const row = torrentsTable.rows[hash].full_data;
252 const origValues = row.ratio_limit + "|" + row.seeding_time_limit + "|" + row.inactive_seeding_time_limit + "|"
253 + row.max_ratio + "|" + row.max_seeding_time + "|" + row.max_inactive_seeding_time;
255 // initialize value
256 if (shareRatio === null)
257 shareRatio = origValues;
259 if (origValues !== shareRatio) {
260 torrentsHaveSameShareRatio = false;
261 break;
265 // if all torrents have same share ratio, display that share ratio. else use the default
266 const orig = torrentsHaveSameShareRatio ? shareRatio : "";
267 new MochaUI.Window({
268 id: "shareRatioPage",
269 icon: "images/qbittorrent-tray.svg",
270 title: "QBT_TR(Torrent Upload/Download Ratio Limiting)QBT_TR[CONTEXT=UpDownRatioDialog]",
271 loadMethod: "iframe",
272 contentURL: new URI("shareratio.html").setData("hashes", hashes.join("|")).setData("orig", orig).toString(),
273 scrollbars: false,
274 maximizable: false,
275 paddingVertical: 0,
276 paddingHorizontal: 0,
277 width: 424,
278 height: 200
283 toggleSequentialDownloadFN = function() {
284 const hashes = torrentsTable.selectedRowsIds();
285 if (hashes.length) {
286 new Request({
287 url: "api/v2/torrents/toggleSequentialDownload",
288 method: "post",
289 data: {
290 hashes: hashes.join("|")
292 }).send();
293 updateMainData();
297 toggleFirstLastPiecePrioFN = function() {
298 const hashes = torrentsTable.selectedRowsIds();
299 if (hashes.length) {
300 new Request({
301 url: "api/v2/torrents/toggleFirstLastPiecePrio",
302 method: "post",
303 data: {
304 hashes: hashes.join("|")
306 }).send();
307 updateMainData();
311 setSuperSeedingFN = function(val) {
312 const hashes = torrentsTable.selectedRowsIds();
313 if (hashes.length) {
314 new Request({
315 url: "api/v2/torrents/setSuperSeeding",
316 method: "post",
317 data: {
318 value: val,
319 hashes: hashes.join("|")
321 }).send();
322 updateMainData();
326 setForceStartFN = function() {
327 const hashes = torrentsTable.selectedRowsIds();
328 if (hashes.length) {
329 new Request({
330 url: "api/v2/torrents/setForceStart",
331 method: "post",
332 data: {
333 value: "true",
334 hashes: hashes.join("|")
336 }).send();
337 updateMainData();
341 globalDownloadLimitFN = function() {
342 new MochaUI.Window({
343 id: "downloadLimitPage",
344 icon: "images/qbittorrent-tray.svg",
345 title: "QBT_TR(Global Download Speed Limit)QBT_TR[CONTEXT=MainWindow]",
346 loadMethod: "iframe",
347 contentURL: new URI("downloadlimit.html").setData("hashes", "global").toString(),
348 scrollbars: false,
349 resizable: false,
350 maximizable: false,
351 paddingVertical: 0,
352 paddingHorizontal: 0,
353 width: 424,
354 height: 80
358 StatisticsLinkFN = function() {
359 const id = "statisticspage";
360 new MochaUI.Window({
361 id: id,
362 icon: "images/qbittorrent-tray.svg",
363 title: "QBT_TR(Statistics)QBT_TR[CONTEXT=StatsDialog]",
364 loadMethod: "xhr",
365 contentURL: new URI("views/statistics.html").toString(),
366 maximizable: false,
367 padding: 10,
368 width: loadWindowWidth(id, 275),
369 height: loadWindowHeight(id, 370),
370 onResize: function() {
371 saveWindowSize(id);
376 downloadLimitFN = function() {
377 const hashes = torrentsTable.selectedRowsIds();
378 if (hashes.length) {
379 new MochaUI.Window({
380 id: "downloadLimitPage",
381 icon: "images/qbittorrent-tray.svg",
382 title: "QBT_TR(Torrent Download Speed Limiting)QBT_TR[CONTEXT=TransferListWidget]",
383 loadMethod: "iframe",
384 contentURL: new URI("downloadlimit.html").setData("hashes", hashes.join("|")).toString(),
385 scrollbars: false,
386 resizable: false,
387 maximizable: false,
388 paddingVertical: 0,
389 paddingHorizontal: 0,
390 width: 424,
391 height: 80
396 deleteFN = function(deleteFiles = false) {
397 const hashes = torrentsTable.selectedRowsIds();
398 if (hashes.length) {
399 new MochaUI.Window({
400 id: "confirmDeletionPage",
401 icon: "images/qbittorrent-tray.svg",
402 title: "QBT_TR(Remove torrent(s))QBT_TR[CONTEXT=confirmDeletionDlg]",
403 loadMethod: "iframe",
404 contentURL: new URI("confirmdeletion.html").setData("hashes", hashes.join("|")).setData("deleteFiles", deleteFiles).toString(),
405 scrollbars: false,
406 resizable: true,
407 maximizable: false,
408 padding: 10,
409 width: 424,
410 height: 160
412 updateMainData();
416 addClickEvent("delete", (e) => {
417 e.preventDefault();
418 e.stopPropagation();
419 deleteFN();
422 stopFN = function() {
423 const hashes = torrentsTable.selectedRowsIds();
424 if (hashes.length) {
425 new Request({
426 url: "api/v2/torrents/stop",
427 method: "post",
428 data: {
429 hashes: hashes.join("|")
431 }).send();
432 updateMainData();
436 startFN = function() {
437 const hashes = torrentsTable.selectedRowsIds();
438 if (hashes.length) {
439 new Request({
440 url: "api/v2/torrents/start",
441 method: "post",
442 data: {
443 hashes: hashes.join("|")
445 }).send();
446 updateMainData();
450 autoTorrentManagementFN = function() {
451 const hashes = torrentsTable.selectedRowsIds();
452 if (hashes.length) {
453 let enable = false;
454 hashes.each((hash, index) => {
455 const row = torrentsTable.rows[hash];
456 if (!row.full_data.auto_tmm)
457 enable = true;
459 new Request({
460 url: "api/v2/torrents/setAutoManagement",
461 method: "post",
462 data: {
463 hashes: hashes.join("|"),
464 enable: enable
466 }).send();
467 updateMainData();
471 recheckFN = function() {
472 const hashes = torrentsTable.selectedRowsIds();
473 if (hashes.length) {
474 new Request({
475 url: "api/v2/torrents/recheck",
476 method: "post",
477 data: {
478 hashes: hashes.join("|"),
480 }).send();
481 updateMainData();
485 reannounceFN = function() {
486 const hashes = torrentsTable.selectedRowsIds();
487 if (hashes.length) {
488 new Request({
489 url: "api/v2/torrents/reannounce",
490 method: "post",
491 data: {
492 hashes: hashes.join("|"),
494 }).send();
495 updateMainData();
499 setLocationFN = function() {
500 const hashes = torrentsTable.selectedRowsIds();
501 if (hashes.length) {
502 const hash = hashes[0];
503 const row = torrentsTable.rows[hash];
505 new MochaUI.Window({
506 id: "setLocationPage",
507 icon: "images/qbittorrent-tray.svg",
508 title: "QBT_TR(Set location)QBT_TR[CONTEXT=TransferListWidget]",
509 loadMethod: "iframe",
510 contentURL: new URI("setlocation.html").setData("hashes", hashes.join("|")).setData("path", encodeURIComponent(row.full_data.save_path)).toString(),
511 scrollbars: false,
512 resizable: true,
513 maximizable: false,
514 paddingVertical: 0,
515 paddingHorizontal: 0,
516 width: 400,
517 height: 130
522 renameFN = function() {
523 const hashes = torrentsTable.selectedRowsIds();
524 if (hashes.length === 1) {
525 const hash = hashes[0];
526 const row = torrentsTable.rows[hash];
527 if (row) {
528 new MochaUI.Window({
529 id: "renamePage",
530 icon: "images/qbittorrent-tray.svg",
531 title: "QBT_TR(Rename)QBT_TR[CONTEXT=TransferListWidget]",
532 loadMethod: "iframe",
533 contentURL: new URI("rename.html").setData("hash", hash).setData("name", row.full_data.name).toString(),
534 scrollbars: false,
535 resizable: true,
536 maximizable: false,
537 paddingVertical: 0,
538 paddingHorizontal: 0,
539 width: 400,
540 height: 100
546 renameFilesFN = function() {
547 const hashes = torrentsTable.selectedRowsIds();
548 if (hashes.length === 1) {
549 const hash = hashes[0];
550 const row = torrentsTable.rows[hash];
551 if (row) {
552 new MochaUI.Window({
553 id: "multiRenamePage",
554 icon: "images/qbittorrent-tray.svg",
555 title: "QBT_TR(Renaming)QBT_TR[CONTEXT=TransferListWidget]",
556 data: { hash: hash, selectedRows: [] },
557 loadMethod: "xhr",
558 contentURL: "rename_files.html",
559 scrollbars: false,
560 resizable: true,
561 maximizable: false,
562 paddingVertical: 0,
563 paddingHorizontal: 0,
564 width: 800,
565 height: 420,
566 resizeLimit: { "x": [800], "y": [420] }
572 torrentNewCategoryFN = function() {
573 const action = "set";
574 const hashes = torrentsTable.selectedRowsIds();
575 if (hashes.length) {
576 new MochaUI.Window({
577 id: "newCategoryPage",
578 icon: "images/qbittorrent-tray.svg",
579 title: "QBT_TR(New Category)QBT_TR[CONTEXT=TransferListWidget]",
580 loadMethod: "iframe",
581 contentURL: new URI("newcategory.html").setData("action", action).setData("hashes", hashes.join("|")).toString(),
582 scrollbars: false,
583 resizable: true,
584 maximizable: false,
585 paddingVertical: 0,
586 paddingHorizontal: 0,
587 width: 400,
588 height: 150,
589 onCloseComplete: function() {
590 updateMainData();
596 torrentSetCategoryFN = function(categoryHash) {
597 const hashes = torrentsTable.selectedRowsIds();
598 if (hashes.length <= 0)
599 return;
601 const categoryName = category_list.has(categoryHash)
602 ? category_list.get(categoryHash).name
603 : "";
604 new Request({
605 url: "api/v2/torrents/setCategory",
606 method: "post",
607 data: {
608 hashes: hashes.join("|"),
609 category: categoryName
611 onSuccess: function() {
612 updateMainData();
614 }).send();
617 createCategoryFN = function() {
618 const action = "create";
619 new MochaUI.Window({
620 id: "newCategoryPage",
621 icon: "images/qbittorrent-tray.svg",
622 title: "QBT_TR(New Category)QBT_TR[CONTEXT=CategoryFilterWidget]",
623 loadMethod: "iframe",
624 contentURL: new URI("newcategory.html").setData("action", action).toString(),
625 scrollbars: false,
626 resizable: true,
627 maximizable: false,
628 paddingVertical: 0,
629 paddingHorizontal: 0,
630 width: 400,
631 height: 150
633 updateMainData();
636 createSubcategoryFN = function(categoryHash) {
637 const action = "createSubcategory";
638 const categoryName = category_list.get(categoryHash).name + "/";
639 new MochaUI.Window({
640 id: "newSubcategoryPage",
641 icon: "images/qbittorrent-tray.svg",
642 title: "QBT_TR(New Category)QBT_TR[CONTEXT=CategoryFilterWidget]",
643 loadMethod: "iframe",
644 contentURL: new URI("newcategory.html").setData("action", action).setData("categoryName", categoryName).toString(),
645 scrollbars: false,
646 resizable: true,
647 maximizable: false,
648 paddingVertical: 0,
649 paddingHorizontal: 0,
650 width: 400,
651 height: 150
653 updateMainData();
656 editCategoryFN = function(categoryHash) {
657 const action = "edit";
658 const category = category_list.get(categoryHash);
659 new MochaUI.Window({
660 id: "editCategoryPage",
661 icon: "images/qbittorrent-tray.svg",
662 title: "QBT_TR(Edit Category)QBT_TR[CONTEXT=TransferListWidget]",
663 loadMethod: "iframe",
664 contentURL: new URI("newcategory.html").setData("action", action).setData("categoryName", category.name).setData("savePath", category.savePath).toString(),
665 scrollbars: false,
666 resizable: true,
667 maximizable: false,
668 paddingVertical: 0,
669 paddingHorizontal: 0,
670 width: 400,
671 height: 150
673 updateMainData();
676 removeCategoryFN = function(categoryHash) {
677 const categoryName = category_list.get(categoryHash).name;
678 new Request({
679 url: "api/v2/torrents/removeCategories",
680 method: "post",
681 data: {
682 categories: categoryName
684 }).send();
685 setCategoryFilter(CATEGORIES_ALL);
688 deleteUnusedCategoriesFN = function() {
689 const categories = [];
690 category_list.forEach((category, hash) => {
691 if (torrentsTable.getFilteredTorrentsNumber("all", hash, TAGS_ALL, TRACKERS_ALL) === 0)
692 categories.push(category.name);
695 new Request({
696 url: "api/v2/torrents/removeCategories",
697 method: "post",
698 data: {
699 categories: categories.join("\n")
701 }).send();
702 setCategoryFilter(CATEGORIES_ALL);
705 startTorrentsByCategoryFN = function(categoryHash) {
706 const hashes = torrentsTable.getFilteredTorrentsHashes("all", categoryHash, TAGS_ALL, TRACKERS_ALL);
707 if (hashes.length) {
708 new Request({
709 url: "api/v2/torrents/start",
710 method: "post",
711 data: {
712 hashes: hashes.join("|")
714 }).send();
715 updateMainData();
719 stopTorrentsByCategoryFN = function(categoryHash) {
720 const hashes = torrentsTable.getFilteredTorrentsHashes("all", categoryHash, TAGS_ALL, TRACKERS_ALL);
721 if (hashes.length) {
722 new Request({
723 url: "api/v2/torrents/stop",
724 method: "post",
725 data: {
726 hashes: hashes.join("|")
728 }).send();
729 updateMainData();
733 deleteTorrentsByCategoryFN = function(categoryHash) {
734 const hashes = torrentsTable.getFilteredTorrentsHashes("all", categoryHash, TAGS_ALL, TRACKERS_ALL);
735 if (hashes.length) {
736 new MochaUI.Window({
737 id: "confirmDeletionPage",
738 icon: "images/qbittorrent-tray.svg",
739 title: "QBT_TR(Remove torrent(s))QBT_TR[CONTEXT=confirmDeletionDlg]",
740 loadMethod: "iframe",
741 contentURL: new URI("confirmdeletion.html").setData("hashes", hashes.join("|")).toString(),
742 scrollbars: false,
743 resizable: true,
744 maximizable: false,
745 padding: 10,
746 width: 424,
747 height: 160
749 updateMainData();
753 torrentAddTagsFN = function() {
754 const action = "set";
755 const hashes = torrentsTable.selectedRowsIds();
756 if (hashes.length) {
757 new MochaUI.Window({
758 id: "newTagPage",
759 icon: "images/qbittorrent-tray.svg",
760 title: "QBT_TR(Add tags)QBT_TR[CONTEXT=TransferListWidget]",
761 loadMethod: "iframe",
762 contentURL: new URI("newtag.html").setData("action", action).setData("hashes", hashes.join("|")).toString(),
763 scrollbars: false,
764 resizable: true,
765 maximizable: false,
766 paddingVertical: 0,
767 paddingHorizontal: 0,
768 width: 250,
769 height: 100
774 torrentSetTagsFN = function(tagHash, isSet) {
775 const hashes = torrentsTable.selectedRowsIds();
776 if (hashes.length <= 0)
777 return;
779 const tagName = tagList.has(tagHash) ? tagList.get(tagHash).name : "";
780 new Request({
781 url: (isSet ? "api/v2/torrents/addTags" : "api/v2/torrents/removeTags"),
782 method: "post",
783 data: {
784 hashes: hashes.join("|"),
785 tags: tagName,
787 }).send();
790 torrentRemoveAllTagsFN = function() {
791 const hashes = torrentsTable.selectedRowsIds();
792 if (hashes.length) {
793 new Request({
794 url: ("api/v2/torrents/removeTags"),
795 method: "post",
796 data: {
797 hashes: hashes.join("|"),
799 }).send();
803 createTagFN = function() {
804 const action = "create";
805 new MochaUI.Window({
806 id: "newTagPage",
807 icon: "images/qbittorrent-tray.svg",
808 title: "QBT_TR(New Tag)QBT_TR[CONTEXT=TagFilterWidget]",
809 loadMethod: "iframe",
810 contentURL: new URI("newtag.html").setData("action", action).toString(),
811 scrollbars: false,
812 resizable: true,
813 maximizable: false,
814 paddingVertical: 0,
815 paddingHorizontal: 0,
816 width: 250,
817 height: 100
819 updateMainData();
822 removeTagFN = function(tagHash) {
823 const tagName = tagList.get(tagHash).name;
824 new Request({
825 url: "api/v2/torrents/deleteTags",
826 method: "post",
827 data: {
828 tags: tagName
830 }).send();
831 setTagFilter(TAGS_ALL);
834 deleteUnusedTagsFN = function() {
835 const tags = [];
836 tagList.forEach((tag, hash) => {
837 if (torrentsTable.getFilteredTorrentsNumber("all", CATEGORIES_ALL, hash, TRACKERS_ALL) === 0)
838 tags.push(tag.name);
840 new Request({
841 url: "api/v2/torrents/deleteTags",
842 method: "post",
843 data: {
844 tags: tags.join(",")
846 }).send();
847 setTagFilter(TAGS_ALL);
850 startTorrentsByTagFN = function(tagHash) {
851 const hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, tagHash, TRACKERS_ALL);
852 if (hashes.length) {
853 new Request({
854 url: "api/v2/torrents/start",
855 method: "post",
856 data: {
857 hashes: hashes.join("|")
859 }).send();
860 updateMainData();
864 stopTorrentsByTagFN = function(tagHash) {
865 const hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, tagHash, TRACKERS_ALL);
866 if (hashes.length) {
867 new Request({
868 url: "api/v2/torrents/stop",
869 method: "post",
870 data: {
871 hashes: hashes.join("|")
873 }).send();
874 updateMainData();
878 deleteTorrentsByTagFN = function(tagHash) {
879 const hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, tagHash, TRACKERS_ALL);
880 if (hashes.length) {
881 new MochaUI.Window({
882 id: "confirmDeletionPage",
883 icon: "images/qbittorrent-tray.svg",
884 title: "QBT_TR(Remove torrent(s))QBT_TR[CONTEXT=confirmDeletionDlg]",
885 loadMethod: "iframe",
886 contentURL: new URI("confirmdeletion.html").setData("hashes", hashes.join("|")).toString(),
887 scrollbars: false,
888 resizable: true,
889 maximizable: false,
890 padding: 10,
891 width: 424,
892 height: 160
894 updateMainData();
898 startTorrentsByTrackerFN = function(trackerHash) {
899 const trackerHashInt = Number.parseInt(trackerHash, 10);
900 let hashes = [];
901 switch (trackerHashInt) {
902 case TRACKERS_ALL:
903 hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_ALL);
904 break;
905 case TRACKERS_TRACKERLESS:
906 hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_TRACKERLESS);
907 break;
908 default: {
909 const uniqueTorrents = new Set();
910 for (const torrents of trackerList.get(trackerHashInt).trackerTorrentMap.values()) {
911 for (const torrent of torrents)
912 uniqueTorrents.add(torrent);
914 hashes = [...uniqueTorrents];
915 break;
919 if (hashes.length > 0) {
920 new Request({
921 url: "api/v2/torrents/start",
922 method: "post",
923 data: {
924 hashes: hashes.join("|")
926 }).send();
927 updateMainData();
931 stopTorrentsByTrackerFN = function(trackerHash) {
932 const trackerHashInt = Number.parseInt(trackerHash, 10);
933 let hashes = [];
934 switch (trackerHashInt) {
935 case TRACKERS_ALL:
936 hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_ALL);
937 break;
938 case TRACKERS_TRACKERLESS:
939 hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_TRACKERLESS);
940 break;
941 default: {
942 const uniqueTorrents = new Set();
943 for (const torrents of trackerList.get(trackerHashInt).trackerTorrentMap.values()) {
944 for (const torrent of torrents)
945 uniqueTorrents.add(torrent);
947 hashes = [...uniqueTorrents];
948 break;
952 if (hashes.length) {
953 new Request({
954 url: "api/v2/torrents/stop",
955 method: "post",
956 data: {
957 hashes: hashes.join("|")
959 }).send();
960 updateMainData();
964 deleteTorrentsByTrackerFN = function(trackerHash) {
965 const trackerHashInt = Number.parseInt(trackerHash, 10);
966 let hashes = [];
967 switch (trackerHashInt) {
968 case TRACKERS_ALL:
969 hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_ALL);
970 break;
971 case TRACKERS_TRACKERLESS:
972 hashes = torrentsTable.getFilteredTorrentsHashes("all", CATEGORIES_ALL, TAGS_ALL, TRACKERS_TRACKERLESS);
973 break;
974 default: {
975 const uniqueTorrents = new Set();
976 for (const torrents of trackerList.get(trackerHashInt).trackerTorrentMap.values()) {
977 for (const torrent of torrents)
978 uniqueTorrents.add(torrent);
980 hashes = [...uniqueTorrents];
981 break;
985 if (hashes.length) {
986 new MochaUI.Window({
987 id: "confirmDeletionPage",
988 icon: "images/qbittorrent-tray.svg",
989 title: "QBT_TR(Remove torrent(s))QBT_TR[CONTEXT=confirmDeletionDlg]",
990 loadMethod: "iframe",
991 contentURL: new URI("confirmdeletion.html").setData("hashes", hashes.join("|")).toString(),
992 scrollbars: false,
993 resizable: true,
994 maximizable: false,
995 padding: 10,
996 width: 424,
997 height: 160,
998 onCloseComplete: function() {
999 updateMainData();
1000 setTrackerFilter(TRACKERS_ALL);
1006 copyNameFN = function() {
1007 const selectedRows = torrentsTable.selectedRowsIds();
1008 const names = [];
1009 if (selectedRows.length > 0) {
1010 const rows = torrentsTable.getFilteredAndSortedRows();
1011 for (let i = 0; i < selectedRows.length; ++i) {
1012 const hash = selectedRows[i];
1013 names.push(rows[hash].full_data.name);
1016 return names.join("\n");
1019 copyInfohashFN = function(policy) {
1020 const selectedRows = torrentsTable.selectedRowsIds();
1021 const infohashes = [];
1022 if (selectedRows.length > 0) {
1023 const rows = torrentsTable.getFilteredAndSortedRows();
1024 switch (policy) {
1025 case 1:
1026 for (const id of selectedRows) {
1027 const infohash = rows[id].full_data.infohash_v1;
1028 if (infohash !== "")
1029 infohashes.push(infohash);
1031 break;
1032 case 2:
1033 for (const id of selectedRows) {
1034 const infohash = rows[id].full_data.infohash_v2;
1035 if (infohash !== "")
1036 infohashes.push(infohash);
1038 break;
1041 return infohashes.join("\n");
1044 copyMagnetLinkFN = function() {
1045 const selectedRows = torrentsTable.selectedRowsIds();
1046 const magnets = [];
1047 if (selectedRows.length > 0) {
1048 const rows = torrentsTable.getFilteredAndSortedRows();
1049 for (let i = 0; i < selectedRows.length; ++i) {
1050 const hash = selectedRows[i];
1051 magnets.push(rows[hash].full_data.magnet_uri);
1054 return magnets.join("\n");
1057 copyIdFN = function() {
1058 return torrentsTable.selectedRowsIds().join("\n");
1061 copyCommentFN = function() {
1062 const selectedRows = torrentsTable.selectedRowsIds();
1063 const comments = [];
1064 if (selectedRows.length > 0) {
1065 const rows = torrentsTable.getFilteredAndSortedRows();
1066 for (let i = 0; i < selectedRows.length; ++i) {
1067 const hash = selectedRows[i];
1068 const comment = rows[hash].full_data.comment;
1069 if (comment && (comment !== ""))
1070 comments.push(comment);
1073 return comments.join("\n---------\n");
1076 exportTorrentFN = async function() {
1077 const hashes = torrentsTable.selectedRowsIds();
1078 for (const hash of hashes) {
1079 const row = torrentsTable.rows.get(hash);
1080 if (!row)
1081 continue;
1083 const name = row.full_data.name;
1084 const url = new URI("api/v2/torrents/export");
1085 url.setData("hash", hash);
1087 // download response to file
1088 const element = document.createElement("a");
1089 element.href = url;
1090 element.download = (name + ".torrent");
1091 document.body.appendChild(element);
1092 element.click();
1093 document.body.removeChild(element);
1095 // https://stackoverflow.com/questions/53560991/automatic-file-downloads-limited-to-10-files-on-chrome-browser
1096 await window.qBittorrent.Misc.sleep(200);
1100 addClickEvent("stopAll", (e) => {
1101 e.preventDefault();
1102 e.stopPropagation();
1104 if (confirm("QBT_TR(Would you like to stop all torrents?)QBT_TR[CONTEXT=MainWindow]")) {
1105 new Request({
1106 url: "api/v2/torrents/stop",
1107 method: "post",
1108 data: {
1109 hashes: "all"
1111 }).send();
1112 updateMainData();
1116 addClickEvent("startAll", (e) => {
1117 e.preventDefault();
1118 e.stopPropagation();
1120 if (confirm("QBT_TR(Would you like to start all torrents?)QBT_TR[CONTEXT=MainWindow]")) {
1121 new Request({
1122 url: "api/v2/torrents/start",
1123 method: "post",
1124 data: {
1125 hashes: "all"
1127 }).send();
1128 updateMainData();
1132 ["stop", "start", "recheck"].each((item) => {
1133 addClickEvent(item, (e) => {
1134 e.preventDefault();
1135 e.stopPropagation();
1137 const hashes = torrentsTable.selectedRowsIds();
1138 if (hashes.length) {
1139 hashes.each((hash, index) => {
1140 new Request({
1141 url: "api/v2/torrents/" + item,
1142 method: "post",
1143 data: {
1144 hashes: hash
1146 }).send();
1148 updateMainData();
1153 ["decreasePrio", "increasePrio", "topPrio", "bottomPrio"].each((item) => {
1154 addClickEvent(item, (e) => {
1155 e.preventDefault();
1156 e.stopPropagation();
1157 setQueuePositionFN(item);
1161 setQueuePositionFN = function(cmd) {
1162 const hashes = torrentsTable.selectedRowsIds();
1163 if (hashes.length) {
1164 new Request({
1165 url: "api/v2/torrents/" + cmd,
1166 method: "post",
1167 data: {
1168 hashes: hashes.join("|")
1170 }).send();
1171 updateMainData();
1175 addClickEvent("about", (e) => {
1176 e.preventDefault();
1177 e.stopPropagation();
1179 const id = "aboutpage";
1180 new MochaUI.Window({
1181 id: id,
1182 icon: "images/qbittorrent-tray.svg",
1183 title: "QBT_TR(About qBittorrent)QBT_TR[CONTEXT=AboutDialog]",
1184 loadMethod: "xhr",
1185 contentURL: new URI("views/about.html").toString(),
1186 require: {
1187 css: ["css/Tabs.css"]
1189 toolbar: true,
1190 toolbarURL: "views/aboutToolbar.html",
1191 padding: 10,
1192 width: loadWindowWidth(id, 550),
1193 height: loadWindowHeight(id, 360),
1194 onResize: function() {
1195 saveWindowSize(id);
1200 addClickEvent("logout", (e) => {
1201 e.preventDefault();
1202 e.stopPropagation();
1204 new Request({
1205 url: "api/v2/auth/logout",
1206 method: "post",
1207 onSuccess: function() {
1208 window.location.reload(true);
1210 }).send();
1213 addClickEvent("shutdown", (e) => {
1214 e.preventDefault();
1215 e.stopPropagation();
1217 if (confirm("QBT_TR(Are you sure you want to quit qBittorrent?)QBT_TR[CONTEXT=MainWindow]")) {
1218 new Request({
1219 url: "api/v2/app/shutdown",
1220 method: "post",
1221 onSuccess: function() {
1222 const shutdownMessage = "QBT_TR(%1 has been shutdown)QBT_TR[CONTEXT=HttpServer]".replace("%1", window.qBittorrent.Client.mainTitle());
1223 document.write(`<!doctype html><html lang="${LANG}"><head> <meta charset="UTF-8"> <meta name="color-scheme" content="light dark"> <title>${shutdownMessage}</title> <style>* {font-family: Arial, Helvetica, sans-serif;}</style></head><body> <h1 style="text-align: center;">${shutdownMessage}</h1></body></html>`);
1224 document.close();
1225 window.stop();
1226 window.qBittorrent.Client.stop();
1228 }).send();
1232 // Deactivate menu header links
1233 $$("a.returnFalse").each((el) => {
1234 el.addEventListener("click", (e) => {
1235 e.preventDefault();
1236 e.stopPropagation();