diff options
Diffstat (limited to 'src')
99 files changed, 3316 insertions, 3092 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0c1abd6..4602556 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,35 +17,8 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # -NULL = - -public_icons_themes = \ - hicolor \ - $(NULL) - -public_icons = \ - hicolor_apps_scalable_transmission-remote-gtk.svg \ - hicolor_apps_16x16_transmission-remote-gtk.png \ - hicolor_apps_24x24_transmission-remote-gtk.png \ - hicolor_apps_48x48_transmission-remote-gtk.png \ - hicolor_apps_22x22_transmission-remote-gtk.png \ - hicolor_apps_32x32_transmission-remote-gtk.png \ - $(NULL) - -if !WIN32 -EXTRA_DIST = transmission-remote-gtk.desktop.in transmission-remote-gtk.pod -CLEANFILES = transmission-remote-gtk.desktop transmission-remote-gtk.1 - -man_MANS = transmission-remote-gtk.1 - -desktopdir = $(datadir)/applications -desktop_DATA = transmission-remote-gtk.desktop - -endif - bin_PROGRAMS = transmission-remote-gtk -INCLUDES = -std=c99 -Wall -I.. -Wno-overflow -DTRGLICENSE=\""$(trglicense)"\" $(libcurl_CFLAGS) $(jsonglib_CFLAGS) $(gthread_CFLAGS) $(gtk_CFLAGS) $(gio_CFLAGS) $(unique_CFLAGS) $(notify_CFLAGS) $(libproxy_CFLAGS) $(libappindicator_CFLAGS) - + transmission_remote_gtk_SOURCES = \ trg-cell-renderer-speed.c \ trg-cell-renderer-counter.c \ @@ -105,9 +78,97 @@ transmission_remote_gtk_SOURCES = \ trg-client.c \ trg-main-window.c \ main.c \ - $(NULL) - -transmission_remote_gtk_LDFLAGS = -lm $(jsonglib_LIBS) $(gtk_LIBS) $(gthread_LIBS) $(GEOIP_LIBS) $(gio_LIBS) $(unique_LIBS) $(notify_LIBS) $(libproxy_LIBS) $(libcurl_LIBS) $(libappindicator_LIBS) + upload.c + +noinst_HEADERS = \ + trg-cell-renderer-speed.h \ + trg-cell-renderer-counter.h \ + trg-cell-renderer-size.h \ + trg-cell-renderer-ratio.h \ + trg-cell-renderer-eta.h \ + trg-cell-renderer-priority.h \ + trg-cell-renderer-wanted.h \ + trg-cell-renderer-file-icon.h \ + trg-cell-renderer-epoch.h \ + trg-cell-renderer-numgteqthan.h \ + torrent-cell-renderer.h \ + trg-remote-prefs-dialog.h \ + trg-torrent-props-dialog.h \ + trg-torrent-add-url-dialog.h \ + trg-torrent-add-dialog.h \ + trg-torrent-move-dialog.h \ + trg-preferences-dialog.h \ + trg-stats-dialog.h \ + trg-about-window.h \ + trg-destination-combo.h \ + trg-state-selector.h \ + trg-general-panel.h \ + trg-torrent-graph.h \ + trg-icons.h \ + icons.h \ + trg-toolbar.h \ + trg-menu-bar.h \ + trg-status-bar.h \ + trg-file-parser.h \ + trg-json-widgets.h \ + trg-model.h \ + trg-sortable-filtered-model.h \ + trg-files-tree.h \ + trg-files-model.h \ + trg-files-tree-view-common.h \ + trg-files-tree-view.h \ + trg-files-model-common.h \ + trg-trackers-model.h \ + trg-trackers-tree-view.h \ + trg-peers-model.h \ + trg-peers-tree-view.h \ + trg-torrent-model.h \ + trg-torrent-tree-view.h \ + trg-persistent-tree-view.h \ + trg-tree-view.h \ + util.h \ + hig.h \ + bencode.h \ + trg-prefs.h \ + remote-exec.h \ + trg-gtk-app.h \ + requests.h \ + torrent.h \ + session-get.h \ + json.h \ + trg-client.h \ + trg-main-window.h \ + upload.h \ + protocol-constants.h \ + icon-turtle.h + +transmission_remote_gtk_CPPFLAGS = \ + -DLOCALEDIR=\""$(localedir)"\" \ + -I$(top_srcdir)/extern + +transmission_remote_gtk_CFLAGS = \ + $(TRG_CFLAGS) \ + $(GEOIP_CFLAGS) \ + $(NOTIFY_CFLAGS) \ + $(MRSS_CFLAGS) \ + $(APPINDICATOR_CFLAGS) \ + $(PROXY_CFLAGS) + +transmission_remote_gtk_LDFLAGS = \ + $(LIBM) \ + $(TRG_LIBS) \ + $(GEOIP_LIBS) \ + $(NOTIFY_LIBS) \ + $(PROXY_LIBS) \ + $(APPINDICATOR_LIBS) \ + $(MRSS_CFLAGS) + +if HAVE_RSS +transmission_remote_gtk_LDFLAGS += ${top_builddir}/extern/rss-glib/librss.la + +transmission_remote_gtk_SOURCES += trg-rss-model.c trg-rss-window.c trg-rss-cell-renderer.c +noinst_HEADERS += trg-rss-model.h trg-rss-window.h trg-rss-cell-renderer.h +endif if WIN32 .rc.o: @@ -115,49 +176,16 @@ if WIN32 %.o : %.rc windres $^ -o $@ -CFLAGS += -mms-bitfields -mwin32 -mwindows -LDFLAGS += -Wl,--allow-multiple-definition -lws2_32 -lintl +transmission_remote_gtk_CFLAGS += -mms-bitfields -mwin32 -mwindows +transmission_remote_gtk_LDFLAGS += -Wl,--allow-multiple-definition -lws2_32 -lintl transmission_remote_gtk_SOURCES += win32.rc win32-mailslot.c -INCLUDES += -O2 else %.1: %.pod - pod2man --release="" --center="Transmission Remote GTK" $< > $@ + $(POD2MAN) --release="$(PACKAGE_VERSION)" --center="Transmission Remote GTK" $< > $@ + +EXTRA_DIST = transmission-remote-gtk.pod +CLEANFILES = transmission-remote-gtk.1 + +man_MANS = transmission-remote-gtk.1 endif -install-data-local: install-icons update-icon-cache - -gtk_update_icon_cache = gtk-update-icon-cache -f -t - -update-icon-cache: - @-if test -z "$(DESTDIR)"; then \ - echo "Updating Gtk icon cache."; \ - for theme in $(public_icons_themes); do \ - $(gtk_update_icon_cache) $(datadir)/icons/$$theme; \ - done; \ - else \ - echo "*** Icon cache not updated. After (un)install, run this:"; \ - for theme in $(public_icons_themes); do \ - echo "*** $(gtk_update_icon_cache) $(datadir)/icons/$$theme"; \ - done; \ - fi - -install-icons: - for icon in $(public_icons); do \ - THEME=`echo $$icon | cut -d_ -f1`; \ - CONTEXT=`echo $$icon | cut -d_ -f2`; \ - SIZE=`echo $$icon | cut -d_ -f3`; \ - ICONFILE=`echo $$icon | cut -d_ -f4`; \ - mkdir -p $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT; \ - $(INSTALL_DATA) $(srcdir)/$$icon $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \ - done; \ - for icon in $(private_icons); do \ - THEME=`echo $$icon | cut -d_ -f1`; \ - CONTEXT=`echo $$icon | cut -d_ -f2`; \ - SIZE=`echo $$icon | cut -d_ -f3`; \ - ICONFILE=`echo $$icon | cut -d_ -f4`; \ - mkdir -p $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT; \ - $(INSTALL_DATA) $(srcdir)/$$icon $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \ - done - -transmission-remote-gtk.desktop: transmission-remote-gtk.desktop.in - sed -e 's,@bindir\@,$(bindir),g' <transmission-remote-gtk.desktop.in > $@ diff --git a/src/Makefile.in b/src/Makefile.in deleted file mode 100644 index bc32290..0000000 --- a/src/Makefile.in +++ /dev/null @@ -1,968 +0,0 @@ -# Makefile.in generated by automake 1.12.2 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994-2012 Free Software Foundation, Inc. - -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - -# -# transmission-remote-gtk - A GTK RPC client to Transmission -# Copyright (C) 2011 Alan Fitton - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# - - -VPATH = @srcdir@ -am__make_dryrun = \ - { \ - am__dry=no; \ - case $$MAKEFLAGS in \ - *\\[\ \ ]*) \ - echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ - | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ - *) \ - for am__flg in $$MAKEFLAGS; do \ - case $$am__flg in \ - *=*|--*) ;; \ - *n*) am__dry=yes; break;; \ - esac; \ - done;; \ - esac; \ - test $$am__dry = yes; \ - } -pkgdatadir = $(datadir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkglibexecdir = $(libexecdir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -bin_PROGRAMS = transmission-remote-gtk$(EXEEXT) -@WIN32_TRUE@am__append_1 = -mms-bitfields -mwin32 -mwindows -@WIN32_TRUE@am__append_2 = -Wl,--allow-multiple-definition -lws2_32 -lintl -@WIN32_TRUE@am__append_3 = win32.rc win32-mailslot.c -@WIN32_TRUE@am__append_4 = -O2 -subdir = src -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(top_srcdir)/depcomp -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ - $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_HEADER = $(top_builddir)/config.h -CONFIG_CLEAN_FILES = -CONFIG_CLEAN_VPATH_FILES = -am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ - "$(DESTDIR)$(desktopdir)" -PROGRAMS = $(bin_PROGRAMS) -am__transmission_remote_gtk_SOURCES_DIST = trg-cell-renderer-speed.c \ - trg-cell-renderer-counter.c trg-cell-renderer-size.c \ - trg-cell-renderer-ratio.c trg-cell-renderer-eta.c \ - trg-cell-renderer-priority.c trg-cell-renderer-wanted.c \ - trg-cell-renderer-file-icon.c trg-cell-renderer-epoch.c \ - trg-cell-renderer-numgteqthan.c torrent-cell-renderer.c \ - trg-remote-prefs-dialog.c trg-torrent-props-dialog.c \ - trg-torrent-add-url-dialog.c trg-torrent-add-dialog.c \ - trg-torrent-move-dialog.c trg-preferences-dialog.c \ - trg-stats-dialog.c trg-about-window.c trg-destination-combo.c \ - trg-state-selector.c trg-general-panel.c trg-torrent-graph.c \ - trg-icons.c icons.c trg-toolbar.c trg-menu-bar.c \ - trg-status-bar.c trg-file-parser.c trg-json-widgets.c \ - trg-model.c trg-sortable-filtered-model.c trg-files-tree.c \ - trg-files-model.c trg-files-tree-view-common.c \ - trg-files-tree-view.c trg-files-model-common.c \ - trg-trackers-model.c trg-trackers-tree-view.c \ - trg-peers-model.c trg-peers-tree-view.c trg-torrent-model.c \ - trg-torrent-tree-view.c trg-persistent-tree-view.c \ - trg-tree-view.c util.c hig.c bencode.c trg-prefs.c \ - remote-exec.c trg-gtk-app.c requests.c torrent.c session-get.c \ - json.c trg-client.c trg-main-window.c main.c win32.rc \ - win32-mailslot.c -am__objects_1 = -@WIN32_TRUE@am__objects_2 = win32.$(OBJEXT) win32-mailslot.$(OBJEXT) -am_transmission_remote_gtk_OBJECTS = \ - trg-cell-renderer-speed.$(OBJEXT) \ - trg-cell-renderer-counter.$(OBJEXT) \ - trg-cell-renderer-size.$(OBJEXT) \ - trg-cell-renderer-ratio.$(OBJEXT) \ - trg-cell-renderer-eta.$(OBJEXT) \ - trg-cell-renderer-priority.$(OBJEXT) \ - trg-cell-renderer-wanted.$(OBJEXT) \ - trg-cell-renderer-file-icon.$(OBJEXT) \ - trg-cell-renderer-epoch.$(OBJEXT) \ - trg-cell-renderer-numgteqthan.$(OBJEXT) \ - torrent-cell-renderer.$(OBJEXT) \ - trg-remote-prefs-dialog.$(OBJEXT) \ - trg-torrent-props-dialog.$(OBJEXT) \ - trg-torrent-add-url-dialog.$(OBJEXT) \ - trg-torrent-add-dialog.$(OBJEXT) \ - trg-torrent-move-dialog.$(OBJEXT) \ - trg-preferences-dialog.$(OBJEXT) trg-stats-dialog.$(OBJEXT) \ - trg-about-window.$(OBJEXT) trg-destination-combo.$(OBJEXT) \ - trg-state-selector.$(OBJEXT) trg-general-panel.$(OBJEXT) \ - trg-torrent-graph.$(OBJEXT) trg-icons.$(OBJEXT) \ - icons.$(OBJEXT) trg-toolbar.$(OBJEXT) trg-menu-bar.$(OBJEXT) \ - trg-status-bar.$(OBJEXT) trg-file-parser.$(OBJEXT) \ - trg-json-widgets.$(OBJEXT) trg-model.$(OBJEXT) \ - trg-sortable-filtered-model.$(OBJEXT) trg-files-tree.$(OBJEXT) \ - trg-files-model.$(OBJEXT) trg-files-tree-view-common.$(OBJEXT) \ - trg-files-tree-view.$(OBJEXT) trg-files-model-common.$(OBJEXT) \ - trg-trackers-model.$(OBJEXT) trg-trackers-tree-view.$(OBJEXT) \ - trg-peers-model.$(OBJEXT) trg-peers-tree-view.$(OBJEXT) \ - trg-torrent-model.$(OBJEXT) trg-torrent-tree-view.$(OBJEXT) \ - trg-persistent-tree-view.$(OBJEXT) trg-tree-view.$(OBJEXT) \ - util.$(OBJEXT) hig.$(OBJEXT) bencode.$(OBJEXT) \ - trg-prefs.$(OBJEXT) remote-exec.$(OBJEXT) \ - trg-gtk-app.$(OBJEXT) requests.$(OBJEXT) torrent.$(OBJEXT) \ - session-get.$(OBJEXT) json.$(OBJEXT) trg-client.$(OBJEXT) \ - trg-main-window.$(OBJEXT) main.$(OBJEXT) $(am__objects_1) \ - $(am__objects_2) -transmission_remote_gtk_OBJECTS = \ - $(am_transmission_remote_gtk_OBJECTS) -transmission_remote_gtk_LDADD = $(LDADD) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -transmission_remote_gtk_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(transmission_remote_gtk_LDFLAGS) \ - $(LDFLAGS) -o $@ -AM_V_P = $(am__v_P_@AM_V@) -am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) -am__v_P_0 = false -am__v_P_1 = : -AM_V_GEN = $(am__v_GEN_@AM_V@) -am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) -am__v_GEN_0 = @echo " GEN " $@; -am__v_GEN_1 = -AM_V_at = $(am__v_at_@AM_V@) -am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) -am__v_at_0 = @ -am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(transmission_remote_gtk_SOURCES) -DIST_SOURCES = $(am__transmission_remote_gtk_SOURCES_DIST) -am__can_run_installinfo = \ - case $$AM_UPDATE_INFO_DIR in \ - n|no|NO) false;; \ - *) (install-info --version) >/dev/null 2>&1;; \ - esac -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; -am__install_max = 40 -am__nobase_strip_setup = \ - srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` -am__nobase_strip = \ - for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" -am__nobase_list = $(am__nobase_strip_setup); \ - for p in $$list; do echo "$$p $$p"; done | \ - sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ - $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ - if (++n[$$2] == $(am__install_max)) \ - { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ - END { for (dir in files) print dir, files[dir] }' -am__base_list = \ - sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ - sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -man1dir = $(mandir)/man1 -NROFF = nroff -MANS = $(man_MANS) -DATA = $(desktop_DATA) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ $(am__append_1) -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DLLTOOL = @DLLTOOL@ -DSYMUTIL = @DSYMUTIL@ -DUMPBIN = @DUMPBIN@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -FGREP = @FGREP@ -GEOIP_LIBS = @GEOIP_LIBS@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -LD = @LD@ -LDFLAGS = @LDFLAGS@ $(am__append_2) -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LIPO = @LIPO@ -LN_S = @LN_S@ -LOCALEDIR = @LOCALEDIR@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MANIFEST_TOOL = @MANIFEST_TOOL@ -MKDIR_P = @MKDIR_P@ -MSGFMT = @MSGFMT@ -MSGMERGE = @MSGMERGE@ -NM = @NM@ -NMEDIT = @NMEDIT@ -OBJDUMP = @OBJDUMP@ -OBJEXT = @OBJEXT@ -OTOOL = @OTOOL@ -OTOOL64 = @OTOOL64@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_URL = @PACKAGE_URL@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ -PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ -RANLIB = @RANLIB@ -SED = @SED@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -gio_CFLAGS = @gio_CFLAGS@ -gio_LIBS = @gio_LIBS@ -gthread_CFLAGS = @gthread_CFLAGS@ -gthread_LIBS = @gthread_LIBS@ -gtk_CFLAGS = @gtk_CFLAGS@ -gtk_LIBS = @gtk_LIBS@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -jsonglib_CFLAGS = @jsonglib_CFLAGS@ -jsonglib_LIBS = @jsonglib_LIBS@ -libappindicator_CFLAGS = @libappindicator_CFLAGS@ -libappindicator_LIBS = @libappindicator_LIBS@ -libcurl_CFLAGS = @libcurl_CFLAGS@ -libcurl_LIBS = @libcurl_LIBS@ -libdir = @libdir@ -libexecdir = @libexecdir@ -libproxy_CFLAGS = @libproxy_CFLAGS@ -libproxy_LIBS = @libproxy_LIBS@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -notify_CFLAGS = @notify_CFLAGS@ -notify_LIBS = @notify_LIBS@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_build_prefix = @top_build_prefix@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -trglicense = @trglicense@ -unique_CFLAGS = @unique_CFLAGS@ -unique_LIBS = @unique_LIBS@ -NULL = -public_icons_themes = \ - hicolor \ - $(NULL) - -public_icons = \ - hicolor_apps_scalable_transmission-remote-gtk.svg \ - hicolor_apps_16x16_transmission-remote-gtk.png \ - hicolor_apps_24x24_transmission-remote-gtk.png \ - hicolor_apps_48x48_transmission-remote-gtk.png \ - hicolor_apps_22x22_transmission-remote-gtk.png \ - hicolor_apps_32x32_transmission-remote-gtk.png \ - $(NULL) - -@WIN32_FALSE@EXTRA_DIST = transmission-remote-gtk.desktop.in transmission-remote-gtk.pod -@WIN32_FALSE@CLEANFILES = transmission-remote-gtk.desktop transmission-remote-gtk.1 -@WIN32_FALSE@man_MANS = transmission-remote-gtk.1 -@WIN32_FALSE@desktopdir = $(datadir)/applications -@WIN32_FALSE@desktop_DATA = transmission-remote-gtk.desktop -INCLUDES = -std=c99 -Wall -I.. -Wno-overflow \ - -DTRGLICENSE=\""$(trglicense)"\" $(libcurl_CFLAGS) \ - $(jsonglib_CFLAGS) $(gthread_CFLAGS) $(gtk_CFLAGS) \ - $(gio_CFLAGS) $(unique_CFLAGS) $(notify_CFLAGS) \ - $(libproxy_CFLAGS) $(libappindicator_CFLAGS) $(am__append_4) -transmission_remote_gtk_SOURCES = trg-cell-renderer-speed.c \ - trg-cell-renderer-counter.c trg-cell-renderer-size.c \ - trg-cell-renderer-ratio.c trg-cell-renderer-eta.c \ - trg-cell-renderer-priority.c trg-cell-renderer-wanted.c \ - trg-cell-renderer-file-icon.c trg-cell-renderer-epoch.c \ - trg-cell-renderer-numgteqthan.c torrent-cell-renderer.c \ - trg-remote-prefs-dialog.c trg-torrent-props-dialog.c \ - trg-torrent-add-url-dialog.c trg-torrent-add-dialog.c \ - trg-torrent-move-dialog.c trg-preferences-dialog.c \ - trg-stats-dialog.c trg-about-window.c trg-destination-combo.c \ - trg-state-selector.c trg-general-panel.c trg-torrent-graph.c \ - trg-icons.c icons.c trg-toolbar.c trg-menu-bar.c \ - trg-status-bar.c trg-file-parser.c trg-json-widgets.c \ - trg-model.c trg-sortable-filtered-model.c trg-files-tree.c \ - trg-files-model.c trg-files-tree-view-common.c \ - trg-files-tree-view.c trg-files-model-common.c \ - trg-trackers-model.c trg-trackers-tree-view.c \ - trg-peers-model.c trg-peers-tree-view.c trg-torrent-model.c \ - trg-torrent-tree-view.c trg-persistent-tree-view.c \ - trg-tree-view.c util.c hig.c bencode.c trg-prefs.c \ - remote-exec.c trg-gtk-app.c requests.c torrent.c session-get.c \ - json.c trg-client.c trg-main-window.c main.c $(NULL) \ - $(am__append_3) -transmission_remote_gtk_LDFLAGS = -lm $(jsonglib_LIBS) $(gtk_LIBS) $(gthread_LIBS) $(GEOIP_LIBS) $(gio_LIBS) $(unique_LIBS) $(notify_LIBS) $(libproxy_LIBS) $(libcurl_LIBS) $(libappindicator_LIBS) -gtk_update_icon_cache = gtk-update-icon-cache -f -t -all: all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj .rc -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): -install-binPROGRAMS: $(bin_PROGRAMS) - @$(NORMAL_INSTALL) - @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ - fi; \ - for p in $$list; do echo "$$p $$p"; done | \ - sed 's/$(EXEEXT)$$//' | \ - while read p p1; do if test -f $$p || test -f $$p1; \ - then echo "$$p"; echo "$$p"; else :; fi; \ - done | \ - sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ - -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ - sed 'N;N;N;s,\n, ,g' | \ - $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ - { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ - if ($$2 == $$4) files[d] = files[d] " " $$1; \ - else { print "f", $$3 "/" $$4, $$1; } } \ - END { for (d in files) print "f", d, files[d] }' | \ - while read type dir files; do \ - if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ - test -z "$$files" || { \ - echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ - $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ - } \ - ; done - -uninstall-binPROGRAMS: - @$(NORMAL_UNINSTALL) - @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ - files=`for p in $$list; do echo "$$p"; done | \ - sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ - -e 's/$$/$(EXEEXT)/' `; \ - test -n "$$list" || exit 0; \ - echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(bindir)" && rm -f $$files - -clean-binPROGRAMS: - @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list -transmission-remote-gtk$(EXEEXT): $(transmission_remote_gtk_OBJECTS) $(transmission_remote_gtk_DEPENDENCIES) $(EXTRA_transmission_remote_gtk_DEPENDENCIES) - @rm -f transmission-remote-gtk$(EXEEXT) - $(AM_V_CCLD)$(transmission_remote_gtk_LINK) $(transmission_remote_gtk_OBJECTS) $(transmission_remote_gtk_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bencode.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hig.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icons.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remote-exec.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/requests.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session-get.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torrent-cell-renderer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torrent.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-about-window.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-counter.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-epoch.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-eta.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-file-icon.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-numgteqthan.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-priority.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-ratio.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-size.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-speed.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-cell-renderer-wanted.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-client.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-destination-combo.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-file-parser.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-files-model-common.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-files-model.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-files-tree-view-common.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-files-tree-view.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-files-tree.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-general-panel.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-gtk-app.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-icons.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-json-widgets.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-main-window.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-menu-bar.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-model.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-peers-model.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-peers-tree-view.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-persistent-tree-view.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-preferences-dialog.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-prefs.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-remote-prefs-dialog.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-sortable-filtered-model.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-state-selector.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-stats-dialog.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-status-bar.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-toolbar.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-torrent-add-dialog.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-torrent-add-url-dialog.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-torrent-graph.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-torrent-model.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-torrent-move-dialog.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-torrent-props-dialog.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-torrent-tree-view.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-trackers-model.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-trackers-tree-view.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trg-tree-view.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32-mailslot.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs -install-man1: $(man_MANS) - @$(NORMAL_INSTALL) - @list1=''; \ - list2='$(man_MANS)'; \ - test -n "$(man1dir)" \ - && test -n "`echo $$list1$$list2`" \ - || exit 0; \ - echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ - { for i in $$list1; do echo "$$i"; done; \ - if test -n "$$list2"; then \ - for i in $$list2; do echo "$$i"; done \ - | sed -n '/\.1[a-z]*$$/p'; \ - fi; \ - } | while read p; do \ - if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; echo "$$p"; \ - done | \ - sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ - -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ - sed 'N;N;s,\n, ,g' | { \ - list=; while read file base inst; do \ - if test "$$base" = "$$inst"; then list="$$list $$file"; else \ - echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ - $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ - fi; \ - done; \ - for i in $$list; do echo "$$i"; done | $(am__base_list) | \ - while read files; do \ - test -z "$$files" || { \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ - done; } - -uninstall-man1: - @$(NORMAL_UNINSTALL) - @list=''; test -n "$(man1dir)" || exit 0; \ - files=`{ for i in $$list; do echo "$$i"; done; \ - l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ - sed -n '/\.1[a-z]*$$/p'; \ - } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ - -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ - dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) -install-desktopDATA: $(desktop_DATA) - @$(NORMAL_INSTALL) - @list='$(desktop_DATA)'; test -n "$(desktopdir)" || list=; \ - if test -n "$$list"; then \ - echo " $(MKDIR_P) '$(DESTDIR)$(desktopdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(desktopdir)" || exit 1; \ - fi; \ - for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - echo "$$d$$p"; \ - done | $(am__base_list) | \ - while read files; do \ - echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(desktopdir)'"; \ - $(INSTALL_DATA) $$files "$(DESTDIR)$(desktopdir)" || exit $$?; \ - done - -uninstall-desktopDATA: - @$(NORMAL_UNINSTALL) - @list='$(desktop_DATA)'; test -n "$(desktopdir)" || list=; \ - files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - dir='$(DESTDIR)$(desktopdir)'; $(am__uninstall_files_from_dir) - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - set x; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - shift; \ - if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - if test $$# -gt 0; then \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - "$$@" $$unique; \ - else \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$unique; \ - fi; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - test -z "$(CTAGS_ARGS)$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && $(am__cd) $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) "$$here" - -cscopelist: $(HEADERS) $(SOURCES) $(LISP) - list='$(SOURCES) $(HEADERS) $(LISP)'; \ - case "$(srcdir)" in \ - [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ - *) sdir=$(subdir)/$(srcdir) ;; \ - esac; \ - for i in $$list; do \ - if test -f "$$i"; then \ - echo "$(subdir)/$$i"; \ - else \ - echo "$$sdir/$$i"; \ - fi; \ - done >> $(top_builddir)/cscope.files - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - @list='$(MANS)'; if test -n "$$list"; then \ - list=`for p in $$list; do \ - if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ - if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ - if test -n "$$list" && \ - grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ - echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \ - grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ - echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ - echo " typically 'make maintainer-clean' will remove them" >&2; \ - exit 1; \ - else :; fi; \ - else :; fi - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(PROGRAMS) $(MANS) $(DATA) -installdirs: - for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(desktopdir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - if test -z '$(STRIP)'; then \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - install; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ - fi -mostlyclean-generic: - -clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: install-data-local install-desktopDATA install-man - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: install-binPROGRAMS - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: install-man1 - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-binPROGRAMS uninstall-desktopDATA \ - uninstall-man - -uninstall-man: uninstall-man1 - -.MAKE: install-am install-strip - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ - clean-generic clean-libtool cscopelist ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-binPROGRAMS install-data \ - install-data-am install-data-local install-desktopDATA \ - install-dvi install-dvi-am install-exec install-exec-am \ - install-html install-html-am install-info install-info-am \ - install-man install-man1 install-pdf install-pdf-am install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ - uninstall-am uninstall-binPROGRAMS uninstall-desktopDATA \ - uninstall-man uninstall-man1 - - -@WIN32_TRUE@.rc.o: -@WIN32_TRUE@ windres $^ -o $@ -@WIN32_TRUE@%.o : %.rc -@WIN32_TRUE@ windres $^ -o $@ -@WIN32_FALSE@%.1: %.pod -@WIN32_FALSE@ pod2man --release="" --center="Transmission Remote GTK" $< > $@ - -install-data-local: install-icons update-icon-cache - -update-icon-cache: - @-if test -z "$(DESTDIR)"; then \ - echo "Updating Gtk icon cache."; \ - for theme in $(public_icons_themes); do \ - $(gtk_update_icon_cache) $(datadir)/icons/$$theme; \ - done; \ - else \ - echo "*** Icon cache not updated. After (un)install, run this:"; \ - for theme in $(public_icons_themes); do \ - echo "*** $(gtk_update_icon_cache) $(datadir)/icons/$$theme"; \ - done; \ - fi - -install-icons: - for icon in $(public_icons); do \ - THEME=`echo $$icon | cut -d_ -f1`; \ - CONTEXT=`echo $$icon | cut -d_ -f2`; \ - SIZE=`echo $$icon | cut -d_ -f3`; \ - ICONFILE=`echo $$icon | cut -d_ -f4`; \ - mkdir -p $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT; \ - $(INSTALL_DATA) $(srcdir)/$$icon $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \ - done; \ - for icon in $(private_icons); do \ - THEME=`echo $$icon | cut -d_ -f1`; \ - CONTEXT=`echo $$icon | cut -d_ -f2`; \ - SIZE=`echo $$icon | cut -d_ -f3`; \ - ICONFILE=`echo $$icon | cut -d_ -f4`; \ - mkdir -p $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT; \ - $(INSTALL_DATA) $(srcdir)/$$icon $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \ - done - -transmission-remote-gtk.desktop: transmission-remote-gtk.desktop.in - sed -e 's,@bindir\@,$(bindir),g' <transmission-remote-gtk.desktop.in > $@ - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/bencode.c b/src/bencode.c index 89f35ed..476baeb 100644 --- a/src/bencode.c +++ b/src/bencode.c @@ -24,6 +24,10 @@ * into the public domain as well). */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> /* malloc() realloc() free() strtoll() */ #include <string.h> /* memset() */ #include <ctype.h> diff --git a/src/hicolor_apps_16x16_transmission-remote-gtk.png b/src/hicolor_apps_16x16_transmission-remote-gtk.png Binary files differdeleted file mode 100644 index 78b1af2..0000000 --- a/src/hicolor_apps_16x16_transmission-remote-gtk.png +++ /dev/null diff --git a/src/hicolor_apps_22x22_transmission-remote-gtk.png b/src/hicolor_apps_22x22_transmission-remote-gtk.png Binary files differdeleted file mode 100644 index 3283ea2..0000000 --- a/src/hicolor_apps_22x22_transmission-remote-gtk.png +++ /dev/null diff --git a/src/hicolor_apps_24x24_transmission-remote-gtk.png b/src/hicolor_apps_24x24_transmission-remote-gtk.png Binary files differdeleted file mode 100644 index 6200ec0..0000000 --- a/src/hicolor_apps_24x24_transmission-remote-gtk.png +++ /dev/null diff --git a/src/hicolor_apps_32x32_transmission-remote-gtk.png b/src/hicolor_apps_32x32_transmission-remote-gtk.png Binary files differdeleted file mode 100644 index d3d6464..0000000 --- a/src/hicolor_apps_32x32_transmission-remote-gtk.png +++ /dev/null diff --git a/src/hicolor_apps_48x48_transmission-remote-gtk.png b/src/hicolor_apps_48x48_transmission-remote-gtk.png Binary files differdeleted file mode 100644 index 3444de8..0000000 --- a/src/hicolor_apps_48x48_transmission-remote-gtk.png +++ /dev/null diff --git a/src/hicolor_apps_scalable_transmission-remote-gtk.svg b/src/hicolor_apps_scalable_transmission-remote-gtk.svg deleted file mode 100644 index e9c4cec..0000000 --- a/src/hicolor_apps_scalable_transmission-remote-gtk.svg +++ /dev/null @@ -1,445 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="48px" - height="48px" - id="svg5186" - sodipodi:version="0.32" - inkscape:version="0.45+devel" - sodipodi:docname="transmission.svg" - inkscape:output_extension="org.inkscape.output.svg.inkscape" - inkscape:export-filename="/home/andreas/project/application icons/48x48/transmission.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> - <defs - id="defs5188"> - <linearGradient - inkscape:collect="always" - id="linearGradient9795"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop9797" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop9799" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient9783"> - <stop - style="stop-color:#000000;stop-opacity:1;" - offset="0" - id="stop9785" /> - <stop - style="stop-color:#000000;stop-opacity:0;" - offset="1" - id="stop9787" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient9775"> - <stop - style="stop-color:#f9f9f9;stop-opacity:1" - offset="0" - id="stop9777" /> - <stop - style="stop-color:#eeeeec;stop-opacity:0.62037037" - offset="1" - id="stop9779" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5948"> - <stop - style="stop-color:#787b76;stop-opacity:1;" - offset="0" - id="stop5950" /> - <stop - id="stop5956" - offset="0.87125719" - style="stop-color:#babcb9;stop-opacity:1" /> - <stop - style="stop-color:#787b76;stop-opacity:1" - offset="1" - id="stop5952" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5908"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop5910" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop5912" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5898"> - <stop - style="stop-color:#cc0000;stop-opacity:1;" - offset="0" - id="stop5900" /> - <stop - id="stop5906" - offset="0.36509839" - style="stop-color:#ef0000;stop-opacity:1" /> - <stop - style="stop-color:#aa0000;stop-opacity:1" - offset="1" - id="stop5902" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5871"> - <stop - style="stop-color:#f0f2ef;stop-opacity:1" - offset="0" - id="stop5873" /> - <stop - style="stop-color:#cdd1c8;stop-opacity:1" - offset="1" - id="stop5875" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5843"> - <stop - style="stop-color:#888a85;stop-opacity:1" - offset="0" - id="stop5845" /> - <stop - style="stop-color:#2e3436;stop-opacity:1" - offset="1" - id="stop5847" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5835"> - <stop - style="stop-color:#555753;stop-opacity:1;" - offset="0" - id="stop5837" /> - <stop - style="stop-color:#2e3436;stop-opacity:1" - offset="1" - id="stop5839" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5823"> - <stop - style="stop-color:#2e3436;stop-opacity:1;" - offset="0" - id="stop5825" /> - <stop - style="stop-color:#2e3436;stop-opacity:0;" - offset="1" - id="stop5827" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5234"> - <stop - style="stop-color:#babdb6;stop-opacity:1;" - offset="0" - id="stop5236" /> - <stop - id="stop5242" - offset="0.13299191" - style="stop-color:#eeeeec;stop-opacity:1" /> - <stop - style="stop-color:#babdb6;stop-opacity:1" - offset="1" - id="stop5238" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5234" - id="linearGradient5240" - x1="23.738585" - y1="4.156569" - x2="23.738585" - y2="19.46567" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5823" - id="linearGradient5829" - x1="23.732271" - y1="30.057167" - x2="23.688078" - y2="22.632544" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5835" - id="linearGradient5841" - x1="23.9375" - y1="30.616879" - x2="23.9375" - y2="36.357994" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5843" - id="linearGradient5849" - x1="20.771132" - y1="32.248005" - x2="20.563131" - y2="23.939499" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5898" - id="linearGradient5904" - x1="14.8125" - y1="5.6244211" - x2="14.8125" - y2="9" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5908" - id="linearGradient5914" - x1="24.040522" - y1="5.0690055" - x2="24.040522" - y2="10.0086" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5871" - id="linearGradient5928" - x1="13.625" - y1="33.125" - x2="14.125" - y2="24" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5948" - id="linearGradient5954" - x1="10.1875" - y1="20.25" - x2="10.1875" - y2="42.5" - gradientUnits="userSpaceOnUse" /> - <filter - inkscape:collect="always" - id="filter9771" - x="-0.02976581" - width="1.0595316" - y="-0.13995509" - height="1.2799102"> - <feGaussianBlur - inkscape:collect="always" - stdDeviation="0.5196773" - id="feGaussianBlur9773" /> - </filter> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient9775" - id="linearGradient9781" - x1="24.71875" - y1="35.958694" - x2="23.936657" - y2="17.070877" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient9783" - id="linearGradient9789" - x1="18.3125" - y1="20.743757" - x2="18.3125" - y2="21.814325" - gradientUnits="userSpaceOnUse" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient9795" - id="linearGradient9801" - x1="30.4375" - y1="31.82852" - x2="29.742416" - y2="27.45352" - gradientUnits="userSpaceOnUse" /> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="5.6568542" - inkscape:cx="30.372474" - inkscape:cy="21.423534" - inkscape:current-layer="layer1" - showgrid="true" - inkscape:grid-bbox="true" - inkscape:document-units="px" - inkscape:window-width="1091" - inkscape:window-height="777" - inkscape:window-x="557" - inkscape:window-y="164"> - <inkscape:grid - type="xygrid" - id="grid5195" /> - </sodipodi:namedview> - <metadata - id="metadata5191"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <g - id="layer1" - inkscape:label="Layer 1" - inkscape:groupmode="layer"> - <rect - style="opacity:0.28240741;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter9771)" - id="rect9761" - width="41.901279" - height="8.9116125" - x="3" - y="39" - rx="2.2980971" - ry="2.2980971" /> - <path - style="fill:url(#linearGradient5954);fill-rule:evenodd;stroke:#555753;stroke-width:1.00000011999999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" - d="M 10,16.59375 C 8.8196081,16.548814 7.6402135,17.571722 7.53125,18.8125 C 6.643292,26.100083 5.3269606,33.403527 4.65625,40.6875 L 4.65625,43.75 C 4.6900093,45.329492 5.7271791,46.392039 6.875,46.59375 L 41.5,46.59375 C 42.479024,46.569246 43.565009,45.89005 43.53125,44.59375 L 43.53125,40.65625 L 40.40625,19.4375 C 40.152431,18.135677 39.039534,16.752716 37.5,16.59375 L 10,16.59375 z" - id="path5232" - sodipodi:nodetypes="ccccccccccc" /> - <path - style="fill:url(#linearGradient5928);fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:0.99999994000000003px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="M 10.601853,39.624614 C 9.47224,39.502143 8.6733861,38.760954 8.7014295,37.401046 L 10.601853,21.407733 C 10.893931,20.339398 11.586949,19.485349 12.680909,19.488442 L 34.605501,19.488442 C 35.691818,19.455762 36.778134,20.208796 37.062569,21.104687 L 39.478435,37.237611 C 39.535481,38.706714 38.931012,39.557098 37.913093,39.523599 L 10.601853,39.624614 z" - id="path5230" - sodipodi:nodetypes="ccccccccc" /> - <path - style="fill:url(#linearGradient5841);fill-rule:evenodd;stroke:url(#linearGradient5849);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" - d="M 20.46875,20.4375 L 18.40625,32.46875 L 15.4375,32.46875 L 23.46875,37.625 L 32.4375,32.46875 L 29.46875,32.46875 L 27.59375,20.4375 L 20.46875,20.4375 z" - id="path5197" - sodipodi:nodetypes="cccccccc" /> - <rect - style="opacity:1;fill:url(#linearGradient5904);fill-opacity:1;stroke:#930000;stroke-width:1.00000011999999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect5224" - width="31.113209" - height="6.0609155" - x="8.4847708" - y="4.5135489" - rx="5.0159144" - ry="1.9854566" /> - <rect - style="opacity:0.58333333;fill:none;fill-opacity:1;stroke:url(#linearGradient5914);stroke-width:1.00000011999999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect5896" - width="29.080278" - height="3.9395947" - x="9.5003824" - y="5.5690055" - rx="1.8339339" - ry="1.2783499" /> - <path - style="opacity:0.24537036000000001;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient9781);stroke-width:1.00000011999999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="M 10.592965,17.57221 C 9.474152,17.53019 8.3562869,18.486727 8.2530054,19.647002 L 5.4687498,39.722803 C 5.4796612,39.847886 5.4997885,39.979699 5.5279893,40.102694 L 5.5279893,42.966491 C 5.559989,44.443503 6.5430497,45.407885 7.6309909,45.596509 L 40.479283,45.596509 C 41.407232,45.573597 42.406944,44.967688 42.374947,43.755497 L 42.374947,40.073472 C 42.382229,40.044972 42.398547,40.013922 42.404566,39.985805 L 42.374947,39.781247 L 42.374947,39.576691 L 42.345327,39.576691 L 39.442592,20.202228 C 39.202015,18.98487 38.147175,17.72086 36.687956,17.57221 L 10.592965,17.57221 z" - id="path5881" /> - <path - style="fill:url(#linearGradient9789);fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1;opacity:0.20833333000000001" - d="M 10.210155,29.955767 L 12.048004,22 L 36.07815,22.05802 L 37.857941,31.044156 L 36.681164,21.969631 C 36.460193,20.967897 35.929863,20 34.957591,20.025088 L 13.037281,19.980893 C 11.606886,19.936699 11.32554,20.864777 11,21.969631 L 10.210155,29.955767 z" - id="path5926" - sodipodi:nodetypes="ccccccccc" /> - <rect - style="opacity:1;fill:url(#linearGradient5240);fill-opacity:1;stroke:#888a85;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect5226" - width="7.0964494" - height="25.970053" - x="20.48369" - y="3.6044116" - rx="1.0763195" - ry="1.0763192" /> - <rect - style="opacity:1;fill:url(#linearGradient5829);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect5244" - width="8.1317272" - height="8.0433397" - x="19.975765" - y="22.013826" - rx="1.0763195" - ry="1.0763192" /> - <path - style="opacity:0.43518521;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" - d="M 11.423372,41.486321 L 39.533811,41.486321" - id="path5879" - sodipodi:nodetypes="cc" /> - <rect - style="opacity:0.22685185;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect5892" - width="5.151906" - height="23.93712" - x="21.428234" - y="4.6321397" - rx="1.0763195" - ry="1.0763192" /> - <g - id="g5972" - style="opacity:0.62037037"> - <path - sodipodi:nodetypes="cc" - id="path5831" - d="M 20.4375,30.5 L 27.5,30.5" - style="fill:none;fill-rule:evenodd;stroke:#888a85;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;opacity:1" /> - <path - sodipodi:nodetypes="cc" - id="path5833" - d="M 19.960998,32.5 L 27.976504,32.5" - style="fill:none;fill-rule:evenodd;stroke:#888a85;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;opacity:0.68055556" /> - <path - sodipodi:nodetypes="cc" - id="path5958" - d="M 20.273498,31.5 L 27.726504,31.5" - style="fill:none;fill-rule:evenodd;stroke:#5d5d5c;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;opacity:1" /> - <path - sodipodi:nodetypes="cc" - id="path5960" - d="M 19.869986,33.488738 L 28.141277,33.488738" - style="fill:none;fill-rule:evenodd;stroke:#5d5d5c;stroke-width:0.99999994000000003px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;opacity:0.68055556" /> - </g> - <path - style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" - d="M 14.381412,31.513733 L 17.519198,31.513733" - id="path9791" - sodipodi:nodetypes="cc" /> - <path - style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" - d="M 30.443912,31.451233 L 33.581698,31.451233" - id="path9803" - sodipodi:nodetypes="cc" /> - <path - sodipodi:type="arc" - style="opacity:0.33500001;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="path5119" - sodipodi:cx="9.8553009" - sodipodi:cy="42.188465" - sodipodi:rx="1.1932427" - sodipodi:ry="1.0827572" - d="M 11.048544,42.188465 A 1.1932427,1.0827572 0 1 1 8.6620582,42.188465 A 1.1932427,1.0827572 0 1 1 11.048544,42.188465 z" - transform="matrix(0.4216252,0,0,0.4766032,5.3634688,21.39228)" /> - </g> -</svg> @@ -1,213 +1,173 @@ /* - * This file Copyright (C) 2007-2010 Mnemosyne LLC + * This file Copyright (C) Mnemosyne LLC * - * This file is licensed by the GPL version 2. Works owned by the - * Transmission project are granted a special exemption to clause 2(b) + * This file is licensed by the GPL version 2. Works owned by the + * Transmission project are granted a special exemption to clause 2 (b) * so that the bulk of its code can remain under the MIT license. * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: hig.c 9868 2010-01-04 21:00:47Z charles $ + * $Id: hig.c 13677 2012-12-16 22:51:29Z jordan $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <gtk/gtk.h> #include "hig.h" -#include "util.h" -GtkWidget *hig_workarea_create(void) +GtkWidget* +hig_workarea_create (void) { - GtkWidget *t = gtk_table_new(1, 2, FALSE); + GtkWidget * grid = gtk_grid_new (); + + gtk_container_set_border_width (GTK_CONTAINER (grid), GUI_PAD_BIG); + gtk_grid_set_row_spacing (GTK_GRID (grid), GUI_PAD); + gtk_grid_set_column_spacing (GTK_GRID (grid), GUI_PAD_BIG); - gtk_container_set_border_width(GTK_CONTAINER(t), GUI_PAD_BIG); - gtk_table_set_col_spacing(GTK_TABLE(t), 0, GUI_PAD_BIG); - gtk_table_set_row_spacings(GTK_TABLE(t), GUI_PAD); - return t; + return grid; } -void hig_workarea_add_section_divider(GtkWidget * t, guint * row) +void +hig_workarea_add_section_divider (GtkWidget * t, guint * row) { - GtkWidget *w = gtk_alignment_new(0.0f, 0.0f, 0.0f, 0.0f); + GtkWidget * w = gtk_alignment_new (0.0f, 0.0f, 0.0f, 0.0f); - gtk_widget_set_size_request(w, 0u, 6u); - gtk_table_attach(GTK_TABLE(t), w, 0, 2, *row, *row + 1, 0, 0, 0, 0); - ++*row; + gtk_widget_set_size_request (w, 0u, 6u); + gtk_grid_attach (GTK_GRID (t), w, 0, *row, 2, 1); + ++ * row; } void -hig_workarea_add_section_title_widget(GtkWidget * t, guint * row, - GtkWidget * w) +hig_workarea_add_section_title_widget (GtkWidget * t, guint * row, GtkWidget * w) { - gtk_table_attach(GTK_TABLE(t), w, 0, 2, *row, *row + 1, ~0, 0, 0, 0); - ++*row; + gtk_widget_set_hexpand (w, TRUE); + gtk_grid_attach (GTK_GRID (t), w, 0, *row, 2, 1); + ++ * row; } void -hig_workarea_add_section_title(GtkWidget * t, - guint * row, const char *section_title) +hig_workarea_add_section_title (GtkWidget * t, guint * row, const char * section_title) { char buf[512]; - GtkWidget *l; - - g_snprintf(buf, sizeof(buf), "<b>%s</b>", section_title); - l = gtk_label_new(buf); - gtk_misc_set_alignment(GTK_MISC(l), 0.0f, 0.5f); - gtk_label_set_use_markup(GTK_LABEL(l), TRUE); - hig_workarea_add_section_title_widget(t, row, l); -} + GtkWidget * l; -static GtkWidget *rowNew(GtkWidget * w) -{ - GtkWidget *a; - GtkWidget *h = trg_hbox_new(FALSE, 0); - - /* spacer */ - a = gtk_alignment_new(0.0f, 0.0f, 0.0f, 0.0f); - gtk_widget_set_size_request(a, 18u, 0u); - gtk_box_pack_start(GTK_BOX(h), a, FALSE, FALSE, 0); - - /* lhs widget */ - if (GTK_IS_MISC(w)) - gtk_misc_set_alignment(GTK_MISC(w), 0.0f, 0.5f); - if (GTK_IS_LABEL(w)) - gtk_label_set_use_markup(GTK_LABEL(w), TRUE); - gtk_box_pack_start(GTK_BOX(h), w, TRUE, TRUE, 0); - - return h; + g_snprintf (buf, sizeof (buf), "<b>%s</b>", section_title); + l = gtk_label_new (buf); + gtk_misc_set_alignment (GTK_MISC (l), 0.0f, 0.5f); + gtk_label_set_use_markup (GTK_LABEL (l), TRUE); + hig_workarea_add_section_title_widget (t, row, l); } -void hig_workarea_add_wide_control(GtkWidget * t, guint * row, - GtkWidget * w) +void +hig_workarea_add_wide_control (GtkWidget * t, guint * row, GtkWidget * w) { - GtkWidget *r = rowNew(w); - - gtk_table_attach(GTK_TABLE(t), r, 0, 2, *row, *row + 1, GTK_FILL, - 0, 0, 0); - ++*row; + gtk_widget_set_hexpand (w, TRUE); + gtk_widget_set_margin_left (w, 18); + gtk_grid_attach (GTK_GRID (t), w, 0, *row, 2, 1); + ++ * row; } - void -hig_workarea_add_wide_tall_control(GtkWidget * t, guint * row, - GtkWidget * w) +hig_workarea_add_wide_tall_control (GtkWidget * t, guint * row, GtkWidget * w) { - GtkWidget *r = rowNew(w); - - gtk_table_attach(GTK_TABLE(t), r, 0, 2, *row, *row + 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); - - ++*row; + gtk_widget_set_hexpand (w, TRUE); + gtk_widget_set_vexpand (w, TRUE); + hig_workarea_add_wide_control (t, row, w); } -GtkWidget *hig_workarea_add_wide_checkbutton(GtkWidget * t, - guint * row, - const char *mnemonic_string, - gboolean is_active) +GtkWidget * +hig_workarea_add_wide_checkbutton (GtkWidget * t, + guint * row, + const char * mnemonic_string, + gboolean is_active) { - GtkWidget *w = gtk_check_button_new_with_mnemonic(mnemonic_string); + GtkWidget * w = gtk_check_button_new_with_mnemonic (mnemonic_string); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), is_active); - hig_workarea_add_wide_control(t, row, w); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w), is_active); + hig_workarea_add_wide_control (t, row, w); return w; } -void hig_workarea_add_label_w(GtkWidget * t, guint row, GtkWidget * l) +void +hig_workarea_add_label_w (GtkWidget * t, guint row, GtkWidget * w) { - GtkWidget *w = rowNew(l); - - gtk_table_attach(GTK_TABLE(t), w, 0, 1, row, row + 1, GTK_FILL, - GTK_FILL, 0, 0); -} - -GtkWidget *hig_workarea_add_label(GtkWidget * t, guint row, - const char *mnemonic_string) -{ - GtkWidget *l = gtk_label_new_with_mnemonic(mnemonic_string); - - hig_workarea_add_label_w(t, row, l); - return l; + gtk_widget_set_margin_left (w, 18); + if (GTK_IS_MISC (w)) + gtk_misc_set_alignment (GTK_MISC (w), 0.0f, 0.5f); + if (GTK_IS_LABEL (w)) + gtk_label_set_use_markup (GTK_LABEL (w), TRUE); + gtk_grid_attach (GTK_GRID (t), w, 0, row, 1, 1); } static void -hig_workarea_add_tall_control(GtkWidget * t, guint row, - GtkWidget * control) +hig_workarea_add_tall_control (GtkWidget * t, guint row, GtkWidget * control) { - if (GTK_IS_MISC(control)) - gtk_misc_set_alignment(GTK_MISC(control), 0.0f, 0.5f); + if (GTK_IS_MISC (control)) + gtk_misc_set_alignment (GTK_MISC (control), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(t), control, - 1, 2, row, row + 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0); + g_object_set (control, "expand", TRUE, NULL); + gtk_grid_attach (GTK_GRID (t), control, 1, row, 1, 1); } -void hig_workarea_add_control(GtkWidget * t, guint row, - GtkWidget * control) +static void +hig_workarea_add_control (GtkWidget * t, guint row, GtkWidget * control) { - if (GTK_IS_MISC(control)) - gtk_misc_set_alignment(GTK_MISC(control), 0.0f, 0.5f); + if (GTK_IS_MISC (control)) + gtk_misc_set_alignment (GTK_MISC (control), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(t), control, - 1, 2, row, row + 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0, 0); + gtk_widget_set_hexpand (control, TRUE); + gtk_grid_attach (GTK_GRID (t), control, 1, row, 1, 1); } void -hig_workarea_add_row_w(GtkWidget * t, - guint * row, - GtkWidget * label, - GtkWidget * control, GtkWidget * mnemonic) -{ - hig_workarea_add_label_w(t, *row, label); - hig_workarea_add_control(t, *row, control); - if (GTK_IS_LABEL(label)) - gtk_label_set_mnemonic_widget(GTK_LABEL(label), - mnemonic ? mnemonic : control); - ++*row; -} - -GtkWidget *hig_workarea_add_row(GtkWidget * t, - guint * row, - const char *mnemonic_string, - GtkWidget * control, GtkWidget * mnemonic) -{ - GtkWidget *l = gtk_label_new_with_mnemonic(mnemonic_string); - - hig_workarea_add_row_w(t, row, l, control, mnemonic); +hig_workarea_add_row_w (GtkWidget * t, + guint * row, + GtkWidget * label, + GtkWidget * control, + GtkWidget * mnemonic) +{ + hig_workarea_add_label_w (t, *row, label); + hig_workarea_add_control (t, *row, control); + if (GTK_IS_LABEL (label)) + gtk_label_set_mnemonic_widget (GTK_LABEL (label), + mnemonic ? mnemonic : control); + ++ * row; +} + +GtkWidget* +hig_workarea_add_row (GtkWidget * t, + guint * row, + const char * mnemonic_string, + GtkWidget * control, + GtkWidget * mnemonic) +{ + GtkWidget * l = gtk_label_new_with_mnemonic (mnemonic_string); + + hig_workarea_add_row_w (t, row, l, control, mnemonic); return l; } -GtkWidget *hig_workarea_add_tall_row(GtkWidget * table, - guint * row, - const char *mnemonic_string, - GtkWidget * control, - GtkWidget * mnemonic) +GtkWidget* +hig_workarea_add_tall_row (GtkWidget * table, + guint * row, + const char * mnemonic_string, + GtkWidget * control, + GtkWidget * mnemonic) { - GtkWidget *l = gtk_label_new_with_mnemonic(mnemonic_string); - GtkWidget *h = trg_hbox_new(FALSE, 0); - GtkWidget *v = trg_vbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(h), l, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(v), h, FALSE, FALSE, GUI_PAD_SMALL); + GtkWidget * l = gtk_label_new_with_mnemonic (mnemonic_string); + GtkWidget * h = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + GtkWidget * v = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_box_pack_start (GTK_BOX (h), l, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (v), h, FALSE, FALSE, GUI_PAD_SMALL); - hig_workarea_add_label_w(table, *row, v); - hig_workarea_add_tall_control(table, *row, control); + hig_workarea_add_label_w (table, *row, v); + hig_workarea_add_tall_control (table, *row, control); - if (GTK_IS_LABEL(l)) - gtk_label_set_mnemonic_widget(GTK_LABEL(l), - mnemonic ? mnemonic : control); + if (GTK_IS_LABEL (l)) + gtk_label_set_mnemonic_widget (GTK_LABEL (l), + mnemonic ? mnemonic : control); - ++*row; + ++ * row; return l; } - -void hig_workarea_finish(GtkWidget * t, guint * row) -{ - gtk_table_resize(GTK_TABLE(t), *row, 2); -} - -void -hig_message_dialog_set_text(GtkMessageDialog * dialog, - const char *primary, const char *secondary) -{ - gtk_message_dialog_set_markup(dialog, primary); - gtk_message_dialog_format_secondary_text(dialog, "%s", secondary); -} @@ -1,17 +1,17 @@ /* - * This file Copyright (C) 2007-2010 Mnemosyne LLC + * This file Copyright (C) Mnemosyne LLC * - * This file is licensed by the GPL version 2. Works owned by the - * Transmission project are granted a special exemption to clause 2(b) + * This file is licensed by the GPL version 2. Works owned by the + * Transmission project are granted a special exemption to clause 2 (b) * so that the bulk of its code can remain under the MIT license. * This exemption does not extend to derived works not owned by * the Transmission project. * - * $Id: hig.h 9868 2010-01-04 21:00:47Z charles $ + * $Id: hig.h 13625 2012-12-05 17:29:46Z jordan $ */ -#ifndef __HIG_H__ -#define __HIG_H__ +#ifndef GTR_HIG_H +#define GTR_HIG_H #include <gtk/gtk.h> @@ -20,67 +20,60 @@ *** see section 8.2.2, Visual Design > Window Layout > Dialogs. **/ -GtkWidget *hig_workarea_create(void); +GtkWidget* hig_workarea_create (void); -void hig_workarea_add_section_divider(GtkWidget * table, guint * row); +void hig_workarea_add_section_divider (GtkWidget * table, + guint * row); -void hig_workarea_add_section_title_widget(GtkWidget * t, - guint * row, GtkWidget * w); +void hig_workarea_add_section_title_widget (GtkWidget * t, + guint * row, + GtkWidget * w); -void hig_workarea_add_section_title(GtkWidget * table, - guint * row, - const char *section_title); +void hig_workarea_add_section_title (GtkWidget * table, + guint * row, + const char * section_title); -void hig_workarea_add_wide_tall_control(GtkWidget * table, - guint * row, GtkWidget * w); +void hig_workarea_add_wide_tall_control (GtkWidget * table, + guint * row, + GtkWidget * w); -void hig_workarea_add_wide_control(GtkWidget * table, - guint * row, GtkWidget * w); +void hig_workarea_add_wide_control (GtkWidget * table, + guint * row, + GtkWidget * w); -GtkWidget *hig_workarea_add_wide_checkbutton(GtkWidget * table, - guint * row, - const char *mnemonic_string, - gboolean is_active); +GtkWidget* hig_workarea_add_wide_checkbutton (GtkWidget * table, + guint * row, + const char * mnemonic_string, + gboolean is_active); -GtkWidget *hig_workarea_add_label(GtkWidget * table, - guint row, const char *mnemonic_string); +void hig_workarea_add_label_w (GtkWidget * table, + guint row, + GtkWidget * label_widget); -void hig_workarea_add_label_w(GtkWidget * table, - guint row, GtkWidget * label_widget); +GtkWidget* hig_workarea_add_tall_row (GtkWidget * table, + guint * row, + const char * mnemonic_string, + GtkWidget * control, + GtkWidget * mnemonic_or_null_for_control); -void hig_workarea_add_control(GtkWidget * table, - guint row, GtkWidget * control); +GtkWidget* hig_workarea_add_row (GtkWidget * table, + guint * row, + const char * mnemonic_string, + GtkWidget * control, + GtkWidget * mnemonic_or_null_for_control); -GtkWidget *hig_workarea_add_tall_row(GtkWidget * table, - guint * row, - const char *mnemonic_string, - GtkWidget * control, - GtkWidget * - mnemonic_or_null_for_control); +void hig_workarea_add_row_w (GtkWidget * table, + guint * row, + GtkWidget * label, + GtkWidget * control, + GtkWidget * mnemonic_or_null_for_control); -GtkWidget *hig_workarea_add_row(GtkWidget * table, - guint * row, - const char *mnemonic_string, - GtkWidget * control, - GtkWidget * mnemonic_or_null_for_control); - -void hig_workarea_add_row_w(GtkWidget * table, - guint * row, - GtkWidget * label, - GtkWidget * control, - GtkWidget * mnemonic_or_null_for_control); - -void hig_workarea_finish(GtkWidget * table, guint * row); - -void hig_message_dialog_set_text(GtkMessageDialog * dialog, - const char *primary, - const char *secondary); - -enum { +enum +{ GUI_PAD_SMALL = 3, GUI_PAD = 6, GUI_PAD_BIG = 12, GUI_PAD_LARGE = 12 }; -#endif /* __HIG_H__ */ +#endif /* GTR_HIG_H */ diff --git a/src/icons.c b/src/icons.c index bb8e33d..8275961 100644 --- a/src/icons.c +++ b/src/icons.c @@ -6,6 +6,10 @@ * $Id: icons.c 12639 2011-08-07 18:41:13Z jordan $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <string.h> /* strcmp */ #include <glib.h> #include <gtk/gtk.h> @@ -17,12 +17,15 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib-object.h> #include <glib/gprintf.h> #include <json-glib/json-glib.h> #include <gtk/gtk.h> -#include "config.h" #include "protocol-constants.h" #include "requests.h" #include "json.h" @@ -100,7 +103,7 @@ gdouble json_double_to_progress(JsonNode * n) gdouble json_node_really_get_double(JsonNode * node) { - GValue a = { 0 }; + GValue a = G_VALUE_INIT; json_node_get_value(node, &a); switch (G_VALUE_TYPE(&a)) { @@ -32,11 +32,8 @@ #include <json-glib/json-glib.h> #include <fontconfig/fontconfig.h> -#if !GTK_CHECK_VERSION( 3, 0, 0 ) && HAVE_LIBUNIQUE -#include <unique/unique.h> -#elif GTK_CHECK_VERSION( 3, 0, 0 ) #include "trg-gtk-app.h" -#elif WIN32 +#if WIN32 #include "win32-mailslot.h" #endif @@ -44,105 +41,16 @@ #include "trg-client.h" #include "util.h" -/* Handle arguments and start the main window. Unfortunately, there's three - * different ways to achieve a unique instance and pass arguments around. :( +/* Handle arguments and start the main window. * - * 1) libunique - GTK2 (non-win32). deprecated in GTK3 for GtkApplication. - * 2) GtkApplication - replaces libunique, GTK3 only, and non-win32. - * 3) win32 API mailslots. - */ - -/* - * libunique. + * either GtkApplication - replaces libunique, GTK3 only, and non-win32. + * or win32 API mailslots. + * + * win32 could possibly run from GtkApplication now, mailslots were needed + * for GTK2 (support removed). */ -#if !GTK_CHECK_VERSION( 3, 0, 0 ) && HAVE_LIBUNIQUE - -enum { - COMMAND_0, - COMMAND_ADD -}; - -static UniqueResponse -message_received_cb(UniqueApp * app G_GNUC_UNUSED, - gint command, - UniqueMessageData * message, - guint time_, gpointer user_data) -{ - TrgMainWindow *win; - UniqueResponse res; - gchar **uris; - - win = TRG_MAIN_WINDOW(user_data); - - switch (command) { - case UNIQUE_ACTIVATE: - gtk_window_set_screen(GTK_WINDOW(user_data), - unique_message_data_get_screen(message)); - gtk_window_present_with_time(GTK_WINDOW(user_data), time_); - res = UNIQUE_RESPONSE_OK; - break; - case COMMAND_ADD: - uris = unique_message_data_get_uris(message); - res = - trg_add_from_filename(win, - uris) ? UNIQUE_RESPONSE_OK : - UNIQUE_RESPONSE_FAIL; - break; - default: - res = UNIQUE_RESPONSE_OK; - break; - } - - return res; -} - -static gint -trg_libunique_init(TrgClient * client, int argc, - gchar * argv[], gchar ** args) -{ - UniqueApp *app = unique_app_new_with_commands("uk.org.eth0.trg", NULL, - "add", COMMAND_ADD, - NULL); - TrgMainWindow *window; - - if (unique_app_is_running(app)) { - UniqueCommand command; - UniqueResponse response; - UniqueMessageData *message; - - if (args) { - command = COMMAND_ADD; - message = unique_message_data_new(); - unique_message_data_set_uris(message, args); - g_strfreev(args); - } else { - command = UNIQUE_ACTIVATE; - message = NULL; - } - - response = unique_app_send_message(app, command, message); - unique_message_data_free(message); - - if (response != UNIQUE_RESPONSE_OK) - return EXIT_FAILURE; - } else { - window = - trg_main_window_new(client, should_be_minimised(argc, argv)); - g_signal_connect(app, "message-received", - G_CALLBACK(message_received_cb), window); - - trg_main_window_set_start_args(window, args); - auto_connect_if_required(window); - gtk_main(); - } - - g_object_unref(app); - - return EXIT_SUCCESS; -} - -#elif !WIN32 && GTK_CHECK_VERSION( 3, 0, 0 ) +#if !WIN32 /* GtkApplication - the replacement for libunique. * This is implemented in trg-gtk-app.c @@ -205,18 +113,18 @@ trg_simple_init(TrgClient * client, int argc, char *argv[], gchar ** args) /* Win32 mailslots. I've implemented this in win32-mailslot.c */ #if !WIN32 -static void trg_non_win32_init() +static void trg_non_win32_init(void) { bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); } #endif -static void trg_cleanup() +static void trg_cleanup(void) { curl_global_cleanup(); } -#if WIN32 || !GTK_CHECK_VERSION( 3, 0, 0 ) +#if WIN32 static gchar **convert_args(int argc, char *argv[]) { @@ -261,17 +169,15 @@ static gchar **convert_args(int argc, char *argv[]) int main(int argc, char *argv[]) { -#if WIN32 || !GTK_CHECK_VERSION( 3, 0, 0 ) +#if WIN32 gchar **args; #endif gint exitCode = EXIT_SUCCESS; TrgClient *client; - g_type_init(); - g_thread_init(NULL); gtk_init(&argc, &argv); -#if WIN32 || !GTK_CHECK_VERSION( 3, 0, 0 ) +#if WIN32 args = convert_args(argc, argv); #endif @@ -286,13 +192,7 @@ int main(int argc, char *argv[]) exitCode = trg_win32_init(client, argc, argv, args); #else trg_non_win32_init(); -#if !GTK_CHECK_VERSION( 3, 0, 0 ) && HAVE_LIBUNIQUE - exitCode = trg_libunique_init(client, argc, argv, args); -#elif GTK_CHECK_VERSION( 3, 0, 0 ) exitCode = trg_gtkapp_init(client, argc, argv); -#else - exitCode = trg_simple_init(client, argc, argv, args); -#endif #endif trg_cleanup(); diff --git a/src/protocol-constants.h b/src/protocol-constants.h index 061a10e..8fffb00 100644 --- a/src/protocol-constants.h +++ b/src/protocol-constants.h @@ -56,6 +56,7 @@ #define FIELD_ETA "eta" #define FIELD_UPLOADEDEVER "uploadedEver" #define FIELD_DOWNLOADEDEVER "downloadedEver" +#define FIELD_CORRUPTEVER "corruptEver" #define FIELD_HAVEVALID "haveValid" #define FIELD_HAVEUNCHECKED "haveUnchecked" #define FIELD_PERCENTDONE "percentDone" diff --git a/src/remote-exec.c b/src/remote-exec.c index edf75f2..774c266 100644 --- a/src/remote-exec.c +++ b/src/remote-exec.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib.h> #include <gtk/gtk.h> #include <json-glib/json-glib.h> @@ -26,6 +30,7 @@ #include "trg-prefs.h" #include "protocol-constants.h" #include "torrent.h" +#include "remote-exec.h" /* A few functions used to build local commands, otherwise known as actions. * @@ -53,7 +58,7 @@ static const char json_exceptions[] = { 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, static gchar *dump_json_value(JsonNode * node) { - GValue value = { 0, }; + GValue value = G_VALUE_INIT; GString *buffer; buffer = g_string_new(""); diff --git a/src/requests.c b/src/requests.c index 95be1d7..4e044ab 100644 --- a/src/requests.c +++ b/src/requests.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <glib/gstdio.h> @@ -180,6 +184,7 @@ JsonNode *torrent_get(gint64 id) json_array_add_string_element(fields, FIELD_ADDED_DATE); json_array_add_string_element(fields, FIELD_DOWNLOADEDEVER); json_array_add_string_element(fields, FIELD_UPLOADEDEVER); + json_array_add_string_element(fields, FIELD_CORRUPTEVER); json_array_add_string_element(fields, FIELD_SIZEWHENDONE); json_array_add_string_element(fields, FIELD_QUEUE_POSITION); json_array_add_string_element(fields, FIELD_ID); @@ -227,7 +232,22 @@ JsonNode *torrent_add_url(const gchar * url, gboolean paused) return root; } -JsonNode *torrent_add(gchar * target, gint flags) +JsonNode *torrent_add_from_response(trg_response *response, gint flags) { + JsonNode *root = base_request(METHOD_TORRENT_ADD); + JsonObject *args = node_get_arguments(root); + gchar *encoded = g_base64_encode((guchar *)response->raw, response->size); + + json_object_set_string_member(args, PARAM_METAINFO, + encoded); + g_free(encoded); + + json_object_set_boolean_member(args, PARAM_PAUSED, + (flags & TORRENT_ADD_FLAG_PAUSED)); + + return root; +} + +JsonNode *torrent_add_from_file(gchar * target, gint flags) { JsonNode *root; JsonObject *args; diff --git a/src/requests.h b/src/requests.h index 5ea9b2a..7430fda 100644 --- a/src/requests.h +++ b/src/requests.h @@ -23,6 +23,8 @@ #include <glib-object.h> #include <json-glib/json-glib.h> +#include "trg-client.h" + JsonNode *generic_request(gchar * method, JsonArray * array); JsonNode *session_set(void); @@ -34,7 +36,8 @@ JsonNode *torrent_start(JsonArray * array); JsonNode *torrent_verify(JsonArray * array); JsonNode *torrent_reannounce(JsonArray * array); JsonNode *torrent_remove(JsonArray * array, int removeData); -JsonNode *torrent_add(gchar * filename, gint flags); +JsonNode *torrent_add_from_response(trg_response *response, gint flags); +JsonNode *torrent_add_from_file(gchar * filename, gint flags); JsonNode *torrent_add_url(const gchar * url, gboolean paused); JsonNode *torrent_set_location(JsonArray * array, gchar * location, gboolean move); diff --git a/src/session-get.c b/src/session-get.c index 98c466c..4706c72 100644 --- a/src/session-get.c +++ b/src/session-get.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <json-glib/json-glib.h> diff --git a/src/torrent-cell-renderer.c b/src/torrent-cell-renderer.c index 95f4d37..1157537 100644 --- a/src/torrent-cell-renderer.c +++ b/src/torrent-cell-renderer.c @@ -13,6 +13,10 @@ /* This cell renderer has been modified heavily to work with the * TrgTorrentModel instead of libtransmission. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <gtk/gtk.h> #include <gdk/gdk.h> #include <glib/gi18n.h> @@ -58,17 +62,10 @@ enum { #define COMPACT_ICON_SIZE GTK_ICON_SIZE_MENU #define FULL_ICON_SIZE GTK_ICON_SIZE_DND -#if GTK_CHECK_VERSION( 3, 0, 0 ) #define FOREGROUND_COLOR_KEY "foreground-rgba" typedef GdkRGBA GtrColor; typedef cairo_t GtrDrawable; typedef GtkRequisition GtrRequisition; -#else -#define FOREGROUND_COLOR_KEY "foreground-gdk" -typedef GdkColor GtrColor; -typedef GdkWindow GtrDrawable; -typedef GdkRectangle GtrRequisition; -#endif /*** **** @@ -329,16 +326,16 @@ static void getStatusString(GString * gstr, TorrentCellRenderer * r) if (priv->fileCount > 0) { g_string_append_printf(gstr, ngettext - ("Downloading from %1$li of %2$li connected peer", - "Downloading from %1$li of %2$li connected peers", + ("Downloading from %1$"G_GUINT64_FORMAT" of %2$"G_GUINT64_FORMAT" connected peer", + "Downloading from %1$"G_GUINT64_FORMAT" of %2$"G_GUINT64_FORMAT" connected peers", priv->webSeedsToUs + priv->peersToUs), priv->webSeedsToUs + priv->peersToUs, priv->webSeedsToUs + priv->connected); } else { g_string_append_printf(gstr, ngettext - ("Downloading metadata from %1$li peer (%2$s done)", - "Downloading metadata from %1$li peers (%2$s done)", + ("Downloading metadata from %1$"G_GUINT64_FORMAT" peer (%2$s done)", + "Downloading metadata from %1$"G_GUINT64_FORMAT" peers (%2$s done)", priv->connected + priv->webSeedsToUs), priv->connected + priv->webSeedsToUs, tr_strlpercent(buf, @@ -348,8 +345,8 @@ static void getStatusString(GString * gstr, TorrentCellRenderer * r) } else if (priv->flags & TORRENT_FLAG_SEEDING) { g_string_append_printf(gstr, ngettext - ("Seeding to %1$li of %2$li connected peer", - "Seeding to %1$li of %2$li connected peers", + ("Seeding to %1$"G_GUINT64_FORMAT" of %2$"G_GUINT64_FORMAT" connected peer", + "Seeding to %1$"G_GUINT64_FORMAT" of %2$"G_GUINT64_FORMAT" connected peers", priv->connected), priv->peersFromUs, priv->connected); } @@ -401,18 +398,8 @@ gtr_cell_renderer_get_preferred_size(GtkCellRenderer * renderer, GtkRequisition * minimum_size, GtkRequisition * natural_size) { -#if GTK_CHECK_VERSION( 3, 0, 0 ) gtk_cell_renderer_get_preferred_size(renderer, widget, minimum_size, natural_size); -#else - GtkRequisition r; - gtk_cell_renderer_get_size(renderer, widget, NULL, NULL, NULL, - &r.width, &r.height); - if (minimum_size) - *minimum_size = r; - if (natural_size) - *natural_size = r; -#endif } static void @@ -462,8 +449,6 @@ get_size_compact(TorrentCellRenderer * cell, g_object_unref(icon); } -#define MAX3(a,b,c) MAX(a,MAX(b,c)) - static void get_size_full(TorrentCellRenderer * cell, GtkWidget * widget, gint * width, gint * height) @@ -526,11 +511,7 @@ get_size_full(TorrentCellRenderer * cell, static void torrent_cell_renderer_get_size(GtkCellRenderer * cell, GtkWidget * widget, -#if GTK_CHECK_VERSION( 3,0,0 ) const GdkRectangle * cell_area, -#else - GdkRectangle * cell_area, -#endif gint * x_offset, gint * y_offset, gint * width, gint * height) @@ -570,7 +551,6 @@ get_text_color(TorrentCellRenderer * r, GtkWidget * widget, GtrColor * setme) { struct TorrentCellRendererPrivate *p = r->priv; -#if GTK_CHECK_VERSION( 3,0,0 ) static const GdkRGBA red = { 1.0, 0, 0, 0 }; if (p->error) @@ -581,16 +561,6 @@ get_text_color(TorrentCellRenderer * r, GtkWidget * widget, else gtk_style_context_get_color(gtk_widget_get_style_context(widget), GTK_STATE_FLAG_NORMAL, setme); -#else - static const GdkColor red = { 0, 65535, 0, 0 }; - - if (p->error) - *setme = red; - else if (p->flags & TORRENT_FLAG_PAUSED) - *setme = gtk_widget_get_style(widget)->text[GTK_STATE_INSENSITIVE]; - else - *setme = gtk_widget_get_style(widget)->text[GTK_STATE_NORMAL]; -#endif } static double get_percent_done(TorrentCellRenderer * r, gboolean * seed) @@ -623,26 +593,15 @@ gtr_cell_renderer_render(GtkCellRenderer * renderer, const GdkRectangle * area, GtkCellRendererState flags) { -#if GTK_CHECK_VERSION( 3, 0, 0 ) gtk_cell_renderer_render(renderer, drawable, widget, area, area, flags); -#else - gtk_cell_renderer_render(renderer, drawable, widget, area, area, area, - flags); -#endif } static void torrent_cell_renderer_render(GtkCellRenderer * cell, GtrDrawable * window, GtkWidget * widget, -#if GTK_CHECK_VERSION( 3,0,0 ) const GdkRectangle * background_area, const GdkRectangle * cell_area, -#else - GdkRectangle * background_area, - GdkRectangle * cell_area, - GdkRectangle * expose_area, -#endif GtkCellRendererState flags) { TorrentCellRenderer *self = TORRENT_CELL_RENDERER(cell); diff --git a/src/torrent.c b/src/torrent.c index ed595dd..e5577ee 100644 --- a/src/torrent.c +++ b/src/torrent.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib-object.h> #include <glib/gi18n.h> #include <gtk/gtk.h> @@ -176,6 +180,11 @@ gint64 torrent_get_uploaded(JsonObject * t) return json_object_get_int_member(t, FIELD_UPLOADEDEVER); } +gint64 torrent_get_corrupted(JsonObject * t) +{ + return json_object_get_int_member(t, FIELD_CORRUPTEVER); +} + gint64 torrent_get_have_valid(JsonObject * t) { return json_object_get_int_member(t, FIELD_HAVEVALID); @@ -299,23 +308,23 @@ torrent_get_flags(JsonObject * t, gint64 rpcv, gint64 status, gchar *torrent_get_status_icon(gint64 rpcv, guint flags) { if (flags & TORRENT_FLAG_ERROR) - return g_strdup(GTK_STOCK_DIALOG_WARNING); + return g_strdup("dialog-warning"); else if (flags & TORRENT_FLAG_DOWNLOADING_METADATA) - return g_strdup(GTK_STOCK_FIND); + return g_strdup("edit-find"); else if (flags & TORRENT_FLAG_DOWNLOADING) - return g_strdup(GTK_STOCK_GO_DOWN); + return g_strdup("go-down"); else if (flags & TORRENT_FLAG_PAUSED) - return g_strdup(GTK_STOCK_MEDIA_PAUSE); + return g_strdup("media-playback-pause"); else if (flags & TORRENT_FLAG_SEEDING) - return g_strdup(GTK_STOCK_GO_UP); + return g_strdup("go-up"); else if (flags & TORRENT_FLAG_CHECKING) - return g_strdup(GTK_STOCK_REFRESH); + return g_strdup("view-refresh"); else if (flags & TORRENT_FLAG_DOWNLOADING_WAIT) - return g_strdup(GTK_STOCK_MEDIA_REWIND); + return g_strdup("media-seek-backward"); else if (flags & TORRENT_FLAG_SEEDING_WAIT) - return g_strdup(GTK_STOCK_MEDIA_FORWARD); + return g_strdup("media-seek-forward"); else - return g_strdup(GTK_STOCK_DIALOG_QUESTION); + return g_strdup("dialog-question"); } gint64 torrent_get_done_date(JsonObject * t) diff --git a/src/torrent.h b/src/torrent.h index cebdd76..c837046 100644 --- a/src/torrent.h +++ b/src/torrent.h @@ -51,6 +51,7 @@ gint64 torrent_get_rate_down(JsonObject * t); gint64 torrent_get_rate_up(JsonObject * t); gint64 torrent_get_eta(JsonObject * t); gint64 torrent_get_uploaded(JsonObject * t); +gint64 torrent_get_corrupted(JsonObject * t); gint64 torrent_get_downloaded(JsonObject * t); const gchar *torrent_get_errorstr(JsonObject * t); gint64 torrent_get_error(JsonObject * t); diff --git a/src/transmission-remote-gtk.desktop.in b/src/transmission-remote-gtk.desktop.in deleted file mode 100644 index 30a9a5d..0000000 --- a/src/transmission-remote-gtk.desktop.in +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -Name=Transmission Remote -Comment=Remotely manage the Transmission BitTorrent client -Exec=@bindir@/transmission-remote-gtk %U -Icon=transmission-remote-gtk -Terminal=false -TryExec=transmission-remote-gtk -Type=Application -MimeType=application/x-bittorrent;x-scheme-handler/magnet; -Categories=Network;FileTransfer;P2P;GTK; diff --git a/src/trg-about-window.c b/src/trg-about-window.c index 8dbf7a8..c14482b 100644 --- a/src/trg-about-window.c +++ b/src/trg-about-window.c @@ -23,24 +23,14 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> -#include <json-glib/json-glib.h> #include "trg-about-window.h" -#include "util.h" GtkWidget *trg_about_window_new(GtkWindow * parent) { GtkWidget *dialog; GdkPixbuf *logo; - gchar *licenseText = NULL; const gchar *trgAuthors[] = { "Alan Fitton <alan@eth0.org.uk>", NULL }; - gchar *licenseFile; - -#ifdef WIN32 - licenseFile = trg_win32_support_path("COPYING.TXT"); -#else - licenseFile = g_strdup(TRGLICENSE); -#endif dialog = gtk_about_dialog_new(); gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); @@ -56,12 +46,7 @@ GtkWidget *trg_about_window_new(GtkWindow * parent) g_object_unref(logo); } - if (g_file_get_contents(licenseFile, &licenseText, NULL, NULL)) { - gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(dialog), - licenseText); - } else { - gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(dialog), "GPL2"); - } + gtk_about_dialog_set_license_type (GTK_ABOUT_DIALOG(dialog), GTK_LICENSE_GPL_2_0); gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(dialog), PACKAGE_NAME); @@ -92,8 +77,6 @@ GtkWidget *trg_about_window_new(GtkWindow * parent) "* Ã…ke Svensson (Swedish)\n" "* ROR191 (Ukranian)\n"); - g_free(licenseFile); - g_free(licenseText); return dialog; } diff --git a/src/trg-cell-renderer-counter.c b/src/trg-cell-renderer-counter.c index 9a4049c..b4494c2 100644 --- a/src/trg-cell-renderer-counter.c +++ b/src/trg-cell-renderer-counter.c @@ -17,27 +17,36 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <stdint.h> +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <gtk/gtk.h> #include "trg-cell-renderer-counter.h" -#include "util.h" -enum { - PROP_0, PROP_STATE_LABEL, PROP_STATE_COUNT +enum +{ + PROP_0, + PROP_STATE_LABEL, + PROP_STATE_COUNT, + N_PROPS, }; -G_DEFINE_TYPE(TrgCellRendererCounter, trg_cell_renderer_counter, - GTK_TYPE_CELL_RENDERER_TEXT) -#define TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_CELL_RENDERER_COUNTER, TrgCellRendererCounterPrivate)) -typedef struct _TrgCellRendererCounterPrivate - TrgCellRendererCounterPrivate; +struct _TrgCellRendererCounter +{ + GtkCellRendererText parent; +}; -struct _TrgCellRendererCounterPrivate { - gint count; +typedef struct +{ + gint count; gchar *originalLabel; -}; +} TrgCellRendererCounterPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE(TrgCellRendererCounter, trg_cell_renderer_counter, + GTK_TYPE_CELL_RENDERER_TEXT) + static void trg_cell_renderer_counter_get_property(GObject * object, guint property_id, @@ -45,7 +54,7 @@ static void trg_cell_renderer_counter_get_property(GObject * object, GParamSpec * pspec) { TrgCellRendererCounterPrivate *priv = - TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(object); + trg_cell_renderer_counter_get_instance_private(TRG_CELL_RENDERER_COUNTER(object)); switch (property_id) { case PROP_STATE_COUNT: g_value_set_int(value, priv->count); @@ -59,7 +68,7 @@ static void trg_cell_renderer_counter_get_property(GObject * object, static void trg_cell_renderer_counter_refresh(TrgCellRendererCounter * cr) { TrgCellRendererCounterPrivate *priv = - TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(cr); + trg_cell_renderer_counter_get_instance_private(cr); if (priv->originalLabel && priv->count > 0) { gchar *counterLabel = g_strdup_printf("%s <span size=\"small\">(%d)</span>", @@ -79,7 +88,7 @@ trg_cell_renderer_counter_set_property(GObject * object, GParamSpec * pspec) { TrgCellRendererCounterPrivate *priv = - TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(object); + trg_cell_renderer_counter_get_instance_private(TRG_CELL_RENDERER_COUNTER(object)); if (property_id == PROP_STATE_LABEL) { g_free(priv->originalLabel); @@ -101,10 +110,9 @@ trg_cell_renderer_counter_set_property(GObject * object, static void trg_cell_renderer_counter_dispose(GObject * object) { TrgCellRendererCounterPrivate *priv = - TRG_CELL_RENDERER_COUNTER_GET_PRIVATE(object); + trg_cell_renderer_counter_get_instance_private(TRG_CELL_RENDERER_COUNTER(object)); g_free(priv->originalLabel); - G_OBJECT_CLASS(trg_cell_renderer_counter_parent_class)->dispose - (object); + G_OBJECT_CLASS(trg_cell_renderer_counter_parent_class)->dispose(object); } static void @@ -125,9 +133,7 @@ trg_cell_renderer_counter_class_init(TrgCellRendererCounterClass * klass) INT_MAX, -1, G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); + G_PARAM_STATIC_STRINGS)); g_object_class_install_property(object_class, PROP_STATE_LABEL, @@ -136,13 +142,7 @@ trg_cell_renderer_counter_class_init(TrgCellRendererCounterClass * klass) "State Label", NULL, G_PARAM_READWRITE | - G_PARAM_STATIC_NAME - | - G_PARAM_STATIC_NICK - | - G_PARAM_STATIC_BLURB)); - - g_type_class_add_private(klass, sizeof(TrgCellRendererCounterPrivate)); + G_PARAM_STATIC_STRINGS)); } static void trg_cell_renderer_counter_init(TrgCellRendererCounter * self) @@ -151,7 +151,5 @@ static void trg_cell_renderer_counter_init(TrgCellRendererCounter * self) GtkCellRenderer *trg_cell_renderer_counter_new(void) { - return - GTK_CELL_RENDERER(g_object_new - (TRG_TYPE_CELL_RENDERER_COUNTER, NULL)); + return g_object_new (TRG_TYPE_CELL_RENDERER_COUNTER, NULL); } diff --git a/src/trg-cell-renderer-counter.h b/src/trg-cell-renderer-counter.h index 7e70c4b..2c4f2ed 100644 --- a/src/trg-cell-renderer-counter.h +++ b/src/trg-cell-renderer-counter.h @@ -17,35 +17,16 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef TRG_CELL_RENDERER_COUNTER_H_ -#define TRG_CELL_RENDERER_COUNTER_H_ +#pragma once -#include <glib-object.h> #include <gtk/gtk.h> G_BEGIN_DECLS -#define TRG_TYPE_CELL_RENDERER_COUNTER trg_cell_renderer_counter_get_type() -#define TRG_CELL_RENDERER_COUNTER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_CELL_RENDERER_COUNTER, TrgCellRendererCounter)) -#define TRG_CELL_RENDERER_COUNTER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_CELL_RENDERER_COUNTER, TrgCellRendererCounterClass)) -#define TRG_IS_CELL_RENDERER_COUNTER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_CELL_RENDERER_COUNTER)) -#define TRG_IS_CELL_RENDERER_COUNTER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_CELL_RENDERER_COUNTER)) -#define TRG_CELL_RENDERER_COUNTER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_CELL_RENDERER_COUNTER, TrgCellRendererCounterClass)) - typedef struct { - GtkCellRendererText parent; -} TrgCellRendererCounter; - -typedef struct { - GtkCellRendererTextClass parent_class; -} TrgCellRendererCounterClass; - -GType trg_cell_renderer_counter_get_type(void); + +#define TRG_TYPE_CELL_RENDERER_COUNTER (trg_cell_renderer_counter_get_type()) +G_DECLARE_FINAL_TYPE (TrgCellRendererCounter, trg_cell_renderer_counter, TRG, CELL_RENDERER_COUNTER, GtkCellRendererText) GtkCellRenderer *trg_cell_renderer_counter_new(void); G_END_DECLS -#endif /* TRG_CELL_RENDERER_COUNTER_H_ */ + diff --git a/src/trg-cell-renderer-epoch.c b/src/trg-cell-renderer-epoch.c index 8e38949..6036e0e 100644 --- a/src/trg-cell-renderer-epoch.c +++ b/src/trg-cell-renderer-epoch.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdint.h> #include <time.h> #include <gtk/gtk.h> diff --git a/src/trg-cell-renderer-eta.c b/src/trg-cell-renderer-eta.c index 90e8886..455fcd9 100644 --- a/src/trg-cell-renderer-eta.c +++ b/src/trg-cell-renderer-eta.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdint.h> #include <gtk/gtk.h> diff --git a/src/trg-cell-renderer-file-icon.c b/src/trg-cell-renderer-file-icon.c index e116d90..5642ace 100644 --- a/src/trg-cell-renderer-file-icon.c +++ b/src/trg-cell-renderer-file-icon.c @@ -17,13 +17,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <stdint.h> -#include <gtk/gtk.h> - #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include <stdint.h> +#include <gtk/gtk.h> + #include "trg-cell-renderer-file-icon.h" #include "util.h" diff --git a/src/trg-cell-renderer-numgteqthan.c b/src/trg-cell-renderer-numgteqthan.c index 3be1cd6..6b648ad 100644 --- a/src/trg-cell-renderer-numgteqthan.c +++ b/src/trg-cell-renderer-numgteqthan.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdint.h> #include <gtk/gtk.h> diff --git a/src/trg-cell-renderer-priority.c b/src/trg-cell-renderer-priority.c index d52129a..28c503a 100644 --- a/src/trg-cell-renderer-priority.c +++ b/src/trg-cell-renderer-priority.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdint.h> #include <glib/gi18n.h> #include <gtk/gtk.h> diff --git a/src/trg-cell-renderer-ratio.c b/src/trg-cell-renderer-ratio.c index ed0a453..3404282 100644 --- a/src/trg-cell-renderer-ratio.c +++ b/src/trg-cell-renderer-ratio.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <limits.h> #include <gtk/gtk.h> diff --git a/src/trg-cell-renderer-size.c b/src/trg-cell-renderer-size.c index ebe6b25..23edb55 100644 --- a/src/trg-cell-renderer-size.c +++ b/src/trg-cell-renderer-size.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdint.h> #include <gtk/gtk.h> diff --git a/src/trg-cell-renderer-speed.c b/src/trg-cell-renderer-speed.c index a527b59..7487e01 100644 --- a/src/trg-cell-renderer-speed.c +++ b/src/trg-cell-renderer-speed.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdint.h> #include <gtk/gtk.h> diff --git a/src/trg-cell-renderer-wanted.c b/src/trg-cell-renderer-wanted.c index c23aae1..8fbe031 100644 --- a/src/trg-cell-renderer-wanted.c +++ b/src/trg-cell-renderer-wanted.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdint.h> #include <glib/gi18n.h> #include <gtk/gtk.h> diff --git a/src/trg-client.c b/src/trg-client.c index f20677a..6b47d7a 100644 --- a/src/trg-client.c +++ b/src/trg-client.c @@ -17,7 +17,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif #include <stdlib.h> #include <string.h> @@ -71,6 +73,7 @@ struct _TrgClientPrivate { gint64 updateSerial; JsonObject *session; gboolean ssl; + gboolean ssl_validate; gdouble version; char *url; char *username; @@ -79,9 +82,10 @@ struct _TrgClientPrivate { GHashTable *torrentTable; GThreadPool *pool; TrgPrefs *prefs; - GPrivate *tlsKey; + GPrivate tlsKey; gint configSerial; - GMutex *configMutex; + guint http_class; + GMutex configMutex; gboolean seedRatioLimited; gdouble seedRatioLimit; }; @@ -155,8 +159,8 @@ TrgClient *trg_client_new(void) trg_prefs_load(prefs); - priv->configMutex = g_mutex_new(); - priv->tlsKey = g_private_new(NULL); + g_mutex_init(&priv->configMutex); + //priv->tlsKey = g_private_new(NULL); priv->seedRatioLimited = FALSE; priv->seedRatioLimit = 0.00; @@ -227,7 +231,7 @@ int trg_client_populate_with_settings(TrgClient * tc) pxProxyFactory *pf = NULL; #endif - g_mutex_lock(priv->configMutex); + g_mutex_lock(&priv->configMutex); trg_prefs_set_connection(prefs, trg_prefs_get_profile(prefs)); @@ -249,12 +253,15 @@ int trg_client_populate_with_settings(TrgClient * tc) if (!host || strlen(host) < 1) { g_free(host); - g_mutex_unlock(priv->configMutex); + g_mutex_unlock(&priv->configMutex); return TRG_NO_HOSTNAME_SET; } #ifndef CURL_NO_SSL priv->ssl = trg_prefs_get_bool(prefs, TRG_PREFS_KEY_SSL, TRG_PREFS_CONNECTION); + priv->ssl_validate = trg_prefs_get_bool(prefs, TRG_PREFS_KEY_SSL_VALIDATE, + TRG_PREFS_CONNECTION); + #else priv->ssl = FALSE; #endif @@ -296,7 +303,7 @@ int trg_client_populate_with_settings(TrgClient * tc) #endif priv->configSerial++; - g_mutex_unlock(priv->configMutex); + g_mutex_unlock(&priv->configMutex); return 0; } @@ -325,14 +332,14 @@ void trg_client_set_session_id(TrgClient * tc, gchar * session_id) { TrgClientPrivate *priv = tc->priv; - g_mutex_lock(priv->configMutex); + g_mutex_lock(&priv->configMutex); if (priv->session_id) g_free(priv->session_id); priv->session_id = session_id; - g_mutex_unlock(priv->configMutex); + g_mutex_unlock(&priv->configMutex); } void trg_client_status_change(TrgClient * tc, gboolean connected) @@ -344,9 +351,9 @@ void trg_client_status_change(TrgClient * tc, gboolean connected) json_object_unref(priv->session); priv->session = NULL; } - g_mutex_lock(priv->configMutex); + g_mutex_lock(&priv->configMutex); trg_prefs_set_connection(priv->prefs, NULL); - g_mutex_unlock(priv->configMutex); + g_mutex_unlock(&priv->configMutex); } } @@ -377,6 +384,11 @@ gboolean trg_client_get_ssl(TrgClient * tc) { return tc->priv->ssl; } + +gboolean trg_client_get_ssl_validate(TrgClient * tc) +{ + return tc->priv->ssl_validate; +} #endif gchar *trg_client_get_proxy(TrgClient * tc) @@ -404,7 +416,7 @@ gboolean trg_client_is_connected(TrgClient * tc) void trg_client_configlock(TrgClient * tc) { - g_mutex_lock(tc->priv->configMutex); + g_mutex_lock(&tc->priv->configMutex); } guint trg_client_get_failcount(TrgClient * tc) @@ -425,16 +437,22 @@ void trg_client_reset_failcount(TrgClient * tc) void trg_client_configunlock(TrgClient * tc) { - g_mutex_unlock(tc->priv->configMutex); + g_mutex_unlock(&tc->priv->configMutex); } /* formerly http.c */ void trg_response_free(trg_response * response) { - if (response->obj) - json_object_unref(response->obj); - g_free(response); + if (response) { + if (response->obj) + json_object_unref(response->obj); + + if (response->raw) + g_free(response->raw); + + g_free(response); + } } static size_t @@ -474,100 +492,131 @@ header_callback(void *ptr, size_t size, size_t nmemb, void *data) return (nmemb * size); } -static void trg_tls_update(TrgClient * tc, trg_tls * tls, gint serial) -{ - gchar *proxy; - - curl_easy_setopt(tls->curl, CURLOPT_PASSWORD, - trg_client_get_password(tc)); - curl_easy_setopt(tls->curl, CURLOPT_USERNAME, - trg_client_get_username(tc)); - curl_easy_setopt(tls->curl, CURLOPT_URL, trg_client_get_url(tc)); - -#ifndef CURL_NO_SSL - if (trg_client_get_ssl(tc)) - curl_easy_setopt(tls->curl, CURLOPT_SSL_VERIFYPEER, 0); -#endif - - proxy = trg_client_get_proxy(tc); - if (proxy) { - curl_easy_setopt(tls->curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); - curl_easy_setopt(tls->curl, CURLOPT_PROXY, proxy); - } - - tls->serial = serial; -} - -trg_tls *trg_tls_new(TrgClient * tc) +static trg_tls *trg_tls_new(TrgClient * tc) { trg_tls *tls = g_new0(trg_tls, 1); tls->curl = curl_easy_init(); - curl_easy_setopt(tls->curl, CURLOPT_USERAGENT, PACKAGE_NAME); - curl_easy_setopt(tls->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_easy_setopt(tls->curl, CURLOPT_WRITEFUNCTION, - &http_receive_callback); - curl_easy_setopt(tls->curl, CURLOPT_HEADERFUNCTION, &header_callback); - curl_easy_setopt(tls->curl, CURLOPT_WRITEHEADER, (void *) tc); - tls->serial = -1; return tls; } -static int -trg_http_perform_inner(TrgClient * tc, gchar * reqstr, - trg_response * response, gboolean recurse) -{ - TrgClientPrivate *priv = tc->priv; - TrgPrefs *prefs = trg_client_get_prefs(tc); - gpointer threadLocalStorage = g_private_get(priv->tlsKey); - trg_tls *tls; - long httpCode = 0; - gchar *session_id; - struct curl_slist *headers = NULL; +static trg_tls *get_tls(TrgClient *tc) { + TrgClientPrivate *priv = tc->priv; + gpointer threadLocalStorage = g_private_get(&priv->tlsKey); + trg_tls *tls; if (!threadLocalStorage) { tls = trg_tls_new(tc); - g_private_set(priv->tlsKey, tls); + g_private_set(&priv->tlsKey, tls); } else { tls = (trg_tls *) threadLocalStorage; } - g_mutex_lock(priv->configMutex); + return tls; +} + +static CURL* get_curl(TrgClient *tc, guint http_class) +{ + TrgClientPrivate *priv = tc->priv; + TrgPrefs *prefs = trg_client_get_prefs(tc); + trg_tls *tls = get_tls(tc); + CURL *curl = tls->curl; + + g_mutex_lock(&priv->configMutex); - if (priv->configSerial > tls->serial) - trg_tls_update(tc, tls, priv->configSerial); + if (priv->configSerial > tls->serial || http_class != priv->http_class) { + gchar *proxy; + + curl_easy_reset(curl); + + curl_easy_setopt(curl, CURLOPT_USERAGENT, PACKAGE_NAME); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, + &http_receive_callback); +#ifdef DEBUG + if (g_getenv("TRG_CURL_VERBOSE") != NULL) + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); +#endif + + if (http_class == HTTP_CLASS_TRANSMISSION) { + curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *) tc); + curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &header_callback); + curl_easy_setopt(curl, CURLOPT_PASSWORD, + trg_client_get_password(tc)); + curl_easy_setopt(curl, CURLOPT_USERNAME, + trg_client_get_username(tc)); + curl_easy_setopt(curl, CURLOPT_URL, trg_client_get_url(tc)); + } - session_id = trg_client_get_session_id(tc); - if (session_id) { - headers = curl_slist_append(NULL, session_id); - curl_easy_setopt(tls->curl, CURLOPT_HTTPHEADER, headers); + #ifndef CURL_NO_SSL + if (trg_client_get_ssl(tc) && !trg_client_get_ssl_validate(tc)) { + + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + } + #endif + + proxy = trg_client_get_proxy(tc); + if (proxy) { + curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + curl_easy_setopt(curl, CURLOPT_PROXY, proxy); + } + + tls->serial = priv->configSerial; + priv->http_class = http_class; } - curl_easy_setopt(tls->curl, CURLOPT_TIMEOUT, - (long) trg_prefs_get_int(prefs, TRG_PREFS_KEY_TIMEOUT, - TRG_PREFS_CONNECTION)); + if (http_class == HTTP_CLASS_TRANSMISSION) + curl_easy_setopt(curl, CURLOPT_URL, trg_client_get_url(tc)); + + curl_easy_setopt(curl, CURLOPT_TIMEOUT, + (long) trg_prefs_get_int(prefs, TRG_PREFS_KEY_TIMEOUT, + TRG_PREFS_CONNECTION)); - g_mutex_unlock(priv->configMutex); + g_mutex_unlock(&priv->configMutex); + + /* Headers are set on each use, then freed, so make sure invalid headers aren't still around. */ + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL); + + return curl; + +} + +static inline int +trg_http_perform_inner(TrgClient * tc, trg_request * request, + trg_response * response, gboolean recurse) +{ + CURL* curl = get_curl(tc, HTTP_CLASS_TRANSMISSION); + struct curl_slist *headers = NULL; + gchar *session_id = NULL; + long httpCode = 0; response->size = 0; response->raw = NULL; - curl_easy_setopt(tls->curl, CURLOPT_POSTFIELDS, reqstr); - curl_easy_setopt(tls->curl, CURLOPT_WRITEDATA, (void *) response); - response->status = curl_easy_perform(tls->curl); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request->body); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) response); - if (session_id) { - g_free(session_id); - curl_slist_free_all(headers); - } + session_id = trg_client_get_session_id(tc); + if (session_id) + headers = curl_slist_append(NULL, session_id); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + response->status = curl_easy_perform(curl); - curl_easy_getinfo(tls->curl, CURLINFO_RESPONSE_CODE, &httpCode); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); + + g_free(session_id); + + if (headers) + curl_slist_free_all(headers); if (response->status == CURLE_OK) { if (httpCode == HTTP_CONFLICT && recurse == TRUE) - return trg_http_perform_inner(tc, reqstr, response, FALSE); + return trg_http_perform_inner(tc, request, response, FALSE); else if (httpCode != HTTP_OK) response->status = (-httpCode) - 100; } @@ -575,32 +624,37 @@ trg_http_perform_inner(TrgClient * tc, gchar * reqstr, return response->status; } -int trg_http_perform(TrgClient * tc, gchar * reqstr, trg_response * reqrsp) +int trg_http_perform(TrgClient * tc, trg_request *request, trg_response * rsp) { - return trg_http_perform_inner(tc, reqstr, reqrsp, TRUE); + return trg_http_perform_inner(tc, request, rsp, TRUE); } -/* formerly dispatch.c */ +static void trg_request_free(trg_request *req) { + g_free(req->body); + g_free(req->url); + g_free(req->cookie); -trg_response *dispatch(TrgClient * tc, JsonNode * req) -{ - gchar *serialized = trg_serialize(req); - json_node_free(req); -#ifdef DEBUG - if (g_getenv("TRG_SHOW_OUTGOING")) - g_debug("=>(OUTgoing)=>: %s", serialized); -#endif - return dispatch_str(tc, serialized); + if (req->node) + json_node_free(req->node); } -trg_response *dispatch_str(TrgClient * tc, gchar * req) +/* formerly dispatch.c */ + +trg_response *dispatch(TrgClient * tc, trg_request *req) { trg_response *response = g_new0(trg_response, 1); GError *decode_error = NULL; JsonNode *result; + if (req->node && !req->body) + req->body = trg_serialize(req->node); + +#ifdef DEBUG + if (g_getenv("TRG_SHOW_OUTGOING")) + g_message("=>(OUTgoing)=>: %s", req->body); +#endif + trg_http_perform(tc, req, response); - g_free(req); if (response->status == CURLE_OK) response->obj = trg_deserialize(response, &decode_error); @@ -625,16 +679,56 @@ trg_response *dispatch_str(TrgClient * tc, gchar * req) return response; } +trg_response *dispatch_public_http(TrgClient *tc, trg_request *req) { + trg_response *response = g_new0(trg_response, 1); + CURL* curl = get_curl(tc, HTTP_CLASS_PUBLIC); + struct curl_slist *headers = NULL; + long httpCode = 0; + gchar *cookie_header = NULL; + + response->size = 0; + response->raw = NULL; + + curl_easy_setopt(curl, CURLOPT_URL, req->url); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) response); + + if (req->cookie) { + cookie_header = g_strdup_printf("Cookie: %s", req->cookie); + headers = curl_slist_append(NULL, cookie_header); + } + + if (headers) + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + response->status = curl_easy_perform(curl); + + trg_request_free(req); + + g_free(cookie_header); + + if (headers) + curl_slist_free_all(headers); + + //g_message(response->raw); + + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); + + if (response->status == CURLE_OK && httpCode != HTTP_OK) { + response->status = (-httpCode) - 100; + } + + return response; +} + static void dispatch_async_threadfunc(trg_request * req, TrgClient * tc) { TrgClientPrivate *priv = tc->priv; - trg_response *rsp; - if (req->str) - rsp = dispatch_str(tc, req->str); + if (req->url) + rsp = dispatch_public_http(tc, req); else - rsp = dispatch(tc, req->node); + rsp = dispatch(tc, req); rsp->cb_data = req->cb_data; @@ -679,14 +773,14 @@ dispatch_async(TrgClient * tc, JsonNode * req, return dispatch_async_common(tc, trg_req, callback, data); } -gboolean -dispatch_async_str(TrgClient * tc, gchar * req, - GSourceFunc callback, gpointer data) -{ - trg_request *trg_req = g_new0(trg_request, 1); - trg_req->str = req; +gboolean async_http_request(TrgClient *tc, gchar *url, const gchar *cookie, GSourceFunc callback, gpointer data) { + trg_request *trg_req = g_new0(trg_request, 1); + trg_req->url = g_strdup(url); - return dispatch_async_common(tc, trg_req, callback, data); + if (cookie) + trg_req->cookie = g_strdup(cookie); + + return dispatch_async_common(tc, trg_req, callback, data); } gboolean trg_client_update_session(TrgClient * tc, GSourceFunc callback, diff --git a/src/trg-client.h b/src/trg-client.h index 3b7d916..2c53628 100644 --- a/src/trg-client.h +++ b/src/trg-client.h @@ -22,10 +22,6 @@ #ifndef _TRG_CLIENT_H_ #define _TRG_CLIENT_H_ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <curl/curl.h> #include <curl/easy.h> @@ -57,6 +53,9 @@ #define FAIL_RESPONSE_UNSUCCESSFUL -3 #define DISPATCH_POOL_SIZE 3 +#define HTTP_CLASS_TRANSMISSION 0 +#define HTTP_CLASS_PUBLIC 1 + typedef struct { int status; int size; @@ -68,9 +67,11 @@ typedef struct { typedef struct { gint connid; JsonNode *node; - gchar *str; + gchar *body; + gchar *url; GSourceFunc callback; gpointer cb_data; + gchar *cookie; } trg_request; typedef struct _TrgClientPrivate TrgClientPrivate; @@ -109,20 +110,23 @@ typedef struct { * We lock updating (and checking for updates) with priv->configMutex */ int serial; + guint client_class; CURL *curl; } trg_tls; /* stuff that used to be in http.h */ void trg_response_free(trg_response * response); -int trg_http_perform(TrgClient * client, gchar * reqstr, - trg_response * reqrsp); +int trg_http_perform(TrgClient * tc, trg_request *request, trg_response * rsp); + /* end http.h*/ /* stuff that used to be in dispatch.c */ -trg_response *dispatch(TrgClient * client, JsonNode * req); -trg_response *dispatch_str(TrgClient * client, gchar * req); +trg_response *dispatch(TrgClient * tc, trg_request *req); +trg_response *dispatch_public_http(TrgClient *tc, trg_request *req); gboolean dispatch_async(TrgClient * client, JsonNode * req, GSourceFunc callback, gpointer data); +gboolean async_http_request(TrgClient *tc, gchar *url, const gchar *cookie, GSourceFunc callback, gpointer data); + /* end dispatch.c*/ GType trg_client_get_type(void); @@ -141,6 +145,7 @@ gchar *trg_client_get_session_id(TrgClient * tc); void trg_client_set_session_id(TrgClient * tc, gchar * session_id); #ifndef CURL_NO_SSL gboolean trg_client_get_ssl(TrgClient * tc); +gboolean trg_client_get_ssl_validate(TrgClient * tc); #endif gchar *trg_client_get_proxy(TrgClient * tc); gint64 trg_client_get_serial(TrgClient * tc); diff --git a/src/trg-destination-combo.c b/src/trg-destination-combo.c index d2e3eb0..a361bae 100644 --- a/src/trg-destination-combo.c +++ b/src/trg-destination-combo.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <gtk/gtk.h> @@ -26,25 +30,24 @@ #include "trg-destination-combo.h" #include "util.h" -G_DEFINE_TYPE(TrgDestinationCombo, trg_destination_combo, - GTK_TYPE_COMBO_BOX) -#define TRG_DESTINATION_COMBO_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_DESTINATION_COMBO, TrgDestinationComboPrivate)) -typedef struct _TrgDestinationComboPrivate TrgDestinationComboPrivate; +struct _TrgDestinationCombo { + GtkComboBox parent_instance; +}; -struct _TrgDestinationComboPrivate { +typedef struct { TrgClient *client; gchar *last_selection; - GtkWidget *entry; - GtkCellRenderer *text_renderer; -}; +} TrgDestinationComboPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE(TrgDestinationCombo, trg_destination_combo, + GTK_TYPE_COMBO_BOX) enum { PROP_0, PROP_CLIENT, PROP_LAST_SELECTION }; enum { - DEST_DEFAULT, DEST_LABEL, DEST_EXISTING, DEST_USERADD + DEST_DEFAULT, DEST_LABEL, DEST_EXISTING }; enum { @@ -54,7 +57,7 @@ enum { static void trg_destination_combo_finalize(GObject * object) { TrgDestinationComboPrivate *priv = - TRG_DESTINATION_COMBO_GET_PRIVATE(object); + trg_destination_combo_get_instance_private(TRG_DESTINATION_COMBO(object)); g_free(priv->last_selection); } @@ -64,7 +67,7 @@ trg_destination_combo_get_property(GObject * object, GValue * value, GParamSpec * pspec) { TrgDestinationComboPrivate *priv = - TRG_DESTINATION_COMBO_GET_PRIVATE(object); + trg_destination_combo_get_instance_private(TRG_DESTINATION_COMBO(object)); switch (property_id) { case PROP_CLIENT: g_value_set_pointer(value, priv->client); @@ -85,7 +88,7 @@ trg_destination_combo_set_property(GObject * object, GParamSpec * pspec) { TrgDestinationComboPrivate *priv = - TRG_DESTINATION_COMBO_GET_PRIVATE(object); + trg_destination_combo_get_instance_private(TRG_DESTINATION_COMBO(object)); switch (property_id) { case PROP_CLIENT: priv->client = g_value_get_pointer(value); @@ -115,7 +118,7 @@ static gboolean g_slist_str_set_add(GSList ** list, const gchar * string) void trg_destination_combo_save_selection(TrgDestinationCombo * combo_box) { TrgDestinationComboPrivate *priv = - TRG_DESTINATION_COMBO_GET_PRIVATE(combo_box); + trg_destination_combo_get_instance_private(combo_box); GtkTreeIter iter; if (priv->last_selection @@ -126,53 +129,16 @@ void trg_destination_combo_save_selection(TrgDestinationCombo * combo_box) TrgPrefs *prefs = trg_client_get_prefs(priv->client); gchar *text; - gtk_tree_model_get(model, &iter, DEST_COLUMN_LABEL, &text, -1); + gtk_tree_model_get(model, &iter, DEST_COLUMN_DIR, &text, -1); trg_prefs_set_string(prefs, priv->last_selection, text, TRG_PREFS_CONNECTION); g_free(text); } } -static void -gtk_combo_box_entry_active_changed(GtkComboBox * combo_box, - gpointer user_data) +static inline GtkEntry *trg_destination_combo_get_entry(TrgDestinationCombo * combo) { - GtkTreeModel *model; - GtkTreeIter iter; - gboolean editableEntry = TRUE; - - if (gtk_combo_box_get_active_iter(combo_box, &iter)) { - GtkEntry *entry = - trg_destination_combo_get_entry(TRG_DESTINATION_COMBO - (combo_box)); - - if (entry) { - GValue value = { 0, }; - guint type; - - model = gtk_combo_box_get_model(combo_box); - - gtk_tree_model_get_value(model, &iter, DEST_COLUMN_LABEL, - &value); - gtk_tree_model_get(model, &iter, DEST_COLUMN_TYPE, &type, -1); - - g_object_set_property(G_OBJECT(entry), "text", &value); - g_value_unset(&value); - - if (type == DEST_LABEL) - editableEntry = FALSE; - } - } -#if GTK_CHECK_VERSION( 3, 0, 0 ) - gtk_editable_set_editable(GTK_EDITABLE - (trg_destination_combo_get_entry - (TRG_DESTINATION_COMBO(combo_box))), - editableEntry); -#else - gtk_entry_set_editable(trg_destination_combo_get_entry - (TRG_DESTINATION_COMBO(combo_box)), - editableEntry); -#endif + return GTK_ENTRY(gtk_bin_get_child(GTK_BIN(combo))); } gboolean trg_destination_combo_has_text(TrgDestinationCombo * combo) @@ -183,35 +149,12 @@ gboolean trg_destination_combo_has_text(TrgDestinationCombo * combo) return strlen(text) > 0; } -GtkEntry *trg_destination_combo_get_entry(TrgDestinationCombo * combo) -{ - TrgDestinationComboPrivate *priv = - TRG_DESTINATION_COMBO_GET_PRIVATE(combo); - return GTK_ENTRY(priv->entry); -} - -static void -add_entry_cb(GtkEntry * entry, - GtkEntryIconPosition icon_pos, - GdkEvent * event, gpointer user_data) -{ - GtkComboBox *combo = GTK_COMBO_BOX(user_data); - GtkTreeModel *model = gtk_combo_box_get_model(combo); - GtkTreeIter iter; - - gtk_list_store_insert_with_values(GTK_LIST_STORE(model), &iter, - INT_MAX, DEST_COLUMN_LABEL, "", - DEST_COLUMN_DIR, "", - DEST_COLUMN_TYPE, DEST_USERADD, -1); - gtk_combo_box_set_active_iter(combo, &iter); -} - struct findDupeArg { const gchar *dir; gboolean isDupe; }; -gboolean +static gboolean trg_destination_combo_insert_check_dupe_foreach(GtkTreeModel * model, GtkTreePath * path G_GNUC_UNUSED, @@ -228,12 +171,11 @@ trg_destination_combo_insert_check_dupe_foreach(GtkTreeModel * model, static void trg_destination_combo_insert(GtkComboBox * box, const gchar * label, - const gchar * dir, guint type, - const gchar * lastDestination) + const gchar * dir, + guint type) { GtkTreeModel *model = gtk_combo_box_get_model(box); gchar *comboLabel; - GtkTreeIter iter; if (type == DEST_EXISTING) { struct findDupeArg args; @@ -250,110 +192,88 @@ trg_destination_combo_insert(GtkComboBox * box, comboLabel = label ? g_strdup_printf("%s (%s)", label, dir) : g_strdup(dir); - gtk_list_store_insert_with_values(GTK_LIST_STORE(model), &iter, - INT_MAX, DEST_COLUMN_LABEL, - comboLabel, DEST_COLUMN_DIR, dir, + gtk_list_store_insert_with_values(GTK_LIST_STORE(model), NULL, -1, + DEST_COLUMN_LABEL, comboLabel, + DEST_COLUMN_DIR, dir, DEST_COLUMN_TYPE, type, -1); - - if (lastDestination && !g_strcmp0(lastDestination, comboLabel)) - gtk_combo_box_set_active_iter(box, &iter); - g_free(comboLabel); } -static GObject *trg_destination_combo_constructor(GType type, - guint - n_construct_properties, - GObjectConstructParam * - construct_params) +gchar *trg_destination_combo_get_dir(TrgDestinationCombo * combo) { - GObject *object = G_OBJECT_CLASS - (trg_destination_combo_parent_class)->constructor(type, - n_construct_properties, - construct_params); - TrgDestinationComboPrivate *priv = - TRG_DESTINATION_COMBO_GET_PRIVATE(object); + GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); + GtkTreeIter iter; + + if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) { + gchar *value; + guint type; + + gtk_tree_model_get(model, &iter, DEST_COLUMN_TYPE, &type, -1); + + if (type == DEST_LABEL) { + gtk_tree_model_get(model, &iter, DEST_COLUMN_DIR, &value, -1); + return value; + } + } + + return + g_strdup(gtk_entry_get_text + (trg_destination_combo_get_entry(combo))); +} +static void +load_directory_model(TrgDestinationCombo *self) +{ + TrgDestinationComboPrivate *priv = trg_destination_combo_get_instance_private(self); TrgClient *client = priv->client; TrgPrefs *prefs = trg_client_get_prefs(client); GSList *dirs = NULL, *sli; GList *li, *list; - GtkTreeRowReference *rr; - GtkTreeModel *model; - GtkTreePath *path; - GtkListStore *comboModel; + JsonArray *savedDestinations; gchar *defaultDir; - gchar *lastDestination = NULL; - - comboModel = gtk_list_store_new(N_DEST_COLUMNS, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_UINT); - gtk_combo_box_set_model(GTK_COMBO_BOX(object), - GTK_TREE_MODEL(comboModel)); - g_object_unref(comboModel); - - g_signal_connect(object, "changed", - G_CALLBACK(gtk_combo_box_entry_active_changed), NULL); - - priv->entry = gtk_entry_new(); - gtk_container_add(GTK_CONTAINER(object), priv->entry); - - priv->text_renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(object), - priv->text_renderer, TRUE); - - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(object), - priv->text_renderer, "text", 0, NULL); - - g_slist_foreach(dirs, (GFunc) g_free, NULL); - g_slist_free(dirs); - - gtk_entry_set_icon_from_stock(GTK_ENTRY(priv->entry), - GTK_ENTRY_ICON_SECONDARY, - GTK_STOCK_CLEAR); - - g_signal_connect(priv->entry, "icon-release", - G_CALLBACK(add_entry_cb), object); + /* Add default dir */ defaultDir = g_strdup(session_get_download_dir(trg_client_get_session(client))); rm_trailing_slashes(defaultDir); + trg_destination_combo_insert(GTK_COMBO_BOX(self), + NULL, + defaultDir, DEST_DEFAULT); + g_free (defaultDir); + + + /* Add saved dirs */ savedDestinations = trg_prefs_get_array(prefs, TRG_PREFS_KEY_DESTINATIONS, TRG_PREFS_CONNECTION); - - if (priv->last_selection) - lastDestination = trg_prefs_get_string(prefs, priv->last_selection, - TRG_PREFS_CONNECTION); - - trg_destination_combo_insert(GTK_COMBO_BOX(object), - NULL, - defaultDir, DEST_DEFAULT, - lastDestination); - gtk_combo_box_set_active(GTK_COMBO_BOX(object), 0); - if (savedDestinations) { list = json_array_get_elements(savedDestinations); if (list) { for (li = list; li; li = g_list_next(li)) { JsonObject *obj = json_node_get_object((JsonNode *) li->data); - trg_destination_combo_insert(GTK_COMBO_BOX(object), - json_object_get_string_member - (obj, TRG_PREFS_SUBKEY_LABEL), + trg_destination_combo_insert(GTK_COMBO_BOX(self), json_object_get_string_member - (obj, - TRG_PREFS_KEY_DESTINATIONS_SUBKEY_DIR), - DEST_LABEL, lastDestination); + (obj, TRG_PREFS_SUBKEY_LABEL), + json_object_get_string_member + (obj, TRG_PREFS_KEY_DESTINATIONS_SUBKEY_DIR), + DEST_LABEL); } g_list_free(list); } } + + /* Add all previously used download dirs */ list = g_hash_table_get_values(trg_client_get_torrent_table(client)); for (li = list; li; li = g_list_next(li)) { + GtkTreeRowReference *rr; + GtkTreeModel *model; + GtkTreePath *path; + rr = (GtkTreeRowReference *) li->data; model = gtk_tree_row_reference_get_model(rr); path = gtk_tree_row_reference_get_path(rr); @@ -378,38 +298,48 @@ static GObject *trg_destination_combo_constructor(GType type, } for (sli = dirs; sli; sli = g_slist_next(sli)) - trg_destination_combo_insert(GTK_COMBO_BOX(object), + trg_destination_combo_insert(GTK_COMBO_BOX(self), NULL, (gchar *) sli->data, - DEST_EXISTING, lastDestination); + DEST_EXISTING); + g_slist_free_full (dirs, g_free); g_list_free(list); - g_free(defaultDir); - g_free(lastDestination); +} - return object; +static void set_text_column(GtkCellLayout *layout, guint col) +{ + GList *cells = gtk_cell_layout_get_cells (layout); + g_assert (cells != NULL); + gtk_cell_layout_set_attributes (layout, GTK_CELL_RENDERER(cells->data), "text", col, NULL); + g_list_free (cells); } -gchar *trg_destination_combo_get_dir(TrgDestinationCombo * combo) +static void trg_destination_combo_constructed(GObject *object) { - GtkTreeModel *model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); - GtkTreeIter iter; + TrgDestinationCombo *self = TRG_DESTINATION_COMBO (object); + TrgDestinationComboPrivate *priv = + trg_destination_combo_get_instance_private(self); + TrgPrefs *prefs = trg_client_get_prefs(priv->client); - if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter)) { - gchar *value; - guint type; + G_OBJECT_CLASS(trg_destination_combo_parent_class)->constructed(object); - gtk_tree_model_get(model, &iter, DEST_COLUMN_TYPE, &type, -1); + load_directory_model (self); + set_text_column (GTK_CELL_LAYOUT(self), DEST_COLUMN_LABEL); - if (type == DEST_LABEL) { - gtk_tree_model_get(model, &iter, DEST_COLUMN_DIR, &value, -1); - return value; - } + /* Must be set after constructed */ + if (priv->last_selection) { + /* Restore any previous selection */ + char *lastDestination = trg_prefs_get_string(prefs, priv->last_selection, + TRG_PREFS_CONNECTION); + if (!gtk_combo_box_set_active_id (GTK_COMBO_BOX(object), lastDestination)) + g_warning ("Last selection was not a valid ID"); + g_free(lastDestination); + } + else { + /* DefaultDir is the first item otherwise */ + gtk_combo_box_set_active (GTK_COMBO_BOX(object), 0); } - - return - g_strdup(gtk_entry_get_text - (trg_destination_combo_get_entry(combo))); } static void @@ -417,27 +347,19 @@ trg_destination_combo_class_init(TrgDestinationComboClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); - g_type_class_add_private(klass, sizeof(TrgDestinationComboPrivate)); - object_class->get_property = trg_destination_combo_get_property; object_class->set_property = trg_destination_combo_set_property; object_class->finalize = trg_destination_combo_finalize; - object_class->constructor = trg_destination_combo_constructor; + object_class->constructed = trg_destination_combo_constructed; g_object_class_install_property(object_class, PROP_CLIENT, g_param_spec_pointer("trg-client", "TClient", "Client", - G_PARAM_READWRITE - | - G_PARAM_CONSTRUCT_ONLY - | - G_PARAM_STATIC_NAME - | - G_PARAM_STATIC_NICK - | - G_PARAM_STATIC_BLURB)); + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property(object_class, PROP_LAST_SELECTION, @@ -447,19 +369,25 @@ trg_destination_combo_class_init(TrgDestinationComboClass * klass) "LastSelectionKey", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB)); + G_PARAM_STATIC_STRINGS)); } static void trg_destination_combo_init(TrgDestinationCombo * self) { + GtkListStore *store; + + store = gtk_list_store_new(N_DEST_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); + gtk_combo_box_set_model(GTK_COMBO_BOX(self), GTK_TREE_MODEL(store)); + gtk_combo_box_set_id_column (GTK_COMBO_BOX(self), DEST_COLUMN_DIR); + gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX(self), DEST_COLUMN_LABEL); + g_object_unref(store); } GtkWidget *trg_destination_combo_new(TrgClient * client, const gchar * lastSelectionKey) { return GTK_WIDGET(g_object_new(TRG_TYPE_DESTINATION_COMBO, + "has-entry", TRUE, "trg-client", client, "last-selection-key", lastSelectionKey, NULL)); diff --git a/src/trg-destination-combo.h b/src/trg-destination-combo.h index 9ab5076..9ece8cc 100644 --- a/src/trg-destination-combo.h +++ b/src/trg-destination-combo.h @@ -26,32 +26,14 @@ #include "trg-client.h" G_BEGIN_DECLS -#define TRG_TYPE_DESTINATION_COMBO trg_destination_combo_get_type() -#define TRG_DESTINATION_COMBO(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_DESTINATION_COMBO, TrgDestinationCombo)) -#define TRG_DESTINATION_COMBO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_DESTINATION_COMBO, TrgDestinationComboClass)) -#define TRG_IS_DESTINATION_COMBO(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_DESTINATION_COMBO)) -#define TRG_IS_DESTINATION_COMBO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_DESTINATION_COMBO)) -#define TRG_DESTINATION_COMBO_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_DESTINATION_COMBO, TrgDestinationComboClass)) - typedef struct { - GtkComboBox parent; -} TrgDestinationCombo; - -typedef struct { - GtkComboBoxClass parent_class; -} TrgDestinationComboClass; - -GType trg_destination_combo_get_type(void); + +#define TRG_TYPE_DESTINATION_COMBO (trg_destination_combo_get_type()) +G_DECLARE_FINAL_TYPE(TrgDestinationCombo, trg_destination_combo, TRG, DESTINATION_COMBO, GtkComboBox) GtkWidget *trg_destination_combo_new(TrgClient * client, const gchar * lastSelectionKey); gchar *trg_destination_combo_get_dir(TrgDestinationCombo * combo); gboolean trg_destination_combo_has_text(TrgDestinationCombo * combo); -GtkEntry *trg_destination_combo_get_entry(TrgDestinationCombo * combo); void trg_destination_combo_save_selection(TrgDestinationCombo * combo_box); G_END_DECLS diff --git a/src/trg-file-parser.c b/src/trg-file-parser.c index fbfb6aa..2200ec6 100644 --- a/src/trg-file-parser.c +++ b/src/trg-file-parser.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> @@ -134,32 +138,11 @@ static trg_files_tree_node *trg_parse_torrent_file_nodes(be_node * return top_node; } -trg_torrent_file *trg_parse_torrent_file(const gchar * filename) -{ - GError *error = NULL; - GMappedFile *mf; - be_node *top_node, *info_node, *name_node; - trg_torrent_file *ret = NULL; - - if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { - g_message("%s does not exist", filename); - return NULL; - } - - mf = g_mapped_file_new(filename, FALSE, &error); - - if (error) { - g_error("%s", error->message); - g_error_free(error); - g_mapped_file_unref(mf); - return NULL; - } else { - top_node = - be_decoden(g_mapped_file_get_contents(mf), - g_mapped_file_get_length(mf)); - } +trg_torrent_file *trg_parse_torrent_data(const gchar *data, gsize length) { + trg_torrent_file *ret = NULL; + be_node *top_node, *info_node, *name_node; - g_mapped_file_unref(mf); + top_node = be_decoden(data, length); if (!top_node) { return NULL; @@ -199,3 +182,30 @@ trg_torrent_file *trg_parse_torrent_file(const gchar * filename) be_free(top_node); return ret; } + +trg_torrent_file *trg_parse_torrent_file(const gchar * filename) +{ + GError *error = NULL; + trg_torrent_file *ret = NULL; + GMappedFile *mf; + + if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { + g_message("%s does not exist", filename); + return NULL; + } + + mf = g_mapped_file_new(filename, FALSE, &error); + + if (error) { + g_error("%s", error->message); + g_error_free(error); + g_mapped_file_unref(mf); + return NULL; + } else { + ret = trg_parse_torrent_data(g_mapped_file_get_contents(mf), g_mapped_file_get_length(mf)); + } + + g_mapped_file_unref(mf); + + return ret; +} diff --git a/src/trg-file-parser.h b/src/trg-file-parser.h index 1344be2..caec42f 100644 --- a/src/trg-file-parser.h +++ b/src/trg-file-parser.h @@ -26,3 +26,4 @@ typedef struct { void trg_torrent_file_free(trg_torrent_file * t); trg_torrent_file *trg_parse_torrent_file(const gchar * filename); +trg_torrent_file *trg_parse_torrent_data(const gchar *data, gsize length); diff --git a/src/trg-files-model-common.c b/src/trg-files-model-common.c index b435069..9be7aec 100644 --- a/src/trg-files-model-common.c +++ b/src/trg-files-model-common.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <glib.h> diff --git a/src/trg-files-model.c b/src/trg-files-model.c index bb1b46b..418748e 100644 --- a/src/trg-files-model.c +++ b/src/trg-files-model.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <string.h> #include <limits.h> #include <gtk/gtk.h> @@ -299,7 +303,7 @@ struct MinorUpdateData { JsonArray *wanted; }; -gboolean +static gboolean trg_files_model_update_foreach(GtkListStore * model, GtkTreePath * path G_GNUC_UNUSED, GtkTreeIter * iter, gpointer data) diff --git a/src/trg-files-tree-view-common.c b/src/trg-files-tree-view-common.c index 4680d5f..37dc821 100644 --- a/src/trg-files-tree-view-common.c +++ b/src/trg-files-tree-view-common.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <glib.h> @@ -62,31 +66,23 @@ view_popup_menu(GtkWidget * treeview, GdkEventButton * event, gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); - menuitem = gtk_image_menu_item_new_with_label(GTK_STOCK_APPLY); - gtk_image_menu_item_set_use_stock(GTK_IMAGE_MENU_ITEM(menuitem), TRUE); - gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM - (menuitem), TRUE); - gtk_menu_item_set_label(GTK_MENU_ITEM(menuitem), _("Download")); + menuitem = gtk_menu_item_new_with_label(_("Download")); g_signal_connect(menuitem, "activate", wanted_cb, treeview); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - menuitem = gtk_image_menu_item_new_with_label(GTK_STOCK_CANCEL); - gtk_image_menu_item_set_use_stock(GTK_IMAGE_MENU_ITEM(menuitem), TRUE); - gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM - (menuitem), TRUE); - gtk_menu_item_set_label(GTK_MENU_ITEM(menuitem), _("Skip")); + menuitem = gtk_menu_item_new_with_label(_("Skip")); g_signal_connect(menuitem, "activate", unwanted_cb, treeview); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new()); - menuitem = gtk_image_menu_item_new_with_label(_("Expand All")); + menuitem = gtk_menu_item_new_with_label(_("Expand All")); g_signal_connect(menuitem, "activate", G_CALLBACK(expand_all_cb), treeview); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - menuitem = gtk_image_menu_item_new_with_label(_("Collapse All")); + menuitem = gtk_menu_item_new_with_label(_("Collapse All")); g_signal_connect(menuitem, "activate", G_CALLBACK(collapse_all_cb), treeview); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); diff --git a/src/trg-files-tree-view.c b/src/trg-files-tree-view.c index 1c93ad6..70147f7 100644 --- a/src/trg-files-tree-view.c +++ b/src/trg-files-tree-view.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <gtk/gtk.h> @@ -93,7 +97,7 @@ static gboolean on_files_update(gpointer data) response->cb_data = priv->win; - return on_generic_interactive_action(data); + return on_generic_interactive_action_response(data); } static void send_updated_file_prefs(TrgFilesTreeView * tv) diff --git a/src/trg-files-tree-view.h b/src/trg-files-tree-view.h index dedcb3d..3cfecd7 100644 --- a/src/trg-files-tree-view.h +++ b/src/trg-files-tree-view.h @@ -38,12 +38,12 @@ G_BEGIN_DECLS (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_FILES_TREE_VIEW)) #define TRG_FILES_TREE_VIEW_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_FILES_TREE_VIEW, TrgFilesTreeViewClass)) - typedef struct { - GtkTreeView parent; +typedef struct { + TrgTreeView parent; } TrgFilesTreeView; typedef struct { - GtkTreeViewClass parent_class; + TrgTreeViewClass parent_class; } TrgFilesTreeViewClass; enum { diff --git a/src/trg-files-tree.c b/src/trg-files-tree.c index b3a3df9..1c93a8f 100644 --- a/src/trg-files-tree.c +++ b/src/trg-files-tree.c @@ -20,6 +20,11 @@ /* This is the stuff common between both files trees, built up before * populating the model. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> diff --git a/src/trg-general-panel.c b/src/trg-general-panel.c index cec641a..7cb2a90 100644 --- a/src/trg-general-panel.c +++ b/src/trg-general-panel.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <string.h> #include <glib-object.h> #include <glib/gi18n.h> @@ -27,6 +31,7 @@ #include "util.h" #include "trg-general-panel.h" #include "trg-torrent-model.h" +#include "protocol-constants.h" #define TRG_GENERAL_PANEL_WIDTH_FROM_KEY 20 #define TRG_GENERAL_PANEL_WIDTH_FROM_VALUE 60 @@ -53,12 +58,15 @@ struct _TrgGeneralPanelPrivate { GtkLabel *gen_seeders_label; GtkLabel *gen_leechers_label; GtkLabel *gen_status_label; + GtkLabel *gen_priority_label; GtkLabel *gen_eta_label; GtkLabel *gen_downloaded_label; GtkLabel *gen_uploaded_label; + GtkLabel *gen_corrupted_label; GtkLabel *gen_down_rate_label; GtkLabel *gen_up_rate_label; GtkLabel *gen_ratio_label; + GtkLabel *gen_limit_label; GtkLabel *gen_completedat_label; GtkLabel *gen_downloaddir_label; GtkLabel *gen_comment_label; @@ -77,12 +85,15 @@ void trg_general_panel_clear(TrgGeneralPanel * panel) gtk_label_clear(priv->gen_seeders_label); gtk_label_clear(priv->gen_leechers_label); gtk_label_clear(priv->gen_status_label); + gtk_label_clear(priv->gen_priority_label); gtk_label_clear(priv->gen_eta_label); gtk_label_clear(priv->gen_downloaded_label); gtk_label_clear(priv->gen_uploaded_label); + gtk_label_clear(priv->gen_corrupted_label); gtk_label_clear(priv->gen_down_rate_label); gtk_label_clear(priv->gen_up_rate_label); gtk_label_clear(priv->gen_ratio_label); + gtk_label_clear(priv->gen_limit_label); gtk_label_clear(priv->gen_completedat_label); gtk_label_clear(priv->gen_downloaddir_label); gtk_label_clear(priv->gen_comment_label); @@ -111,12 +122,10 @@ trg_general_panel_update(TrgGeneralPanel * panel, JsonObject * t, GtkTreeIter * iter) { TrgGeneralPanelPrivate *priv; - gchar buf[32]; - gint sizeOfBuf; - gchar *statusString, *fullStatusString, *completedAtString, *comment, - *markup; + gchar buf[32], buf1[32]; //TODO: do it better + gchar *statusString, *fullStatusString, *completedAtString, *speed, *comment, *markup; const gchar *errorStr; - gint64 eta, uploaded, haveValid, completedAt; + gint64 eta, uploaded, corrupted, haveValid, completedAt; GtkLabel *keyLabel; gint64 seeders = 0, leechers = 0; @@ -127,16 +136,30 @@ trg_general_panel_update(TrgGeneralPanel * panel, JsonObject * t, TORRENT_COLUMN_LEECHERS, &leechers, TORRENT_COLUMN_STATUS, &statusString, -1); - sizeOfBuf = sizeof(buf); - trg_strlsize(buf, torrent_get_size_when_done(t)); gtk_label_set_text(GTK_LABEL(priv->gen_size_label), buf); - trg_strlspeed(buf, torrent_get_rate_down(t) / disk_K); - gtk_label_set_text(GTK_LABEL(priv->gen_down_rate_label), buf); - - trg_strlspeed(buf, torrent_get_rate_up(t) / disk_K); - gtk_label_set_text(GTK_LABEL(priv->gen_up_rate_label), buf); + trg_strlspeed(buf, torrent_get_rate_down(t) / disk_K); + if (torrent_get_download_limited(t)){ + trg_strlspeed(buf1, torrent_get_download_limit(t)); + speed = g_strdup_printf("%s [%s]", buf, buf1); + } else + speed = g_strdup_printf("%s", buf); + gtk_label_set_text(GTK_LABEL(priv->gen_down_rate_label), speed); + g_free(speed); + + trg_strlspeed(buf, torrent_get_rate_up(t) / disk_K); + if (torrent_get_upload_limited(t)){ + trg_strlspeed(buf1, torrent_get_upload_limit(t)); + speed = g_strdup_printf("%s [%s]", buf, buf1); + } else + speed = g_strdup_printf("%s", buf); + gtk_label_set_text(GTK_LABEL(priv->gen_up_rate_label), speed); + g_free(speed); + + corrupted = torrent_get_corrupted(t); + trg_strlsize(buf, corrupted); + gtk_label_set_text(GTK_LABEL(priv->gen_corrupted_label), buf); uploaded = torrent_get_uploaded(t); trg_strlsize(buf, uploaded); @@ -153,6 +176,9 @@ trg_general_panel_update(TrgGeneralPanel * panel, JsonObject * t, gtk_label_set_text(GTK_LABEL(priv->gen_ratio_label), _("N/A")); } + trg_strlratio(buf, torrent_get_seed_ratio_limit(t)); + gtk_label_set_text(GTK_LABEL(priv->gen_limit_label), buf); + completedAt = torrent_get_done_date(t); if (completedAt > 0) { completedAtString = epoch_to_string(completedAt); @@ -171,6 +197,18 @@ trg_general_panel_update(TrgGeneralPanel * panel, JsonObject * t, g_free(fullStatusString); g_free(statusString); + switch(torrent_get_bandwidth_priority(t)){ + case TR_PRI_LOW: + gtk_label_set_text(GTK_LABEL(priv->gen_priority_label), _("Low")); + break; + case TR_PRI_NORMAL: + gtk_label_set_text(GTK_LABEL(priv->gen_priority_label), _("Normal")); + break; + case TR_PRI_HIGH: + gtk_label_set_text(GTK_LABEL(priv->gen_priority_label), _("High")); + break; + } + trg_strlpercent(buf, torrent_get_percent_done(t)); gtk_label_set_text(GTK_LABEL(priv->gen_completed_label), buf); @@ -206,16 +244,16 @@ trg_general_panel_update(TrgGeneralPanel * panel, JsonObject * t, } if ((eta = torrent_get_eta(t)) > 0) { - tr_strltime_long(buf, eta, sizeOfBuf); + tr_strltime_long(buf, eta, sizeof(buf)); gtk_label_set_text(GTK_LABEL(priv->gen_eta_label), buf); } else { gtk_label_set_text(GTK_LABEL(priv->gen_eta_label), _("N/A")); } - snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT, + g_snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT, seeders >= 0 ? seeders : 0); gtk_label_set_text(GTK_LABEL(priv->gen_seeders_label), buf); - snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT, + g_snprintf(buf, sizeof(buf), "%" G_GINT64_FORMAT, leechers >= 0 ? leechers : 0); gtk_label_set_text(GTK_LABEL(priv->gen_leechers_label), buf); } @@ -274,48 +312,52 @@ static void trg_general_panel_init(TrgGeneralPanel * self) g_object_set(G_OBJECT(self), "n-columns", TRG_GENERAL_PANEL_COLUMNS_TOTAL, "n-rows", 7, NULL); - priv->gen_name_label = - trg_general_panel_add_label_with_width(self, _("Name"), 0, 0, -1); - - priv->gen_size_label = - trg_general_panel_add_label(self, _("Size"), 0, 1); - priv->gen_eta_label = - trg_general_panel_add_label(self, _("ETA"), 1, 1); - priv->gen_completed_label = - trg_general_panel_add_label(self, _("Completed"), 2, 1); - - priv->gen_seeders_label = - trg_general_panel_add_label(self, _("Seeders"), 0, 2); - priv->gen_down_rate_label = - trg_general_panel_add_label(self, _("Rate Down"), 1, 2); - priv->gen_downloaded_label = - trg_general_panel_add_label(self, _("Downloaded"), 2, 2); - - priv->gen_leechers_label = - trg_general_panel_add_label(self, _("Leechers"), 0, 3); - priv->gen_up_rate_label = - trg_general_panel_add_label(self, _("Rate Up"), 1, 3); - priv->gen_uploaded_label = - trg_general_panel_add_label(self, _("Uploaded"), 2, 3); - - priv->gen_status_label = - trg_general_panel_add_label(self, _("Status"), 0, 4); - priv->gen_ratio_label = - trg_general_panel_add_label(self, _("Ratio"), 1, 4); - - priv->gen_comment_label = - trg_general_panel_add_label(self, _("Comment"), 2, 4); - - priv->gen_completedat_label = - trg_general_panel_add_label_with_width(self, _("Completed At"), 0, - 5, -1); - - priv->gen_downloaddir_label = - trg_general_panel_add_label_with_width(self, _("Location"), 1, 5, - -1); - - priv->gen_error_label = - trg_general_panel_add_label_with_width(self, "", 0, 6, -1); + priv->gen_name_label = + trg_general_panel_add_label_with_width(self, _("Name"), 0, 0, -1); + + priv->gen_size_label = + trg_general_panel_add_label(self, _("Size"), 0, 1); + priv->gen_down_rate_label = + trg_general_panel_add_label(self, _("Rate Down"), 1, 1); + priv->gen_completed_label = + trg_general_panel_add_label(self, _("Completed"), 2, 1); + + priv->gen_eta_label = + trg_general_panel_add_label(self, _("ETA"), 0, 2); + priv->gen_up_rate_label = + trg_general_panel_add_label(self, _("Rate Up"), 1, 2); + priv->gen_downloaded_label = + trg_general_panel_add_label(self, _("Downloaded"), 2, 2); + + priv->gen_seeders_label = + trg_general_panel_add_label(self, _("Seeders"), 0, 3); + priv->gen_ratio_label = + trg_general_panel_add_label(self, _("Ratio"), 1, 3); + priv->gen_uploaded_label = + trg_general_panel_add_label(self, _("Uploaded"), 2, 3); + + priv->gen_leechers_label = + trg_general_panel_add_label(self, _("Leechers"), 0, 4); + priv->gen_limit_label = + trg_general_panel_add_label(self, _("Ratio limit"), 1, 4); + priv->gen_corrupted_label = + trg_general_panel_add_label(self, _("Corrupted"), 2, 4); + + priv->gen_status_label = + trg_general_panel_add_label(self, _("Status"), 0, 5); + priv->gen_priority_label = + trg_general_panel_add_label(self, _("Priority"), 1, 5); + priv->gen_completedat_label = + trg_general_panel_add_label(self, _("Completed At"), 2, 5); + + priv->gen_downloaddir_label = + trg_general_panel_add_label_with_width(self, _("Location"), 0, 6, -1); + + priv->gen_comment_label = + trg_general_panel_add_label(self, _("Comment"), 0, 7); + + priv->gen_error_label = + trg_general_panel_add_label_with_width(self, "", 0, 8, -1); for (i = 0; i < TRG_GENERAL_PANEL_COLUMNS_TOTAL; i++) gtk_table_set_col_spacing(GTK_TABLE(self), i, diff --git a/src/trg-gtk-app.c b/src/trg-gtk-app.c index a0c9ac4..7865767 100644 --- a/src/trg-gtk-app.c +++ b/src/trg-gtk-app.c @@ -17,33 +17,42 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <gtk/gtk.h> +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif -#if GTK_CHECK_VERSION( 3, 0, 0 ) +#include <glib/gi18n.h> +#include <gtk/gtk.h> #include "trg-main-window.h" #include "trg-gtk-app.h" #include "util.h" enum { - PROP_0, PROP_CLIENT, PROP_MINIMISE_ON_START + PROP_0, + PROP_CLIENT, + PROP_MINIMISE_ON_START, + N_PROPS, }; -G_DEFINE_TYPE(TrgGtkApp, trg_gtk_app, GTK_TYPE_APPLICATION) -#define GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_GTK_APP, TrgGtkAppPrivate)) -typedef struct _TrgGtkAppPrivate TrgGtkAppPrivate; +struct _TrgGtkApp +{ + GtkApplication parent; +}; -struct _TrgGtkAppPrivate { +typedef struct +{ TrgClient *client; gboolean min_start; -}; +} TrgGtkAppPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE(TrgGtkApp, trg_gtk_app, GTK_TYPE_APPLICATION) static void trg_gtk_app_get_property(GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { - TrgGtkAppPrivate *priv = GET_PRIVATE(object); + TrgGtkAppPrivate *priv = trg_gtk_app_get_instance_private (TRG_GTK_APP(object)); switch (property_id) { case PROP_CLIENT: g_value_set_pointer(value, priv->client); @@ -61,7 +70,7 @@ static void trg_gtk_app_set_property(GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { - TrgGtkAppPrivate *priv = GET_PRIVATE(object); + TrgGtkAppPrivate *priv = trg_gtk_app_get_instance_private (TRG_GTK_APP(object)); switch (property_id) { case PROP_CLIENT: priv->client = g_value_get_pointer(value); @@ -75,22 +84,12 @@ trg_gtk_app_set_property(GObject * object, guint property_id, } } -static void trg_gtk_app_dispose(GObject * object) -{ - G_OBJECT_CLASS(trg_gtk_app_parent_class)->dispose(object); -} - -static void trg_gtk_app_finalize(GObject * object) -{ - G_OBJECT_CLASS(trg_gtk_app_parent_class)->finalize(object); -} - -static void trg_gtk_app_startup(GtkApplication * app, gpointer data) +static void trg_gtk_app_startup(GApplication * app, gpointer userdata) { - TrgGtkAppPrivate *priv = GET_PRIVATE(app); + TrgGtkAppPrivate *priv = trg_gtk_app_get_instance_private (TRG_GTK_APP(app)); TrgMainWindow *window = trg_main_window_new(priv->client, priv->min_start); - gtk_window_set_application(GTK_WINDOW(window), app); + gtk_window_set_application(GTK_WINDOW(window), GTK_APPLICATION(app)); } static int @@ -135,7 +134,7 @@ static gboolean test_local_cmdline(GApplication * application, gchar *** arguments, gint * exit_status) { - TrgGtkAppPrivate *priv = GET_PRIVATE(application); + TrgGtkAppPrivate *priv = trg_gtk_app_get_instance_private (TRG_GTK_APP(application)); gchar **argv; gchar *cwd = g_get_current_dir(); gchar *tmp; @@ -144,7 +143,7 @@ test_local_cmdline(GApplication * application, argv = *arguments; shift_args(argv, 0); - i = 1; + i = 0; while (argv[i]) { if (is_minimised_arg(argv[i])) { shift_args(argv, i); @@ -171,44 +170,30 @@ static void trg_gtk_app_class_init(TrgGtkAppClass * klass) GObjectClass *object_class = G_OBJECT_CLASS(klass); GApplicationClass *app_class = G_APPLICATION_CLASS(klass); - g_type_class_add_private(klass, sizeof(TrgGtkAppPrivate)); - object_class->get_property = trg_gtk_app_get_property; object_class->set_property = trg_gtk_app_set_property; - object_class->dispose = trg_gtk_app_dispose; - object_class->finalize = trg_gtk_app_finalize; app_class->local_command_line = test_local_cmdline; + //app_class->startup = trg_gtk_app_startup; + app_class->command_line = trg_gtk_app_command_line; g_object_class_install_property(object_class, PROP_CLIENT, g_param_spec_pointer("trg-client", "TClient", - "Client", - G_PARAM_READWRITE - | - G_PARAM_CONSTRUCT_ONLY - | - G_PARAM_STATIC_NAME - | - G_PARAM_STATIC_NICK - | - G_PARAM_STATIC_BLURB)); + _("Client"), + G_PARAM_READWRITE| + G_PARAM_CONSTRUCT_ONLY| + G_PARAM_STATIC_STRINGS)); g_object_class_install_property(object_class, PROP_MINIMISE_ON_START, g_param_spec_boolean("min-on-start", "Min On Start", - "Min On Start", + _("Min On Start"), FALSE, - G_PARAM_READWRITE - | - G_PARAM_CONSTRUCT_ONLY - | - G_PARAM_STATIC_NAME - | - G_PARAM_STATIC_NICK - | - G_PARAM_STATIC_BLURB)); + G_PARAM_READWRITE| + G_PARAM_CONSTRUCT_ONLY| + G_PARAM_STATIC_STRINGS)); } static void trg_gtk_app_init(TrgGtkApp * self) @@ -216,8 +201,8 @@ static void trg_gtk_app_init(TrgGtkApp * self) g_application_set_inactivity_timeout(G_APPLICATION(self), 10000); g_signal_connect(self, "command-line", G_CALLBACK(trg_gtk_app_command_line), NULL); - g_signal_connect(self, "startup", G_CALLBACK(trg_gtk_app_startup), - NULL); + g_signal_connect(self, "startup", + G_CALLBACK(trg_gtk_app_startup), NULL); } TrgGtkApp *trg_gtk_app_new(TrgClient * client) @@ -227,5 +212,3 @@ TrgGtkApp *trg_gtk_app_new(TrgClient * client) "flags", G_APPLICATION_HANDLES_COMMAND_LINE, "trg-client", client, NULL); } - -#endif diff --git a/src/trg-gtk-app.h b/src/trg-gtk-app.h index b60425a..e369fae 100644 --- a/src/trg-gtk-app.h +++ b/src/trg-gtk-app.h @@ -17,39 +17,17 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include <gtk/gtk.h> - -#ifndef TRG_GTKAPP_ -#define TRG_GTKAPP_ -#if GTK_CHECK_VERSION( 3, 0, 0 ) -#include <glib-object.h> +#pragma once +#include <gtk/gtk.h> #include "trg-client.h" G_BEGIN_DECLS -#define TRG_TYPE_GTK_APP trg_gtk_app_get_type() -#define TRG_GTK_APP(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_GTK_APP, TrgGtkApp)) -#define TRG_GTK_APP_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_GTK_APP, TrgGtkAppClass)) -#define TRG_IS_GTK_APP(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_GTK_APP)) -#define TRG_IS_GTK_APP_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_GTK_APP)) -#define TRG_GTK_APP_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_GTK_APP, TrgGtkAppClass)) - typedef struct { - GtkApplication parent; -} TrgGtkApp; - -typedef struct { - GtkApplicationClass parent_class; -} TrgGtkAppClass; - -GType trg_gtk_app_get_type(void); - -TrgGtkApp *trg_gtk_app_new(TrgClient * client); - -#endif -#endif + +#define TRG_TYPE_GTK_APP (trg_gtk_app_get_type()) +G_DECLARE_FINAL_TYPE (TrgGtkApp, trg_gtk_app, TRG, GTK_APP, GtkApplication) + +TrgGtkApp *trg_gtk_app_new (TrgClient *client); + +G_END_DECLS diff --git a/src/trg-icons.c b/src/trg-icons.c index efa45a7..20fb577 100644 --- a/src/trg-icons.c +++ b/src/trg-icons.c @@ -17,8 +17,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <gtk/gtk.h> +#include "trg-icons.h" #include "icon-turtle.h" typedef struct { diff --git a/src/trg-json-widgets.c b/src/trg-json-widgets.c index abca7e1..79299c6 100644 --- a/src/trg-json-widgets.c +++ b/src/trg-json-widgets.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <gtk/gtk.h> #include <json-glib/json-glib.h> @@ -117,16 +121,6 @@ GtkWidget *trg_json_widget_entry_new(GList ** wl, JsonObject * obj, return w; } -void -trg_json_widget_time_save(GtkWidget * widget, JsonObject * obj, - gchar * key) -{ - - json_object_set_double_member(obj, key, - gtk_spin_button_get_value(GTK_SPIN_BUTTON - (widget))); -} - GtkWidget *trg_json_widget_spin_new(GList ** wl, JsonObject * obj, const gchar * key, GtkWidget * toggleDep, gdouble min, diff --git a/src/trg-main-window.c b/src/trg-main-window.c index 975e68f..d85a364 100644 --- a/src/trg-main-window.c +++ b/src/trg-main-window.c @@ -31,9 +31,7 @@ #include <gtk/gtk.h> #include <json-glib/json-glib.h> #include <gdk/gdkkeysyms.h> -#if GTK_CHECK_VERSION( 3, 0, 0 ) #include <gdk/gdkkeysyms-compat.h> -#endif #include <curl/curl.h> #ifdef HAVE_LIBNOTIFY #include <libnotify/notify.h> @@ -75,8 +73,12 @@ #include "trg-menu-bar.h" #include "trg-status-bar.h" #include "trg-stats-dialog.h" +#ifdef HAVE_RSS +#include "trg-rss-window.h" +#endif #include "trg-remote-prefs-dialog.h" #include "trg-preferences-dialog.h" +#include "upload.h" /* The rather large main window class, which glues everything together. */ @@ -206,9 +208,13 @@ static gboolean window_state_event(TrgMainWindow * win, GdkEventWindowState * event, gpointer trayIcon); +struct _TrgMainWindow +{ + GtkApplicationWindow parent; +}; -G_DEFINE_TYPE(TrgMainWindow, trg_main_window, GTK_TYPE_WINDOW) -struct _TrgMainWindowPrivate { +typedef struct +{ TrgClient *client; TrgToolbar *toolBar; TrgMenuBar *menuBar; @@ -257,7 +263,9 @@ struct _TrgMainWindowPrivate { gboolean queuesEnabled; gchar **args; -}; +} TrgMainWindowPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE(TrgMainWindow, trg_main_window, GTK_TYPE_WINDOW) enum { PROP_0, PROP_CLIENT, PROP_MINIMISE_ON_START @@ -265,7 +273,7 @@ enum { static void reset_connect_args(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (priv->args) { g_strfreev(priv->args); priv->args = NULL; @@ -274,21 +282,18 @@ static void reset_connect_args(TrgMainWindow * win) static void trg_main_window_init(TrgMainWindow * self) { - self->priv = - G_TYPE_INSTANCE_GET_PRIVATE(self, TRG_TYPE_MAIN_WINDOW, - TrgMainWindowPrivate); } gint trg_mw_get_selected_torrent_id(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); return priv->selectedTorrentId; } static void update_selected_torrent_notebook(TrgMainWindow * win, gint mode, gint64 id) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *client = priv->client; gint64 serial = trg_client_get_serial(client); JsonObject *t; @@ -322,7 +327,7 @@ torrent_event_notification(TrgTorrentModel * model, GtkTreeIter * iter, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); gchar *name; NotifyNotification *notify; @@ -388,7 +393,7 @@ delete_event(GtkWidget * w, GdkEvent * event G_GNUC_UNUSED, static void destroy_window(TrgMainWindow * win, gpointer data G_GNUC_UNUSED) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); trg_prefs_set_int(prefs, TRG_PREFS_KEY_WINDOW_HEIGHT, priv->height, @@ -421,7 +426,7 @@ destroy_window(TrgMainWindow * win, gpointer data G_GNUC_UNUSED) TRG_TREE_VIEW_PERSIST_LAYOUT); trg_prefs_save(prefs); -#if ! GTK_CHECK_VERSION( 3, 0, 0 ) +#if WIN32 gtk_main_quit(); #else g_application_quit (g_application_get_default ()); @@ -430,7 +435,7 @@ destroy_window(TrgMainWindow * win, gpointer data G_GNUC_UNUSED) static void open_props_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgTorrentPropsDialog *dialog; if (priv->selectedTorrentId < 0) @@ -456,7 +461,7 @@ torrent_tv_onRowActivated(GtkTreeView * treeview, static void add_url_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgTorrentAddUrlDialog *dlg = trg_torrent_add_url_dialog_new(win, priv-> @@ -467,7 +472,7 @@ static void add_url_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) static void add_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (trg_client_is_connected(priv->client)) trg_torrent_add_dialog(win, priv->client); @@ -475,27 +480,27 @@ static void add_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) static void pause_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (trg_client_is_connected(priv->client)) dispatch_async(priv->client, torrent_pause(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void pause_all_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (trg_client_is_connected(priv->client)) dispatch_async(priv->client, torrent_pause(NULL), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } gint trg_add_from_filename(TrgMainWindow * win, gchar ** uris) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *client = priv->client; TrgPrefs *prefs = trg_client_get_prefs(client); GSList *filesList = NULL; @@ -506,10 +511,14 @@ gint trg_add_from_filename(TrgMainWindow * win, gchar ** uris) return EXIT_SUCCESS; } - if (uris) - for (i = 0; uris[i]; i++) - if (uris[i]) + if (uris) { + for (i = 0; uris[i]; i++) { + if (is_minimised_arg(uris[i])) + g_free(uris[i]); + else if (uris[i]) filesList = g_slist_append(filesList, uris[i]); + } + } g_free(uris); @@ -519,20 +528,21 @@ gint trg_add_from_filename(TrgMainWindow * win, gchar ** uris) if (trg_prefs_get_bool(prefs, TRG_PREFS_KEY_ADD_OPTIONS_DIALOG, TRG_PREFS_GLOBAL)) { TrgTorrentAddDialog *dialog = - trg_torrent_add_dialog_new(win, client, + trg_torrent_add_dialog_new_from_filenames(win, client, filesList); gtk_widget_show_all(GTK_WIDGET(dialog)); + gtk_window_present(GTK_WINDOW(dialog)); } else { - struct add_torrent_threadfunc_args *args = - g_new0(struct add_torrent_threadfunc_args, 1); - args->list = filesList; - args->cb_data = win; - args->client = client; - args->extraArgs = FALSE; - args->flags = trg_prefs_get_add_flags(prefs); - - launch_add_thread(args); + trg_upload *upload = g_new0(trg_upload, 1); + + upload->list = filesList; + upload->main_window = win; + upload->client = client; + upload->extra_args = FALSE; + upload->flags = trg_prefs_get_add_flags(prefs); + + trg_do_upload(upload); } return EXIT_SUCCESS; @@ -540,28 +550,28 @@ gint trg_add_from_filename(TrgMainWindow * win, gchar ** uris) static void resume_all_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (trg_client_is_connected(priv->client)) dispatch_async(priv->client, torrent_start(NULL), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void resume_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (trg_client_is_connected(priv->client)) dispatch_async(priv->client, torrent_start(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void disconnect_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); trg_client_inc_connid(priv->client); trg_main_window_conn_changed(TRG_MAIN_WINDOW(data), FALSE); @@ -571,7 +581,7 @@ static void disconnect_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) void connect_cb(GtkWidget * w, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); JsonObject *currentProfile = trg_prefs_get_profile(prefs); @@ -628,7 +638,7 @@ void connect_cb(GtkWidget * w, gpointer data) static void open_local_prefs_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); GtkWidget *dlg = trg_preferences_dialog_get_instance(win, priv->client); @@ -638,7 +648,7 @@ open_local_prefs_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) static void open_remote_prefs_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (trg_client_is_connected(priv->client)) gtk_widget_show_all(GTK_WIDGET @@ -650,7 +660,7 @@ static void main_window_toggle_filter_dirs(GtkCheckMenuItem * w, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (gtk_widget_is_sensitive(GTK_WIDGET(w))) trg_state_selector_set_show_dirs(priv->stateSelector, @@ -662,7 +672,7 @@ static void main_window_toggle_filter_trackers(GtkCheckMenuItem * w, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (gtk_widget_is_sensitive(GTK_WIDGET(w))) trg_state_selector_set_show_trackers(priv->stateSelector, @@ -670,9 +680,19 @@ main_window_toggle_filter_trackers(GtkCheckMenuItem * w, gpointer data) (w)); } +static void +main_window_toggle_directories_first(GtkCheckMenuItem * w, gpointer data){ + TrgMainWindow *win = TRG_MAIN_WINDOW(data); + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); + + if (gtk_widget_is_sensitive(GTK_WIDGET(w))) + trg_state_selector_set_directories_first(priv->stateSelector, + gtk_check_menu_item_get_active(w)); +} + static TrgToolbar *trg_main_window_toolbar_new(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); GObject *b_connect, *b_disconnect, *b_add, *b_resume, *b_pause; @@ -708,80 +728,80 @@ static TrgToolbar *trg_main_window_toolbar_new(TrgMainWindow * win) static void reannounce_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (trg_client_is_connected(priv->client)) dispatch_async(priv->client, torrent_reannounce(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void verify_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (is_ready_for_torrent_action(win)) dispatch_async(priv->client, torrent_verify(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void start_now_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (is_ready_for_torrent_action(win)) dispatch_async(priv->client, torrent_start_now(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void up_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (priv->queuesEnabled && is_ready_for_torrent_action(win)) dispatch_async(priv->client, torrent_queue_move_up(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void top_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (priv->queuesEnabled && is_ready_for_torrent_action(win)) dispatch_async(priv->client, torrent_queue_move_top(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void bottom_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (priv->queuesEnabled && is_ready_for_torrent_action(win)) dispatch_async(priv->client, torrent_queue_move_bottom(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void down_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (priv->queuesEnabled && is_ready_for_torrent_action(win)) dispatch_async(priv->client, torrent_queue_move_down(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static gint @@ -792,7 +812,7 @@ confirm_action_dialog(GtkWindow * gtk_win, const gchar * action_stock) { TrgMainWindow *win = TRG_MAIN_WINDOW(gtk_win); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); gint selectCount; gint response; GtkWidget *dialog = NULL; @@ -850,14 +870,14 @@ confirm_action_dialog(GtkWindow * gtk_win, static gboolean is_ready_for_torrent_action(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); return priv->selectedTorrentId >= 0 && trg_client_is_connected(priv->client); } static void move_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (is_ready_for_torrent_action(win)) gtk_widget_show_all(GTK_WIDGET @@ -867,7 +887,7 @@ static void move_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) static void remove_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); GtkTreeSelection *selection; JsonArray *ids; @@ -883,14 +903,14 @@ static void remove_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) _("<big><b>Remove %d torrents?</b></big>"), GTK_STOCK_REMOVE) == GTK_RESPONSE_ACCEPT) dispatch_async(priv->client, torrent_remove(ids, FALSE), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); else json_array_unref(ids); } static void delete_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); GtkTreeSelection *selection; JsonArray *ids; @@ -915,7 +935,7 @@ static void delete_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) static void view_stats_toggled_cb(GtkWidget * w, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (trg_client_is_connected(priv->client)) { TrgStatsDialog *dlg = @@ -926,10 +946,26 @@ static void view_stats_toggled_cb(GtkWidget * w, gpointer data) } } +#ifdef HAVE_RSS +static void view_rss_toggled_cb(GtkWidget * w, gpointer data) +{ + TrgMainWindow *win = TRG_MAIN_WINDOW(data); + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); + + if (trg_client_is_connected(priv->client)) { + TrgRssWindow *rss = + trg_rss_window_get_instance(TRG_MAIN_WINDOW(data), priv->client); + + gtk_widget_show_all(GTK_WIDGET(rss)); + gtk_window_present(GTK_WINDOW(rss)); + } +} +#endif + static void view_states_toggled_cb(GtkCheckMenuItem * w, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); trg_widget_set_visible(priv->stateSelectorScroller, gtk_check_menu_item_get_active(w)); @@ -938,7 +974,7 @@ view_states_toggled_cb(GtkCheckMenuItem * w, TrgMainWindow * win) static void view_notebook_toggled_cb(GtkCheckMenuItem * w, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); trg_widget_set_visible(priv->notebook, gtk_check_menu_item_get_active(w)); @@ -949,7 +985,7 @@ static void trg_main_window_toggle_graph_cb(GtkCheckMenuItem * w, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (!gtk_widget_is_sensitive(GTK_WIDGET(w))) { return; @@ -965,13 +1001,13 @@ trg_main_window_toggle_graph_cb(GtkCheckMenuItem * w, gpointer data) void trg_main_window_notebook_set_visible(TrgMainWindow * win, gboolean visible) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); trg_widget_set_visible(priv->notebook, visible); } static GtkWidget *trg_main_window_notebook_new(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); GtkWidget *notebook = priv->notebook = gtk_notebook_new(); @@ -1029,7 +1065,7 @@ gboolean on_session_set(gpointer data) { trg_response *response = (trg_response *) data; TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (response->status == CURLE_OK || response->status == FAIL_RESPONSE_UNSUCCESSFUL) @@ -1053,7 +1089,7 @@ static gboolean on_session_get_timer(gpointer data) { trg_response *response = (trg_response *) data; TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); on_session_get(data); @@ -1071,7 +1107,7 @@ static gboolean on_session_get(gpointer data) { trg_response *response = (trg_response *) data; TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *client = priv->client; gboolean isConnected = trg_client_is_connected(client); @@ -1156,7 +1192,7 @@ TRANSMISSION_MIN_SUPPORTED, version); static void connchange_whatever_statusicon(TrgMainWindow * win, gboolean connected) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); gchar *display = connected ? trg_prefs_get_string(prefs, TRG_PREFS_KEY_PROFILE_NAME, @@ -1187,7 +1223,7 @@ static void update_whatever_statusicon(TrgMainWindow * win, trg_torrent_model_update_stats * stats) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); #ifdef HAVE_LIBAPPINDICATOR if (!priv->appIndicator && !priv->statusIcon) @@ -1229,7 +1265,7 @@ static gboolean on_torrent_get(gpointer data, int mode) { trg_response *response = (trg_response *) data; TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *client = priv->client; TrgPrefs *prefs = trg_client_get_prefs(client); trg_torrent_model_update_stats *stats; @@ -1333,7 +1369,7 @@ static gboolean on_torrent_get_first(gpointer data) { trg_response *response = (trg_response *) data; TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); gboolean result = on_torrent_get(data, TORRENT_GET_MODE_FIRST); @@ -1358,7 +1394,7 @@ static gboolean on_torrent_get_update(gpointer data) static gboolean trg_session_update_timerfunc(gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); trg_client_update_session(priv->client, on_session_get_timer, win); @@ -1373,7 +1409,7 @@ static gboolean trg_update_torrents_timerfunc(gpointer data) return FALSE; TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *tc = priv->client; TrgPrefs *prefs = trg_client_get_prefs(tc); @@ -1411,7 +1447,7 @@ trg_torrent_tree_view_visible_func(GtkTreeModel * model, GtkTreeIter * iter, gpointer data) { TrgMainWindow *win = TRG_MAIN_WINDOW(data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); guint flags; gboolean visible; const gchar *filterText; @@ -1478,7 +1514,7 @@ trg_torrent_tree_view_visible_func(GtkTreeModel * model, void trg_main_window_reload_dir_aliases(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); trg_torrent_model_reload_dir_aliases(priv->client, GTK_TREE_MODEL (priv->torrentModel)); } @@ -1487,7 +1523,7 @@ static TrgTorrentTreeView * trg_main_window_torrent_tree_view_new(TrgMainWindow * win, GtkTreeModel * model) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgTorrentTreeView *torrentTreeView = trg_torrent_tree_view_new(priv->client, model); @@ -1504,7 +1540,7 @@ static TrgTorrentTreeView static gboolean trg_dialog_error_handler(TrgMainWindow * win, trg_response * response) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (response->status != CURLE_OK) { GtkWidget *dialog; @@ -1530,7 +1566,7 @@ static gboolean torrent_selection_changed(GtkTreeSelection * selection, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); GList *selectionList; GList *firstNode; gint64 id; @@ -1565,21 +1601,18 @@ gboolean on_delete_complete(gpointer data) { trg_response *response = (trg_response *) data; TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *tc = priv->client; if (trg_client_is_connected(tc) && response->status == CURLE_OK) trg_client_update_session(priv->client, on_session_get, response->cb_data); - return on_generic_interactive_action(data); + return on_generic_interactive_action_response(data); } -gboolean on_generic_interactive_action(gpointer data) -{ - trg_response *response = (trg_response *) data; - TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); - TrgMainWindowPrivate *priv = win->priv; +void on_generic_interactive_action(TrgMainWindow *win, trg_response *response) { + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *tc = priv->client; if (trg_client_is_connected(tc)) { @@ -1598,12 +1631,21 @@ gboolean on_generic_interactive_action(gpointer data) } trg_response_free(response); +} + +gboolean on_generic_interactive_action_response(gpointer data) +{ + trg_response *response = (trg_response *) data; + TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); + + on_generic_interactive_action(win, response); + return FALSE; } static void trg_main_window_torrent_scrub(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); gtk_tree_store_clear(GTK_TREE_STORE(priv->filesModel)); gtk_list_store_clear(GTK_LIST_STORE(priv->trackersModel)); @@ -1618,7 +1660,7 @@ static void trg_main_window_torrent_scrub(TrgMainWindow * win) static void entry_filter_changed_cb(GtkWidget * w, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); gboolean clearSensitive = gtk_entry_get_text_length(GTK_ENTRY(w)) > 0; gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER @@ -1639,7 +1681,7 @@ torrent_state_selection_changed(TrgStateSelector * static void trg_main_window_conn_changed(TrgMainWindow * win, gboolean connected) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *tc = priv->client; trg_toolbar_connected_change(priv->toolBar, connected); @@ -1686,7 +1728,7 @@ trg_main_window_get_property(GObject * object, GParamSpec * pspec) { TrgMainWindow *win = TRG_MAIN_WINDOW(object); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); switch (property_id) { case PROP_CLIENT: @@ -1707,7 +1749,7 @@ trg_main_window_set_property(GObject * object, const GValue * value, GParamSpec * pspec) { TrgMainWindow *win = TRG_MAIN_WINDOW(object); - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); switch (property_id) { case PROP_CLIENT: @@ -1729,17 +1771,20 @@ static void quit_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) static TrgMenuBar *trg_main_window_menu_bar_new(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); GObject *b_disconnect, *b_add, *b_resume, *b_pause, *b_verify, *b_remove, *b_delete, *b_props, *b_local_prefs, *b_remote_prefs, *b_about, *b_view_states, *b_view_notebook, *b_view_stats, *b_add_url, *b_quit, *b_move, *b_reannounce, *b_pause_all, - *b_resume_all, *b_dir_filters, *b_tracker_filters, *b_up_queue, - *b_down_queue, *b_top_queue, *b_bottom_queue, + *b_resume_all, *b_dir_filters, *b_tracker_filters, *b_directories_first, + *b_up_queue, *b_down_queue, *b_top_queue, *b_bottom_queue, #if TRG_WITH_GRAPH *b_show_graph, #endif +#ifdef HAVE_RSS + *b_view_rss, +#endif *b_start_now; TrgMenuBar *menuBar; @@ -1764,10 +1809,13 @@ static TrgMenuBar *trg_main_window_menu_bar_new(TrgMainWindow * win) "view-states-button", &b_view_states, "view-stats-button", &b_view_stats, "about-button", &b_about, "quit-button", &b_quit, "dir-filters", &b_dir_filters, "tracker-filters", - &b_tracker_filters, + &b_tracker_filters, TRG_PREFS_KEY_DIRECTORIES_FIRST, &b_directories_first, #if TRG_WITH_GRAPH "show-graph", &b_show_graph, #endif +#ifdef HAVE_RSS + "view-rss-button", &b_view_rss, +#endif "up-queue", &b_up_queue, "down-queue", &b_down_queue, "top-queue", &b_top_queue, "bottom-queue", &b_bottom_queue, "start-now", &b_start_now, NULL); @@ -1808,10 +1856,16 @@ static TrgMenuBar *trg_main_window_menu_bar_new(TrgMainWindow * win) G_CALLBACK(main_window_toggle_filter_dirs), win); g_signal_connect(b_tracker_filters, "toggled", G_CALLBACK(main_window_toggle_filter_trackers), win); + g_signal_connect(b_directories_first, "toggled", + G_CALLBACK(main_window_toggle_directories_first), win); g_signal_connect(b_view_states, "toggled", G_CALLBACK(view_states_toggled_cb), win); g_signal_connect(b_view_stats, "activate", G_CALLBACK(view_stats_toggled_cb), win); +#ifdef HAVE_RSS + g_signal_connect(b_view_rss, "activate", + G_CALLBACK(view_rss_toggled_cb), win); +#endif #if TRG_WITH_GRAPH g_signal_connect(b_show_graph, "toggled", G_CALLBACK(trg_main_window_toggle_graph_cb), win); @@ -1828,7 +1882,7 @@ static void status_icon_activated(GtkStatusIcon * icon G_GNUC_UNUSED, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); trg_main_window_set_hidden_to_tray(win, @@ -1841,7 +1895,7 @@ status_icon_activated(GtkStatusIcon * icon G_GNUC_UNUSED, static gboolean trg_status_icon_popup_menu_cb(GtkStatusIcon * icon, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); gtk_menu_popup(priv->iconMenu, NULL, NULL, #ifdef WIN32 @@ -1858,7 +1912,7 @@ static gboolean status_icon_button_press_event(GtkStatusIcon * icon, GdkEventButton * event, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (event->type == GDK_BUTTON_PRESS && event->button == 3) { @@ -1905,7 +1959,7 @@ static GtkWidget *trg_imagemenuitem_new(GtkMenuShell * shell, static void set_limit_cb(GtkWidget * w, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); GtkWidget *parent = gtk_widget_get_parent(w); @@ -1930,7 +1984,7 @@ static void set_limit_cb(GtkWidget * w, TrgMainWindow * win) json_object_set_boolean_member(args, enabledKey, speed >= 0); if (limitIds) - dispatch_async(priv->client, req, on_generic_interactive_action, + dispatch_async(priv->client, req, on_generic_interactive_action_response, win); else dispatch_async(priv->client, req, on_session_set, win); @@ -1938,7 +1992,7 @@ static void set_limit_cb(GtkWidget * w, TrgMainWindow * win) static void set_priority_cb(GtkWidget * w, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); GtkWidget *parent = gtk_widget_get_parent(w); @@ -1955,7 +2009,7 @@ static void set_priority_cb(GtkWidget * w, TrgMainWindow * win) json_object_set_int_member(args, FIELD_BANDWIDTH_PRIORITY, priority); - dispatch_async(priv->client, req, on_generic_interactive_action, win); + dispatch_async(priv->client, req, on_generic_interactive_action_response, win); } static GtkWidget *limit_item_new(TrgMainWindow * win, GtkWidget * menu, @@ -1997,7 +2051,7 @@ static GtkWidget *priority_menu_item_new(TrgMainWindow * win, static GtkWidget *priority_menu_new(TrgMainWindow * win, JsonArray * ids) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *client = priv->client; JsonObject *t = NULL; gint selected_pri = TR_PRI_UNSET; @@ -2034,7 +2088,7 @@ static GtkWidget *limit_menu_new(TrgMainWindow * win, gchar * title, gchar * enabledKey, gchar * speedKey, JsonArray * ids) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgClient *client = priv->client; JsonObject *current = NULL; GtkTreeIter iter; @@ -2102,7 +2156,7 @@ static GtkWidget *limit_menu_new(TrgMainWindow * win, gchar * title, static void exec_cmd_cb(GtkWidget * w, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); JsonObject *cmd_obj = (JsonObject *) g_object_get_data(G_OBJECT(w), "cmd-object"); GtkTreeSelection *selection = @@ -2157,7 +2211,7 @@ static void trg_torrent_tv_view_menu(GtkWidget * treeview, GdkEventButton * event, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); GtkWidget *menu; gint n_cmds; @@ -2188,8 +2242,8 @@ trg_torrent_tv_view_menu(GtkWidget * treeview, trg_imagemenuitem_new(GTK_MENU_SHELL(menu), _("Remove"), GTK_STOCK_REMOVE, TRUE, G_CALLBACK(remove_cb), win); - trg_imagemenuitem_new(GTK_MENU_SHELL(menu), _("Remove & Delete"), - GTK_STOCK_CLEAR, TRUE, G_CALLBACK(delete_cb), + trg_imagemenuitem_new(GTK_MENU_SHELL(menu), _("Remove and delete data"), + GTK_STOCK_DELETE, TRUE, G_CALLBACK(delete_cb), win); cmds = trg_prefs_get_array(prefs, TRG_PREFS_KEY_EXEC_COMMANDS, @@ -2283,7 +2337,7 @@ trg_torrent_tv_view_menu(GtkWidget * treeview, static GtkMenu *trg_status_icon_view_menu(TrgMainWindow * win, const gchar * msg) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); gboolean connected = trg_client_is_connected(priv->client); GtkWidget *menu, *connect; @@ -2403,7 +2457,7 @@ static void trg_main_window_set_hidden_to_tray(TrgMainWindow * win, gboolean hidden) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (hidden) { gtk_widget_hide(GTK_WIDGET(win)); @@ -2426,7 +2480,7 @@ static gboolean window_state_event(TrgMainWindow * win, GdkEventWindowState * event, gpointer trayIcon) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); if (priv->statusIcon @@ -2443,7 +2497,7 @@ window_state_event(TrgMainWindow * win, void trg_main_window_remove_status_icon(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); #ifdef HAVE_LIBAPPINDICATOR if (priv->appIndicator) { g_object_unref(G_OBJECT(priv->appIndicator)); @@ -2463,7 +2517,7 @@ void trg_main_window_remove_status_icon(TrgMainWindow * win) #if TRG_WITH_GRAPH void trg_main_window_add_graph(TrgMainWindow * win, gboolean show) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); priv->graph = trg_torrent_graph_new(gtk_widget_get_style(priv->notebook)); @@ -2480,7 +2534,7 @@ void trg_main_window_add_graph(TrgMainWindow * win, gboolean show) void trg_main_window_remove_graph(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if (priv->graphNotebookIndex >= 0) { gtk_notebook_remove_page(GTK_NOTEBOOK(priv->notebook), @@ -2500,9 +2554,9 @@ void trg_main_window_remove_graph(TrgMainWindow * win) void trg_main_window_add_status_icon(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); #ifdef HAVE_LIBAPPINDICATOR - if (is_unity() && (priv->appIndicator = + if ((priv->appIndicator = app_indicator_new(PACKAGE_NAME, PACKAGE_NAME, APP_INDICATOR_CATEGORY_APPLICATION_STATUS))) { @@ -2512,7 +2566,7 @@ void trg_main_window_add_status_icon(TrgMainWindow * win) trg_status_icon_view_menu(win, NULL)); } else { #else - if (!is_unity()) { + if (1) { #endif priv->statusIcon = gtk_status_icon_new_from_icon_name(PACKAGE_NAME); @@ -2534,7 +2588,7 @@ void trg_main_window_add_status_icon(TrgMainWindow * win) TrgStateSelector *trg_main_window_get_state_selector(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); return priv->stateSelector; } @@ -2545,7 +2599,7 @@ trg_main_window_config_event(TrgMainWindow * win, GdkEvent * event, gpointer user_data G_GNUC_UNUSED) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); priv->width = event->configure.width; priv->height = event->configure.height; return FALSE; @@ -2555,7 +2609,7 @@ static void trg_client_session_updated_cb(TrgClient * tc, JsonObject * session, TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); gboolean queuesEnabled; trg_status_bar_session_update(priv->statusBar, session); @@ -2615,10 +2669,11 @@ static gboolean window_key_press_handler(GtkWidget * widget, gpointer user_data) { TrgMainWindow *win = TRG_MAIN_WINDOW(widget); + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); if ((event->key.state & GDK_CONTROL_MASK) && event->key.keyval == GDK_k) { - gtk_widget_grab_focus(win->priv->filterEntry); + gtk_widget_grab_focus(priv->filterEntry); return TRUE; } @@ -2641,7 +2696,7 @@ static GObject *trg_main_window_constructor(GType type, GtkWidget *w; GtkWidget *outerVbox; GtkWidget *toolbarHbox; - GtkWidget *outerAlignment; + //GtkWidget *outerAlignment; GtkIconTheme *theme; gint width, height, pos; gboolean tray; @@ -2704,15 +2759,15 @@ static GObject *trg_main_window_constructor(GType type, g_signal_connect(priv->torrentTreeView, "row-activated", G_CALLBACK(torrent_tv_onRowActivated), self); - outerVbox = trg_vbox_new(FALSE, 2); + outerVbox = trg_vbox_new(FALSE, 0); /* Create a GtkAlignment to hold the outerVbox making possible * some padding. */ - outerAlignment = gtk_alignment_new (0.5f, 0.5f, 1.0f, 1.0f); - gtk_alignment_set_padding (GTK_ALIGNMENT (outerAlignment), 0, 0, 6, 6); - gtk_container_add (GTK_CONTAINER (outerAlignment), outerVbox); + //outerAlignment = gtk_alignment_new (0.5f, 0.5f, 1.0f, 1.0f); + //gtk_alignment_set_padding (GTK_ALIGNMENT (outerAlignment), 0, 0, 0, 0); + //gtk_container_add (GTK_CONTAINER (outerAlignment), outerVbox); - gtk_container_add(GTK_CONTAINER(self), outerAlignment); + gtk_container_add(GTK_CONTAINER(self), outerVbox); priv->menuBar = trg_main_window_menu_bar_new(self); gtk_box_pack_start(GTK_BOX(outerVbox), GTK_WIDGET(priv->menuBar), @@ -2738,13 +2793,8 @@ static GObject *trg_main_window_constructor(GType type, gtk_box_pack_start(GTK_BOX(outerVbox), GTK_WIDGET(toolbarHbox), FALSE, FALSE, 0); -#if GTK_CHECK_VERSION( 3, 0, 0 ) priv->hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL); priv->vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL); -#else - priv->vpaned = gtk_vpaned_new(); - priv->hpaned = gtk_hpaned_new(); -#endif gtk_box_pack_start(GTK_BOX(outerVbox), priv->vpaned, TRUE, TRUE, 0); gtk_paned_pack1(GTK_PANED(priv->vpaned), priv->hpaned, TRUE, TRUE); @@ -2837,8 +2887,6 @@ static void trg_main_window_class_init(TrgMainWindowClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); - g_type_class_add_private(klass, sizeof(TrgMainWindowPrivate)); - object_class->constructor = trg_main_window_constructor; object_class->get_property = trg_main_window_get_property; object_class->set_property = trg_main_window_set_property; @@ -2848,15 +2896,9 @@ static void trg_main_window_class_init(TrgMainWindowClass * klass) g_param_spec_pointer("trg-client", "TClient", "Client", - G_PARAM_READWRITE - | - G_PARAM_CONSTRUCT_ONLY - | - G_PARAM_STATIC_NAME - | - G_PARAM_STATIC_NICK - | - G_PARAM_STATIC_BLURB)); + G_PARAM_READWRITE| + G_PARAM_CONSTRUCT_ONLY| + G_PARAM_STATIC_STRINGS)); g_object_class_install_property(object_class, PROP_MINIMISE_ON_START, @@ -2864,26 +2906,20 @@ static void trg_main_window_class_init(TrgMainWindowClass * klass) "Min On Start", "Min On Start", FALSE, - G_PARAM_READWRITE - | - G_PARAM_CONSTRUCT_ONLY - | - G_PARAM_STATIC_NAME - | - G_PARAM_STATIC_NICK - | - G_PARAM_STATIC_BLURB)); + G_PARAM_READWRITE| + G_PARAM_CONSTRUCT_ONLY| + G_PARAM_STATIC_STRINGS)); } void trg_main_window_set_start_args(TrgMainWindow * win, gchar ** args) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); priv->args = args; } void auto_connect_if_required(TrgMainWindow * win) { - TrgMainWindowPrivate *priv = win->priv; + TrgMainWindowPrivate *priv = trg_main_window_get_instance_private(win); TrgPrefs *prefs = trg_client_get_prefs(priv->client); gchar *host = trg_prefs_get_string(prefs, TRG_PREFS_KEY_HOSTNAME, TRG_PREFS_PROFILE); diff --git a/src/trg-main-window.h b/src/trg-main-window.h index 3c6ace5..1432502 100644 --- a/src/trg-main-window.h +++ b/src/trg-main-window.h @@ -17,13 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MAIN_WINDOW_H_ -#define MAIN_WINDOW_H_ +#pragma once -#include <glib.h> -#include <glib-object.h> -#include <gtk/gtk.h> #include <json-glib/json-glib.h> +#include <gtk/gtk.h> #include "trg-torrent-model.h" #include "trg-peers-model.h" @@ -34,36 +31,18 @@ #include "trg-client.h" G_BEGIN_DECLS -#define TRG_TYPE_MAIN_WINDOW trg_main_window_get_type() -#define TRG_MAIN_WINDOW(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_MAIN_WINDOW, TrgMainWindow)) -#define TRG_MAIN_WINDOW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_MAIN_WINDOW, TrgMainWindowClass)) -#define TRG_IS_MAIN_WINDOW(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_MAIN_WINDOW)) -#define TRG_IS_MAIN_WINDOW_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_MAIN_WINDOW)) -#define TRG_MAIN_WINDOW_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_MAIN_WINDOW, TrgMainWindowClass)) -typedef struct _TrgMainWindowPrivate TrgMainWindowPrivate; -typedef struct { - GtkWindow parent; - TrgMainWindowPrivate *priv; -} TrgMainWindow; - -typedef struct { - GtkWindowClass parent_class; -} TrgMainWindowClass; +#define TRG_TYPE_MAIN_WINDOW (trg_main_window_get_type()) +G_DECLARE_FINAL_TYPE (TrgMainWindow, trg_main_window, TRG, MAIN_WINDOW, GtkApplicationWindow) #define TORRENT_COMPLETE_NOTIFY_TMOUT 8000 #define TORRENT_ADD_NOTIFY_TMOUT 3000 -GType trg_main_window_get_type(void); gint trg_add_from_filename(TrgMainWindow * win, gchar ** uris); gboolean on_session_set(gpointer data); gboolean on_delete_complete(gpointer data); -gboolean on_generic_interactive_action(gpointer data); +void on_generic_interactive_action(TrgMainWindow *win, trg_response *response); +gboolean on_generic_interactive_action_response(gpointer data); void auto_connect_if_required(TrgMainWindow * win); void trg_main_window_set_start_args(TrgMainWindow * win, gchar ** args); TrgMainWindow *trg_main_window_new(TrgClient * tc, gboolean minonstart); @@ -79,9 +58,4 @@ void trg_main_window_notebook_set_visible(TrgMainWindow * win, void connect_cb(GtkWidget * w, gpointer data); void trg_main_window_reload_dir_aliases(TrgMainWindow * win); -#if !GTK_CHECK_VERSION(2, 21, 1) -#define gdk_drag_context_get_actions(context) context->actions -#endif - G_END_DECLS -#endif /* MAIN_WINDOW_H_ */ diff --git a/src/trg-menu-bar.c b/src/trg-menu-bar.c index 4fcd06c..faf3548 100644 --- a/src/trg-menu-bar.c +++ b/src/trg-menu-bar.c @@ -17,12 +17,14 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> -#if GTK_CHECK_VERSION( 3, 0, 0 ) #include <gdk/gdkkeysyms-compat.h> -#endif #include "trg-prefs.h" #include "trg-torrent-graph.h" @@ -51,6 +53,9 @@ enum { PROP_LOCAL_PREFS_BUTTON, PROP_ABOUT_BUTTON, PROP_VIEW_STATS_BUTTON, +#ifdef HAVE_RSS + PROP_VIEW_RSS_BUTTON, +#endif PROP_VIEW_STATES_BUTTON, PROP_VIEW_NOTEBOOK_BUTTON, PROP_QUIT, @@ -60,6 +65,7 @@ enum { PROP_ACCEL_GROUP, PROP_DIR_FILTERS, PROP_TRACKER_FILTERS, + PROP_DIRECTORIES_FIRST, #if TRG_WITH_GRAPH PROP_VIEW_SHOW_GRAPH, #endif @@ -98,10 +104,14 @@ struct _TrgMenuBarPrivate { GtkWidget *mb_view_states; GtkWidget *mb_view_notebook; GtkWidget *mb_view_stats; +#ifdef HAVE_RSS + GtkWidget *mb_view_rss; +#endif GtkWidget *mb_about; GtkWidget *mb_quit; GtkWidget *mb_directory_filters; GtkWidget *mb_tracker_filters; + GtkWidget *mb_directory_first; #if TRG_WITH_GRAPH GtkWidget *mb_view_graph; #endif @@ -142,6 +152,9 @@ void trg_menu_bar_connected_change(TrgMenuBar * mb, gboolean connected) gtk_widget_set_sensitive(priv->mb_disconnect, connected); gtk_widget_set_sensitive(priv->mb_remote_prefs, connected); gtk_widget_set_sensitive(priv->mb_view_stats, connected); +#ifdef HAVE_RSS + gtk_widget_set_sensitive(priv->mb_view_rss, connected); +#endif gtk_widget_set_sensitive(priv->mb_resume_all, connected); gtk_widget_set_sensitive(priv->mb_pause_all, connected); } @@ -275,6 +288,11 @@ trg_menu_bar_get_property(GObject * object, guint property_id, case PROP_VIEW_STATS_BUTTON: g_value_set_object(value, priv->mb_view_stats); break; +#ifdef HAVE_RSS + case PROP_VIEW_RSS_BUTTON: + g_value_set_object(value, priv->mb_view_rss); + break; +#endif case PROP_QUIT: g_value_set_object(value, priv->mb_quit); break; @@ -284,6 +302,9 @@ trg_menu_bar_get_property(GObject * object, guint property_id, case PROP_TRACKER_FILTERS: g_value_set_object(value, priv->mb_tracker_filters); break; + case PROP_DIRECTORIES_FIRST: + g_value_set_object(value, priv->mb_directory_first); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -522,6 +543,14 @@ static GtkWidget *trg_menu_bar_view_menu_new(TrgMenuBar * mb) gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), priv->mb_tracker_filters); + priv->mb_directory_first = + trg_menu_bar_view_item_new(priv->prefs, + TRG_PREFS_KEY_DIRECTORIES_FIRST, + _("Directories first"), + priv->mb_view_states); + gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), + priv->mb_directory_first); + priv->mb_view_notebook = trg_menu_bar_view_item_new(priv->prefs, TRG_PREFS_KEY_SHOW_NOTEBOOK, @@ -544,6 +573,14 @@ static GtkWidget *trg_menu_bar_view_menu_new(TrgMenuBar * mb) gtk_widget_set_sensitive(priv->mb_view_stats, FALSE); gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), priv->mb_view_stats); +#ifdef HAVE_RSS + priv->mb_view_rss = + gtk_menu_item_new_with_mnemonic(_("_RSS")); + //trg_menu_bar_accel_add(mb, priv->mb_view_rss, GDK_F7, 0); + gtk_widget_set_sensitive(priv->mb_view_rss, FALSE); + gtk_menu_shell_append(GTK_MENU_SHELL(viewMenu), priv->mb_view_rss); +#endif + return view; } @@ -580,7 +617,7 @@ trg_menu_bar_file_connect_item_new(TrgMainWindow * win, { GtkWidget *item = gtk_check_menu_item_new_with_label(text); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), checked); + gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), checked); g_object_set_data(G_OBJECT(item), "profile", profile); gtk_check_menu_item_set_draw_as_radio(GTK_CHECK_MENU_ITEM(item), TRUE); @@ -709,7 +746,7 @@ static GtkWidget *trg_menu_bar_torrent_menu_new(TrgMenuBar * menu) priv->mb_delete = trg_menu_bar_item_new(GTK_MENU_SHELL(torrentMenu), - _("Remove and Delete"), GTK_STOCK_CLEAR, + _("Remove and delete data"), GTK_STOCK_DELETE, FALSE); trg_menu_bar_accel_add(menu, priv->mb_delete, GDK_Delete, GDK_SHIFT_MASK); @@ -872,6 +909,11 @@ static void trg_menu_bar_class_init(TrgMenuBarClass * klass) trg_menu_bar_install_widget_prop(object_class, PROP_VIEW_STATS_BUTTON, "view-stats-button", "View stats button"); +#ifdef HAVE_RSS + trg_menu_bar_install_widget_prop(object_class, PROP_VIEW_RSS_BUTTON, + "view-rss-button", + "View rss button"); +#endif trg_menu_bar_install_widget_prop(object_class, PROP_VIEW_STATES_BUTTON, "view-states-button", "View states Button"); @@ -892,6 +934,8 @@ static void trg_menu_bar_class_init(TrgMenuBarClass * klass) "dir-filters", "Dir Filters"); trg_menu_bar_install_widget_prop(object_class, PROP_TRACKER_FILTERS, "tracker-filters", "Tracker Filters"); + trg_menu_bar_install_widget_prop(object_class, PROP_DIRECTORIES_FIRST, + TRG_PREFS_KEY_DIRECTORIES_FIRST, "Directories first"); #if TRG_WITH_GRAPH trg_menu_bar_install_widget_prop(object_class, PROP_VIEW_SHOW_GRAPH, "show-graph", "Show Graph"); diff --git a/src/trg-model.c b/src/trg-model.c index fa67d08..c9ce968 100644 --- a/src/trg-model.c +++ b/src/trg-model.c @@ -17,9 +17,14 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib.h> #include <gtk/gtk.h> #include <json-glib/json-glib.h> +#include "trg-model.h" /* An extension of GtkListStore which provides some functions for looking up * an entry by ID. Also for removing entries which have an old update serial, @@ -32,7 +37,7 @@ struct trg_model_remove_removed_foreachfunc_args { GList *toRemove; }; -gboolean +static gboolean trg_model_remove_removed_foreachfunc(GtkTreeModel * model, GtkTreePath * path G_GNUC_UNUSED, GtkTreeIter * iter, gpointer data) diff --git a/src/trg-peers-model.c b/src/trg-peers-model.c index 0d15753..d8e42ed 100644 --- a/src/trg-peers-model.c +++ b/src/trg-peers-model.c @@ -28,6 +28,7 @@ #include <glib/gstdio.h> #ifdef HAVE_GEOIP #include <GeoIP.h> +#include <GeoIPCity.h> #endif #include "trg-tree-view.h" @@ -46,6 +47,7 @@ typedef struct _TrgPeersModelPrivate TrgPeersModelPrivate; struct _TrgPeersModelPrivate { GeoIP *geoip; GeoIP *geoipv6; + GeoIP *geoipcity; }; #endif @@ -57,7 +59,7 @@ static void trg_peers_model_class_init(TrgPeersModelClass * #endif } -gboolean +static gboolean find_existing_peer_item_foreachfunc(GtkTreeModel * model, GtkTreePath * path G_GNUC_UNUSED, @@ -78,7 +80,7 @@ find_existing_peer_item_foreachfunc(GtkTreeModel * model, return pi->found; } -gboolean +static gboolean find_existing_peer_item(TrgPeersModel * model, JsonObject * p, GtkTreeIter * iter) { @@ -143,6 +145,20 @@ static void resolved_dns_cb(GObject * source_object, GAsyncResult * res, } } +#ifdef HAVE_GEOIP +/* for handling v4 or v6 addresses. string is owned by GeoIP, should not be freed. */ +static const gchar* lookup_country(TrgPeersModel *model, const gchar *address) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + + if (strchr(address, ':') && priv->geoipv6) + return GeoIP_country_name_by_addr_v6(priv->geoipv6, address); + else if (priv->geoip) + return GeoIP_country_name_by_addr(priv->geoip, address); + else + return NULL; +} +#endif + void trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, gint64 updateSerial, JsonObject * t, gint mode) @@ -151,6 +167,8 @@ trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); gboolean doGeoLookup = trg_tree_view_is_column_showing(tv, PEERSCOL_COUNTRY); + gboolean doGeoCityLookup = + trg_tree_view_is_column_showing(tv, PEERSCOL_CITY); #endif gboolean doHostLookup = @@ -171,6 +189,7 @@ trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, const gchar *address = NULL, *flagStr; #ifdef HAVE_GEOIP const gchar *country = NULL; + GeoIPRecord *city = NULL; #endif if (mode == TORRENT_GET_MODE_FIRST @@ -179,21 +198,19 @@ trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, address = peer_get_address(peer); #ifdef HAVE_GEOIP - if (address && doGeoLookup) { /* just in case address wasn't set */ - if (strchr(address, ':') && priv->geoipv6) - country = - GeoIP_country_name_by_addr_v6(priv->geoipv6, - address); - else if (priv->geoip) - country = - GeoIP_country_name_by_addr(priv->geoip, address); + if (address) { /* just in case address wasn't set */ + if (doGeoLookup) + country = lookup_country(model, address); + if (doGeoCityLookup) + city = GeoIP_record_by_addr(priv->geoipcity, address); } #endif gtk_list_store_set(GTK_LIST_STORE(model), &peerIter, - PEERSCOL_ICON, GTK_STOCK_NETWORK, + PEERSCOL_ICON, "network-workgroup", PEERSCOL_IP, address, #ifdef HAVE_GEOIP PEERSCOL_COUNTRY, country ? country : "", + PEERSCOL_CITY, city ? city->city : "", #endif PEERSCOL_CLIENT, peer_get_client_name(peer), -1); @@ -203,6 +220,11 @@ trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, isNew = FALSE; } +#ifdef HAVE_GEOIP + if (city) + GeoIPRecord_delete(city); +#endif + flagStr = peer_get_flagstr(peer); gtk_list_store_set(GTK_LIST_STORE(model), &peerIter, PEERSCOL_FLAGS, flagStr, PEERSCOL_PROGRESS, @@ -244,6 +266,8 @@ static void trg_peers_model_init(TrgPeersModel * self) TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(self); gchar *geoip_db_path = NULL; gchar *geoip_v6_db_path = NULL; + gchar *geoip_city_db_path = NULL; + gchar *geoip_city_alt_db_path = NULL; #endif GType column_types[PEERSCOL_COLUMNS]; @@ -252,6 +276,7 @@ static void trg_peers_model_init(TrgPeersModel * self) column_types[PEERSCOL_IP] = G_TYPE_STRING; #ifdef HAVE_GEOIP column_types[PEERSCOL_COUNTRY] = G_TYPE_STRING; + column_types[PEERSCOL_CITY] = G_TYPE_STRING; #endif column_types[PEERSCOL_HOST] = G_TYPE_STRING; column_types[PEERSCOL_FLAGS] = G_TYPE_STRING; @@ -268,9 +293,13 @@ static void trg_peers_model_init(TrgPeersModel * self) #ifdef WIN32 geoip_db_path = trg_win32_support_path("GeoIP.dat"); geoip_v6_db_path = trg_win32_support_path("GeoIPv6.dat"); + geoip_city_db_path = trg_win32_support_path("GeoLiteCity.dat"); + geoip_city_alt_db_path = trg_win32_support_path("GeoIPCity.dat"); #else geoip_db_path = g_strdup(TRG_GEOIP_DATABASE); geoip_v6_db_path = g_strdup(TRG_GEOIPV6_DATABASE); + geoip_city_db_path = g_strdup(TRG_GEOIP_CITY_DATABASE); + geoip_city_alt_db_path = g_strdup(TRG_GEOIP_CITY_ALT_DATABASE); #endif if (g_file_test(geoip_db_path, G_FILE_TEST_EXISTS) == TRUE) @@ -281,11 +310,83 @@ static void trg_peers_model_init(TrgPeersModel * self) priv->geoipv6 = GeoIP_open(geoip_v6_db_path, GEOIP_STANDARD | GEOIP_CHECK_CACHE); + if (g_file_test(geoip_city_db_path, G_FILE_TEST_EXISTS) == TRUE) + priv->geoipcity = GeoIP_open(geoip_city_db_path, + GEOIP_STANDARD | GEOIP_CHECK_CACHE); + else if (g_file_test(geoip_city_alt_db_path, G_FILE_TEST_EXISTS) == TRUE) + priv->geoipcity = GeoIP_open(geoip_city_alt_db_path, + GEOIP_STANDARD | GEOIP_CHECK_CACHE); + + if (priv->geoipcity) + GeoIP_set_charset(priv->geoipcity, GEOIP_CHARSET_UTF8); + + g_free(geoip_city_db_path); + g_free(geoip_city_alt_db_path); g_free(geoip_db_path); g_free(geoip_v6_db_path); #endif } +#ifdef HAVE_GEOIP +static gboolean trg_peers_model_add_city_foreach(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + gchar *address = NULL; + GeoIPRecord *record = NULL; + + gtk_tree_model_get(GTK_TREE_MODEL(model), iter, PEERSCOL_IP, &address, -1); + record = GeoIP_record_by_addr(priv->geoipcity, address); + + if (record) { + gtk_list_store_set(GTK_LIST_STORE(model), iter, PEERSCOL_CITY, record->city, -1); + GeoIPRecord_delete(record); + } + + g_free(address); + + return FALSE; +} + +gboolean trg_peers_model_has_city_db(TrgPeersModel *model) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + return priv->geoipcity != NULL; +} + +gboolean trg_peers_model_has_country_db(TrgPeersModel *model) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + return priv->geoip != NULL; +} + +void trg_peers_model_add_city_column(TrgPeersModel *model) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + if (priv->geoipcity) + gtk_tree_model_foreach(GTK_TREE_MODEL(model), trg_peers_model_add_city_foreach, NULL); +} + +static gboolean trg_peers_model_add_country_foreach(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) { + gchar *address = NULL; + + gtk_tree_model_get(GTK_TREE_MODEL(model), iter, PEERSCOL_IP, &address, -1); + gtk_list_store_set(GTK_LIST_STORE(model), iter, PEERSCOL_COUNTRY, lookup_country(TRG_PEERS_MODEL(model), address), -1); + + g_free(address); + + return FALSE; +} + +void trg_peers_model_add_country_column(TrgPeersModel *model) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + if (priv->geoip) + gtk_tree_model_foreach(GTK_TREE_MODEL(model), trg_peers_model_add_country_foreach, NULL); +} +#endif + + TrgPeersModel *trg_peers_model_new() { return g_object_new(TRG_TYPE_PEERS_MODEL, NULL); diff --git a/src/trg-peers-model.h b/src/trg-peers-model.h index 6ae941a..8d6b76c 100644 --- a/src/trg-peers-model.h +++ b/src/trg-peers-model.h @@ -56,7 +56,7 @@ typedef struct { GType trg_peers_model_get_type(void); -TrgPeersModel *trg_peers_model_new(); +TrgPeersModel *trg_peers_model_new(void); G_END_DECLS struct peerAndIter { const gchar *ip; @@ -69,6 +69,7 @@ enum { PEERSCOL_IP, #if HAVE_GEOIP PEERSCOL_COUNTRY, + PEERSCOL_CITY, #endif PEERSCOL_HOST, PEERSCOL_FLAGS, @@ -84,7 +85,16 @@ void trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, gint64 updateSerial, JsonObject * t, gboolean first); +#if HAVE_GEOIP +void trg_peers_model_add_city_column(TrgPeersModel *model); +void trg_peers_model_add_country_column(TrgPeersModel *model); +gboolean trg_peers_model_has_city_db(TrgPeersModel *model); +gboolean trg_peers_model_has_country_db(TrgPeersModel *model); +#endif + #endif /* TRG_PEERS_MODEL_H_ */ #define TRG_GEOIP_DATABASE "/usr/share/GeoIP/GeoIP.dat" #define TRG_GEOIPV6_DATABASE "/usr/share/GeoIP/GeoIPv6.dat" +#define TRG_GEOIP_CITY_DATABASE "/usr/share/GeoIP/GeoLiteCity.dat" +#define TRG_GEOIP_CITY_ALT_DATABASE "/usr/share/GeoIP/GeoIPCity.dat" diff --git a/src/trg-peers-tree-view.c b/src/trg-peers-tree-view.c index f7fbd7c..3d6052d 100644 --- a/src/trg-peers-tree-view.c +++ b/src/trg-peers-tree-view.c @@ -40,13 +40,17 @@ trg_peers_tree_view_class_init(TrgPeersTreeViewClass * klass G_GNUC_UNUSED) { } -static void trg_peers_tree_view_init(TrgPeersTreeView * self) +static void trg_peers_tree_view_init(TrgPeersTreeView * self) { + +} + +static void trg_peers_tree_view_setup_columns(TrgPeersTreeView * self, TrgPeersModel *model) { TrgTreeView *ttv = TRG_TREE_VIEW(self); trg_column_description *desc; desc = - trg_tree_view_reg_column(ttv, TRG_COLTYPE_STOCKICONTEXT, + trg_tree_view_reg_column(ttv, TRG_COLTYPE_ICONTEXT, PEERSCOL_IP, _("IP"), "ip", 0); desc->model_column_extra = PEERSCOL_ICON; @@ -54,8 +58,13 @@ static void trg_peers_tree_view_init(TrgPeersTreeView * self) _("Host"), "host", 0); #ifdef HAVE_GEOIP - trg_tree_view_reg_column(ttv, TRG_COLTYPE_TEXT, PEERSCOL_COUNTRY, - _("Country"), "country", 0); + if (trg_peers_model_has_country_db(model)) + trg_tree_view_reg_column(ttv, TRG_COLTYPE_TEXT, PEERSCOL_COUNTRY, + _("Country"), "country", 0); + + if (trg_peers_model_has_city_db(model)) + trg_tree_view_reg_column(ttv, TRG_COLTYPE_TEXT, PEERSCOL_CITY, + _("City"), "city", 0); #endif trg_tree_view_reg_column(ttv, TRG_COLTYPE_SPEED, PEERSCOL_DOWNSPEED, _("Down Speed"), "down-speed", 0); @@ -71,6 +80,17 @@ static void trg_peers_tree_view_init(TrgPeersTreeView * self) gtk_tree_view_set_search_column(GTK_TREE_VIEW(self), PEERSCOL_HOST); } +#ifdef HAVE_GEOIP +static void trg_peers_tree_view_column_added(TrgTreeView *tv, const gchar *id) { + TrgPeersModel *model = TRG_PEERS_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(tv))); + if (!g_strcmp0(id, "city")) { + trg_peers_model_add_city_column(model); + } else if (!g_strcmp0(id, "country")) { + trg_peers_model_add_country_column(model); + } +} +#endif + TrgPeersTreeView *trg_peers_tree_view_new(TrgPrefs * prefs, TrgPeersModel * model, const gchar * configId) @@ -79,9 +99,15 @@ TrgPeersTreeView *trg_peers_tree_view_new(TrgPrefs * prefs, "config-id", configId, "prefs", prefs, NULL); + trg_peers_tree_view_setup_columns(TRG_PEERS_TREE_VIEW(obj), model); + gtk_tree_view_set_model(GTK_TREE_VIEW(obj), GTK_TREE_MODEL(model)); trg_tree_view_restore_sort(TRG_TREE_VIEW(obj), 0x00); trg_tree_view_setup_columns(TRG_TREE_VIEW(obj)); +#ifdef HAVE_GEOIP + g_signal_connect(obj, "column-added", G_CALLBACK(trg_peers_tree_view_column_added), NULL); +#endif + return TRG_PEERS_TREE_VIEW(obj); } diff --git a/src/trg-peers-tree-view.h b/src/trg-peers-tree-view.h index 57a09c1..3e683d3 100644 --- a/src/trg-peers-tree-view.h +++ b/src/trg-peers-tree-view.h @@ -17,7 +17,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - #ifndef TRG_PEERS_TREE_VIEW_H_ #define TRG_PEERS_TREE_VIEW_H_ @@ -40,11 +39,11 @@ G_BEGIN_DECLS #define TRG_PEERS_TREE_VIEW_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_PEERS_TREE_VIEW, TrgPeersTreeViewClass)) typedef struct { - GtkTreeView parent; + TrgTreeView parent; } TrgPeersTreeView; typedef struct { - GtkTreeViewClass parent_class; + TrgTreeViewClass parent_class; } TrgPeersTreeViewClass; GType trg_peers_tree_view_get_type(void); diff --git a/src/trg-persistent-tree-view.c b/src/trg-persistent-tree-view.c index e116fdf..6a0aa01 100644 --- a/src/trg-persistent-tree-view.c +++ b/src/trg-persistent-tree-view.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <gtk/gtk.h> #include "trg-prefs.h" @@ -37,7 +41,7 @@ typedef struct _TrgPersistentTreeViewPrivate TrgPersistentTreeViewPrivate; enum { - PROP_0, PROP_PREFS, PROP_KEY, PROP_MODEL + PROP_0, PROP_PREFS, PROP_KEY, PROP_MODEL, PROP_CONF_FLAGS }; struct _TrgPersistentTreeViewPrivate { @@ -52,6 +56,7 @@ struct _TrgPersistentTreeViewPrivate { trg_pref_widget_desc *wd; GtkTreeModel *model; trg_persistent_tree_view_column *addSelect; + gint conf_flags; }; static void selection_changed(TrgPersistentTreeView * ptv, @@ -322,6 +327,9 @@ trg_persistent_tree_view_set_property(GObject * object, case PROP_MODEL: priv->model = g_value_get_object(value); break; + case PROP_CONF_FLAGS: + priv->conf_flags = g_value_get_int(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -411,7 +419,7 @@ static GObject *trg_persistent_tree_view_constructor(GType type, gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 4); priv->wd = trg_pref_widget_desc_new(GTK_WIDGET(priv->tv), priv->key, - TRG_PREFS_PROFILE); + priv->conf_flags); priv->wd->widget = GTK_WIDGET(object); priv->wd->saveFunc = &trg_persistent_tree_view_save; priv->wd->refreshFunc = &trg_persistent_tree_view_refresh; @@ -462,6 +470,20 @@ trg_persistent_tree_view_class_init(TrgPersistentTreeViewClass * klass) G_PARAM_STATIC_BLURB)); g_object_class_install_property(object_class, + PROP_CONF_FLAGS, + g_param_spec_int("conf-flags", + "Conf Flags", + "Conf Flags", + INT_MIN, + INT_MAX, + TRG_PREFS_PROFILE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property(object_class, PROP_MODEL, g_param_spec_object("persistent-model", "Persistent Model", @@ -483,12 +505,12 @@ static void trg_persistent_tree_view_init(TrgPersistentTreeView * self) TrgPersistentTreeView *trg_persistent_tree_view_new(TrgPrefs * prefs, GtkListStore * model, - const gchar * key) + const gchar * key, gint conf_flags) { GObject *obj = g_object_new(TRG_TYPE_PERSISTENT_TREE_VIEW, "prefs", prefs, "conf-key", key, "persistent-model", - model, + model, "conf-flags", conf_flags, NULL); return TRG_PERSISTENT_TREE_VIEW(obj); diff --git a/src/trg-persistent-tree-view.h b/src/trg-persistent-tree-view.h index a5a7c8f..0d16fb6 100644 --- a/src/trg-persistent-tree-view.h +++ b/src/trg-persistent-tree-view.h @@ -57,7 +57,7 @@ typedef struct { TrgPersistentTreeView *trg_persistent_tree_view_new(TrgPrefs * prefs, GtkListStore * model, - const gchar * key); + const gchar * key, gint conf_flags); trg_pref_widget_desc * trg_persistent_tree_view_get_widget_desc(TrgPersistentTreeView * diff --git a/src/trg-preferences-dialog.c b/src/trg-preferences-dialog.c index 6e98f25..6a0df94 100644 --- a/src/trg-preferences-dialog.c +++ b/src/trg-preferences-dialog.c @@ -60,6 +60,7 @@ struct _TrgPreferencesDialogPrivate { GtkWidget *profileNameEntry; GtkWidget *fullUpdateCheck; GList *widgets; + GtkWidget *notebook; }; static GObject *instance = NULL; @@ -329,6 +330,13 @@ static void toggle_filter_trackers(GtkToggleButton * w, gpointer win) gtk_toggle_button_get_active(w)); } +static void toggle_directories_first(GtkToggleButton * w, gpointer win){ + TrgStateSelector *selector = + trg_main_window_get_state_selector(TRG_MAIN_WINDOW(win)); + trg_state_selector_set_directories_first(selector, + gtk_toggle_button_get_active(w)); +} + #if TRG_WITH_GRAPH static void toggle_graph(GtkToggleButton * w, gpointer win) { @@ -601,7 +609,7 @@ static GtkWidget *trg_prefs_openExecPage(TrgPreferencesDialog * dlg) model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); ptv = trg_persistent_tree_view_new(priv->prefs, model, - TRG_PREFS_KEY_EXEC_COMMANDS); + TRG_PREFS_KEY_EXEC_COMMANDS, TRG_PREFS_CONNECTION); trg_persistent_tree_view_set_add_select(ptv, trg_persistent_tree_view_add_column (ptv, 0, @@ -614,13 +622,49 @@ static GtkWidget *trg_prefs_openExecPage(TrgPreferencesDialog * dlg) trg_pref_widget_refresh(dlg, wd); priv->widgets = g_list_append(priv->widgets, wd); - gtk_table_attach(GTK_TABLE(t), GTK_WIDGET(ptv), 1, 2, row, row + 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0); + hig_workarea_add_wide_tall_control(t, &row, GTK_WIDGET(ptv)); return t; } +#ifdef HAVE_RSS +static GtkWidget *trg_prefs_rss_page(TrgPreferencesDialog * dlg) { + TrgPreferencesDialogPrivate *priv = + TRG_PREFERENCES_DIALOG_GET_PRIVATE(dlg); + GtkWidget *t; + guint row = 0; + TrgPersistentTreeView *ptv; + trg_pref_widget_desc *wd; + GtkListStore *model; + + t = hig_workarea_create(); + + hig_workarea_add_section_title(t, &row, + _("RSS Feeds")); + + model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); + + ptv = trg_persistent_tree_view_new(priv->prefs, model, + TRG_PREFS_KEY_RSS, TRG_PREFS_GLOBAL); + trg_persistent_tree_view_set_add_select(ptv, + trg_persistent_tree_view_add_column + (ptv, 0, + TRG_PREFS_RSS_SUBKEY_ID, + _("Name"))); + trg_persistent_tree_view_add_column(ptv, 1, + TRG_PREFS_RSS_SUBKEY_URL, + _("URL")); + + wd = trg_persistent_tree_view_get_widget_desc(ptv); + trg_pref_widget_refresh(dlg, wd); + priv->widgets = g_list_append(priv->widgets, wd); + + hig_workarea_add_wide_tall_control(t, &row, GTK_WIDGET(ptv)); + + return t; +} +#endif + static GtkWidget *trg_prefs_dirsPage(TrgPreferencesDialog * dlg) { TrgPreferencesDialogPrivate *priv = @@ -639,7 +683,7 @@ static GtkWidget *trg_prefs_dirsPage(TrgPreferencesDialog * dlg) model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); ptv = trg_persistent_tree_view_new(priv->prefs, model, - TRG_PREFS_KEY_DESTINATIONS); + TRG_PREFS_KEY_DESTINATIONS, TRG_PREFS_CONNECTION); trg_persistent_tree_view_set_add_select(ptv, trg_persistent_tree_view_add_column (ptv, 0, @@ -652,9 +696,7 @@ static GtkWidget *trg_prefs_dirsPage(TrgPreferencesDialog * dlg) trg_pref_widget_refresh(dlg, wd); priv->widgets = g_list_append(priv->widgets, wd); - gtk_table_attach(GTK_TABLE(t), GTK_WIDGET(ptv), 1, 2, row, row + 1, - GTK_EXPAND | GTK_SHRINK | GTK_FILL, - GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0); + hig_workarea_add_wide_tall_control(t, &row, GTK_WIDGET(ptv)); return t; } @@ -667,6 +709,7 @@ static GtkWidget *trg_prefs_viewPage(TrgPreferencesDialog * dlg) GtkWidget *w, *dep, *t, *tray; guint row = 0; gboolean _is_unity = is_unity(); + gchar *tray_label; t = hig_workarea_create(); @@ -693,6 +736,13 @@ static GtkWidget *trg_prefs_viewPage(TrgPreferencesDialog * dlg) G_CALLBACK(toggle_filter_trackers), priv->win); hig_workarea_add_wide_control(t, &row, w); + w = trgp_check_new(dlg, _("Directories first"), + TRG_PREFS_KEY_DIRECTORIES_FIRST, TRG_PREFS_GLOBAL, + GTK_TOGGLE_BUTTON(dep)); + g_signal_connect(G_OBJECT(w), "toggled", + G_CALLBACK(toggle_directories_first), priv->win); + hig_workarea_add_wide_control(t, &row, w); + w = trgp_check_new(dlg, _("Torrent Details"), TRG_PREFS_KEY_SHOW_NOTEBOOK, TRG_PREFS_GLOBAL, NULL); @@ -708,33 +758,29 @@ static GtkWidget *trg_prefs_viewPage(TrgPreferencesDialog * dlg) hig_workarea_add_wide_control(t, &row, w); #endif -#ifndef HAVE_LIBAPPINDICATOR - if (!_is_unity) { -#endif - hig_workarea_add_section_title(t, &row, _("System Tray")); - - tray = trgp_check_new(dlg, _("Show in system tray"), - TRG_PREFS_KEY_SYSTEM_TRAY, TRG_PREFS_GLOBAL, - NULL); - g_signal_connect(G_OBJECT(tray), "toggled", - G_CALLBACK(toggle_tray_icon), priv->win); - hig_workarea_add_wide_control(t, &row, tray); - - if (!_is_unity) { - w = trgp_check_new(dlg, _("Minimise to system tray"), - TRG_PREFS_KEY_SYSTEM_TRAY_MINIMISE, - TRG_PREFS_GLOBAL, NULL); - gtk_widget_set_sensitive(w, - gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(tray))); - g_signal_connect(G_OBJECT(tray), "toggled", - G_CALLBACK(toggle_active_arg_is_sensitive), - w); - hig_workarea_add_wide_control(t, &row, w); - } -#ifndef HAVE_LIBAPPINDICATOR - } -#endif + hig_workarea_add_section_title(t, &row, _("System Tray")); + + if (_is_unity) { + tray_label = _("Show in system tray (needs whitelisting in unity)"); + } else { + tray_label = _("Show in system tray"); + } + + tray = trgp_check_new(dlg, tray_label, + TRG_PREFS_KEY_SYSTEM_TRAY, TRG_PREFS_GLOBAL, + NULL); + g_signal_connect(G_OBJECT(tray), "toggled", G_CALLBACK(toggle_tray_icon), + priv->win); + hig_workarea_add_wide_control(t, &row, tray); + + w = trgp_check_new(dlg, _("Minimise to system tray"), + TRG_PREFS_KEY_SYSTEM_TRAY_MINIMISE, + TRG_PREFS_GLOBAL, NULL); + gtk_widget_set_sensitive(w, + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tray))); + g_signal_connect(G_OBJECT(tray), "toggled", + G_CALLBACK(toggle_active_arg_is_sensitive), w); + hig_workarea_add_wide_control(t, &row, w); #ifdef HAVE_LIBNOTIFY hig_workarea_add_section_title(t, &row, _("Notifications")); @@ -799,10 +845,7 @@ static GtkWidget *trg_prefs_serverPage(TrgPreferencesDialog * dlg) hig_workarea_add_row(t, &row, _("Name:"), priv->profileNameEntry, NULL); - gtk_table_attach(GTK_TABLE(t), profileButtonsHbox, 1, 2, row, row + 1, - GTK_EXPAND | GTK_SHRINK, 0, 0, 0); - - row++; + hig_workarea_add_wide_control(t, &row, profileButtonsHbox); hig_workarea_add_section_title(t, &row, _("Connection")); @@ -831,6 +874,10 @@ static GtkWidget *trg_prefs_serverPage(TrgPreferencesDialog * dlg) w = trgp_check_new(dlg, _("SSL"), TRG_PREFS_KEY_SSL, TRG_PREFS_PROFILE, NULL); hig_workarea_add_wide_control(t, &row, w); + w = trgp_check_new(dlg, _("Validate SSL Certificate"), TRG_PREFS_KEY_SSL_VALIDATE, TRG_PREFS_PROFILE, + GTK_TOGGLE_BUTTON(w)); + hig_workarea_add_wide_control(t, &row, w); + #endif w = trgp_spin_new(dlg, TRG_PREFS_KEY_TIMEOUT, 1, 3600, 1, @@ -847,6 +894,7 @@ static GtkWidget *trg_prefs_serverPage(TrgPreferencesDialog * dlg) gtk_box_pack_start(GTK_BOX(frameHbox), priv->profileComboBox, FALSE, FALSE, 4); gtk_frame_set_label_widget(GTK_FRAME(frame), frameHbox); + gtk_container_set_border_width(GTK_CONTAINER(frame), 5); gtk_container_add(GTK_CONTAINER(frame), t); return frame; @@ -886,7 +934,7 @@ static GObject *trg_preferences_dialog_constructor(GType type, g_signal_connect(G_OBJECT(object), "response", G_CALLBACK(trg_preferences_response_cb), NULL); - notebook = gtk_notebook_new(); + notebook = priv->notebook = gtk_notebook_new(); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), trg_prefs_serverPage(TRG_PREFERENCES_DIALOG @@ -913,6 +961,13 @@ static GObject *trg_preferences_dialog_constructor(GType type, (object)), gtk_label_new(_("Directories"))); +#ifdef HAVE_RSS + gtk_notebook_append_page(GTK_NOTEBOOK(notebook), + trg_prefs_rss_page(TRG_PREFERENCES_DIALOG + (object)), + gtk_label_new(_("RSS Feeds"))); +#endif + gtk_container_set_border_width(GTK_CONTAINER(notebook), GUI_PAD); gtk_box_pack_start(GTK_BOX(contentvbox), notebook, TRUE, TRUE, 0); @@ -920,6 +975,11 @@ static GObject *trg_preferences_dialog_constructor(GType type, return object; } +void trg_preferences_dialog_set_page(TrgPreferencesDialog *pref_dlg, guint page) { + TrgPreferencesDialogPrivate *priv = TRG_PREFERENCES_DIALOG_GET_PRIVATE(pref_dlg); + gtk_notebook_set_current_page(GTK_NOTEBOOK(priv->notebook), page); +} + static void trg_preferences_dialog_init(TrgPreferencesDialog * pref_dlg) { } diff --git a/src/trg-preferences-dialog.h b/src/trg-preferences-dialog.h index f5e9825..e163964 100644 --- a/src/trg-preferences-dialog.h +++ b/src/trg-preferences-dialog.h @@ -60,6 +60,7 @@ GtkWidget *trg_preferences_dialog_get_instance(TrgMainWindow * win, TrgClient * client); trg_pref_widget_desc *trg_pref_widget_desc_new(GtkWidget * w, gchar * key, int flags); +void trg_preferences_dialog_set_page(TrgPreferencesDialog *pref_dlg, guint page); G_END_DECLS #endif /* TRG_PREFERENCES_WINDOW_H_ */ diff --git a/src/trg-prefs.c b/src/trg-prefs.c index b559479..ff6b1b8 100644 --- a/src/trg-prefs.c +++ b/src/trg-prefs.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib.h> #include <glib/gstdio.h> #include <json-glib/json-glib.h> @@ -106,6 +110,7 @@ static void trg_prefs_create_defaults(TrgPrefs * p) trg_prefs_add_default_bool_true(p, TRG_PREFS_KEY_FILTER_DIRS); trg_prefs_add_default_bool_true(p, TRG_PREFS_KEY_FILTER_TRACKERS); + trg_prefs_add_default_bool_true(p, TRG_PREFS_KEY_DIRECTORIES_FIRST); trg_prefs_add_default_bool_true(p, TRG_PREFS_KEY_SHOW_GRAPH); trg_prefs_add_default_bool_true(p, TRG_PREFS_KEY_ADD_OPTIONS_DIALOG); trg_prefs_add_default_bool_true(p, TRG_PREFS_KEY_SHOW_STATE_SELECTOR); @@ -172,7 +177,7 @@ TrgPrefs *trg_prefs_new(void) return g_object_new(TRG_TYPE_PREFS, NULL); } -static JsonObject *trg_prefs_new_profile_object() +static JsonObject *trg_prefs_new_profile_object(void) { return json_object_new(); } @@ -421,6 +426,12 @@ JsonArray *trg_prefs_get_profiles(TrgPrefs * p) TRG_PREFS_KEY_PROFILES); } +JsonArray *trg_prefs_get_rss(TrgPrefs *p) { + TrgPrefsPrivate *priv = p->priv; + return json_object_get_array_member(priv->userObj, + TRG_PREFS_KEY_RSS); +} + void trg_prefs_set_double(TrgPrefs * p, const gchar * key, gdouble value, int flags) @@ -487,7 +498,7 @@ JsonObject *trg_prefs_get_root(TrgPrefs * p) return priv->userObj; } -void trg_prefs_empty_init(TrgPrefs * p) +static void trg_prefs_empty_init(TrgPrefs * p) { TrgPrefsPrivate *priv = p->priv; JsonArray *profiles = json_array_new(); diff --git a/src/trg-prefs.h b/src/trg-prefs.h index e7a7f48..3923e7d 100644 --- a/src/trg-prefs.h +++ b/src/trg-prefs.h @@ -33,6 +33,7 @@ #define TRG_PREFS_KEY_RPC_URL_PATH "rpc-url-path" #define TRG_PREFS_KEY_PROFILE_ID "profile-id" #define TRG_PREFS_KEY_PROFILES "profiles" +#define TRG_PREFS_KEY_RSS "rss" #define TRG_PREFS_KEY_PROFILE_NAME "profile-name" #define TRG_PREFS_KEY_HOSTNAME "hostname" #define TRG_PREFS_KEY_PORT "port" @@ -41,6 +42,7 @@ #define TRG_PREFS_KEY_PASSWORD "password" #define TRG_PREFS_KEY_AUTO_CONNECT "auto-connect" #define TRG_PREFS_KEY_SSL "ssl" +#define TRG_PREFS_KEY_SSL_VALIDATE "ssl-validate" #define TRG_PREFS_KEY_TIMEOUT "timeout" #define TRG_PREFS_KEY_RETRIES "retries" #define TRG_PREFS_KEY_UPDATE_INTERVAL "update-interval" @@ -54,6 +56,7 @@ #define TRG_PREFS_KEY_SHOW_GRAPH "show-graph" #define TRG_PREFS_KEY_SYSTEM_TRAY_MINIMISE "system-tray-minimise" #define TRG_PREFS_KEY_FILTER_TRACKERS "filter-trackers" +#define TRG_PREFS_KEY_DIRECTORIES_FIRST "directories-first" #define TRG_PREFS_KEY_FILTER_DIRS "filter-dirs" #define TRG_PREFS_KEY_SHOW_STATE_SELECTOR "show-state-selector" #define TRG_PREFS_KEY_SHOW_NOTEBOOK "show-notebook" @@ -77,6 +80,9 @@ #define TRG_PREFS_KEY_EXEC_COMMANDS "exec-commands" #define TRG_PREFS_KEY_EXEC_COMMANDS_SUBKEY_CMD "cmd" #define TRG_PREFS_KEY_DESTINATIONS "destinations" +#define TRG_PREFS_KEY_RSS "rss" +#define TRG_PREFS_RSS_SUBKEY_ID "id" +#define TRG_PREFS_RSS_SUBKEY_URL "url" #define TRG_PREFS_KEY_LAST_MOVE_DESTINATION "last-move-destination" #define TRG_PREFS_KEY_LAST_ADD_DESTINATION "last-add-destination" #define TRG_PREFS_KEY_DESTINATIONS_SUBKEY_DIR "dir" @@ -138,6 +144,7 @@ gboolean trg_prefs_get_bool(TrgPrefs * p, const gchar * key, int flags); JsonObject *trg_prefs_get_profile(TrgPrefs * p); JsonObject *trg_prefs_get_connection(TrgPrefs * p); JsonArray *trg_prefs_get_profiles(TrgPrefs * p); +JsonArray *trg_prefs_get_rss(TrgPrefs *p); void trg_prefs_set_connection(TrgPrefs * p, JsonObject * profile); gint trg_prefs_get_profile_id(TrgPrefs * p); void trg_prefs_del_profile(TrgPrefs * p, JsonObject * profile); diff --git a/src/trg-remote-prefs-dialog.c b/src/trg-remote-prefs-dialog.c index f8bd43b..3fcd910 100644 --- a/src/trg-remote-prefs-dialog.c +++ b/src/trg-remote-prefs-dialog.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <math.h> #include <stdint.h> #include <glib/gi18n.h> @@ -436,7 +440,7 @@ static gboolean on_port_tested(gpointer data) _ ("Port is <span font_weight=\"bold\" fgcolor=\"red\">closed</span>")); } else { - trg_error_dialog(GTK_WINDOW(data), response); + trg_error_dialog(GTK_WINDOW(response->cb_data), response); } } @@ -471,7 +475,7 @@ static gboolean on_blocklist_updated(gpointer data) if (response->status == CURLE_OK) { JsonObject *args = get_arguments(response->obj); gchar *labelText = - g_strdup_printf(_("Blocklist (%ld entries)"), + g_strdup_printf(_("Blocklist (%" G_GINT64_FORMAT " entries)"), json_object_get_int_member(args, SGET_BLOCKLIST_SIZE)); gtk_button_set_label(GTK_BUTTON(priv->blocklist_check), @@ -565,7 +569,7 @@ static GtkWidget *trg_rprefs_connPage(TrgRemotePrefsDialog * win, hig_workarea_add_section_title(t, &row, _("Blocklist")); - stringValue = g_strdup_printf(_("Blocklist (%ld entries)"), + stringValue = g_strdup_printf(_("Blocklist (%" G_GINT64_FORMAT " entries)"), session_get_blocklist_size(s)); tb = priv->blocklist_check = trg_json_widget_check_new(&priv->widgets, s, diff --git a/src/trg-rss-cell-renderer.c b/src/trg-rss-cell-renderer.c new file mode 100644 index 0000000..3477d4a --- /dev/null +++ b/src/trg-rss-cell-renderer.c @@ -0,0 +1,431 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_RSS + +#include <gtk/gtk.h> +#include <gdk/gdk.h> +#include <glib/gi18n.h> + +#include "icons.h" +#include "hig.h" +#include "util.h" +#include "trg-rss-cell-renderer.h" + +enum { + PROP_TITLE = 1, + PROP_FEED, + PROP_PUBLISHED, + PROP_UPLOADED +}; + +#define SMALL_SCALE 0.9 +#define COMPACT_ICON_SIZE GTK_ICON_SIZE_MENU +#define FULL_ICON_SIZE GTK_ICON_SIZE_DND + +#define FOREGROUND_COLOR_KEY "foreground-rgba" +typedef GdkRGBA GtrColor; +typedef cairo_t GtrDrawable; +typedef GtkRequisition GtrRequisition; + +struct TrgRssCellRendererPrivate { + GtkCellRenderer *text_renderer; + GtkCellRenderer *icon_renderer; + GString *gstr1; + GString *gstr2; + gchar *title; + gchar *published; + gchar *feed; + gboolean uploaded; +}; + +static void +trg_rss_cell_renderer_render(GtkCellRenderer * cell, + GtrDrawable * window, GtkWidget * widget, + const GdkRectangle * background_area, + const GdkRectangle * cell_area, + GtkCellRendererState flags); + +static void +gtr_cell_renderer_render(GtkCellRenderer * renderer, + GtrDrawable * drawable, + GtkWidget * widget, + const GdkRectangle * area, + GtkCellRendererState flags) +{ + gtk_cell_renderer_render(renderer, drawable, widget, area, area, + flags); +} + +static void trg_rss_cell_renderer_set_property(GObject * object, + guint property_id, + const GValue * v, + GParamSpec * pspec) +{ + TrgRssCellRenderer *self = TRG_RSS_CELL_RENDERER(object); + struct TrgRssCellRendererPrivate *p = self->priv; + + switch (property_id) { + case PROP_TITLE: + g_free(p->title); + p->title = g_value_dup_string(v); + break; + case PROP_PUBLISHED: + g_free(p->published); + p->published = g_value_dup_string(v); + break; + case PROP_FEED: + g_free(p->feed); + p->feed = g_value_dup_string(v); + break; + case PROP_UPLOADED: + p->uploaded = g_value_get_boolean(v); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +trg_rss_cell_renderer_get_property(GObject * object, + guint property_id, + GValue * v, GParamSpec * pspec) +{ + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); +} + +G_DEFINE_TYPE(TrgRssCellRenderer, trg_rss_cell_renderer, + GTK_TYPE_CELL_RENDERER) + +static void trg_rss_cell_renderer_dispose(GObject * o) +{ + TrgRssCellRenderer *r = TRG_RSS_CELL_RENDERER(o); + + if (r && r->priv) { + struct TrgRssCellRendererPrivate *priv = r->priv; + + g_string_free(priv->gstr1, TRUE); + g_free(priv->feed); + g_free(priv->published); + g_free(priv->title); + g_object_unref(G_OBJECT(priv->text_renderer)); + g_object_unref(G_OBJECT(priv->icon_renderer)); + r->priv = NULL; + } + + G_OBJECT_CLASS(trg_rss_cell_renderer_parent_class)->dispose(o); +} + +static GdkPixbuf *get_icon(TrgRssCellRenderer * r, GtkIconSize icon_size, + GtkWidget * for_widget) +{ + const char *mime_type = "file"; + + return gtr_get_mime_type_icon(mime_type, icon_size, for_widget); +} + +static void +trg_rss_cell_renderer_get_size(GtkCellRenderer * cell, GtkWidget * widget, + const GdkRectangle * cell_area, + gint * x_offset, + gint * y_offset, + gint * width, gint * height) +{ + TrgRssCellRenderer *self = TRG_RSS_CELL_RENDERER(cell); + + if (self) { + struct TrgRssCellRendererPrivate *p = self->priv; + int xpad, ypad; + int h, w; + GtkRequisition icon_size; + GtkRequisition name_size; + GtkRequisition stat_size; + GtkRequisition prog_size; + GdkPixbuf *icon; + + icon = get_icon(self, FULL_ICON_SIZE, widget); + + gtk_cell_renderer_get_padding(cell, &xpad, &ypad); + + /* get the idealized cell dimensions */ + g_object_set(p->icon_renderer, "pixbuf", icon, NULL); + gtk_cell_renderer_get_preferred_size(p->icon_renderer, widget, NULL, + &icon_size); + g_object_set(p->text_renderer, "text", p->title, + "weight", PANGO_WEIGHT_BOLD, "scale", 1.0, "ellipsize", + PANGO_ELLIPSIZE_NONE, NULL); + gtk_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, + &name_size); + g_object_set(p->text_renderer, "text", p->feed, "weight", + PANGO_WEIGHT_NORMAL, "scale", SMALL_SCALE, NULL); + gtk_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, + &prog_size); + g_object_set(p->text_renderer, "text", p->published, NULL); + gtk_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, + &stat_size); + + /** + *** LAYOUT + **/ + + if (width != NULL) + *width = w = + xpad * 2 + icon_size.width + GUI_PAD + MAX3(name_size.width, + prog_size.width, + stat_size.width); + if (height != NULL) + *height = h = + ypad * 2 + name_size.height + prog_size.height + + GUI_PAD_SMALL + stat_size.height; + + /* cleanup */ + g_object_unref(icon); + + if (x_offset) + *x_offset = cell_area ? cell_area->x : 0; + + if (y_offset) { + int xpad, ypad; + gtk_cell_renderer_get_padding(cell, &xpad, &ypad); + *y_offset = + cell_area ? (int) ((cell_area->height - (ypad * 2 + h)) / + 2.0) : 0; + } + } +} + +static void +trg_rss_cell_renderer_class_init(TrgRssCellRendererClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(klass); + + g_type_class_add_private(klass, + sizeof(struct TrgRssCellRendererPrivate)); + + cell_class->render = trg_rss_cell_renderer_render; + cell_class->get_size = trg_rss_cell_renderer_get_size; + gobject_class->set_property = trg_rss_cell_renderer_set_property; + gobject_class->get_property = trg_rss_cell_renderer_get_property; + gobject_class->dispose = trg_rss_cell_renderer_dispose; + + g_object_class_install_property(gobject_class, + PROP_TITLE, + g_param_spec_string("title", + "title", + "Title", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME + | + G_PARAM_STATIC_NICK + | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property(gobject_class, + PROP_PUBLISHED, + g_param_spec_string("published", + "published", + "Published", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME + | + G_PARAM_STATIC_NICK + | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property(gobject_class, + PROP_FEED, + g_param_spec_string("feed", + "feed", + "Feed", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME + | + G_PARAM_STATIC_NICK + | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property(gobject_class, + PROP_UPLOADED, + g_param_spec_boolean("uploaded", + "uploaded", + "Uploaded", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME + | + G_PARAM_STATIC_NICK + | + G_PARAM_STATIC_BLURB)); + + /*g_object_class_install_property(gobject_class, P_BAR_HEIGHT, + g_param_spec_int("bar-height", NULL, + "Bar Height", + 1, INT_MAX, + DEFAULT_BAR_HEIGHT, + G_PARAM_READWRITE));*/ + +} + +static void trg_rss_cell_renderer_init(TrgRssCellRenderer * self) +{ + struct TrgRssCellRendererPrivate *p; + + p = self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, + TRG_RSS_CELL_RENDERER_TYPE, + struct + TrgRssCellRendererPrivate); + + p->gstr1 = g_string_new(NULL); + p->gstr2 = g_string_new(NULL); + p->text_renderer = gtk_cell_renderer_text_new(); + g_object_set(p->text_renderer, "xpad", 0, "ypad", 0, NULL); + p->icon_renderer = gtk_cell_renderer_pixbuf_new(); + g_object_ref_sink(p->text_renderer); + g_object_ref_sink(p->icon_renderer); +} + + +GtkCellRenderer *trg_rss_cell_renderer_new(void) +{ + return (GtkCellRenderer *) g_object_new(TRG_RSS_CELL_RENDERER_TYPE, + NULL); +} + +static void +get_text_color(TrgRssCellRenderer * r, GtkWidget * widget, + GtrColor * setme) +{ + struct TrgRssCellRendererPrivate *p = r->priv; + + if (p->uploaded) + gtk_style_context_get_color(gtk_widget_get_style_context(widget), + GTK_STATE_FLAG_INSENSITIVE, setme); + else + gtk_style_context_get_color(gtk_widget_get_style_context(widget), + GTK_STATE_FLAG_NORMAL, setme); +} + +static void +trg_rss_cell_renderer_render(GtkCellRenderer * cell, + GtrDrawable * window, GtkWidget * widget, + const GdkRectangle * background_area, + const GdkRectangle * cell_area, + GtkCellRendererState flags) +{ + TrgRssCellRenderer *self = TRG_RSS_CELL_RENDERER(cell); + int xpad, ypad; + GtkRequisition size; + GdkRectangle fill_area; + GdkRectangle icon_area; + GdkRectangle name_area; + GdkRectangle stat_area; + GdkRectangle prog_area; + GdkRectangle prct_area; + GdkPixbuf *icon; + GtrColor text_color; + struct TrgRssCellRendererPrivate *p; + + if (!self) + return; + + p = self->priv; + + icon = get_icon(self, FULL_ICON_SIZE, widget); + gtk_cell_renderer_get_padding(GTK_CELL_RENDERER(cell), &xpad, &ypad); + get_text_color(self, widget, &text_color); + + /* get the idealized cell dimensions */ + g_object_set(p->icon_renderer, "pixbuf", icon, NULL); + gtk_cell_renderer_get_preferred_size(p->icon_renderer, widget, NULL, + &size); + icon_area.width = size.width; + icon_area.height = size.height; + g_object_set(p->text_renderer, "text", p->title, + "weight", PANGO_WEIGHT_BOLD, "ellipsize", + PANGO_ELLIPSIZE_NONE, "scale", 1.0, NULL); + gtk_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, + &size); + name_area.width = size.width; + name_area.height = size.height; + g_object_set(p->text_renderer, "text", p->feed, "weight", + PANGO_WEIGHT_NORMAL, "scale", SMALL_SCALE, NULL); + gtk_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, + &size); + prog_area.width = size.width; + prog_area.height = size.height; + g_object_set(p->text_renderer, "text", p->published, NULL); + gtk_cell_renderer_get_preferred_size(p->text_renderer, widget, NULL, + &size); + stat_area.width = size.width; + stat_area.height = size.height; + + /** + *** LAYOUT + **/ + + fill_area = *background_area; + fill_area.x += xpad; + fill_area.y += ypad; + fill_area.width -= xpad * 2; + fill_area.height -= ypad * 2; + + /* icon */ + icon_area.x = fill_area.x; + icon_area.y = fill_area.y + (fill_area.height - icon_area.height) / 2; + + /* name */ + name_area.x = icon_area.x + icon_area.width + GUI_PAD; + name_area.y = fill_area.y; + name_area.width = + fill_area.width - GUI_PAD - icon_area.width - GUI_PAD_SMALL; + + /* prog */ + prog_area.x = name_area.x; + prog_area.y = name_area.y + name_area.height; + prog_area.width = name_area.width; + + /* progressbar */ + prct_area.x = prog_area.x; + prct_area.y = prog_area.y + prog_area.height + GUI_PAD_SMALL; + prct_area.width = prog_area.width; + prct_area.height = 0; + + /* status */ + stat_area.x = prct_area.x; + stat_area.y = prct_area.y + prct_area.height + GUI_PAD_SMALL; + stat_area.width = prct_area.width; + + /** + *** RENDER + **/ + + g_object_set(p->icon_renderer, "pixbuf", icon, "sensitive", TRUE, + NULL); + gtr_cell_renderer_render(p->icon_renderer, window, widget, &icon_area, + flags); + g_object_set(p->text_renderer, "text", p->title, + "scale", 1.0, FOREGROUND_COLOR_KEY, &text_color, + "ellipsize", PANGO_ELLIPSIZE_END, "weight", + PANGO_WEIGHT_BOLD, NULL); + gtr_cell_renderer_render(p->text_renderer, window, widget, &name_area, + flags); + g_object_set(p->text_renderer, "text", p->feed, "scale", + SMALL_SCALE, "weight", PANGO_WEIGHT_NORMAL, NULL); + gtr_cell_renderer_render(p->text_renderer, window, widget, &prog_area, + flags); + g_object_set(p->text_renderer, "text", p->published, + FOREGROUND_COLOR_KEY, &text_color, NULL); + gtr_cell_renderer_render(p->text_renderer, window, widget, &stat_area, + flags); + + /* cleanup */ + g_object_unref(icon); +} + +#endif diff --git a/src/trg-rss-cell-renderer.h b/src/trg-rss-cell-renderer.h new file mode 100644 index 0000000..17c6c69 --- /dev/null +++ b/src/trg-rss-cell-renderer.h @@ -0,0 +1,53 @@ +/* + * transmission-remote-gtk - A GTK RPC client to Transmission + * Copyright (C) 2011-2013 Alan Fitton + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef TRG_RSS_CELL_RENDERER_H +#define TRG_RSS_CELL_RENDERER_H + +#ifdef HAVE_RSS + +#include <gtk/gtk.h> + +#define TRG_RSS_CELL_RENDERER_TYPE ( trg_rss_cell_renderer_get_type( ) ) + +#define TRG_RSS_CELL_RENDERER( o ) \ + ( G_TYPE_CHECK_INSTANCE_CAST( ( o ), \ + TRG_RSS_CELL_RENDERER_TYPE, \ + TrgRssCellRenderer ) ) + +typedef struct TrgRssCellRenderer TrgRssCellRenderer; + +typedef struct TrgRssCellRendererClass TrgRssCellRendererClass; + +struct TrgRssCellRenderer { + GtkCellRenderer parent; + struct TrgRssCellRendererPrivate *priv; +}; + +struct TrgRssCellRendererClass { + GtkCellRendererClass parent; +}; + +GType trg_rss_cell_renderer_get_type(void) G_GNUC_CONST; + +GtkCellRenderer *trg_rss_cell_renderer_new(void); + +#endif + +#endif /* TRG_RSS_CELL_RENDERER_H */ diff --git a/src/trg-rss-model.c b/src/trg-rss-model.c new file mode 100644 index 0000000..aa15829 --- /dev/null +++ b/src/trg-rss-model.c @@ -0,0 +1,277 @@ +/* + * transmission-remote-gtk - A GTK RPC client to Transmission + * Copyright (C) 2011-2013 Alan Fitton + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_RSS + +#include <gtk/gtk.h> +#include <json-glib/json-glib.h> +#include <rss-glib/rss-glib.h> + +#include "config.h" +#include "torrent.h" +#include "trg-client.h" +#include "trg-model.h" +#include "trg-rss-model.h" + +enum { + PROP_0, PROP_CLIENT +}; + +enum { + SIGNAL_GET_ERROR, SIGNAL_PARSE_ERROR, SIGNAL_COUNT +}; + +static guint signals[SIGNAL_COUNT] = { 0 }; + +G_DEFINE_TYPE(TrgRssModel, trg_rss_model, GTK_TYPE_LIST_STORE) +#define TRG_RSS_MODEL_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_RSS_MODEL, TrgRssModelPrivate)) +typedef struct _TrgRssModelPrivate TrgRssModelPrivate; + +struct _TrgRssModelPrivate { + TrgClient *client; + GHashTable *table; + guint index; +}; + +typedef struct { + TrgRssModel *model; + gchar *feed_id; + gchar *feed_url; + gchar *feed_cookie; + GError *error; + trg_response *response; +} feed_update; + +static void feed_update_free(feed_update *update) { + if (update->error) + g_error_free(update->error); + + g_free(update->feed_id); + g_free(update->feed_url); + g_free(update->feed_cookie); + + g_free(update); +} + +static gboolean on_rss_receive(gpointer data) { + trg_response *response = (trg_response *) data; + feed_update *update = (feed_update*) response->cb_data; + TrgRssModel *model = update->model; + TrgRssModelPrivate *priv = TRG_RSS_MODEL_GET_PRIVATE(model); + + if (response->status == CURLE_OK) { + RssParser* parser = rss_parser_new(); + GError *error = NULL; + if (rss_parser_load_from_data(parser, response->raw, + response->size, &error)) { + RssDocument *doc = rss_parser_get_document(parser); + GtkTreeIter iter; + GList *list, *tmp; + + list = rss_document_get_items(doc); + + for (tmp = list; tmp != NULL; tmp = tmp->next) { + RssItem *item = (RssItem*) tmp->data; + const gchar *guid = rss_item_get_guid(item); + if (g_hash_table_lookup(priv->table, guid) != (void*) 1) { + gtk_list_store_append(GTK_LIST_STORE(model), &iter); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, RSSCOL_ID, + guid, RSSCOL_TITLE, rss_item_get_title(item), + RSSCOL_LINK, rss_item_get_link(item), RSSCOL_FEED, + update->feed_id, RSSCOL_COOKIE, update->feed_cookie, RSSCOL_PUBDATE, + rss_item_get_pub_date(item), -1); + g_hash_table_insert(priv->table, g_strdup(guid), (void*) 1); + } + } + + g_list_free(list); + g_object_unref(doc); + g_object_unref(parser); + } else { + rss_parse_error perror; + perror.error = error; + perror.feed_id = update->feed_id; + + g_signal_emit(model, signals[SIGNAL_PARSE_ERROR], 0, + &perror); + + g_message("parse error: %s", error->message); + g_error_free(error); + } + } else { + rss_get_error get_error; + get_error.error_code = response->status; + get_error.feed_id = update->feed_id; + + g_signal_emit(model, signals[SIGNAL_GET_ERROR], 0, + &get_error); + } + + trg_response_free(response); + feed_update_free(update); + + return FALSE; +} + +void trg_rss_model_update(TrgRssModel * model) { + TrgRssModelPrivate *priv = TRG_RSS_MODEL_GET_PRIVATE(model); + TrgPrefs *prefs = trg_client_get_prefs(priv->client); + JsonArray *feeds = trg_prefs_get_rss(prefs); + GRegex *cookie_regex; + GList *li; + + if (!feeds) + return; + + cookie_regex = g_regex_new("(.*):COOKIE:(.*)", 0, 0, NULL); + + for (li = json_array_get_elements(feeds); li != NULL; + li = g_list_next(li)) { + JsonObject *feed = json_node_get_object((JsonNode *) li->data); + const gchar *feed_url = json_object_get_string_member(feed, "url"); + const gchar *id = json_object_get_string_member(feed, "id"); + feed_update *update; + GMatchInfo *match; + + if (!feed_url || !id) + continue; + + update = g_new0(feed_update, 1); + update->feed_id = g_strdup(id); + update->model = model; + + if (g_regex_match (cookie_regex, feed_url, 0, &match)) { + update->feed_url = g_match_info_fetch(match, 1); + update->feed_cookie = g_match_info_fetch(match, 2); + g_match_info_free(match); + } else { + update->feed_url = g_strdup(feed_url); + } + + async_http_request(priv->client, update->feed_url, update->feed_cookie, on_rss_receive, + update); + } + + g_regex_unref(cookie_regex); + + /*trg_model_remove_removed(GTK_LIST_STORE(model), + RSSCOL_UPDATESERIAL, updateSerial);*/ +} + +static void trg_rss_model_set_property(GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec G_GNUC_UNUSED) { + TrgRssModelPrivate *priv = TRG_RSS_MODEL_GET_PRIVATE(object); + + switch (prop_id) { + case PROP_CLIENT: + priv->client = g_value_get_pointer(value); + break; + } +} + +static void trg_rss_model_get_property(GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec G_GNUC_UNUSED) { +} + +static GObject *trg_rss_model_constructor(GType type, + guint n_construct_properties, GObjectConstructParam * construct_params) { + GObject *obj = G_OBJECT_CLASS + (trg_rss_model_parent_class)->constructor(type, + n_construct_properties, construct_params); + TrgRssModelPrivate *priv = TRG_RSS_MODEL_GET_PRIVATE(obj); + + priv->table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + + return obj; +} + +static void trg_rss_model_dispose(GObject * object) { + TrgRssModelPrivate *priv = TRG_RSS_MODEL_GET_PRIVATE(object); + g_hash_table_destroy(priv->table); + G_OBJECT_CLASS(trg_rss_model_parent_class)->dispose(object); +} + +static void trg_rss_model_class_init(TrgRssModelClass * klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof(TrgRssModelPrivate)); + + object_class->set_property = trg_rss_model_set_property; + object_class->get_property = trg_rss_model_get_property; + object_class->constructor = trg_rss_model_constructor; + object_class->dispose = trg_rss_model_dispose; + + g_object_class_install_property(object_class, PROP_CLIENT, + g_param_spec_pointer("client", "client", "client", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY + | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK + | G_PARAM_STATIC_BLURB)); + + signals[SIGNAL_GET_ERROR] = g_signal_new("get-error", + G_TYPE_FROM_CLASS + (object_class), + G_SIGNAL_RUN_LAST | + G_SIGNAL_ACTION, + G_STRUCT_OFFSET + (TrgRssModelClass, + get_error), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + signals[SIGNAL_PARSE_ERROR] = g_signal_new("parse-error", + G_TYPE_FROM_CLASS + (object_class), + G_SIGNAL_RUN_LAST | + G_SIGNAL_ACTION, + G_STRUCT_OFFSET + (TrgRssModelClass, + parse_error), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, + G_TYPE_POINTER); +} + +static void trg_rss_model_init(TrgRssModel * self) { + GType column_types[RSSCOL_COLUMNS]; + + column_types[RSSCOL_ID] = G_TYPE_STRING; + column_types[RSSCOL_TITLE] = G_TYPE_STRING; + column_types[RSSCOL_LINK] = G_TYPE_STRING; + column_types[RSSCOL_COOKIE] = G_TYPE_STRING; + column_types[RSSCOL_FEED] = G_TYPE_STRING; + column_types[RSSCOL_PUBDATE] = G_TYPE_STRING; + column_types[RSSCOL_UPLOADED] = G_TYPE_BOOLEAN; + + gtk_list_store_set_column_types(GTK_LIST_STORE(self), RSSCOL_COLUMNS, + column_types); +} + +TrgRssModel *trg_rss_model_new(TrgClient *client) { + return g_object_new(TRG_TYPE_RSS_MODEL, "client", client, NULL); +} + +#endif diff --git a/src/trg-rss-model.h b/src/trg-rss-model.h new file mode 100644 index 0000000..a97ab3c --- /dev/null +++ b/src/trg-rss-model.h @@ -0,0 +1,85 @@ +/* + * transmission-remote-gtk - A GTK RPC client to Transmission + * Copyright (C) 2011-2013 Alan Fitton + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef TRG_RSS_MODEL_H_ +#define TRG_RSS_MODEL_H_ + +#ifdef HAVE_RSS + +#include <glib-object.h> +#include <json-glib/json-glib.h> + +#include "trg-client.h" +#include "trg-model.h" + +G_BEGIN_DECLS +#define TRG_TYPE_RSS_MODEL trg_rss_model_get_type() +#define TRG_RSS_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_RSS_MODEL, TrgRssModel)) +#define TRG_RSS_MODEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_RSS_MODEL, TrgRssModelClass)) +#define TRG_IS_RSS_MODEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_RSS_MODEL)) +#define TRG_IS_RSS_MODEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_RSS_MODEL)) +#define TRG_RSS_MODEL_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_RSS_MODEL, TrgRssModelClass)) + typedef struct { + GtkListStore parent; +} TrgRssModel; + +typedef struct { + gchar *feed_id; + gint error_code; +} rss_get_error; + +typedef struct { + GError *error; + gchar *feed_id; +} rss_parse_error; + +typedef struct { + GtkListStoreClass parent_class; + void (*get_error) (TrgRssModel * model, + rss_get_error *error); + void (*parse_error) (TrgRssModel * model, + rss_parse_error *error); +} TrgRssModelClass; + +GType trg_rss_model_get_type(void); + +TrgRssModel *trg_rss_model_new(TrgClient *client); + +G_END_DECLS +void trg_rss_model_update(TrgRssModel * model); + +enum { + RSSCOL_ID, + RSSCOL_TITLE, + RSSCOL_LINK, + RSSCOL_FEED, + RSSCOL_COOKIE, + RSSCOL_PUBDATE, + RSSCOL_UPLOADED, + RSSCOL_COLUMNS +}; + +#endif + +#endif /* TRG_RSS_MODEL_H_ */ diff --git a/src/trg-rss-window.c b/src/trg-rss-window.c new file mode 100644 index 0000000..a4b6f63 --- /dev/null +++ b/src/trg-rss-window.c @@ -0,0 +1,371 @@ +/* + * transmission-remote-gtk - A GTK RPC client to Transmission + * Copyright (C) 2011-2013 Alan Fitton + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_RSS + +#include <gtk/gtk.h> +#include <glib/gi18n.h> +#include <rss-glib/rss-glib.h> + +#include "trg-rss-window.h" +#include "trg-rss-model.h" +#include "trg-rss-cell-renderer.h" +#include "trg-torrent-add-dialog.h" +#include "trg-preferences-dialog.h" +#include "trg-client.h" +#include "upload.h" +#include "util.h" + +G_DEFINE_TYPE(TrgRssWindow, trg_rss_window, + GTK_TYPE_WINDOW) +#define TRG_RSS_WINDOW_GET_PRIVATE(o) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_RSS_WINDOW, TrgRssWindowPrivate)) +enum { + PROP_0, PROP_PARENT, PROP_CLIENT +}; + +typedef struct _TrgRssWindowPrivate TrgRssWindowPrivate; + +struct _TrgRssWindowPrivate { + TrgMainWindow *parent; + TrgClient *client; + GtkTreeView *tree_view; + TrgRssModel *tree_model; +}; + +static GObject *instance = NULL; + +static void +trg_rss_window_get_property(GObject * object, + guint property_id, + GValue * value, GParamSpec * pspec) +{ + TrgRssWindowPrivate *priv = + TRG_RSS_WINDOW_GET_PRIVATE(object); + switch (property_id) { + case PROP_CLIENT: + g_value_set_pointer(value, priv->client); + break; + case PROP_PARENT: + g_value_set_object(value, priv->parent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void +trg_rss_window_set_property(GObject * object, + guint property_id, + const GValue * value, + GParamSpec * pspec) +{ + TrgRssWindowPrivate *priv = + TRG_RSS_WINDOW_GET_PRIVATE(object); + switch (property_id) { + case PROP_PARENT: + priv->parent = g_value_get_object(value); + break; + case PROP_CLIENT: + priv->client = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static gboolean upload_complete_searchfunc(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) { + trg_upload *upload = (trg_upload*)data; + gchar *item_guid = NULL; + gboolean stop = FALSE; + + gtk_tree_model_get(model, iter, RSSCOL_ID, &item_guid, -1); + + if (!g_strcmp0(item_guid, upload->uid)) { + gtk_list_store_set(GTK_LIST_STORE(model), iter, RSSCOL_UPLOADED, TRUE, -1); + stop = TRUE; + } + + g_free(item_guid); + + return stop; +} + +static gboolean on_upload_complete(gpointer data) { + trg_response *response = (trg_response*)data; + trg_upload *upload = (trg_upload*)response->cb_data; + TrgRssWindowPrivate *priv = TRG_RSS_WINDOW_GET_PRIVATE(upload->cb_data); + + if (response->status == CURLE_OK) + gtk_tree_model_foreach(GTK_TREE_MODEL(priv->tree_model), upload_complete_searchfunc, upload); + + return FALSE; +} + +static gboolean on_torrent_receive(gpointer data) { + trg_response *response = (trg_response *) data; + trg_upload *upload = (trg_upload*)response->cb_data; + TrgRssWindowPrivate *priv = TRG_RSS_WINDOW_GET_PRIVATE(upload->cb_data); + TrgClient *client = priv->client; + TrgPrefs *prefs = trg_client_get_prefs(client); + TrgMainWindow *main_win = priv->parent; + + upload->upload_response = response; + + if (response->status == CURLE_OK) { + if (trg_prefs_get_bool(prefs, TRG_PREFS_KEY_ADD_OPTIONS_DIALOG, + TRG_PREFS_GLOBAL)) { + TrgTorrentAddDialog *dialog = + trg_torrent_add_dialog_new_from_upload(main_win, client, + upload); + gtk_widget_show_all(GTK_WIDGET(dialog)); + } else { + trg_do_upload(upload); + } + } else { + trg_error_dialog(GTK_WINDOW(main_win), response); + trg_upload_free(upload); + } + + return FALSE; +} + +static void +rss_item_activated(GtkTreeView * treeview, + GtkTreePath * path, + GtkTreeViewColumn * + col G_GNUC_UNUSED, gpointer userdata) +{ + TrgRssWindow *win = TRG_RSS_WINDOW(userdata); + TrgRssWindowPrivate *priv = TRG_RSS_WINDOW_GET_PRIVATE(win); + TrgClient *client = priv->client; + TrgPrefs *prefs = trg_client_get_prefs(client); + GtkTreeModel *model = gtk_tree_view_get_model(treeview); + trg_upload *upload = g_new0(trg_upload, 1); + GtkTreeIter iter; + gchar *link, *uid, *cookie; + + //upload->upload_response = response; + upload->main_window = priv->parent; + upload->client = client; + upload->extra_args = FALSE; + upload->flags = trg_prefs_get_add_flags(prefs); + upload->callback = on_upload_complete; + upload->cb_data = win; + + gtk_tree_model_get_iter(model, &iter, path); + + gtk_tree_model_get(model, &iter, RSSCOL_LINK, &link, RSSCOL_ID, &uid, RSSCOL_COOKIE, &cookie, -1); + + upload->uid = uid; + + async_http_request(priv->client, link, cookie, on_torrent_receive, upload); + + g_free(cookie); + g_free(link); +} + +static void trg_rss_on_get_error(TrgRssModel *model, rss_get_error *error, gpointer data) { + GtkWindow *win = GTK_WINDOW(data); + gchar *msg; + if (error->error_code <= -100) { + msg = g_strdup_printf(_("Request failed with HTTP code %d"), -(error->error_code + 100)); + } else { + msg = g_strdup(curl_easy_strerror(error->error_code)); + } + GtkWidget *dialog = gtk_message_dialog_new(win, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "%s", msg); + g_free(msg); + gtk_window_set_title(GTK_WINDOW(dialog), _("Error")); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); +} + +static void trg_rss_on_parse_error(TrgRssModel *model, rss_parse_error *error, gpointer data) { + GtkWindow *win = GTK_WINDOW(data); + gchar *msg = g_strdup_printf(_("Error parsing RSS feed \"%s\": %s"), error->feed_id, error->error->message); + GtkWidget *dialog = gtk_message_dialog_new(win, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "%s", msg); + g_free(msg); + gtk_window_set_title(GTK_WINDOW(dialog), _("Error")); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); +} + +static void on_configure(GtkWidget *widget, gpointer data) { + TrgRssWindowPrivate *priv = TRG_RSS_WINDOW_GET_PRIVATE(data); + GtkWidget *dlg = trg_preferences_dialog_get_instance(priv->parent, priv->client); + gtk_widget_show_all(dlg); + trg_preferences_dialog_set_page(TRG_PREFERENCES_DIALOG(dlg), 5); +} + +static void on_refresh(GtkWidget *widget, gpointer data) { + TrgRssWindowPrivate *priv = TRG_RSS_WINDOW_GET_PRIVATE(data); + trg_rss_model_update(priv->tree_model); +} + +static GObject *trg_rss_window_constructor(GType type, + guint + n_construct_properties, + GObjectConstructParam * + construct_params) +{ + GObject *object; + TrgRssWindowPrivate *priv; + GtkWidget *vbox; + GtkToolItem *item; + GtkWidget *toolbar; + + object = G_OBJECT_CLASS + (trg_rss_window_parent_class)->constructor(type, + n_construct_properties, + construct_params); + priv = TRG_RSS_WINDOW_GET_PRIVATE(object); + + priv->tree_model = trg_rss_model_new(priv->client); + + g_signal_connect(priv->tree_model, "get-error", + G_CALLBACK(trg_rss_on_get_error), object); + g_signal_connect(priv->tree_model, "parse-error", + G_CALLBACK(trg_rss_on_parse_error), object); + + trg_rss_model_update(priv->tree_model); + + priv->tree_view = GTK_TREE_VIEW(gtk_tree_view_new()); + gtk_tree_view_set_headers_visible(priv->tree_view, FALSE); + gtk_tree_view_set_model(priv->tree_view, GTK_TREE_MODEL(priv->tree_model)); + + gtk_tree_view_insert_column_with_attributes(priv->tree_view, -1, NULL, trg_rss_cell_renderer_new(), "title", RSSCOL_TITLE, "feed", RSSCOL_FEED, "published", RSSCOL_PUBDATE, "uploaded", RSSCOL_UPLOADED, NULL); + + g_signal_connect(priv->tree_view, "row-activated", + G_CALLBACK(rss_item_activated), object); + + gtk_window_set_title(GTK_WINDOW(object), _("RSS Feeds")); + + toolbar = gtk_toolbar_new(); + + item = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH); + gtk_widget_set_sensitive(GTK_WIDGET(item), TRUE); + gtk_tool_item_set_tooltip_text(item, "Refresh"); + g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(on_refresh), object); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, 0); + + item = gtk_tool_button_new_from_stock(GTK_STOCK_PREFERENCES); + gtk_widget_set_sensitive(GTK_WIDGET(item), TRUE); + gtk_tool_item_set_tooltip_text(item, "Configure Feeds"); + g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(on_configure), object); + gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, 0); + + vbox = trg_vbox_new(FALSE, 0); + + gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(toolbar), + FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), my_scrolledwin_new(GTK_WIDGET(priv->tree_view)), + TRUE, TRUE, 0); + + gtk_container_add(GTK_CONTAINER(object), vbox); + + /*g_signal_connect(object, "response", + G_CALLBACK(trg_rss_window_response_cb), NULL);*/ + + gtk_widget_set_size_request(GTK_WIDGET(object), 500, 300); + + return object; +} + +static void trg_rss_window_dispose(GObject * object) +{ + instance = NULL; + G_OBJECT_CLASS(trg_rss_window_parent_class)->dispose(object); +} + +static void +trg_rss_window_class_init(TrgRssWindowClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof(TrgRssWindowPrivate)); + + object_class->constructor = trg_rss_window_constructor; + object_class->get_property = trg_rss_window_get_property; + object_class->set_property = trg_rss_window_set_property; + object_class->dispose = trg_rss_window_dispose; + + g_object_class_install_property(object_class, + PROP_CLIENT, + g_param_spec_pointer("trg-client", + "TClient", + "Client", + G_PARAM_READWRITE + | + G_PARAM_CONSTRUCT_ONLY + | + G_PARAM_STATIC_NAME + | + G_PARAM_STATIC_NICK + | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property(object_class, + PROP_PARENT, + g_param_spec_object("parent-window", + "Parent window", + "Parent window", + TRG_TYPE_MAIN_WINDOW, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY + | + G_PARAM_STATIC_NAME + | + G_PARAM_STATIC_NICK + | + G_PARAM_STATIC_BLURB)); +} + +static void +trg_rss_window_init(TrgRssWindow * self G_GNUC_UNUSED) +{ +} + +TrgRssWindow *trg_rss_window_get_instance(TrgMainWindow *parent, TrgClient *client) +{ + if (instance == NULL) { + instance = + g_object_new(TRG_TYPE_RSS_WINDOW, "parent-window", parent, "trg-client", client, NULL); + } + + return TRG_RSS_WINDOW(instance); +} + +#endif diff --git a/src/trg-rss-window.h b/src/trg-rss-window.h new file mode 100644 index 0000000..714451e --- /dev/null +++ b/src/trg-rss-window.h @@ -0,0 +1,58 @@ +/* + * transmission-remote-gtk - A GTK RPC client to Transmission + * Copyright (C) 2011-2013 Alan Fitton + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef TRG_RSS_WINDOW_H_ +#define TRG_RSS_WINDOW_H_ + +#ifdef HAVE_RSS + +#include <glib-object.h> +#include <gtk/gtk.h> + +#include "trg-main-window.h" + +G_BEGIN_DECLS +#define TRG_TYPE_RSS_WINDOW trg_rss_window_get_type() +#define TRG_RSS_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRG_TYPE_RSS_WINDOW, TrgRssWindow)) +#define TRG_RSS_WINDOW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), TRG_TYPE_RSS_WINDOW, TrgRssWindowClass)) +#define TRG_IS_RSS_WINDOW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRG_TYPE_RSS_WINDOW)) +#define TRG_IS_RSS_WINDOW_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), TRG_TYPE_RSS_WINDOW)) +#define TRG_RSS_WINDOW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), TRG_TYPE_RSS_WINDOW, TrgRssWindowClass)) + typedef struct { + GtkWindow parent; +} TrgRssWindow; + +typedef struct { + GtkWindowClass parent_class; +} TrgRssWindowClass; + +GType trg_rss_window_get_type(void); + +TrgRssWindow *trg_rss_window_get_instance(TrgMainWindow *parent, TrgClient *client); + +G_END_DECLS + +#endif + +#endif /* TRG_RSS_WINDOW_H_ */ diff --git a/src/trg-sortable-filtered-model.c b/src/trg-sortable-filtered-model.c index 9db1827..3acc443 100644 --- a/src/trg-sortable-filtered-model.c +++ b/src/trg-sortable-filtered-model.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <gtk/gtk.h> #include "trg-sortable-filtered-model.h" diff --git a/src/trg-state-selector.c b/src/trg-state-selector.c index cee0c56..4110f7b 100644 --- a/src/trg-state-selector.c +++ b/src/trg-state-selector.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib-object.h> #include <json-glib/json-glib.h> #include <glib/gi18n.h> @@ -49,6 +53,7 @@ struct _TrgStateSelectorPrivate { guint flag; gboolean showDirs; gboolean showTrackers; + gboolean dirsFirst; TrgClient *client; TrgPrefs *prefs; GHashTable *trackers; @@ -163,7 +168,7 @@ trg_state_selector_update_dynamic_filter(GtkTreeModel * model, GtkTreeIter iter; GtkTreePath *path = gtk_tree_row_reference_get_path(rr); gint64 oldSerial; - GValue gvalue = { 0 }; + GValue gvalue = G_VALUE_INIT; gint oldCount; gtk_tree_model_get_iter(model, &iter, path); @@ -356,10 +361,13 @@ void trg_state_selector_update(TrgStateSelector * s, guint whatsChanged) updateSerial); g_free(announceHost); } else { - trg_state_selector_insert(s, priv->n_categories, - g_hash_table_size - (priv->trackers), - announceHost, &iter); + if (priv->dirsFirst){ + trg_state_selector_insert(s, priv->n_categories + + g_hash_table_size(priv->directories), -1, announceHost, &iter); + } else { + trg_state_selector_insert(s, priv->n_categories, + g_hash_table_size(priv->trackers), announceHost, &iter); + } gtk_list_store_set(GTK_LIST_STORE(model), &iter, STATE_SELECTOR_ICON, GTK_STOCK_NETWORK, @@ -390,11 +398,13 @@ void trg_state_selector_update(TrgStateSelector * s, guint whatsChanged) *) result, updateSerial); } else { - trg_state_selector_insert(s, - priv->n_categories + - g_hash_table_size - (priv->trackers), -1, dir, - &iter); + if (priv->dirsFirst){ + trg_state_selector_insert(s, priv->n_categories, + g_hash_table_size(priv->directories), dir, &iter); + } else { + trg_state_selector_insert(s, priv->n_categories + + g_hash_table_size(priv->trackers), -1, dir, &iter); + } gtk_list_store_set(GTK_LIST_STORE(model), &iter, STATE_SELECTOR_ICON, GTK_STOCK_DIRECTORY, @@ -466,6 +476,15 @@ trg_state_selector_set_show_trackers(TrgStateSelector * s, gboolean show) trg_state_selector_update(s, TORRENT_UPDATE_ADDREMOVE); } +void +trg_state_selector_set_directories_first(TrgStateSelector * s, gboolean _dirsFirst){ + TrgStateSelectorPrivate *priv = TRG_STATE_SELECTOR_GET_PRIVATE(s); + priv->dirsFirst = _dirsFirst; + g_hash_table_remove_all(priv->directories); + g_hash_table_remove_all(priv->trackers); + trg_state_selector_update(s, TORRENT_UPDATE_ADDREMOVE); +} + static void trg_state_selector_add_state(TrgStateSelector * selector, GtkTreeIter * iter, gint pos, @@ -511,7 +530,7 @@ static void trg_state_selector_update_stat(GtkTreeRowReference * rr, gint count) { if (rr) { - GValue gvalue = { 0 }; + GValue gvalue = G_VALUE_INIT; GtkTreeIter iter; GtkTreePath *path = gtk_tree_row_reference_get_path(rr); GtkTreeModel *model = gtk_tree_row_reference_get_model(rr); @@ -715,6 +734,9 @@ static GObject *trg_state_selector_constructor(GType type, priv->showTrackers = trg_prefs_get_bool(priv->prefs, TRG_PREFS_KEY_FILTER_TRACKERS, TRG_PREFS_GLOBAL); + priv->dirsFirst = + trg_prefs_get_bool(priv->prefs, TRG_PREFS_KEY_DIRECTORIES_FIRST, + TRG_PREFS_GLOBAL); return object; } diff --git a/src/trg-state-selector.h b/src/trg-state-selector.h index 5107505..ece419a 100644 --- a/src/trg-state-selector.h +++ b/src/trg-state-selector.h @@ -71,6 +71,7 @@ GRegex *trg_state_selector_get_url_host_regex(TrgStateSelector * s); void trg_state_selector_disconnect(TrgStateSelector * s); void trg_state_selector_set_show_trackers(TrgStateSelector * s, gboolean show); +void trg_state_selector_set_directories_first(TrgStateSelector * s, gboolean _dirsFirst); void trg_state_selector_set_show_dirs(TrgStateSelector * s, gboolean show); void trg_state_selector_set_queues_enabled(TrgStateSelector * s, gboolean enabled); diff --git a/src/trg-stats-dialog.c b/src/trg-stats-dialog.c index 3ae0336..c23628d 100644 --- a/src/trg-stats-dialog.c +++ b/src/trg-stats-dialog.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <gtk/gtk.h> #include <json-glib/json-glib.h> @@ -56,7 +60,7 @@ struct _TrgStatsDialogPrivate { TrgMainWindow *parent; GtkWidget *tv; GtkListStore *model; - GtkTreeRowReference *rr_up, *rr_down, *rr_files_added, + GtkTreeRowReference *rr_down, *rr_up, *rr_ratio, *rr_files_added, *rr_session_count, *rr_active, *rr_version; }; @@ -156,8 +160,7 @@ update_int_stat(JsonObject * args, GtkTreeRowReference * rr, } static void -update_size_stat(JsonObject * args, GtkTreeRowReference * rr, - gchar * jsonKey) +update_size_stat(JsonObject * args, GtkTreeRowReference * rr, gchar * jsonKey) { gchar session_val[32]; gchar cumulat_val[32]; @@ -173,6 +176,23 @@ update_size_stat(JsonObject * args, GtkTreeRowReference * rr, } static void +update_ratio_stat(JsonObject * args, GtkTreeRowReference * rr, gchar * jsonKeyA, gchar * jsonKeyB) +{ + gchar session_val[32]; + gchar cumulat_val[32]; + + trg_strlratio(session_val, + json_object_get_double_member(get_session_arg(args), jsonKeyA) / + json_object_get_double_member(get_session_arg(args), jsonKeyB) ); + + trg_strlratio(cumulat_val, + json_object_get_double_member(get_cumulat_arg(args), jsonKeyA) / + json_object_get_double_member(get_cumulat_arg(args), jsonKeyB) ); + + update_statistic(rr, session_val, cumulat_val); +} + +static void update_time_stat(JsonObject * args, GtkTreeRowReference * rr, gchar * jsonKey) { @@ -214,6 +234,7 @@ static gboolean on_stats_reply(gpointer data) update_size_stat(args, priv->rr_up, "uploadedBytes"); update_size_stat(args, priv->rr_down, "downloadedBytes"); + update_ratio_stat(args, priv->rr_ratio, "uploadedBytes", "downloadedBytes"); update_int_stat(args, priv->rr_files_added, "filesAdded"); update_int_stat(args, priv->rr_session_count, "sessionCount"); update_time_stat(args, priv->rr_active, "secondsActive"); @@ -296,6 +317,8 @@ static GObject *trg_stats_dialog_constructor(GType type, stats_dialog_add_statistic(priv->model, _("Download Total")); priv->rr_up = stats_dialog_add_statistic(priv->model, _("Upload Total")); + priv->rr_ratio = + stats_dialog_add_statistic(priv->model, _("Ratio")); priv->rr_files_added = stats_dialog_add_statistic(priv->model, _("Files Added")); priv->rr_session_count = diff --git a/src/trg-status-bar.c b/src/trg-status-bar.c index 34454df..862e3f9 100644 --- a/src/trg-status-bar.c +++ b/src/trg-status-bar.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <glib/gprintf.h> #include <gtk/gtk.h> @@ -133,15 +137,14 @@ trg_status_bar_set_connected_label(TrgStatusBar * sb, JsonObject * session, TrgClient * client) { TrgPrefs *prefs = trg_client_get_prefs(client); - gdouble version = session_get_version(session); gchar *profileName = trg_prefs_get_string(prefs, TRG_PREFS_KEY_PROFILE_NAME, TRG_PREFS_CONNECTION); gchar *statusMsg = - g_strdup_printf(_("Connected: %s (Transmission %g)"), + g_strdup_printf(_("Connected: %s :: Transmission %s"), profileName, - version); + session_get_version_string(session)); trg_status_bar_push_connection_msg(sb, statusMsg); @@ -200,19 +203,19 @@ trg_status_bar_update_speed(TrgStatusBar * sb, gchar downRateTotalString[32], upRateTotalString[32]; gchar uplimit[64], downlimit[64]; - if (session_get_speed_limit_down_enabled(session)) - downlimitraw = session_get_speed_limit_down(session); - else if (altLimits) + if (altLimits) { downlimitraw = session_get_alt_speed_limit_down(session); - else - downlimitraw = -1; - - if (session_get_speed_limit_up_enabled(session)) - uplimitraw = session_get_speed_limit_up(session); - else if (altLimits) uplimitraw = session_get_alt_speed_limit_up(session); - else - uplimitraw = -1; + } else { + if (session_get_speed_limit_down_enabled(session)) + downlimitraw = session_get_speed_limit_down(session); + else + downlimitraw = -1; + if (session_get_speed_limit_up_enabled(session)) + uplimitraw = session_get_speed_limit_up(session); + else + uplimitraw = -1; + } trg_strlspeed(downRateTotalString, stats->downRateTotal / disk_K); trg_strlspeed(upRateTotalString, stats->upRateTotal / disk_K); diff --git a/src/trg-status-bar.h b/src/trg-status-bar.h index b4942ee..a5edfe8 100644 --- a/src/trg-status-bar.h +++ b/src/trg-status-bar.h @@ -47,7 +47,7 @@ typedef struct { GType trg_status_bar_get_type(void); -TrgStatusBar *trg_status_bar_new(); +TrgStatusBar *trg_status_bar_new(TrgMainWindow * win, TrgClient * client); G_END_DECLS void trg_status_bar_update(TrgStatusBar * sb, diff --git a/src/trg-toolbar.c b/src/trg-toolbar.c index 96dd95d..cb870d3 100644 --- a/src/trg-toolbar.c +++ b/src/trg-toolbar.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <gtk/gtk.h> @@ -143,7 +147,7 @@ trg_toolbar_install_widget_prop(GObjectClass * class, guint propId, G_PARAM_STATIC_BLURB)); } -GtkWidget *trg_toolbar_item_new(TrgToolbar * toolbar, +static GtkWidget *trg_toolbar_item_new(TrgToolbar * toolbar, gchar * text, int *index, gchar * icon, gboolean sensitive) @@ -229,8 +233,8 @@ static GObject *trg_toolbar_constructor(GType type, GTK_STOCK_REMOVE, FALSE); priv->tb_delete = - trg_toolbar_item_new(TRG_TOOLBAR(obj), _("Remove with data"), - &position, GTK_STOCK_CLEAR, FALSE); + trg_toolbar_item_new(TRG_TOOLBAR(obj), _("Remove and delete data"), + &position, GTK_STOCK_DELETE, FALSE); separator = gtk_separator_tool_item_new(); gtk_toolbar_insert(GTK_TOOLBAR(obj), separator, position++); @@ -243,10 +247,6 @@ static GObject *trg_toolbar_constructor(GType type, trg_toolbar_item_new(TRG_TOOLBAR(obj), _("Remote Preferences"), &position, GTK_STOCK_NETWORK, FALSE); -#if !GTK_CHECK_VERSION( 3, 0, 0 ) - gtk_toolbar_set_tooltips(GTK_TOOLBAR(obj), TRUE); -#endif - g_signal_connect(G_OBJECT(priv->prefs), "pref-profile-changed", G_CALLBACK(trg_toolbar_refresh_menu), obj); diff --git a/src/trg-toolbar.h b/src/trg-toolbar.h index 7d12b2d..6887a16 100644 --- a/src/trg-toolbar.h +++ b/src/trg-toolbar.h @@ -17,7 +17,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - #ifndef TRG_TOOLBAR_H_ #define TRG_TOOLBAR_H_ diff --git a/src/trg-torrent-add-dialog.c b/src/trg-torrent-add-dialog.c index bde24eb..31ddd85 100644 --- a/src/trg-torrent-add-dialog.c +++ b/src/trg-torrent-add-dialog.c @@ -22,6 +22,10 @@ * and JSON dispatch. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <gtk/gtk.h> #include <json-glib/json-glib.h> @@ -45,9 +49,10 @@ #include "torrent.h" #include "json.h" #include "protocol-constants.h" +#include "upload.h" enum { - PROP_0, PROP_FILENAME, PROP_PARENT, PROP_CLIENT + PROP_0, PROP_FILENAME, PROP_PARENT, PROP_CLIENT, PROP_UPLOAD }; enum { @@ -63,6 +68,7 @@ struct _TrgTorrentAddDialogPrivate { TrgClient *client; TrgMainWindow *parent; GSList *filenames; + trg_upload *upload; GtkWidget *source_chooser; GtkWidget *dest_combo; GtkWidget *priority_combo; @@ -70,6 +76,7 @@ struct _TrgTorrentAddDialogPrivate { GtkTreeStore *store; GtkWidget *paused_check; GtkWidget *delete_check; + guint n_files; }; #define MAGNET_MAX_LINK_WIDTH 75 @@ -90,6 +97,9 @@ static void trg_torrent_add_dialog_set_property(GObject * object, case PROP_PARENT: priv->parent = g_value_get_object(value); break; + case PROP_UPLOAD: + priv->upload = g_value_get_pointer(value); + break; case PROP_CLIENT: priv->client = g_value_get_pointer(value); break; @@ -115,72 +125,13 @@ trg_torrent_add_dialog_get_property(GObject * object, } } -static void -add_set_common_args(JsonObject * args, gint priority, gchar * dir) -{ - json_object_set_string_member(args, FIELD_FILE_DOWNLOAD_DIR, dir); - json_object_set_int_member(args, FIELD_BANDWIDTH_PRIORITY, - (gint64) priority); -} - -static gpointer add_files_threadfunc(gpointer data) -{ - struct add_torrent_threadfunc_args *files_thread_data = - (struct add_torrent_threadfunc_args *) data; - - GSList *li; - - for (li = files_thread_data->list; li; li = g_slist_next(li)) { - gchar *fileName = (gchar *) li->data; - JsonNode *request = - torrent_add(fileName, files_thread_data->flags); - JsonObject *args; - trg_response *response; - - if (!request) - continue; - - args = node_get_arguments(request); - - if (files_thread_data->extraArgs) - add_set_common_args(args, files_thread_data->priority, - files_thread_data->dir); - - response = dispatch(files_thread_data->client, request); - response->cb_data = files_thread_data->cb_data; - g_idle_add(on_generic_interactive_action, response); - } - - g_str_slist_free(files_thread_data->list); - - if (files_thread_data->extraArgs) - g_free(files_thread_data->dir); - - g_free(files_thread_data); - - return NULL; -} - -void launch_add_thread(struct add_torrent_threadfunc_args *args) -{ - GError *error = NULL; - g_thread_create(add_files_threadfunc, args, FALSE, &error); - - if (error) { - g_error("thread creation error: %s", error->message); - g_error_free(error); - g_str_slist_free(args->list); - g_free(args); - } -} - static gboolean add_file_indexes_foreachfunc(GtkTreeModel * model, GtkTreePath * path G_GNUC_UNUSED, GtkTreeIter * iter, gpointer data) { - JsonObject *args = (JsonObject *) data; + trg_upload *upload = (trg_upload *) data; gint priority, index, wanted; gtk_tree_model_get(model, iter, FC_PRIORITY, &priority, FC_ENABLED, @@ -189,17 +140,8 @@ add_file_indexes_foreachfunc(GtkTreeModel * model, if (gtk_tree_model_iter_has_child(model, iter) || index < 0) return FALSE; - if (wanted) - add_file_id_to_array(args, FIELD_FILES_WANTED, index); - else - add_file_id_to_array(args, FIELD_FILES_UNWANTED, index); - - if (priority == TR_PRI_LOW) - add_file_id_to_array(args, FIELD_FILES_PRIORITY_LOW, index); - else if (priority == TR_PRI_HIGH) - add_file_id_to_array(args, FIELD_FILES_PRIORITY_HIGH, index); - else - add_file_id_to_array(args, FIELD_FILES_PRIORITY_NORMAL, index); + upload->file_wanted[index] = wanted; + upload->file_priorities[index] = priority; return FALSE; } @@ -225,38 +167,33 @@ trg_torrent_add_response_cb(GtkDialog * dlg, gint res_id, gpointer data) gchar *dir = trg_destination_combo_get_dir(TRG_DESTINATION_COMBO (priv->dest_combo)); + trg_upload *upload; - if (g_slist_length(priv->filenames) == 1) { - JsonNode *req = - torrent_add((gchar *) priv->filenames->data, flags); - if (req) { - JsonObject *args = node_get_arguments(req); - gtk_tree_model_foreach(GTK_TREE_MODEL(priv->store), - add_file_indexes_foreachfunc, args); - add_set_common_args(args, priority, dir); - dispatch_async(priv->client, req, - on_generic_interactive_action, - priv->parent); - } - g_str_slist_free(priv->filenames); + if (priv->upload) { + upload = priv->upload; } else { - struct add_torrent_threadfunc_args *args = - g_new(struct add_torrent_threadfunc_args, 1); - args->list = priv->filenames; - args->cb_data = priv->parent; - args->client = priv->client; - args->dir = g_strdup(dir); - args->priority = priority; - args->flags = flags; - args->extraArgs = TRUE; - - launch_add_thread(args); + upload = g_new0(trg_upload, 1); + upload->list = priv->filenames; } + upload->main_window = priv->parent; + upload->client = priv->client; + upload->dir = dir; + upload->priority = priority; + upload->flags = flags; + upload->extra_args = TRUE; + + upload->n_files = priv->n_files; + upload->file_priorities = g_new0(gint, priv->n_files); + upload->file_wanted = g_new0(gint, priv->n_files); + + gtk_tree_model_foreach(GTK_TREE_MODEL(priv->store), + add_file_indexes_foreachfunc, upload); + + trg_do_upload(upload); + trg_destination_combo_save_selection(TRG_DESTINATION_COMBO (priv->dest_combo)); - - g_free(dir); } else { g_str_slist_free(priv->filenames); } @@ -305,7 +242,7 @@ onViewButtonPressed(GtkWidget * w, GdkEventButton * event, gpointer gdata) (set_unwanted), gdata); } -GtkWidget *gtr_file_list_new(GtkTreeStore ** store) +static GtkWidget *gtr_file_list_new(GtkTreeStore ** store) { int size; int width; @@ -323,7 +260,6 @@ GtkWidget *gtr_file_list_new(GtkTreeStore ** store) /* create the view */ view = gtk_tree_view_new(); tree_view = GTK_TREE_VIEW(view); - gtk_tree_view_set_rules_hint(tree_view, TRUE); gtk_container_set_border_width(GTK_CONTAINER(view), GUI_PAD_BIG); g_signal_connect(view, "button-press-event", G_CALLBACK(onViewButtonPressed), view); @@ -431,11 +367,7 @@ GtkWidget *gtr_file_list_new(GtkTreeStore ** store) static GtkWidget *gtr_dialog_get_content_area(GtkDialog * dialog) { -#if GTK_CHECK_VERSION( 2,14,0 ) return gtk_dialog_get_content_area(dialog); -#else - return dialog->vbox; -#endif } static void gtr_dialog_set_content(GtkDialog * dialog, GtkWidget * content) @@ -445,7 +377,7 @@ static void gtr_dialog_set_content(GtkDialog * dialog, GtkWidget * content) gtk_widget_show_all(content); } -GtkWidget *gtr_priority_combo_new(void) +static GtkWidget *gtr_priority_combo_new(void) { return gtr_combo_box_new_enum(_("Low"), TR_PRI_LOW, _("Normal"), TR_PRI_NORMAL, _("High"), TR_PRI_HIGH, @@ -469,7 +401,7 @@ static void addTorrentFilters(GtkFileChooser * chooser) static void store_add_node(GtkTreeStore * store, GtkTreeIter * parent, - trg_files_tree_node * node) + trg_files_tree_node * node, guint *n_files) { GtkTreeIter child; GList *li; @@ -480,11 +412,14 @@ store_add_node(GtkTreeStore * store, GtkTreeIter * parent, 1, FC_INDEX, node->index, FC_PRIORITY, TR_PRI_NORMAL, FC_SIZE, node->length, -1); + + if (!node->children) + *n_files = *n_files + 1; } for (li = node->children; li; li = g_list_next(li)) store_add_node(store, node->name ? &child : NULL, - (trg_files_tree_node *) li->data); + (trg_files_tree_node *) li->data, n_files); } static void torrent_not_parsed_warning(GtkWindow * parent) @@ -515,6 +450,28 @@ static void torrent_not_found_error(GtkWindow * parent, gchar * file) } static void +trg_torrent_add_dialog_set_upload(TrgTorrentAddDialog *d, trg_upload *upload) { + TrgTorrentAddDialogPrivate *priv = + TRG_TORRENT_ADD_DIALOG_GET_PRIVATE(d); + GtkButton *chooser = GTK_BUTTON(priv->source_chooser); + trg_torrent_file *tor_data = NULL; + + if (upload->uid) + gtk_button_set_label(chooser, upload->uid); + + tor_data = trg_parse_torrent_data(upload->upload_response->raw, upload->upload_response->size); + + if (!tor_data) { + torrent_not_parsed_warning(GTK_WINDOW(priv->parent)); + } else { + store_add_node(priv->store, NULL, tor_data->top_node, &priv->n_files); + trg_torrent_file_free(tor_data); + } + + gtk_widget_set_sensitive(priv->file_list, tor_data != NULL); +} + +static void trg_torrent_add_dialog_set_filenames(TrgTorrentAddDialog * d, GSList * filenames) { @@ -525,6 +482,11 @@ trg_torrent_add_dialog_set_filenames(TrgTorrentAddDialog * d, gtk_tree_store_clear(priv->store); + if (priv->upload) { + trg_upload_free(priv->upload); + priv->upload = NULL; + } + if (nfiles == 1) { gchar *file_name = (gchar *) filenames->data; if (is_url(file_name) || is_magnet(file_name)) { @@ -560,7 +522,7 @@ trg_torrent_add_dialog_set_filenames(TrgTorrentAddDialog * d, if (!tor_data) { torrent_not_parsed_warning(GTK_WINDOW(priv->parent)); } else { - store_add_node(priv->store, NULL, tor_data->top_node); + store_add_node(priv->store, NULL, tor_data->top_node, &priv->n_files); trg_torrent_file_free(tor_data); } } else { @@ -738,7 +700,8 @@ static GObject *trg_torrent_add_dialog_constructor(GType type, TRG_TORRENT_ADD_DIALOG_GET_PRIVATE(obj); TrgPrefs *prefs = trg_client_get_prefs(priv->client); - GtkWidget *t, *l, *applyall_combo; + GtkWidget *t, *applyall_combo; + guint row = 0; /* window */ gtk_window_set_title(GTK_WINDOW(obj), _("Add Torrent")); @@ -757,10 +720,8 @@ static GObject *trg_torrent_add_dialog_constructor(GType type, gtk_dialog_set_default_response(GTK_DIALOG(obj), GTK_RESPONSE_ACCEPT); /* workspace */ - t = gtk_table_new(6, 2, FALSE); - gtk_container_set_border_width(GTK_CONTAINER(t), GUI_PAD_BIG); - gtk_table_set_row_spacings(GTK_TABLE(t), GUI_PAD); - gtk_table_set_col_spacings(GTK_TABLE(t), GUI_PAD_BIG); + t = hig_workarea_create(); + //gtk_container_set_border_width(GTK_CONTAINER(t), GUI_PAD_BIG); priv->file_list = gtr_file_list_new(&priv->store); gtk_widget_set_sensitive(priv->file_list, FALSE); @@ -782,59 +743,41 @@ static GObject *trg_torrent_add_dialog_constructor(GType type, priv->priority_combo = gtr_priority_combo_new(); gtk_combo_box_set_active(GTK_COMBO_BOX(priv->priority_combo), 1); - l = gtk_label_new_with_mnemonic(_("_Torrent file:")); - gtk_misc_set_alignment(GTK_MISC(l), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(t), l, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); - priv->source_chooser = gtk_button_new(); + hig_workarea_add_row(t, &row, _("_Torrent file:"), priv->source_chooser, NULL); + gtk_button_set_alignment(GTK_BUTTON(priv->source_chooser), 0.0f, 0.5f); - trg_torrent_add_dialog_set_filenames(TRG_TORRENT_ADD_DIALOG(obj), - priv->filenames); - gtk_table_attach(GTK_TABLE(t), priv->source_chooser, 1, 2, 0, - 1, ~0, 0, 0, 0); - gtk_label_set_mnemonic_widget(GTK_LABEL(l), priv->source_chooser); + if (priv->filenames) + trg_torrent_add_dialog_set_filenames(TRG_TORRENT_ADD_DIALOG(obj), + priv->filenames); + else if (priv->upload) + trg_torrent_add_dialog_set_upload(TRG_TORRENT_ADD_DIALOG(obj), priv->upload); + + g_signal_connect(priv->source_chooser, "clicked", G_CALLBACK(trg_torrent_add_dialog_source_click_cb), obj); - l = gtk_label_new_with_mnemonic(_("_Destination folder:")); - gtk_misc_set_alignment(GTK_MISC(l), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(t), l, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); - priv->dest_combo = trg_destination_combo_new(priv->client, TRG_PREFS_KEY_LAST_ADD_DESTINATION); - gtk_table_attach(GTK_TABLE(t), priv->dest_combo, 1, 2, 1, - 2, ~0, 0, 0, 0); - gtk_label_set_mnemonic_widget(GTK_LABEL(l), priv->dest_combo); + + hig_workarea_add_row(t, &row, _("_Destination folder:"), priv->dest_combo, NULL); gtk_widget_set_size_request(priv->file_list, 466u, 300u); - gtk_table_attach_defaults(GTK_TABLE(t), priv->file_list, 0, 2, 2, 3); - l = gtk_label_new_with_mnemonic(_("Apply to all:")); - gtk_misc_set_alignment(GTK_MISC(l), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(t), l, 0, 1, 3, 4, ~0, 0, 0, 0); + hig_workarea_add_wide_tall_control(t, &row, priv->file_list); applyall_combo = - trg_torrent_add_dialog_apply_all_combo_new(TRG_TORRENT_ADD_DIALOG - (obj)); - gtk_table_attach(GTK_TABLE(t), applyall_combo, 1, 2, 3, 4, ~0, 0, 0, - 0); + trg_torrent_add_dialog_apply_all_combo_new(TRG_TORRENT_ADD_DIALOG(obj)); - l = gtk_label_new_with_mnemonic(_("Torrent _priority:")); - gtk_misc_set_alignment(GTK_MISC(l), 0.0f, 0.5f); - gtk_table_attach(GTK_TABLE(t), l, 0, 1, 4, 5, ~0, 0, 0, 0); + hig_workarea_add_row(t, &row, _("Apply to all:"), applyall_combo, NULL); - gtk_table_attach(GTK_TABLE(t), priv->priority_combo, 1, 2, 4, - 5, ~0, 0, 0, 0); - gtk_label_set_mnemonic_widget(GTK_LABEL(l), priv->priority_combo); + hig_workarea_add_row(t, &row, _("Torrent _priority:"), priv->priority_combo, NULL); - gtk_table_attach(GTK_TABLE(t), priv->paused_check, 0, 2, 5, - 6, GTK_FILL, 0, 0, 0); - - gtk_table_attach(GTK_TABLE(t), priv->delete_check, 0, 2, 6, - 7, GTK_FILL, 0, 0, 0); + hig_workarea_add_wide_control(t, &row, priv->paused_check); + hig_workarea_add_wide_control(t, &row, priv->delete_check); gtr_dialog_set_content(GTK_DIALOG(obj), t); @@ -872,6 +815,21 @@ trg_torrent_add_dialog_class_init(TrgTorrentAddDialogClass * klass) G_PARAM_STATIC_BLURB)); g_object_class_install_property(object_class, + PROP_UPLOAD, + g_param_spec_pointer("upload", + "upload", + "upload", + G_PARAM_READWRITE + | + G_PARAM_CONSTRUCT_ONLY + | + G_PARAM_STATIC_NAME + | + G_PARAM_STATIC_NICK + | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property(object_class, PROP_CLIENT, g_param_spec_pointer("client", "client", @@ -906,7 +864,7 @@ static void trg_torrent_add_dialog_init(TrgTorrentAddDialog * self) { } -TrgTorrentAddDialog *trg_torrent_add_dialog_new(TrgMainWindow * parent, +TrgTorrentAddDialog *trg_torrent_add_dialog_new_from_filenames(TrgMainWindow * parent, TrgClient * client, GSList * filenames) { @@ -915,6 +873,15 @@ TrgTorrentAddDialog *trg_torrent_add_dialog_new(TrgMainWindow * parent, NULL); } +TrgTorrentAddDialog *trg_torrent_add_dialog_new_from_upload(TrgMainWindow * parent, + TrgClient * client, + trg_upload *upload) +{ + return g_object_new(TRG_TYPE_TORRENT_ADD_DIALOG, "upload", + upload, "parent", parent, "client", client, + NULL); +} + void trg_torrent_add_dialog(TrgMainWindow * win, TrgClient * client) { GtkWidget *w; @@ -941,22 +908,21 @@ void trg_torrent_add_dialog(TrgMainWindow * win, TrgClient * client) prefs); if (showOptions) { - TrgTorrentAddDialog *dialog = trg_torrent_add_dialog_new(win, + TrgTorrentAddDialog *dialog = trg_torrent_add_dialog_new_from_filenames(win, client, l); - gtk_widget_show_all(GTK_WIDGET(dialog)); + gtk_window_present(GTK_WINDOW(dialog)); } else { - struct add_torrent_threadfunc_args *args = - g_new0(struct add_torrent_threadfunc_args, 1); + trg_upload *upload = g_new0(trg_upload, 1); - args->list = l; - args->cb_data = win; - args->client = client; - args->extraArgs = FALSE; - args->flags = trg_prefs_get_add_flags(prefs); + upload->list = l; + upload->main_window = win; + upload->client = client; + upload->extra_args = FALSE; + upload->flags = trg_prefs_get_add_flags(prefs); - launch_add_thread(args); + trg_do_upload(upload); } } diff --git a/src/trg-torrent-add-dialog.h b/src/trg-torrent-add-dialog.h index 0f45e2c..eebea45 100644 --- a/src/trg-torrent-add-dialog.h +++ b/src/trg-torrent-add-dialog.h @@ -24,6 +24,7 @@ #include <gtk/gtk.h> #include "trg-client.h" +#include "upload.h" #include "trg-main-window.h" G_BEGIN_DECLS @@ -46,28 +47,15 @@ typedef struct { GtkDialogClass parent_class; } TrgTorrentAddDialogClass; -/* Use synchronous dispatch() in our dedicated thread function. - * This means torrents are added in sequence, instead of dispatch_async() - * working concurrently for each upload. - */ - -struct add_torrent_threadfunc_args { - GSList *list; - TrgClient *client; - gpointer cb_data; - guint flags; - gchar *dir; - gint priority; - gboolean extraArgs; -}; - GType trg_torrent_add_dialog_get_type(void); -TrgTorrentAddDialog *trg_torrent_add_dialog_new(TrgMainWindow * win, +TrgTorrentAddDialog *trg_torrent_add_dialog_new_from_filenames(TrgMainWindow * parent, TrgClient * client, GSList * filenames); +TrgTorrentAddDialog *trg_torrent_add_dialog_new_from_upload(TrgMainWindow * parent, + TrgClient * client, + trg_upload *upload); void trg_torrent_add_dialog(TrgMainWindow * win, TrgClient * client); -void launch_add_thread(struct add_torrent_threadfunc_args *args); G_END_DECLS #endif /* TRG_TORRENT_ADD_DIALOG_H_ */ diff --git a/src/trg-torrent-add-url-dialog.c b/src/trg-torrent-add-url-dialog.c index 7f6335e..2562008 100644 --- a/src/trg-torrent-add-url-dialog.c +++ b/src/trg-torrent-add-url-dialog.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <gtk/gtk.h> #include <json-glib/json-glib.h> @@ -90,7 +94,7 @@ trg_torrent_add_url_response_cb(TrgTorrentAddUrlDialog * dlg, gint res_id, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(priv->startCheck))); dispatch_async(priv->client, request, - on_generic_interactive_action, data); + on_generic_interactive_action_response, data); } gtk_widget_destroy(GTK_WIDGET(dlg)); diff --git a/src/trg-torrent-graph.c b/src/trg-torrent-graph.c index 40d3b4a..8c768f6 100644 --- a/src/trg-torrent-graph.c +++ b/src/trg-torrent-graph.c @@ -27,6 +27,11 @@ * on this widget but with some improvements I didn't do. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "trg-torrent-graph.h" #if TRG_WITH_GRAPH diff --git a/src/trg-torrent-model.c b/src/trg-torrent-model.c index b1e98e5..8e916f4 100644 --- a/src/trg-torrent-model.c +++ b/src/trg-torrent-model.c @@ -17,15 +17,15 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <string.h> #include <gtk/gtk.h> #include <json-glib/json-glib.h> #include <glib/gi18n.h> -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include "torrent.h" #include "json.h" #include "trg-torrent-model.h" @@ -504,7 +504,7 @@ update_torrent_iter(TrgTorrentModel * model, peerfrom_get_resume(pf)); } } -#ifdef DEBUG +#ifdef TRG_DEBUG gtk_list_store_set(ls, iter, TORRENT_COLUMN_ICON, statusIcon, -1); gtk_list_store_set(ls, iter, TORRENT_COLUMN_NAME, torrent_get_name(t), -1); @@ -536,6 +536,10 @@ update_torrent_iter(TrgTorrentModel * model, -1); gtk_list_store_set(ls, iter, TORRENT_COLUMN_DOWNLOADDIR, downloadDir, -1); + gtk_list_store_set(ls, iter, TORRENT_COLUMN_PEERS_CONNECTED, torrent_get_peers_connected(t), + -1); + gtk_list_store_set(ls, iter, TORRENT_COLUMN_ETA, torrent_get_eta(t), + -1); gtk_list_store_set(ls, iter, TORRENT_COLUMN_BANDWIDTH_PRIORITY, torrent_get_bandwidth_priority(t), -1); gtk_list_store_set(ls, iter, TORRENT_COLUMN_TOTALSIZE, @@ -667,7 +671,7 @@ GHashTable *get_torrent_table(TrgTorrentModel * model) return priv->ht; } -gboolean +static gboolean trg_model_find_removed_foreachfunc(GtkTreeModel * model, GtkTreePath * path G_GNUC_UNUSED, @@ -688,7 +692,7 @@ trg_model_find_removed_foreachfunc(GtkTreeModel * model, return FALSE; } -GList *trg_torrent_model_find_removed(GtkTreeModel * model, +static GList *trg_torrent_model_find_removed(GtkTreeModel * model, gint64 currentSerial) { struct TrgModelRemoveData args; diff --git a/src/trg-torrent-model.h b/src/trg-torrent-model.h index 078afe8..4f17a8c 100644 --- a/src/trg-torrent-model.h +++ b/src/trg-torrent-model.h @@ -74,7 +74,7 @@ typedef struct { GType trg_torrent_model_get_type(void); -TrgTorrentModel *trg_torrent_model_new(); +TrgTorrentModel *trg_torrent_model_new(void); G_END_DECLS gboolean diff --git a/src/trg-torrent-move-dialog.c b/src/trg-torrent-move-dialog.c index 7669545..fec1932 100644 --- a/src/trg-torrent-move-dialog.c +++ b/src/trg-torrent-move-dialog.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <string.h> #include <glib/gi18n.h> #include <gtk/gtk.h> @@ -69,14 +73,14 @@ trg_torrent_move_response_cb(GtkDialog * dlg, gint res_id, gpointer data) trg_destination_combo_save_selection(TRG_DESTINATION_COMBO (priv->location_combo)); dispatch_async(priv->client, request, - on_generic_interactive_action, data); + on_generic_interactive_action_response, data); } else { json_array_unref(priv->ids); } gtk_widget_destroy(GTK_WIDGET(dlg)); } -static void location_changed(GtkWidget * w, gpointer data) +static void location_changed(GtkComboBox * w, gpointer data) { TrgTorrentMoveDialogPrivate *priv = TRG_TORRENT_MOVE_DIALOG_GET_PRIVATE(data); @@ -110,8 +114,7 @@ static GObject *trg_torrent_move_dialog_constructor(GType type, w = priv->location_combo = trg_destination_combo_new(priv->client, TRG_PREFS_KEY_LAST_MOVE_DESTINATION); - g_signal_connect(trg_destination_combo_get_entry - (TRG_DESTINATION_COMBO(w)), "changed", + g_signal_connect(w, "changed", G_CALLBACK(location_changed), object); hig_workarea_add_row(t, &row, _("Location:"), w, NULL); diff --git a/src/trg-torrent-props-dialog.c b/src/trg-torrent-props-dialog.c index 90ef4e3..ae75146 100644 --- a/src/trg-torrent-props-dialog.c +++ b/src/trg-torrent-props-dialog.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <gtk/gtk.h> #include <json-glib/json-glib.h> @@ -172,7 +176,7 @@ static void trg_torrent_props_response_cb(GtkDialog * dialog, gint res_id, trg_json_widgets_save(priv->widgets, args); trg_json_widget_desc_list_free(priv->widgets); - dispatch_async(priv->client, request, on_generic_interactive_action, + dispatch_async(priv->client, request, on_generic_interactive_action_response, priv->parent); } @@ -329,11 +333,15 @@ static void info_page_update(TrgTorrentPropsDialog * dialog, gint64 dateCreated = torrent_get_date_created(t); gchar *dateStr = epoch_to_string(dateCreated); - if (!creator || strlen(creator) <= 0) - g_snprintf(buf, sizeof(buf), _("Created on %1$s"), dateStr); - else - g_snprintf(buf, sizeof(buf), _("Created by %1$s on %2$s"), - creator, dateStr); + if (creator && strlen(creator) > 0 && dateCreated > 0) + g_snprintf(buf, sizeof(buf), _("Created by %1$s on %2$s"), + creator, dateStr); + else if (dateCreated > 0) + g_snprintf(buf, sizeof(buf), _("Created on %1$s"), dateStr); + else if (creator && strlen(creator) > 0) + g_snprintf(buf, sizeof(buf), _("Created by %1$s"), creator); + else + g_strlcpy(buf, _("N/A"), sizeof(buf)); g_free(dateStr); gtk_label_set_text(GTK_LABEL(priv->origin_lb), buf); diff --git a/src/trg-torrent-tree-view.c b/src/trg-torrent-tree-view.c index 207bef7..bba78c2 100644 --- a/src/trg-torrent-tree-view.c +++ b/src/trg-torrent-tree-view.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib/gi18n.h> #include <gtk/gtk.h> @@ -48,7 +52,7 @@ static void trg_torrent_tree_view_init(TrgTorrentTreeView * tttv) trg_column_description *desc; desc = - trg_tree_view_reg_column(ttv, TRG_COLTYPE_STOCKICONTEXT, + trg_tree_view_reg_column(ttv, TRG_COLTYPE_ICONTEXT, TORRENT_COLUMN_NAME, _("Name"), "name", 0); desc->model_column_extra = TORRENT_COLUMN_ICON; @@ -206,11 +210,7 @@ trg_torrent_tree_view_renderer_pref_changed(TrgPrefs * p, TRG_STYLE_TR_COMPACT; g_object_set(G_OBJECT(data), "compact", GINT_TO_POINTER(compact), NULL); -#if GTK_CHECK_VERSION( 3,0,0 ) g_signal_emit_by_name(tv, "style-updated", NULL, NULL); -#else - g_signal_emit_by_name(tv, "style-set", NULL, NULL); -#endif } } diff --git a/src/trg-trackers-model.c b/src/trg-trackers-model.c index c998c93..2e7fb9b 100644 --- a/src/trg-trackers-model.c +++ b/src/trg-trackers-model.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <gtk/gtk.h> #include <json-glib/json-glib.h> @@ -85,7 +89,7 @@ trg_trackers_model_update(TrgTrackersModel * model, #ifdef DEBUG gtk_list_store_set(GTK_LIST_STORE(model), &trackIter, - TRACKERCOL_ICON, GTK_STOCK_NETWORK, -1); + TRACKERCOL_ICON, "network-workgroup", -1); gtk_list_store_set(GTK_LIST_STORE(model), &trackIter, TRACKERCOL_TIER, tracker_stats_get_tier(tracker), -1); @@ -123,7 +127,7 @@ trg_trackers_model_update(TrgTrackersModel * model, tracker_stats_get_seeder_count(tracker), -1); #else gtk_list_store_set(GTK_LIST_STORE(model), &trackIter, - TRACKERCOL_ICON, GTK_STOCK_NETWORK, + TRACKERCOL_ICON, "network-workgroup", TRACKERCOL_ID, trackerId, TRACKERCOL_UPDATESERIAL, updateSerial, TRACKERCOL_TIER, diff --git a/src/trg-trackers-tree-view.c b/src/trg-trackers-tree-view.c index 0dfd4f9..58a732c 100644 --- a/src/trg-trackers-tree-view.c +++ b/src/trg-trackers-tree-view.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <glib.h> #include <glib/gi18n.h> #include <gtk/gtk.h> @@ -66,7 +70,7 @@ static gboolean on_trackers_update(gpointer data) trg_trackers_model_set_accept(TRG_TRACKERS_MODEL(model), TRUE); response->cb_data = priv->win; - return on_generic_interactive_action(data); + return on_generic_interactive_action_response(data); } void @@ -115,7 +119,7 @@ trg_tracker_announce_edited(GtkCellRendererText * renderer, req = torrent_set(torrentIds); args = node_get_arguments(req); - if (!g_strcmp0(icon, GTK_STOCK_ADD)) { + if (!g_strcmp0(icon, "list-add")) { json_array_add_string_element(trackerModifiers, new_text); json_object_set_array_member(args, "trackerAdd", trackerModifiers); } else { @@ -164,7 +168,7 @@ static void trg_trackers_tree_view_init(TrgTrackersTreeView * self) trg_column_description *desc; desc = - trg_tree_view_reg_column(ttv, TRG_COLTYPE_STOCKICONTEXT, + trg_tree_view_reg_column(ttv, TRG_COLTYPE_ICONTEXT, TRACKERCOL_TIER, _("Tier"), "tier", TRG_COLUMN_UNREMOVABLE); desc->model_column_extra = TRACKERCOL_ICON; @@ -220,7 +224,7 @@ static void add_tracker(GtkWidget * w, gpointer data) gtk_list_store_append(GTK_LIST_STORE(model), &iter); gtk_list_store_set(GTK_LIST_STORE(model), &iter, TRACKERCOL_ICON, - GTK_STOCK_ADD, -1); + "list-add", -1); path = gtk_tree_model_get_path(model, &iter); gtk_tree_view_set_cursor(tv, path, priv->announceColumn, TRUE); diff --git a/src/trg-tree-view.c b/src/trg-tree-view.c index 3f7b95e..bea3cbf 100644 --- a/src/trg-tree-view.c +++ b/src/trg-tree-view.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <gtk/gtk.h> #include <json-glib/json-glib.h> @@ -49,6 +53,12 @@ enum { PROP_0, PROP_PREFS, PROP_CONFIGID }; +enum { + SIGNAL_COLUMN_ADDED, SIGNAL_COUNT +}; + +static guint signals[SIGNAL_COUNT] = { 0 }; + G_DEFINE_TYPE(TrgTreeView, trg_tree_view, GTK_TYPE_TREE_VIEW) #define TRG_TREE_VIEW_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRG_TYPE_TREE_VIEW, TrgTreeViewPrivate)) @@ -215,6 +225,8 @@ trg_tree_view_user_add_column_cb(GtkWidget * w, TRG_TREE_VIEW(gtk_tree_view_column_get_tree_view(col)); trg_tree_view_add_column_after(tv, desc, -1, col); + + g_signal_emit(tv, signals[SIGNAL_COLUMN_ADDED], 0, desc->id); } static void trg_tree_view_sort_menu_item_toggled(GtkCheckMenuItem * w, @@ -324,18 +336,12 @@ view_popup_menu(GtkButton * button, GdkEventButton * event, TrgTreeViewPrivate *priv = TRG_TREE_VIEW_GET_PRIVATE(tv); GtkWidget *menu, *menuitem; trg_column_description *desc; + guint n_showing = 0; GList *li; menu = gtk_menu_new(); desc = g_object_get_data(G_OBJECT(column), GDATA_KEY_COLUMN_DESC); - menuitem = gtk_check_menu_item_new_with_label(desc->header); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE); - g_signal_connect(menuitem, "activate", - G_CALLBACK(trg_tree_view_hide_column), column); - gtk_widget_set_sensitive(menuitem, - !(desc->flags & TRG_COLUMN_UNREMOVABLE)); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); for (li = priv->columns; li; li = g_list_next(li)) { trg_column_description *desc = (trg_column_description *) li->data; @@ -346,8 +352,19 @@ view_popup_menu(GtkButton * button, GdkEventButton * event, G_CALLBACK(trg_tree_view_user_add_column_cb), desc); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } else { + n_showing++; } } + + menuitem = gtk_check_menu_item_new_with_label(desc->header); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), TRUE); + g_signal_connect(menuitem, "activate", + G_CALLBACK(trg_tree_view_hide_column), column); + gtk_widget_set_sensitive(menuitem, + !(desc->flags & TRG_COLUMN_UNREMOVABLE) && n_showing > 1); + gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem); + gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, @@ -355,12 +372,28 @@ view_popup_menu(GtkButton * button, GdkEventButton * event, gdk_event_get_time((GdkEvent *) event)); } +/* This used to get the column as an argument binded when the signal was + * created, but it seems GTK now destroys and recreates them in some + * circumstances. So bind the column description instead and search for the + * column by its title. + */ static gboolean col_onButtonPressed(GtkButton * button, - GdkEventButton * event, GtkTreeViewColumn * col) + GdkEventButton * event, trg_column_description *desc) { if (event->type == GDK_BUTTON_PRESS && event->button == 3) { - view_popup_menu(button, event, col); + GtkTreeView *gtv = GTK_TREE_VIEW(gtk_widget_get_parent(GTK_WIDGET(button))); + GList *cols = gtk_tree_view_get_columns(gtv); + GList *li; + for (li = cols; li; li = g_list_next(li)) { + GtkTreeViewColumn *col = GTK_TREE_VIEW_COLUMN(li->data); + if (!g_strcmp0(desc->header, gtk_tree_view_column_get_title(col))) { + view_popup_menu(button, event, col); + break; + } + } + g_list_free(cols); + return TRUE; } @@ -417,6 +450,7 @@ trg_tree_view_add_column_after(TrgTreeView * tv, { GtkCellRenderer *renderer; GtkTreeViewColumn *column = NULL; + GtkButton *column_button = NULL; switch (desc->type) { case TRG_COLTYPE_TEXT: @@ -495,8 +529,8 @@ trg_tree_view_add_column_after(TrgTreeView * tv, "wanted-value", desc->model_column, NULL); break; - case TRG_COLTYPE_STOCKICONTEXT: - column = trg_tree_view_icontext_column_new(desc, "stock-id"); + case TRG_COLTYPE_ICONTEXT: + column = trg_tree_view_icontext_column_new(desc, "icon-name"); break; case TRG_COLTYPE_FILEICONTEXT: column = trg_tree_view_fileicontext_column_new(desc); @@ -533,15 +567,17 @@ trg_tree_view_add_column_after(TrgTreeView * tv, return; } - gtk_tree_view_column_set_min_width(column, 0); + //gtk_tree_view_column_set_min_width(column, 0); gtk_tree_view_column_set_resizable(column, TRUE); gtk_tree_view_column_set_reorderable(column, TRUE); gtk_tree_view_column_set_sort_column_id(column, desc->model_column); + gtk_tree_view_column_set_expand(column, TRUE); + + /*gtk_tree_view_column_set_sizing(column, + GTK_TREE_VIEW_COLUMN_FIXED);*/ if (width > 0) { - gtk_tree_view_column_set_sizing(column, - GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(column, width); + //gtk_tree_view_column_set_fixed_width(column, width); } g_object_set_data(G_OBJECT(column), GDATA_KEY_COLUMN_DESC, desc); @@ -552,14 +588,11 @@ trg_tree_view_add_column_after(TrgTreeView * tv, gtk_tree_view_move_column_after(GTK_TREE_VIEW(tv), column, after_col); -#if GTK_CHECK_VERSION( 3,0,0 ) - g_signal_connect(gtk_tree_view_column_get_button(column), + column_button = GTK_BUTTON(gtk_tree_view_column_get_button(column)); + + g_signal_connect(column_button, "button-press-event", G_CALLBACK(col_onButtonPressed), - column); -#else - g_signal_connect(column->button, "button-press-event", - G_CALLBACK(col_onButtonPressed), column); -#endif + desc); if (desc->out) *(desc->out) = column; @@ -770,6 +803,16 @@ static void trg_tree_view_class_init(TrgTreeViewClass * klass) G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + signals[SIGNAL_COLUMN_ADDED] = + g_signal_new("column-added", + G_TYPE_FROM_CLASS(object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET(TrgTreeViewClass, + column_added), NULL, + NULL, g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + } static void trg_tree_view_init(TrgTreeView * tv) diff --git a/src/trg-tree-view.h b/src/trg-tree-view.h index 5a17073..435848f 100644 --- a/src/trg-tree-view.h +++ b/src/trg-tree-view.h @@ -42,6 +42,7 @@ G_BEGIN_DECLS typedef struct { GtkTreeViewClass parent_class; + void (*column_added) (TrgTreeView * tv, const gchar *id); } TrgTreeViewClass; GType trg_tree_view_get_type(void); @@ -51,7 +52,7 @@ GtkWidget *trg_tree_view_new(void); G_END_DECLS GList *trg_tree_view_get_selected_refs_list(GtkTreeView * tv); enum { - TRG_COLTYPE_STOCKICONTEXT, + TRG_COLTYPE_ICONTEXT, TRG_COLTYPE_FILEICONTEXT, TRG_COLTYPE_WANTED, TRG_COLTYPE_TEXT, diff --git a/src/upload.c b/src/upload.c new file mode 100644 index 0000000..1f2f8c0 --- /dev/null +++ b/src/upload.c @@ -0,0 +1,107 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "protocol-constants.h" +#include "requests.h" +#include "trg-client.h" +#include "util.h" +#include "trg-main-window.h" +#include "json.h" +#include "upload.h" + +static gboolean upload_complete_callback(gpointer data); +static void next_upload(trg_upload *upload); + +static void +add_set_common_args(JsonObject * args, gint priority, gchar * dir) +{ + json_object_set_string_member(args, FIELD_FILE_DOWNLOAD_DIR, dir); + json_object_set_int_member(args, FIELD_BANDWIDTH_PRIORITY, + (gint64) priority); +} + +void trg_upload_free(trg_upload *upload) { + g_str_slist_free(upload->list); + g_free(upload->dir); + g_free(upload->uid); + g_free(upload->file_wanted); + g_free(upload->file_priorities); + trg_response_free(upload->upload_response); + g_free(upload); +} + +static void add_priorities(JsonObject *args, gint* priorities, gint n_files) +{ + gint i; + for (i = 0; i < n_files; i++) { + gint priority = priorities[i]; + if (priority == TR_PRI_LOW) + add_file_id_to_array(args, FIELD_FILES_PRIORITY_LOW, i); + else if (priority == TR_PRI_HIGH) + add_file_id_to_array(args, FIELD_FILES_PRIORITY_HIGH, i); + else + add_file_id_to_array(args, FIELD_FILES_PRIORITY_NORMAL, i); + } +} + +static void add_wanteds(JsonObject *args, gint* wanteds, gint n_files) { + gint i; + for (i = 0; i < n_files; i++) { + if (wanteds[i]) + add_file_id_to_array(args, FIELD_FILES_WANTED, i); + else + add_file_id_to_array(args, FIELD_FILES_UNWANTED, i); + } +} + +static void next_upload(trg_upload *upload) { + JsonNode *req = NULL; + + if (upload->upload_response && upload->progress_index < 1) + req = torrent_add_from_response(upload->upload_response, upload->flags); + else if (upload->list && upload->progress_index < g_slist_length(upload->list)) + req = torrent_add_from_file((gchar*)g_slist_nth_data(upload->list, upload->progress_index), upload->flags); + + if (req) { + JsonObject *args = node_get_arguments(req); + + if (upload->extra_args) + add_set_common_args(args, upload->priority, upload->dir); + + if (upload->file_wanted) + add_wanteds(args, upload->file_wanted, upload->n_files); + + if (upload->file_priorities) + add_priorities(args, upload->file_priorities, upload->n_files); + + upload->progress_index++; + dispatch_async(upload->client, req, upload_complete_callback, upload); + } else { + trg_upload_free(upload); + } +} + +static gboolean upload_complete_callback(gpointer data) { + trg_response *response = (trg_response*)data; + trg_upload *upload = (trg_upload*)response->cb_data; + + if (upload->callback) + upload->callback(data); + + /* the callback we're delegating to will destroy the response */ + + if (upload->main_window) + on_generic_interactive_action(upload->main_window, response); + else + trg_response_free(response); + + next_upload(upload); + + return FALSE; +} + +void trg_do_upload(trg_upload *upload) +{ + next_upload(upload); +} diff --git a/src/upload.h b/src/upload.h new file mode 100644 index 0000000..5dc17e2 --- /dev/null +++ b/src/upload.h @@ -0,0 +1,30 @@ +#ifndef UPLOAD_H_ +#define UPLOAD_H_ + +#include <glib.h> + +#include "trg-client.h" +#include "trg-main-window.h" + +typedef struct { + GSList *list; // list of filenames + trg_response *upload_response; // OR: a HTTP response containing a torrent + TrgClient *client; + gpointer cb_data; + TrgMainWindow *main_window; // a parent window to attach any error dialogs to + guint flags; + gchar *dir; + gint priority; + gint* file_priorities; + gint* file_wanted; + guint n_files; + gboolean extra_args; + guint progress_index; + GSourceFunc callback; + gchar *uid; +} trg_upload; + +void trg_upload_free(trg_upload *upload); +void trg_do_upload(trg_upload *upload); + +#endif @@ -113,7 +113,7 @@ static char *formatter_get_size_str(const struct formatter_units *u, precision = 2; else precision = 1; - tr_snprintf(buf, buflen, "%.*f %s", precision, value, units); + g_snprintf(buf, buflen, "%.*f %s", precision, value, units); return buf; } @@ -151,19 +151,19 @@ char *tr_formatter_speed_KBps(char *buf, double KBps, size_t buflen) double speed = KBps; if (speed <= 999.95) /* 0.0 KB to 999.9 KB */ - tr_snprintf(buf, buflen, "%d %s", (int) speed, + g_snprintf(buf, buflen, "%d %s", (int) speed, speed_units.units[TR_FMT_KB].name); else { speed /= K; if (speed <= 99.995) /* 0.98 MB to 99.99 MB */ - tr_snprintf(buf, buflen, "%.2f %s", speed, + g_snprintf(buf, buflen, "%.2f %s", speed, speed_units.units[TR_FMT_MB].name); else if (speed <= 999.95) /* 100.0 MB to 999.9 MB */ - tr_snprintf(buf, buflen, "%.1f %s", speed, + g_snprintf(buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_MB].name); else { speed /= K; - tr_snprintf(buf, buflen, "%.1f %s", speed, + g_snprintf(buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_GB].name); } } @@ -340,7 +340,7 @@ gchar *make_error_message(JsonObject * response, int status) { if (status == FAIL_JSON_DECODE) { return g_strdup(_("JSON decoding error.")); - } else if (status == FAIL_RESPONSE_UNSUCCESSFUL) { + } else if (response && status == FAIL_RESPONSE_UNSUCCESSFUL) { const gchar *resultStr = json_object_get_string_member(response, "result"); if (resultStr == NULL) @@ -367,7 +367,7 @@ char *tr_strlpercent(char *buf, double x, size_t buflen) else precision = 0; - tr_snprintf(buf, buflen, "%.*f%%", precision, tr_truncd(x, precision)); + g_snprintf(buf, buflen, "%.*f%%", precision, tr_truncd(x, precision)); return buf; } @@ -382,15 +382,15 @@ char *tr_strratio(char *buf, size_t buflen, double ratio, const char *infinity) { if ((int) ratio == TR_RATIO_NA) - tr_strlcpy(buf, _("None"), buflen); + g_strlcpy(buf, _("None"), buflen); else if ((int) ratio == TR_RATIO_INF) - tr_strlcpy(buf, infinity, buflen); + g_strlcpy(buf, infinity, buflen); else if (ratio < 10.0) - tr_snprintf(buf, buflen, "%.2f", tr_truncd(ratio, 2)); + g_snprintf(buf, buflen, "%.2f", tr_truncd(ratio, 2)); else if (ratio < 100.0) - tr_snprintf(buf, buflen, "%.1f", tr_truncd(ratio, 1)); + g_snprintf(buf, buflen, "%.1f", tr_truncd(ratio, 1)); else - tr_snprintf(buf, buflen, "%'.0f", ratio); + g_snprintf(buf, buflen, "%'.0f", ratio); return buf; } @@ -481,31 +481,14 @@ char *gtr_localtime2(char *buf, time_t time, size_t buflen) return buf; } -int tr_snprintf(char *buf, size_t buflen, const char *fmt, ...) -{ - int len; - va_list args; - - va_start(args, fmt); - len = evutil_vsnprintf(buf, buflen, fmt, args); - va_end(args); - return len; -} - gchar *epoch_to_string(gint64 epoch) { -#if GLIB_CHECK_VERSION(2, 26, 00) + if(epoch == 0) + return g_strdup(_("N/A")); GDateTime *dt = g_date_time_new_from_unix_local(epoch); gchar *timestring = g_date_time_format(dt, "%F %H:%M:%S"); g_date_time_unref(dt); return timestring; -#else - char buf[64]; - time_t time_val = epoch; - struct tm *ts = localtime(&time_val); - int wrote = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ts); - return g_strndup(buf, wrote); -#endif } /* wrap a link in text with a hyperlink, for use in pango markup. @@ -542,51 +525,6 @@ gchar *add_links_to_text(const gchar * original) return newText; } -size_t tr_strlcpy(char *dst, const void *src, size_t siz) -{ -#ifdef HAVE_STRLCPY - return strlcpy(dst, src, siz); -#else - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0) { - while (--n != 0) { - if ((*d++ = *s++) == '\0') - break; - } - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++); - } - - return s - (char *) src - 1; /* count does not include NUL */ -#endif -} - -int -evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) -{ -#ifdef _MSC_VER - int r = _vsnprintf(buf, buflen, format, ap); - buf[buflen - 1] = '\0'; - if (r >= 0) - return r; - else - return _vscprintf(format, ap); -#else - int r = vsnprintf(buf, buflen, format, ap); - buf[buflen - 1] = '\0'; - return r; -#endif -} - char *tr_strlsize(char *buf, guint64 bytes, size_t buflen) { if (!bytes) @@ -616,24 +554,16 @@ gboolean should_be_minimised(int argc, char *argv[]) GtkWidget *trg_hbox_new(gboolean homogeneous, gint spacing) { GtkWidget *box; -#if GTK_CHECK_VERSION( 3, 0, 0 ) box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, spacing); gtk_box_set_homogeneous(GTK_BOX(box), homogeneous); -#else - box = gtk_hbox_new(homogeneous, spacing); -#endif return box; } GtkWidget *trg_vbox_new(gboolean homogeneous, gint spacing) { GtkWidget *box; -#if GTK_CHECK_VERSION( 3, 0, 0 ) box = gtk_box_new(GTK_ORIENTATION_VERTICAL, spacing); gtk_box_set_homogeneous(GTK_BOX(box), homogeneous); -#else - box = gtk_vbox_new(homogeneous, spacing); -#endif return box; } @@ -648,7 +578,7 @@ gchar *trg_win32_support_path(gchar * file) } #endif -gboolean is_unity() +gboolean is_unity(void) { return g_strcmp0(g_getenv("XDG_CURRENT_DESKTOP"), "Unity") == 0; } @@ -32,6 +32,7 @@ #define trg_strlpercent(a, b) tr_strlpercent(a, b, sizeof(a)) #define trg_strlsize(a, b) tr_formatter_size_B(a, b, sizeof(a)) #define trg_strlratio(a, b) tr_strlratio(a, b, sizeof(a)) +#define MAX3(a,b,c) MAX(a,MAX(b,c)) #define TR_RATIO_NA -1 #define TR_RATIO_INF -2 @@ -78,12 +79,7 @@ char *tr_strratio(char *buf, size_t buflen, double ratio, char *tr_strlratio(char *buf, double ratio, size_t buflen); char *gtr_localtime(time_t time); char *gtr_localtime2(char *buf, time_t time, size_t buflen); -int tr_snprintf(char *buf, size_t buflen, const char *fmt, ...); -int tr_snprintf(char *buf, size_t buflen, const char *fmt, ...); -size_t tr_strlcpy(char *dst, const void *src, size_t siz); double tr_truncd(double x, int decimal_places); -int evutil_vsnprintf(char *buf, size_t buflen, const char *format, - va_list ap); char *tr_strlsize(char *buf, guint64 bytes, size_t buflen); void rm_trailing_slashes(gchar * str); void trg_widget_set_visible(GtkWidget * w, gboolean visible); @@ -97,7 +93,7 @@ gboolean should_be_minimised(int argc, char *argv[]); gboolean is_minimised_arg(const gchar * arg); GtkWidget *trg_vbox_new(gboolean homogeneous, gint spacing); GtkWidget *trg_hbox_new(gboolean homogeneous, gint spacing); -gboolean is_unity(); +gboolean is_unity(void); #ifdef WIN32 gchar *trg_win32_support_path(gchar * file); diff --git a/src/win32-mailslot.c b/src/win32-mailslot.c index 0ca52a9..4fb5af2 100644 --- a/src/win32-mailslot.c +++ b/src/win32-mailslot.c @@ -17,6 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #if WIN32 #define TRG_MAILSLOT_NAME "\\\\.\\mailslot\\TransmissionRemoteGTK" |