2008-02-13 03:00:21 +00:00
|
|
|
/*
|
2014-01-18 20:56:57 +00:00
|
|
|
* This file Copyright (C) 2010-2014 Mnemosyne LLC
|
2008-02-13 03:00:21 +00:00
|
|
|
*
|
2014-01-21 03:10:30 +00:00
|
|
|
* It may be used under the GNU GPL versions 2 or 3
|
2014-01-19 01:09:44 +00:00
|
|
|
* or any future license endorsed by Mnemosyne LLC.
|
2008-09-23 19:11:04 +00:00
|
|
|
*
|
2008-02-13 03:00:21 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <glib/gi18n.h>
|
|
|
|
#include <gtk/gtk.h>
|
2009-11-22 16:20:22 +00:00
|
|
|
|
2010-02-05 12:35:29 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2010-12-22 07:04:11 +00:00
|
|
|
#include <libtransmission/transmission.h>
|
2017-04-21 07:40:57 +00:00
|
|
|
#include <libtransmission/file.h> /* tr_sys_path_is_same() */
|
2010-12-22 07:04:11 +00:00
|
|
|
|
2008-03-18 20:41:27 +00:00
|
|
|
#include "conf.h"
|
2008-02-13 03:00:21 +00:00
|
|
|
#include "file-list.h"
|
|
|
|
#include "hig.h"
|
2011-01-20 19:57:42 +00:00
|
|
|
#include "open-dialog.h"
|
2008-03-18 20:41:27 +00:00
|
|
|
#include "tr-prefs.h"
|
2017-04-21 07:40:57 +00:00
|
|
|
#include "util.h" /* gtr_priority_combo_get_value() */
|
2008-02-13 03:00:21 +00:00
|
|
|
|
2008-07-02 00:17:27 +00:00
|
|
|
/****
|
|
|
|
*****
|
|
|
|
****/
|
|
|
|
|
|
|
|
#define N_RECENT 4
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static GSList* get_recent_destinations(void)
|
2008-07-02 00:17:27 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
GSList* list = NULL;
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
for (int i = 0; i < N_RECENT; ++i)
|
2008-07-02 00:17:27 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
char key[64];
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* val;
|
2017-04-19 12:04:45 +00:00
|
|
|
g_snprintf(key, sizeof(key), "recent-download-dir-%d", i + 1);
|
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if ((val = gtr_pref_string_get(tr_quark_new(key, TR_BAD_SIZE))) != NULL)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
list = g_slist_append(list, (void*)val);
|
|
|
|
}
|
2008-07-02 00:17:27 +00:00
|
|
|
}
|
2013-07-20 16:19:15 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
return list;
|
2008-07-02 00:17:27 +00:00
|
|
|
}
|
|
|
|
|
2017-04-20 16:02:19 +00:00
|
|
|
static void save_recent_destination(TrCore* core, char const* dir)
|
2008-07-02 00:17:27 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
int i;
|
|
|
|
GSList* l;
|
|
|
|
GSList* list = get_recent_destinations();
|
2013-07-20 16:19:15 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (dir == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-07-20 16:19:15 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
/* if it was already in the list, remove it */
|
2017-04-30 16:25:26 +00:00
|
|
|
if ((l = g_slist_find_custom(list, dir, (GCompareFunc)g_strcmp0)) != NULL)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
list = g_slist_delete_link(list, l);
|
|
|
|
}
|
2013-07-20 16:19:15 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
/* add it to the front of the list */
|
|
|
|
list = g_slist_prepend(list, (void*)dir);
|
2013-07-20 16:19:15 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
/* make local copies of the strings that aren't
|
2017-04-21 07:40:57 +00:00
|
|
|
* invalidated by gtr_pref_string_set() */
|
2017-04-30 16:25:26 +00:00
|
|
|
for (l = list; l != NULL; l = l->next)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
l->data = g_strdup(l->data);
|
|
|
|
}
|
2013-07-20 16:19:15 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
/* save the first N_RECENT directories */
|
2017-04-30 16:25:26 +00:00
|
|
|
for (l = list, i = 0; l != NULL && i < N_RECENT; ++i, l = l->next)
|
2013-07-20 16:19:15 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
char key[64];
|
|
|
|
g_snprintf(key, sizeof(key), "recent-download-dir-%d", i + 1);
|
|
|
|
gtr_pref_string_set(tr_quark_new(key, TR_BAD_SIZE), l->data);
|
2008-07-02 00:17:27 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
gtr_pref_save(gtr_core_session(core));
|
|
|
|
|
|
|
|
/* cleanup */
|
fix: gcc warnings in libtransmission/ and utils/ (#843)
* fix: __attribute__(__printf__) warnings
* fix: implicit fallthrough warning
* fixup! fix: implicit fallthrough warning
* fix: disable warnings for 3rd party code
Since we want to leave upstream code as-is
* fixup! fix: disable warnings for 3rd party code
* fixup! fix: disable warnings for 3rd party code
* silence spurious alignment warning
Xrefs
Discussion: https://stackoverflow.com/a/35554349
Macro inspiration: https://pagure.io/SSSD/sssd/blob/90ac46f71068d131391492360a8553bdd005b5a7/f/src/util/util_safealign.h#_35
* fixup! fix: disable warnings for 3rd party code
* fixup! fix: implicit fallthrough warning
* make uncrustify happy
* remove uncrustify-test.sh
that's probably off-topic for this PR
* fixup! fix: __attribute__(__printf__) warnings
* Update libtransmission/CMakeLists.txt
Co-Authored-By: ckerr <ckerr@github.com>
* fixup! silence spurious alignment warning
* use -w for DISABLE_WARNINGS in Clang
* refactor: fix libtransmission deprecation warnings
* fix: pthread_create's start_routine's return value
This was defined as `void` on non-Windows but should have been `void*`
* chore: uncrustify
* fix: add DISABLE_WARNINGS option for SunPro Studio
* fix "unused in lambda capture" warnings by clang++
* fix 'increases required alignment' warning
Caused from storing int16_t's in a char array.
* fix net.c 'increases required alignment' warning
The code passes in a `struct sockaddr_storage*` which is a padded struct
large enough for the necessary alignment. Unfortunately it was recast as
a `struct sockaddr*` which has less padding and a smaller alignment. The
warning occrred because of these differing alignments.
* make building quieter so warnings are more visible
* fixup! fix 'increases required alignment' warning
* Fix -Wcast-function-type warnings in GTK+ app code
https://gitlab.gnome.org/GNOME/gnome-terminal/issues/96 talks about both
the issue and its solution.
GCC 8's -Wcast-function-type, enabled by -Wextra, is problematic in glib
applications because it's idiomatic there to recast function signatures,
e.g. `g_slist_free(list, (GFunc)g_free, NULL);`.
Disabling the warning with pragmas causes "unrecognized pragma" warnings
on clang and older versions of gcc, and disabling the warning could miss
actual bugs. GCC defines `void (*)(void)` as a special case that matches
anything so we can silence warnings by double-casting through GCallback.
In the previous example, the warning is silenced by changing the code to
read `g_slist_free(list, (GFunc)(GCallback)g_free, NULL);`).
* fixup! fix "unused in lambda capture" warnings by clang++
* fixup! fix "unused in lambda capture" warnings by clang++
* fix two more libtransmission compiler warnings
* fix: in watchdir, use TR_ENABLE_ASSERTS not NDEBUG
2019-11-06 17:27:03 +00:00
|
|
|
g_slist_foreach(list, (GFunc)(GCallback)g_free, NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
g_slist_free(list);
|
2008-07-02 00:17:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/****
|
|
|
|
*****
|
|
|
|
****/
|
|
|
|
|
2011-01-20 19:48:13 +00:00
|
|
|
struct OpenData
|
2008-02-13 03:00:21 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
TrCore* core;
|
|
|
|
GtkWidget* file_list;
|
|
|
|
GtkWidget* run_check;
|
|
|
|
GtkWidget* trash_check;
|
|
|
|
GtkWidget* priority_combo;
|
|
|
|
GtkWidget* freespace_label;
|
|
|
|
char* filename;
|
|
|
|
char* downloadDir;
|
|
|
|
tr_torrent* tor;
|
|
|
|
tr_ctor* ctor;
|
2008-02-13 03:00:21 +00:00
|
|
|
};
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static void removeOldTorrent(struct OpenData* o)
|
2008-02-13 03:00:21 +00:00
|
|
|
{
|
2017-04-30 16:25:26 +00:00
|
|
|
if (o->tor != NULL)
|
2008-02-13 03:00:21 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
gtr_file_list_clear(o->file_list);
|
|
|
|
tr_torrentRemove(o->tor, FALSE, NULL);
|
|
|
|
o->tor = NULL;
|
2008-02-13 03:00:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static void addResponseCB(GtkDialog* dialog, gint response, gpointer gdata)
|
2008-02-13 03:00:21 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
struct OpenData* o = gdata;
|
2008-02-13 03:00:21 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (o->tor != NULL)
|
2008-02-13 03:00:21 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
if (response != GTK_RESPONSE_ACCEPT)
|
2008-12-13 23:17:36 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
removeOldTorrent(o);
|
2008-12-13 23:17:36 +00:00
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
else
|
2008-09-23 19:11:04 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_torrentSetPriority(o->tor, gtr_priority_combo_get_value(GTK_COMBO_BOX(o->priority_combo)));
|
2010-02-02 07:51:45 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(o->run_check)))
|
|
|
|
{
|
|
|
|
tr_torrentStart(o->tor);
|
|
|
|
}
|
2008-12-13 23:17:36 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
gtr_core_add_torrent(o->core, o->tor, FALSE);
|
2008-12-13 23:17:36 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(o->trash_check)))
|
|
|
|
{
|
|
|
|
gtr_file_trash_or_remove(o->filename, NULL);
|
|
|
|
}
|
2008-12-13 23:17:36 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
save_recent_destination(o->core, o->downloadDir);
|
2008-02-13 03:00:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_ctorFree(o->ctor);
|
|
|
|
g_free(o->filename);
|
|
|
|
g_free(o->downloadDir);
|
|
|
|
g_free(o);
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
2008-02-13 03:00:21 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static void updateTorrent(struct OpenData* o)
|
2008-02-13 03:00:21 +00:00
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
gboolean const isLocalFile = tr_ctorGetSourceFile(o->ctor) != NULL;
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_widget_set_sensitive(o->trash_check, isLocalFile);
|
2010-05-13 13:12:27 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (o->tor == NULL)
|
2010-05-13 13:12:27 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
gtr_file_list_clear(o->file_list);
|
|
|
|
gtk_widget_set_sensitive(o->file_list, FALSE);
|
2010-05-13 13:12:27 +00:00
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
else
|
2010-05-13 13:12:27 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_torrentSetDownloadDir(o->tor, o->downloadDir);
|
|
|
|
gtk_widget_set_sensitive(o->file_list, tr_torrentHasMetadata(o->tor));
|
|
|
|
gtr_file_list_set_torrent(o->file_list, tr_torrentId(o->tor));
|
|
|
|
tr_torrentVerify(o->tor, NULL, NULL);
|
2009-04-24 01:37:04 +00:00
|
|
|
}
|
2008-02-13 03:00:21 +00:00
|
|
|
}
|
|
|
|
|
2008-08-14 03:37:02 +00:00
|
|
|
/**
|
|
|
|
* When the source .torrent file is deleted
|
|
|
|
* (such as, if it was a temp file that a web browser passed to us),
|
|
|
|
* gtk invokes this callback and `filename' will be NULL.
|
|
|
|
* The `filename' tests here are to prevent us from losing the current
|
|
|
|
* metadata when that happens.
|
|
|
|
*/
|
2017-04-19 12:04:45 +00:00
|
|
|
static void sourceChanged(GtkFileChooserButton* b, gpointer gdata)
|
2008-02-13 03:00:21 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
struct OpenData* o = gdata;
|
|
|
|
char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(b));
|
2008-02-13 03:00:21 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
/* maybe instantiate a torrent */
|
2017-04-30 16:25:26 +00:00
|
|
|
if (filename != NULL || o->tor == NULL)
|
2008-08-14 03:37:02 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
int err = 0;
|
2017-04-30 16:25:26 +00:00
|
|
|
bool new_file = false;
|
2017-04-19 12:04:45 +00:00
|
|
|
int duplicate_id = 0;
|
|
|
|
tr_torrent* torrent;
|
2008-08-14 03:37:02 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (filename != NULL && (o->filename == NULL || !tr_sys_path_is_same(filename, o->filename, NULL)))
|
2008-08-14 03:37:02 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
g_free(o->filename);
|
|
|
|
o->filename = g_strdup(filename);
|
|
|
|
tr_ctorSetMetainfoFromFile(o->ctor, o->filename);
|
2017-04-30 16:25:26 +00:00
|
|
|
new_file = true;
|
2008-08-14 03:37:02 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_ctorSetDownloadDir(o->ctor, TR_FORCE, o->downloadDir);
|
|
|
|
tr_ctorSetPaused(o->ctor, TR_FORCE, TRUE);
|
|
|
|
tr_ctorSetDeleteSource(o->ctor, FALSE);
|
2008-08-14 03:37:02 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if ((torrent = tr_torrentNew(o->ctor, &err, &duplicate_id)) != NULL)
|
2008-09-23 19:11:04 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
removeOldTorrent(o);
|
|
|
|
o->tor = torrent;
|
2008-09-23 19:11:04 +00:00
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
else if (new_file)
|
2008-09-23 19:11:04 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
tr_torrent* tor;
|
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (duplicate_id != 0)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
tor = gtr_core_find_torrent(o->core, duplicate_id);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tor = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
gtr_add_torrent_error_dialog(GTK_WIDGET(b), err, tor, o->filename);
|
2008-08-14 03:37:02 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
updateTorrent(o);
|
2008-02-13 03:00:21 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
g_free(filename);
|
2008-02-13 03:00:21 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static void downloadDirChanged(GtkFileChooserButton* b, gpointer gdata)
|
2008-02-13 03:00:21 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
struct OpenData* data = gdata;
|
|
|
|
char* fname = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(b));
|
2008-08-14 03:37:02 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (fname != NULL && (data->downloadDir == NULL || !tr_sys_path_is_same(fname, data->downloadDir, NULL)))
|
2008-04-13 01:36:53 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
g_free(data->downloadDir);
|
|
|
|
data->downloadDir = g_strdup(fname);
|
|
|
|
updateTorrent(data);
|
2013-02-09 04:05:03 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
gtr_freespace_label_set_dir(data->freespace_label, data->downloadDir);
|
2008-04-13 01:36:53 +00:00
|
|
|
}
|
2008-08-14 03:37:02 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
g_free(fname);
|
2008-02-13 03:00:21 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static void addTorrentFilters(GtkFileChooser* chooser)
|
2008-03-19 20:34:35 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
GtkFileFilter* filter;
|
2008-03-19 20:34:35 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
filter = gtk_file_filter_new();
|
|
|
|
gtk_file_filter_set_name(filter, _("Torrent files"));
|
|
|
|
gtk_file_filter_add_pattern(filter, "*.torrent");
|
|
|
|
gtk_file_chooser_add_filter(chooser, filter);
|
2008-03-19 20:34:35 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
filter = gtk_file_filter_new();
|
|
|
|
gtk_file_filter_set_name(filter, _("All files"));
|
|
|
|
gtk_file_filter_add_pattern(filter, "*");
|
|
|
|
gtk_file_chooser_add_filter(chooser, filter);
|
2008-03-19 20:34:35 +00:00
|
|
|
}
|
|
|
|
|
2008-02-13 03:00:21 +00:00
|
|
|
/****
|
|
|
|
*****
|
|
|
|
****/
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
GtkWidget* gtr_torrent_options_dialog_new(GtkWindow* parent, TrCore* core, tr_ctor* ctor)
|
2008-02-13 03:00:21 +00:00
|
|
|
{
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* str;
|
2017-04-19 12:04:45 +00:00
|
|
|
GtkWidget* w;
|
|
|
|
GtkWidget* d;
|
|
|
|
GtkGrid* grid;
|
|
|
|
int row;
|
|
|
|
GtkWidget* l;
|
|
|
|
GtkWidget* source_chooser;
|
|
|
|
struct OpenData* data;
|
|
|
|
bool flag;
|
|
|
|
GSList* list;
|
|
|
|
|
|
|
|
/* make the dialog */
|
2020-07-27 17:49:45 +00:00
|
|
|
d = gtk_dialog_new_with_buttons(_("Torrent Options"), parent, GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
|
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
|
|
_("_Open"), GTK_RESPONSE_ACCEPT,
|
|
|
|
NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT);
|
|
|
|
|
|
|
|
if (!tr_ctorGetDownloadDir(ctor, TR_FORCE, &str))
|
|
|
|
{
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert(str);
|
|
|
|
|
|
|
|
data = g_new0(struct OpenData, 1);
|
|
|
|
data->core = core;
|
|
|
|
data->ctor = ctor;
|
|
|
|
data->filename = g_strdup(tr_ctorGetSourceFile(ctor));
|
|
|
|
data->downloadDir = g_strdup(str);
|
|
|
|
data->file_list = gtr_file_list_new(core, 0);
|
|
|
|
str = _("Mo_ve .torrent file to the trash");
|
|
|
|
data->trash_check = gtk_check_button_new_with_mnemonic(str);
|
|
|
|
str = _("_Start when added");
|
|
|
|
data->run_check = gtk_check_button_new_with_mnemonic(str);
|
|
|
|
|
|
|
|
w = data->priority_combo = gtr_priority_combo_new();
|
|
|
|
gtr_priority_combo_set_value(GTK_COMBO_BOX(w), TR_PRI_NORMAL);
|
|
|
|
|
|
|
|
g_signal_connect(G_OBJECT(d), "response", G_CALLBACK(addResponseCB), data);
|
|
|
|
|
|
|
|
row = 0;
|
|
|
|
grid = GTK_GRID(gtk_grid_new());
|
|
|
|
gtk_container_set_border_width(GTK_CONTAINER(grid), GUI_PAD_BIG);
|
|
|
|
gtk_grid_set_row_spacing(grid, GUI_PAD);
|
|
|
|
gtk_grid_set_column_spacing(grid, GUI_PAD_BIG);
|
|
|
|
|
|
|
|
/* "torrent file" row */
|
|
|
|
l = gtk_label_new_with_mnemonic(_("_Torrent file:"));
|
2019-11-06 19:09:27 +00:00
|
|
|
g_object_set(l, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_CENTER, NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_grid_attach(grid, l, 0, row, 1, 1);
|
|
|
|
w = gtk_file_chooser_button_new(_("Select Source File"), GTK_FILE_CHOOSER_ACTION_OPEN);
|
|
|
|
source_chooser = w;
|
|
|
|
gtk_widget_set_hexpand(w, TRUE);
|
|
|
|
gtk_grid_attach_next_to(grid, w, l, GTK_POS_RIGHT, 1, 1);
|
|
|
|
gtk_label_set_mnemonic_widget(GTK_LABEL(l), w);
|
|
|
|
addTorrentFilters(GTK_FILE_CHOOSER(w));
|
|
|
|
g_signal_connect(w, "selection-changed", G_CALLBACK(sourceChanged), data);
|
|
|
|
|
|
|
|
/* "destination folder" row */
|
|
|
|
row++;
|
|
|
|
l = gtk_label_new_with_mnemonic(_("_Destination folder:"));
|
2019-11-06 19:09:27 +00:00
|
|
|
g_object_set(l, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_CENTER, NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_grid_attach(grid, l, 0, row, 1, 1);
|
|
|
|
w = gtk_file_chooser_button_new(_("Select Destination Folder"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
|
|
|
|
|
|
|
|
if (!gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(w), data->downloadDir))
|
|
|
|
{
|
|
|
|
g_warning("couldn't select '%s'", data->downloadDir);
|
|
|
|
}
|
|
|
|
|
|
|
|
list = get_recent_destinations();
|
|
|
|
|
2017-05-13 22:38:31 +00:00
|
|
|
for (GSList* walk = list; walk != NULL; walk = walk->next)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(w), walk->data, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_slist_free(list);
|
|
|
|
gtk_grid_attach_next_to(grid, w, l, GTK_POS_RIGHT, 1, 1);
|
|
|
|
gtk_label_set_mnemonic_widget(GTK_LABEL(l), w);
|
|
|
|
g_signal_connect(w, "selection-changed", G_CALLBACK(downloadDirChanged), data);
|
|
|
|
|
|
|
|
row++;
|
|
|
|
l = data->freespace_label = gtr_freespace_label_new(core, data->downloadDir);
|
|
|
|
gtk_widget_set_margin_bottom(l, GUI_PAD_BIG);
|
2019-11-06 19:09:27 +00:00
|
|
|
g_object_set(l, "halign", GTK_ALIGN_END, "valign", GTK_ALIGN_CENTER, NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_grid_attach(grid, l, 0, row, 2, 1);
|
|
|
|
|
|
|
|
/* file list row */
|
|
|
|
row++;
|
|
|
|
w = data->file_list;
|
|
|
|
gtk_widget_set_vexpand(w, TRUE);
|
2019-03-17 04:07:48 +00:00
|
|
|
gtk_widget_set_size_request(w, 466U, 300U);
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_grid_attach(grid, w, 0, row, 2, 1);
|
|
|
|
|
|
|
|
/* torrent priority row */
|
|
|
|
row++;
|
|
|
|
l = gtk_label_new_with_mnemonic(_("Torrent _priority:"));
|
2019-11-06 19:09:27 +00:00
|
|
|
g_object_set(l, "halign", GTK_ALIGN_START, "valign", GTK_ALIGN_CENTER, NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_grid_attach(grid, l, 0, row, 1, 1);
|
|
|
|
w = data->priority_combo;
|
|
|
|
gtk_label_set_mnemonic_widget(GTK_LABEL(l), w);
|
|
|
|
gtk_grid_attach_next_to(grid, w, l, GTK_POS_RIGHT, 1, 1);
|
|
|
|
|
|
|
|
/* torrent priority row */
|
|
|
|
row++;
|
|
|
|
w = data->run_check;
|
|
|
|
|
|
|
|
if (!tr_ctorGetPaused(ctor, TR_FORCE, &flag))
|
|
|
|
{
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), !flag);
|
|
|
|
gtk_grid_attach(grid, w, 0, row, 2, 1);
|
|
|
|
|
|
|
|
/* "trash .torrent file" row */
|
|
|
|
row++;
|
|
|
|
w = data->trash_check;
|
|
|
|
|
|
|
|
if (!tr_ctorGetDeleteSource(ctor, &flag))
|
|
|
|
{
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), flag);
|
|
|
|
gtk_grid_attach(grid, w, 0, row, 2, 1);
|
|
|
|
|
|
|
|
/* trigger sourceChanged, either directly or indirectly,
|
|
|
|
* so that it creates the tor/gtor objects */
|
|
|
|
w = source_chooser;
|
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (data->filename != NULL)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(w), data->filename);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sourceChanged(GTK_FILE_CHOOSER_BUTTON(w), data);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtr_dialog_set_content(GTK_DIALOG(d), GTK_WIDGET(grid));
|
|
|
|
w = gtk_dialog_get_widget_for_response(GTK_DIALOG(d), GTK_RESPONSE_ACCEPT);
|
|
|
|
gtk_widget_grab_focus(w);
|
|
|
|
return d;
|
2008-02-13 03:00:21 +00:00
|
|
|
}
|
2008-03-18 01:22:11 +00:00
|
|
|
|
|
|
|
/****
|
|
|
|
*****
|
|
|
|
****/
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static void onOpenDialogResponse(GtkDialog* dialog, int response, gpointer core)
|
2008-03-18 01:22:11 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
char* folder;
|
2008-03-19 14:54:32 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
/* remember this folder the next time we use this dialog */
|
|
|
|
folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
|
|
|
|
gtr_pref_string_set(TR_KEY_open_dialog_dir, folder);
|
|
|
|
g_free(folder);
|
2008-03-18 20:41:27 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (response == GTK_RESPONSE_ACCEPT)
|
2008-03-19 14:54:32 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog);
|
|
|
|
GtkWidget* w = gtk_file_chooser_get_extra_widget(chooser);
|
|
|
|
GtkToggleButton* tb = GTK_TOGGLE_BUTTON(w);
|
2017-04-20 16:02:19 +00:00
|
|
|
gboolean const do_start = gtr_pref_flag_get(TR_KEY_start_added_torrents);
|
|
|
|
gboolean const do_prompt = gtk_toggle_button_get_active(tb);
|
|
|
|
gboolean const do_notify = FALSE;
|
2017-04-19 12:04:45 +00:00
|
|
|
GSList* files = gtk_file_chooser_get_files(chooser);
|
|
|
|
|
|
|
|
gtr_core_add_files(core, files, do_start, do_prompt, do_notify);
|
fix: gcc warnings in libtransmission/ and utils/ (#843)
* fix: __attribute__(__printf__) warnings
* fix: implicit fallthrough warning
* fixup! fix: implicit fallthrough warning
* fix: disable warnings for 3rd party code
Since we want to leave upstream code as-is
* fixup! fix: disable warnings for 3rd party code
* fixup! fix: disable warnings for 3rd party code
* silence spurious alignment warning
Xrefs
Discussion: https://stackoverflow.com/a/35554349
Macro inspiration: https://pagure.io/SSSD/sssd/blob/90ac46f71068d131391492360a8553bdd005b5a7/f/src/util/util_safealign.h#_35
* fixup! fix: disable warnings for 3rd party code
* fixup! fix: implicit fallthrough warning
* make uncrustify happy
* remove uncrustify-test.sh
that's probably off-topic for this PR
* fixup! fix: __attribute__(__printf__) warnings
* Update libtransmission/CMakeLists.txt
Co-Authored-By: ckerr <ckerr@github.com>
* fixup! silence spurious alignment warning
* use -w for DISABLE_WARNINGS in Clang
* refactor: fix libtransmission deprecation warnings
* fix: pthread_create's start_routine's return value
This was defined as `void` on non-Windows but should have been `void*`
* chore: uncrustify
* fix: add DISABLE_WARNINGS option for SunPro Studio
* fix "unused in lambda capture" warnings by clang++
* fix 'increases required alignment' warning
Caused from storing int16_t's in a char array.
* fix net.c 'increases required alignment' warning
The code passes in a `struct sockaddr_storage*` which is a padded struct
large enough for the necessary alignment. Unfortunately it was recast as
a `struct sockaddr*` which has less padding and a smaller alignment. The
warning occrred because of these differing alignments.
* make building quieter so warnings are more visible
* fixup! fix 'increases required alignment' warning
* Fix -Wcast-function-type warnings in GTK+ app code
https://gitlab.gnome.org/GNOME/gnome-terminal/issues/96 talks about both
the issue and its solution.
GCC 8's -Wcast-function-type, enabled by -Wextra, is problematic in glib
applications because it's idiomatic there to recast function signatures,
e.g. `g_slist_free(list, (GFunc)g_free, NULL);`.
Disabling the warning with pragmas causes "unrecognized pragma" warnings
on clang and older versions of gcc, and disabling the warning could miss
actual bugs. GCC defines `void (*)(void)` as a special case that matches
anything so we can silence warnings by double-casting through GCallback.
In the previous example, the warning is silenced by changing the code to
read `g_slist_free(list, (GFunc)(GCallback)g_free, NULL);`).
* fixup! fix "unused in lambda capture" warnings by clang++
* fixup! fix "unused in lambda capture" warnings by clang++
* fix two more libtransmission compiler warnings
* fix: in watchdir, use TR_ENABLE_ASSERTS not NDEBUG
2019-11-06 17:27:03 +00:00
|
|
|
g_slist_foreach(files, (GFunc)(GCallback)g_object_unref, NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
g_slist_free(files);
|
2008-03-18 01:22:11 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
2008-03-18 01:22:11 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
GtkWidget* gtr_torrent_open_from_file_dialog_new(GtkWindow* parent, TrCore* core)
|
2008-03-18 01:22:11 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
GtkWidget* w;
|
|
|
|
GtkWidget* c;
|
2017-04-20 16:02:19 +00:00
|
|
|
char const* folder;
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2020-07-27 17:49:45 +00:00
|
|
|
w = gtk_file_chooser_dialog_new(_("Open a Torrent"), parent, GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
|
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
|
|
_("_Open"), GTK_RESPONSE_ACCEPT,
|
|
|
|
NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(w), TRUE);
|
|
|
|
addTorrentFilters(GTK_FILE_CHOOSER(w));
|
|
|
|
g_signal_connect(w, "response", G_CALLBACK(onOpenDialogResponse), core);
|
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if ((folder = gtr_pref_string_get(TR_KEY_open_dialog_dir)) != NULL)
|
2017-04-19 12:04:45 +00:00
|
|
|
{
|
|
|
|
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(w), folder);
|
|
|
|
}
|
|
|
|
|
|
|
|
c = gtk_check_button_new_with_mnemonic(_("Show _options dialog"));
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(c), gtr_pref_flag_get(TR_KEY_show_options_window));
|
|
|
|
gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(w), c);
|
|
|
|
gtk_widget_show(c);
|
|
|
|
|
|
|
|
return w;
|
2008-03-18 01:22:11 +00:00
|
|
|
}
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2009-11-22 16:20:22 +00:00
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
static void onOpenURLResponse(GtkDialog* dialog, int response, gpointer user_data)
|
2009-11-22 16:20:22 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
bool handled = false;
|
2009-11-22 16:20:22 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (response == GTK_RESPONSE_ACCEPT)
|
2009-11-22 16:20:22 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
GtkWidget* e = GTK_WIDGET(g_object_get_data(G_OBJECT(dialog), "url-entry"));
|
|
|
|
char* url = g_strdup(gtk_entry_get_text(GTK_ENTRY(e)));
|
|
|
|
g_strstrip(url);
|
2013-07-20 16:19:15 +00:00
|
|
|
|
2017-04-30 16:25:26 +00:00
|
|
|
if (url != NULL)
|
2013-07-20 16:19:15 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
handled = gtr_core_add_from_url(user_data, url);
|
|
|
|
|
|
|
|
if (!handled)
|
|
|
|
{
|
|
|
|
gtr_unrecognized_url_dialog(GTK_WIDGET(dialog), url);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(url);
|
2009-11-22 16:20:22 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-19 12:04:45 +00:00
|
|
|
else if (response == GTK_RESPONSE_CANCEL)
|
2012-04-07 00:41:21 +00:00
|
|
|
{
|
2017-04-30 16:25:26 +00:00
|
|
|
handled = true;
|
2012-04-07 00:41:21 +00:00
|
|
|
}
|
2009-11-22 16:20:22 +00:00
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
if (handled)
|
|
|
|
{
|
|
|
|
gtk_widget_destroy(GTK_WIDGET(dialog));
|
|
|
|
}
|
2009-11-22 16:20:22 +00:00
|
|
|
}
|
|
|
|
|
2017-04-19 12:04:45 +00:00
|
|
|
GtkWidget* gtr_torrent_open_from_url_dialog_new(GtkWindow* parent, TrCore* core)
|
2009-11-22 16:20:22 +00:00
|
|
|
{
|
2017-04-19 12:04:45 +00:00
|
|
|
guint row;
|
|
|
|
GtkWidget* e;
|
|
|
|
GtkWidget* t;
|
|
|
|
GtkWidget* w;
|
|
|
|
|
2020-07-27 17:49:45 +00:00
|
|
|
w = gtk_dialog_new_with_buttons(_("Open URL"), parent, GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
|
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
|
|
_("_Open"), GTK_RESPONSE_ACCEPT,
|
|
|
|
NULL);
|
2017-04-19 12:04:45 +00:00
|
|
|
g_signal_connect(w, "response", G_CALLBACK(onOpenURLResponse), core);
|
|
|
|
|
|
|
|
row = 0;
|
|
|
|
t = hig_workarea_create();
|
|
|
|
hig_workarea_add_section_title(t, &row, _("Open torrent from URL"));
|
|
|
|
e = gtk_entry_new();
|
|
|
|
gtk_widget_set_size_request(e, 400, -1);
|
|
|
|
gtr_paste_clipboard_url_into_entry(e);
|
|
|
|
g_object_set_data(G_OBJECT(w), "url-entry", e);
|
|
|
|
hig_workarea_add_row(t, &row, _("_URL"), e, NULL);
|
|
|
|
|
|
|
|
gtr_dialog_set_content(GTK_DIALOG(w), t);
|
|
|
|
|
|
|
|
if (gtk_entry_get_text_length(GTK_ENTRY(e)) == 0)
|
|
|
|
{
|
|
|
|
gtk_widget_grab_focus(e);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_widget_grab_focus(gtk_dialog_get_widget_for_response(GTK_DIALOG(w), GTK_RESPONSE_ACCEPT));
|
|
|
|
}
|
|
|
|
|
|
|
|
return w;
|
2009-11-22 16:20:22 +00:00
|
|
|
}
|