(trunk) first draft of changing the FreeSpace API to behave as https://trac.transmissionbt.com/ticket/4076#comment:25 -- libT, rpc, qt, and gtk implementations.

This commit is contained in:
Jordan Lee 2013-02-09 04:05:03 +00:00
parent 794a0c1d80
commit cd09204a6e
31 changed files with 552 additions and 190 deletions

View File

@ -1523,8 +1523,6 @@ printSession (tr_variant * top)
printf (" Configuration directory: %s\n", str);
if (tr_variantDictFindStr (args, TR_KEY_download_dir, &str, NULL))
printf (" Download directory: %s\n", str);
if (tr_variantDictFindInt (args, TR_KEY_download_dir_free_space, &i))
printf (" Download directory free space: %s\n", strlsize (buf, i, sizeof buf));
if (tr_variantDictFindInt (args, TR_KEY_peer_port, &i))
printf (" Listenport: %" PRId64 "\n", i);
if (tr_variantDictFindBool (args, TR_KEY_port_forwarding_enabled, &boolVal))

View File

@ -457,7 +457,6 @@
"cache-size-mb" | number | maximum size of the disk cache (MB)
"config-dir" | string | location of transmission's configuration directory
"download-dir" | string | default path to download torrents
"download-dir-free-space" | number | number of free bytes available in download-dir, or -1 if it can't be calculated
"download-queue-size" | number | max number of torrents to download at once (see download-queue-enabled)
"download-queue-enabled" | boolean | if true, limit how many torrents can be downloaded at once
"dht-enabled" | boolean | true means allow dht in public torrents
@ -516,8 +515,8 @@
Method name: "session-set"
Request arguments: one or more of 4.1's arguments, except: "blocklist-size",
"config-dir", "download-dir-free-space", "rpc-version",
"rpc-version-minimum", and "version"
"config-dir", "rpc-version", "rpc-version-minimum", and
"version"
Response arguments: none
4.1.2. Accessors
@ -598,6 +597,27 @@
Response arguments: none
4.7. Free Space
This method tests how much free space is available in a
client-specified folder.
Method name: "free-space"
Request arguments:
string | value type & description
------------+----------------------------------------------------------
"path" | string the directory to query
Response arguments:
string | value type & description
------------+----------------------------------------------------------
"path" | string same as the Request argument
"size-bytes"| number the size, in bytes, of the free space in that directory
5.0. Protocol Versions
The following changes have been made to the RPC interface:
@ -738,6 +758,8 @@
| | yes | | new method "queue-move-bottom"
| | yes | | new method "torrent-start-now"
------+---------+-----------+--------------------------+-------------------------------
15 | 2.80 | yes | torrent-get | new arg "etaIdle"
15 | 2.80 | NO | session-get | removed arg "download-dir-free-space"
| | yes | torrent-get | new arg "etaIdle"
| | yes | torrent-rename-path | new method
| | yes | free-space | new method

View File

@ -94,6 +94,7 @@ struct OpenData
GtkWidget * run_check;
GtkWidget * trash_check;
GtkWidget * priority_combo;
GtkWidget * freespace_label;
char * filename;
char * downloadDir;
tr_torrent * tor;
@ -226,6 +227,8 @@ downloadDirChanged (GtkFileChooserButton * b, gpointer gdata)
g_free (data->downloadDir);
data->downloadDir = g_strdup (fname);
updateTorrent (data);
gtr_freespace_label_set_dir (data->freespace_label, data->downloadDir);
}
g_free (fname);
@ -339,6 +342,13 @@ gtr_torrent_options_dialog_new (GtkWindow * parent, TrCore * core, tr_ctor * cto
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);
gtk_misc_set_alignment (GTK_MISC (l), 1.0f, 0.5f);
gtk_grid_attach (grid, l, 0, row, 2, 1);
// file list row
row++;
w = data->file_list;

View File

@ -25,6 +25,23 @@
#include "tr-prefs.h"
#include "util.h"
/**
***
**/
struct prefs_dialog_data
{
TrCore * core;
gulong core_prefs_tag;
GtkWidget * freespace_label;
GtkWidget * port_label;
GtkWidget * port_button;
GtkWidget * port_spin;
};
/**
***
**/
@ -256,7 +273,7 @@ target_cb (GtkWidget * tb, gpointer target)
****/
static GtkWidget*
downloadingPage (GObject * core)
downloadingPage (GObject * core, struct prefs_dialog_data * data)
{
GtkWidget * t;
GtkWidget * w;
@ -289,6 +306,10 @@ downloadingPage (GObject * core)
w = new_path_chooser_button (TR_KEY_download_dir, core);
hig_workarea_add_row (t, &row, _("Save to _Location:"), w, NULL);
l = data->freespace_label = gtr_freespace_label_new (TR_CORE(core), NULL);
gtk_misc_set_alignment (GTK_MISC (l), 1.0f, 0.5f);
hig_workarea_add_wide_control (t, &row, l);
hig_workarea_add_section_divider (t, &row);
hig_workarea_add_section_title (t, &row, _("Download Queue"));
@ -1242,11 +1263,49 @@ networkPage (GObject * core)
*****
****/
static void
on_prefs_dialog_destroyed (gpointer gdata, GObject * dead_dialog G_GNUC_UNUSED)
{
struct prefs_dialog_data * data = gdata;
if (data->core_prefs_tag > 0)
g_signal_handler_disconnect (data->core, data->core_prefs_tag);
g_free (data);
}
static void
on_core_prefs_changed (TrCore * core, const tr_quark key, gpointer gdata)
{
struct prefs_dialog_data * data = gdata;
#if 0
if (key == TR_KEY_peer_port)
{
gtr_label_set_text (GTK_LABEL (data->port_label), _("Status unknown"));
gtk_widget_set_sensitive (data->port_button, TRUE);
gtk_widget_set_sensitive (data->port_spin, TRUE);
}
#endif
if (key == TR_KEY_download_dir)
{
const char * downloadDir = tr_sessionGetDownloadDir (gtr_core_session (core));
gtr_freespace_label_set_dir (data->freespace_label, downloadDir);
}
}
GtkWidget *
gtr_prefs_dialog_new (GtkWindow * parent, GObject * core)
{
size_t i;
GtkWidget * d;
GtkWidget * n;
struct prefs_dialog_data * data;
const tr_quark prefs_quarks[] = { TR_KEY_peer_port, TR_KEY_download_dir };
data = g_new0 (struct prefs_dialog_data, 1);
data->core = TR_CORE (core);
data->core_prefs_tag = g_signal_connect (TR_CORE (core), "prefs-changed", G_CALLBACK (on_core_prefs_changed), data);
d = gtk_dialog_new_with_buttons (_("Transmission Preferences"),
parent,
@ -1254,6 +1313,7 @@ gtr_prefs_dialog_new (GtkWindow * parent, GObject * core)
GTK_STOCK_HELP, GTK_RESPONSE_HELP,
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
NULL);
g_object_weak_ref (G_OBJECT(d), on_prefs_dialog_destroyed, data);
gtk_window_set_role (GTK_WINDOW (d), "transmission-preferences-dialog");
gtk_container_set_border_width (GTK_CONTAINER (d), GUI_PAD);
@ -1262,7 +1322,7 @@ gtr_prefs_dialog_new (GtkWindow * parent, GObject * core)
gtk_notebook_append_page (GTK_NOTEBOOK (n), speedPage (core),
gtk_label_new (_("Speed")));
gtk_notebook_append_page (GTK_NOTEBOOK (n), downloadingPage (core),
gtk_notebook_append_page (GTK_NOTEBOOK (n), downloadingPage (core, data),
gtk_label_new (C_("Gerund", "Downloading")));
gtk_notebook_append_page (GTK_NOTEBOOK (n), seedingPage (core),
gtk_label_new (C_("Gerund", "Seeding")));
@ -1275,6 +1335,10 @@ gtr_prefs_dialog_new (GtkWindow * parent, GObject * core)
gtk_notebook_append_page (GTK_NOTEBOOK (n), remotePage (core),
gtk_label_new (_("Remote")));
/* init from prefs keys */
for (i=0; i<sizeof(prefs_quarks)/sizeof(prefs_quarks[0]); ++i)
on_core_prefs_changed (TR_CORE(core), prefs_quarks[i], data);
g_signal_connect (d, "response", G_CALLBACK (response_cb), core);
gtr_dialog_set_content (GTK_DIALOG (d), n);
return d;

View File

@ -54,8 +54,6 @@ typedef struct
GtkLabel * ul_lb;
GtkLabel * dl_lb;
GtkLabel * stats_lb;
GtkLabel * freespace_lb;
GtkWidget * freespace_icon;
GtkWidget * alt_speed_image;
GtkWidget * alt_speed_button;
GtkWidget * options_menu;
@ -715,25 +713,6 @@ gtr_window_new (GtkApplication * app, GtkUIManager * ui_mgr, TrCore * core)
gtk_grid_attach_next_to (grid, w, sibling, GTK_POS_RIGHT, 1, 1);
sibling = w;
/* freespace */
w = gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU);
p->freespace_icon = w;
g_object_set (G_OBJECT(w), "margin-left", GUI_PAD, NULL);
gtk_grid_attach_next_to (grid, w, sibling, GTK_POS_RIGHT, 1, 1);
sibling = w;
w = gtk_label_new (NULL);
g_object_set (G_OBJECT(w), "margin-left", GUI_PAD_BIG*2, NULL);
p->freespace_lb = GTK_LABEL (w);
gtk_label_set_single_line_mode (p->freespace_lb, TRUE);
gtk_grid_attach_next_to (grid, w, sibling, GTK_POS_RIGHT, 1, 1);
sibling = w;
/* spacer */
w = gtk_alignment_new (0.0f, 0.0f, 0.0f, 0.0f);
gtk_widget_set_hexpand (w, TRUE);
gtk_grid_attach_next_to (grid, w, sibling, GTK_POS_RIGHT, 1, 1);
sibling = w;
/* download */
w = dl_lb = gtk_label_new (NULL);
p->dl_lb = GTK_LABEL (w);
@ -814,45 +793,6 @@ gtr_window_new (GtkApplication * app, GtkUIManager * ui_mgr, TrCore * core)
return self;
}
static void
updateFreeSpace (PrivateData * p)
{
GtkWidget * w;
bool visible = false;
g_return_if_fail (p != NULL);
w = GTK_WIDGET (p->freespace_lb);
if (p->core != NULL)
{
tr_session * session = gtr_core_session (p->core);
const int64_t n = tr_sessionGetDownloadDirFreeSpace (session);
const char * downloadDir = tr_sessionGetDownloadDir (session);
visible = n >= 0;
if (visible)
{
char * str;
char sizeStr[32];
tr_strlsize (sizeStr, n, sizeof(sizeStr));
str = g_strdup_printf (_("%s Free"), sizeStr);
gtk_label_set_text (p->freespace_lb, str);
g_free (str);
str = g_strdup_printf (_("Download folder \"%1$s\" has %2$s free"), downloadDir, sizeStr);
gtk_widget_set_tooltip_text (w, str);
g_free (str);
}
}
gtk_widget_set_visible (w, visible);
gtk_widget_set_visible (p->freespace_icon, visible);
}
static void
updateStats (PrivateData * p)
{
@ -958,7 +898,6 @@ gtr_window_refresh (GtkWindow * self)
{
updateSpeeds (p);
updateStats (p);
updateFreeSpace (p);
}
}

View File

@ -26,6 +26,7 @@
#include "conf.h"
#include "hig.h"
#include "tr-core.h"
#include "tr-prefs.h"
#include "util.h"
@ -631,3 +632,122 @@ gtr_label_set_text (GtkLabel * lb, const char * newstr)
if (tr_strcmp0 (oldstr, newstr))
gtk_label_set_text (lb, newstr);
}
/***
****
***/
struct freespace_label_data
{
guint timer_id;
TrCore * core;
GtkLabel * label;
char * dir;
};
static void on_freespace_label_core_destroyed (gpointer gdata, GObject * dead_core);
static void on_freespace_label_destroyed (gpointer gdata, GObject * dead_label);
static void
freespace_label_data_free (gpointer gdata)
{
struct freespace_label_data * data = gdata;
if (data->core != NULL)
g_object_weak_unref (G_OBJECT(data->core), on_freespace_label_core_destroyed, data);
if (data->label != NULL)
g_object_weak_ref (G_OBJECT(data->label), on_freespace_label_destroyed, data);
g_source_remove (data->timer_id);
g_free (data->dir);
g_free (data);
}
static GQuark
freespace_label_data_quark (void)
{
static GQuark q = 0;
if (G_UNLIKELY(!q))
q = g_quark_from_static_string ("data");
return q;
}
static void
on_freespace_label_core_destroyed (gpointer gdata, GObject * dead_core G_GNUC_UNUSED)
{
struct freespace_label_data * data = gdata;
data->core = NULL;
freespace_label_data_free (data);
}
static void
on_freespace_label_destroyed (gpointer gdata, GObject * dead_label G_GNUC_UNUSED)
{
struct freespace_label_data * data = gdata;
data->label = NULL;
freespace_label_data_free (data);
}
static gboolean
on_freespace_timer (gpointer gdata)
{
char text[128];
char markup[128];
int64_t bytes;
tr_session * session;
struct freespace_label_data * data = gdata;
session = gtr_core_session (data->core);
bytes = tr_sessionGetDirFreeSpace (session, data->dir);
if (bytes < 0)
{
g_snprintf (text, sizeof(text), _("Error"));
}
else
{
char size[128];
tr_strlsize (size, bytes, sizeof(size));
g_snprintf (text, sizeof(text), _("%s free"), size);
}
g_snprintf (markup, sizeof(markup), "<i>%s</i>", text);
gtk_label_set_markup (data->label, markup);
return G_SOURCE_CONTINUE;
}
GtkWidget *
gtr_freespace_label_new (struct _TrCore * core, const char * dir)
{
struct freespace_label_data * data;
data = g_new0 (struct freespace_label_data, 1);
data->timer_id = g_timeout_add_seconds (3, on_freespace_timer, data);
data->core = core;
data->label = GTK_LABEL (gtk_label_new (NULL));
data->dir = g_strdup (dir);
/* when either the core or the label is destroyed, stop updating */
g_object_weak_ref (G_OBJECT(core), on_freespace_label_core_destroyed, data);
g_object_weak_ref (G_OBJECT(data->label), on_freespace_label_destroyed, data);
g_object_set_qdata (G_OBJECT(data->label), freespace_label_data_quark (), data);
on_freespace_timer (data);
return GTK_WIDGET (data->label);
}
void
gtr_freespace_label_set_dir (GtkWidget * label, const char * dir)
{
struct freespace_label_data * data;
data = g_object_get_qdata (G_OBJECT(label), freespace_label_data_quark ());
tr_free (data->dir);
data->dir = g_strdup (dir);
on_freespace_timer (data);
}

View File

@ -109,6 +109,16 @@ void gtr_combo_box_set_active_enum (GtkComboBox *, int value);
****
***/
struct _TrCore;
GtkWidget * gtr_freespace_label_new (struct _TrCore * core, const char * dir);
void gtr_freespace_label_set_dir (GtkWidget * label, const char * dir);
/***
****
***/
void gtr_unrecognized_url_dialog (GtkWidget * parent, const char * url);
void gtr_http_failure_dialog (GtkWidget * parent, const char * url, long response_code);

View File

@ -56,6 +56,7 @@
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -81,6 +82,8 @@
#include <xfs/xqm.h>
#endif
#include <event2/util.h> /* evutil_ascii_strcasecmp () */
#include "transmission.h"
#include "session.h"
#include "list.h"
@ -732,7 +735,7 @@ tr_getWebClientDir (const tr_session * session UNUSED)
***/
#ifndef WIN32
static char *
static const char *
getdev (const char * path)
{
#ifdef HAVE_GETMNTENT
@ -783,7 +786,7 @@ getdev (const char * path)
#endif
}
static char *
static const char *
getfstype (const char * device)
{
@ -833,12 +836,12 @@ getfstype (const char * device)
#endif
}
static char *
static const char *
getblkdev (const char * path)
{
char * c;
char * dir;
char * device;
const char * device;
dir = tr_strdup(path);
@ -860,7 +863,7 @@ getblkdev (const char * path)
}
static int64_t
getquota (char * device)
getquota (const char * device)
{
struct dqblk dq;
int64_t limit;
@ -960,41 +963,24 @@ getxfsquota (char * device)
#endif /* WIN32 */
static int64_t
tr_getQuotaFreeSpace (const char * path, char * device, char * fstype)
tr_getQuotaFreeSpace (const struct tr_device_info * info)
{
int64_t ret=-1;
int64_t ret = -1;
#ifndef WIN32
/* save device for future use */
if (!*device)
{
char * d = getblkdev (path);
if (d == NULL)
return ret;
tr_strlcpy (device, d, PATH_MAX + 1);
}
/* save FS type for future use */
if (!*fstype)
{
char * fs = getfstype (device);
if (fs != NULL)
tr_strlcpy (fstype, fs, PATH_MAX + 1);
}
if (strcasecmp(fstype, "xfs") == 0)
if (info->fstype && !evutil_ascii_strcasecmp(info->fstype, "xfs"))
{
#ifdef HAVE_XQM
ret = getxfsquota(device);
ret = getxfsquota (info->device);
#endif
}
else
{
ret = getquota(device);
ret = getquota (info->device);
}
#endif /* WIN32 */
return ret;
}
@ -1021,15 +1007,50 @@ tr_getDiskFreeSpace (const char * path)
#endif
}
int64_t
tr_getFreeSpace (const char * path, char * device, char * fstype)
struct tr_device_info *
tr_device_info_create (const char * path)
{
int64_t i = tr_getQuotaFreeSpace (path, device, fstype);
struct tr_device_info * info;
if (i < 0)
i = tr_getDiskFreeSpace (path);
info = tr_new0 (struct tr_device_info, 1);
info->path = tr_strdup (path);
info->device = tr_strdup (getblkdev (path));
info->fstype = tr_strdup (getfstype (path));
return i;
return info;
}
void
tr_device_info_free (struct tr_device_info * info)
{
if (info != NULL)
{
tr_free (info->fstype);
tr_free (info->device);
tr_free (info->path);
tr_free (info);
}
}
int64_t
tr_device_info_get_free_space (const struct tr_device_info * info)
{
int64_t free_space;
if ((info == NULL) || (info->path == NULL))
{
errno = EINVAL;
free_space = -1;
}
else
{
free_space = tr_getQuotaFreeSpace (info);
if (free_space < 0)
free_space = tr_getDiskFreeSpace (info->path);
}
return free_space;
}
/***

View File

@ -42,9 +42,20 @@ const char * tr_getTorrentDir (const tr_session *);
/** @brief return the directory where the Web Client's web ui files are kept */
const char * tr_getWebClientDir (const tr_session *);
struct tr_device_info
{
char * path;
char * device;
char * fstype;
};
struct tr_device_info * tr_device_info_create (const char * path);
/** If the disk quota is enabled and readable, this returns how much is available in the quota.
Otherwise, it returns how much is available on the disk, or -1 on error. */
int64_t tr_getFreeSpace (const char * path, char * device, char * fstype);
int64_t tr_device_info_get_free_space (const struct tr_device_info * info);
void tr_device_info_free (struct tr_device_info * info);
/** @} */

View File

@ -78,7 +78,6 @@ static const struct tr_key_struct my_static[] =
{ "done-date", 9 },
{ "doneDate", 8 },
{ "download-dir", 12 },
{ "download-dir-free-space", 23 },
{ "download-queue-enabled", 22 },
{ "download-queue-size", 19 },
{ "downloadCount", 13 },

View File

@ -88,7 +88,6 @@ enum
TR_KEY_done_date,
TR_KEY_doneDate,
TR_KEY_download_dir,
TR_KEY_download_dir_free_space,
TR_KEY_download_queue_enabled,
TR_KEY_download_queue_size,
TR_KEY_downloadCount,

View File

@ -106,7 +106,6 @@ test_session_get_and_set (void)
check (tr_variantDictFind (args, TR_KEY_config_dir) != NULL);
check (tr_variantDictFind (args, TR_KEY_dht_enabled) != NULL);
check (tr_variantDictFind (args, TR_KEY_download_dir) != NULL);
check (tr_variantDictFind (args, TR_KEY_download_dir_free_space) != NULL);
check (tr_variantDictFind (args, TR_KEY_download_queue_enabled) != NULL);
check (tr_variantDictFind (args, TR_KEY_download_queue_size) != NULL);
check (tr_variantDictFind (args, TR_KEY_encryption) != NULL);

View File

@ -1726,8 +1726,8 @@ torrentAdd (tr_session * session,
static const char*
sessionSet (tr_session * session,
tr_variant * args_in,
tr_variant * args_out UNUSED,
tr_variant * args_in,
tr_variant * args_out UNUSED,
struct tr_rpc_idle_data * idle_data UNUSED)
{
int64_t i;
@ -1905,7 +1905,6 @@ sessionGet (tr_session * s,
tr_variantDictAddStr (d, TR_KEY_download_dir, tr_sessionGetDownloadDir (s));
tr_variantDictAddBool (d, TR_KEY_download_queue_enabled, tr_sessionGetQueueEnabled (s, TR_DOWN));
tr_variantDictAddInt (d, TR_KEY_download_queue_size, tr_sessionGetQueueSize (s, TR_DOWN));
tr_variantDictAddInt (d, TR_KEY_download_dir_free_space, tr_sessionGetDownloadDirFreeSpace (s));
tr_variantDictAddInt (d, TR_KEY_peer_limit_global, tr_sessionGetPeerLimit (s));
tr_variantDictAddInt (d, TR_KEY_peer_limit_per_torrent, tr_sessionGetPeerLimitPerTorrent (s));
tr_variantDictAddStr (d, TR_KEY_incomplete_dir, tr_sessionGetIncompleteDir (s));
@ -1948,6 +1947,33 @@ sessionGet (tr_session * s,
return NULL;
}
static const char*
freeSpace (tr_session * session,
tr_variant * args_in,
tr_variant * args_out,
struct tr_rpc_idle_data * idle_data UNUSED)
{
int tmperr;
const char * path = NULL;
const char * err = NULL;
int64_t free_space = -1;
/* get the free space */
tr_variantDictFindStr (args_in, TR_KEY_path, &path, NULL);
tmperr = errno;
errno = 0;
free_space = tr_sessionGetDirFreeSpace (session, path);
if (free_space < 0)
err = tr_strerror (errno);
errno = tmperr;
/* response */
if (path != NULL)
tr_variantDictAddStr (args_out, TR_KEY_path, path);
tr_variantDictAddInt (args_out, TR_KEY_size_bytes, free_space);
return err;
}
/***
****
***/
@ -1978,6 +2004,7 @@ methods[] =
{
{ "port-test", false, portTest },
{ "blocklist-update", false, blocklistUpdate },
{ "free-space", true, freeSpace },
{ "session-close", true, sessionClose },
{ "session-get", true, sessionGet },
{ "session-set", true, sessionSet },

View File

@ -386,7 +386,7 @@ tr_sessionGetSettings (tr_session * s, tr_variant * d)
tr_variantDictAddBool (d, TR_KEY_dht_enabled, s->isDHTEnabled);
tr_variantDictAddBool (d, TR_KEY_utp_enabled, s->isUTPEnabled);
tr_variantDictAddBool (d, TR_KEY_lpd_enabled, s->isLPDEnabled);
tr_variantDictAddStr (d, TR_KEY_download_dir, s->downloadDir);
tr_variantDictAddStr (d, TR_KEY_download_dir, tr_sessionGetDownloadDir (s));
tr_variantDictAddInt (d, TR_KEY_download_queue_size, tr_sessionGetQueueSize (s, TR_DOWN));
tr_variantDictAddBool (d, TR_KEY_download_queue_enabled, tr_sessionGetQueueEnabled (s, TR_DOWN));
tr_variantDictAddInt (d, TR_KEY_speed_limit_down, tr_sessionGetSpeedLimit_KBps (s, TR_DOWN));
@ -953,33 +953,40 @@ tr_sessionSet (tr_session * session, tr_variant * settings)
void
tr_sessionSetDownloadDir (tr_session * session, const char * dir)
{
assert (tr_isSession (session));
struct tr_device_info * info = NULL;
if (session->downloadDir != dir)
{
tr_free (session->downloadDir);
session->downloadDir = tr_strdup (dir);
memset (session->downloadDirBlkDev, 0, sizeof(session->downloadDirBlkDev));
memset (session->downloadDirFsType, 0, sizeof(session->downloadDirFsType));
}
assert (tr_isSession (session));
if (dir != NULL)
info = tr_device_info_create (dir);
tr_device_info_free (session->downloadDir);
session->downloadDir = info;
}
const char *
tr_sessionGetDownloadDir (const tr_session * session)
{
assert (tr_isSession (session));
const char * dir = NULL;
return session->downloadDir;
assert (tr_isSession (session));
if ((session != NULL) && (session->downloadDir != NULL))
dir = session->downloadDir->path;
return dir;
}
int64_t
tr_sessionGetDownloadDirFreeSpace (tr_session * session)
tr_sessionGetDirFreeSpace (tr_session * session, const char * dir)
{
assert (tr_isSession (session));
int64_t free_space;
return tr_getFreeSpace (session->downloadDir,
session->downloadDirBlkDev,
session->downloadDirFsType);
if (!tr_strcmp0 (dir, tr_sessionGetDownloadDir (session)))
free_space = tr_device_info_get_free_space (session->downloadDir);
else
free_space = tr_getDirFreeSpace (dir);
return free_space;
}
/***
@ -1883,12 +1890,12 @@ tr_sessionClose (tr_session * session)
tr_variantFree (session->metainfoLookup);
tr_free (session->metainfoLookup);
}
tr_device_info_free (session->downloadDir);
tr_free (session->torrentDoneScript);
tr_free (session->tag);
tr_free (session->configDir);
tr_free (session->resumeDir);
tr_free (session->torrentDir);
tr_free (session->downloadDir);
tr_free (session->incompleteDir);
tr_free (session->blocklist_url);
tr_free (session->peer_congestion_algorithm);

View File

@ -56,6 +56,7 @@ struct tr_announcer_udp;
struct tr_bindsockets;
struct tr_cache;
struct tr_fdInfo;
struct tr_device_info;
typedef void (tr_web_config_func)(tr_session * session, void * curl_pointer, const char * url, void * user_data);
@ -183,15 +184,14 @@ struct tr_session
char * tag;
char * configDir;
char * downloadDir;
char downloadDirBlkDev[TR_PATH_MAX + 1];
char downloadDirFsType[TR_PATH_MAX + 1];
char * resumeDir;
char * torrentDir;
char * incompleteDir;
char * blocklist_url;
struct tr_device_info * downloadDir;
struct tr_list * blocklists;
struct tr_peerMgr * peerMgr;
struct tr_shared * shared;

View File

@ -452,7 +452,7 @@ tr_ctorNew (const tr_session * session)
tr_ctorSetDeleteSource (ctor, tr_sessionGetDeleteSource (session));
tr_ctorSetPaused (ctor, TR_FALLBACK, tr_sessionGetPaused (session));
tr_ctorSetPeerLimit (ctor, TR_FALLBACK, session->peerLimitPerTorrent);
tr_ctorSetDownloadDir (ctor, TR_FALLBACK, session->downloadDir);
tr_ctorSetDownloadDir (ctor, TR_FALLBACK, tr_sessionGetDownloadDir(session));
}
tr_ctorSetSave (ctor, true);
return ctor;

View File

@ -82,7 +82,7 @@ tr_torrentName (const tr_torrent * tor)
int
tr_torrentId (const tr_torrent * tor)
{
return tor->uniqueId;
return tor ? tor->uniqueId : -1;
}
tr_torrent*

View File

@ -291,10 +291,10 @@ void tr_sessionSetDownloadDir (tr_session * session, const char * downloadDir);
const char * tr_sessionGetDownloadDir (const tr_session * session);
/**
* @brief Get available disk space (in bytes) for the default download folder.
* @brief Get available disk space (in bytes) for the specified directory.
* @return zero or positive integer on success, -1 in case of error.
*/
int64_t tr_sessionGetDownloadDirFreeSpace (tr_session * session);
int64_t tr_sessionGetDirFreeSpace (tr_session * session, const char * dir);
/**
* @brief Set the torrent's bandwidth priority.

View File

@ -420,6 +420,27 @@ tr_fileExists (const char * filename, time_t * mtime)
return ok;
}
int64_t
tr_getDirFreeSpace (const char * dir)
{
int64_t free_space;
if (!dir || !*dir)
{
errno = EINVAL;
free_space = -1;
}
else
{
struct tr_device_info * info;
info = tr_device_info_create (dir);
free_space = tr_device_info_get_free_space (info);
tr_device_info_free (info);
}
return free_space;
}
/****
*****
****/

View File

@ -140,6 +140,12 @@ char* tr_buildPath (const char * first_element, ...) TR_GNUC_NULL_TERMINATED
bool tr_fileExists (const char * filename, time_t * mtime);
/**
* @brief Get available disk space (in bytes) for the specified folder.
* @return zero or positive integer on success, -1 in case of error.
*/
int64_t tr_getDirFreeSpace (const char * path);
struct event;

86
qt/freespace-label.cc Normal file
View File

@ -0,0 +1,86 @@
/*
* This file Copyright (C) Mnemosyne LLC
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* $Id:$
*/
#include <libtransmission/transmission.h>
#include <libtransmission/variant.h>
#include "formatter.h"
#include "freespace-label.h"
#include "session.h"
namespace
{
static const int INTERVAL_MSEC = 5000;
}
FreespaceLabel :: FreespaceLabel (Session & session,
const QString & path,
QWidget * parent):
QLabel (parent),
mySession (session),
myTag (-1),
myPath (path),
myTimer (this)
{
myTimer.setSingleShot (false);
myTimer.setInterval (INTERVAL_MSEC);
myTimer.start ();
connect (&myTimer, SIGNAL(timeout()), this, SLOT(onTimer()));
connect (&mySession, SIGNAL(executed(int64_t, const QString&, struct tr_variant*)),
this, SLOT(onSessionExecuted(int64_t, const QString&, struct tr_variant*)));
onTimer ();
}
void
FreespaceLabel :: onTimer ()
{
const int64_t tag = mySession.getUniqueTag ();
const QByteArray myPathUtf8 = myPath.toUtf8 ();
myTag = tag;
tr_variant top;
tr_variantInitDict (&top, 3);
tr_variantDictAddStr (&top, TR_KEY_method, "free-space");
tr_variantDictAddInt (&top, TR_KEY_tag, tag);
tr_variant * args = tr_variantDictAddDict (&top, TR_KEY_arguments, 1);
tr_variantDictAddStr (args, TR_KEY_path, myPathUtf8.constData());
mySession.exec (&top);
tr_variantFree (&top);
}
void
FreespaceLabel :: onSessionExecuted (int64_t tag, const QString& result, struct tr_variant * arguments)
{
if (tag != myTag)
return;
QString str;
// update the label
int64_t bytes = -1;
tr_variantDictFindInt (arguments, TR_KEY_size_bytes, &bytes);
if (bytes < 0)
str = tr("Error: %1").arg(result);
else
str = tr("%1 free").arg(Formatter::sizeToString (bytes));
setText (QString("<i>%1</i>").arg(str));
// update the tooltip
size_t len = 0;
const char * path = 0;
tr_variantDictFindStr (arguments, TR_KEY_path, &path, &len);
str = QString::fromUtf8 (path, len);
setToolTip (str);
}

44
qt/freespace-label.h Normal file
View File

@ -0,0 +1,44 @@
/*
* This file Copyright (C) Mnemosyne LLC
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* $Id:$
*/
#ifndef QTR_FREESPACE_LABEL_H
#define QTR_FREESPACE_LABEL_H
#include <QString>
#include <QTimer>
#include <QtGui/QLabel>
class Session;
class FreespaceLabel: public QLabel
{
Q_OBJECT
public:
FreespaceLabel (Session&, const QString& path, QWidget *parent=0);
virtual ~FreespaceLabel () {}
void setPath (const QString& folder) { myPath=folder; onTimer(); }
private:
Session& mySession;
int64_t myTag;
QString myPath;
QTimer myTimer;
private slots:
void onSessionExecuted (int64_t tag, const QString& result, struct tr_variant * arguments);
void onTimer ();
};
#endif // QTR_FREESPACE_LABEL_H

View File

@ -281,7 +281,6 @@ TrMainWindow :: TrMainWindow (Session& session, Prefs& prefs, TorrentModel& mode
connect (&mySession, SIGNAL (sourceChanged ()), this, SLOT (onSessionSourceChanged ()));
connect (&mySession, SIGNAL (statsUpdated ()), this, SLOT (refreshStatusBar ()));
connect (&mySession, SIGNAL (sessionUpdated ()), this, SLOT (refreshFreeSpace ()));
connect (&mySession, SIGNAL (dataReadProgress ()), this, SLOT (dataReadProgress ()));
connect (&mySession, SIGNAL (dataSendProgress ()), this, SLOT (dataSendProgress ()));
connect (&mySession, SIGNAL (httpAuthenticationRequired ()), this, SLOT (wrongAuthentication ()));
@ -303,7 +302,6 @@ TrMainWindow :: TrMainWindow (Session& session, Prefs& prefs, TorrentModel& mode
refreshActionSensitivitySoon ();
refreshTrayIconSoon ();
refreshStatusBar ();
refreshFreeSpace ();
refreshTitle ();
}
@ -389,16 +387,6 @@ TrMainWindow :: createStatusBar ()
l = myNetworkLabel = new QLabel;
h->addWidget (l);
h->addStretch (1);
l = myFreeSpaceIconLabel = new QLabel (this);
l->setPixmap (getStockIcon ("drive-harddisk", QStyle::SP_DriveHDIcon).pixmap (smallIconSize));
h->addWidget (l);
l = myFreeSpaceTextLabel = new QLabel (this);
const int minimumFreeSpaceWidth = l->fontMetrics ().width (Formatter::sizeToString (1024 * 1024));
l->setMinimumWidth (minimumFreeSpaceWidth);
h->addWidget (l);
h->addStretch (1);
l = myDownloadSpeedLabel = new QLabel (this);
@ -712,28 +700,6 @@ TrMainWindow :: refreshTitle ()
setWindowTitle (title);
}
void
TrMainWindow :: refreshFreeSpace ()
{
const int64_t bytes (mySession.downloadDirFreeSpace ());
if (bytes >= 0)
{
const QString sizeStr = Formatter::sizeToString (bytes);
const QString tip = tr ("Download folder \"%1\" has %2 free")
.arg (myPrefs.getString (Prefs::DOWNLOAD_DIR))
.arg (sizeStr);
myFreeSpaceTextLabel->setText (tr("%1 Free").arg(sizeStr));
myFreeSpaceTextLabel->setToolTip (tip);
myFreeSpaceIconLabel->setToolTip (tip);
}
myFreeSpaceTextLabel->setVisible (bytes >= 0);
myFreeSpaceIconLabel->setVisible (bytes >= 0);
}
void
TrMainWindow :: refreshTrayIconSoon ()
{

View File

@ -104,7 +104,6 @@ class TrMainWindow: public QMainWindow
void showTotalTransfer ();
void showSessionRatio ();
void showSessionTransfer ();
void refreshFreeSpace ();
void refreshTitle ();
void refreshStatusBar ();
void refreshTrayIcon ();
@ -158,8 +157,6 @@ class TrMainWindow: public QMainWindow
QLabel * myStatsLabel;
QLabel * myDownloadSpeedLabel;
QLabel * myUploadSpeedLabel;
QLabel * myFreeSpaceTextLabel;
QLabel * myFreeSpaceIconLabel;
QLabel * myNetworkLabel;
public slots:

View File

@ -36,6 +36,7 @@
#include "add-data.h"
#include "file-tree.h"
#include "freespace-label.h"
#include "hig.h"
#include "options.h"
#include "prefs.h"
@ -118,10 +119,11 @@ Options :: Options( Session& session, const Prefs& prefs, const AddData& addme,
l = new QLabel( tr( "&Destination folder:" ) );
layout->addWidget( l, ++row, 0, Qt::AlignLeft );
const QString downloadDir (prefs.getString (Prefs::DOWNLOAD_DIR));
if( session.isLocal( ) )
{
myDestination.setPath( prefs.getString( Prefs :: DOWNLOAD_DIR ) );
myDestination.setPath (downloadDir);
p = myDestinationButton = new QPushButton;
p->setIcon( folderPixmap );
p->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
@ -133,11 +135,15 @@ Options :: Options( Session& session, const Prefs& prefs, const AddData& addme,
else
{
QLineEdit * e = myDestinationEdit = new QLineEdit;
e->setText( prefs.getString( Prefs :: DOWNLOAD_DIR ) );
e->setText (downloadDir);
layout->addWidget( e, row, 1 );
l->setBuddy( e );
}
l = myFreespaceLabel = new FreespaceLabel (mySession, downloadDir, this);
layout->addWidget (l, ++row, 0, 1, 2, Qt::Alignment (Qt::AlignRight | Qt::AlignTop));
layout->setRowMinimumHeight (row, l->height() + HIG::PAD);
myTree = new FileTreeView (0, false);
layout->addWidget( myTree, ++row, 0, 1, 2 );
if( !session.isLocal( ) )
@ -174,7 +180,7 @@ Options :: Options( Session& session, const Prefs& prefs, const AddData& addme,
connect( b, SIGNAL(accepted()), this, SLOT(onAccepted()) );
layout->addWidget( b, ++row, 0, 1, 2 );
layout->setRowStretch( 2, 2 );
layout->setRowStretch( 3, 2 );
layout->setColumnStretch( 1, 2 );
layout->setSpacing( HIG :: PAD );
@ -448,13 +454,14 @@ Options :: onDestinationClicked( )
}
void
Options :: onDestinationsSelected( const QStringList& destinations )
Options :: onDestinationsSelected (const QStringList& destinations)
{
if( destinations.size() == 1 )
if (destinations.size() == 1)
{
const QString& destination( destinations.first( ) );
myDestination.setPath( destination );
refreshDestinationButton( );
const QString& destination (destinations.first ());
myFreespaceLabel->setPath (destination);
myDestination.setPath (destination);
refreshDestinationButton ();
}
}

View File

@ -21,7 +21,6 @@
#include <QDir>
#include <QVector>
#include <QMap>
#include <QPushButton>
#include <QString>
#include <QStringList>
#include <QCryptographicHash>
@ -32,10 +31,13 @@
#include "add-data.h" // AddData
#include "file-tree.h" // FileList
class FileTreeView;
class Prefs;
class QCheckBox;
class QComboBox;
class QPushButton;
class FileTreeView;
class FreespaceLabel;
class Prefs;
class Session;
extern "C" { struct tr_variant; };
@ -78,6 +80,7 @@ class Options: public QDialog
bool myHaveInfo;
tr_info myInfo;
FileTreeView * myTree;
FreespaceLabel * myFreespaceLabel;
QCheckBox * myStartCheck;
QCheckBox * myTrashCheck;
QComboBox * myPriorityCombo;

View File

@ -36,6 +36,7 @@
#include <QTimer>
#include <QVBoxLayout>
#include "freespace-label.h"
#include "formatter.h"
#include "hig.h"
#include "prefs.h"
@ -588,6 +589,13 @@ PrefsDialog :: createDownloadingTab( )
connect( b, SIGNAL(clicked(bool)), this, SLOT(onDestinationClicked(void)) );
hig->addRow( tr( "Save to &Location:" ), b );
const QString downloadDir (myPrefs.getString(Prefs::DOWNLOAD_DIR));
l = myFreespaceLabel = new FreespaceLabel (mySession, downloadDir, this);
QHBoxLayout * h = new QHBoxLayout ();
h->addStretch (1);
h->addWidget (l);
hig->addWideControl (h);
hig->addSectionDivider( );
hig->addSectionTitle( tr( "Download Queue" ) );
@ -746,8 +754,9 @@ PrefsDialog :: refreshPref( int key )
break;
case Prefs :: DOWNLOAD_DIR: {
QString path( myPrefs.getString( key ) );
const QString path( myPrefs.getString( key ) );
myDestinationButton->setText( QFileInfo(path).fileName() );
myFreespaceLabel->setPath (path);
break;
}

View File

@ -32,6 +32,7 @@ class QPushButton;
class QMessageBox;
class QHttp;
class FreespaceLabel;
class Prefs;
class Session;
@ -108,6 +109,7 @@ class PrefsDialog: public QDialog
QWidgetList mySchedWidgets;
QWidgetList myBlockWidgets;
QWidgetList myUnsupportedWhenRemote;
FreespaceLabel * myFreespaceLabel;
int myBlocklistHttpTag;
QHttp * myBlocklistHttp;

View File

@ -52,6 +52,7 @@ SOURCES += about.cc \
file-tree.cc \
filterbar.cc \
filters.cc \
freespace-label.cc \
formatter.cc \
hig.cc \
license.cc \

View File

@ -258,8 +258,7 @@ Session :: Session (const char * configDir, Prefs& prefs):
myPrefs (prefs),
mySession (0),
myConfigDir (QString::fromUtf8 (configDir)),
myNAM (0),
myDownloadDirFreeSpace (-1)
myNAM (0)
{
myStats.ratio = TR_RATIO_NA;
myStats.uploadedBytes = 0;
@ -1008,9 +1007,6 @@ Session :: updateInfo (tr_variant * d)
if (tr_variantDictFindStr (d, TR_KEY_version, &str, NULL) && (mySessionVersion != str))
mySessionVersion = str;
if (tr_variantDictFindInt (d, TR_KEY_download_dir_free_space, &i) && (myDownloadDirFreeSpace != i))
myDownloadDirFreeSpace = i;
//std::cerr << "Session :: updateInfo end" << std::endl;
connect (&myPrefs, SIGNAL (changed (int)), this, SLOT (updatePref (int)));

View File

@ -57,7 +57,6 @@ class Session: public QObject
const struct tr_session_stats& getStats () const { return myStats; }
const struct tr_session_stats& getCumulativeStats () const { return myCumulativeStats; }
const QString& sessionVersion () const { return mySessionVersion; }
int64_t downloadDirFreeSpace () const { return myDownloadDirFreeSpace; }
public:
int64_t blocklistSize () const { return myBlocklistSize; }
@ -160,7 +159,6 @@ class Session: public QObject
struct tr_session_stats myStats;
struct tr_session_stats myCumulativeStats;
QString mySessionVersion;
int64_t myDownloadDirFreeSpace;
};
#endif