From 1f5eed407c762bf7ca118e377f91c6cb1e63eb31 Mon Sep 17 00:00:00 2001 From: Jannis Pohlmann <jannis@xfce.org> Date: Fri, 21 Aug 2009 17:47:20 +0200 Subject: [PATCH] Merge the migration-to-gio branch into master. I'm 100% sure I can implement all ThunarVFS thumbnailers on top of tumbler in time for the Xfce 4.8 release. Same about the volume monitor backend for GIO to avoid a GVfs dependency. So why not merge the GIO branch now? Not much to say about this merge. It replaces ThunarVFS with GIO inside Thunar and Thunarx, something I've been working on over the past few months. It currently requires GVfs for volume monitoring and also (optionally) depends on tumbler for thumbnail generation. Enjoy. All .po files are going to be updated in the next commit. Conflicts: ChangeLog INSTALL acinclude.m4 configure.in.in plugins/thunar-wallpaper/twp-provider.c po-doc/ChangeLog po/ChangeLog po/LINGUAS thunar-vfs/thunar-vfs-1.pc.in thunar-vfs/thunar-vfs-thumb.c thunar/thunar-templates-action.c --- .gitignore | 132 + AUTHORS | 1 + ChangeLog | 1241 +++ ChangeLog.pre-gio | 7500 +++++++++++++++++ INSTALL | 302 - Makefile.am | 2 - README | 5 + acinclude.m4 | 156 - autogen.sh | 39 +- configure.in.in | 304 +- docs/reference/Makefile.am | 1 - docs/reference/thunar-vfs/Makefile.am | 70 - .../reference/thunar-vfs/thunar-vfs-docs.sgml | 125 - .../thunar-vfs/thunar-vfs-overrides.txt | 0 .../thunar-vfs/thunar-vfs-sections.txt | 449 - docs/reference/thunar-vfs/thunar-vfs.types | 17 - .../thunar-vfs/tmpl/thunar-vfs-group.sgml | 43 - .../thunar-vfs/tmpl/thunar-vfs-info.sgml | 158 - .../tmpl/thunar-vfs-init-shutdown.sgml | 33 - .../tmpl/thunar-vfs-interactive-job.sgml | 35 - .../thunar-vfs/tmpl/thunar-vfs-job.sgml | 131 - .../thunar-vfs/tmpl/thunar-vfs-jobs.sgml | 205 - .../tmpl/thunar-vfs-mime-action.sgml | 27 - .../tmpl/thunar-vfs-mime-application.sgml | 119 - .../tmpl/thunar-vfs-mime-database.sgml | 144 - .../tmpl/thunar-vfs-mime-handler.sgml | 120 - .../thunar-vfs/tmpl/thunar-vfs-mime-info.sgml | 126 - .../thunar-vfs/tmpl/thunar-vfs-monitor.sgml | 113 - .../tmpl/thunar-vfs-operations.sgml | 182 - .../thunar-vfs/tmpl/thunar-vfs-path.sgml | 273 - .../tmpl/thunar-vfs-thumb-factory.sgml | 97 - .../thunar-vfs/tmpl/thunar-vfs-thumb.sgml | 48 - .../tmpl/thunar-vfs-trash-info.sgml | 60 - .../tmpl/thunar-vfs-trash-manager.sgml | 68 - .../thunar-vfs/tmpl/thunar-vfs-trash.sgml | 88 - .../thunar-vfs/tmpl/thunar-vfs-types.sgml | 109 - .../thunar-vfs/tmpl/thunar-vfs-uri.sgml | 234 - .../tmpl/thunar-vfs-user-manager.sgml | 62 - .../thunar-vfs/tmpl/thunar-vfs-user.sgml | 79 - .../thunar-vfs/tmpl/thunar-vfs-util.sgml | 49 - .../tmpl/thunar-vfs-volume-manager.sgml | 93 - .../thunar-vfs/tmpl/thunar-vfs-volume.sgml | 200 - docs/reference/thunar-vfs/version.xml.in | 1 - docs/reference/thunarx/Makefile.am | 2 +- docs/reference/thunarx/thunarx-docs.sgml | 22 +- docs/reference/thunarx/thunarx-sections.txt | 4 +- .../thunarx/tmpl/thunarx-file-info.sgml | 24 +- examples/tex-open-terminal/Makefile.am | 6 +- plugins/thunar-apr/Makefile.am | 2 +- plugins/thunar-apr/README | 2 +- plugins/thunar-sbr/Makefile.am | 2 +- plugins/thunar-sbr/README | 2 +- plugins/thunar-sbr/thunar-sbr-date-renamer.c | 87 +- plugins/thunar-sendto-email/Makefile.am | 4 - plugins/thunar-sendto-email/main.c | 186 +- plugins/thunar-uca/Makefile.am | 3 +- plugins/thunar-uca/README | 2 +- plugins/thunar-uca/thunar-uca-model.c | 63 +- plugins/thunar-uca/thunar-uca-provider.c | 31 +- plugins/thunar-wallpaper/Makefile.am | 8 +- plugins/thunar-wallpaper/twp-provider.c | 34 +- po-doc/LINGUAS | 2 - po-doc/Makefile.am | 3 +- po/LINGUAS | 2 - po/POTFILES.in | 68 +- po/Thunar.pot | 1649 ++-- tests/Makefile.am | 32 - tests/data/Makefile.am | 9 - tests/data/test-thunar-vfs-volume-bsd.fstab | 4 - tests/test-thunar-vfs-path.c | 128 - tests/test-thunar-vfs-uri.c | 82 - thunar-vfs/Makefile.am | 365 - thunar-vfs/abicheck.sh | 24 - thunar-vfs/make-thunar-vfs-alias.pl | 155 - thunar-vfs/thunar-vfs-1.pc.in | 11 - thunar-vfs/thunar-vfs-config.c | 126 - thunar-vfs/thunar-vfs-config.h.in | 63 - thunar-vfs/thunar-vfs-deep-count-job.c | 417 - thunar-vfs/thunar-vfs-deep-count-job.h | 51 - thunar-vfs/thunar-vfs-exec.h | 53 - .../thunar-vfs-font-thumbnailer-1.desktop.in | 11 - thunar-vfs/thunar-vfs-font-thumbnailer.c | 434 - thunar-vfs/thunar-vfs-info.c | 570 -- thunar-vfs/thunar-vfs-info.h | 218 - thunar-vfs/thunar-vfs-interactive-job.c | 62 - thunar-vfs/thunar-vfs-interactive-job.h | 82 - thunar-vfs/thunar-vfs-io-jobs.c | 797 -- thunar-vfs/thunar-vfs-io-jobs.h | 63 - thunar-vfs/thunar-vfs-io-local-xfer.c | 638 -- thunar-vfs/thunar-vfs-io-local-xfer.h | 65 - thunar-vfs/thunar-vfs-io-local.c | 1062 --- thunar-vfs/thunar-vfs-io-local.h | 63 - thunar-vfs/thunar-vfs-io-ops.c | 509 -- thunar-vfs/thunar-vfs-io-ops.h | 92 - thunar-vfs/thunar-vfs-io-scandir.c | 173 - thunar-vfs/thunar-vfs-io-scandir.h | 53 - thunar-vfs/thunar-vfs-io-trash.c | 1748 ---- thunar-vfs/thunar-vfs-io-trash.h | 92 - thunar-vfs/thunar-vfs-job-private.h | 91 - thunar-vfs/thunar-vfs-job.c | 1309 --- thunar-vfs/thunar-vfs-job.h | 124 - thunar-vfs/thunar-vfs-marshal.list | 4 - thunar-vfs/thunar-vfs-mime-action-private.h | 50 - thunar-vfs/thunar-vfs-mime-action.c | 92 - thunar-vfs/thunar-vfs-mime-action.h | 46 - thunar-vfs/thunar-vfs-mime-application.c | 497 -- thunar-vfs/thunar-vfs-mime-application.h | 91 - thunar-vfs/thunar-vfs-mime-cache.c | 583 -- thunar-vfs/thunar-vfs-mime-cache.h | 44 - thunar-vfs/thunar-vfs-mime-cleaner.c | 491 -- thunar-vfs/thunar-vfs-mime-database-private.h | 42 - thunar-vfs/thunar-vfs-mime-database.c | 1839 ---- thunar-vfs/thunar-vfs-mime-database.h | 76 - thunar-vfs/thunar-vfs-mime-handler-private.h | 50 - thunar-vfs/thunar-vfs-mime-handler.c | 571 -- thunar-vfs/thunar-vfs-mime-handler.h | 82 - thunar-vfs/thunar-vfs-mime-info.c | 518 -- thunar-vfs/thunar-vfs-mime-info.h | 106 - thunar-vfs/thunar-vfs-mime-legacy.c | 1183 --- thunar-vfs/thunar-vfs-mime-legacy.h | 44 - thunar-vfs/thunar-vfs-mime-parser.c | 257 - thunar-vfs/thunar-vfs-mime-parser.h | 33 - thunar-vfs/thunar-vfs-mime-provider.c | 60 - thunar-vfs/thunar-vfs-mime-provider.h | 210 - thunar-vfs/thunar-vfs-mime-sniffer.c | 118 - thunar-vfs/thunar-vfs-mime-sniffer.h | 37 - thunar-vfs/thunar-vfs-monitor-private.h | 40 - thunar-vfs/thunar-vfs-monitor.c | 851 -- thunar-vfs/thunar-vfs-monitor.h | 106 - thunar-vfs/thunar-vfs-os-bsd.c | 322 - thunar-vfs/thunar-vfs-os-generic.c | 225 - thunar-vfs/thunar-vfs-os.h | 42 - thunar-vfs/thunar-vfs-path-private.h | 101 - thunar-vfs/thunar-vfs-path.c | 1483 ---- thunar-vfs/thunar-vfs-path.h | 279 - thunar-vfs/thunar-vfs-pixbuf-thumbnailer.c | 85 - thunar-vfs/thunar-vfs-private.c | 438 - thunar-vfs/thunar-vfs-private.h | 126 - thunar-vfs/thunar-vfs-simple-job.c | 203 - thunar-vfs/thunar-vfs-simple-job.h | 67 - thunar-vfs/thunar-vfs-thumb-jpeg.c | 657 -- thunar-vfs/thunar-vfs-thumb-jpeg.h | 37 - thunar-vfs/thunar-vfs-thumb-private.h | 37 - thunar-vfs/thunar-vfs-thumb.c | 1251 --- thunar-vfs/thunar-vfs-thumb.h | 86 - thunar-vfs/thunar-vfs-transfer-job.c | 630 -- thunar-vfs/thunar-vfs-transfer-job.h | 48 - thunar-vfs/thunar-vfs-types.h | 158 - .../thunar-vfs-update-thumbnailers-cache.c | 589 -- thunar-vfs/thunar-vfs-user.h | 87 - thunar-vfs/thunar-vfs-util.c | 341 - thunar-vfs/thunar-vfs-util.h | 40 - thunar-vfs/thunar-vfs-volume-freebsd.c | 528 -- thunar-vfs/thunar-vfs-volume-freebsd.h | 55 - thunar-vfs/thunar-vfs-volume-hal.c | 1244 --- thunar-vfs/thunar-vfs-volume-hal.h | 55 - thunar-vfs/thunar-vfs-volume-manager.c | 492 -- thunar-vfs/thunar-vfs-volume-none.c | 73 - thunar-vfs/thunar-vfs-volume-none.h | 55 - thunar-vfs/thunar-vfs-volume-private.h | 113 - thunar-vfs/thunar-vfs-volume.c | 722 -- thunar-vfs/thunar-vfs-volume.h | 146 - thunar-vfs/thunar-vfs.c | 815 -- thunar-vfs/thunar-vfs.h | 112 - thunar-vfs/thunar-vfs.symbols | 339 - thunar/Makefile.am | 85 +- thunar/main.c | 89 +- thunar/thunar-abstract-icon-view.c | 4 - thunar/thunar-application.c | 985 ++- thunar/thunar-application.h | 32 +- thunar/thunar-browser.c | 549 ++ thunar/thunar-browser.h | 72 + thunar/thunar-chooser-button.c | 131 +- thunar/thunar-chooser-dialog.c | 232 +- thunar/thunar-chooser-model.c | 450 +- thunar/thunar-chooser-model.h | 23 +- thunar/thunar-clipboard-manager.c | 53 +- thunar/thunar-clipboard-manager.h | 3 +- thunar/thunar-create-dialog.c | 155 +- thunar/thunar-create-dialog.h | 27 +- thunar/thunar-dbus-client.c | 16 + thunar/thunar-dbus-client.h | 2 + thunar/thunar-dbus-service-infos.xml | 16 +- thunar/thunar-dbus-service.c | 65 +- thunar/thunar-debug.c | 4 - thunar/thunar-deep-count-job.c | 373 + thunar/thunar-deep-count-job.h | 48 + thunar/thunar-details-view.c | 20 - thunar/thunar-dialogs.c | 152 +- thunar/thunar-dialogs.h | 45 +- thunar/thunar-dnd.c | 21 +- thunar/thunar-enum-types.c | 57 + thunar/thunar-enum-types.h | 56 + .../thunar-vfs-exec.c => thunar/thunar-exec.c | 251 +- thunar/thunar-exec.h | 54 + thunar/thunar-file.c | 2272 +++-- thunar/thunar-file.h | 397 +- thunar/thunar-folder.c | 204 +- thunar/thunar-gio-extensions.c | 446 + thunar/thunar-gio-extensions.h | 73 + thunar/thunar-gtk-extensions.c | 4 - thunar/thunar-icon-factory.c | 345 +- thunar/thunar-icon-factory.h | 4 - thunar/thunar-image.c | 253 + thunar/thunar-image.h | 47 + thunar/thunar-io-jobs-util.c | 139 + thunar/thunar-io-jobs-util.h | 36 + thunar/thunar-io-jobs.c | 1162 +++ thunar/thunar-io-jobs.h | 56 + thunar/thunar-io-scan-directory.c | 130 + thunar/thunar-io-scan-directory.h | 39 + thunar/thunar-job.c | 624 ++ thunar/thunar-job.h | 94 + thunar/thunar-launcher.c | 818 +- thunar/thunar-list-model.c | 215 +- thunar/thunar-location-button.c | 53 +- thunar/thunar-location-buttons.c | 33 +- thunar/thunar-location-dialog.c | 2 +- thunar/thunar-location-entry.c | 247 +- thunar/thunar-marshal.list | 5 + thunar/thunar-metafile.c | 46 +- thunar/thunar-metafile.h | 7 +- thunar/thunar-misc-jobs.c | 104 + thunar/thunar-misc-jobs.h | 32 + thunar/thunar-path-entry.c | 93 +- thunar/thunar-permissions-chooser.c | 265 +- thunar/thunar-preferences-dialog.c | 103 +- thunar/thunar-preferences.c | 71 +- thunar/thunar-private.h | 20 - thunar/thunar-progress-dialog.c | 163 +- thunar/thunar-progress-dialog.h | 11 +- thunar/thunar-properties-dialog.c | 240 +- thunar/thunar-renamer-dialog.c | 36 +- thunar/thunar-renamer-dialog.h | 3 +- thunar/thunar-renamer-model.c | 48 +- thunar/thunar-renamer-progress.c | 2 +- thunar/thunar-sendto-model.c | 196 +- thunar/thunar-shortcuts-icon-renderer.c | 45 +- thunar/thunar-shortcuts-model.c | 474 +- thunar/thunar-shortcuts-view.c | 590 +- thunar/thunar-simple-job.c | 232 + thunar/thunar-simple-job.h | 64 + thunar/thunar-size-label.c | 107 +- thunar/thunar-standard-view.c | 280 +- thunar/thunar-templates-action.c | 555 +- thunar/thunar-text-renderer.c | 19 - thunar/thunar-thumbnail-generator.c | 368 - thunar/thunar-thumbnail-generator.h | 46 - thunar/thunar-thumbnailer-dbus.xml | 36 + thunar/thunar-thumbnailer-manager-dbus.xml | 14 + thunar/thunar-thumbnailer.c | 1096 +++ thunar/thunar-thumbnailer.h | 48 + thunar/thunar-transfer-job.c | 887 ++ thunar/thunar-transfer-job.h | 60 + thunar/thunar-trash-action.c | 9 +- thunar/thunar-tree-model.c | 280 +- thunar/thunar-tree-model.h | 2 +- thunar/thunar-tree-view.c | 777 +- .../thunar-vfs-user.c => thunar/thunar-user.c | 394 +- thunar/thunar-user.h | 88 + thunar/thunar-util.c | 105 +- thunar/thunar-util.h | 16 +- thunar/thunar-window.c | 401 +- thunarx/Makefile.am | 22 +- thunarx/abicheck.sh | 2 +- thunarx/thunarx-1.pc.in | 13 - thunarx/thunarx-2.pc.in | 13 + thunarx/thunarx-file-info.c | 74 +- thunarx/thunarx-file-info.h | 78 +- thunarx/thunarx.symbols | 5 +- 270 files changed, 24407 insertions(+), 41428 deletions(-) create mode 100644 .gitignore create mode 100644 ChangeLog.pre-gio delete mode 100644 INSTALL delete mode 100644 docs/reference/thunar-vfs/Makefile.am delete mode 100644 docs/reference/thunar-vfs/thunar-vfs-docs.sgml delete mode 100644 docs/reference/thunar-vfs/thunar-vfs-overrides.txt delete mode 100644 docs/reference/thunar-vfs/thunar-vfs-sections.txt delete mode 100644 docs/reference/thunar-vfs/thunar-vfs.types delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-group.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-info.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-init-shutdown.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-interactive-job.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-job.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-jobs.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-action.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-application.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-database.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-handler.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-info.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-monitor.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-operations.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-path.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-thumb-factory.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-thumb.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-trash-info.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-trash-manager.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-trash.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-types.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-uri.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-user-manager.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-user.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-util.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-volume-manager.sgml delete mode 100644 docs/reference/thunar-vfs/tmpl/thunar-vfs-volume.sgml delete mode 100644 docs/reference/thunar-vfs/version.xml.in delete mode 100644 po-doc/LINGUAS delete mode 100644 po/LINGUAS delete mode 100644 tests/Makefile.am delete mode 100644 tests/data/Makefile.am delete mode 100644 tests/data/test-thunar-vfs-volume-bsd.fstab delete mode 100644 tests/test-thunar-vfs-path.c delete mode 100644 tests/test-thunar-vfs-uri.c delete mode 100644 thunar-vfs/Makefile.am delete mode 100755 thunar-vfs/abicheck.sh delete mode 100755 thunar-vfs/make-thunar-vfs-alias.pl delete mode 100644 thunar-vfs/thunar-vfs-1.pc.in delete mode 100644 thunar-vfs/thunar-vfs-config.c delete mode 100644 thunar-vfs/thunar-vfs-config.h.in delete mode 100644 thunar-vfs/thunar-vfs-deep-count-job.c delete mode 100644 thunar-vfs/thunar-vfs-deep-count-job.h delete mode 100644 thunar-vfs/thunar-vfs-exec.h delete mode 100644 thunar-vfs/thunar-vfs-font-thumbnailer-1.desktop.in delete mode 100644 thunar-vfs/thunar-vfs-font-thumbnailer.c delete mode 100644 thunar-vfs/thunar-vfs-info.c delete mode 100644 thunar-vfs/thunar-vfs-info.h delete mode 100644 thunar-vfs/thunar-vfs-interactive-job.c delete mode 100644 thunar-vfs/thunar-vfs-interactive-job.h delete mode 100644 thunar-vfs/thunar-vfs-io-jobs.c delete mode 100644 thunar-vfs/thunar-vfs-io-jobs.h delete mode 100644 thunar-vfs/thunar-vfs-io-local-xfer.c delete mode 100644 thunar-vfs/thunar-vfs-io-local-xfer.h delete mode 100644 thunar-vfs/thunar-vfs-io-local.c delete mode 100644 thunar-vfs/thunar-vfs-io-local.h delete mode 100644 thunar-vfs/thunar-vfs-io-ops.c delete mode 100644 thunar-vfs/thunar-vfs-io-ops.h delete mode 100644 thunar-vfs/thunar-vfs-io-scandir.c delete mode 100644 thunar-vfs/thunar-vfs-io-scandir.h delete mode 100644 thunar-vfs/thunar-vfs-io-trash.c delete mode 100644 thunar-vfs/thunar-vfs-io-trash.h delete mode 100644 thunar-vfs/thunar-vfs-job-private.h delete mode 100644 thunar-vfs/thunar-vfs-job.c delete mode 100644 thunar-vfs/thunar-vfs-job.h delete mode 100644 thunar-vfs/thunar-vfs-marshal.list delete mode 100644 thunar-vfs/thunar-vfs-mime-action-private.h delete mode 100644 thunar-vfs/thunar-vfs-mime-action.c delete mode 100644 thunar-vfs/thunar-vfs-mime-action.h delete mode 100644 thunar-vfs/thunar-vfs-mime-application.c delete mode 100644 thunar-vfs/thunar-vfs-mime-application.h delete mode 100644 thunar-vfs/thunar-vfs-mime-cache.c delete mode 100644 thunar-vfs/thunar-vfs-mime-cache.h delete mode 100644 thunar-vfs/thunar-vfs-mime-cleaner.c delete mode 100644 thunar-vfs/thunar-vfs-mime-database-private.h delete mode 100644 thunar-vfs/thunar-vfs-mime-database.c delete mode 100644 thunar-vfs/thunar-vfs-mime-database.h delete mode 100644 thunar-vfs/thunar-vfs-mime-handler-private.h delete mode 100644 thunar-vfs/thunar-vfs-mime-handler.c delete mode 100644 thunar-vfs/thunar-vfs-mime-handler.h delete mode 100644 thunar-vfs/thunar-vfs-mime-info.c delete mode 100644 thunar-vfs/thunar-vfs-mime-info.h delete mode 100644 thunar-vfs/thunar-vfs-mime-legacy.c delete mode 100644 thunar-vfs/thunar-vfs-mime-legacy.h delete mode 100644 thunar-vfs/thunar-vfs-mime-parser.c delete mode 100644 thunar-vfs/thunar-vfs-mime-parser.h delete mode 100644 thunar-vfs/thunar-vfs-mime-provider.c delete mode 100644 thunar-vfs/thunar-vfs-mime-provider.h delete mode 100644 thunar-vfs/thunar-vfs-mime-sniffer.c delete mode 100644 thunar-vfs/thunar-vfs-mime-sniffer.h delete mode 100644 thunar-vfs/thunar-vfs-monitor-private.h delete mode 100644 thunar-vfs/thunar-vfs-monitor.c delete mode 100644 thunar-vfs/thunar-vfs-monitor.h delete mode 100644 thunar-vfs/thunar-vfs-os-bsd.c delete mode 100644 thunar-vfs/thunar-vfs-os-generic.c delete mode 100644 thunar-vfs/thunar-vfs-os.h delete mode 100644 thunar-vfs/thunar-vfs-path-private.h delete mode 100644 thunar-vfs/thunar-vfs-path.c delete mode 100644 thunar-vfs/thunar-vfs-path.h delete mode 100644 thunar-vfs/thunar-vfs-pixbuf-thumbnailer.c delete mode 100644 thunar-vfs/thunar-vfs-private.c delete mode 100644 thunar-vfs/thunar-vfs-private.h delete mode 100644 thunar-vfs/thunar-vfs-simple-job.c delete mode 100644 thunar-vfs/thunar-vfs-simple-job.h delete mode 100644 thunar-vfs/thunar-vfs-thumb-jpeg.c delete mode 100644 thunar-vfs/thunar-vfs-thumb-jpeg.h delete mode 100644 thunar-vfs/thunar-vfs-thumb-private.h delete mode 100644 thunar-vfs/thunar-vfs-thumb.c delete mode 100644 thunar-vfs/thunar-vfs-thumb.h delete mode 100644 thunar-vfs/thunar-vfs-transfer-job.c delete mode 100644 thunar-vfs/thunar-vfs-transfer-job.h delete mode 100644 thunar-vfs/thunar-vfs-types.h delete mode 100644 thunar-vfs/thunar-vfs-update-thumbnailers-cache.c delete mode 100644 thunar-vfs/thunar-vfs-user.h delete mode 100644 thunar-vfs/thunar-vfs-util.c delete mode 100644 thunar-vfs/thunar-vfs-util.h delete mode 100644 thunar-vfs/thunar-vfs-volume-freebsd.c delete mode 100644 thunar-vfs/thunar-vfs-volume-freebsd.h delete mode 100644 thunar-vfs/thunar-vfs-volume-hal.c delete mode 100644 thunar-vfs/thunar-vfs-volume-hal.h delete mode 100644 thunar-vfs/thunar-vfs-volume-manager.c delete mode 100644 thunar-vfs/thunar-vfs-volume-none.c delete mode 100644 thunar-vfs/thunar-vfs-volume-none.h delete mode 100644 thunar-vfs/thunar-vfs-volume-private.h delete mode 100644 thunar-vfs/thunar-vfs-volume.c delete mode 100644 thunar-vfs/thunar-vfs-volume.h delete mode 100644 thunar-vfs/thunar-vfs.c delete mode 100644 thunar-vfs/thunar-vfs.h delete mode 100644 thunar-vfs/thunar-vfs.symbols create mode 100644 thunar/thunar-browser.c create mode 100644 thunar/thunar-browser.h create mode 100644 thunar/thunar-deep-count-job.c create mode 100644 thunar/thunar-deep-count-job.h rename thunar-vfs/thunar-vfs-exec.c => thunar/thunar-exec.c (67%) create mode 100644 thunar/thunar-exec.h create mode 100644 thunar/thunar-gio-extensions.c create mode 100644 thunar/thunar-gio-extensions.h create mode 100644 thunar/thunar-image.c create mode 100644 thunar/thunar-image.h create mode 100644 thunar/thunar-io-jobs-util.c create mode 100644 thunar/thunar-io-jobs-util.h create mode 100644 thunar/thunar-io-jobs.c create mode 100644 thunar/thunar-io-jobs.h create mode 100644 thunar/thunar-io-scan-directory.c create mode 100644 thunar/thunar-io-scan-directory.h create mode 100644 thunar/thunar-job.c create mode 100644 thunar/thunar-job.h create mode 100644 thunar/thunar-misc-jobs.c create mode 100644 thunar/thunar-misc-jobs.h create mode 100644 thunar/thunar-simple-job.c create mode 100644 thunar/thunar-simple-job.h delete mode 100644 thunar/thunar-thumbnail-generator.c delete mode 100644 thunar/thunar-thumbnail-generator.h create mode 100644 thunar/thunar-thumbnailer-dbus.xml create mode 100644 thunar/thunar-thumbnailer-manager-dbus.xml create mode 100644 thunar/thunar-thumbnailer.c create mode 100644 thunar/thunar-thumbnailer.h create mode 100644 thunar/thunar-transfer-job.c create mode 100644 thunar/thunar-transfer-job.h rename thunar-vfs/thunar-vfs-user.c => thunar/thunar-user.c (51%) create mode 100644 thunar/thunar-user.h delete mode 100644 thunarx/thunarx-1.pc.in create mode 100644 thunarx/thunarx-2.pc.in diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..946970150 --- /dev/null +++ b/.gitignore @@ -0,0 +1,132 @@ +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +compile +config.guess +config.h +config.h.in +config.log +config.status +config.sub +configure +configure.in +depcomp +install-sh +intltool-* +libtool +ltmain.sh +mkinstalldirs +missing +stamp-h1 +.*.swp +[Tt]hunar-*.tar.bz2 +[Tt]hunar-*.tar.gz +core.* +core +*.core +*.desktop +*.desktop.in +*.service +gtk-doc.make +ThunarBulkRename +ThunarHelp +Thunar.spec +docs/.*.swp +docs/*.1 +docs/design/.*.swp +docs/manual/.*.swp +docs/manual/*/.*.swp +docs/manual/*/Thunar.xml +docs/manual/*/html +docs/manual/*/*.stamp +docs/manual/*/images/.*.swp +docs/papers/.*.swp +docs/reference/.*.swp +docs/reference/thunarx/xml +docs/reference/thunarx/html +docs/reference/thunarx/*.stamp +docs/reference/thunarx/.*.swp +docs/reference/thunarx/*.bak +docs/reference/thunarx/thunarx-decl-list.txt +docs/reference/thunarx/thunarx-decl.txt +docs/reference/thunarx/thunarx-overrides.txt +docs/reference/thunarx/thunarx-undeclared.txt +docs/reference/thunarx/thunarx-undocumented.txt +docs/reference/thunarx/thunarx-unused.txt +docs/reference/thunarx/thunarx.args +docs/reference/thunarx/thunarx.hierarchy +docs/reference/thunarx/thunarx.interfaces +docs/reference/thunarx/thunarx.prerequisites +docs/reference/thunarx/thunarx.signals +docs/reference/thunarx/version.xml +docs/reference/thunarx/tmpl/*.bak +docs/reference/thunarx/tmpl/.*.swp +docs/reference/thunarx/tmpl/thunarx-unused.sgml +examples/.*.swp +examples/tex-open-terminal/.*.swp +icons/.*.swp +icons/16x16/.*.swp +icons/24x24/.*.swp +icons/48x48/.*.swp +icons/scalable/.*.swp +pixmaps/.*.swp +plugins/.*.swp +plugins/thunar-apr/.*.swp +plugins/thunar-sbr/.*.swp +plugins/thunar-sendto-email/thunar-sendto-email +plugins/thunar-sendto-email/thunar-sendto-email.desktop +plugins/thunar-sendto-email/.*.swp +plugins/thunar-tpa/thunar-tpa-bindings.h +plugins/thunar-tpa/thunar-tpa.desktop +plugins/thunar-tpa/thunar-tpa.desktop.in +plugins/thunar-tpa/.*.swp +plugins/thunar-tpa/thunar-tpa +plugins/thunar-uca/.*.swp +plugins/thunar-uca/uca.xml +po-doc/.*.swp +po-doc/.xml2po.mo +po/Makefile.in.in +po/.*.swp +po/*.gmo +po/*.mo +po/POTFILES +po/*.pot +po/.intltool-merge-cache +po/stamp-* +tdb/tdbconfig.h +tdb/.*.swp +tdb/tdbspeed +tdb/tdbtool +tdb/tdbtorture +tdb/*.tdb +tests/*.loT +tests/.*.swp +tests/core.* +tests/*.core +tests/data/.*.swp +thunar/*.loT +thunar/.*.swp +thunar/thunar-fallback-icon.c +thunar/thunar-throbber-fallback.c +thunar/thunar-thumbnail-frame.c +thunar/thunar-thumbnailer-manager-proxy.h +thunar/thunar-thumbnailer-proxy.h +thunar/Thunar +thunar/core.* +thunar/*.core +thunar/thunar-marshal.[ch] +thunar/thunar-*-ui.h +thunar/stamp-thunar-*.* +thunar/thunar-dbus-service-infos.h +thunarx/.*.swp +thunarx/*.pc +thunarx/thunarx-alias*.[ch] +thunarx/thunarx-config.h +*.o +*.lo +*.la +.libs +.deps +thunar-vfs +config.h.in~ diff --git a/AUTHORS b/AUTHORS index ae59092ee..243174992 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,5 @@ Benedikt Meurer <benny@xfce.org> +Jannis Pohlmann <jannis@xfce.org> Jeffs Franks <jcfranks@xfce.org> The tdb library, which is included with the Thunar distribution, was originally diff --git a/ChangeLog b/ChangeLog index adc970e9a..732a18e9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,892 @@ +2009-07-22 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Fix typo in thunar_file_info_has_mime_type() + which caused a lot of problems. Patch by Nick. + +2009-07-18 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Only return true from + thunar_file_is_executable() if the file is either a desktop file or + is an application/x-executable or application/x-shellscript. On + Windows we use g_content_type_can_be_executable() directly instead + of checking for these two content types. Patch by Nick. + +2009-07-18 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Introduce new function + thunar_file_same_filesystem() which uses + G_FILE_ATTRIBUTE_ID_FILESYSTEM to check whether two files reside on + the same device/filesystem. Use this to fix the copy/move decision + in thunar_file_accepts_drop(). + * thunarx/thunarx-file-info.h: Add the "id" namespace to + THUNARX_FILE_INFO_NAMESPACE. + +2009-07-18 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-launcher.c: Make executing files work again. Note that + this only works for one selected file right now. Poking/launching + multiple files/directories still have to be worked on anyway. + +2009-06-20 Jannis Pohlmann <jannis@xfce.org> + + * po/POTFILES.in: Add thunar-settings.desktop.in. + +2009-06-20 Jannis Pohlmann <jannis@xfce.org> + + * po/POTFILES.in: Remove thunar-vfs source files, update those of + Thunar itself. + +2009-06-20 Jannis Pohlmann <jannis@xfce.org> + + * docs/reference/thunarx/Makefile.am: Use THUNARX_VERSION_API instead + of THUNAR_VERSION_API. + +2009-06-20 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in, Makefile.am, tests/: Remove test folder which only + tests thunar-vfs anyway. + * docs/reference/thunar-vfs/, thunar-vfs/: Remove empty folders. + +2009-06-20 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in: Add header and function checks required for tdb. + +2009-06-20 Jannis Pohlmann <jannis@xfce.org> + + * Remove thunar-vfs. There might be some pieces left which will be + cleaned up next. Update the list of functions and headers the + configure script checks because a lot of them were only required for + thunar-vfs. + +2009-06-20 Jannis Pohlmann <jannis@xfce.org> + + * Makefile.am, configure.in.in, plugins/, thunarx/, thunar/: + thunarx-1 is dead, long live thunarx-2. thunarx-2 introduces three + new functions: thunarx_file_info_get_file_info() which returns the + GFileInfo of a ThunarxFileInfo, + thunarx_file_info_get_filesystem_info() which returns a GFileInfo + with filesystem information for a ThunarxFileInfo and + thunarx_file_info_get_location() which returns the GFile the + ThunarxFileInfo refers to. thunarx-2 doesn't have + thunarx_file_info_get_vfs_info() anymore. Port all plugins shipped + with Thunar from thunarx-1 to thunarx-2. Especially thunar-uca and + thunar-sendto-email need testing due to non-trivial changes. Don't + link Thunar against ThunarVFS anymore - ALL REFERENCES ARE GONE! + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Nothing really. + * thunar/thunar-window.c: Derive from ThunarBrowser and use + thunar_browser_poke_file() to resolve/mount files when the location + dialog is activated. + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-list-model.c: Fix thunar_list_model_get_value() and + thunar_list_model_get_statusbar_text() for files without content + type. Use special statusbar texts for mountables and shortcuts. + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Assume the file is read- and writable if it + has no G_FILE_ATTRIBUTE_ACCESS_CAN_READ or + G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE attribute. This usually is the + case with shortcuts and mountables. This change removes all those + irritating emblems when browsing computer://, network:// and smb://. + Only show the "drive-harddisk" icon for local root directories (this + should only be the filesystem root, not media or anything). + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am: Add missing entries for thunar-browser.{c,h}. + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-launcher.c: Derive from ThunarBrowser and use the poke + file function to resolve/mount/open the selected file, if there is + only one selected. Still need to work on selections of more files. + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-path-entry.c: Unescape URIs before displaying them. + This is to make sure we don't see things like "%20" in the location + bar/dialog. + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-location-entry.c: Simplify the activate code by + deriving from ThunarBrowser and using the poke functions to mount + volumes or resolve files asynchronously and on demand. + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-shortcuts-view.c: Dramatically simplify the way + directories and volumes are mounted and opened by deriving from + ThunarBrowser and calling thunar_browser_poke_file() and + thunar_browser_poke_volume() to resolve directories and volumes + before opening them. + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-browser.{c,h}: Add a new interface with two + convenience functions for browsing (possibly not yet mounted or + resolved) volumes and files. thunar_browser_poke_file() can be used + to asynchronously resolve shortcuts, mount mountables or enclosing + volumes. When finished, the ThunarBrowserPokeFileFunc callback is + called with the source and target file. thunar_browser_poke_volume() + mounts volumes on demand and resolves the mount point and passes it + to the ThunarBrowsePokeVolumeFunc callback. Both functions are + possibly asynchronous. + +2009-06-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Add "mountable::*" namespace to the file + info attributes we request from the GFileInfo. In + thunar_file_load(), check for type G_FILE_TYPE_MOUNTABLE and set + is_mounted to FALSE if its G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT is + TRUE. Add function thunar_file_get_target_location() which returns + a GFile for the target location of a file of type + G_FILE_TYPE_SHORTCUT or G_FILE_TYPE_MOUNTABLE and otherwise returns + NULL. Don't assume all files have a content type - shortcuts and + mountables don't. Work around this in thunar_file_is_desktop_file() + and thunar_file_list_get_applications(). Check if we have a + GFileInfo before querying the original path in + thunar_file_get_original_path(). + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Use special icon names for root folders other + than trash://: "disk-harddrive" for the local root and + "folder-remote" for root folders on other machines. + * thunar/thunar-location-button.c: Show a label even for the local + root, just to be more consistent. + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-shortcuts-view.c: Rework mounting and mounting + open. + Also make opening items other than volumes work asynchronously. To + do that, first check if the file to be opened is mounted already. If + that's the case, open it directly. If not, mount the enclosing + volume asynchronously and open the file in the mount callback. This + works for opening in the same or a new window. + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-shortcuts-model.c: Minor code reorganization. + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-window.c: Split thunar_window_start_open_location() + up into three functions and load unmounted files asynchronously. + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-location-entry.c: Check if files are mounted before + mounting their volumes asynchronously. If they are, just open them + directly. Rework the code a bit, add a new private method + thunar_location_entry_open_or_launch(). + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Add new boolean is_mounted member to + ThunarFile. It is FALSE iff the GFileInfo of the file couldn't be + loaded due to G_IO_ERROR_NO_MOUNTED. Return TRUE from + thunar_file_load() only when the file info could be loaded or the + file is not mounted yet. Use the path instead of the file:// URI for + the display name of local files. Add new method + thunar_file_is_mounted(). Add support for GFileIcons in + thunar_file_get_icon_name() by returning the path to the icon + filename if the file has a GFileIcon. Call thunar_file_reload() + instead of thunar_file_destroy() on G_FILE_MONITOR_EVENT_DELETED and + G_FILE_MONITOR_EVEN_PRE_UNMOUNT. The reload function will then + destroy the file if it doesn't exist anymore. Not mounted files will + not be destroyed though. + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-thumbnailer.c: Make all D-Bus related code only + available when D-Bus is installed at compile time. + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-shortcuts-view.c: Don't request context menu items + from Thunarx for files which don't exist. Reported by Nick. + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Refactor thunar_file_load() and + thunar_file_get() a bit. For now, thunar_file_load() will always + return successful, even if the GFileInfo cannot be loaded. This is + because we want ThunarFiles for remote URIs that are not yet + mounted. To compensate for that, there's a new method + thunar_file_exists() which returns TRUE iff the ThunarFile exists. + +2009-06-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/main.c, thunar/thunar-application.{c,h}: + thunar_application_process_filenames() now works asynchronously + because it might have to mount the enclosing volumes of one of the + filenames first (which is only possible asynchronously). Add new + method thunar_application_is_processing() which returns whether + ThunarApplication is still busy processing filenames or not. In + main(), always enter the main loop but schedule an idle source to + repeatedly check whether ThunarApplication has finished processing + the command line arguments. Once this is the case, exit if there are + no open Thunar windows. All in all, this gives us about the same + behaviour main() had before, except that it the application might + exit with a short delay. The result: Calling "thunar <remote URI>" + from the shell works now! + +2009-06-16 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-location-entry.c: Split + thunar_location_entry_activate() up into two functions, + thunar_location_entry_activate() an + thunar_location_entry_activate_finished(). Use + g_file_mount_enclosing_volume() to make sure the volume is mounted + before we switch to the new directory or launch the file. Remote + machine browsing, here we come! + +2009-06-16 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: In thunar_file_reload(), always reload the + file first, before checking if it still exists and needs to be + destroyed. + +2009-06-16 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-path-entry.c: Display the local path only for native + files. If there is no path, use the URI. Always use the URI for + non-native files. + +2009-06-16 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-renamer-model.c: Remove the ThunarVfsInfo member of + ThunarRenamerModelItem. Always invalidate and update the item/row + when the ThunarFile changes (unless the model is frozen of course). + ThunarRenamerModel is now ThunarVFS-free. + +2009-06-16 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Use S_ISCHR, S_ISSOCK, S_ISFIFO and S_ISBLK to + generate the first character of mode strings for special/unknown + file types because we don't have THUNAR_VFS_FILE_TYPE_SOCKET etc. + anymore. There will be no replacements for THUNAR_VFS_FILE_TYPE_PORT + and THUNAR_VFS_FILE_TYPE_DOOR for now. + +2009-06-16 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-icon-factory.c: Remove commented code. + +2009-06-15 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-thumbnailer.c: Don't queue files that are part of an + already queued thumbnailer request or a ready idle struct. This + dramatically reduces the amount of D-Bus messages being sent. + +2009-06-15 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-icon-factory.c: Drop the ThunarVfsThumbFactory + reference. Don't cache SVGs. The number of SVGs we need to load that + are not ThunarFiles is relatively small, I don't think we need to + cache them. ThunarThumbnailer takes care of the ThunarFiles that are + SVGs. Always try to load thumbnails for files, even though their + thumbnail state is not ready. Don't use the loading icon. Together, + this reduces flicker when switching folders. ThunarIconFactory is + now ThunarVFS-free. + +2009-06-15 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Add new boolean method + thunar_file_is_thumbnail() which returns TRUE if, and only if + a file resides in $HOME/.thumbnails/. + +2009-06-15 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-icon-factory.c: Rewrite the file icon loading process + once again, this time based on the also rewritten ThunarThumbnailer. + We first assume no thumbnail exists and use the default icon for the + MIME type. At the same time we request a thumbnail. Once the + thumbnailer has started processing the request, we change to a + loading icon. Once thumbnailer has the thumbnail ready, we change + to the thumbnail. If there's an error with the thumbnail, we + fall back to the default icon. + * thunar/thunar-image.c: Simplify this one. It now always requests the + icon from the icon factory and uses ThunarFileMonitor to watch the + file for changes. After each change it requests the icon from the + factory again. It's probably a good idea to use the thumbnailer + directly, so this will change in the future. + * thunar/thunar-list-model.c: Don't request thumbnails for the entire + content of new folders. Instead, just let the icon renderers do + their job. In the future, the model should at least unqueue all + requests for the old folder when the folder changes. + * thunar/thunar-thumbnailer.{c,h}: Rewrite the class entirely. It does + asynchronous D-Bus calls now and uses idle sources for updating the + thumbnail state of the ThunarFiles for which it requests the + thumbnails. It doesn't emit any signals anymore. In the future, + there should be a method to cancel all requests made by a component + for a certain base URI, so that we can cancel all pending requests + when leaving a folder. + +2009-06-14 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Emit a ThunarFileMonitor "file-changed" + signal whenever the thumbnail state of a ThunarFile is changed. This + helps all components in refreshing their file information and + possibly update the file icon. + +2009-06-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-thumbnailer-manager-dbus.xml: Add + XML D-Bus information for the org.freedesktop.thumbnails.Manager + interface. + * thunar/thunar-thumbnailer.{c,h}: Start implementing the client side + of the org.freedesktop.thumbnails.Manager interface. Add new method + thunar_thumbnailer_file_is_supported() which requests the supported + content types from the thumbnailer manager on demand and checks if + the content type of a ThunarFile is a subtype of any of these. Use + this in thunar_thumbnailer_queue_files() and + thunar_thumbnailer_queue_file() to filter out files which + are not supported by the thumbnailer anyway. Make queue requests + fail when there are no supported files in the request. + +2009-06-12 Jannis Pohlmann <jannis@xfce.org> + + * Makefile.am, thunar/thunar-image.{c,h}, + thunar/thunar-thumbnailer-dbus.xml, thunar/thunar-thumbnailer.{c,h}: + Add two new classes ThunarImage and ThunarThumbnailer. ThunarImage + is a subclass of GtkImage which takes a ThunarFile and + asynchronously loads a thumbnail for the file using the + org.freedesktop.thumbnails.Thumbnailer D-Bus service. + ThunarThumbnailer is essentially a proxy client for this service + which adds a few convenience methods around the DBusGProxy API. It + can be used by other classes to request thumbnails over D-Bus. + * thunar/thunar-file.{c,h}: Add a new method + thunar_file_get_thumbnail_path(), which returns the thumbnail path + for a ThunarFile. GFileInfo has something similar but unfortunately + it's only set if the thumbnail exists, which means you have to + reload the GFileInfo whenever a new thumbnail has been generated ... + and unfortunately that requires a thunar_file_reload() which causes + a lot of flicker. Another new method is + thunar_file_get_preview_icon() which returns a preview GIcon that + can act as a thumbnail replacement if there is any. + * thunar/thunar-folder.c: Make sure never to emit the "files-added" + signal with an empty list. + * thunar/thunar-icon-factory.c: Use thunar_file_get_preview_icon() and + thunar_file_get_thumbnail_path() to load ThunarFile icons. Drop the + reference on ThunarThumbnailGenerator. Thumbnails are now requested + by ThunarListModel and ThunarImage instead of the icon factory. + * thunar/thunar-list-model.c: Request thumbnails from + ThunarThumbnailer whenever the "files-added" signal is emitted. + Unqueue all pending requests when the folder changes or the list + model is destroyed. Still missing: thumbnail requests after file + change events. + * thunar/thunar-marshal.list: Add another marshaller: + VOID:UINT,POINTER,UINT,STRING. + * thunar/thunar-private.h: Remove ifdefs for GLib <= 2.14. + * thunar/thunar-properties-dialog.c: Use ThunarImage for the file + icon instead of a regular GtkImage. + * thunar/thunar-thumbnail-generator.{c,h}: Remove the + ThunarThumbnailerGenerator class. We no longer need it. + +2009-05-12 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in: Depend on libexo-0.3.101svn-r29948 for + exo_job_send_to_mainloop(). + * thunar/thunar-dialogs.{c,h}, thunar/thunar-io-jobs.{c,h}, + thunar/thunar-dialogs.{c,h}, thunar/thunar-properties-dialog.c, + thunar/thunar-standard-view.c, thunar/thunar-tree-view.c: Add new + simple job thunar_io_jobs_rename_file() which renames a ThunarFile + asynchronously. Make us of it in thunar_dialogs_show_rename_file() + which now launches and returns the rename job instead of calling + thunar_file_rename() directly. Update ThunarPropertiesDialog, + ThunarStandardView and ThunarTreeView to handle the error/finished + signals and destroy the job when it's finished. + * thunar/thunar-file.{c,h}: Add a GCancellable parameter and a boolean + parameter called "called_from_job". The latter is used to disable + the thunarx_file_info_renamed() and thunar_file_changed() calls. The + rename job is responsible to call these in the mainloop of the + application after the rename has succeeded. + * thunar/thunar-simple-job.{c,h}: Add new function + thunar_simple_job_get_param_values() which returns the GValueArray + created from the parameters passed to thunar_simple_job_launch(). + +2009-05-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-exec.{c,h}: Import thunar_exec_*() + functions from ThunarVFS. A part of that can probably be replaced + with calls to libxfce4ui. + * thunar/thunar-dialogs.{c,h}: Rename left-out THUNAR_VFS_JOB_RESPONSE* + defines to THUNAR_JOB_RESPONSE*. Remove thunar-vfs.h include. + * thunar/thunar-file.{c,h}: Remove the ThunarVfsInfo struct member of + ThunarFile. In all function calls, make sure that we don't crash if + we can't load the GFileInfo for the file. Cache the basename and + display name of the file in thunar_file_load(). If no GFileInfo is + available, try to guess them from the GFile. Use the new methods for + querying a GKeyFile for a GFile to determine the custom icon name, + if available. Cache that one, too. Remove thunar_file_get_for_info(), + thunar_file_get_for_path(), rewrite thunar_file_get_for_uri(), + rewrite thunar_file_get_parent(), thunar_file_execute() (based on + thunar_exec_*() functions), thunar_file_rename() (based on + g_file_set_display_name()), replace/disable ThunarVfsFileType + references in thunar_file_get_mode_string(), return TRUE from + thunar_file_is_executable() for .desktop files, rewrite + thunar_file_is_renamable(), thunar_file_get_custom_icon(), + thunar_file_set_custom_icon(), thunar_file_reload(), remove + thunar_file_cache_lookup_path(), thunar_file_list_to_path_list(), + thunar_file_get_path() and thunar_file_get_mime_info(). Make + thunar_file_get_info() return the GFileInfo. Rewrite + thunarx_file_info_get_vfs_info() which for now creates a new + ThunarVfsInfo and returns it. Callers now have to release the + ThunarVfsInfo later. Add GMount member to ThunarFile. + * thunar/thunar-folder.c: Make sure to set the job to NULL after + unref'ing it. Otherwise thunar_folder_get_loading() will always + return TRUE and the watch cursor won't disappear. + * thunar/thunar-gio-extensions.{c,h}: Add new functions + g_file_query_key_file() and g_file_write_key_file(). Also add + g_file_get_location() which returns a path for local files and an + URI for the rest, and g_mount_is_same_drive() which checks whether + two GMounts belong to the same GDrive. + * thunar/thunar-icon-factory.c, thunar/thunar-renamer-model.c, + thunar/thunar-thumbnail-generator.{c,h}: Migrate to the new + thunarx_file_info_get_vfs_info() function. + * thunar/thunar-list-model.c: Make sure not to crash when trying to + compare two ThunarFile of which at least one has no GFileInfo. + * thunar/thunar-metafile.{c,h}: Remove thunar-vfs.h include. + * thunar/thunar-progress-dialog.{c,h}: Use ThunarJob instead of ExoJob + whenever it is appropriate. Remove thunar-vfs.h include. + * thunar/thunar-window.c: Rewrite + thunar_window_current_directory_destroy() so that it simply searches + for the first parent directory that still exists and falls back to + $HOME otherwise. + +2009-05-07 Jannis Pohlmann <jannis@xfce.org> + + * Makefile.am, thunar/thunar-misc-jobs.{c,h}: Add new file for + miscellaneous jobs. Add new job + thunar_misc_jobs_load_template_files() which recursively loads all + template files/directories as ThunarFile objects from + G_USER_DIRECTORY_TEMPLATES. + * thunar/thunar-gio-extensions.{c,h}: Add new method + g_file_new_for_user_special_dir() which creates a GFile for a + GUserDirectory and falls back to $HOME (so it's ignored later) if + the special dir is not set. + * thunar/thunar-create-dialog.h, thunar/thunar-standard-view.c, + thunar/thunar-templates-action.c: Migrate ThunarTemplatesAction away + from ThunarVFS. Use ThunarFile instead of ThunarVfsInfo for the + "create-template" signal. Load the templates menu using + thunar_misc_jobs_load_template_files(). + +2009-05-05 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in: Depend on exo-0.3.101svn-r29926 for ExoJob. + * thunar/thunar-application.c, thunar/thunar-deep-count-job.{c,h}, + thunar/thunar-folder.c, thunar/thunar-io-jobs-util.c, + thunar/thunar-io-jobs.c, thunar/thunar-io-scan-directory.{c,h}, + thunar/thunar-job.{c,h}, thunar/thunar-permissions-chooser.c, + thunar/thunar-progress-dialog.{c,h}, thunar/thunar-simple-job.{c,h}, + thunar/thunar-size-label.c, thunar/thunar-transfer-job.c: Implement + ThunarJob based on ExoJob. Update a lot of classes to use the + equivalent ExoJob functions instead the ones from ThunarJob which + have been removed. + +2009-05-01 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}, thnuar/thunar-standard-view.c, + thunar/thunar-util.{c,h}: Do it right this time by using guint64 and + GFileInfo instead of the ThunarVfsMimeInfo to determine the + access/changed/modified time. Update + thunar_util_humanize_file_time() to reflect this. + * thunar/thunar-standard-view.c: Rewrite tsv_reload_directory() + based on GFileMonitor. + * thunar/thunar-launcher.c: Use GVolumeMonitor/GVolume for the volume + send-to actions. Another class free of ThunarVFS. + +2009-04-30 Jannis Pohlmann <jannis@xfce.org> + + * thunar/*.c: Remove all occurances of GLIB_CHECK_VERSION() and + GTK_CHECK_VERSION() because we depend on much more recent GLib/GTK+ + versions now anyway. + * thunar/thnuar-file.{c,h}, thunar/thunar-util.{c,h}: Actually, time_t + instead of guint64 is the correct type to use (fixes the previous + commit). + * thunar/thunar-window.c: Implement thunar_window_directory_destroy() + around g_file_find_enclosing_mount(). I'm not 100% happy with this + implementation but it'll do for now. Open the home directory if the + new directory cannot be determined. + +2009-04-30 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-util.{c,h}: Replace ThunarVfsFileTime with guint64. + +2009-04-30 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}, thunar/thunar-properties-dialog.c: + Re-implement thunar_file_get_volume() around + g_file_find_enclosing_mount(). Ideally this would be asynchronous + but for now it'll stay the old way. Remove the + ThunarVfsVolumeManager member from the properties dialog. We only + need thunar_file_get_volume() here now. + +2009-04-30 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-application.c: Replace "hal-udi" with + G_VOLUME_IDENTIFIER_KIND_HAL_UDI. + * thunar/thunar-gio-extensions.c: Change g_volume_is_removable() so + that it returns TRUE for almost all volumes. I feel that something is + very wrong in GHalVolumeManager ... + * thunar/thunar-location-entry.c: Replace ThunarVfsVolume with + GVolume. Mount+open launcher entry items asynchronously when + activated. + +2009-04-29 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-tree-model.c, thunar/thunar-tree-view.c: Rewrite the + volume management code based on GVolumeMonitor/GVolume. This code + still has quite a few problems with trying to mount several times in + a row and mount+open doesn't seem to work. + +2009-04-29 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-shortcuts-view.c: Avoid segfaults due to an invalid + GtkTreeSelection being used in thunar_shortcuts_view_open_selection() + and thunar_shortcuts_view_open_selection_in_new_window(). This can + happen when the shortcuts view is essentially being destroyed but a + reference to it is still being kept for the mount/unmount/eject + handler. Increase the reference counter before passing the view to + asynchronous mount/unmount/eject functions and release the reference + in the handler. + +2009-04-29 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-shortcuts-model.c: In thunar_shortcuts_model_init() + don't increase the reference counter on the volumes, otherwise we'd + leak them here. + +2009-04-29 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-gio-extensions.{c,h}: Add new function + g_volume_is_present() which checks whether the GDrive of a volume + has media or not. + * thunar/thunar-shortcuts-icon-renderer.c: Use GVolume instead of + ThunarVfsVolume and create the icon by loading a GtkIconInfo based + on the volume GIcon in thunar_shortcuts_renderer_render(). + * thunar/thunar-shortcuts-model.{c,h}: Use GVolumeMonitor and + GVolume/GMount instead of ThunarVfsVolumeManager/ThunarVfsVolume + everywhere. + * thunar/thunar-shortcuts-view.c: Rewrite the mount/eject/unmount code + to use GVolume/GMount. Need to review this again to make sure it + works. + * thunar/thunar-window.c: Re-implement the mount-pre-unmount signal + handler by using GVolumeMonitor/GMount. + +2009-04-28 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-io-jobs.c, thunar/thunar-io-scan-directory.c: Improve + error handling. Use thunar_file_list_free() instead of iterating over + the ThunarFile list manually. Make sure to release the + GFileEnumerator in thunar_io_scan_directory(), otherwise unmounting + volumes fails due to open file descriptors. + * thunar/thunar-job.c: Cancel jobs in thunar_job_finalize() before + destroying the GCancellable. + +2009-04-28 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Make the ThunarFile cache somewhat + thread-safe. + * thunar/thunar-gio-extensions.{c,h}: Add new functions + g_volume_is_removable() and g_volume_is_mounted(). + +2009-04-27 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-io-jobs-util.{c,h}: Add missing files. + +2009-04-27 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-preferences-dialog.c: Always assume we have volume + management. Remove the ThunarVfsVolumeManager reference here. + +2009-04-27 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-application.c: Use GVolumeMonitor instead of + ThunarVfsVolumeManager. Connect to the "drive-connected", + "drive-disconnected" and "drive-eject-button" signals and determine + the device UDIs using g_drive_get_identifier(). Rename + thunar_application_volman_device_added(), + thunar_application_volman_device_removed(), + thunar_application_volman_device_eject() to + thunar_application_drive_connected(), + thunar_application_drive_disconnected() and + thunar_application_drive_eject(). ThunarApplication is now + ThunarVFS-free! + * thunar/thunar-io-scan-directory.c: Avoid segfault when cancelling the + job and trying to free the error. + +2009-04-24 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-tree-view.c: Add missing include statement for + thunar-job.h. + +2009-04-24 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-dialogs.c, thunar/thunar-progress-dialog.{c,h}, + thunar/thunar-standard-view.c thunar/thunar-tree-view.c: Remove + all references to ThunarVfsJob/ThunarVfsJobResponse from comments and + source code. + * thunar/thunar-io-jobs.c: Fix overwriting of a GError when cancelling + the list_directory job. + +2009-04-24 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Implement thunar_file_get_group(), + thunar_file_get_user() and thunar_file_get_emblem_names() based on + GFile/GFileInfo. + * thunar/thunar-folder.c, thunar/thunar-io-jobs.{c,h}, + thunar/thunar-job.{c,h}: Add new "files-ready" signal to ThunarJob + which is emitted when a list of ThunarFiles is ready. Also add a new + function called thunar_job_files_ready() which emits the signal. + Implement a new job thunar_io_jobs_list_directory() as an equivalent + to thunar_vfs_listdir(), using the new "files-ready" signal. Update + ThunarJob to use "files-ready" instead of "infos-ready". For the + first time in a while you can open the trash again without crashing + Thunar. + +2009-04-24 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-folder.c: Add "corresponding-file" property for the + ThunarFile member of ThunarFolder. Monitor folders using + GFileMonitor instead of ThunarVfsMonitor. + +2009-04-24 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-enum-types.{c,h}, thunar/thunar-file.h: Move + ThunarFileMode into the enum types file. Add THUNAR_TYPE_FILE_MODE + macro and thunar_file_mode_get_type() function which registers a + flags type for file modes. + * thunar/thunar-io-jobs.{c,h}: Add new jobs + thunar_io_jobs_change_group() and thunar_io_jobs_change_mode(). + * thunar/thunar-permissions-chooser.c: Migrate the permissions chooser + to the new jobs. + +2009-04-24 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-application, thunar/thunar-io-jobs.{c,h}, + thunar/thunar-job.{c,h}, thunar/thunar-transfer-job.c: Re-implement + thunar_application_restore_files() based on a new job called + thunar_io_jobs_restore_files(). Modify ThunarTransferJob so that it + checks whether the parent directory of the original path exists and + otherwise tries to create it (with user interaction). Add new + function thunar_job_ask_create() to ThunarJob. ThunarApplication is + now almost ThunarVFS free. + +2009-04-23 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-dialogs.c: Use more fine-grained labels for files, + directories and links in thunar_dialogs_show_job_ask_replace(). + +2009-04-23 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-application.c, thunar/thunar-job.{c,h}, + thunar/thunar-io-jobs.c, thunar/thunar-transfer-job.c, + thunar/thunar-standard-view.c, thunar/thunar-tree-view.c: Implement + and connect to the "new-files" signal again. Update + ThunarStandardView and ThunarTreeView to use a GFile list for the + new_files_closure. + +2009-04-23 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-application.{c,h}, thunar/thunar-dbus-service.c, + thunar/thunar-io-jobs.{c,h},: Add new job + thunar_io_jobs_trash_files() and a new function + thunar_application_trash() which are used in + thunar_dbus_service_move_to_trash(), thunar_application_move_into() + and thunar_application_unlink() to move files into the trash. + * thunar/thunar-standard-view.c: Use GFiles for the drag file list. + +2009-04-23 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-application.h: Fix thunar_appliation_link_into() + declaration and rename a few parameters. + +2009-04-23 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-io-jobs-util.{c,h}: Add new files + for I/O job utility functions. Right now there's only one new + function called thunar_io_jobs_util_next_duplicate_file() which + generates alternative "copy of X", "another copy of X", + "third copy of X" and "nth copy of X" #GFiles for an input #GFile. + It also works for symbolic links. + * thunar/thunar-application.{c,h}, thunar/thunar-dnd.c, + thunar/thunar-io-jobs.{c,h}, thunar/thunar-launcher.c, + thunar-standard-view.c: Add new + job thunar_io_jobs_link_files() and use it in + thunar_application_link_into(). Disable + thunar_application_restore_files() for now so that we can replace + thunar_application_collect_and_launch() and + thunar_application_launch() with the implementations based on GIO. + Enable creating links in thunar-dnd.c again. Update ThunarLauncher + and ThunarStandardView to reflect the API changes in + ThunarApplication. + * thunar/thunar-dialogs.c: In thunar_dialogs_show_job_ask_replace(), + use different labels for target symlinks than for normal files to + make clear that we're only replacing the symlinks, not the files + they point to. + * thunar/thunar-permissions-chooser.c: Make sure the array index + is never out of bounds when iterating over the combos. + * thunar/thunar-transfer-job.{c,h}: Improve the copy/move algorithm so + that it resembles the old behaviour, creates "copy of X" files when + copying/linking files into the same directory, handles directory + merges properly and is more readable. + +2009-04-23 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-transfer-job.{c,h}: Implement + ThunarTransferJob as an equivalent to ThunarVfsTransferJob. The code + is very similar except that the error handling is a bit different + and all basic operations (non-recursive copy/move) is done based on + GFile and GFileInfo. Copying a file into the same directory + currently does not work the way it did before (new file 'copy of + "%s"' was created). This will be fixed soon. + * thunar/thunar-application.{c,h}: Add new function + thunar_application_collect_and_launch_job() as an alternative to + thunar_application_collect_and_launch() but based on GFile and + JobLauncher. Implement thunar_application_move_into(), + thunar_application_copy_into() and thunar_application_copy_to() + based on ThunarTransferJob and GFile instead of ThunarVfsTransferJob. + * thunar/thunar-clipboard-manager.{c,h}, thunar/thunar-dialogs.{c,h}, + thunar/thunar-dnd.c, thunar/thunar-dbus-service.c, + thunar/thunar-launcher.c, thunar/thunar-location-button.c, + thunar/thunar-location-buttons.c, thunar/thunar-progress-dialog.c, + thunar/thunar-shortcuts-view.c, thunar/thunar-standard-view.c, + thunar/thunar-tree-view.c: Update to new API of + ThunarClipboardManager, ThunarApplication and ThunarJob. Replace + *a lot* of ThunarVFS references with code based on GIO. + * thunar/thunar-file.{c,h}: Re-implement thunar_file_accepts_drop() + based on a GFile input list. Add new function + thunar_file_can_be_trashed(). + * thunar/thunar-io-jobs.{c,h}: Add new jobs + thunar_io_jobs_move_files() and thunar_io_jobs_copy_files(). + * thunar/thunar-job.{c,h}: Add "ask-replace" signal and public + function thunar_job_ask_replace(), mainly for ThunarTransferJob. + * thunar/thunar-marshal.list: Add new marshal function + _thunar_marshal_FLAGS__OBJECT_OBJECT(). + +2009-04-22 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-io-scan-directory.{c,h}: Port + _thunar_vfs_info_scan_directory() to GIO and rename it to + thunar_io_scan_directory(). + * thunar/thunar-application.c, thunar/thunar-io-jobs.{c,h}: Implement + thunar_io_jobs_unlink_files() as an equivalent to + thunar_vfs_jobs_unlink_files(). Use it in unlink_stub() and modify + thunar_application_unlink_files() and + hunar_application_empty_trash() to use + thunar_application_job_launch() and GFile lists. + * thunar/thunar-gio-extensions.{c,h}: Add g_file_list_prepend(). + * thunar/thunar-job.c: Don't treat cancellation as an error for now. + * thunar/thunar-simple-job.c: Use g_clear_error() instead of + g_error_free() in thunar_simple_job_execute(). + +2009-04-21 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-application.c, thunar/thunar-io-jobs.{c,h}, + thunar/thunar-location-buttons.c, thunar/thunar-standard-view.c, + thunar/thunar-tree-view.c: Add new simple job + thunar_io_jobs_make_directories(). Rename all I/O job functions from + thunar_io_job_*() to thunar_io_jobs*(). Use the make directories job + in thunar_application_mkdir() and modify mkdir_stub() according to + this. Pass a GFile list to thunar_application_mkdir() in + ThunarLocationButtons, ThunarStandardView and ThunarTreeView. + +2009-04-21 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-io-jobs.{c,h}, + thunar/thunar-simple.job.{c,h}: Add ThunarSimpleJob class which is + equivalent to ThunarVfsSimpleJob. Add the first simple job by + implementing thunar_io_job_create_files() as an equivalent to + thunar_vfs_create_files(). The "new-files" signal is not implemented + yet because it would break the new_files_closure. + * thunar/thunar-application.c: Add JobLauncher function pointer type + as an equivalent to Launcher. Add thunar_application_launch_job() as + an equivalent to thunar_application_launch() based on ThunarJob + instead of ThunarVfsJob. Modify creat_stub() according to this. Use + thunar_application_launch_job() in thunar_application_creat(). + * thunar/thunar-job.{c,h}: Implement thunar_job_ask_skip(). + * thunar/thunar-standard-view.c: Pass a GFile list instaed of a + ThunarVfsPath list to thunar_application_creat(). + +2009-04-21 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-enum-types.c: Remove vfs_ from + thunar_vfs_job_response_get_type(). + * thunar/thunar-gio-extensions.c: Include exo.h for the I_() macro. + * thunar/thunar-job.{c,h}: Add functions thunar_job_ask_overwrite(), + thunar_job_info_message(), thunar_job_percent(), + thunar_job_set_total_files() and thunar_job_processing_file(). Add + signals "ask", "info-message" and "percent". + * thunar/thunar-progress-dialog.{c,h}: Make ThunarProgressDialog work + with both, ThunarVfsJob and ThunarJob by using a G_TYPE_OBJECT + property and gpointer parameters. + +2009-04-21 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-deep-count-job.c: Improve the error handling code in + thunar_deep_count_job_execute(). + * thunar/thunar-gio-extensions.{c,h}: Add G_TYPE_FILE_LIST macro and + g_file_list_get_type() for a boxed GFile list type. Fix + g_file_list_copy() to actually return the list copy and not the + original. Don't set the original to NULL before iterating over it. + +2009-04-20 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-window.c: Fix runtime error due to an NULL path being + passed to g_file_new_for_path() in + thunar_window_setup_user_dir_menu_entries(). + +2009-04-20 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-chooser-dialog.c, thunar/thunar-deep-count-job.c, + thunar/thunar-job.c, thunar/thunar-preferences.c, + thunar/thunar-shortcuts-model.c, thunar/thunar-size-label.c: Fix + compiler warnings and errors. + +2009-04-20 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-deep-count-job.{c,h}: Add new class + for computing the total size of a file/directory recursively while + also counting the total number of files and directories. This + implementation is almost equivalent to ThunarVfsDeepCountJob except + that it is an implementation of ThunarJob and uses GIOScheduler for + the asynchronous operation. + * thunar/thunar-enum-types.h: Add missing public declaration of + thunar_job_response_get_type(). + * thunar/thunar-job.{c,h}: Add new functions + thunar_job_get_cancellable() and thunar_job_set_error_if_cancelled(). + Make thunar_job_emit() public so that it can be used in subclasses. + Don't try to emit signals in thunar_job_finished() and + thunar_job_error() using GIOScheduler because they are only emitted + in thunar_job_async_ready() which is called from the GUI thread. + * thunar/thunar-size-label.c: Drop all ThunarVFS references by + replacing ThunarVfsDeepCountJob with ThunarDeepCountJob. Yay, it + works! + +2009-04-20 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-enum-types.{c,h}, + thunar/thunar-job.{c,h}, thunar/thunar-marshal.list: Add abstract + class ThunarJob which is going to be an equivalent to ThunarVfsJob. + The main difference is that ThunarJob uses GIOScheduler to handle + the asynchronous execution of the job instead of managing worker + threads on its own. It's not finished yet though. Add + ThunarJobResponse enum type and new marshal functions for job + signals. + +2009-04-19 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-location-button.c: Use g_file_list_to_string() instead + of thunar_vfs_path_list_to_string() in + thunar_location_button_drag_data_get(). + 2009-04-18 Stephan Arts <stephan@xfce.org> * == Released 1.0.1 == @@ -11,6 +900,358 @@ Don't pretend gconftool exists (if it exists it is just a symlink), instead look for gconftool-2 - Patch by Mike Massonnet +2009-04-17 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-clipboard-manager.c: Remove GTK+ 2.6 check. + * thunar/thunar-dbus-service.c: Replace ThunarVfsPath with GFile in + thunar_dbus_service_connect_trash_bin() and + thunar_dbus_service_display_folder_and_select(). + +2009-04-15 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-standard-view.c: Use GFile instead of ThunarVfsPath in + thunar_standard_view_drag_drop(). + +2009-04-15 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-preferences.c, thunar/thunar-sendto-model.c, + thunar/thunar-shortcuts-model.c: Check whether the created file + monitor is != NULL before connecting to its "changed" signal. + +2009-04-15 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-gio-extensions.c: Add new functions + g_file_new_for_desktop() and g_file_is_desktop(). + * thunar/thunar-shortcuts-model.c: Monitor ~/.gtk-bookmarks using + GFileMOnitor instead of ThunarVfsMonitor. Replace all ThunarVfsPath + references with equivalent code based on GFile. + +2009-04-14 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-preferences.c: Monitor thunarrc with GFileMonitor + instead of ThunarVfsMonitor. All ThunarVFS references removed from + the class. + +2009-04-13 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-sendto-model.c: Monitor sendto/ directories with + GFileMonitor instead of ThunarVfsMonitor. + +2009-04-13 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-icon-factory.c: Replace ThunarVfsFileTime with + guint64. + * thunar/thunar-path-entry.c, thunar/thunar-util.{c,h}: Replace + thunar_vfs_expand_filename() with thunar_util_expand_filename(). + * thunar/thunar-renamer-model.c: Use GFile instead of ThunarVfsPath in + trm_same_directory(). + +2009-04-13 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-permissions-chooser.c: Rename all occurances of + ThunarVfsFileMode to ThunarFileMode. + +2009-04-13 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-renamer-dialog.c: Use a GFile instead of a + ThunarVfsPath list in thunar_renamer_dialog_drag_data_received(). + +2009-04-13 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-list-model.c: Remove all ThunarVFS references left. + +2009-04-13 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-chooser-dialog.c: Expand the recommended/other rows + properly after initializing the ThunarChooserModel. + +2009-04-13 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in: Bump exo dependency for the "gicon" property of + ExoCellRendererIcon. + * thunar/main.c: Set the desktop environment for GDesktopAppInfo if + gio-unix is available. + * thunar/thunar-chooser-dialog.c, thunar-chooser-model.{c,h}: Replace + all ThunarVfsMime* references with code based on GAppInfo. Use the + new "gicon" property of ExoCellRendererIcon. Only regression is that + there is no way to check whether a GAppInfo was created by the user + in GIO. + +2009-04-13 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-properties-dialog.c: Remove ThunarVfsMimeInfo and use + a content type string in thunar_properties_dialog_update(). + +2009-04-13 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-create-dialog.{c,h}: Replace the ThunarVfsMimeInfo + member/property of ThunarCreateDialog with a content type string + member/property. Rename thunar_create_dialog_{get,set}_mime_info() + to thunar_create_dialog_{get,set}_content_type(). + * thunar/thunar-location-buttons.c, thunar/thunar-standard-view.c, + thunar/thunar-tree-view.c: Update calls to + thunar_show_create_dialog() to use a content type string rather than + ThunarVfsMimeInfo. + +2009-04-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-chooser-button.c: Don't leak GAppInfos in + thunar_chooser_button_pressed(). + +2009-04-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-chooser-button.c: Migrate ThunarChooserButton from + ThunarVFS to GIO, using GAppInfo instead if ThunarVfsMime* classes. + +2009-04-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Use GFileMonitor instead of + ThunarVfsMonitor for monitoring a ThunarFile. Rewrite + thunar_file_monitor(), remove thunar_file_watch_handle_quark and + thunar_file_watch_free(). Add GFileMonitor member to ThunarFile. + Make thunar_file_info_get_name() use thunar_file_get_basename(). + * thunar/thunar-gio-extensions.c: Don't escape URIs when appending + them to the string in g_file_list_to_string(). This seems to break + copy&paste. + +2009-04-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-application.c, thunar/thunar-file.{c,h}, + thunar/thunar-list-model.c, thunar/thunar-properties-dialog.c: + Make thunar_file_get_original_path() and + thunar_file_get_symlink_target() to return const strings. Update + ThunarApplication, ThunarListModel and ThunarPropertiesDialog to + reflect these changes. Implement thunar_file_is_trashed(), + thunar_file_is_desktop_file() and thunar_file_get_display_name() + based on GIO. Remove thunar_file_read_link(). + +2009-04-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Re-implement thunar_file_is_local(), + thunar_file_is_ancestor(), thunar_file_is_executable(), + thunar_file_is_readable(), thunar_file_is_writable(), + thunar_file_is_hidden(), thunar_file_is_home(), + thunar_file_is_regular() and thunar_file_dup_uri() based on GIO. + +2009-04-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Add GFileInfo filesystem info member to + ThunarFile. Initialize it in thunar_file_load(), otherwise make sure + it's set to NULL. Make thunar_file_get_default_handler(), + thunar_file_get_kind(), thunar_file_get_mode(), + thunar_file_get_free_space(), thunar_file_is_directory() real + functions and make them use GFile/GFileInfo. + * thunar/thunar-list-model.c, thunar/thunar-properties-dialog.c: Use + guint64 instead of ThunarVfsFileSize. Use g_file_size_humanize() + instead of thunar_vfs_humanize_size(). + +2009-04-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-clipboard-manager.c: Use a GFile list and + thunar_file_list_to_g_file_list() instead of the ThunarVFS + equivalents in thunar_clipboard_manager_get_callback(). + +2009-04-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Add new or re-implement the functions or + macros thunar_file_get_content_type(), + thunar_file_get_symlink_target(), thunar_file_get_basename(), + thunar_file_is_symlink(), thunar_file_get_size() based on GIO. + * thunar/thunar-list-model.c: Re-implement + thunar_list_model_get_value() based on the new/changed functions. + Same goes for sort_by_file_name(), sort_by_mime_type(), + sort_by_type() and thunar_list_model_get_statusbar_text() which are + almost ThunarVFS-free now. + +2009-04-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-path-entry.c: Re-implement + thunar_path_entry_drag_data_get(), thunar_path_entry_changed() and + thunar_path_entry_set_current_file() with GFile. file:// URI + completion doesn't work yet. + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c, thunar/thunar-metafile.{c,h}: Migrate + ThunarMetadata to GIO. Update ThunarFile to pass the GFile instead + of ThunarVfsPath to thunar_metafile_fetch() and + thunar_metafile_store(). + * thunar/thunar-tree-model.c: Re-implement thunar_tree_model_init() + based on GFile. Unfortunately this breaks the trash (again) and thus + the whole tree view. + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-trash-action.c: Replace all ThunarVfsPath references + with GFile. + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Add assertion to thunar_file_load() to see for + which files it fails rather than to see that in some random function + later. + * thunar/thunar-window.c: Re-implement thunar_window_open_trash() + based on GFile. + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Fix segfault in thunar_file_get(). + * thunar/thunar-window.c: Re-implement + thunar_window_open_user_folder() based on GFile. + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Add new function thunar_file_get(GFile*). + Internally this still uses thunar_file_load() and can thus block the + UI. For the sake of a smoother transition, asynchronous loading will + be implemented at a later stage. + * thunar/thunar-window.c: Re-implement thunar_window_open_home() based + on thunar_file_get(). + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.c: Tweak thunar_file_is_desktop() a little bit. + * thunar/thunar-window.c: Re-implement + thunar_window_setup_user_dir_menu_entries() based on GFile. Remove + the special code for GLib < 2.14. + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Change thunar_file_get_custom_icon() to + return a newly allocated string instead of a const one. Re-implement + thunar_file_get_icon_name() based on GFileInfo and GThemedIcon. It + now returns a string that has to be freed. + * thunar/thunar-icon-factory.c, thunar/thunar-location-button.c, + thunar/thunar-properties-dialog.c: Avoid leaks by freeing the + strings returned by thunar_file_get_custom_icon() and + thunar_file_get_icon_name(). + * thunar/thunar-launcher.c, thunar/thunar-sendto-model.c: Remove debug + statements. + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in, thunar/Makefile.am: Add optional dependency on + gio-unix-2.0. + * thunar/thunar-launcher.c, thunar/thunar-sendto-model.c: Load sendto + handlers using GDesktopAppInfo (only supported on UNIX for whatever + reason). Update ThunarLauncher to use GAppInfo for handlers + retrieved from ThunarSendtoModel. Unfortunately, GIO doesn't support + checking whether a GAppInfo supports more than one file argument. + There's also no way to find out what MIME types a GAppInfo supports + which forces us to drop a few nice sanity checks in + thunar_sendto_model_get_matching(). + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Add new macro + thunar_file_get_default_handler() for querying the default GAppInfo + to handle a ThunarFile. Use it in thunar_file_launch(). Fix pointer + corruption issue thunar_file_reload(). Re-implement + thunar_file_list_get_applications() based on GFileInfo/GAppInfo. Add + new method thunar_file_list_to_g_file_list() as the GFile equivalent + to thunar_file_list_to_path_list(). Add new macro + thunar_file_get_file() to get the GFile for a ThunarFile. + * thunar/thunar-gio-extensions.{c,h}: Add new function + g_file_list_append() to append a GFile to a GFile list. + * thunar/thunar-launcher.c: Replace most occurances of + ThunarVfsMimeHandler with GAppInfo based on the changes made to + ThunarFile. This currently breaks ThunarSendtoModel which will be + worked on next. + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Re-implement thunar_file_get_size_string() + based on GFileInfo and the new function g_file_size_humanize(). + Re-implement thunar_file_get_deletion_date(), + thunar_file_get_original_path() as well. They currently fail because + there are no GFileInfos for objects in the Thunar trash at the + moment. Also rewrite thunar_file_is_desktop() and make sure to + reload the GFileInfo in thunar_file_reload(). + * thunar/thunar-gio-extensions.{c,h}: Add new method + g_file_size_humanize() to create nice file size labels. + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Re-implement thunar_file_get_parent(), + thunar_file_launch(), thunar_file_is_root() and + thunar_file_has_parent() based on GFile/GFileInfo/GAppInfo. + * thunar/thunar-gio-extensions.c: Fix problem in g_file_is_root(). + +2009-04-11 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Replace all occurances of + ThunarVfsFileMode with ThunarFileMode, which is the same, just moved + from ThunarVFS into thunar-file.h. Re-implement + thunar_file_info_get_name(), thunar_file_info_get_uri(), + thunar_file_info_get_parent(), thunar_file_info_get_uri_scheme(), + thunar_file_info_get_mime_type() and + thunar_file_info_has_mime_type() based on GFile/GFileInfo. + +2009-04-10 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-file.{c,h}, + thunar/thunar-list-model.c, thunar/thunar-permissions-chooser.c, + thunar/thunar-user.{c,h}: Move ThunarVfsUserManager, ThunarVfsUser + and ThunarVfsGroup into Thunar, renaming them to ThunarUserManager, + ThunarUser and ThunarGroup. Update the Thunar code to reflect this + change. + +2009-04-10 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-file.{c,h}: Use GFile in thunar_file_atexit_foreach(). + When finalizing, creating or loading a ThunarFile, check whether the + GFileInfo is NULL before unref'ing it. Use the GFile member instead + of the ThunarVfsPath in thunar_file_rename(). Tweak + thunar_file_accepts_drop() so that it converts the ThunarVfsPath + elements of the path list into GFile objects for everything. This + will make the transition away from ThunarVfsPath easier later. + Rewrite thunar_file_is_trashed() so that it uses + g_file_is_trashed(). + * thunar/thunar-gio-extensions.{c,h}: Add new function + g_file_is_trashed() which checks whether a GFile resides in the + trash. + * thunar/thunar-launcher.c, thunar/thunar-location-buttons.c, + thunar/thunar-properties-dialog.c, thunar/thunar-shortcuts-view.c, + thunar/thunar-standard-view.c, thunar/thunar-tree-model.c, + thunar/thunar-tree-view.c, thunar/thunar-window.c: Include + thunar-gio-extensions.h to compile with thunar_file_is_trashed(). + +2009-04-10 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-dnd.c, thunar/thunar-standard-view.c, + thunar/thunar-tree-view.c, thunar/thunar-window.c: Use + thunar_file_cache_lookup_path() instead of + thunar_file_cache_lookup(). + * thunar/thunar-file.{c,h}: Add new function thunar_file_load() for + loading the GFileInfo of a ThunarFile synchronously. Use it in + thunar_file_get_for_info() to load GIO data for a ThunarFile in + addition to ThunarVFS information. Use GFile for the keys of the + file cache and change the function signature of + thunar_file_cache_lookup(). Add thunar_file_cache_lookup_path() for + a smoother transition. + +2009-04-10 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-gio-extensions.c: Remove unused variable in + g_file_list_new_from_string(). + +2009-04-10 Jannis Pohlmann <jannis@xfce.org> + + * thunar/Makefile.am, thunar/thunar-gio-extensions.{c,h}: Add a set of + functions extending the GIO API, like g_file_new_for_home(), + g_file_list_new_from_string(), g_file_list_to_string() and more. + +2009-04-10 Jannis Pohlmann <jannis@xfce.org> + + * AUTHORS: Put my name in. Yeah, yeah ... + * configure.in.in, thunar/Makefile.am, thunarx/Makefile.am: Add + dependency on GIO. Bump required GTK+/GLib version to 2.14/2.16. + +2009-04-09 Jannis Pohlmann <jannis@xfce.org> + + * README: Add information about the purpose of this branch and + the thesis. + 2009-04-08 Jannis Pohlmann <jannis@xfce.org> * configure.in.in, docs/manual/gl/images/: Fix broken build due diff --git a/ChangeLog.pre-gio b/ChangeLog.pre-gio new file mode 100644 index 000000000..adc970e9a --- /dev/null +++ b/ChangeLog.pre-gio @@ -0,0 +1,7500 @@ +2009-04-18 Stephan Arts <stephan@xfce.org> + + * == Released 1.0.1 == + * configure.in.in: Bump version number + * NEWS: Update NEWS for the release + * plugins/thunar-wallpaper/twp-provider.c(twp_action_set_wallpaper): + Escape spaces in filename (bug #5056) and set style auto (bug #5057) - + Patch by Mike Massonnet + * plugins/thunar-wallpaper/twp-provider.c(twp_action_set_wallpaper), + plugins/thunar-wallpaper/twp-provider.c(check_cli_tools): + Don't pretend gconftool exists (if it exists it is just a symlink), + instead look for gconftool-2 - Patch by Mike Massonnet + +2009-04-08 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in, docs/manual/gl/images/: Fix broken build due + to incomplete integration of the Galician manual translations. + +2009-03-12 Jannis Pohlmann <jannis@xfce.org> + + * thunar-vfs/thunar-vfs-io-jobs.c: Apply umask properly when + creating files/directories. Patch by Giovanni Bechis (bug + #3532). + +2009-02-24 Stephan Arts <stephan@xfce.org> + + * == Released 1.0.0 == + * configure.in.in: Bump version number and dependency versions + * NEWS: Update NEWS for the release + +2009-02-04 Jannis Pohlmann <jannis@xfce.org> + + * thunar-vfs/thunar-vfs-font-thumbnailer-1.desktop.in: Use + Type=X-Thumbnailer instead of Type=X-XFCE-Thumbnailer and + X-Thumbnailer-Exec instead of Exec (bug #4821). + +2009-01-25 Nick Schermer <nick@xfce.org> + + * thunar/thunar-path-entry.c: Fix crash when entering the same + hidden directory twice in the location entry (bug #4847). + +2009-01-25 Jannis Pohlmann <jannis@xfce.org> + + * == Released 0.9.99.1 == + * NEWS: Update NEWS for the release. + * configure.in.in: Bump version number. + +2009-01-14 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in: Add the 'svn' version tag again. + +2009-01-12 Stephan Arts <stephan@xfce.org> + + * === Release 0.9.93 === + * configure.in.in: Bump version number + +2009-01-11 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in: Add missing docs subdirectories. + +2009-01-10 Jannis Pohlmann <jannis@xfce.org> + + * NEWS: Update NEWS for the upcoming 0.9.93 release. + +2009-01-02 Nick Schermer <nick@xfce.org> + + * thunar/thunar-dialogs.c, thunar/main.c, configure.in.in: + Update copyright to 2009. + +2008-12-25 Nick Schermer <nick@xfce.org> + + * NEWS: Update. + +2008-12-08 Nick Schermer <nick@xfce.org> + + * thunar/thunar-standard-view.c: Go back and forward using the + 8th and 9th button on the mouse. Merge this with the scroll + left and right event handling. Bug #4687. + +2008-12-07 Nick Schermer <nick@xfce.org> + + * thunar/thunar-launcher.c, thunar/thunar-properties-dialog.c, + thunar/thunar-path-entry.c, thunar/thunar-application.c, + thunar/thunar-window.c, thunar-vfs/thunar-vfs-thumb.c, + thunar-vfs/thunar-vfs-private.c, thunar-vfs/thunar-vfs-path.c, + thunar-vfs/thunar-vfs-mime-database.c, + plugins/thunar-uca/thunar-uca-model.c: Fix compilation with + -Wformat-security. + +2008-12-04 Jannis Pohlmann <jannis@xfce.org> + + * Thunar.desktop.in.in: Change Name string to "Thunar File Manager" so + that people don't have to guess what Thunar is good for. + +2008-12-03 Nick Schermer <nick@xfce.org> + + * thunar/thunar-renamer-dialog.c, thunar/thunar-renamer-model.c, + thunar/thunar-renamer-model.h: Implement reorder, rubber banding + and position dnd in the renamer dialog. Bug #3325. + +2008-12-02 Nick Schermer <nick@xfce.org> + + * thunar/thunar-shortcuts-view.c, thunar/thunar-tree-view.c: + Use get_folder_actions for the provider actions in the sidepane + since it makes more sence. + +2008-12-02 Nick Schermer <nick@xfce.org> + + * thunar/thunar-renamer-dialog.c, thunar/thunar-shortcuts-view.c, + thunar/thunar-location-button.c, thunar/thunar-standard-view.c, + thunar/thunar-clipboard-manager.c, thunar/thunar-tree-view.c: + Use gdk_atom_intern_static_string() in the main program. + +2008-11-30 Nick Schermer <nick@xfce.org> + + * thunar/thunar-dialogs.c: Add function description. + +2008-11-30 Nick Schermer <nick@xfce.org> + + * thunar/thunar-dialogs.c, thunar/thunar-dialogs.h, + thunar/thunar-standard-view.c: Move the rename dialog to + thunar-dialog.c so we can share it with the treeview. + * thunar/thunar-tree-view.c: Add rename option to the tree pane. + +2008-11-30 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-history.c (thunar_history_set_current_directory): + Don't go back in the history anymore if the new directory is the + first one in the backward history as this results in unexpected + behavior (bug #4660). + +2008-11-30 Nick Schermer <nick@xfce.org> + + * thunar/thunar-tree-model.c: Fix a possible crash discovered by + Jannis. Also add some extra debug checks. + +2008-11-29 Nick Schermer <nick@xfce.org> + + * thunar/thunar-shortcuts-view.c, thunar/thunar-tree-view.c: + Use thunarx_menu_provider_get_file_actions() instead of + thunarx_menu_provider_get_folder_actions(). + +2008-11-29 Nick Schermer <nick@xfce.org> + + * thunar/thunar-tree-view.c: Implement menu providers in the + tree side pane too. + +2008-11-29 Nick Schermer <nick@xfce.org> + + * thunar/thunar-shortcuts-view.c: Implement menu providers in + the shortcuts menu. Bug #2740. + * thunar/thunar-shortcuts-icon-renderer.c: Make unmounted volumes + 50% translucent in the bookmarks and treeview, to give some + visualization whether the device is mounted or not. + +2008-11-29 Nick Schermer <nick@xfce.org> + + * thunar/thunar-standard-view.c, thunar/thunar-tree-view.c: + Don't respond to the predefined keybindings when the user + has set a custom accelerator for delete. The difference with + the previous patch is that Shift + Delete still counts as a valid + action, so when you set Ctrl + Delete as custom accelerator, + we don't respond to Delete, but Shift + Delete still works, + since you probably don't press that accidentally... The only + exception is Shift + Delete as custom accelerator for delete: + this will always result in a permanent delete. + +2008-11-29 Nick Schermer <nick@xfce.org> + + * thunar/thunar-tree-model.c, thunar/thunar-tree-model.h, + thunar/thunar-tree-view.c: Instead of unloading folders + when their ref count is zero, we schedule a tree cleanup when + a row is collapsed. The reason is simple: the reffing the + treeview does is weird which results in glitches when scrolling + a large tree. + Also added some extra debug code. + +2008-11-28 Nick Schermer <nick@xfce.org> + + * Revert pervious commit, not a good way to fix this. + +2008-11-28 Nick Schermer <nick@xfce.org> + + * thunar/thunar-standard-view.c, thunar/thunar-tree-view.c: Only + respond to the predefined key bindings for deleting files when + the user has not set a custom accelerator. Bug #4173. + +2008-11-28 Jannis Pohlmann <jannis@xfce.org> + + * Thunar.desktop.in.in: Use "Thunar" for Name. This fixes bug #4084. + +2008-11-28 Nick Schermer <nick@xfce.org> + + * docs/reference/thunarx/thunarx-docs.sgml: Update links to the + glib reference manual in the docs. Patch by Mike Massonnet. + Bug #4555. + +2008-11-27 Nick Schermer <nick@xfce.org> + + * thunar-vfs/thunar-vfs-mime-info.c: Fix crash when unreffing the + mime info. This happens here sometimes when unknown files were + found in /proc. + +2008-11-27 Nick Schermer <nick@xfce.org> + + * thunar-vfs/thunar-vfs-monitor.c: Implement a simpler version of + the /proc and /dev ignore test. + * thunar-vfs/thunar-vfs-monitor.c: Use a GSList for the handles + since we only walk forwards. + +2008-11-27 Nick Schermer <nick@xfce.org> + + * plugins/thunar-sbr/thunar-sbr-case-renamer.c: Apply patch from + Mathias Brodala to make the first character after a paranthesis + uppercase. Bug #3559. + +2008-11-27 Nick Schermer <nick@xfce.org> + + * plugins/thunar-uca/thunar-uca-chooser.c: Open a question dialog + before removing a custom action. Bug #3838. + * plugins/thunar-uca/thunar-uca-model.c: Return an empty string + when the name is not set instead of null, so the action always + has a valid name and gtk does not send a critical warning. + * po/*: Merge new strings. + +2008-11-27 Nick Schermer <nick@xfce.org> + + * thunar/thunar-preferences-dialog.c: Instead of using a transient + window, we do a fake-center-on-parent. So it looks like the + window belongs to the parent, but it is a standalone window. This + should fix the last part of bug #3586. + * thunar/thunar-window.c: Register the properties dialog with + thunar_application_take_window() so it will get a new + GtkWindowGroup. + +2008-11-27 Jannis Pohlmann <jannis@xfce.org> + + * configure.in.in, thunar-vfs/thunar-vfs-monitor.c: Add HAVE_LINUX + define to config.h and implement support for excluding certain base + paths (such as /dev and /proc) from being monitored. Gamin does the + same but only for dnotify and inotify, not for polling. + +2008-11-26 Nick Schermer <nick@xfce.org> + + * thunar/thunar-application.c: Create a new window group for + windows added with thunar_application_take_window() that don't have + a transient window. This will make different windows work + independant when a modal dialog is created. + +2008-11-26 Jannis Pohlmann <jannis@xfce.org> + + * thunar-vfs/thunar-vfs-monitor.c, thunar/thunar-tree-model.{c,h}, + thunar/thunar-tree-view.c: Apply tree view pane improvements written + by Nick. It implements a GtkTreeModelFilter inside the tree model + and improves CPU performance when expanding folders in the tree + view. It also stops monitoring tree view folders when they are + closed. It improves thread safety in ThunarVfsMonitor and a few + other things. Should fix bug #4051. + +2008-11-25 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-standard-view.c: Make the location selector pop up + with the home directory pre-entered when GDK_dead_tilde is pressed. + This allows people with dead keys to use the location selector just + like people which don't use dead keys. + +2008-11-25 Nick Schermer <nick@xfce.org> + + * plugins/thunar-tpa/thunar-tpa-icon.c: Change the tooltip text + of the tpa plugin when the trash is 'full' to "Trash contains + files". Bug #3266. + * po/*: Regenerate po files. + +2008-11-25 Nick Schermer <nick@xfce.org> + + * thunar-vfs/thunar-vfs-util.c: Fix completion when ~/ is used. + Patch by Peter de Ridder. Bug #2973. + +2008-11-25 Nick Schermer <nick@xfce.org> + + * thunar/thunar-preferences.c: Store the option name used for + the thunarrc file in the nickname of the GParamSpec so we + don't have to generate it during load/save. + When debugging is enabled property_name_to_option_name() is + still used to check for typos between the name and nickname. + +2008-11-25 Nick Schermer <nick@xfce.org> + + * thunar/thunar-file.c: Remove the display-name property from + ThunarFile. It's not used and some say g_property_notify() is + not the fastest glib function, so we probably don't want to + call it every file change. + +2008-11-25 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-standard-view.c: Restore the selection after deleting + a file/folder. This is done by connecting to the "row-deleted" + signal of the model twice. The first handler saves the tree path to + be selected after the removal in the selection_before_delete member. + The second handler (which is called after the signal is emitted) + selects this path. Selection is not modified if there are two or + more files selected. This should fix bug #3884. + +2008-11-24 Nick Schermer <nick@xfce.org> + + * configure.in.in, thunar-vfs/thunar-vfs-io-local-xfer.c: Use + posix_fadvise when available. + +2008-11-23 Nick Schermer <nick@xfce.org> + + * thunar/main.c: Use -V for version information. + +2008-11-23 Jannis Pohlmann <jannis@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c: Check if volumes are != NULL + when handling "EjectPressed" events. This should fix bug #4257. + Patch again supplied by Nick. + +2008-11-23 Jannis Pohlmann <jannis@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c + (thunar_vfs_volume_hal_is_ejectable): Return TRUE if and only if + requires_eject is TRUE. This should fix bug #3978. + +2008-11-23 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-shortcuts-model.c, thunar/thunar-window.c: Add ifdefs + around includes to fix make distcheck. Spotted by Nick. + +2008-11-20 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-application.c (thunar_application_process_filenames): + Always show an error dialog if one of the files passed via the + command line cannot be opened. Required for exo-open to give proper + visual feedback because spawning Thunar asynchronously will always + make exo-open think that the file(s) were opened successfully. + Ideally Thunar would display an error dialog with a tree view + listing all the files that could not be opened (I'll file a bug for + this). + +2008-11-15 Jannis Pohlmann <jannis@xfce.org> + + * plugins/, tdb/, thunar-vfs/, thunar/: Fix several compiler warnings. + Patch again provided by Nick Schermer. + +2008-11-15 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-tree-model.{c,h}, thunar/thunar-tree-view.c: Fix + freeze in the tree view pane when the visibility of hidden files is + toggled. Kudos to Nick Schermer for the patch. This fixes bug #2502. + +2008-11-06 Brian Tarricone <bjt23@cornell.edu> + + * thunar/thunar-private.h, + thunar/thunar-{shortcuts-model,templates-action,window}.c: Fix + compilation with glib < 2.14. + +2008-11-05 Olivier Fourdan <olivier@xfce.org> + + * thunar/thunar-window.c: Remove portion including a C_() macro. + +2008-10-31 Jannis Pohlmann <jannis@xfce.org> + + * thunar/thunar-settings.desktop.in: Remove GenericName and + X-XfceSettingsName. Use more generic "File Manager" string in the + Name field. + +2008-10-29 Brian Tarricone <kelnos@xfce.org> + + * *: Patch mostly from Andrea Santilli <yawara@quipo.it> (bug 4365). + * thunar/{thunar-file.c,thunar-file.h}: Replace + thunar_file_is_desktop() macro with a function that + recognizes the xdg user Desktop folder. The old macro is still + available for glib < 2.14.0 + * thunar/thunar-private.h: Add macros to better support + GUserDirectory and an array containing the xdg user dir defaults. + * thunar/thunar-{launcher.c,shortcuts-model.c,templates-action.c}: + Address to the right Desktop and Templates directories. Don't + list templates in submenus if the templates dir points to $HOME. + * thunar/thunar-shortcuts-model.c: Creation and translation of + links to some xdg user dirs in the sidebar in case of unexisting + ~/.gtk-bookmarks. Entries pointing to $HOME are disabled. + * thunar/{thunar-shortcuts-model.c,thunar-private.h}: Add + _thunar_get_xdg_user_dirs_locale() to translate the xdg user dir + names (package xdg-user-dirs needed for that). + * thunar/thunar-stock.h: Add icon name for normal directories. + * thunar/{thunar-window.c,thunar-window-ui.xml}: Add new menu + entries, hide the ones related to unused directories and + translate their labels. Entries pointing to $HOME are disabled. + +2008-10-28 Brian Tarricone <kelnos@xfce.org> + + * thunar/Makefile.am: Don't symlink thunar -> Thunar on case- + insensitive filesystems (bug 4430). + +2008-10-28 Brian Tarricone <kelnos@xfce.org> + + * thunar-vfs/thunar-vfs-mime-database.c: Fix usage of + fgetxattr() on MacOS X. Patch from Anders Björklund + <afb@users.sourceforge.net> (bug 4433). + +2008-10-25 Stephan Arts <stephan@xfce.org> + + * plugins/thunar-wallpaper: + Add thunar-wallpaper-plugin which can be used to set the wallpaper + on xfdesktop >= 4.5.90 + +2008-08-25 Brian Tarricone <kelnos@xfce.org> + + * thunar/{Makefile.am,thunar-settings,thunar-settings.desktop.in}: + Include script and .desktop file to launch thunar settings dialog. + +2007-12-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-view.c, thunar/thunar-tree-view.c: + Display "Eject" in the context menu if the device of the + volume requires an eject. + +2007-12-03 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-exec.c: Make sure, processes spawned from + Thunar and xfdesktop are properly joined. Bug #2983. + +2007-12-03 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c: Make sure to pass volumes + without mountable file systems to thunar-volman. + +2007-12-02 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Post-release version bump. + +2007-12-02 Benedikt Meurer <benny@xfce.org> + + * === Released 0.9.0 === + * NEWS, configure.in.in: Bump version. + * README, configure.in.in: Depend on exo 0.3.4. + * THANKS: Add missing translator credits. + * po/*.po: Update Project-Id-Version. + * docs/reference/thunar-vfs/Makefile.am, + docs/reference/thunarx/Makefile.am: Fix dist building. + * docs/reference/thunar-vfs/thunar-vfs-docs.sgml, + docs/reference/thunarx/thunarx-docs.sgml: Update documentation dates. + +2007-11-28 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c: Ignore volumes that do + not mountable file systems. Bug #3555. + +2007-11-28 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-uca/thunar-uca-model.c: Properly recognize + OGG files as audio files. Bug #3604. + +2007-11-28 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-sbr/: Import new date renamer based on patch + from Nick Schermer <nick@xfce.org>. Bug #3656. + * docs/manual/: Update the user manual. + * po/POTFILES.in: Add new file here. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + * po-doc/Thunar.pot, po-doc/*.po: Merge new strings. + +2007-11-28 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-exec.c(thunar_vfs_exec_on_screen): + Make sure to pass the correct $DISPLAY value to processes + spawned by Thunar and xfdesktop. Bug #3667. + +2007-08-24 Jean-François Wauthy <pollux@xfce.org> + + * docs/manual/fr/Thunar.xml.in: minor corrections in French + translation of the manual (patch by Adrien Grellier + <adrien.grellier@laposte.net>) + +2007-08-23 Jean-François Wauthy <pollux@xfce.org> + + * docs/manual/pl/images/file-manager-window.png, + docs/manual/pl/images/preferences-views.png, + docs/manual/pl/images/removable-media-unmount.png, + docs/manual/pl/images/preferences-behavior.png, + docs/manual/pl/images/sendto-menu.png, + docs/manual/pl/images/bulk-rename.png, + docs/manual/pl/images/removable-drives-and-media.png, + docs/manual/pl/images/preferences-advanced.png, + docs/manual/pl/images/preferences-side-pane.png, + docs/manual/pl/images/file-properties.png, + docs/manual/pl/images/visible-columns.png: Updated Polish translation + of the manual + +2007-08-17 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Preselect the complete filename when + renaming a folder. Bug #3057. + +2007-08-11 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb-jpeg.c: Better way to detect recursion + in exif IFDs. + +2007-08-11 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb-jpeg.c: Prevent infinite recursion + on JPEG files with broken exif directories. Bug #3452. + +2007-06-24 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-path.c: Fix crash on amd64 because of + invalid size of integer constants. Bug #3303. + +2007-05-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dialogs.c(thunar_dialogs_show_about): Add support + for new GTK+ 2.11 API. + * docs/reference/thunar-vfs/tmpl/thunar-vfs-job.sgml: Add new + signal "ask-replace" to the reference manual. + +2007-05-23 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-io-jobs.c, thunar-vfs/thunar-vfs-job.{c,h}, + thunar-vfs/thunar-vfs-job-private.h, thunar/thunar-dialogs.c, + thunar-vfs/thunar-vfs-transfer-job.c: Add support to retry job + based operations. + * thunar-vfs/thunar-vfs-job-private.h, thunar-vfs-job.{c,h}, + thunar-vfs/thunar-vfs-transfer-job.c, thunar/thunar-dialogs.{c,h}, + thunar/thunar-progress-dialog.c, thunar-vfs/thunar-vfs-marshal.list: + Display more details when asking the user whether to replace an + existing file with another file. Bug #3268. + * po/tr.po: Revert broken file. + * po/*.po, po/*.pot: Merge new strings. + * po/de.po: Update german translations. + +2007-05-22 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, docs/README.thunarrc, thunar/: Add support for + different date/time formats. Bug #3265. + * po/*.po, po/*.pot: Merge new strings. + * po/de.po: Update german translations. + +2007-05-22 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-path.c: Fix unaligned access in ThunarVfsPath + on sparc64. Bug #2815. + * docs/reference/: Update reference manual. + +2007-05-20 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-preferences.c(thunar_preferences_set_property): + Properly initialize value to its default prior to comparing + with a (probably) new value. + +2007-05-20 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-uca/thunar-uca-editor.c: Properly quote files + selected via the file chooser if necessary. Bug #3105. + +2007-05-20 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-freebsd.c, + thunar-vfs/thunar-vfs-volume-hal.c, + thunar-vfs/thunar-vfs-volume.{c,h}, thunar-vfs/thunar-vfs.symbols: + Apply patch from Brian Tarricone <bjt23@cornell.edu> to fix + invalid invocation of thunar-volman for devices that should be + ignored, and add a MOUNTABLE flag for volumes. Bug #2789. + * configure.in.in: Bump library interface version. + +2007-05-20 Benedikt Meurer <benny@xfce.org> + + * thunar/Makefile.am: Strip unused characters from the user + interface description files. Bug #3094. + +2007-05-09 Benedikt Meurer <benny@xfce.org> + + * INSTALL, configure.in.in: Update for latest autoconf. + +2007-05-09 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c + (thunar_vfs_volume_manager_hal_device_removed): Emit the correct + signal when removing devices. Patch from Brian Tarricone. + Bug #3205. + +2007-04-27 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-freebsd.c, + thunar-vfs/thunar-vfs-volume-hal.c, + thunar-vfs/thunar-vfs-volume-private.h, + thunar-vfs/thunar-vfs-volume.c: Use the requires_eject HAL + property to determine whether a given volume is ejectable. + Bug #3119. + +2007-04-27 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-util.c(thunar_util_humanize_file_time): Use larger + date buffer. Bug #3127. + +2007-04-08 Jean-Francois Wauthy <pollux@xfce.org> + + * configure.in.in: Add support for nl translations into + configure.in.in (patch by Maximilian Schleiss) + +2007-03-19 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-factory.c: Automatically disable thumbnailing + if storing of thumbnails failes because of a fatal error (i.e. + broken setup). Bug #3020. + +2007-02-12 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb-jpeg.c: Fix unaligned memory access in + exif code. Bug #2880. + +2007-02-12 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-path-private.h: Fix compilation with the + Sun Studio 11 compiler based on patch from William Bonnet + <william@wbonnet.net>. Bug #2899. + +2007-02-12 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb-jpeg.c: Fix compilation with the + Sun Studio 11 compiler based on patch from William Bonnet + <william@wbonnet.net>. Bug #2900. + +2007-01-28 Benedikt Meurer <benny@xfce.org> + + * acinclude.m4: Fix switches to disable plugins, thanks to Oliver + Lehmann <oliver@FreeBSD.org>. + +2007-01-20 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Post-release version bump. + +2007-01-20 Benedikt Meurer <benny@xfce.org> + + * === Released 0.8.0 === + * NEWS, configure.in.in: Bump version. + * README, configure.in.in: Depend on exo 0.3.2. + * THANKS: Add missing translator credits. + * po/*.po: Update Project-Id-Version. + * thunar-vfs/Makefile.am, docs/reference/thunar-vfs/Makefile.am, + thunar/Makefile.am, plugins/thunar-sendto-email/Makefile.am, + tests/Makefile.am, plugins/thunar-apr/Makefile.am, + plugins/thunar-sbr/Makefile.am, plugins/thunar-tpa/Makefile.am, + plugins/thunar-uca/Makefile.am: No need to define + EXO_API_SUBJECT_TO_CHANGE any more. + * docs/reference/thunar-vfs/thunar-vfs-docs.sgml, + docs/reference/thunarx/thunarx-docs.sgml: Update documentation dates. + +2007-01-20 Benedikt Meurer <benny@xfce.org> + + * po-doc/*.po: Regenerate the translations. + * docs/manual/pl/Thunar.xml.in, po-doc/pl.po: Updated the polish + translations of the user manual by Szymon KaÅ‚asz + <szymon_maestro@gazeta.pl>. + +2007-01-20 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, docs/manual/: Integrate the polish translations + of the user manual. + +2007-01-18 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c(thunar_vfs_volume_hal_update): + Treat hotplugged drives as removable, so they are displayed in + the side pane. + +2007-01-16 Benedikt Meurer <benny@xfce.org> + + * docs/manual/C/Thunar.xml.in, docs/manual/C/images/bulk-rename.png: + Add documentation for the bulk renamer. Bug #1594. + * docs/manual/C/: Improve the user manual. Bug #1365. + * thunar/: Connect the various "Help" buttons. Bug #1230. + * po-doc/Thunar.pot, po-doc/*.po: Merge new strings. + * docs/manual/: Merge the new strings into the translated XML files. + +2007-01-16 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c: Automatically add removable devices as + targets to the "Send To" menu. Bug #2683. + +2007-01-16 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c, thunar-vfs/thunar-vfs-volume.c, + thunar-vfs/thunar-vfs-volume-private.h, thunar/thunar-application.c: + Allow to use "Eject" button on CD-ROM drives to unmount and eject + the media. Bug #2759. + +2007-01-15 Benedikt Meurer <benny@xfce.org> + + * docs/manual/: Fix thunar-volman website URL. + * po-doc/Thunar.pot, po-doc/*.po: Merge new strings. + +2007-01-15 Benedikt Meurer <benny@xfce.org> + + * docs/manual/: Add documentation for removable drive and media + handling in Thunar. + * po-doc/Thunar.pot, po-doc/*.po: Merge new strings. + +2007-01-15 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, docs/manual/Makefile.am, docs/manual/eu/: + Integrate the basque translations of the manual. + +2007-01-15 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb-jpeg.c: Fix data parameter types for + tvtj_exif_get_ushort() and tvtj_exif_get_ulong(). + +2007-01-15 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb-jpeg.c: Use Exif embedded thumbnails + if available, which reduces the amount of data that must be + retrieved from a camera to around 50k instead of the whole JPEG + image, which can be up to several mega bytes. + * thunar-vfs/thunar-vfs-thumb.c + (thunar_vfs_thumb_factory_generate_thumbnail): Do not scale down + thumbnails extracted from JPEG images that use the rather common + size 160x120 pixels, to save some time and avoid messing up the + thumbnail. + +2007-01-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-exec.c: Improve startup notification handling, + based on a patch from Gregoire Gentil <gregoire@gentil.com>. + * thunar-vfs/thunar-vfs-exec.{c,h}, thunar-vfs/thunar-vfs-info.c, + thunar-vfs/thunar-vfs-mime-handler.c: Allow to pass in icon_name + of the application to start, which can be used by window managers + that detailed support startup notification feedback. + +2007-01-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-io-local.c(_thunar_vfs_io_local_listdir): + Use g_list_free_1() instead of g_list_free1(). + +2007-01-13 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, thunar-vfs/thunar-vfs-io-trash.{c,h}: Add support + for $top_dir-Trashes, as described in the Desktop Trash Specifica- + tion. Bug #2132. + * thunar-vfs/thunar-vfs-volume.c(thunar_vfs_volume_changed): Rescan + the active mount points whenever a volume changes. + +2007-01-12 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-io-local-xfer.c(tvilx_copy_regular): Drop + unused variable. + * thunar-vfs/thunar-vfs-transfer-job.c: Properly report errors if + copying a file fails for some reason. Also fix a memory leak that + wasn't detected previously. + +2007-01-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c: Finally fix crash on platforms where + sizeof(GType) != sizeof(gint). Bug #2726. + +2007-01-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-gdk-extensions.{c,h}: Add new helper function + thunar_gdk_screen_get_active(), which returns the currently + active screen, i.e. the screen which currently contains the + mouse pointer. + * thunar-vfs/thunar-vfs-volume-hal.c: Use the new ExoMountPoint + module to query active and configured mount points. + * thunar-vfs/thunar-vfs-volume-hal.c: Add new signals "device-added" + and "device-removed", which correspond to the HAL signals of the + same name, and are emitted by the volume manager whenever a new + device is added or an existing device is removed. This is an + internal support mechanism for the volume manager integration of + Thunar and should not be used by other applications. + * thunar/thunar-application.c: Add hooks for the thunar-volman, + which, if installed and enabled, will be spawned whenever a new + device is reported by HAL. This enables lightweight volume management + avoiding an additional daemon, as Thunar already listens for HAL + events anyway. Note that Thunar doesn't provide any functionality + by itself here. It just acts a proxy between HAL and thunar-volman. + * docs/README.thunarrc, thunar/thunar-preferences.c: Add preference + MiscVolumeManagement, which controls whether volume manager should + be enabled. + * docs/references/thunar-vfs/: Add missing enums to the manual. + * thunar/thunar-preferences-dialog.c, thunar/sexy-url-label.{c,h}, + thunar/Makefile.am: Extend the preferences dialog with options + to control the volume manager. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2007-01-08 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-io-local.c(_thunar_vfs_io_local_listdir): + Change back to the previous working directory after listing the + directory contents. + +2007-01-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-view.c(thunar_shortcuts_view_init): Ellipsize + long shortcut names, but make sure "File System" still fits into the + side pane. + +2007-01-08 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c, + thunar-vfs/thunar-vfs-volume.{c,h}: Add support for memory cards and + generic removable disk drives. Bug #2652. + +2007-01-07 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs-volume-hal.c, + acinclude.m4: Use exo-hal to determine icons and display names + for the volumes. + * thunar-vfs/thunar-vfs-volume-hal.c, + thunar-vfs/thunar-vfs-volume.{c,h}: Do not discard blank discs and + pure audio discs. Bug #2599. + +2007-01-06 Benedikt Meurer <benny@xfce.org> + + * README, configure.in.in: Requires libexo 0.3.1.13svn. + * thunar-vfs/thunar-vfs-exec.c(thunar_vfs_exec_sync): Strip trailing + dots from the error message. + * thunar-vfs/thunar-vfs-volume-freebsd.c, docs/README.volumes, + thunar-vfs/thunar-vfs-volume-hal.c: Use exo-mount to mount, eject + and unmount volumes instead of relying on external utilities that + don't always behave properly. Bug #2715. + * thunar-vfs/thunar-vfs-volume-hal.c: Add ability to mount floppy + drives using exo-mount. Bug #2075. + * thunar-vfs/Makefile.am: Fix distcheck. + * po/de.po: Some german translation love. + +2007-01-03 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, docs/manual/, thunar/main.c, thunar/thunar-dialogs.c: + Update copyright dates. + * po-doc/Thunar.pot, po-doc/*.po: Merge new strings. + * po/Thunar.pot, po/*.po: Drop obsolete strings. + * po/de.po: Update german translations. + +2007-01-03 Benedikt Meurer <benny@xfce.org> + + * thunar/main.c(main): Need to initialize GThread first. + +2006-12-31 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-update-thumbnailers-cache.c: Add ability to + load custom thumbnailers from .desktop files. Drop the hardcoded + font thumbnailer. + * thunar-vfs/thunar-vfs-font-thumbnailer-1.desktop.in, + thunar-vfs/Makefile.am: Install a .desktop file for the font + thumbnailer. + * docs/manual/, po-doc/: Update the user guide with detailed information + about the custom thumbnailers. + +2006-12-31 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs.c(_thunar_vfs_init): Do not maintain more than + four unused threads, and stop unused threads after ten seconds of + idle time (requires GLib 2.10). + +2006-12-29 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-io-local-xfer.c, + thunar-vfs/thunar-vfs-mime-database.c, + thunar-vfs/thunar-vfs-monitor.c, thunar-vfs/thunar-vfs-os-bsd.c, + thunar-vfs/thunar-vfs-os-generic.c, thunar-vfs/thunar-vfs-path.c, + thunar-vfs/thunar-vfs-path-private.h, + thunar-vfs/thunar-vfs-transfer-job.c: Add _thunar_vfs_path_child() + as internal implementation of thunar_vfs_path_relative(), that does + not perform the expensive sanity checking for release builds. + * thunar-vfs/thunar-vfs-io-local.{c,h}: List folders parallel again, + with up to four threads collecting file infos at the same time. + Additionally, in order to avoid the costly inode lookups when + listing folder contents, we change to the requested folder and + use relative file names (requires locking, since the current + working directory is per-process rather than per-thread). Last, + the executable sanity checking was optimized for the common case + of a binary or shellscript, which should further improve the + loading performance of large folders with binaries. + +2006-12-28 Benedikt Meurer <benny@xfce.org> + + * thunar/: Several improvements to the GtkTreeModel implementations + that should further speed up loading really large folders. For the + icon view, the real bottleneck is still Pango. + +2006-12-21 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs.c: Apply Brian's + patch to properly initialize the gettext textdomain for thunar-vfs. + Bug #2543. + +2006-12-21 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-entry.c(thunar_location_entry_init): + Make sure the down button in the location bar doesn't get too + large. Bug #2582. + +2006-12-21 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_get_statusbar_text): + Don't try to open non-regular files to gather detailed statistics + to avoid hanging Thunar forever while trying to read from a named + pipe. Bug #2655. + +2006-11-26 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c(thunar_window_init): Add shortcuts <control>1, + <control>2 and <control>3 to switch between icon, detailed list and + compact list view. Bug #2600. + +2006-11-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c(thunar_launcher_dispose): Fix a possible + crash if thunar_launcher_update() is called while disposing the + launcher. + +2006-11-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c(thunar_launcher_set_selected_files): Do + not force an update of the launcher actions if the list of selected + files did not change to avoid flicker in menus for files being + downloaded, etc. + +2006-11-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c(thunar_launcher_sendto_idle): Do not + display the "Desktop (Create Link)" sendto-action for trashed + files, because symbolic links cannot be created for files in + the trash. Bug #2539. + +2006-11-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-view.c: Set word-wrap-width depending on the + current zoom-level. Bug #2505. + +2006-11-11 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-path.c(thunar_vfs_path_list_to_string): Fix + crash when transfering a lot of files via DnD or clipbord. Bug #2356. + +2006-11-11 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-tpa/Makefile.am: Starting with version 0.72 + dbus-binding-tool now requires the --prefix command line option + even though it isn't used for anything. Bug #2528. + +2006-11-11 Benedikt Meurer <benny@xfce.org> + + * docs/README.volumes, thunar-vfs/thunar-vfs-volume-hal.c: Apply patch + from Bernhard Walle <bernhard.walle@gmx.de> to add support for + halmount to ThunarVfsVolumeHAL. Bug #2556. + +2006-11-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dialogs.c(thunar_dialogs_show_about): Modal about + dialog seems to block all other windows as well. Bug #2545. + +2006-11-06 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, thunar/Makefile.am: Fix installation on case + insensitive file systems. Bug #2521. + +2006-11-06 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c(thunar_path_entry_changed): Changing the + model currently in used by a GtkEntryCompletion is very slow with + recent GTK+ versions. Therefore we disconnect the model first when + changing the folder and reconnect it to the entry completion after- + wards. Bug #1681. + +2006-11-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-view.c(thunar_shortcuts_view_drag_leave): + Schedule a repaint of the shortcuts pane after resetting the folder + drop icon. Bug #2498. + +2006-11-04 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Post-release version bump. + +2006-11-04 Benedikt Meurer <benny@xfce.org> + + * === Released 0.5.0rc2 === + * configure.in.in, NEWS: Bump version. + * configure.in.in, README: Depend on libexo 0.3.1.12rc2. + * docs/reference/thunarx/: Regenerate API docs. + * THANKS: Add missing translator credits. + * po/*.po: Update Project-Id-Version. + * tests/: Drop the FreeBSD fstab check, as the default volume manager + backend for FreeBSD is HAL. + +2006-11-04 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c(thunar_vfs_volume_hal_update): + Do not use the deprecated HAL policy framework. Bug #2475. + +2006-11-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-button.c, thunar/thunar-location-buttons.c: + Properly clean up the path bar when a folder on the path bar is + deleted. + +2006-11-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-tree-model.c(thunar_tree_model_item_files_removed): + The "row-has-child-toggled" signal must not be emitted if the + children of the row did not change, otherwise newer GtkTreeView's + will loose sync with the model and probably crash. Bug #2372. + +2006-11-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-entry.c: Merge drop-down menu making shortcuts + accessible even if the classic file manager look'n'feel is being + used. Bug #2024. + +2006-11-03 Benedikt Meurer <benny@xfce.org> + + * thunar/xfce-heading.{c,h}, thunar/xfce-titled-dialog.{c,h}, + thunar/Makefile.am, thunar/thunar-preferences-dialog.c: Adjust the + preferences dialog to match the look of the other Xfce preferences + dialogs. Bug #2379. + +2006-11-03 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c(thunar_window_set_current_directory): Place + focus on the main view after changing the currently displayed + folder. Bug #2367. + +2006-11-03 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Make sure + emblems don't get too large with SVG icon themes. Bug #2466. + +2006-11-03 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-trash-action.{c,h}, thunar/Makefile.am, + thunar/thunar-stock.{c,h}, thunar/thunar-window-ui.xml, + thunar/thunar-window.c: Add a "Trash" entry to the "Go" menu. + Bug #2486. + * po/POTFILES.in: Add new files here. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-10-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-chooser-model.c(thunar_chooser_model_import): + Use preferences-desktop-default-applications for the "Recommended + Applications" group. + * thunar/thunar-chooser-dialog.c, thunar/thunar-chooser-model.{c,h}: + Use the ExoCellRendererIcon to render the icons instead of preloading + the icons in the model. Don't display the expanders with GTK+ 2.9 + and above. + +2006-10-28 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job-private.h, thunar-vfs/thunar-vfs-job.c: + Handle file names with printf(3)-style format arguments properly + when emitting the "info-message" signal from a job. Bug #2468. + +2006-10-28 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-cache.c(thunar_vfs_mime_cache_finalize): + Fix compiler warning if mmap() is not available. + * configure.in.in, thunar/Makefile.am: Do not install the symlink from + thunar to Thunar on Win32 platforms. Bug #2432. + +2006-10-28 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-io-local.c(_thunar_vfs_io_local_get_free_space): + Apply patch from Tim van der Molen <tbvdm@xs4all.nl> to calculate + free space properly on OpenBSD/amd64. Bug #2383. + +2006-10-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c(thunar_properties_dialog_init): + Use an input-only window to trap mouse events for mime type tooltip. + +2006-10-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c: Display the real mime type as + tooltip for the "Kind" label. Bug #2369. + +2006-10-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c + (thunar_standard_view_set_selected_files): Place the cursor on the + first selected file. Bug #2368. + +2006-10-01 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Depend on exo 0.3.1.11 because thunar-uca requires + exo-open to support the --working-directory switch. + +2006-09-21 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dbus-client.c, thunar/thunar-dbus-service.c: Fix build + with latest dbus-glib. Bug #2263. + +2006-09-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-io-local.c(_thunar_vfs_io_local_get_info): + Properly validate the Name of .desktop files. Bug #2227. + +2006-09-14 Benedikt Meurer <benny@xfce.org> + + * thunarx/thunarx-config.h.in, thunarx/thunarx-file-info.h: Fix build + with GLib 2.6.x. Bug #2317. + +2006-09-14 Benedikt Meurer <benny@xfce.org> + + * thunarx/thunarx-menu-provider.{c,h}, thunarx/thunarx.symbols: Add a + new method get_dnd_actions() to the ThunarxMenuProvider, which allows + menu providers to install additional actions into the Drag'n'Drop + menu of the file manager. + * docs/reference/thunarx/: Update the thunarx reference manual. + * thunar/thunar-dnd.{c,h}, thunar/thunar-location-button.c, + thunar/thunar-shortcuts-view.c, thunar/thunar-standard-view.c, + thunar/thunar-tree-view.c: Insert the additional actions supplied + by the installed menu providers into the Drag'n'Drop menu. + +2006-09-13 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-monitor.c, thunar/thunar-standard-view.c: + Fix several race conditions that were introduced over time and + prevented the "new-files" job handling from working properly with + Gamin and automatic folder reload. Bug #2199. + * thunar/thunar-file.c: The file must not be dropped from the hash + table in the dispose() function, but only when finalize is called, + because dispose() may be invoked more than once and hence we might + drop a newly created ThunarFile object with the same path from + the hash table. + +2006-09-13 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, Makefile.am: Place automake options into + configure.in.in instead of Makefile.am and add the tar-ustar + option to fix building distributions on system where tar defaults + to the deprecated V7 format. Bug #2304. + +2006-09-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dbus-client.c: Use default dbus connection timeout. + Bug #2243. + +2006-09-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-renamer-model.c(thunar_renamer_model_iter_n_children): + Fix typo. + +2006-09-11 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-io-local-xfer.c + (_thunar_vfs_io_local_xfer_next_path): Remove duplicate const. + Bug #2300. + +2006-09-10 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-uca/uca.xml.in: Use exo-open for the default "Open + Terminal Here" action. Bug #2256. + +2006-09-10 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs-io-local.c, + thunar-vfs/thunar-vfs-private.{c,h}, thunar-vfs/thunar-vfs.symbols, + thunar/thunar-file.{c,h}, thunar/thunar-properties-dialog.c: Allow + to change the icon of .desktop files. Bug #2150. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-09-09 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, thunar-vfs/thunar-vfs-io-local-xfer.c: Keep the + modification time when copying files. Bug #2244. + * thunar-vfs/thunar-vfs-io-local-xfer.c + (_thunar_vfs_io_local_xfer_next_path): Further reduce the number + of relocations. + +2006-09-09 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add missing check for setmntent(). + +2006-09-08 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-os-bsd.c(_thunar_vfs_os_scandir): Allocate the + directory scan buffer on the heap rather than the stack to avoid + crashes on systems with very small thread stacks. Bug #2269. + +2006-09-08 Benedikt Meurer <benny@xfce.org> + + * acinclude.m4, configure.in.in, thunar-vfs/thunar-vfs-volume-hal.c: + Add support for FreeBSD to the HAL based volume manager. + +2006-09-06 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Fix typo, -DNDEBUG instead of -NDEBUG. + +2006-09-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-session-client.c(thunar_session_client_connect): Make + sure Thunar is restarted prior to xfdesktop, so the trash support + in xfdesktop works as expected even if D-Bus autoactivation is not + setup properly. + +2006-09-05 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-info.c: Update the icon mime icon lookup + to try icon names from Icon Naming Spec first, and fallback to + legacy GNOME icon names. + * thunar/thunar-icon-factory.c: Use the thumbnail database to load + SVG icons from the icon theme, because loading SVG is quite slow + and takes a lot more memory than loading and scaling PNG icons + from the thumbnail database. + * thunar/thunar-properties-dialog.c(thunar_properties_dialog_init): + Ellipsize the kind label at the end. + * thunar/thunar-properties-dialog.c: No need to keep the "reload" + signal id around. + +2006-09-02 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Post-release version bump. + +2006-09-02 Benedikt Meurer <benny@xfce.org> + + * === Released 0.4.0rc1 === + * configure.in.in, NEWS: Bump version. + * configure.in.in, README: Depend on libexo 0.3.1.10rc1. + * THANKS: Add missing translator credits. + * po/*.po, po-doc/*.po: Update Project-Id-Version. + +2006-09-02 Benedikt Meurer <benny@xfce.org> + + * docs/reference/thunar-vfs/, thunar-vfs/: Update the thunar-vfs + reference manual. + * po/cs.po: Update czech translations by Michal Várady + <miko.vaji@gmail.com>. + * po/it.po: Update italian translations by Roberto Pariset + <robdebian@gmail.com>. + * po/pl.po: Update polish translations by Szymon KaÅ‚asz + <szymon_maestro@gazeta.pl>. + +2006-09-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c: GMemChunk in GLib 2.10 and above is not + only inefficient, but also continously leaks memory. Therefore we + don't use GMemChunk anymore, but use GSList directly. + +2006-09-01 Benedikt Meurer <benny@xfce.org> + + * docs/Thunar.xml, docs/Makefile.am: Add manual page for Thunar. + Bug #1650. + +2006-08-31 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c(thunar_vfs_volume_hal_eject): + Unmount volumes prior to ejecting them if they are currently + mounted. Bug #2236. + +2006-08-30 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-io-local.c, thunar-vfs/thunar-vfs-os-generic.c, + thunar/thunar-shortcuts-view.c(thunar_shortcuts_view_drag_leave), + thunar/thunar-tree-view.c(thunar_tree_view_drag_leave): Enable + compilation with Sun Studio Pro. Bug #1852. + +2006-08-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view-ui.xml, thunar/thunar-window-ui.xml, + thunar/thunar-window.c: Add "Empty Trash" action to "File" and + folder context menu, which is only visible when displaying the + trash root folder. Bug #2238. + +2006-08-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-column-editor.c, thunar/thunar-preferences-dialog.c, + thunar/thunar-gtk-extensions.{c,h}, thunar/thunar-location-dialog.c, + thunar/thunar-permissions-chooser.c, thunar/thunar-create-dialog.c: + Add helper function thunar_gtk_label_set_a11y_relation(), which sets + up the ATK_RELATION_LABEL_FOR for a label and a widget, so we don't + need to repeat the same code over and over again. + +2006-08-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.{c,h}, thunar/thunar-location-button.c, + thunar/thunar-shortcuts-model.c: Add desktop shortcut to the + shortcuts pane, and use a special icon for the desktop folder. + Bug #2235. + * thunar/thunar-chooser-button.c, thunar/thunar-chooser-dialog.c, + thunar/thunar-gtk-extensions.{c,h}, thunar/thunar-location-buttons.c, + thunar/thunar-renamer-dialog.c, thunar/thunar-shortcuts-view.c, + thunar/thunar-standard-view.c, thunar/thunar-tree-view.c: Add helper + method thunar_gtk_menu_run(), which takes care of running a GtkMenu + in a separate main loop, placing the menu on the appropriate screen + first. + +2006-08-29 Benedikt Meurer <benny@xfce.org> + + * docs/README.gtkrc, docs/README.thunarrc, thunar/: Revert location bar + related changes to the previous user interface, because the new user + interface wastes too much space, and makes the file manager look busy. + * po/POTFILES.in: Synchronize file list. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-08-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c: Add warning text to the window when running + as super user. Bug #2218. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-08-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c(action_entries), thunar/thunar-stock.{c,h}: + Use "gnome-fs-home" instead of "gtk-home" as icon for Home for + consistency. + * thunar/thunar-window.c(action_entries): Fix a mnemonic clash. + * thunar/thunar-window.c(thunar_window_current_directory_changed): + Use "<folder> - File Manager" for the title to make it easier to + indentify file manager windows in the taskbar. + * thunar/thunar-create-dialog.c, thunar/thunar-permissions-chooser.c, + thunar/thunar-standard-view.c: No need to include thunar-stock.h + here anymore. + * thunar/thunar-history.c(thunar_history_init): Consider "back" as + an important action wrt to the appearance in the toolbar. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Decouple the + location bar from the toolbar by separating them into "Location Bar" + and "Main Toolbar". Bug #1349. + * thunar/thunar-preferences.c, docs/README.thunarrc: Add new options + LastLocationBarVisible and LastToolbarVisible, which control the + visibility of the "Location Bar" and "Main Toolbar". Add new option + LastNavigationBarEntry, which controls whether the navigation bar + will display the path entry widget by default. + * thunar/thunar-gtk-extensions.{c,h}: Add new helper function + thunar_gtk_action_set_tooltip(), which changes the tooltip of + a GtkAction. + * thunar/thunar-navigation-bar.{c,h}, thunar/thunar-path-button.{c,h}, + thunar/thunar-navigation-bar-ui.xml, thunar/thunar-path-bar.{c,h}, + thunar/thunar-location-button.{c,h}, thunar/thunar-location-bar.{c,h}, + thunar/thunar-location-buttons-ui.xml, docs/README.gtkrc, + thunar/thunar-location-buttons.{c,h}, thunar/Makefile.am, + thunar/thunar-location-entry.{c,h}, thunar/thunar-marshal.list, + thunar/thunar-shortcuts-pane.c, thunar/thunar-shortcuts-view.c, + thunar/thunar-tree-pane.c, thunar/thunar-tree-view.c, + thunar/thunar-window-ui.xml, thunar/thunar-window.c: Synchronize + the latest user interface changes in GtkFileChooser. This way the + location bar will be used for both the path bar and the path entry + widgets, and a simple toggle button controls whether the path entry + is visible. This way (nearly) the full width of the window is avail- + able for the path bar. Bug #2060. + * thunar/thunar-gtk-extensions.{c,h}: Drop now obsolete helper function + thunar_gtk_action_group_create_tool_item() as it's no longer used. + * thunar/thunar-location-dialog.c(thunar_location_dialog_init): Reduce + translation overhead and don't use a mnemonic here. It was pretty + useless anyway. + * thunar/thunar-preferences.c, docs/README.thunarrc: Remove now + obsolete option LastLocationBar. + * po/POTFILES.in: Synchronize file list. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-08-26 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(action_entries): Do not register an + additional accelerator for "Select all Files", instead rely on the + key bindings registered by ExoIconView/GtkTreeView. Bug #2036. + +2006-08-26 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-uca/thunar-uca-model.c(thunar_uca_model_parse_argv): + Substitute %d properly. Bug #2214. + * thunar/thunar-gdk-pixbuf-extensions.{c,h}, thunar/Makefile.am, + thunar/thunar-icon-factory.c, thunar/thunar-icon-renderer.c: Use + exo_gdk_pixbuf_frame() instead of thunar_gdk_pixbuf_frame() and drop + the GdkPixbuf extensions. + * thunar-vfs/thunar-vfs-pixbuf-thumbnailer.c, thunar/Makefile.am: Use + exo_gdk_pixbuf_new_from_file_at_max_size() for the pixbuf thumbnai- + ler. + * configure.in.in, README, thunar-vfs/thunar-vfs-font-thumbnailer.c, + thunar-vfs/thunar-vfs-update-thumbnailers-cache.c, + thunar-vfs/Makefile.am: Import the font thumbnailer, which uses + freetype 2.x (if available) to generate a thumbnail of a font file. + * plugins/thunar-uca/thunar-uca-editor.c: Use ExoIconChooserDialog to + select an icon for a custom action. + * po/POTFILES.in: Add new files here. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-08-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-renamer-model.c, thunar/thunar-shortcuts-model.c: Fix + two typos in the tree model implementations. + * configure.in.in, thunar-vfs/thunar-vfs-private.h, + thunar/thunar-private.h: Use -DNDEBUG in release builds and + -GG_ENABLE_DEBUG only for full debug builds. + +2006-08-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-path.c(thunar_vfs_path_list_to_string): Use + CRLF for text/uri-list, as specified by RFC 2483. Bug #2166. + +2006-08-13 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-private.h, thunar-vfs/*.c: Several cleanups + in the error handling. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-08-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-history-action.{c,h}, thunar/thunar-history.c, + thunar/Makefile.am: Add "back" and "forward" menus to the history + support module. Bug #1782. + * thunar/thunar-create-dialog.c, thunar/thunar-standard-view.c, + thunar/thunar-stock.{c,h}: We don't really need stock items for + create and rename. Instead use labels with mnemonics. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-08-11 Benedikt Meurer <benny@xfce.org> + + * thunar/Makefile.am: Fix typo. + +2006-08-09 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-exec.c(tvsn_get_active_workspace_number), + configure.in.in: Enable compilation with -fstrict-aliasing without + breaking the strict aliasing rules of the compiler. + * configure.in.in: Enable compilation with --enable-debug=yes or + --enable-debug=full and compilers other than gcc. + * configure.in.in, thunar/thunar-private.h, thunar/thunar-*.c: + Disable extra debugging in release builds, Thunar received + quite a lot of stabilization now. This affects only the internals + of the binary. The public API is still fully sanity checked. + * thunar/thunar-column-model.c, thunar/thunar-renamer-model.c, + thunar/thunar-shortcuts-model.c, thunar/thunar-tree-model.c: + Remove unused variables when building with --enable-debug=no or + --enable-debug=minimum now. + +2006-08-09 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c(thunar_details_view_init): Enable + rubberband selection with GTK+ 2.9.0 and above. Bug #1996. + * configure.in.in: Depend on exo 0.3.1.9svn. + +2006-08-08 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, docs/ThumbnailersCacheFormat.txt, docs/Makefile.am, + thunar-vfs/thunar-vfs-thumb.c, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs-update-thumbnailers-cache.c: Drop the dependen- + cy of libthunar-vfs on GConf, which was required to load the GNOME + thumbnailers. Instead there's now an external program, which genera- + tes an mmap()able file that contains a mapping between a mime type + and the thumbnailer used to generate thumbnails for that mime type. + Bug #2131. + * thunar-vfs/thunar-vfs-pixbuf-thumbnailer.c, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs-thumb-pixbuf.{c,h}, + thunar-vfs/thunar-vfs-thumb.c: Put the gdk-pixbuf thumbnailer into + a separate program, which gets registered via the thumbnailers.cache + file, so we don't need any extra overhead for thumbnails that can be + generated using gdk-pixbuf. + * thunar-vfs/thunar-vfs-monitor-private.h, + thunar-vfs/thunar-vfs-monitor.c: Add a simple helper method + _thunar_vfs_monitor_handle_get_path() that returns the path for + a given monitor handle so we don't need to keep around both the + path and the handle. + * thunar-vfs/thunar-vfs-mime-database.c: Do not keep both the handle + and the path around for monitored resources. + * thunar-vfs/thunar-vfs-io-jobs.c(_thunar_vfs_io_jobs_chown): Fix + typo. Thanks to Roberto Pariset <robdebian@gmail.com> for the hint. + * po/POTFILES.in: Remove no longer existing file. + * po/Thunar.pot, po/*.po: Update translations. + * po/de.po: Update german translations. + * po/it.po: Update italian translations by Roberto Pariset + <robdebian@gmail.com>. + +2006-08-06 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c(thunar_launcher_update): Place additional + "Open With" action into a submenu if either more than 2 are available + or the default action for the file is "Execute". + +2006-08-06 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb.c + (thunar_vfs_thumb_factory_lookup_thumbnail): Fix an invalid return + value. + * thunar-vfs/thunar-vfs-thumb.c + (thunar_vfs_thumb_factory_generate_thumbnail), + thunar/thunar-icon-factory.c(thunar_icon_factory_load_file_icon): + Add support for generating and loading thumbnails for files in the + trash. + * thunar-vfs/thunar-vfs-info.c(_thunar_vfs_io_local_rename), + thunar-vfs/thunar-vfs-mime-application.c + (thunar_vfs_mime_application_new_from_file), + thunar-vfs/thunar-vfs-mime-cleaner.c(main), + thunar-vfs/thunar-vfs-mime-handler.c + (thunar_vfs_mime_handler_set_icon), + thunar/thunar-dialogs.c(thunar_dialogs_show_job_error), + thunar/thunar-launcher.c, + thunar/thunar-path-entry.c(thunar_path_entry_check_completion_idle): + Use strncmp() instead of g_str_has_prefix() where it makes sense. Try + to avoid g_str_has_suffix() if checking only for a single character. + * thunar/thunar-standard-view.c(thunar_standard_view_drag_motion): + Deny XdndDirectSave0 and _NETSCAPE_URL drops to locations in the + trash. + +2006-08-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-application.c(thunar_application_unlink_files): Unlink + permanently if atleast one non-local (not necessary trash) file is + included in the file list. + * thunar/thunar-path-entry.c(thunar_path_entry_changed): Do not try + to autocomplete non-local paths, as that's not going to work pro- + perly with trash paths anyway. + +2006-08-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.c(thunar_file_info_get_uri_scheme): Use a more + generic implementation here. + * thunar/thunar-location-button.c(thunar_location_button_file_changed): + Hide the label only for the file system root node. + +2006-08-04 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, thunar-vfs/thunar-vfs-os-bsd.c: OpenBSD doesn't + support getdents() and whiteout inodes, instead getdirentries() + will be used on OpenBSD. + +2006-08-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-util.c(thunar_util_time_from_rfc3339): Fix typo. + +2006-08-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.c, thunar/thunar-util.{c,h}: Add new helper method + thunar_util_time_from_rfc3339(), which parses a date string to a time + value, using strptime() if available. Use the method to parse the + deletion date string for trashed resources, so the deletion date will + be displayed properly even on systems that lack strptime(). + * thunar/thunar-util.c(thunar_util_humanize_file_time): Use + g_date_set_time() to enable compilation with GLib 2.6/2.8. + Hopefully nobody will still use GLib 2.6/2.8 in 2038. + +2006-07-31 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, thunar-vfs/thunar-vfs-io-local-xfer.c, + thunar-vfs/thunar-vfs-io-local.c: Use statvfs1()/fstatvfs1() on + NetBSD 2.99 and above. + +2006-07-31 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-permissions-chooser.c + (thunar_permissions_chooser_file_changed): Make sure that the file's + group is included in the "Group" box. Bug #1838. + +2006-07-31 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-transfer-job.c, thunar/thunar-dialogs.c: + Add "No to all" response to the transfer progress dialog, which + allows to skip all further overwrite dialogs. Bug #1666. + +2006-07-31 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dbus-service-infos.xml, thunar/thunar-dbus-service.c: + Add DisplayChooserDialog() to the org.xfce.FileManager interface, + which pops up the "Open With" dialog, optionally allowing the user + to open the file with the choosen application. Bug #1811. + +2006-07-31 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, plugins/thunar-sendto-email/main.c: Check for + missing mkdtemp, and use a fallback implementation if missing + from the system. Bug #2070. + +2006-07-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-tree-model.c: Emit "row-deleted" prior to deleting the + node from the tree structure, as required for GTK+ 2.10. + +2006-07-30 Benedikt Meurer <benny@xfce.org> + + * acinclude.m4(BM_THUNAR_PLUGIN_TPA): Display "no" if the tpa plugin + should not be build. + * configure.in.in: Finally fix the glibc detection. + +2006-07-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-application.c(thunar_application_collect_and_launch): + Always sanity check the list of paths when collecting files for a + copy or move operation, as applications might provide invalid URI + lists during a DnD operation. + +2006-07-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-factory.c(thunar_icon_factory_load_file_icon): Do + not try to load or generate thumbnails for files in the trash. + +2006-07-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dbus-service.c, thunar/thunar-tree-model.c: Monitor + the trash bin for changes. + +2006-07-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-tree-model.c(thunar_tree_model_node_drop_dummy): We + can avoid an additional path lookup here. + +2006-07-27 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb-pixbuf.c(thunar_vfs_thumb_pixbuf_load): + Properly close the pixbuf loader prior to releasing it, even if the + pixbuf wasn't loaded successfully. + * configure.in.in: The glibc specified work-arounds break other the + build on other systems. Instead try to guess whether glibc-style + work-arounds are required. + +2006-07-27 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, thunar-vfs/thunar-vfs-io-local-xfer.c, + tdb/Makefile.am: Work-around various glibc oddities. + +2006-07-27 Benedikt Meurer <benny@xfce.org> + + * README, acinclude.m4, configure.in.in, thunar-vfs/, thunar/, + plugins/thunar-apr/thunar-apr-provider.c, + plugins/thunar-uca/thunar-uca-model.c: Import the trash framework, + based on the XDG trash specification, but currently limited to the + home trash. + * thunar/thunar-file.{c,h}, thunar/thunar-standard-view.c + (thunar_standard_view_merge_custom_actions): Remove obsolete + thunar_file_get_actions(). Bug #1241. + * thunar/thunar-file.c, thunar/thunar-util.{c,h}: Use localized + human readable format for file dates. Bug #2057. + * thunar/thunar-private.h, thunar/thunar-tree-model.c, + thunar/thunar-thumbnail-generator.c, thunar/thunar-shortcuts-model.c, + thunar/thunar-renamer-pair.c, thunar/thunar-renamer-model.c, + thunar/thunar-clipboard-manager.c: Use the slice allocator to reduce + the memory overhead. + * thunar/thunar-gtk-extensions.{c,h}, thunar/thunar-chooser-button.c, + thunar/thunar-permissions-chooser.c, thunar/thunar-chooser-dialog.c, + thunar/thunar-preferences-dialog.c, thunar/thunar-renamer-dialog.c, + thunar/thunar-size-label.c: Use a single shared GtkTooltips instance + for the whole application. + * thunar/thunar-path-entry.c: Update the path entry icon and text + whenever the current file changes. + * README, acinclude.m4, configure.in.in, plugins/thunar-tpa/: Add a + trash panel applet, that communicates with Thunar via D-BUS to + display the current state of the trash can and move files to the + trash by dropping them to the panel applet. + * thunar/thunar-preferences.c(thunar_preferences_class_init), + docs/README.thunarrc: Disable case-sensitive sorting of the + files by default. Bug #2064. + * docs/reference/thunar-vfs/: Update the API documentation. + * po/POTFILES.in: Add new files here. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-07-22 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-renamer-progress.c(thunar_renamer_progress_next_idle): + Pass the error pointer to thunar_file_rename(). + +2006-07-21 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-handler.h(ThunarVfsMimeHandlerFlags): Add + THUNAR_VFS_MIME_HANDLER_SUPPORTS_URIS to indicate that the handler + supports URIs. + * thunar-vfs/thunar-vfs-mime-application.c + (thunar_vfs_mime_application_new_from_file): Test whether the + application launcher and the associated desktop actions support + URIs. + +2006-07-14 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-apr/thunar-apr-image-page.c: Add ISO Speed Ratings + to the Image page. + * thunar/thunar-preferences-dialog.c(thunar_preferences_dialog_init): + Avoid duplication in the user interface, as suggested by Eugenia + Loli-Queru <eloli@hotmail.com>. + +2006-07-10 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb-pixbuf.c: sys/types.h must be included + before sys/mman.h to compile properly on OpenBSD. + * thunar/thunar-progress-dialog.c(thunar_progress_dialog_percent): Do + not truncate the text in the progress bar. Bug #2003. + * thunar/thunar-list-model.c: Fix improper behaviour of ThunarListModel + with GtkEntryCompletion and GtkTreeView. Bug #1891. + +2006-07-09 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Post-release version bump. + +2006-07-09 Benedikt Meurer <benny@xfce.org> + + * === Released 0.3.2beta2 === + * configure.in.in: Bump version. + * configure.in.in, README: Depend on libexo 0.3.1.8beta2. + * THANKS: Add missing translator credits. + * NEWS: Add missing news items. + * po/*.po: Update Project-Id-Version. + * po/*.po: Update translations. + +2006-07-08 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-path.c(thunar_vfs_path_escape_uri): Fix + alignment issues for Linux/sparc. Bug #1983. + +2006-07-06 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_get_sort_column_id): + Fix a crash with GTK+ 2.10. Bug #1995. + +2006-07-01 Benedikt Meurer <benny@xfce.org> + + * docs/README.thunarrc, thunar/thunar-preferences.c: Add a new option + MiscRememberGeometry, which controls whether Thunar will store the + window size whenever the user resizes the window. + * thunar/thunar-window.c: Don't save the window geometry unless the + MiscRememberGeometry setting is TRUE. + +2006-06-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-renamer-dialog-ui.xml, thunar/thunar-renamer-dialog.c: + Add missing "sendto-menu" action. Bug #1921. + +2006-06-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/: Reduce the number of relocations. + +2006-06-13 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Use --as-needed if supported by the linker. + * thunar/thunar-properties-dialog.c(thunar_properties_dialog_init): + Use GtkLabel instead of ExoEllipsizedLabel here. + * plugins/thunar-sendto/main.c(tse_ask_compress): Initialize info + properly here. + +2006-06-11 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-sendto-email/main.c(tse_ask_compress): Do not try to + create an archive for a list of archive files, but always attach these + files directly. + +2006-06-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-gtk-extensions.{c,h}, thunar/thunar-launcher.c: Add + utility function thunar_gtk_icon_factory_insert_icon(), which inserts + a named icon or an icon file to a GtkIconFactory with a given name. + This is used in ThunarLauncher to add icons for the various launcher + GtkAction's. + * thunar/thunar-sendto-model.{c,h}, thunar/Makefile.am: Import class + ThunarSendtoModel, which provides access to additional "Send To" + targets registered as .desktop files in $XDG_DATA_DIRS/Thunar/sendto. + * icons/16x16/Makefile.am, icons/16x16/stock_thunar-shortcuts.png: + Add stock icon for the shortcuts pane. + * thunar/thunar-stock.{c,h}: Add stock icons for the desktop and + shortcuts side pane "Send To" targets. + * thunar/thunar-launcher-ui.xml, thunar/thunar-launcher.c, + thunar/thunar-shortcuts-pane-ui.xml, thunar/thunar-shortcuts-pane.c, + thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add "Send To" + sub menu to the "File" and file context menus. Turn "Add Folder to + Shortcuts" into a sendto target, named "Side Pane (Create Shortcut)". + Use ThunarSendtoModel to load additional sendto targets, represented + as ThunarVfsMimeHandlers, and add them to the "Send To" menu (will be + loaded only on-demand). + * configure.in.in, plugins/thunar-sendto-email/, plugins/Makefile.am: + Import the sendto-email plugin, which adds an entry to the new "Send + To" menu, named "Mail Recipient", and allows to attach files to mails + from within the file manager. + * po/POTFILES.in: Add new files here. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-06-11 Daichi Kawahata <daichi@xfce.org> + + * plugins/thunar-sbr/thunar-sbr-remove-renamer.c, + thunar/thunar-permissions-chooser.c: Fixed typos, modified string + suggested by Misu Moldovan <dumol@gnome.ro>. + * po/Thunar.pot, po/*.po: Updated. + +2006-05-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_drag_drop): Fix + signedness warning introduced with the previous commit. + +2006-05-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_drag_drop): Don't + crash if the XDS drag site provides an invalid filename. + +2006-05-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-button.c, thunar/thunar-location-buttons.c: + Cleanup location buttons properly when a directory is unmounted or + otherwise destroyed. Bug #1752. + +2006-05-23 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c(thunar_vfs_volume_hal_mount): + Fix memory leak introduced by the previous commit. + +2006-05-23 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c(thunar_vfs_volume_hal_mount): + pmount-hal returns an error if the volume is already mounted. + Bug #1833. + +2006-05-23 Daichi Kawahata <daichi@xfce.org> + + * configure.in.in, docs/manual/Makefile.am, + docs/manual/zh_TW/Thunar.xml.in, docs/manual/zh_TW/images/Makefile.am, + docs/manual/zh_TW/Makefile.am, po-doc/ChangeLog, po-doc/LINGUAS, + po-doc/zh_TW.po: Import initial Traditional Chinese translations by + Cosmo Chene <cosmolax@gmail.com>. + +2006-05-17 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-application.{c,h}, + thunar-vfs/thunar-vfs.symbols: Add new method + thunar_vfs_mime_application_is_usercreated(), which tells whether + a given mime application was automatically created by the user + via the "custom command" box in the file manager(s). + * thunar-vfs/thunar-vfs-mime-database.{c,h}, + thunar-vfs/thunar-vfs.symbols: Add new method + thunar_vfs_mime_database_remove_application() to remove a previously + added mime application (user-created) from the mime database. + * thunar/thunar-chooser-dialog.c, thunar/thunar-chooser-model.{c,h}: + Add a context menu to the chooser dialog with a "Remove Launcher" + item, which allows to remove previously added (user-created) + application launchers from the mime database. Bug #1814. + * docs/reference/thunar-vfs/: Update the API documentation. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-05-15 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.h: Add convenience macro thunar_file_dup_uri(). + * thunar/thunar-ice.{c,h}, thunar/thunar-session-client.{c,h}, + thunar/main.c, thunar/Makefile.am, configure.in.in: Add session + management support, based on XSM. Bug #1415. + +2006-05-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job.c: Fix compile warning. Bug #1756. + +2006-05-11 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Check for both libpng.pc and libpng12.pc. + +2006-05-08 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-user.c(thunar_vfs_user_manager_get_all_groups): + Properly rewind/close the groups database before iterating over the + groups. Bug #1772. + +2006-05-07 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Allow dropping URLs from web browsers + to a file manager window, which results in popping up the "Create + Link" dialog in the appropriate folder. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-05-07 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-uca/thunar-uca-editor.c + (thunar_uca_editor_icon_clicked): Use + gtk_file_filter_add_pixbuf_formats(). + * THANKS: Update translator credits. + +2006-05-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-buttons.c + (thunar_location_buttons_action_create_folder): Fix double unref. + +2006-05-04 Daichi Kawahata <daichi@xfce.org> + + * configure.in.in, docs/manual/Makefile.am, docs/manual/ru/Makefile.am, + docs/manual/ru/Thunar.xml.in, docs/manual/ru/images/Makefile.am, + po-doc/LINGUAS, po-doc/ru.po: Import initial Russian translations by + Andrey Fedoseev <andrey.fedoseev@gmail.com>, Maxim Zenin + <webmechanics@gmail.com>. + +2006-05-02 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-cleaner.c: Apply patch from Oliver + Lehmann <oliver@freebsd.org> to fix compilation on older FreeBSD + systems. + +2006-05-02 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Don't set G_DISABLE_DEPRECATED. + * thunar-vfs/thunar-vfs-monitor.c: Fix compilation with older gcc + releases. + +2006-05-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c: Handle Tab key properly when the comple- + tion popup window is shown. + * thunar/thunar-path-entry.c: Popup the completion window when the + Tab key is pressed. Bug #1745. + +2006-05-01 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-apr/thunar-apr-desktop-page.c + (thunar_apr_desktop_page_save), + thunar-vfs/thunar-vfs-info.c(thunar_vfs_info_rename): Avoid race + condition between g_file_set_content() and inotify. Bug #1701. + +2006-05-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c(thunar_path_entry_activate): Activate if + only a single item matches. Bug #1747. + +2006-05-01 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job.c: Fix a possible race condition when emit- + ting signals from another thread, and make sure the prepare source + method doesn't return -1 for the timeout if the source is ready to + be dispatched. Bug #1743. + +2006-04-30 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-apr/thunar-apr-desktop-page.c: Use g_access() on Win32. + * plugins/thunar-apr/thunar-apr-private.{c,h}, + plugins/thunar-apr/thunar-apr-abstract-page.c, + plugins/thunar-apr/Makefile.am: Properly initialize the i18n support + for the Advanced Properties plugin. + * plugins/thunar-uca/thunar-uca-private.{c,h}, + plugins/thunar-uca/thunar-uca-provider.c, + plugins/thunar-uca/Makefile.am: Properly initialize the i18n support + for the User Customizable Actions plugin. + +2006-04-26 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-folder.c: No need to reset the folder in the dispose() + method, instead we can do that when finalize() is called. + * thunar/thunar-standard-view.c + (thunar_standard_view_set_current_directory): Resetting the folder + for the model with a view connected can take a lot of time, so we + temporarily disconnect the model from the view while resetting the + folder. + +2006-04-26 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.c(thunar_file_accepts_drop): Ups, no need to check + the suggested action twice. + +2006-04-26 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.c(thunar_file_accepts_drop): Be a bit smarter in + guessing the default action for a folder drop operation. For example + it will default to move now if both the source and the target are on + the same disk and the user owns the source files. + * NEWS: Update news. + +2006-04-25 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job.c: Improve the asynchronous job handling to + avoid two possible race conditions. In addition, jobs are launched + instantely now, instead of having to wait for the next main loop + iteration. + +2006-04-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c: Improve the properties dialog. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-04-24 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb-pixbuf.{c,h}, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs-thumb.c: Improve the GdkPixbuf fallback thumb- + nail generator. Bug #1703. + +2006-04-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c, thunar/thunar-permissions-chooser.c: Revert + typos. The whole change didn't make sense at all. + +2006-04-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_action_delete): + Fix typo. + * docs/README.thunarrc: Add link to "Advanced Settings" page on the + project wiki. + * docs/Makefile.am, docs/README.gtkrc, thunar/thunar-compact-view.c, + thunar/thunar-abstract-icon-view.c: Add style properties "row-spacing" + and "column-spacing" to ThunarAbstractIconView to allow customizing + the spacings in the icon/compact views. Bug #1698. + +2006-04-24 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.c, thunar-vfs/thunar-vfs-link-job.c, + thunar-vfs/thunar-vfs-mime-cache.c, thunar-vfs/thunar-vfs-scandir.c, + thunar-vfs/thunar-vfs-mime-database.c, thunar-vfs/thunar-vfs-thumb.c, + thunar-vfs/thunar-vfs-transfer-job.c, thunar-vfs/thunar-vfs-xfer.c, + thunar-vfs/thunar-vfs-unlink-job.c, configure.in.in: Properly use GLib + replacements for POSIX functions on Windows. Properly check whether + symlinks and named pipes are supported on the target platform. + * thunar-vfs/thunar-vfs-types.h, thunar-vfs/thunar-vfs-info.c, + thunar/thunar-file.{c,h}: Determine the real access permissions + for files and add them as flags to the ThunarVfsInfo, instead of + guessing them from the mode and the uid/gid. Bug #1670. + * docs/reference/thunar-vfs/tmpl/thunar-vfs-types.sgml: Update API docs. + +2006-04-24 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.c: No need to cache inode/symlink, as users + file systems shouldn't be full of broken links. + +2006-04-23 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c, thunar/thunar-permissions-chooser.c, + thunar/thunar-standard-view.c: Use indirect string passing for + gtk_message_dialog_new() in case the strings (i.e. filenames) + contain printf() parameter specifications. Bug #1704. + +2006-04-23 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c: Add reload keyboard shortcuts to + the properties dialog. Bug #1674. + +2006-04-23 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-folder.c(thunar_folder_finished): Finally fix the + merging step when reloading the folder content. + +2006-04-23 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-tree-view.c: Allow to delete folders in the tree view + using the context menu or the usual keyboard shortcuts. Bug #1712. + * thunar/thunar-folder.c: Do not try to process the new files before + the job finishes. This fixes a possible race condition. + * thunar/thunar-window.c: Go to the parent folder when the current + directory is deleted. + +2006-04-20 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.c(_thunar_vfs_info_new_internal): Be sure + to check names extracted from the .desktop file first before passing + them to thunar_vfs_mime_database_get_info_for_name(). Bug #1696. + +2006-04-20 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-create-dialog.c(thunar_create_dialog_set_filename): + Properly select the whole filename in the create dialog if it + doesn't contain a dot. Bug #1679. + +2006-04-19 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-buttons.c: Add "Properties" to the path bar + context menu. Bug #1675. + * thunar/thunar-location-button.c(thunar_location_button_set_file): Watch + folders in the path bar for changes. Bug #1686. + +2006-04-19 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-size-label.c: Add possibility to stop calculating the + folder size in the properties dialog by clicking on the animated + throbber. Bug #1673. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-04-19 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Check for paths.h. + * plugins/thunar-uca/thunar-uca-model.c: Run the action commands using + the bourne shell (or the systems replacement), so environment variables + and backticks can be used. + * NEWS: Update NEWS. + +2006-04-18 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dialogs.c(thunar_dialogs_show_about): Use (translatable) + license GPL text provided by libxfce4util. + +2006-04-17 Benedikt Meurer <benny@xfce.org> + + * docs/manual/es/Thunar.xml.in, po-doc/es.po: Update spanish + translations by José M <josem88@gmail.com>. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Post-release version bump. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * === Released 0.3.0beta1 === + * configure.in.in: Bump version. + * configure.in.in, README: Depend on libexo 0.3.1.6beta1. + * Makefile.am, configure.in.in, Thunar.spec.in: Add RPM spec file for + Thunar. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * thunar/main.c(main): Use g_print() instead of g_printf() to print + the version information. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * docs/manual/es/, docs/manual/fr/, configure.in.in, + docs/manual/Makefile.am: Apply Daichi's patch to properly build + and install the spanish and french translations of the user manual. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * po-doc/LINGUAS, po-doc/fr.po, docs/manual/fr/Thunar.xml.in: Import + initial french translations for the user manual by + josem <josem88@gmail.com>. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * po-doc/LINGUAS, po-doc/fr.po, docs/manual/fr/Thunar.xml.in: Import + initial french translations for the user manual by Stephane + Roy <sroy@j2n.net>. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * po/Thunar.pot, po/*.po: Updated. + * po/de.po: Update german translations. + * po-doc/Thunar.pot, po-doc/*.po, docs/manual/ja/Thunar.xml.in: Updated. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c: Bind "zoom-reset" to Ctrl+KP_0 and + Ctrl+KP_Insert. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * docs/manual/C/Thunar.xml.in: Update documentation date. + * TODO: Clean up TODO. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * docs/reference/thunar-vfs/tmpl/thunar-vfs-types.sgml: Update API + docs. + * icons/16x16/Makefile.am: stock/generic is no longer present in + hicolor, use stock/navigation instead. + +2006-04-16 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Update PACKAGE_BUGREPORT. + * thunar/main.c: Add --version switch. + +2006-04-15 Benedikt Meurer <benny@xfce.org> + + * po/LINGUAS, po/he.po: Import initial hebrew translations by Yo'av + Moshe <bjesus@gmail.com>. + * THANKS: Add translator credits for Yo'av Moshe <bjesus@gmail.com>. + +2006-04-15 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_drag_scroll_timer): + Add support for horizontal drag-scrolling in the compact list view. + +2006-04-14 Benedikt Meurer <benny@xfce.org> + + * Thunar-folder-handler.desktop.in.in: Use a more specific Name, as + suggested by Jaap Karssenberg. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-04-14 Benedikt Meurer <benny@xfce.org> + + * po/de.po: Update german translations, thanks to Fabian Nowak and + Jannis Pohlmann. + +2006-04-14 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-apr/thunar-apr-desktop-page.c + (thunar_apr_desktop_page_save): Fix invalid parameter to fopen() in + GTK+ 2.6 codepath. + +2006-04-14 Benedikt Meurer <benny@xfce.org> + + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-04-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-preferences-dialog.c: Add "Compact List View" to the + preferences dialog. + +2006-04-14 Benedikt Meurer <benny@xfce.org> + + * docs/README.thunarrc, thunar/thunar-preferences.c: Add new option + LastCompactViewZoomLevel. + * thunar/thunar-abstract-icon-view-ui.xml, thunar/Makefile.am, + thunar/thunar-abstract-icon-view.{c,h}, thunar/thunar-window.c + thunar/thunar-compact-view.{c,h}, thunar/thunar-window-ui.xml, + thunar/thunar-icon-view.{c,h}: Add a "Compact View", which uses + ExoIconView with EXO_ICON_VIEW_LAYOUT_COLS layout mode. Based on + patches from Matt McClinch <mattmcclinch@gmail.com>. + * THANKS: Add Matt McClinch. + * po/POTFILES.in: Add new files. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-04-12 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-apr/, acinclude.m4, plugins/Makefile.am, + configure.in.in: Import the "Advanced Properties" plugin. + * README: Add note about optional pcre and libexif dependencies. + * po/POTFILES.in: Add new files. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-04-11 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-deep-count-job.c + (thunar_vfs_deep_count_job_status_ready): Be sure to use 64bit + unsigned integers for the time comparison. Fix another typo. + * plugins/thunar-uca/thunar-uca-plugin.c(thunar_extension_initialize): + Fix typo. + * thunar-vfs/thunar-vfs-info.c: Try to identify malicious .desktop + files that try to look like a regular document. + +2006-04-09 Benedikt Meurer <benny@xfce.org> + + * icons/Makefile.am: Be sure to run gtk-update-icon-cache after + installing new icons into the hicolor icon theme (skipped if $DESTDIR + is set). + +2006-04-09 Benedikt Meurer <benny@xfce.org> + + * docs/README.thunarrc, thunar/thunar-preferences.c: Add new option + "MiscSingleClickTimeout", which specifies the delay after which + items are automatically selected in single-click mode. + * thunar/thunar-preferences-dialog.c(thunar_preferences_dialog_init): + Add "MiscSingleClickTimeout" setting to the preferences dialog. + * thunar/thunar-standard-view.c(thunar_standard_view_constructor): + Apply global single-click timeout setting to the view. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-04-08 Benedikt Meurer <benny@xfce.org> + + * *.desktop.in.in: It's a FileManager. + +2006-04-08 Benedikt Meurer <benny@xfce.org> + + * po/de.po: Improve german translations, based on suggestions by + Fabian Novak. + +2006-04-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-buttons.c: Add "Create Folder" action to the + path bar button context menu. + +2006-04-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-renamer-dialog.c: Fix tooltips for "add-files" and + "remove-files" as pointed out by Jari Rahkonen. + * po/Thunar.pot, po/*.po: Merge changed strings. + * po/de.po: Update german translations. + +2006-04-05 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.c, thunar-vfs/thunar-vfs-types.h, + thunar/thunar-file.c(thunar_file_get_mode_string): Add support for + special Solaris file types (doors and event ports). + +2006-04-05 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.c(thunar_vfs_info_get_free_space): Use + statvfs() on Solaris. + * thunar-vfs/thunar-vfs-scandir.c: Solaris also lacks dirfd(). + * plugins/thunar-uca/thunar-uca-model.c(thunar_uca_model_item_reset): + Use memset() instead of bzero(). + +2006-04-04 Benedikt Meurer <benny@xfce.org> + + * docs/manual/ja/Thunar.xml.in: Update the docbook version of the + japanese user manual. + +2006-04-04 Benedikt Meurer <benny@xfce.org> + + * po-doc/ja.po: Update japanese translations for the user manual, + Daichi Kawahata <daichi@xfce.org>. Bug #1366. + +2006-04-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_get_statusbar_text): + Include a size summary in the statusbar text if no items are + selected as suggested by Fabian Novak. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-04-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-tree-model.{c,h}, thunar/thunar-tree-view.c: Add + removable volumes to the tree view. Bug #1636. + * po/Thunar.pot, po/*.po: Update translations. + +2006-04-03 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_class_init): Shift + Delete/KP_Delete now also emits "delete-selected-files". Bug #1631. + +2006-03-31 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_file_changed): Do not + re-sort the model unless the name of the file (and thereby its + position) has changed. Greatly improves the performance of the + internal bulk renamer. + * thunar/thunar-list-model.c(thunar_list_model_sort): Reuse the memory + of the sort_array for new_order to reduce stack usage with large + folders. + +2006-03-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-folder.c: Reload the folder when the corresponding + file changes. Use the ThunarFileMonitor to stay informed about + changes to the corresponding rather than connecting additional + signal handlers to the file. + * plugins/thunar-uca/thunar-uca-provider.c: Schedule a "changed" + event for the working directory once the custom command + terminates. Bug #1625. + +2006-03-28 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Check for limits.h and localeconv(). + * thunar/thunar-size-label.c: Format the size summary string properly + according to the current locale. + +2006-03-28 Benedikt Meurer <benny@xfce.org> + + * docs/README.thunarrc, thunar/thunar-preferences.c: Add new hidden + setting MiscCaseSensitive, which controls whether sorting is done + in a case-sensitive manner. + * configure.in.in: Check for strcoll(). + * thunar/thunar-file.{c,h}: Add thunar_file_compare_by_name(), which + implements a rather complex but very efficient and smart comparison + function for file names. + * thunar/thunar-tree-model.c(thunar_tree_model_cmp_array): Use + thunar_file_compare_by_name() here. + * thunar/thunar-list-model.{c,h}: Add "case-sensitive" property and + use thunar_file_compare_by_name(). + * thunar/thunar-standard-view.c(thunar_standard_view_init): Synchronize + the "misc-case-sensitive" preference with the "case-sensitive" pro- + perty of the list model. + * thunar/thunar-tree-model.{c,h}: Add "case-sensitive" property and + synchronize with the global "misc-case-sensitive" preference. + +2006-03-26 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-xfer.c(thunar_vfs_xfer_copy_regular): Use a + better error message for the case that the target file already + exists. + * thunar/thunar-progress-dialog.c(thunar_progress_dialog_ask): Improve + the confirmation dialog as suggested by Fabian Novak. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations, thanks to Fabian Novak. + +2006-03-26 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c: Add support for gnome-mount based + on an initial patch by Roman Moravcik <roman.moravcik@gmail.com>. + +2006-03-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c + (thunar_standard_view_action_select_by_pattern): Fix the appearance + of the "Select by Pattern" dialog. + * thunar/thunar-renamer-dialog.c: Need to grab a reference on the + ThunarIconFactory instance for the screen of the dialog, else the + standalone dialog will not generate thumbnails properly. + * plugins/thunar-sbr/thunar-sbr-enum-types.c + (thunar_sbr_register_enum_types): Improve the offset mode labels. + * plugins/thunar-sbr/: Import the last pending renamer, the "Numbering" + renamer. Bug #1609. + * po/POTFILES.in: Add new files. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-03-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c: Add F9 shortcut to toggle the visibility of + the side pane. Bug #1568. + +2006-03-25 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-deep-count-job.{c,h}, + thunar-vfs/thunar-vfs-types.h, thunar-vfs/thunar-vfs.{c,h}, + thunar-vfs/thunar-vfs.symbols: Allow caller to specify whether the + ThunarVfsDeepCountJob should follow symlinks to folders. Bug #1606. + * thunar/thunar-size-label.c(thunar_size_label_file_changed): Do not + follow symlinks when calculating the size of folders. Bug #1606. + +2006-03-25 Benedikt Meurer <benny@xfce.org> + + * Thunar.desktop.in.in(Exec): Support dragging files and folders to + the Thunar application icon, which will then be opened using Thunar. + +2006-03-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-renamer-dialog.c: Add support for dropping files to the + bulk rename dialog. Bug #1605. + +2006-03-24 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-marshal.list: Add a marshaller for the + "status-ready" signal for the upcoming ThunarVfsDeepCountJob. + * thunar-vfs/thunar-vfs.{c,h}, thunar-vfs/thunar-vfs.symbols, + thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs-deep-count-job.{c,h}: + Add ThunarVfsDeepCountJob, which calculates the number of items and + the total size of the items in a given directory. Bug #1603. + * thunar/Makefile.am, thunar/thunar-size-label.{c,h}, + thunar/thunar-properties-dialog.c: Add ThunarSizeLabel widget class, + which handles the ThunarVfsDeepCountJob and displays the total size + of a file for the properties dialog. Bug #1603. + * thunar/thunar-gtk-extensions.c: Make sure tooltips are shown for + the toolbar items. Bug #1593. + * po/POTFILES.in: Add new files. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-03-24 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-sbr/thunar-sbr-case-renamer.h, + plugins/thunar-sbr/thunar-sbr-insert-renamer.h, + plugins/thunar-sbr/thunar-sbr-remove-renamer.h, + plugins/thunar-sbr/thunar-sbr-replace-renamer.h: Fix typos. + * docs/reference/thunarx/tmpl/thunarx-file-info.sgml, + thunarx/thunarx-file-info.c: Register the "changed" and "renamed" + signals right after the type is registered. This way gtk-doc will + properly display the signals (gtk-doc doesn't invoke base_init() for + interfaces). Bug #1418. + * docs/reference/thunarx/tmpl/thunarx-property-page-provider.sgml, + docs/reference/thunarx/tmpl/thunarx-property-page.sgml, + thunarx/thunarx-property-page-provider.c: Properly document + ThunarxPropertyPage and ThunarxPropertyPageProvider. Bug #1456. + +2006-03-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-renamer-progress.{c,h}: Add new helper method + thunar_renamer_progress_running(), which tells whether the rename + operation is currently in progress. + * thunar/thunar-renamer-dialog.c(thunar_renamer_dialog_response): Fix + the Cancel/Close button handling. + * examples/nautilus-bulk-rename.py, examples/Makefile.am: Add an ex- + ample how to use Thunar Bulk Rename as Nautilus extension. Bug #1597. + +2006-03-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.{c,h}: Add wrapper method thunar_file_get_for_uri() + which is a rather common operation. + * thunar/thunar-dbus-service.c + (thunar_dbus_service_parse_uri_and_display): Use the newly added + method thunar_file_get_for_uri(). + * thunar/thunar-launcher.c: If no current directory is set, directories + will always be opened in new windows. + * thunar/thunar-renamer-progress.{c,h}: Add support for explicit + cancellation of the rename operation. + * thunar/thunar-renamer-dialog-ui.xml,thunar/thunar-renamer-model.{c,h}, + thunar/thunar-renamer-dialog.{c,h}, thunar/Makefile.am: Some polish on + the dialog and the model. Allow users to add/remove files using the + context menu. Add a standalone mode in which the bulk rename dialog + appears as standalone application and which can be invoked through the + D-BUS service. Bug #1597. + * thunar/thunar-standard-view.c(thunar_standard_view_action_rename): + Keep up with the ThunarRenamerDialog changes. + * thunar/main.c, thunar/thunar-application.{c,h}, + thunar/thunar-dbus-client.{c,h}, thunar/thunar-dbus-service-infos.xml, + thunar/thunar-dbus-service.c: Add BulkRename() method to the D-BUS + interface org.xfce.Thunar and add command line option -B to Thunar, + which allows to open the bulk rename dialog directly. Bug #1597. + * Thunar-folder-handler.desktop.in.in, Thunar.desktop.in.in, + Makefile.am: Rearrange the .desktop file handling. + * Makefile.am, Thunar-bulk-rename.desktop.in.in, ThunarBulkRename.in: + Add launcher for the bulk rename utility. Bug #1597. + * examples/thunar-file-manager.py, examples/Makefile.am: Add example + for the usage of the org.xfce.Thunar interface. + * thunarx/thunarx-renamer.{c,h}, thunarx/thunarx.symbols: Add new method + get_actions() to ThunarxRenamer, as discussed with Jannis, to allow + plugin writers to add custom actions to the renamers tree view + context menu (i.e. "Edit Tags" for the thunar-media-tag-plugin). First + part of bug #1602. + * docs/reference/thunarx/: Update the API docs. + * thunar/thunar-renamer-dialog.c(thunar_renamer_dialog_context_menu), + thunar/thunar-renamer-dialog-ui.xml: Add custom actions provided by + the active ThunarxRenamer to the file context menu in the renamer + dialog. Second part of bug #1602. + * po/POTFILES.in: Add new files. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-03-23 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dialogs.c, thunar/thunar-window.{c,h}: Move the generic + parts of the about dialog to thunar-dialogs.c. + * thunar/thunar-properties-dialog.c + (thunar_properties_dialog_update_providers): Fix missing + gtk_widget_show() for the provided pages. + +2006-03-22 Benedikt Meurer <benny@xfce.org> + + * docs/reference/thunarx/tmpl/thunarx-renamer.sgml: Fix a typo. + * thunar/thunar-renamer-model.c: Only invalidate items on "file-changed" + signals if the file changed on the disk, to avoid invalidating items + constantly while generating thumbnails. + * thunar/thunar-gobject-extensions.c: Register a transformation func- + tion string->uint. + * plugins/thunar-sbr/thunar-sbr-case-renamer.c + (thunar_sbr_case_renamer_new): More consistent naming scheme for the + renamer titles. + * plugins/thunar-sbr/: Import additional renamers "Insert / Overwrite" + and "Remove Characters". Bug #1599. + * po/POTFILES.in: Add new files. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-03-22 Benedikt Meurer <benny@xfce.org> + + * docs/reference/thunarx/: Update the thunarx API documentation. 100% + symbol docs coverage! + +2006-03-21 Benedikt Meurer <benny@xfce.org> + + * plugins/thunar-uca/README: Fix typos. + * thunarx/thunarx-private.{c,h}: Import new helper function + thunarx_param_spec_get_option_name(). + * thunarx/Makefile.am, thunarx/thunarx.h, thunarx/thunarx-renamer.{c,h}, + thunarx/thunarx-renamer-provider.{c,h}, thunarx/thunarx.symbols: + Merge the ThunarxRenamer extension point, which can be used to hook + additional bulk renamers into Thunar. Bug #1416. + * thunar/thunar-renamer-dialog.{c,h}, thunar/thunar-renamer-model.{c,h}, + thunar/thunar-renamer-pair.{c,h},thunar/thunar-renamer-progress.{c,h}, + thunar/Makefile.am, thunar/thunar-standard-view.c: Merge the bulk + rename framework for Thunar, which uses the ThunarxRenamers to + rename multiple files at once. Bug #1416. + * acinclude.m4, configure.in.in, plugins/thunar-sbr/, + plugins/Makefile.am: Merge stable version of the thunar-sbr exten- + sion ("Simple Builtin Renamers"), which provides "Search & Replace", + which optionally uses PCRE to support regular expressions, and + "Convert upper/lowercase". Additional renamers will be merged once + ready. Bug #1416. + * po/POTFILES.in: Add new files. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-03-21 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-gobject-extensions.c + (thunar_g_initialize_transformations): Register one string->enum + transformation function that is used by all GEnum derived types. + * thunar/thunar-enum-types.{c,h}: Import ThunarRenamerMode enum. Don't + need to register a transformation for each and every enum type. + * thunar/thunar-preferences.c(thunar_preferences_class_init), + thunar/main.c(main): Initialize the additional GType transformations + on startup, rather than in the ThunarPreferences class constructor. + +2006-03-20 Benedikt Meurer <benny@xfce.org> + + * Makefile.am, acinclude.m4, configure.in.in, po/POTFILES.in, + po/Thunar.pot, plugins/: Move thunar-uca to plugins/. + +2006-03-20 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Render + the icon properly when the widget state is insensitive. + +2006-03-18 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-xfer.c: Make sure the user can always read and + write copied directories. + +2006-03-16 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume.c(thunar_vfs_volume_lookup_icon_name): + Fix typo, s/gnome-dev-dvdrom/gnome-dev-disc-dvdrom/. + +2006-03-16 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-tree-view.c: gtk_tree_view_get_visible_range() is only + available in GTK+ 2.8 and above. + +2006-03-16 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-xfer.c: Also chmod u+rw the target file if we + are not the owner of the source file. + * thunar-vfs/thunar-vfs-path.c(thunar_vfs_path_to_uri): Double checking + bufsize doesn't make much sense. + +2006-03-16 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c: Add backspace as shortcut for "Back". + * thunar/thunar-application.c: Save accelerators on exit and restore + them on startup. This way users can customize all shortcuts to their + needs and Thunar will remember those shortcuts. + * FAQ, docs/manual/C/Thunar.xml.in: Update the documentation. + * po-doc/Thunar.pot, po-doc/*.po: Merge new strings. + +2006-03-16 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-buttons.c, thunar/thunar-standard-view-ui.xml, + thunar/thunar-standard-view.c: Yet another attempt to set appropriate + labels/tooltips for the cut/copy/paste actions. Cut/copy/paste in file + manager is really different to other applications, not the actual data + is stored in the clipboard, but only the location where to find the + data. + * thunar/thunar-tree-view.c: Add drop site support and clipboard + actions. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. Use "Ordner" instead of + "Verzeichnis" to be consistent with the shared-mime-info and Gtk+ + translations. + +2006-03-15 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-debug.{c,h}, thunar/Makefile.am: Add THUNAR_DEBUG_MARK() + which can be used to easily profile parts of Thunar. + +2006-03-15 Benedikt Meurer <benny@xfce.org> + + * acinclude.m4(BM_THUNAR_VFS_VOLUME_IMPL): Handle "none" properly. + * thunar-vfs/thunar-vfs-volume-manager.c, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs-volume-private.h, thunar-vfs/thunar-vfs.symbols, + thunar-vfs/thunar-vfs-volume.c, thunar-vfs/thunar-vfs-volume-none.c, + thunar-vfs/thunar-vfs-volume.h, thunar-vfs/thunar-vfs-volume-hal.c, + thunar-vfs/thunar-vfs-volume-freebsd.c: Improve the volume manager + implemenation. The ThunarVfsVolumeManager and ThunarVfsVolume inter- + faces are now abstract base classes, with the implementation API + completely separated from the public API. The HAL backend was fixed + to work around a strange HAL bug, where 'volume.is_mounted' is FALSE + for mounted volumes (instead of trusting HAL, we ask the kernel to + make sure we always display the proper state). Also, new signals + "mounted", "pre-unmount" and "unmounted" were added to both + ThunarVfsVolume and ThunarVfsVolumeManager, to allow applications to + perform certain actions for these events. + * docs/reference/thunar-vfs/: Update the API documentation. + * thunar/thunar-window.c: Whenever the user requests to unmount a + volume, check if the window displays a folder on this volume and if + so, go to the home folder, to make sure we don't display a probably + no longer existing mount point afterwards. + +2006-03-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-exec.{c,h}: Add thunar_vfs_exec_sync() helper + function. + * thunar-vfs/thunar-vfs-volume-freebsd.c: Use thunar_vfs_exec_sync(). + +2006-03-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c(thunar_details_view_zoom_level_changed): + Fix bug in Gtk+ 2.6 version of this method. + +2006-03-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-path.{c,h}, thunar-vfs/thunar-vfs.symbols: Add + convenience method thunar_vfs_path_is_ancestor(), used to implement + the auto-expand in the tree pane. + * docs/reference/thunar-vfs/: Update thunar-vfs API docs. + * thunar/thunar-file.h: Add thunar_file_is_ancestor(). + * docs/README.thunarrc, thunar/thunar-preferences.c, + thunar/thunar-window.c: Add new preference LastSeparatorPosition, + which includes the last position of the gutter that separates the + side pane and the main view. + * docs/README.thunarrc, thunar/thunar-preferences.c, + thunar/thunar-preferences-dialog.c: Add new preferences + TreeIconEmblems and TreeIconSize, similar to their shortcuts + counterparts. + * thunar/thunar-tree-model.{c,h}, thunar/thunar-tree-pane.{c,h}, + thunar/thunar-tree-view.{c,h}, thunar/Makefile.am, + thunar/thunar-window-ui.xml, thunar/thunar-window.c: Initial import + of the tree side pane. Still missing a lot of features, but the basics + are in place and the performance and memory overhead is quite good + already. Bug #1363. + * po/POTFILES.in: Add new files. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-03-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-util.c: Do not include + <libxfce4util/libxfce4util.h> directly. + +2006-03-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c(thunar_path_entry_init): Always sort + folders before files here, and always include hidden files in the + entry completion. + +2006-03-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_drag_motion): Add + drag scroll support for XDS. + +2006-03-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-button.c(thunar_location_button_init): Fix + misalignment of the file system icon. Reported by Pablo Hdez-M. Saiz + <homeless3d@gmail.com>. + +2006-03-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-permissions-chooser.c + (thunar_permissions_chooser_fixperm_clicked): Forgot to adjust the + mode mask. + +2006-03-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-permissions-chooser.c + (thunar_permissions_chooser_fixperm_clicked): Make sure the owner can + read and enter the folder after fixing folder permissions. + +2006-03-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c(thunar_details_view_init): Use 2px + spacing for the name column. + +2006-03-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-text-renderer.c: Don't setup a fixed height if text + wrapping is enabled. + * po/Thunar.pot, po/*.po: Update translations again. + * po/de.po: Fix typo in german translations. + +2006-03-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-column-editor.c(thunar_column_editor_init): Fix a typo. + +2006-03-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-enum-types.{c,h}, thunar/thunar-list-model.c, + thunar/thunar-path-entry.c: Rename THUNAR_COLUMN_REAL_NAME to + THUNAR_COLUMN_FILE_NAME. + * thunar/thunar-enum-types.{c,h}, thunar/thunar-list-model.c: Add new + list model columns THUNAR_COLUMN_GROUP and THUNAR_COLUMN_OWNER. + * thunar/thunar-enum-types.{c,h}: Divide ThunarColumns into visible and + special columns. + * thunar/thunar-text-renderer.c(thunar_text_renderer_get_size): Improve + guessing the required width for text columns. + * thunar/thunar-text-renderer.c(thunar_text_renderer_set_widget): Set + fixed height for the text render. + * thunar/thunar-preferences.c, docs/README.thunarrc: Add preferences for + the configurable detailed list view columns. Bug #1351. + * thunar/thunar-column-editor.{c,h}, thunar/thunar-column-model.{c,h}, + thunar/Makefile.am: Import ThunarColumnModel and ThunarColumnEditor + classes. The ThunarColumnModel class handles the order, visibility and + fixed widths of columns. The ThunarColumnEditor class provides a + dialog to configure the ThunarColumnModel. Bug #1351. + * thunar/thunar-details-view.{c,h}, thunar/thunar-details-view-ui.xml, + thunar/Makefile.am: Use column order and visibility from the + ThunarColumnOrder. Add "Configure Columns..." menu item to "View", + which pops up the ThunarColumnEditor. For fixed column mode, we use + the fixed height mode provided by GtkTreeView, which speeds up the + detailed list view a lot, esp. with older Pango version. Bug #1351. + * po/POTFILES.in: Add new files here. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update the german translations. + +2006-03-11 Benedikt Meurer <benny@xfce.org> + + * thunar-uca/thunar-uca-editor.c(thunar_uca_editor_command_clicked), + thunar/thunar-chooser-dialog.c(thunar_chooser_dialog_browse): Try to + resolve relative filenames in $PATH. + * thunar/thunar-chooser-dialog.c: Allow users to specify whether or not + an application should become the default for the given MIME type. + * thunar/thunar-chooser-dialog.c: Add tooltips and improve the overall + usability of the chooser dialog. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-03-09 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-view.c: Improve keyboard navigation. Remove + the "Display Icon Emblems" menu item. Bug #1559. + * thunar/thunar-preferences-dialog.c: Add options for the shortcuts pane + to the preferences dialog. Improve the recursive permissions option in + the preference dialog and avoid the term "recursive". + * po/*.po, po/Thunar.pot: Merge new strings. + * po/de.po: Update german translations. + +2006-03-09 Benedikt Meurer <benny@xfce.org> + + * examples/xfce-file-manager.py: Add note about DisplayFolderAndSelect() + to the example. + +2006-03-09 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-view.c: Add support to drop files to folders + listed in the shortcuts pane. Bug #1345. + +2006-03-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-view.{c,h}: Add new methods get_visible_range() and + scroll_to_file(). + * thunar/thunar-standard-view.c: Implement get_visible_range() and + scroll_to_file(). Drop the scroll_offsets, will be handled in + ThunarWindow. + * thunar/thunar-window.{c,h}: Remember the first visible file whenever + leaving a directory and scroll to it when entering the directory + again. + * thunar/thunar-application.{c,h}: Return the created window from the + thunar_application_open_window() method. + * thunar/thunar-dbus-service-infos.xml, thunar/thunar-dbus-service.c: + Add DisplayFolderAndSelect() to the org.xfce.FileManager interface. + File managers that cannot scroll and select to a given file can + silently ignore the filename parameter and handle it like an + invocation of DisplayFolder(). Bug #1553. + +2006-03-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-view.c: Fix shortcut rename. + +2006-03-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-view.c: Always open shortcuts using single + clicks. + +2006-03-08 Benedikt Meurer <benny@xfce.org> + + * thunar-uca/thunar-uca-provider.c: Pass the correct working directory + when launching folder actions. + +2006-03-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c(thunar_properties_dialog_init): + Properly synchronize the dialog title with the name entry box. + * thunar/thunar-file.{c,h}: Add THUNAR_FILE_ICON_STATE_OPEN. + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Use + THUNAR_FILE_ICON_STATE_OPEN for expanded rows. + * thunar/thunar-side-pane.{c,h}, thunar/thunar-shortcuts-pane.c: Add + "show-hidden" property. + +2006-03-07 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-legacy.c: Fix gcc4 warnings. Bug #1556. + * thunar-vfs/thunar-vfs-xfer.c: Prefer statvfs() over statfs() on + systems that provide both. Bug #1556. + +2006-03-07 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-legacy.c: Implement magic handling for + the legacy backend (shared-mime-info <= 0.16). Bug #1106. + +2006-03-07 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-xfer.c: Automatically give write permissions to + regular files and folders copied from read-only media. Bug #1555. + +2006-03-06 Benedikt Meurer <benny@xfce.org> + + * autogen.sh, configure.in.in, po/LINGUAS: Read the set of available + languages from po/LINGUAS and substitute them when autogen.sh is + run. This way we can continue to use glib-gettext. + * docs/manual/, po-doc/, configure.in.in, Makefile.am: Import Daichi's + initial japanese translations for the user manual. + +2006-03-05 Benedikt Meurer <benny@xfce.org> + + * po/POTFILES.in: Add Thunar-folder-handler.desktop.in here. + * po/Thunar.pot, po/*.po: Merge new strings. + +2006-03-05 Benedikt Meurer <benny@xfce.org> + + * Thunar-folder-handler.desktop.in, Makefile.am: Install folder handler + .desktop file for Thunar. This way firefox and thunderbird can use + Thunar to open folders. + +2006-03-05 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Bump version to 0.2.3svn. + +2006-03-05 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Depend on libexo >= 0.3.1.4. + +2006-03-05 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Bump version to 0.2.2alpha2. + * configure.in.in: Bump soname. + +2006-03-05 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-xfer.c, thunar/thunar-preferences-dialog.c: Fix + en_GB words to their american english counterparts. + * po/*.po, po/Thunar.pot: Update translations. + +2006-03-04 Benedikt Meurer <benny@xfce.org> + + * po/de.po: Update german translations. + +2006-03-02 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, thunar/thunar-gdk-pixbuf-extensions.{c,h}, + thunar/thunar-icon-renderer.c: Some of the gdk-pixbuf extensions were + moved to libexo. Use the libexo ones. + +2006-03-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-stock.{c,h}, thunar/thunar-create-dialog.c, + thunar/thunar-standard-view.c: Add stock items THUNAR_STOCK_RENAME + and THUNAR_STOCK_CREATE and use them for the create and rename + dialogs. Bug #1523. + * po/de.po: Fix german translations. + +2006-03-02 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add zh_TW to XDT_I18N(). + * THANKS: Add translator credits for Hydonsingore Cia + <hydonsingore@mail.educities.edu.tw>. + +2006-03-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_get_drop_file): + Allow to drop into full details view. Thunar will accept drops to + the current folder on all non-executable regular files. Bug #1343. + +2006-03-02 Benedikt Meurer <benny@xfce.org> + + * po/de.po: Fix typo. + +2006-03-02 Benedikt Meurer <benny@xfce.org> + + * po/*.po: Previous commit removed the semicolons from the "Recommended + applications" and "Other applications" strings. Update the po files + accordingly. + +2006-03-02 Benedikt Meurer <benny@xfce.org> + + * thunar-uca/thunar-uca-chooser.c(thunar_uca_chooser_init): Fix the + vertical icon alignment. + * thunar-uca/thunar-uca-editor.c(thunar_uca_editor_command_clicked): + Verify that an absolute filename is given. Else GtkFileChooser will + complain. + * thunar-uca/thunar-uca-editor.c(thunar_uca_editor_icon_clicked): Same + story. + * thunar/thunar-dialogs.c, thunar/thunar-dialogs.c, + thunar-uca/thunar-uca-chooser.c, thunar-uca/thunar-uca-provider.c: + "%s." is really not something that must be translated. + * thunar/thunar-chooser-dialog.c, thunar/thunar-chooser-model.{c,h}: Use + bold font for the titles. + * po/Thunar.pot, po/*.po: Update po files. + * po/de.po: Updated the german translations. Thanks to Fabian Nowak + <timystery@arcor.de>. + +2006-03-01 Benedikt Meurer <benny@xfce.org> + + * docs/manual/C/Thunar.xml.in: Add "Frequently Asked Questions". + * thunar/thunar-location-buttons.c(thunar_location_buttons_clicked): + Make sure the new active button is visible on the location button bar. + * ThunarHelp.in, Makefile.am: Add ThunarHelp script, which is used to + display the Thunar user manual. + * thunar/thunar-dialogs.{c,h}, thunar/Makefile.am: Add new helper method + thunar_dialogs_show_help(), which is used to open the documentation + browser. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add "Contents" + item to the "Help" menu. + * thunar/thunar-chooser-button.c(thunar_chooser_button_file_changed): + Fix typo. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Updated the german translations. + +2006-03-01 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, docs/Makefile.am, docs/manual/: Import initial parts + of the user manual. + * HACKING: Update repository URLs. + * docs/README.volumes: Update notes. + +2006-02-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c, thunar/thunar-icon-view.c, + thunar/thunar-standard-view.{c,h}: Remember the scroll offset when + changing directory and apply saved scroll offset once a folder is + loaded again. + +2006-02-27 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c(thunar_path_entry_common_prefix_append): Do + not append a slash for the current directory. Otherwise a slash will + automatically be appended while browsing folders under certain + conditions, and the slash will be selected, but that is not what we + want. + +2006-02-27 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-create-dialog.c(thunar_create_dialog_init): Use "Create" + instead of "Ok" for the button label. + * thunar/thunar-standard-view.c: Add tooltip for the "Paste Files" + action. Update the tooltip for the "Paste Files into Folder" action. + * thunar/thunar-standard-view.c(thunar_standard_view_action_rename): + Use "Rename" instead of "Ok" for the button label. + +2006-02-27 Benedikt Meurer <benny@xfce.org> + + * thunar/main.c, thunar/thunar-application.{c,h}, + thunar/thunar-dbus-client.{c,h}, thunar/thunar-dbus-service-infos.xml, + thunar/thunar-dbus-service.c, po/Thunar.pot, po/*.po: Revert the + previous commit. Lightweight session management won't work for + Thunar, instead XSM should be implemented. Bug #1415. + +2006-02-27 Benedikt Meurer <benny@xfce.org> + + * thunar/main.c, thunar/thunar-application.{c,h}, + thunar/thunar-dbus-client.{c,h}, thunar/thunar-dbus-service-infos.xml, + thunar/thunar-dbus-service.c: Add session management support based on + the ExoXsessionClient class. Bug #1415. + * po/Thunar.pot, po/*.po: Update translations. + +2006-02-26 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_drag_begin): + Release the drag path list, just in case drag_end() wasn't called + before (Gtk+ is somewhat buggy here, but I wasn't able to locate + the bug yet). + * thunar/thunar-window.c(thunar_window_action_location_bar_changed): + Add "reload" button to the toolbar. + * thunar/thunar-shortcuts-view.c, thunar/thunar-details-view.c: Use + ExoTreeView, which provides a tree view with single-click support. + * thunar/thunar-standard-view.c, thunar/thunar-icon-view.c: The internal + widgets now both provide the "single-click" property, so we can + connect it in the ThunarStandardView constructor. + +2006-02-25 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Bump soname. + * thunar-vfs/thunar-vfs-info.{c,h}: Add working_directory parameter to + thunar_vfs_info_execute() to allow xfdesktop to launch applications + with $HOME as working directory, as requested on the xfce mailing + list. Bug #1473. + * docs/reference/thunar-vfs/tmpl/thunar-vfs-info.sgml: Update API docs. + * thunar/thunar-file.c(thunar_file_execute): Update to the new API. + +2006-02-25 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: And of course eu and sv. + * configure.in.in: Set PACKAGE_BUGREPORT to thunar-dev@xfce.org. + +2006-02-25 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: And add fi to XDT_I18N(). + +2006-02-25 Benedikt Meurer <benny@xfce.org> + + * THANKS: Add translator credits for Jari Rahkonen (fi). + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c(thunar_vfs_volume_hal_update): All + volumes provided by USB devices are now marked as removable. + * thunar/thunar-shortcuts-model.c(thunar_shortcuts_model_iter_for_file): + Also check volumes here. + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * thunar-uca/thunar-uca-chooser.c: Fix two typos that already survived + for too long. + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * THANKS: Add translator credits for Piarres Beobide (eu) and Daniel + Nylander (sv). + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c(thunar_details_view_button_press_event), + thunar/thunar-shortcuts-view.c + (thunar_shortcuts_view_button_press_event): Properly verify the event + modifier state according to the default modifier mask. + * thunar/thunar-icon-view.c: Add interactive search capabilities to the + ThunarIconView based on the latest changes to ExoIconView. Bug #1359. + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * autogen.sh: Be sure to run svn info with LC_ALL=C. + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-model.{c,h}, thunar/thunar-shortcuts-view.c: + Make sure the path is still valid when renaming. Update the shortcuts + rename to alter the mode of ThunarTextRenderer, rather than the + "editable" property, which is not valid for ThunarTextRenderer. + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-bar.{c,h}, thunar/thunar-window.c, + thunar/thunar-location-buttons.c, thunar/thunar-location-dialog.{c,h}, + thunar/thunar-location-entry.c, thunar/thunar-standard-view.{c,h}: + Focus the location selector when the user types "/" or "~" into the + main view, to stay compatible with GtkFileChooser. + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c(thunar_window_action_about): Add credits for + Young Hahn <youngjin.hahn@gmail.com> to the about dialog. + * thunar/thunar-preferences.c, docs/README.thunarrc: Add new preference + MiscSingleClick, which controls whether single click navigation + should be used. + * thunar/thunar-preferences-dialog.c(thunar_preferences_dialog_init): + Add single/double-click options to the preferences dialog. + * thunar/thunar-pango-extensions.{c,h}: Add new helper function + thunar_pango_attr_list_underline_single(), which returns a Pango + attribute list for single-underlined text rendering. + * thunar/thunar-text-renderer.c: Add "follow-prelit" property, which + controls whether the text renderer should highlight text using the + single underline attribute when a row/item is highlighted. + * thunar/thunar-details-view.c, thunar/thunar-icon-view.c, + thunar/thunar-shortcuts-view.c, thunar/thunar-standard-view.c: Add + support for single click navigation to the details and icon views, + and also to the shortcuts view. Bug #1396. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-view-ui.xml, thunar/thunar-launcher-ui.xml, + thunar/thunar-shortcuts-pane-ui.xml, thunar/thunar-window-ui.xml, + thunar/thunar-standard-view-ui.xml: Cleanup the ui description files. + * thunar-vfs/thunar-vfs-link-job.c, thunar-vfs/thunar-vfs-util.c, + thunar/thunar-create-dialog.c, thunar/thunar-icon-factory.c, + thunar/thunar-location-entry.c, thunar/thunar-window.c, + thunar/thunar-properties-dialog.c, thunar/thunar-standard-view.c, + thunar-uca/thunar-uca-provider.c: Further string cleanups. + * thunar/thunar-location-bar.{c.h}, thunar/thunar-window.c: + ThunarLocationBar derives from ThunarComponent now, so the location + bar widget is able to add its own custom actions to the ui manager. + * thunar/thunar-location-entry.c: Implement ThunarComponent here. + * thunar/Makefile.am, thunar/thunar-location-buttons-ui.xml, + thunar/thunar-location-buttons.c, thunar/thunar-location-button.c: + Let ThunarLocationButtons handle the menu for ThunarLocationButton + managed by it. Also add a accelerator <Alt>Down for "down-folder", + similar to GtkFileChooser. Bug #1472. + * po/Thunar.pot, po/*.po: Merge new strings. + +2006-02-24 Benedikt Meurer <benny@xfce.org> + + * THANKS, configure.in.in, icons/: Import new Thunar icon, designed by + Young Hahn <youngjin.hahn@gmail.com>. + +2006-02-19 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Turn the side + pane choice(s) into toggle actions and add <control>B as keyboard + accelerator for the shortcuts pane, similar to the way its done in + Firefox. + +2006-02-18 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-button.c: Change icon to "drop icon" while + dragging over a location button that can accept the drop. + * thunar/thunar-location-button.c: Add context menu to the location + buttons as requested on thunar-dev. + +2006-02-18 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-button.c: Set toggle button state to + inconsistent while holding down middle mouse button to give + the user some visual feedback. + +2006-02-18 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-button.{c,h}, thunar/Makefile.am, + thunar/thunar-location-buttons.c: Put the location button stuff into + a new class ThunarLocationButton. + * po/POTFILES.in: Add thunar-location-button.c here. + +2006-02-16 Benedikt Meurer <benny@xfce.org> + + * THANKS: Change Nick's email address as requested. + * thunar-vfs/thunar-vfs-volume-none.h: Properly internalize the + get_type() methods. + +2006-02-15 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-unlink-job.c(thunar_vfs_unlink_job_execute): + Ignore ENOENT errors returned by thunar_vfs_scandir() as well, to + fix the problem with not being able to delete broken links on + Linux. + * thunar/thunar-application.c: Generate unique roles for the Thunar + toplevel windows in preparation of session management support. + * thunar/thunar-dbus-service-infos.xml, thunar/thunar-dbus-service.c: + Add Terminate() method to the org.xfce.Thunar interface, which allows + to properly shutdown a daemon instance. + * thunar/main.c, thunar/thunar-dbus-client.{c,h}: Add -q/--quit command + line option, which terminates a running daemon instance. Also cleanup + the --daemon handling. + +2006-02-15 Benedikt Meurer <benny@xfce.org> + + * FAQ, thunar/thunar-icon-view.c: Add mouse gesture for "Reload" as + "move mouse down". The mouse gesture can still be canceled by placing + the cursor back to its initial position (+/- 40px). + +2006-02-15 Benedikt Meurer <benny@xfce.org> + + * THANKS, thunar-uca/thunar-uca-editor.c: Apply patch provided by + Nick Schermer <nickschermer@gmail.com> to fix a crash in the + thunar-uca plugin if the icon specified for an action cannot + be loaded. Bug #1458. + +2006-02-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-xfer.c, thunar-vfs/thunar-vfs-chmod-job.c, + thunar-vfs/thunar-vfs-chown-job.c: Be more consistent with error + messages. + * thunar/thunar-shortcuts-view.c: Even more consistency. + * thunar/thunar-abstract-dialog.{c,h}, thunar/Makefile.am: Add new + abstract class ThunarAbstractDialog, which overrides GtkDialog::close + and provides additional keybindings for the "close" action. Bug #1380. + * thunar/thunar-chooser-dialog.c, thunar/thunar-create-dialog.c, + thunar/thunar-location-dialog.c, thunar/thunar-preferences-dialog.c, + thunar/thunar-properties-dialog.c: Derive from ThunarAbstractDialog, + so all dialogs/windows in Thunar can be closed using the same + keyboard shortcuts and people can customize these shortcuts using + the standard GtkBindingSet mechanism. Bug #1380. + * po/Thunar.pot, po/*.po: Update translations. + * po/de.po: "Gerät auswerfen" is probably not the best translation + for "Eject Volume". ;-) + * po/de.po: Even more love for the german translation. + +2006-02-14 Benedikt Meurer <benny@xfce.org> + + * icons/16x16/Makefile.am, icons/16x16/stock_thunar-group.png, + icons/16x16/stock_thunar-user.png: Remove the "thunar-user" and + "thunar-group" stock icons. + * thunar/thunar-permissions-chooser.c, thunar/thunar-stock.{c,h}: Do + not display "thunar-user" and "thunar-group" stock icons in the + permissions chooser any more, as it makes the dialog look busy. + +2006-02-14 Benedikt Meurer <benny@xfce.org> + + * acinclude.m4, configure.in.in: Print build configuration summary. + +2006-02-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.c(thunar_file_get_emblem_names): Use "cant-write" + emblem for non-writable files owned by the user, to make it obvious + why an application will not be able to save the file (unless the + application uses a write to temporary, rename, unlink temporary + procedure). + * thunar/thunar-location-buttons.c(thunar_location_buttons_forall): Do + not include the slider buttons unless include_internals is TRUE. + * thunar/thunar-location-buttons.c: Remove buttons from the path bar + whenever a displayed directory is deleted. Bug #1451. + +2006-02-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-creat-job.c, thunar-vfs/thunar-vfs-info.c, + thunar-vfs/thunar-vfs-mkdir-job.c, + thunar-vfs/thunar-vfs-transfer-job.c, + thunar-vfs/thunar-vfs-unlink-job.c, + thunar-vfs/thunar-vfs-volume-hal.c, thunar/thunar-dnd.c, + thunar/thunar-gdk-extensions.c, thunar/thunar-preferences.c: Cleanup + error messages. + * po/Thunar.pot, po/*.po: Update translations. + +2006-02-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c: Pass NULL for error on first + attempt to launch pumount. + * thunar/thunar-folder.c: Properly merge the current files with the + previous files when reloading the folder content. This finally fixes + bug #1457. + +2006-02-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c: Fallback to mount/umount if + pmount is not available. Requires fstab-sync to synchronize with HAL + volumes. + +2006-02-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c: Work-around HAL bug #5279, where + the UDIs array returned by libhal_drive_find_all_volumes() is not + properly NULL-terminated. + +2006-02-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-model.c: Include non-removable volumes in + the list of hidden volumes. + * thunar-vfs/thunar-vfs-volume-hal.c: Determine the volumes from the + drives on startup, instead of FindDeviceByCapability(volume), as + that seems to be what GNOME does. Maybe one day, there'll be a + usable HAL documentation, and hardware will really just work. + +2006-02-13 Benedikt Meurer <benny@xfce.org> + + * acinclude.m4, configure.in.in, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs-volume-hal.c, thunar-vfs/thunar-vfs-volume.c, + thunar-vfs/thunar-vfs-volume-freebsd.{c,h}, + thunar-vfs/thunar-vfs-volume-none.{c,h}: Do not use AC_CONFIG_LINKS() + anymore and let the user select it's preferred volume manager using + the --with-volume-manager configure switch. + * po/POTFILES.in: Update file list. + * po/Thunar.pot, po/*.po: Update translations. + +2006-02-13 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-hal.c: Properly update volume state + after eject and unmount. + * README: List optional HAL dependency. + +2006-02-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dbus-service.c: Print a warning to stderr, instead of + using g_warning() if unable to connect to the session bus. + * configure.in.in, thunar-vfs/thunar-vfs-volume-hal.c: Update to use + HAL 0.5.x API. + +2006-02-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-folder.c(thunar_folder_reload): Properly cancel any + previous job to make sure it will terminate as soon as possible. + Bug #1457. + +2006-02-13 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.c(_thunar_vfs_info_new_internal): Fix + typo in hidden file detection. + * thunar-vfs/thunar-vfs-volume.{c,h}: Add a few new volume types. + * docs/reference/thunar-vfs/tmpl/thunar-vfs-volume.sgml: Update API + docs. + * thunar-vfs/thunar-vfs-volume-hal.{c,h}, thunar-vfs/Makefile.am, + configure.in.in: Import the Linux/HAL implementation of the volume + manager. It's still a bit rough, but it seems to work ok. Works only + with pmount-hal currently, but that shouldn't be a problem. Bug #999. + * thunar/thunar-shortcuts-model.c: Handle the addition/removal of + volumes and do not open a file for volume shortcuts as that may + prevent the volume from being unmounted properly. + * thunar-vfs/thunar-vfs-volume.c: Setup a watch cursor on the given + window when ejecting, mounting or unmounting a volume, so the user + gets some feedback during the time it takes to perform the operation. + * po/POTFILES.in: Add new file. + * po/Thunar.pot, po/*.po: Merge new strings. + +2006-02-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-enum-types.{c,h}, thunar/thunar-list-model.h: Rename + ThunarListModelColumn to ThunarColumn and add an enum type for it. + * thunar/thunar-details-view.c, thunar/thunar-icon-view.c, + thunar/thunar-list-model.c, thunar/thunar-path-entry.c: Use the new + ThunarColumn enum type. + * thunar/thunar-gobject-extensions.c: Add transformation function for + GtkSortType to string. + * thunar/thunar-preferences.c, docs/README.thunarrc: Add LastSortColumn + and LastSortOrder preferences, which contain the last selected sort + settings. Bug #1342. + * thunar/thunar-standard-view.c: Apply default sort settings on con- + struction and save new defaults whenever the sort settings are + changed by the user. Bug #1342. + * po/Thunar.pot, po/*.po: Update translations. + +2006-02-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file-monitor.{c,h}, thunar/Makefile.am: Add new class + ThunarFileMonitor, which allows other objects stay informed about + changes to ThunarFile's without having to connect signal handlers to + every ThunarFile. Bug #1447. + * thunar/thunar-file.c: Emit ThunarFileMonitor signals as appropriate. + Bug #1447. + * thunar/thunar-folder.c, thunar/thunar-list-model.c: Use the newly + added ThunarFileMonitor to monitor files for changes and deletion + without having to connect and disconnect signal handlers to each and + every file. Bug #1447. + +2006-02-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-throbber-fallback.png: Import better throbber fallback + icon, thanks to Brian Schott <brian-schott@cox.net>. + +2006-02-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_cmp): Remove the safety + checks here, showing up too high in the profiler stats, and invalid + arguments to this function will be detected earlier (for debug + builds). + +2006-02-10 Benedikt Meurer <benny@xfce.org> + + * docs/reference/thunar-vfs/: Update thunar-vfs API docs. + * thunar/thunar-throbber-fallback.png, thunar/thunar-throbber.c: Use + smaller throbber, so we don't increase the height of the menu bar. + +2006-02-10 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-1.pc.in: Add gthread-2.0 to the dependencies. + * thunar-vfs/thunar-vfs.c(thunar_vfs_init): Make sure the GThread + system is initialized. + * thunar/main.c(main): thunar_vfs_init() will initialize GThread. + * thunar-vfs/thunar-vfs-info.c, thunar-vfs/thunar-vfs-types.h: Add flag + THUNAR_VFS_FILE_FLAGS_HIDDEN, which tells whether a given file should + be considered hidden. + * thunar/thunar-file.{c,h}: Use the THUNAR_VFS_FILE_FLAGS_HIDDEN flag + and implement thunar_file_is_hidden() as simple macro. + * thunar/thunar-list-model.c(thunar_list_model_get_statusbar_text): Fix + a typo in the multi-selection ngettext() call. + * thunar/main.c(main): Call gdk_notify_startup_complete() if the remote + LaunchFiles() succeeds. + +2006-02-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-text-renderer.c(thunar_text_renderer_set_widget): Use + the base text direction specified by Gtk+. Also, do not interpret + line separators in file names. + * thunar-vfs/thunar-vfs-listdir-job.c, + thunar-vfs/thunar-vfs-marshal.list: Add boolean return value to the + ThunarVfsListdirJob::infos-ready signal, and allow handlers to take + over ownership of the infos list to avoid having to allocate a new + list (which reduces both performance overhead and the negative effects + on the data cache). Handlers must take care when using this feature, + documentation has been updated to explain the details. + * thunar/thunar-folder.c: Take over ownership of the list provided by + "infos-ready" and just replace the ThunarVfsInfo's with ThunarFile's + for the initial load case. For the reload case, there's no real gain + in taking over ownership, so we keep the existing behaviour there. + +2006-02-09 Benedikt Meurer <benny@xfce.org> + + * thunarx/thunarx-provider-factory.c: Initialize the factory on demand. + * thunar-vfs/thunar-vfs-scandir.c(thunar_vfs_scandir_collect_fast): Use + a larger buffer to speed up loading large directories. + * thunar-vfs/thunar-vfs-mime-database.c: Initialize the MIME desktop + stores on demand. + +2006-02-09 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.h: Use cast checks instead of type checks here, as + they will be optimized away with regular builds. Debug builds will + still include the checks. + * thunar/thunar-application.c, thunar/thunar-chooser-button.c, + thunar/thunar-chooser-dialog.c, thunar/thunar-chooser-model.c, + thunar/thunar-clipboard-manager.c, thunar/thunar-create-dialog.c, + thunar/thunar-emblem-chooser.c, thunar/thunar-file.c, + thunar/thunar-folder.c, thunar/thunar-gobject-extensions.h, + thunar/thunar-history.c, thunar/thunar-icon-factory.c, + thunar/thunar-icon-renderer.c, thunar/thunar-icon-view.c, + thunar/thunar-launcher.c, thunar/thunar-list-model.c, + thunar/thunar-location-buttons.c, thunar/thunar-location-entry.c, + thunar/thunar-path-entry.c, thunar/thunar-permissions-chooser.c, + thunar/thunar-progress-dialog.c, thunar/thunar-properties-dialog.c, + thunar/thunar-shortcuts-icon-renderer.c, + thunar/thunar-shortcuts-pane.c, thunar/thunar-standard-view.c, + thunar/thunar-statusbar.c, thunar/thunar-text-renderer.c, + thunar/thunar-throbber.c, thunar/thunar-window.c: We don't need + to implement G_OBJECT_WARN_INVALID_PROPERTY_ID() for regular builds, + as GObject will perform the required checks, but we need it for + debug builds to make sure the switch statement is complete. + +2006-02-08 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-util.{c,h}, thunar-vfs/thunar-vfs.symbols: Add + new function thunar_vfs_canonicalize_filename(). + * thunar-vfs/thunar-vfs-path.c(thunar_vfs_path_new): Use + thunar_vfs_canonicalize_filename() on absolute paths. + * docs/reference/thunar-vfs/: Update the thunar-vfs API docs. + * thunar/thunar-dialogs.{c,h}: Use a generic parent parameter instead of + a GtkWidget, so this method is also usable if no GtkWidget is none, + but the dialog must appear on a specific screen. + * thunar/thunar-application.{c,h}: Add a "daemon" property, which + determines whether Thunar will exit once the last window is closed. + Remove the D-BUS service here. Add process_filenames() method, to + process the list of filenames given on the command line. Bug #1384. + * thunar/main.c: Attach the D-BUS here. + * Makefile.am, org.xfce.Thunar.service.in: Add Thunar specific service + file. + * thunar/thunar-dbus-service-infos.xml, thunar/thunar-dbus-service.c: + Add the org.xfce.Thunar interface here, with currently only a + LaunchFiles() method, which can process Thunar command line parameters + in a remote instance. Bug #1384. + * thunar/thunar-dbus-client.{c,h}, thunar/Makefile.am: Add convenience + wrapper for the D-BUS LaunchFiles() of the org.xfce.Thunar interface, + which is used on startup to first try to reuse an existing instance. + This way new folder windows will popup instantly if an instance of + Thunar is already running. + * org.xfce.Thunar.service.in, org.xfce.FileManager.service.in, + thunar/main.c: Add --daemon option and use it when starting from the + message bus. Pass all additional parameters as file names to a run- + ning remote instance or to ThunarApplication as fallback. Bug #1384. + * examples/xfce-file-manager.py, examples/Makefile.am: Add a simple + example how to communicate with the file manager using the D-BUS + Python bindings. + * po/Thunar.pot, po/*.po: Merge new strings. + +2006-02-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c(thunar_window_action_about): Fix the copyright + date. + +2006-02-07 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-application.{c,h}: Add thunar_application_take_window(), + which is used to add a GtkWindow to the internal application windows + list. The application will not exit until the last controlled window + is closed by the user. + * thunar/thunar-file.{c,h}: Use a generic parent parameter for the + thunar_file_launch() method. + * thunar/thunar-chooser-dialog.{c,h}: Use a generic parent paramter for + the thunar_show_chooser_dialog() method, and let the application take + over control of the dialog window. + * thunar/thunar-gdk-extensions.{c,h}, thunar/Makefile.am: Import method + thunar_gdk_screen_open() from Terminal, which opens a GdkScreen from + a full qualified display name. + * README, configure.in.in: Add optional check for D-BUS. + * thunar/Makefile.am, org.xfce.FileManager.service.in, Makefile.am, + thunar/thunar-dbus-service-infos.xml, thunar/thunar-application.{c,h}, + thunar/thunar-dbus-service.{c,h}: Initial import of the basic D-BUS + service for Thunar, the org.xfce.FileManager implementation. See the + thunar-dbus-service-infos.xml file for a description of the current + interface. + * po/Thunar.pot, po/*.po: Update the translations. + +2006-02-07 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-cleaner.c: Also cleanup the defaults.list + file, replacing previously merged desktop-ids and dropping references + to no longer existing .desktop files. + +2006-02-06 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-cleaner.c, thunar-vfs/Makefile.am, + configure.in.in: Add a simple utility program thunar-vfs-mime-cleaner, + which cleans up the user's $XDG_DATA_HOME/applications directory and + removes all automatically generated .desktop files (either generated + by Thunar or Nautilus) whose associated program is no longer installed + on the user's system. In addition, it tries to combine duplicated + .desktop whose Exec values are equal to further the reduce the + overhead. + * thunar-vfs/thunar-vfs-mime-database.c: Invoke thunar-vfs-mime-cleaner + every five minutes. + * thunar-vfs/thunar-vfs.symbols, thunar-vfs/thunar-vfs-*.h: Add + G_GNUC_WARN_UNUSED_RESULT to all methods, whose return value should + never be ignored. This should help to avoid memory leaks in the + future. + +2006-02-06 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-chmod-job.c, thunar-vfs/thunar-vfs-chown-job.c, + thunar-vfs/thunar-vfs-listdir-job.c, thunar-vfs/thunar-vfs-scandir.c, + thunar-vfs/thunar-vfs-scandir.h, thunar-vfs/thunar-vfs-transfer-job.c, + thunar-vfs/thunar-vfs-unlink-job.c: The directory scanning is now + cancelable. Bug #1239. + * thunar/thunar-icon-factory.c: Properly reload/regenerate thumbnails + when image files are changed. Bug #1435. + * thunar-vfs/thunar-vfs-mime-application.c + (thunar_vfs_mime_application_new_from_file): Check TryExec (or Exec) + first prior to allocating a ThunarVfsMimeApplication for a .desktop + file, whose associated program cannot be run. Bug #1436. + +2006-02-06 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Autoscroll while dragging to a + ThunarStandardView widget. Bug #1304. + +2006-02-06 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-templates-action.c: Use "show" instead of "map" to + create the Templates menu, to make sure the menu position is + determined properly. + * README, configure.in.in, thunar/thunar-icon-view.c: Use cairo only + with Gtk+ >= 2.7.1. + * thunar/thunar-shortcuts-view.c(thunar_shortcuts_view_init): Display + typeahead search for the shortcuts view. + +2006-02-06 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-transfer-job.c(thunar_vfs_transfer_job_execute): + Try to use g_rename() first when moving files, and only fallback to + copy&delete if either the target exists (which requires user inter- + action to resolve the issue) or the rename didn't work, i.e. source + and target are not on the same filesystem. Bug #1229. + * thunar-vfs/thunar-vfs-volume.{c,h}: Add thunar_vfs_volume_is_disc() + to allow applications to decide whether to eject or unmount a + volume. + * thunar/thunar-shortcuts-view.c + (thunar_shortcuts_view_button_press_event): Use the newly added method + thunar_vfs_volume_is_disc() to determine whether to display Eject or + Unmount. + * thunar/thunar-side-pane.{c,h}: Derive ThunarSidePane from + ThunarComponent instead of ThunarNavigator. + * thunar/thunar-launcher.c, thunar/thunar-standard-view.c, + thunar/thunar-window.c: Use the class name as name for the action + groups. + * thunar/thunar-shortcuts-pane-ui.xml, thunar/thunar-shortcuts-pane.c, + thunar/thunar-window.c, thunar/thunar-window-ui.xml, + thunar/Makefile.am: Add new action to add a folder (or a list of + folders, depending on the selection content) to the shortcuts pane. + Bug #1397. + * thunar/thunar-throbber.c, thunar/thunar-throbber-fallback.{h,png}, + thunar/Makefile.am: Use the "process-working" icon for the throbber, + as specified by the Icon Naming Specification, with an internal + fallback to a modified version of the Tango "process-working" icon. + * configure.in.in, icons/Makefile.am, icons/scalable/, + icons/16x16/Thunar.png, icons/16x16/Thunar.png, + icons/24x24/Thunar.png, icons/48x48/Thunar.png: Revert to the previous + Thunar icon. + * po/Thunar.pot, po/*.po: Merge new strings. + +2006-02-06 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c(thunar_properties_dialog_update): + Use G_GINT64_FORMAT instead of "lld" as format for the file size. + +2006-02-06 Benedikt Meurer <benny@xfce.org> + + * Thunar.desktop.in: Add "GTK" to the Categories. + +2006-02-06 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c: Make sure to catch the tab key even for + the ThunarLocationEntry case. This doesn't work if the completion list + is visible, tho (Gtk+ bug/limitation). Bug #1346. + +2006-02-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-chooser-dialog.{c,h}: Add a new convenience function + thunar_show_chooser_dialog(). + * thunar/thunar-launcher.c(thunar_launcher_open_files), + thunar/thunar-file.c(thunar_file_launch): Use the new function + thunar_show_chooser_dialog() here. + * thunar/thunar-gtk-extensions.{c,h}: Add a new convenience function + thunar_gtk_ui_manager_get_action_by_name(), which is unfortunately + missing from GtkUIManager. + * thunar/thunar-details-view.c, thunar/thunar-icon-view.c: Use + thunar_gtk_ui_manager_get_action_by_name() to locate the launcher + actions in the UI manager. + * thunar/thunar-file.{c,h}: Add a new convenience function + thunar_file_list_get_applications(), which can be used to determine + the set of applications that can be used to open a given set of + files. + * thunar-uca/thunar-uca-chooser.c(thunar_uca_chooser_delete_clicked): + Save the model after removing a custom action. + * thunar/thunar-launcher.{c,h}, thunar/thunar-chooser-dialog.{c,h}, + thunar/thunar-launcher-ui.xml, thunar/Makefile.am, + thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c, + thunar/thunar-window-ui.xml, thunar/thunar-window.c: Replace the + previous ThunarLauncher class with a more advanced one, which has + access to the GtkUIManager. The new implementation also displays + which application will be used to open files, based on Jonathan + Blandfords suggestion for Nautilus. Bug #1428. + * thunar-vfs/thunar-vfs-mime-action-private.h, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs-mime-action.{c,h},thunar-vfs/thunar-vfs.symbols, + thunar-vfs/thunar-vfs-mime-handler-private.h, thunar-vfs/thunar-vfs.h, + thunar-vfs/thunar-vfs-mime-handler.{c,h}, + thunar-vfs/thunar-vfs-mime-application.{c,h}, + thunar-vfs/thunar-vfs-mime-database.c: Import ThunarVfsMimeAction + class to support desktop actions in Thunar. The abstract base class + ThunarVfsMimeHandler is used to avoid duplicating the existing code + for ThunarVfsMimeApplication in ThunarVfsMimeAction, and it will also + make it easier to handle both ThunarVfsMimeApplication's and + ThunarVfsMimeAction's in the user interface code. Bug #1374. + * docs/reference/thunar-vfs/: Update the Thunar-VFS API docs. + * thunar/thunar-chooser-button.c, thunar/thunar-chooser-dialog.c, + thunar/thunar-chooser-model.c, thunar/thunar-file.c, + thunar/thunar-launcher.c: Update to the new ThunarVfsMimeHandler and + ThunarVfsMimeApplication interface. + * thunar/thunar-launcher.c: Display desktop actions in the file context + menu and the "File" menu, based on the newly added ThunarVfsMimeAction + class. Bug #1375. + * po/POTFILES.in: Update the file list. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Update german translations. + * configure.in.in, icons/: Change the Thunar icon to the new one + provided by Young Hahn <youngjin.hahn@gmail.com>. Any artists around + to make it look even better? + +2006-02-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-permissions-chooser.c + (thunar_permissions_chooser_file_changed): Display the program check + box only for files which we will actually execute. + * thunar/thunar-permissions-chooser.c: Add a warning text to the + permissions chooser for folders, whose exec and read flags are + inconsistent. Add a button to allow the user to fix the folder + permissions automatically if inconsistent. + * po/Thunar.pot, po/*.po: Merge new strings. + +2006-02-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.{c,h}: Add method thunar_file_list_to_path_list(), + which transforms a list of ThunarFile's to a list of ThunarVfsPath's. + * thunar/thunar-clipboard-manager.c + (thunar_clipboard_manager_get_callback): Use newly added function + thunar_file_list_to_path_list() here. + * thunarx/thunarx-file-info.c(thunarx_file_info_list_copy): Use a + slightly more efficient implementation here. + * thunarx/thunarx-file-info.{c,h}, thunarx/thunarx.symbols: Add a boxed + type for a list of ThunarxFileInfo's. + * docs/reference/thunarx/: Update the thunarx API docs. + * thunar/thunar-launcher.c: Use the new boxed type for the list of + selected files, rather than a pointer. + * thunar/thunar-navigator.c(thunar_navigator_get_type): Add requirement + on G_TYPE_OBJECT. + * thunar/thunar-component.{c,h}: Add new interface ThunarComponent for + those parts of a ThunarWindow that require access to both the UI + manager and the currently selected files. ThunarComponent extends + ThunarNavigator. + * thunar/thunar-view.{c,h}: The ui-manager property is now in + ThunarComponent and ThunarView inherits ThunarComponent. + * thunar/thunar-standard-view.{c,h}: Implement ThunarComponent interface + as required by ThunarView now. This way other components will be able + to determine the selected files and set the selected files without + having to interact with the ThunarView implementation directly. + * thunar-vfs/thunar-vfs-info.c(thunar_vfs_info_get_free_space): Be sure + to use statvfs(2) for IRIX. Bug #1425. + * thunar-vfs/thunar-vfs-volume.h(ThunarVfsVolumeManagerIface): Reserve + some space for future expansion now. + * thunar-vfs/thunar-vfs-*.c, docs/reference/thunar-vfs/: Some updates + to the Thunar-VFS API documentation. + * po/Thunar.pot, po/*.po: Update translations. + +2006-02-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c(thunar_path_entry_init): Update to the + new show-hidden settings name. Bug #1424. + +2006-02-02 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Check for statvfs() and statfs(), and required + header files. + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs-volume.{c,h}, + thunar-vfs/thunar-vfs-volume-bsd.c, thunar-vfs/thunar-vfs.symbols: + Move the get_free_space() method from ThunarVfsVolume to ThunarVfsInfo + so we can use it even if no volume manager implementation is avail- + able for the target system. Bug #1420. + * thunar/thunar-file.h: Add get_free_space() method to ThunarFile, so + we can easily determine the amount free space for a given volume + based on a file located on that volume. Bug #1421. + * thunar/thunar-list-model.c(thunar_list_model_get_statusbar_text): Use + new method thunar_file_get_free_space(). + * thunar/thunar-properties-dialog.c: Display the amount of free space + on a certain volume in the properties dialog for folders. + +2006-02-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-throbber.c: Fix typo in GDK_WINDOWING_X11. Cannot use + gdk_cairo_region() with GDK < 2.7.1. + +2006-02-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Make it + easier to distinguish hidden and backup files from regular files. + * docs/README.thunarrc, thunar/thunar-preferences.c: Rename the + DefaultShowHidden preference to LastShowHidden. + * thunar/thunar-preferences-dialog.c, thunar/thunar-window.c: Drop the + "Show hidden files" option from the preferences dialog. Instead Thunar + now preserves the users last selection. This way, the "Show hidden + files" behaviour is now consistent with the rest of the file manager. + Bug #1417. + +2006-02-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-shortcuts-model.{c,h}: Drop obsolete method + thunar_shortcuts_model_file_for_iter() from ThunarShortcutsModel. + * thunar-vfs/thunar-vfs-volume.{c,h}, thunar-vfs/thunar-vfs.symbols: + Add eject(), mount() and unmount() methods to the ThunarVfsVolume + interface. The interface is therefore mostly done now, maybe some + small additions required for certain backends in the future. Bug #995. + * docs/reference/thunar-vfs/: Update the API docs. + * thunar-vfs/thunar-vfs-volume-bsd.c: Implement eject(), mount() and + unmount() for the BSD backend. + * thunar/thunar-shortcuts-view.c: Allow users to mount, unmount and + eject volumes using the shortcuts pane. Volumes will also be mounted + automatically if you select "Open", "Open in New Window" or just + double click them. But all this is currently only available to BSD + users. + * docs/README.volumes: Add notes about the volume manager. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Another four strings translated! + +2006-02-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_scroll_event): + Zoom-in on scroll down, zoom-out on scroll up, to be compatible with + Firefox. + +2006-02-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Open a dialog when renaming a file. + Bug #1413. + * thunar/thunar-standard-view.c(thunar_standard_view_action_delete): + Use "Cancel" and "Delete" buttons in the delete confirmation dialog, + as suggested by Jasper. + * thunar/thunar-progress-dialog.c(thunar_progress_dialog_error), + thunar/thunar-permissions-chooser.c + (thunar_permissions_chooser_job_error): Use "Close" button for the + error dialogs. + * po/Thunar.pot, po/*.po: Merge new strings. + * po/de.po: Some work on the german translations. + * docs/reference/thunar-vfs/tmpl/: Update thunar-vfs API docs. + +2006-02-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c: Don't recreate plugin pages if + the file changes, but instead let the plugins connect to the file's + "changed" signal and update their user interface appropriately. + Bug #1355. + +2006-02-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.{c,h}, thunarx/thunarx-file-info.{c,h}, + thunarx/thunarx.symbols: Move "changed" and "renamed" signals from + ThunarFile to ThunarxFileInfo, so plugins can use these signals to + stay informed about changes to files. First part of bug #1354. + * docs/reference/thunarx/: Update the API documentation. + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs-types.h: + Drop the inode field from the ThunarVfsInfo struct, as we don't + need it anyway and it can cause trouble with systems where ino_t's + size depends on whether largefile support is active or not. + +2006-02-01 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-scandir.c: Use g_access() if available. + * thunar-vfs/thunar-vfs-info.c(_thunar_vfs_info_new_internal): Fix a + bug where the path name was g_free()'d for .desktop files with non + ASCII file names. + * thunar-vfs/thunar-vfs-path.c(thunar_vfs_path_to_string): Apply simple + optimization here: Prefer the stack memory over heap memory when + constructing the absolute path. + +2006-02-01 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-util.c(thunar_vfs_humanize_size): Use "kB" + instead of "KB". + +2006-01-31 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Disable the "create-document" action + on non-writable folders. + * thunar-vfs/thunar-vfs-scandir.c: Return an error when trying to scan + a directory for which the user has no execute permissions. Bug #1408. + * thunar/thunar-file.c(thunar_file_get_emblem_names): Add "cant-read" + emblem to folders, where we don't have permissions to enter. Second + part of fix for bug #1408. + +2006-01-31 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.c: Treat .desktop files of Type=Link as + executable as well, and when requested to execute such a file, extract + the URL and pass it to exo-open for further processing. Bug #1369. + +2006-01-31 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-exec.c(thunar_vfs_exec_parse): Use exo-open + instead of hardcoding Terminal as terminal emulator. Bug #1400. + +2006-01-31 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Depend on exo 0.3.1.3. + * thunar-vfs/thunar-vfs-listdir-job.c: Make sure the list head always + points to a valid ThunarVfsInfo list, even if an error occurred while + stat()'ing files in a given directory. Bug #1390. + * thunar/thunar-window.c(thunar_window_action_about): Use the newly + added exo_url_about_dialog_hook() functions to open links in the + about dialog. + +2006-01-31 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_scroll_event): Add + support to zoom in/out using Control+MouseWheel. + +2006-01-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c(thunar_window_action_open_templates): Improve + the text for the "About Templates" dialog. Thanks to Brian for the + suggestion. Bug #1392. + +2006-01-30 Benedikt Meurer <benny@xfce.org> + + * thunar/Makefile.am, thunar/thunar-throbber.{c,h}: Import the + ThunarThrobber widget class, which display a loading animation + similar to the one found in Firefox. + * thunar/thunar-statusbar.{c,h}: Drop the statusbar icon, as it's + confusing, since it refers to the current folder instead of the + selected items, but the text displayed in the statusbar refers to the + selected items. + * thunar/thunar-window.c: Add a ThunarThrobber to the menu bar, and use + it to display loading animation instead of the statusbar icon. + * thunar/thunar-window.c: Add additional reload shortcut GDK_F5. + * docs/README.thunarrc, thunar/thunar-preferences.c, + thunar/thunar-window-ui.xml, thunar/thunar-window.c: The statusbar + is optional now. Bug #1395. + * po/Thunar.pot, po/*.po: Merge new strings. + +2006-01-30 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add ru translations. + * THANKS: Add ru translator credits for Andrey Fedoseev + <andrey.fedoseev@gmail.com>. + +2006-01-29 Benedikt Meurer <benny@xfce.org> + + * docs/README.thunarrc: Add missing preferences. + * thunar/thunar-preferences.c: Rearrange stuff. + +2006-01-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-enum-types.{c,h}: Add ThunarZoomLevel and ThunarIconSize + required for the zoom-level support. + * docs/README.thunarrc, thunar/thunar-preferences.c: Changed property + ShortcutsIconSize to ThunarIconSize, required for the upcoming + changes to ThunarIconRenderer. People starting Thunar for the first + time after this upgrade will notice that the size of the shortcuts + icons is too small because of this change. Either edit thunarrc and + change ShortcutsIconSize appropriately or just remove thunarrc and + let Thunar recreate it with sane defaults (your settings will be lost + then). Add two new preferences LastDetailsViewZoomLevel and + LastIconViewZoomLevel. + * thunar/thunar-icon-renderer.{c,h}: The size property is now of type + ThunarIconSize, rather than plain int. + * thunar/thunar-view.{c,h}: Add zoom control methods to the ThunarView + interface. + * thunar/thunar-standard-view.{c,h}, thunar/thunar-standard-view-ui.xml, + thunar/thunar-window-ui.xml, thunar/thunar-window.{c,h}, + thunar/thunar-details-view.c, thunar/thunar-icon-view.c: Add support + for seven different zoom levels to Thunar based on the previous + changes. This fixes bug #1357, and thereby implements one of the most + oftenly requested features. + * po/Thunar.pot, po/*.po: Merge new strings. + +2006-01-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-buttons.c: Add support to drop on pathbar + buttons, as requested in bug #1344. + +2006-01-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_files_removed): Fix bug + where only the first file was removed. + * thunar/thunar-folder.{c,h}: Add new method thunar_folder_reload(), + which explicitly forces the ThunarFolder to reload its contents. + This fixes bug #1360. + * thunar/thunar-view.{c,h}: Add new method thunar_view_reload() to the + ThunarView interface. + * thunar/thunar-standard-view.c: Implement thunar_view_reload() for the + ThunarStandardView class, using the newly added thunar_folder_reload() + method. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add a "Reload" + item to the "View" menu, using "Ctrl+R" as accelerator to stay com- + patible with Firefox, Nautilus, etc. This fixes bug #1361. + * thunar/thunar-standard-view.c + (thunar_standard_view_drag_data_received): Reload the contents of the + target folder after a successful XDirectSave. This fixes bug #1362. + * po/Thunar.pot, po/*.po: Merge new strings. + +2006-01-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-templates-action.c: Add support for sub folders below + the ~/Templates folder. This fixes reopened bug #1391. + * thunar-vfs/thunar-vfs.symbols, thunar-vfs/thunar-vfs-info.{c,h}: Add + thunar_vfs_info_read_link(), which determines the target from a + symbolic link. + * thunar/thunar-file.h: Add method thunar_file_read_link() as wrapper + to thunar_vfs_info_read_link(). + * thunar/thunar-properties-dialog.c: Display the "Link Target" for + symbolic links. This fixes bug #1394. + +2006-01-28 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-chmod-job.c(thunar_vfs_chmod_job_execute), + thunar-vfs/thunar-vfs-chown-job.c(thunar_vfs_chown_job_execute): + Properly emit and release an error that occurred on the last file. + * THANKS, thunar/thunar-shortcuts-view.c: Add support to open shortcuts + in new windows using the context menu or double-middle-clicks, based + on a patch by Laurent Meunier <meunier.laurent@laposte.net>. This + fixes bug #1381. + * docs/README.thunarrc, thunar/thunar-preferences.c, + thunar/thunar-window.c: Remember the window dimensions whenever the + size of a window is changed and use the last saved window dimensions + for newly created windows. This fixes bug #1389. + * thunar/thunar-pango-extensions.{c,h}: Add new helper function + thunar_pango_attr_list_big_bold(), which returns a pango attribute + list for big, bold text rendering. + * thunar/thunar-permissions-chooser.c + (thunar_permissions_chooser_ask_recursive): Use big, bold label for + the dialog title to stay consistent with GtkMessageDialog. + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs-creat-job.{c,h}, + thunar-vfs/thunar-vfs.{c,h}, thunar-vfs/thunar-vfs.symbols: Add new + class ThunarVfsCreatJob, which is used to create empty files for a + given list of paths. + * docs/reference/thunar-vfs/tmpl/thunar-vfs-operations.sgml, + docs/reference/thunar-vfs/thunar-vfs-sections.txt: Update API docs. + * thunar/thunar-application.{c,h}: Add thunar_application_creat() as + wrapper for the newly imported ThunarVfsCreatJob. + * thunar/thunar-application.{c,h}: Add thunar_application_copy_to() to + copy files from one location to another, rather than copying files + from different sources to exactly one folder. + * thunar/thunar-create-dialog.c(thunar_create_dialog_set_filename): + If the suggested file name contains a dot, pre-select only the text + up to the dot. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c, + thunar/thunar-templates-action.{c,h}, thunar/Makefile.am: Add support + for Templates in a way compatible with what Nautilus does currently. + This is part one of the fix for bug #1391. + * thunar/thunar-preferences, docs/README.thunarrc: Add new property + "misc-show-about-templates", which determines whether the "About + Templates" dialog will be shown when entering the Templates folder. + * icons/16x16/stock_thunar-templates.png, icons/16x16/Makefile.am, + thunar/thunar-stock.{c,h}: Add new stock icon "thunar-templates". + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add "Templates" + to the "Go" menu, which will open the ~/Templates folder (it will be + created on-demand) and popup a message describing the purpose of the + ~/Templates folder. This is part two of the fix for bug #1391. + * po/POTFILES.in: Add new files here. + * po/*.po: Merge new strings. + +2006-01-25 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.c, thunar-vfs/thunar-vfs-xfer.c: Apply + patch provided by Daichi to add several translator hints to + thunar-vfs. + * thunar/thunar-properties-dialog.c + (thunar_properties_dialog_key_press_event): Support Ctrl+W for clo- + sing the properties dialog, to be consistent with the main windows. + +2006-01-25 Benedikt Meurer <benny@xfce.org> + + * THANKS, configure.in.in: Add nl to XDT_I18N(). Add translator credits + to THANKS. + +2006-01-25 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-util.c(thunar_vfs_humanize_size): Use "GB" + instead of "G", "MB" instead of "M" and "KB" instead of "K", to + make it more obvious what the value means (this fixes bug #1367). + +2006-01-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-chooser-dialog.c, thunar/thunar-chooser-model.c, + thunar/thunar-clipboard-manager.c, thunar/thunar-create-dialog.c, + thunar/thunar-emblem-chooser.c, thunar/thunar-file.c, + thunar/thunar-folder.c, thunar/thunar-history.c, + thunar/thunar-icon-factory.c, thunar/thunar-icon-view.c, + thunar/thunar-launcher.c, thunar/thunar-list-model.c, + thunar/thunar-navigator.c, thunar/thunar-open-with-action.c, + thunar/thunar-path-entry.c, thunar/thunar-progress-dialog.c, + thunar/thunar-properties-dialog.c, thunar/thunar-standard-view.c, + thunar/thunar-statusbar.c, thunar/thunar-text-renderer.c, + thunar/thunar-view.c, thunar/thunar-window.c: Remove various internal + strings from the list of translatable strings to reduce confusion + for translators. + * po/*.po: Update translations. + +2006-01-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-enum-types.{c,h}: Import enum types required for the + desktop background management. + +2006-01-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-preferences.c(thunar_preferences_set_property): No need + to call g_object_notify() here, as GObject does that automatically + whenever set_property() is being called. + * thunar/thunar-preferences.c: Remove useless safetly checks in + get_property() and set_property(), since GObject already makes sure + that the property id is valid. + +2006-01-23 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c(thunar_properties_dialog_update): + Display size only for regular files, as it's misleading for other + file system entities. + * po/*.po: Merge new strings. Some work on the german translations, + we really need a german translator! + +2006-01-23 Benedikt Meurer <benny@xfce.org> + + * docs/README.thunarrc, thunar/thunar-preferences.c: Add new preferences + ShortcutsIconEmblems and ShortcutsIconSize, which control the + appearance of the shortcuts view. + * thunar/thunar-gobject-extensions.c: Add transformator for string to + int transformations. + * thunar/thunar-icon-renderer.{c,h},thunar/thunar-shortcuts-model.{c,h}, + thunar/thunar-shortcuts-icon-renderer.{c,h}, thunar/Makefile.am, + thunar/thunar-shortcuts-view.c: Import ThunarShortcutsIconRenderer + class, which is derived from ThunarIconRenderer and allows us to draw + icon cells consistently throughout the file manager. This also fixes + bug #1340, which requests to display emblems for the icons in the + shortcuts pane. Both the display of emblems in the shortcuts pane + and the size of the icons in the shortcuts pane are now configurable + through the thunarrc file (for the emblems, there's also a menu item + in the context menu). + +2006-01-23 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Bump version to 0.2.1svn. + * thunar/thunar-file.{c,h}: Make thunar_file_accepts_drop() easier to + use. + * thunar/thunar-standard-view.c(thunar_standard_view_get_dest_actions): + Keep up with the thunar_file_accepts_drop() changes. + * docs/reference/thunarx/tmpl/thunarx-preferences-provider.sgml: Let + gtk-doc remove it's empty line here, for whatever reason. + +2006-01-22 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Bump version to 0.2.0alpha. + * configure.in.in: Bump library interface version. + * configure.in.in: Depend on libexo 0.3.1.2. + * po/*.po: Update translations. + * TODO: Remove obsolete TODO items. + +2006-01-14 Benedikt Meurer <benny@xfce.org> + + * THANKS, configure.in.in, po/pl.po: Add initial polish translations, + thanks to Tomasz MichaÅ‚ Åukaszewski <T.Lukaszewski@aster.pl>. + * thunar/thunar-icon-factory.c, thunar/thunar-preferences-dialog.c, + thunar/thunar-preferences.c, thunar/thunar-standard-view.c: Make + thumbnails configurable. + * po/*.po: Merge new strings. + +2006-01-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c(thunar_path_entry_init): The property + "popup-single-match" was introduced in Gtk+ 2.8. Thanks to Erik + for the pointer. + +2006-01-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-text-renderer.c(thunar_text_renderer_render): Render + focus indicator when following state. Part two of fix for bug #1321. + +2006-01-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-preferences.c, FAQ: Store preferences in an .ini file, + $XDG_CONFIG_HOME/Thunar/thunarrc, similar to what Terminal does, so + users can easily adjust hidden settings, and don't have to dive into + the details of managing a tdb database file. + * thunar/thunar-icon-view.c, thunar/thunar-path-entry.c, + thunar/thunar-preferences-dialog.c, thunar/thunar-preferences.c, + thunar/thunar-standard-view.c: Rename "default-folders-first" to + "misc-folders-first" and "default-text-beside-icons" to + "misc-text-beside-icons", as those preferences aren't defaults. + * thunar/thunar-standard-view.c(thunar_standard_view_scroll_event), + thunar/thunar-preferences.c: Add a new hidden preference, + MiscHorizontalWheelNavigates, which controls whether the horizontal + mouse wheel should be used to navigate back and forth within a + Thunar view. This fixes bug #1319. + * docs/Makefile.am, docs/README.thunarrc: Add brief overview of the + various Thunar configuration settings. + +2006-01-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Fix compiler warnings. Again bug + #1318. + +2006-01-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c(thunar_path_entry_changed): Make older + compilers happy. Fixes bug #1318. + +2006-01-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-chooser-dialog.c(thunar_chooser_dialog_response): If + the default application was changed successfully, emit "changed" on + the file so everybody updates its state. + * thunar/thunar-chooser-button.{c,h}, thunar/thunar-properties-dialog.c: + Import the ThunarChooserButton, which allows people to change the + default application from within the properties dialog. + * po/POTFILES.in, po/*.po: Merge new strings. + +2006-01-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c(thunar_path_entry_activate): If we have + a pending completion, accept the completion first, without activating + the entry. This makes it more consistent with the behaviour when + completing from the popup window. + * thunar/thunar-path-entry.c(thunar_path_entry_parse): Properly + transform all parts of the filename to the local encoding. + * thunar/thunar-text-renderer.c(thunar_text_renderer_set_widget): + Calculate the approx. character dimensions based on the font metrics + for the active widget font. + * thunar/thunar-window.c(thunar_window_action_go_up): Handle errors + properly. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c: + Add support to view the properties of the current folder. + * thunar/thunar-file.{c,h}, thunar/thunar-location-buttons.c, + thunar/thunar-shortcuts-model.c, thunar/thunar-window.c: Change + special file naming (home and root folder) to be consistent with + what GtkFileChooser does. + * thunar/thunar-properties-dialog.c(thunar_properties_dialog_update): + Display only the name of the file in the dialog title. + * thunar/thunar-standard-view.c: Add support for the XDS protocol. + * README: Add notes about supported standards. + +2006-01-09 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-util.{c,h}: Add thunar_vfs_expand_filename(), + which is used to expand filenames that start with the tilde character. + * docs/reference/thunar-vfs/thunar-vfs-sections.txt, + docs/reference/thunar-vfs/tmpl/thunar-vfs-util.sgml: Update + documentation. + * thunar/thunar-permissions-chooser.c: Implement cancel-semantics for + the recursive permissions dialog. + * thunar/thunar-permissions-chooser.c: Add tooltips. + * thunar/thunar-list-model.{c,h}: Additional column to access the real + file name (in UTF-8 encoding). + * thunar/thunar-path-entry.{c,h}: Add support for auto path completion. + * thunar/thunar-file.{c,h}: Add thunar_file_launch() to automatically + launch a given ThunarFile without having to manually figure out the + proper action. + * thunar/thunar-location-entry.c, thunar/thunar-window.c: If the + ThunarPathEntry returns a non-directory file, just try to launch it. + This allows users to just open files right away from the path entry + without having to lookup the file in the icon/details view. + * thunar/thunar-standard-view.c, THANKS: Allow people to use the + horizontal mouse wheel to navigate back/forward. Based on a patch + provided by Danny Milosavljevic <danny.milo@gmx.net>. + * po/*.po: Merge new strings. + +2006-01-08 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-monitor.c + (thunar_vfs_monitor_queue_notification): Don't use strcmp() here, as + the notification's filename may be NULL. + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs.symbols: Drop + thunar_vfs_info_chmod() and thunar_vfs_info_chgrp() again. + * thunar-vfs/thunar-vfs-chmod-job.{c,h}, thunar-vfs/thunar-vfs.{c,h}, + thunar-vfs/thunar-vfs-chown-job.{c,h}, thunar-vfs/Makefile.am: Add + new classes ThunarVfsChmodJob and ThunarVfsChownJob as replacements + for the thunar_vfs_info_chmod() and thunar_vfs_info_chgrp() functions. + These jobs can operate recursively. Add interfaces to the new classes, + thunar_vfs_change_mode() and thunar_vfs_change_group(). + * docs/reference/thunar-vfs/: Update documentation. + * thunar/thunar-file.{c,h}: Drop thunar_file_chmod(),thunar_file_chgrp() + and thunar_file_is_chgrpable(), as we'll use the asynchronous jobs + added to Thunar-VFS now. + * thunar/thunar-advanced-permissions-dialog.{c,h}, + thunar/thunar-change-group-dialog.{c,h}, + thunar/thunar-permissions-model.{c,h}, + thunar/thunar-permissions-view.{c,h}, thunar/Makefile.am, + thunar/thunar-properties-dialog.c: Ditch the ACL aware permissions + user interface, as it's unlikely that ACL support will be there for + 1.0 and so there's no need to reduce the usability of the permissions + user interface yet. + * thunar/thunar-pango-extensions.{c,h}: Add new Pango helper method + thunar_pango_attr_list_small_italic(). + * thunar/thunar-enum-types.{c,h}: Import new files to contain enum + types that don't fit anywhere else and provide conversation functions + for these types. + * thunar/thunar-permissions-chooser.{c,h}, thunar/Makefile.am, + thunar/thunar-properties-dialog.c: Import simplified permissions + chooser, similar to the Aqua Finder one, with support to change + permissions recursively for folders. + * thunar/thunar-preferences-dialog.c, thunar/thunar-preferences.c: Add + option "misc-recursive-permissions", which controls whether + permissions are always/never applied recursively, or whether Thunar + should ask the user everytime a permission flag is changed. + * icons/16x16/, thunar/thunar-stock.{c,h}: Remove now obsolete icon + thunar-permissions-other. Rename the user and group icons. + * po/*.po, po/POTFILES.in: Update file list. Merge new strings. + +2006-01-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-text-renderer.c: Don't determine the focus-padding and + focus-line-width style properties on every call to get_size() when + used within the icon view. + +2006-01-04 Benedikt Meurer <benny@xfce.org> + + * thunar/Makefile.am, thunar/thunar-pango-extensions.{c,h}: Add common + PangoAttrList's here, to avoid allocating them over and over again, + and of course to avoid markup, which makes translator's life easier. + * thunar/thunar-location-buttons.c, thunar/thunar-preferences-dialog.c, + thunar/thunar-progress-dialog.c, thunar/thunar-properties-dialog.c: + Use common PangoAttrList's provided by the thunar-pango-extensions. + * thunar/thunar-permissions-view.c(thunar_permissions_view_init): Use + italic font for the warning to make it easier to distinguish the text + from the other parts of the GUI. + * thunar/thunar-chooser-dialog.c(thunar_chooser_dialog_update_header): + Also setup the window icon in addition to the header image icon. + +2006-01-04 Benedikt Meurer <benny@xfce.org> + + * docs/reference/thunar-vfs/thunar-vfs-sections.txt, + thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs.symbols, + docs/reference/thunar-vfs/tmpl/thunar-vfs-info.sgml: Add method + thunar_vfs_info_chmod() to change the permissions of a file + identified by a given ThunarVfsInfo. + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs.symbols, + docs/reference/thunar-vfs/thunar-vfs-sections.txt, + docs/reference/thunar-vfs/tmpl/thunar-vfs-info.sgml: Add method + thunar_vfs_info_chgrp() to change the group id of a file identified + by a given ThunarVfsInfo. + * thunar-vfs/thunar-vfs-user.c(thunar_vfs_user_load): Properly + substitute '&' in real names. + * icons/16x16/, icons/Makefile.am, configure.in.in, thunar/Makefile.am, + thunar/thunar-stock.{c,h}: Add stock icons thunar-permissions-user, + thunar-permissions-group and thunar-permissions-other. + * thunar-uca/thunar-uca-plugin.c: Don't display debug messages unless + G_ENABLE_DEBUG is defined. + * thunar-vfs/thunar-vfs-user.{c,h}, thunar-vfs/thunar-vfs.symbols, + docs/reference/thunar-vfs/thunar-vfs-sections.txt, + docs/reference/thunar-vfs/tmpl/thunar-vfs-user-manager.sgml: Add new + method thunar_vfs_user_manager_get_all_groups() to retrieve all groups + known to the ThunarVfsUserManager. + * thunar/thunar-advanced-permissions-dialog.{c,h}, + thunar/thunar-change-group-dialog.{c,h}, + thunar/thunar-permissions-model.{c,h}, + thunar/thunar-permissions-view.{c,h}, + thunar/Makefile.am, thunar/thunar-file.{c,h}, + thunar/thunar-properties-dialog.c: Add permissions tab to the + file properties dialog. + * po/POTFILES.in: Add new files. + * po/*.po: Merge new strings. + * tdb/tdbtool.c(print_rec): Fix printf format. + +2006-01-02 Benedikt Meurer <benny@xfce.org> + + * thunar-uca/thunar-uca-model.c: Include <locale.h> to get LC_MESSAGES + definition. + +2005-12-30 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add ca to XDT_I18n(). + +2005-12-22 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Use -Wall -Werror for --enable-debug=yes as well. + * thunar/thunar-list-model.c(thunar_list_model_get_value): The MIME info + name is static. + * thunar/thunar-text-renderer.c: Don't copy static strings. + * pixmaps/Thunar-fallback-icon.png, pixmaps/Makefile.am, + thunar/thunar-fallback-icon.{h,png}, thunar/Makefile.am, + thunar/thunar-icon-factory.c: Load the fallback icon and the + thumbnail frame on-demand. + * thunar/main.c(main): Use Thunar icon as default for new windows. + * thunar/thunar-icon-factory.c: Allocate the thumbnail factory and the + thumbnail generator on-demand. + * thunar/thunar-file.c: Add "display-name" and "special-name" readonly + properties and emit notifications on these properties whenever the + file is changed/renamed. + * thunar/thunar-location-buttons.c(thunar_location_buttons_make_button): + Automatically synchronize the button labels with the file's special + names. + * configure.in.in: Add it translations to XDT_I18N(). + * THANKS: Add credits for it translator Roberto Pariset. + +2005-12-20 Benedikt Meurer <benny@xfce.org> + + * THANKS: Update credits. + * README, configure.in.in, thunar-vfs/thunar-vfs-info.c, + thunar-vfs/thunar-vfs-mime-database.c, + thunar-vfs/thunar-vfs-mime-info.c, thunar-vfs/thunar-vfs-path.c, + thunar/main.c, thunar/thunar-file.c: Support four different levels + of debugging support. Default for SVN builds is `yes', while the + default for release builds is `minimum'. Closes bug #1254. + +2005-12-13 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-bsd.c(thunar_vfs_volume_bsd_update): + Specify correct buffer size for read(). + * thunar/thunar-icon-factory.c(thunar_icon_factory_load_from_file): + Don't add frames for small icon sizes (< 36). Be sure to scale icon + to the required size, so we don't need to scale on every render() + call. + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_init): Add 1px + padding to the icons. + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Try to + avoid scaling icons if they fit into the given cell area (including + the padding). + +2005-12-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-progress-dialog.c: Use Pango attribute list instead of + markup for the dialog action label. This fixes bug #1252. + * thunar-uca/thunar-uca-chooser.c(thunar_uca_chooser_init): Be sure to + create the button widgets prior to connecting the "selection-changed" + handler. This fixes bug #1260. + +2005-12-03 Benedikt Meurer <benny@xfce.org> + + * thunar/, po/POTFILES.in, po/*.po: Rename "Favourites" to "Shortcuts", + so we're consistent with the GtkFileChooser wording. This fixes bug + #1258. + +2005-12-03 Benedikt Meurer <benny@xfce.org> + + * thunar-uca/thunar-uca-model.c(start_element_handler): Properly + truncate values. + +2005-12-03 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Build the gnuc visibility test program with -Wall + -Werror, as gcc reports warnings instead of errors if ELF visibility + is not supported for the target platform. This fixes bug #1253. + +2005-11-30 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-scandir.c: Workaround missing dirfd() definition + using the POSIX/XPG API on IRIX. This fixes bug #1247. + +2005-11-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-dnd.c, thunar/thunar-favourites-view.c, + thunar/thunar-folder.c, thunar/thunar-preferences-dialog.c, + thunar/thunar-standard-view.c: Use exo_gtk_object_ref_sink() to + automatically handle floating references properly and avoid the use + of GTK_OBJECT_FLOATING (see GNOME bug #322853 for details). This fixes + bug #1249. + +2005-11-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_renamed): Use + persistent iterators instead of tree row references when renaming a + file. This fixes bug #1248. + +2005-11-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-thumbnail-generator.c + (thunar_thumbnail_generator_thread): Don't generate thumbnails for + files for which only the generator owns a reference. + +2005-11-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c + (thunar_standard_view_merge_custom_actions): Fix typo. + * thunarx/thunarx-private.{c,h}, thunarx/thunarx-menu-provider.c, + thunarx/Makefile.am, thunarx/thunarx-property-page-provider.c: Add + helper function thunarx_object_list_take_reference(), so we don't + need to repeat the same code again and again. + * thunar/thunar-window.c(action_entries): Add ... to the Preferences + action, since it opens a dialog. Use "e" as mnemonic, as "P" is + already used by "Paste". + * thunar/thunar-standard-view.c(action_entries): Add ... to the Select + by Pattern action, since it opens a dialog. + * thunar/thunar-preferences-dialog.c: Close preferences dialog on Esc + key press. + * thunarx/thunarx-preferences-provider.{c,h}, thunarx/thunarx.h, + thunarx/thunarx.symbols, thunarx/Makefile.am: Add new interface + ThunarxPreferencesProvider, which can be implemented to add custom + actions to the preferences section of the "Edit" menu. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Query custom + preferences actions from the installed providers and add them to the + preferences section of the "Edit" menu. Actions are loaded in an idle + source to not delay folder loading when opening a new window, even if + a lot of preferences providers are installed. + * docs/reference/thunarx/: Update the thunarx reference documentation. + * thunar-uca/, configure.in.in, Makefile.am: Import the thunar-uca + module, which provides advanced users with an easy way to add custom + actions to Thunar's context menus. With this extension in place + there's no longer a need to add support G-Scripts (except maybe an + importer for thunar-uca). + * po/POTFILES.in: Add new translatable files. + * po/: Merge new strings. + * examples/tex-open-terminal/README: Add note to use thunar-uca, and + consider the tex-open-terminal as example for extension writers. + +2005-11-29 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, thunar-vfs/thunar-vfs-types.h: Add largefile support + for systems that don't support 64bit file offsets by default. This + fixes bug #1243. + +2005-11-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-buttons.c, thunar/thunar-properties-dialog.c: + Use attribute lists instead of markup strings. + +2005-11-27 Benedikt Meurer <benny@xfce.org> + + * tdb/Makefile.am: Fix make -j<N>. + +2005-11-26 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c + (thunar_standard_view_merge_custom_actions): Don't sort custom actions + explicitly, but leave it up to the provider plugins to determine the + order of their actions. Also, be sure to update the UI manager after + unmerging the previously set menu actions, else GtkUIManager will + mess up the order of the actions. + +2005-11-25 Benedikt Meurer <benny@xfce.org> + + * thunarx/thunarx-provider-factory.c: Make sure, ThunarxProviderModules + are never finalized, as GObject cannot unregister dynamic types (yet). + * thunar/thunar-standard-view.c(thunar_standard_view_renamed): Properly + release the path returned from gtk_tree_row_reference_get_path(). + +2005-11-22 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/*.{c,h}, thunar/*.c, thunarx/*.c: Avoid duplicating static + strings if possible. + * thunar-vfs/thunar-vfs-scandir.c(thunar_vfs_scandir_collect): Ignore + EACCES and EPERM on subdirectories with recursive scanning. + * thunar-vfs/thunar-vfs-info.h(ThunarVfsInfo): Compress "type", "mode" + and "flags" to reduce memory overhead. + +2005-11-22 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add fr and pt_BR to gettext linguas, which were + previously imported by Daichi. + +2005-11-21 Benedikt Meurer <benny@xfce.org> + + * docs/reference/thunar-vfs/, thunar-vfs/thunar-vfs-info.h: Small + documentation tweaks. + * thunar-vfs/thunar-vfs-info.h: Allow previous declarations of the + ThunarVfsInfo typedef. + * thunarx/thunarx-file-info.{c,h}, thunarx/thunarx.symbols, + thunar/thunar-file.c, docs/reference/thunarx/: Add new virtual method + thunarx_file_info_get_vfs_info(), which can be used to query the + ThunarVfsInfo for a given ThunarxFileInfo. + +2005-11-21 Benedikt Meurer <benny@xfce.org> + + * thunarx/thunarx-provider-plugin.{c,h}, thunarx/Makefile.am, + thunarx/thunarx.h, thunarx/thunarx.symbols: Add ThunarxProviderPlugin + interface, which abstracts from the details of the dynamic type + registration, and is accessible to the extensions. + * thunarx/thunarx-provider-module.{c,h}, thunarx/Makefile.am: Add + implementation for the ThunarxProviderPlugin interface, based on + GTypeModule, which is used on the file manager's side to manage the + type plugins. + * thunarx/thunarx-provider-factory.{c,h}, thunarx/Makefile.am, + thunarx/thunarx.h, thunarx/thunarx.symbols: Add ThunarxProviderFactory + based on the ThunarExtensionManager as public interface to the + provider plugin mechanism. This may also be used by other applications + in the future. + * thunarx/thunarx.h: Provide convenience macros ala G_DEFINE_TYPE() to + ease type registration for plugin writers. + * examples/, configure.in.in: Update the "Open Terminal Here" example. + * docs/reference/thunarx/: Update the thunarx reference manual to + include the new classes and interfaces. + * thunar/thunar-extension-manager.{c,h}: Drop the old extension manager + class in favour of the new provider factory class. + * thunar/thunar-properties-dialog.c, thunar/thunar-standard-view.c: Use + ThunarxProviderFactory to load the providers from the installed + extensions. + * po/POTFILES.in: Update with new file list. + * thunar/thunar-file.{c,h}: Implement thunar_file_list_copy() using + thunarx_file_info_list_copy() and thunar_file_list_free() using + thunarx_file_info_list_free(). + * docs/reference/thunar-vfs/thunar-vfs-overrides.txt, + docs/reference/thunarx/thunarx-overrides.txt: Fix build error with + older gtk-doc versions. + +2005-11-16 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-application.{c,h}, + thunar-vfs/thunar-vfs.symbols: Drop obsolete error class + ThunarVfsMimeApplicationError. + +2005-11-15 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-gtk-extensions.{c,h}: Add new convenience function + thunar_gtk_action_group_create_tool_item(), which creates a new + GtkToolItem proxy for a given GtkAction in a GtkActionGroup. + * thunar/thunar-location-bar.{c,h}, thunar/thunar-location-entry.c, + thunar/thunar-location-buttons.c: Add new virtual method + thunar_location_bar_is_standalone(), which determines whether a + given location bar should be displayed in a standalone fashion, or + embedded within a location toolbar. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Check whether + the location should be embedded into a location toolbar and if so, + generate a toolbar for it on-demand and place it below the menubar. + Else, the location bar is placed right above the view pane. This + gives a better appearance when using the location entry implementation + with a toolbar, and you don't need the toolbar with the pathbar + anyways. + * po/POTFILES.in: Add thunar-preferences-dialog.c here. + * po/*.po: Merge new strings. + +2005-11-15 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Use "b" as mnemonic for the "Select by + Pattern" action to avoid clash with "Preferences". + * thunar/thunar-preferences.c: Add "default-folders-first" property, + which determines whether folders should be sorted before other files. + Add "default-view", which dictates the default view pane used for new + windows, or "void" to use the view remembered in "last-view". + * thunar/thunar-standard-view.{c,h}: Connect the list models + "folders-first" property to the "default-folders-first" preference. + * thunar/thunar-window.c(thunar_window_init): Check "default-view" first + and if it does not contain a valid view class name, check "last-view". + * thunar/thunar-details-view.c(thunar_details_view_get_accessible), + thunar/thunar-icon-view.c(thunar_icon_view_get_accessible): Set ATK + role for our folder views to ATK_ROLE_DIRECTORY_PANE. + * thunar/Makefile.am, thunar/thunar-preferences-dialog.{c,h}, + thunar/thunar-window-ui.xml, thunar/thunar-window.c: Import class + ThunarPreferencesDialog, which allows the user to customize the global + preferences for Thunar. Add a "Preferences" menu item to the "Edit" + menu of ThunarWindow's. + * thunar/thunar-preferences.c: Add "default-text-beside-icons" property, + which tells whether the icon view should display the file names beside + the file icons, rather than below the file icons. + * thunar/thunar-icon-view.c: Add a property "text-beside-icons", which + tells whether the icon view will place the icon captions beside the + icons rather than below. Synchronize the property with the global + option "default-text-beside-icons". + * po/*.po: Merge new strings. + +2005-11-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-xfer.c: Return G_FILE_ERROR_INTR when the copy + operation is explicitly cancelled by the user. + * thunar-vfs/thunar-vfs-transfer-job.c + (thunar_vfs_transfer_job_copy_pair): Don't delete the source file when + moving unless the target file was written successfully and the job + wasn't cancelled. This fixes a bug reported by Jari Rahkonen. + +2005-11-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.{c,h}: Register "Delete" as key binding + for the ThunarStandardView class, rather than registering it as + accelerator for the "delete" action. This fixes bug #1226. + * thunar/thunar-marshal.list: Add BOOLEAN:VOID marshaller. + +2005-11-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-exec.c(thunar_vfs_exec_on_screen): Fix invalid + calculation of the number of environment variables. + +2005-11-14 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Bump version to 0.1.4svn and depend on + libexo 0.3.1.1. + +2005-11-14 Benedikt Meurer <benny@xfce.org> + + * po/*.po: Update translations. + * po/ChangeLog: Didn't mean to revert this file. + * README: Mention gconf, libjpeg and libstartup-notification as optional + dependencies. + +2005-11-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c: Don't need to remember the "changed" + signal handler id per row, as g_signal_handlers_disconnect_matched() + using G_SIGNAL_MATCH_ID and G_SIGNAL_MATCH_CLOSURE is nearly as fast + as g_signal_handler_disconnect(). + * thunar/thunar-folder.c(thunar_folder_finalize): Specify both + G_SIGNAL_MATCH_ID and G_SIGNAL_MATCH_CLOSURE when disconnecting + "destroy" signals from files. + * thunar/thunar-preferences.c, thunar/thunar-window.c: Remember the last + active view as default for now. + * thunar/thunar-create-dialog.c(thunar_create_dialog_text_changed): Use + G_IS_DIR_SEPARATOR() rather than hardcoding the slash character. + +2005-11-13 Benedikt Meurer <benny@xfce.org> + + * FAQ, thunar/thunar-icon-view.c: Add initial support for mouse gestures + to the icon view component. + +2005-11-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c, thunar/thunar-preferences.c: Rename + "window-location-bar" to "last-location-bar" and "window-side-pane" + to "last-side-pane" to make clear that it's the last selected + setting. + * thunar/thunar-metafile.h: Drop THUNAR_METAFILE_KEY_SHOWHIDDEN. + * thunar/Makefile.am, thunar/thunar-gobject-extensions.{c,h}: Add + additional GValue transformation functions. + * thunar/thunar-preferences.c: Register additional transformation + functions provided by the GObject extensions in the class_init() + function. Add new preference "default-show-hidden", which tells + whether hidden files are shown by default in new windows. + * thunar/thunar-view.{c,h}: Add the "show-hidden" property to the + ThunarView interface. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c: + Implement the "show-hidden" property from the ThunarView interface, + rather than adding an action to the UI manager. + * thunar/thunar-preferences.c: Add "default-show-hidden" property, which + tells whether hidden files should be shown in newly opened windows. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add the + "show-hidden" action here, which starts with the default value queried + from the preferences, and uses the new ThunarView API to sync the + selected setting. + +2005-11-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-preferences.c(thunar_preferences_set_property): No need + to call g_object_notify() here, as object_set_property() does that + implictly once the set_property() call returns. + +2005-11-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.{c,h}, thunar/thunar-metafile.{c,h}: Remove the + default value handling from the ThunarMetafile class and leave it up + to the caller to specify the default value when fetching/storing + metadata. + * thunar/thunar-folder.{c,h}, thunar/thunar-standard-view.c: Remove + the error parameter from the thunar_folder_get_for_file() method, as + this call cannot fail. If a loading error occurs, it will be reported + asynchronously by the listdir job. + * thunar/thunar-preferences.c(thunar_preferences_set_property): Issue + a warning if a required transformation function is not available to + the GLib Type System, as this is effectively a bug in our application. + +2005-11-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-folder.c, thunar/thunar-list-model.c, + thunar/thunar-standard-view.c: Forward ThunarVfsListdirJob loading + errors to the ThunarStandardView and display an error dialog to the + user. + * thunar/thunar-preferences.c, FAQ: Use a tdb database to store the + preferences, while not saving defaults to the database file. + * thunar/thunar-preferences.c: Add initial preferences + "window-location-bar" and "window-side-pane". + * thunar/thunar-window.c: Always remember the last selected location + bar and side pane setting in the preferences. + +2005-11-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_get_statusbar_text): + Display symbolic links properly just like the MIME type field in + the properties dialog. + +2005-11-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_action_duplicate): + Use thunar_standard_view_get_selected_paths() instead of + thunar_standard_view_get_selected_files(). + * po/POTFILES.in: Add new source files. + * po/*.po: Merge new strings. + * thunar/thunar-dialogs.{c,h}, thunar/Makefile.am: Add new function + thunar_dialogs_show_error(), which takes care of displaying an error + message dialog to the user. + * thunar/thunar-application.c, thunar/thunar-chooser-dialog.c, + thunar/thunar-clipboard-manager.c, thunar/thunar-dnd.c, + thunar/thunar-favourites-view.c, thunar/thunar-launcher.c, + thunar/thunar-properties-dialog.c, thunar/thunar-standard-view.c, + thunar/thunar-window.c: Use thunar_dialogs_show_error() whenever + possible to reduce code duplication. + * thunar-vfs/thunar-vfs-info.h, docs/reference/thunar-vfs/: Update the + Thunar-VFS documentation. + +2005-11-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_new_files): Grab + focus for the view widget after selecting newly created files. + * thunar-vfs/thunar-vfs-mkdir-job.{c,h}, thunar-vfs/Makefile.am: Import + new class ThunarVfsMkdirJob, which is used to asynchronously create + a bunch of directories. + * thunar-vfs/thunar-vfs.{c,h}, thunar-vfs/thunar-vfs.symbols: Add new + methods thunar_vfs_make_directory() and thunar_vfs_make_directories() + as public interface to the newly imported ThunarVfsMkdirJob. + * thunar-vfs/thunar-vfs-mime-database.c + (thunar_vfs_mime_database_get_info_for_data_locked), + (thunar_vfs_mime_database_get_info_for_file): Consider empty + files to be text/plain, so users can easily open newly created (empty) + files in their favourite text editor. + * thunar-vfs/thunar-vfs-mime-sniffer.{c,h}, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs-mime-database.c, configure.in.in: Add function + thunar_vfs_mime_sniffer_looks_like_text(), which performs some smart + checks to determine if a given data block looks like plain text. Plain + text means either UTF-8 - and thereby also ASCII - or valid multi-byte + if the platform supports multi-byte strings. In both cases, even + truncated data blocks will be recognized. + * thunar/thunar-application.{c,h}: Add thunar_application_mkdir() as + frontend to the thunar_vfs_make_directories() function. + * thunar/thunar-create-dialog.{c,h}, thunar-vfs/Makefile.am: Add class + ThunarCreateDialog, which is used to query the user for the filename + that should be used for a new file/folder. + * TODO: Add todo item. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c, + thunar/thunar-window-ui.xml: Add "Create Folder" action, which uses + thunar_application_mkdir() to create a new subfolder in the current + folder. + * thunar/thunar-window.c: Rename thunar_window_action_location() to + thunar_window_action_open_location() to get consistent naming. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add "Home" action + whose primary purpose is to be able to open the home folder using a + keyboard shortcut. + +2005-11-10 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-monitor.c, thunar-vfs/thunar-vfs-thumb.c: Apply + patch from Erik Harrison <erikharrison@gmail.com> to fix unused + variables when FAM/Gamin and/or GConf aren't available. + +2005-11-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_init): Be sure to + update the actions whenever the current folder is changed. + +2005-11-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c(thunar_window_notify_loading): Don't force a + round-trip to the Xserver when setting/unsetting the watch cursor. + Set/unset the cursor only if the window is already realized. + * thunar/thunar-list-model.c(thunar_list_model_get_value): Don't need to + check the result of thunar_file_get_date_string() and + thunar_file_get_size_string() as they are garantied to be non-NULL. + * thunar/thunar-list-model.c(thunar_list_model_file_changed): Use + gtk_tree_path_new_from_indices() instead of gtk_tree_path_new() and + gtk_tree_path_append_index(). + * thunar/thunar-list-model.c(thunar_list_model_set_folder): Use + g_object_freeze_notify()/g_object_thaw_notify() for multiple property + change notification. + * thunar/thunar-list-model.c(thunar_list_model_get_statusbar_text): + Don't need to verify the result of thunar_file_get_size_string(), as + it's garantied to be non-NULL. + +2005-11-09 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-buttons.c + (thunar_location_buttons_set_current_directory): Be a bit smarter here + and try to reuse existing buttons whenever possible. + +2005-11-09 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Depend on GLib 2.6.4 or above. + * tdb/Makefile.am: Add _XOPEN_SOURCE=500 workaround for glibc to make + pread()/pwrite() visible to the compiler. + +2005-11-09 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-history.{c,h}, thunar/Makefile.am: Import new class + ThunarHistory, which handles back/forward history for a ThunarWindow. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Use the newly + imported class ThunarHistory to manage the navigational history for + the ThunarWindow. + +2005-11-09 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c: Display the tooltip of the currently selected + menu item in the statusbar. + * thunar/thunar-icon-render.c(thunar_icon_renderer_render): Render up + to 4 emblems for icon sizes from 48px on and up to 2 emblems for icon + sizes lower than 48px. + * thunar/thunar-icon-render.c(thunar_icon_renderer_render): Use the + proper icon factory for the target drawable, rather than the default + icon factory. + +2005-11-09 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-xfer.{c,h}: Add function thunar_vfs_xfer_link(), + which creates a symbolic link to a file. + * thunar-vfs/thunar-vfs-link-job.{c,h}, thunar-vfs/Makefile.am: Import + new class ThunarVfsLinkJob, which can be used to symlink a bunch of + files. + * thunar-vfs/thunar-vfs.{c,h}, thunar-vfs/thunar-vfs.symbols: Add + thunar_vfs_link_file() and thunar_vfs_link_files() as public interface + to the ThunarVfsLinkJob class. + * po/POTFILES.in: Add thunar-vfs-link-job.c here. + * thunar/thunar-application.{c,h}: Add thunar_application_link_into() as + interface to the thunar_vfs_link_files() method. Restructure the code + to further reduce the code duplication. + * thunar/thunar-dnd.c: Use thunar_application_link_into() to implement + the "Link here" Drag&Drop action. + * thunar-vfs/thunar-vfs-transfer-job.c + (thunar_vfs_transfer_job_copy_pair): Don't access pairs outside the + current pair list. + * thunar-vfs/thunar-vfs-xfer.c(thunar_vfs_xfer_next_path): Also detect + the "%uth copy of %s" pattern when duplicating a file. + * thunar/thunar-standard-view.c: Use upper case for substantives in + action titles where appropriate. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c: + Add "duplicate" and "make-link" actions, for duplicating/linking + files easily. + * po/*.po: Merge new strings. + +2005-11-08 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-transfer-job.c(thunar_vfs_transfer_job_new): + Verify that we don't ever try to transfer the root directory. + * thunar/thunar-file.{c,h}: Make thunar_file_cache_lookup() a public + function. + * thunar-vfs/thunar-vfs-interactive-job.{c,h}: Add a new signal + "new-files", which can be invoked by derived jobs for their new files. + The application can use this signal to get notified when a job added + new files to a folder (e.g. select them in a folder view, etc.). + * thunar-vfs/thunar-vfs-transfer-job.c: Collect the newly created paths + and emit the "new-files" signal when the execution finishes. + * thunar-vfs/thunar-vfs-monitor.{c,h}, thunar-vfs/thunar-vfs.symbols: + Add new method thunar_vfs_monitor_wait(), which can be used by helper + threads to wait until the ThunarVfsMonitor has processed all pending + notifications. + * thunar-vfs/thunar-vfs-interactive-job.c + (thunar_vfs_interactive_job_new_files): Use thunar_vfs_monitor_wait() + to delay the "new-files" emission until the application has processed + all pending notifications. + * thunar-vfs/thunar-vfs-monitor.c: Lower the notification interval to + 250 milliseconds. + * thunar-vfs/thunar-vfs-transfer-job.c(thunar_vfs_transfer_job_execute): + Don't use g_rename() for now, as it causes too much trouble right now. + * thunar/thunar-application.{c,h}, thunar/thunar-dnd.{c,h}, + thunar/thunar-clipboard-manager.{c,h}: Allow the consumers to pass + a "new-files" closure when starting a transfer job. + * thunar/thunar-list-model.{c,h}: Add new method + thunar_list_model_get_paths_for_files(), which returns the list of + tree paths for a given list of ThunarFiles. + * thunar/thunar-standard-view.c: Supply a "new-files" closure when + starting transfer jobs, and select the files that are passed to the + "new-files" callback when the job finishes. + * docs/reference/thunar-vfs/: Update the documentation bits affected + by the latest changes. + +2005-11-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.h: Add method thunar_file_is_symlink() to check + whether a given ThunarFile is a symbolic link. + * thunar/thunar-list-model.c, thunar/thunar-properties-dialog.c: Display + symbolic links properly for the MIME Type fields. + * thunar-vfs/thunar-vfs-transfer-job.{c,h}, thunar-vfs/thunar-vfs.{c,h}, + thunar-vfs/thunar-vfs.symbols: Adjust the asynchronous operations API + again to make it more constistent with the requirements of the file + manager. + * po/*.po: Merge new strings. + * thunar-vfs/thunar-vfs-monitor.c: Add tags to notifications to make + sure (slow) FAM events don't override properly feeded events, as + afterall we know best what we did. + * thunar-vfs/thunar-vfs-transfer-job.c + (thunar_vfs_transfer_job_copy_pair): Fix a typo, where the result + of thunar_vfs_transfer_job_overwrite() was not negated properly. + * thunar-vfs/thunar-vfs-xfer.c, thunar-vfs/thunar-vfs-transfer-job.c, + TODO: Automatically duplicate files when copying and the source and + target paths refer to the same file. + * thunar/thunar-application.{c,h}, thunar/thunar-standard-view.c, + thunar/thunar-clipboard-manager.{c,h}, thunar/thunar-dnd.c: Rework + the ThunarApplication API and internals to reduce the amount of + duplicated code, and make the API more consistent. + * thunar-vfs/thunar-vfs-xfer.{c,h}, thunar-vfs/thunar-vfs.c: Feed events + into the VFS monitor from the xfer module. + * thunar-vfs/thunar-vfs-transfer-job.c + (thunar_vfs_transfer_job_copy_pair): No need to feed a "created" event + into the VFS monitor, as that's done by the xfer module directly (with + the correct target path). + * docs/reference/thunar-vfs/thunar-vfs-sections.txt, + docs/reference/thunar-vfs/tmpl/thunar-vfs-operations.sgml: Update + documentation bits affected by the latest changes to the public API. + +2005-11-07 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c: Use an alloc-only memory chunk to reduce + the overhead. + * thunar/thunar-icon-factory.c(thunar_icon_factory_load_from_file): Add + the thumbnail frame after scaling down the thumbnail to the desired + size. + * thunar/thunar-icon-factory.c(thumbnail_needs_frame): Inline this + function if possible. + +2005-11-07 Benedikt Meurer <benny@xfce.org> + + * tdb/tdbtool.c: Make gcc4 happy. + * thunar/thunar-dnd.c(thunar_dnd_ask): Add icons to the "move" and + "copy" actions. + * thunar/thunar-folder.c(thunar_folder_monitor): Be sure to process + monitor events properly in either case. + * thunar-vfs/thunar-vfs-monitor.c + (thunar_vfs_monitor_queue_notification): Schedule only one + notification per handle, where "deleted" events have the highest + priority. + * docs/reference/thunar-vfs/: Update documentation. + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs-xfer.{c,h}: Add module + to copy various kinds of file system entities (basicly everything that + a normal user is permitted to create, e.g. no device nodes). + * thunar-vfs/thunar-vfs-transfer-job.{c,h}: Add new ThunarVfsTransferJob + class based on the thunar-vfs-xfer module. + * thunar-vfs/thunar-vfs.c: Use new ThunarVfsTransferJob class. + * thunar/thunar-progress-dialog.c: Improve the progress dialog. + * po/POTFILES.in, po/*.po: Update the file list and the translations. + +2005-11-04 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-transfer-job.{c,h}, thunar-vfs/thunar-vfs.{c,h}, + thunar-vfs/thunar-vfs.symbols: Update the Thunar-VFS transfer API. + * thunar/thunar-application.c: Use the new Thunar-VFS transfer API. + +2005-11-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.{c,h}: Add "renamed" signal and emit it whenever + the file is renamed by the user. + * thunar/thunar-folder.c: Use the "ThunarFile::renamed" to re-register + with the file alteration monitor under the new path. + * thunar/thunar-window.c: Update the window icon and title whenever the + current-directory is changed (e.g. the user renamed the directory + file). + * thunar-vfs/thunar-vfs-monitor.c: Place the timeout into a preprocessor + define. + * tdb/, AUTHORS, FAQ, configure.in.in, Makefile.am: Import the tdb - the + Trivial Database - engine from the Samba suite, which will be used to + store file metadata in a lightweight and efficient way. + * thunar/thunar-metafile.{c,h}, thunar/Makefile.am: Add ThunarMetafile + class, which handles metadata for files based on a tdb database. + * thunar/thunar-file.{c,h}: Add methods to access metadata for a given + ThunarFile. + * thunar/thunar-file.c: Query additional emblems from the file's + metadata (in addition to the special emblems that are set + automcatically). + * thunar/thunar-emblem-chooser.{c,h}, thunar/Makefile.am: Add + ThunarEmblemChooser widget class, to edit the list of additional + emblems for a ThunarFile. + * thunar/thunar-standard-view.c: Synchronize the show-hidden property. + * thunar/thunar-properties-dialog.c: Add a notebook tab for the Emblems. + +2005-11-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.c: Use THUNAR_FILE_IN_DESTRUCTION as destruction + flag rather than GTK_IN_DESTRUCTION. + +2005-11-01 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-unlink-job.c(thunar_vfs_unlink_job_remove): + Also remove thumbnails when successfully deleting a regular file. + * thunar-vfs/thunar-vfs-thumb-jpeg.{c,h}, thunar-vfs/Makefile.am, + configure.in.in: Add fast JPEG loader, which is able to scale down + the data while loading it. + * thunar-vfs/thunar-vfs-thumb.c: Use the fast JPEG loader to generate + thumbnails for JPEG files (if supported). + +2005-11-01 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs.symbols: Add + attribute custom_icon to the ThunarVfsInfo struct instead of the hints + framework and a new method thunar_vfs_info_get_custom_icon() to query + the custom icon from a ThunarVfsInfo. + * thunar-vfs/thunar-vfs-thumb.c + (thunar_vfs_thumb_factory_store_thumbnail): Fix invalid check for + valid pixbuf. + * thunar-vfs/thunar-vfs-info.c(_thunar_vfs_info_new_internal): Be sure + to remove any file extension (e.g. '.png') from themed icon names, so + GtkIconTheme is able to locate the icon. + * thunar-vfs/thunar-vfs-info.c: Don't treat .directory files like other + .desktop files, as that's confusing for the casual user. + * thunar/thunar-file.{c,h}: Add method thunar_file_get_custom_icon() + to return the custom icon set for the associated ThunarVfsInfo. + * thunar/thunar-file.c(thunar_file_get_icon_name): Don't return the + custom icon here. + * thunar/thunar-icon-factory.c(thunar_icon_factory_load_file_icon):Check + first if the ThunarFile specifies a custom icon and try to load it, + falling back to thumbnails and regular (mime) icons. + +2005-10-31 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.h: Add thunar_file_is_regular() to check whether a + ThunarFile is a regular file. + * thunar/thunar-file.h: Add thunar_file_get_info() to query the + ThunarVfsInfo for a given ThunarFile. + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs.symbols: Add + new method thunar_vfs_info_copy(), which takes a deep copy of a + ThunarVfsInfo. + * thunar-vfs/thunar-vfs-job.{c,h}, thunar-vfs/thunar-vfs.symbols: Turn + thunar_vfs_job_cancelled() into an inline function. + * thunar-vfs/thunar-vfs-thumb.{c,h}, thunar-vfs/thunar-vfs.symbols, + thunar-vfs/Makefile.am: Readd the ThunarVfsThumbFactory class and + adjust it to use ThunarVfsInfo's instead of ThunarVfsURI's. + * configure.in.in, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs-thumb.{c,h}: Add optional support for GNOME + thumbnailers, which requires GConf. + * thunar/thunar-thumbnail-generator.{c,h}, thunar/Makefile.am: Add new + class ThunarThumbnailGenerator, which is used to asynchronously + generate and store thumbnails for files. + * thunar/thunar-icon-factory.{c,h}: Add support for loading thumbnails. + Add support for generating thumbnails using the new + ThunarThumbnailGenerator class. + * configure.in.in: Bump version to 0.1.3. + +2005-10-30 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-listdir-job.c(thunar_vfs_listdir_job_execute): + Don't immediately terminate the second collector task. + +2005-10-30 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-scandir.c: Don't report EMLINK at all. + +2005-10-30 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-scandir.c(thunar_vfs_scandir): Treat EMLINK + like ENOTDIR, since there's no GFileError to represent EMLINK. + +2005-10-29 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-cache.c(cache_node_lookup_suffix): Always + check the return value to avoid guessing invalid mime types just + because of misleading stopchars. + * thunar/thunar-file.c(thunar_file_get_icon_name): Try to be smart when + looking up the icon name for binaries. + +2005-10-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-clipboard-manager.{c,h}: Use ThunarFile to copy/cut to + the clipboard and monitor the files for deletion. + * thunar/thunar-clipbard-manager.{c,h}: Add new method + thunar_clipboard_manager_has_cutted_file() to check whether a certain + file was cutted to the clipboard. + * thunar/thunar-gdk-pixbuf-extensions.{c,h}: Add new function + thunar_gdk_pixbuf_lucent() when generates a translucent pixbuf. + * thunar/thunar-standard-view.c: Use the new clipboard manager + interface. + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Render + translucent icons for files previously cutted to the clipboard. + * thunar/thunar-window.c: Queue a draw on the window whenever the + clipboard contents change to be sure to always display correct + state. + +2005-10-28 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-monitor.c(thunar_vfs_monitor_feed): Be sure to + schedule directory events only for handles that were registered as + directory. + * thunar-vfs/thunar-vfs-unlink-job.c(thunar_vfs_unlink_job_execute): + Ignore ENOTDIR errors when collecting the files to delete. + * thunar-vfs/thunar-vfs-exec.c(tvsn_startup_timeout), + (thunar_vfs_exec_on_screen): Don't use libsn functions outside the + GDK lock. + * thunar/thunar-file.{c,h}: Inline the most trivial methods. + * thunar-vfs/thunar-vfs-user.{c,h}: Implement ThunarVfsUser and + ThunarVfsGroup directly for local user/group management. + +2005-10-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-clipboard-manager.c + (thunar_clipboard_manager_paste_path_list): Fix possible segmentation + fault. + +2005-10-27 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-interactive-job.{c,h}: Add a VFS monitor pointer + to the interactive job, which will be used by the derived classes to + communicate fs changes to the application. + * thunar-vfs/thunar-vfs-unlink-job.c(thunar_vfs_unlink_job_remove): Feed + deleted events into the VFS monitor whenever a file was successfully + unlinked from the file system, so the application can be updated even + if no file system monitoring mechanism like FAM or Gamin is available. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c: Add + the "Delete file(s)" operation to the user interface. + +2005-10-27 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add optional check for libstartup-notification-1.0. + * thunar-vfs/thunar-vfs-exec.{c,h}, thunar-vfs/Makefile.am: Add optional + support for startup notification. + * thunar-vfs/thunar-vfs-info.c, + thunar-vfs/thunar-vfs-mime-application.c: Use the thunar-vfs-exec + module. + * thunar-vfs/thunar-vfs-transfer-job.c: Don't include + thunar-vfs-sysdep.h anymore. + * po/POTFILES.in: Remove thunar-vfs-sysdep and add thunar-vfs-exec. + +2005-10-22 Benedikt Meurer <benny@xfce.org> + + * thunarx/thunarx-config.c: Fix typo. + * thunar-vfs/thunar-vfs-config.{c,h.in}, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs.symbols, thunar-vfs/abicheck.sh, + thunar-vfs/thunar-vfs.h, configure.in.in: Add support for version + checking to the Thunar-VFS library. + * thunar-vfs/*.[ch], thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs.symbols: Replace ThunarVfsURI with ThunarVfsPath + for the first version and thereby limit the functionality to local + files, which in turn means there's no trash and no computer folder. + This will increase the chance that Thunar will be ready for the Xfce + 4.4.0 release. + * thunar/*.[ch], thunar/Makefile.am: Use ThunarVfsPath instead of + ThunarVfsURI. + * tests/test-thunar-vfs-path.c, tests/test-thunar-vfs-uri.c, + tests/Makefile.am: Replace the ThunarVfsURI test case with a new + ThunarVfsPath test case. + * tests/test-thunar-vfs-volume-bsd.c: Properly initialize and shutdown + the Thunar-VFS library. + * po/POTFILES.in: Update the file list. + * docs/: Sync the documentation with the changes. + * configure.in.in: Don't use -fvisibility=hidden as that causes trouble + with inline functions that are also implemented and exported by the + library. Instead we explicitly mark internal functions with + G_GNUC_INTERNAL. + +2005-10-03 Benedikt Meurer <benny@xfce.org> + + * THANKS, configure.in.in, po/es.po: Add spanish translations, thanks + to Pablo Hernández-M. Saiz <homeless3d@gmail.com>. + +2005-10-02 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-monitor.c: Fire notifications asynchronously, so + events can be injected from threads other than the main thread. This + also fixes problems with Gamins kqueue/inotify backends. + +2005-10-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c(thunar_properties_dialog_update): + Don't update the name label/window title unless the file name has + changed. + +2005-09-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c(thunar_launcher_update): Use mnemonics for + the "Open"/"Execute" action. + * po/de.po: Add initial, incomplete translations. + +2005-09-27 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Substitute platform flags properly. + * thunar/Makefile.am: Don't delete thunar-thumbnail-frame.h. + * thunar/thunar-standard-view.c(thunar_standard_view_selection_changed): + Use ngettext() for the Cut/Copy File(s) actions. + * thunar/thunar-file.{c,h}: Add new virtual method get_actions(), which + is used to support custom actions for certain files (e.g. the Empty + Trash Bin action for the trash file). + * thunar/thunar-application.{c,h}: Add thunar_application_delete_uris() + to be able to easily delete arbitrary files. + * thunar/thunar-trash-file.c(thunar_trash_file_new): Use + thunar_file_destroy() instead of gtk_object_destroy(). + * thunar/thunar-trash-folder.c: Implement the get_actions() method with + the "Empty Trash Bin" action. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c: + Extend the extension menu merge mechanism to also load custom actions + provided by ThunarFile implementations. + * thunar/thunar-file.c(thunar_file_accepts_uri_drop): Fix typo. + * thunar/thunar-trash-folder.c: Watch files for changes. + * thunar/thunar-favourites-view.c + (thunar_favourites_view_button_press_event): Add custom actions to the + favourite context menu. + * TODO: Drop completed item. + * configure.in.in: Disable strict aliasing if debugging is enabled and + the compiler supports the -fno-strict-aliasing switch. + * po/*.po: Update translations. + * main.c(main): Initialize file properly. + * thunar/thunar-file.c(thunar_local_file_is_renameable): Don't permit + users to rename root nodes. + * thunar/thunar-open-with-action.c(thunar_open_with_action_menu_mapped): + Use "Other Application..." instead of just "Other...". + +2005-09-23 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c(thunar_details_view_button_press_event), + thunar/thunar-icon-view.c(thunar_icon_view_button_press_event): Open + folders in new windows on double middle-click events. + +2005-09-22 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Fix typo. + +2005-09-22 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-*.c: Documentation tweaks. + * configure.in.in, docs/reference/Makefile.am, + docs/reference/thunar-vfs/: Prepare Thunar-VFS reference manual. + * thunar/thunar-list-model.c(thunar_list_model_get_statusbar_text): + Use ngettext() for the statusbar text. + * thunar/thunar-launcher.c(thunar_launcher_update): Use ngettext() for + the "Open in n New Windows" menu label. + * thunar/thunar-launcher.c(thunar_launcher_open_new_windows): Use + ngettext() for the question whether to open n separate windows. + * thunar/thunar-launcher.c(thunar_launcher_open_uris): Use ngettext() + to format the error message when opening multiple URIs at once + failes. + * po/*.po: Update po files. + * configure.in.in, examples/open-terminal-here/Makefile.am, + thunar-vfs/Makefile.am, thunar/Makefile.am, thunarx/Makefile.am: + Don't add debugging and visibility flags to CFLAGS, CPPFLAGS and + LDFLAGS, but use PLATFORM_CFLAGS, PLATFORM_CPPFLAGS and + PLATFORM_LDFLAGS instead to avoid trouble with certain conftests + when checking the distribution. + +2005-09-22 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-trash.h: Fix typo. + * thunar/thunar-chooser-dialog.c(thunar_chooser_dialog_response): Handle + absolute paths properly for custom commands. + +2005-09-20 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-application.{c,h}, + thunar-vfs/thunar-vfs.symbols: Load the supported mime types for the + applications. + * thunar-vfs/thunar-vfs-mime-application.{c,h}, + thunar-vfs/thunar-vfs.symbols: Add a new constructor + thunar_vfs_mime_application_new_from_file() for the special case + where a particular file should be loaded by path. + * thunar-vfs/thunar-vfs-mime-application.c + (thunar_vfs_mime_application_equal): Properly initialize the + application variables. + * thunar-vfs/thunar-vfs-mime-application.c + (thunar_vfs_mime_application_lookup_icon_name): Permit applications + to specify absolute paths for the icon name. + * thunar-vfs/thunar-vfs-mime-database.{c,h}, + thunar-vfs/thunar-vfs.symbols: Extend the mime database by a new + method thunar_vfs_mime_database_set_default_application(), which is + used to set the default application for a given mime type. + * thunar-vfs/thunar-vfs-sysdep.c(_thunar_vfs_sysdep_parse_exec): Fix + typo to properly execute applications that require a terminal. + * thunar-vfs/thunar-vfs-mime-database.c + (thunar_vfs_mime_database_get_applications): Always prepend the + default applications for the given mime info to the list returned + from this method. + * thunar/thunar-favourites-model.c(thunar_favourites_model_save): Use + g_mkstemp() to create the temporary file. + * thunar-vfs/thunar-vfs-mime-application.{c,h}, + thunar-vfs/thunar-vfs.symbols: Add public flags to the mime + applications. + * thunar-vfs/thunar-vfs-mime-application.c + (thunar_vfs_mime_application_new_from_file): Strip off known suffixes + for image files if a themed icon is specified. This way we can + work-around quite a few broken .desktop files. + * thunar-vfs/thunar-vfs-mime-database.{c,h}, + thunar-vfs/thunar-vfs.symbols: Support the addition of custom + applications using thunar_vfs_mime_database_add_application() in + a way compatible to what Nautilus does (which is actually quite a + mess). + * thunar/thunar-chooser-dialog.{c,h}, thunar/thunar-chooser-model.{c,h}, + thunar/Makefile.am: Import the "Open With" dialog based on the two + classes ThunarChooserDialog and ThunarChooserModel, which in turn are + based on the new functionality provided by Thunar-VFS, and thereby + permit the user to associate applications with files (actually mime + types) and add new applications. + * thunar/thunar-launcher.c: Connect the "Open With Other" action to + the new ThunarChooserDialog. + * thunar/thunar-favourites-model.c: Document the drag source functions. + * README: Add a list of dependencies for Thunar. + * TODO: Drop completed items. + +2005-09-17 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-database.c: Include exo/exo.h. + +2005-09-15 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-bsd.c, + thunar-vfs/thunar-vfs-volume-sysv.c: Include thunar-vfs-alias.h. + +2005-09-15 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-progress-dialog.c: Use GObject for the job instead of + ExoObject. + +2005-09-15 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-interactive-job.{c,h}, + thunar-vfs/thunar-vfs-job.{c,h}, + thunar-vfs/thunar-vfs-listdir-job.{c,h}, + thunar-vfs/thunar-vfs-transfer-job.{c,h}, + thunar-vfs/thunar-vfs-unlink-job.{c,h}: Allocate a new main loop for + every running job so we can terminate them properly and be sure to + run the finalize method in the main thread. This enables us to use + arbitrary GObjects within a job without having to worry about the + reference counting problem in GLib 2.6. The jobs are GObjects as well + now to easily support language bindings and allow us to drop the + problematic ExoObject class. + +2005-09-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c(thunar_launcher_open_files): Use + g_object_unref() instead of exo_object_unref(). + +2005-09-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-application.{c,h}, + thunar-vfs/thunar-vfs-mime-database.c, thunar-vfs/thunar-vfs.symbols, + thunar/thunar-launcher.c, thunar/thunar-marshal.list, + thunar/thunar-open-with-action.c: Turn ThunarVfsMimeApplication into + a boxed type. + * thunar/thunar-window.c: Apply Daichis patch to make the dynamic + actions titles translatable (#1153). + +2005-09-13 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.c, thunar-vfs/thunar-vfs-mime-database.c, + thunar-vfs/thunar-vfs-mime-info.{c,h}, thunar-vfs/thunar-vfs-thumb.c, + thunar-vfs/thunar-vfs.symbols: Turn ThunarVfsMimeInfo into a boxed + type. + * thunar-vfs/thunar-vfs-mime-provider.c: No need to provide fallback + implementations for the virtual methods, as both providers implement + all virtual methods. + * thunar-vfs/thunar-vfs-mime-provider.{c,h}, + thunar-vfs/thunar-vfs-mime-cache.c, + thunar-vfs/thunar-vfs-mime-legacy.c, + thunar-vfs/thunar-vfs-mime-database.c: Derive the MIME providers from + GObject instead of ExoObject. + * thunar-vfs/thunar-vfs-mime-database.c, thunar-vfs/thunar-vfs-info.c, + thunar-vfs/thunar-vfs-thumb.c, thunar-vfs/thunar-vfs.c, + thunar/thunar-computer-folder.c, thunar/thunar-file.c, + thunar/thunar-open-with-action.c, thunar/thunar-trash-folder.c: + Derive ThunarVfsMimeDatabase from GObject instead of ExoObject. + +2005-09-13 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-sysdep.h: Add inline atomic operations. + * thunar-vfs/thunar-vfs-info.c, thunar-vfs/thunar-vfs-listdir-job.c, + thunar-vfs/thunar-vfs-mime-application.c, + thunar-vfs/thunar-vfs-mime-database.c, + thunar-vfs/thunar-vfs-monitor.c, + thunar-vfs/thunar-vfs-sysdep.c, thunar-vfs/thunar-vfs-thumb.c, + thunar-vfs/thunar-vfs-transfer-job.c, thunar-vfs/thunar-vfs-trash.c, + thunar-vfs/thunar-vfs-uri.{c,h}, thunar-vfs/thunar-vfs.c, + thunar-vfs/thunar-vfs.symbols, thunar/thunar-clipboard-manager.c, + thunar/thunar-computer-folder.c, thunar/thunar-favourites-model.c, + thunar/thunar-favourites-view.c, thunar/thunar-file.c, + thunar/thunar-icon-factory.c, thunar/thunar-local-file.c, + thunar/thunar-local-folder.c, thunar/thunar-location-buttons.c, + thunar/thunar-path-entry.c, thunar/thunar-standard-view.c, + thunar/thunar-statusbar.c, thunar/thunar-trash-file.c, + thunar/thunar-trash-folder.c: Turn ThunarVfsURI into a boxed type + to make language bindings easier and reduce the overhead. Drop the + foreign host support code, as we can't use it anyways, since nearly + every other existing application that handles file URIs is broken + when it comes to file URIs with authorities. Simplify the + thunar_vfs_uri_to_string() method again and return only escaped + versions of the URI. + * thunar/thunar-path-entry.c(thunar_path_entry_set_current_file): + Display file URIs for non-UTF8 paths. + * tests/test-thunar-vfs-uri.c, tests/test-thunar-vfs-volume-bsd.c: + Update the tests. + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs-info.h, + thunar-vfs/thunar-vfs-types.h: Move the system-dependent types to + thunar-vfs-types.h. + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs.symbols: + Turn ThunarVfsInfo into a boxed type. + +2005-09-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Sort the extension actions by their + names instead of their labels. + * thunar/thunar-extension-manager.c(thunar_extension_class_init): + Properly initialize the parent class reference. + * examples/open-terminal-here/Makefile.am: Don't specify CLEANFILES + explicitly. + * thunar/thunar-file.c(thunar_file_get_mime_info): Documentation fix. + * thunar-vfs/thunar-vfs-mime-database.c + (thunar_vfs_mime_database_get_info_for_file): When generating an + application/x-extension-<EXT> mime type and no valid extension is + found for the file name, fallback to the whole filename as suggested + by jrb. This way we can make sure that we will never return + application/octet-stream from this method and thereby allow the + program chooser to set default applications for every mime type + used in the file manager. + * thunar/Makefile.am: Add $(top_builddir) to INCLUDES. + +2005-09-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Sort the extension actions by their + labels prior to adding them to the UI manager. + +2005-09-11 Benedikt Meurer <benny@xfce.org> + + * examples/open-terminal-here/open-terminal-here.c + (open_terminal_here_activate): Remove unused debug statement. + +2005-09-09 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Substitute version information. + * thunar/thunar-window.c(thunar_window_action_about): Escape the + copyright sign. + * thunar/thunar-gdk-pixbuf-extensions.{c,h}, + thunar/thunar-gtk-extensions.{c,h}, thunar/thunar-desktop-view.c, + thunar/thunar-icon-factory.c, thunar/thunar-icon-renderer.c, + thunar/thunar-standard-view.c, thunar/thunar-window.c, + thunar/Makefile.am: Merge the GdkPixbuf and GTK+ extensions into + the thunar namespace. + * configure.in.in, thunarx/: Import the initial extensions library. + * configure.in.in, docs/Makefile.am, Makefile.am, docs/reference/: + Import the reference manual for the extensions library. + * thunar/thunar-file.c: Implement the ThunarxFileInfo interface. + * thunar/thunar-extension-manager.{c,h}, thunar/Makefile.am: Import the + ThunarExtensionManager class. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c: Add + support for context menu providers to the standard views. + * po/POTFILES.in: Add thunarx/thunarx-property-page.c here. + * thunar/thunar-properties-dialog.c: Add support for property page + providers here. + * Makefile.am, configure.in.in, examples/Makefile.am, + examples/open-terminal-here/: Add "Open Terminal Here" menu provider + example. + +2005-09-06 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c: Don't emit the "row-inserted" and + "row-deleted" signals when changing folders unless somebody + is actually interested in these signals. + * thunar/thunar-list-model.c(thunar_list_model_set_folder): Actually + specify the correct path when deleting the previous items from the + model. + * thunar/thunar-local-folder.c(thunar_local_folder_file_destroy): No + need to request a new list from GLib here. + * thunar/thunar-local-folder.c(thunar_local_folder_infos_ready): Don't + add new files to two lists. Instead add them to one temporary list + and append the temporary list to the internal list later. + * thunar/thunar-local-file.c(thunar_local_file_get_for_info): Fix an + invalid instance cast check. + * thunar/thunar-file.c: Manage the file cache directly without using + weak references to avoid problems and save memory (weak references + are allocated in the GObject dataset). + +2005-09-06 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-local-file.c: Store the VFS monitor handle in the + GObject dataset as it's used only for explicit file monitoring (e.g. + for the properties dialog). + * thunar/thunar-list-model.c(thunar_list_model_get_iter): Skip every + second comparison for iter lookups. + * icons/, configure.in.in, Makefile.am: Add the Thunar icon. + +2005-09-06 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.c: Invoke the parent's finalize method, as + that will be required for language bindings once we have weak/toggle + references for ExoObject. + * thunar/thunar-local-file.c(thunar_local_file_rename): Re-register with + the VFS monitor if the rename succeeds. + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_hash): Don't hash the + hostname if it's NULL. + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_equal): We don't need to + query the hostname string here, as local files will always have host + set to NULL. + * tests/test-thunar-vfs-uri.c(main): Extend the ThunarVfsURI test. + * pixmaps/, Makefile.am, configure.in.in, thunar/thunar-window.c, + thunar/Makefile.am: Initial idea for the about dialog logo. + +2005-09-05 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs-listdir-job.c: + Use GList instead of GSList to manage ThunarVfsInfo lists, which + increases data locality and decreases memory usage (as there's no + need to keep another allocator around any more). + * thunar/thunar-computer-folder.c, thunar/thunar-folder.{c,h}, + thunar/thunar-list-model.c, thunar/thunar-local-folder.c, + thunar/thunar-trash-folder.c: Use GList instead of GSList to manage + the list of files for a folder for the same reason. + * thunar/thunar-file.{c,h}, thunar/thunar-folder.c, + thunar/thunar-local-folder.c, thunar/thunar-local-file.c: ThunarFile + is derived from GObject now, instead of GtkObject. + * thunar/thunar-list-model.c: No need to implement GtkTreeDragDest, + as that's handled in ThunarStandardView. + +2005-09-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-launcher.c, thunar/thunar-list-model.c, + thunar/thunar-open-with-action.c, thunar/thunar-properties-dialog.c: + We don't need to check the result of thunar_file_get_mime_info() any + more as it's garantied to be a valid ThunarVfsMimeInfo. + +2005-09-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-computer-folder.c, thunar/thunar-file.c, + thunar/thunar-list-model.c: Always return a valid ThunarVfsMimeInfo + from the get_mime_info() method. + +2005-09-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.{c,h}: Drop the unused icon columns from the + ThunarListModel. + +2005-09-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Generate + the colorized/spotlighted version of the icon only if the icon area + is affected by expose event. + +2005-09-04 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.c(escape): And of course, we need to escape + the '+' and '%' characters in URIs. + +2005-09-04 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.c(escape): Also escape '&' in URIs. + +2005-09-04 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-thumb.{c,h}: Implement the store thumbnail + functionality. + * thunar-vfs/thunar-vfs-sysdep.c, thunar-vfs/thunar-vfs-trash.c, + thunar-vfs/thunar-vfs-uri.{c,h}, thunar-vfs/thunar-vfs.symbols, + thunar/thunar-clipboard-manager.c, thunar/thunar-favourites-model.c, + thunar/thunar-favourites-view.c, thunar/thunar-file.c, + thunar/thunar-location-buttons.c, thunar/thunar-path-entry.c, + thunar/thunar-standard-view.c, thunar/thunar-statusbar.c: Improve + the thunar_vfs_uri_to_string() method to support UTF-8 URI strings + and escaping of URIs, which is required for proper Drag'n'Drop + interaction with other applications. + +2005-09-04 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.{c,h}: Store the watch count in the GObject data + list, as it seldomly used. + * thunar/thunar-file.c(thunar_file_load_icon): Try to load the "loading" + icon directly instead of checking the icon theme first. + * thunar/thunar-standard-view.c: Revert the "num-files" special handling + as it leads to a bug where the actions aren't updated properly when + changing directories. + * thunar-vfs/thunar-vfs-sysdep.h: Fix typo. + * thunar-vfs/thunar-vfs-transfer-job.c, + thunar-vfs/thunar-vfs-unlink-job.c: Unlink thumbnails after removing + a file to reduce the junk in ~/.thumbnails/. + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_get_md5sum): Escape the + path properly, so the thumbnail paths we determine are equal to those + of other file managers. + +2005-09-04 Benedikt Meurer <benny@xfce.org> + + * thunar/Makefile.am: Add the thumbnail frame source image to the + distribution. + * thunar/thunar-icon-factory.c: Add some more cleverness in determining + whether or not to add a frame to a thumbnail. + +2005-09-03 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs.symbols, thunar-vfs/thunar-vfs-mime-info.{c,h}, + thunar-vfs/thunar-vfs-mime-database.c: Determine media and subtype of + a ThunarVfsMimeInfo on-demand. + * thunar-vfs/thunar-vfs-info.c(thunar_vfs_info_new_for_uri): Move the + .desktop file handling to the regular file case. + * thunar-vfs/thunar-vfs-thumb.{c,h}, thunar-vfs/thunar-vfs.symbols, + thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs.h: Import the + ThunarVfsThumbFactory class, which implements the freedesktop + thumbnail management specification. + * thunarx/thunarx-gdk-pixbuf-extensions.{c,h}: Add new helper function + thunarx_gdk_pixbuf_frame(), which is used to embed an arbitrary image + into a frame (e.g. for thumbnails). + * thunar/thunar-favourites-model.c, thunar/thunar-file.c, + thunar/thunar-icon-factory.{c,h}, thunar/thunar-icon-renderer.c, + thunar/thunar-list-model.c, thunar/thunar-location-buttons.c, + thunar/thunar-window.c: Make sure we don't leak the default icon + factory instance on exit. + * thunar/Makefile.am, thunar/thunar-thumbnail-frame.{h,png}: Import + the thumbnail frame image used by Nautilus. + * thunar/thunar-icon-factory.{c,h}: Add thumbnail loading support to + the icon factory and reorganize the internals a bit. + * thunar/thunar-file.c: Load thumbnails for regular if possible. + +2005-09-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Don't + scale the icon if it fits into the cell area. + +2005-09-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-text-renderer.c: Select the text prior to the last + dot when starting to edit a cell. + * thunar/thunar-properties-dialog.c(thunar_properties_dialog_update): + Place input focus on the name entry widget and select the text prior + to the last dot. + +2005-09-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-open-with-action.c(thunar_open_with_action_activated): + Remove obsolete code. + * thunar/thunar-standard-view.c + (thunar_standard_view_button_release_event): Don't popup the context + menu using the just released button, as that would render the items + unclickable. + +2005-09-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Avoid going through the selection + changed handling whenever the number of files in a model changes, + as the only thing that needs updating here is the statusbar text. + * thunar-vfs/thunar-vfs-mime-cache.c + (thunar_vfs_mime_cache_lookup_parents): Fix the offset from which the + parent mime type name is read. + * thunar-vfs/thunar-vfs-mime-cache.c(cache_node_lookup_suffix): + Optimize the tail-recursive suffix lookup. + * thunar-vfs/thunar-vfs-mime-database.c + (thunar_vfs_mime_database_get_info_for_file): Use fast stack memory + for the extattr and content lookups. + +2005-09-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-factory.c(thunar_icon_factory_lookup_icon): Add + support to load icons from absolute paths. + * thunar/thunar-local-file.c(thunar_local_file_get_icon_name): Allow the + VFS layer to pass absolute paths for the file icon hint. This is + required for some .desktop files, that specify absolute icon paths + instead of themed icon names. + * thunar/thunar-location-buttons.c(thunar_location_buttons_make_button): + Don't permit location buttons to grab the focus. + +2005-09-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c: Be sure to override the default + drag-data-delete handler of ExoIconView/GtkTreeView. + * thunar/thunar-icon-view.c(thunar_icon_view_get_path_at_pos): The + exo_icon_view_get_path_at_pos() method really accepts widget + coordinates now, like GtkTreeView does, so we don't need to translate + the widget coordinates to icon window coordinates first. + +2005-09-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_get_dest_actions): + Set the drop-file icon renderer property only if we have a valid + drag action. + * thunar/thunar-local-file.c(thunar_local_file_accepts_uri_drop): Do + not accept directory drops if the directory isn't writable. + +2005-09-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Prelight + drop destination icons. + +2005-09-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-computer-folder.c, thunar/thunar-desktop-view.c, + thunar/thunar-favourites-model.c, thunar/thunar-file.{c,h}, + thunar/thunar-list-model.c, thunar/thunar-local-file.c, + thunar/thunar-location-buttons.c, thunar/thunar-path-entry.c, + thunar/thunar-properties-dialog.c, thunar/thunar-standard-view.c, + thunar/thunar-statusbar.c, thunar/thunar-trash-file.c, + thunar/thunar-trash-folder.c, thunar/thunar-window.c: Add an icon + state parameter to the ThunarFile icon loader, which allows to grab + icons for a certain state from a given file. + * thunar/thunar-file.c: Drop the cached icon, as the ThunarIconFactory + does this pretty well already and we don't need to keep an additional + cached version of every file's icon. + * thunar/thunar-icon-renderer.c, thunar/thunar-standard-view.c: Use the + drop icon for the views while dragging over an item/row in the view. + +2005-09-01 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-listdir-job.c: Fix the pre-sorting of files, so + upper layers always receive the info list sorted by name. + * thunar/thunar-details-view.c(thunar_details_view_button_press_event), + thunar/thunar-icon-view.c(thunar_icon_view_button_press_event): Don't + popup the context menu immediately on right-clicks, but schedule the + menu popup using thunar_standard_view_queue_popup(). + * thunar/thunar-standard-view.{c,h}: Add the ability to start a drag + operation using the right mouse button. + * thunar/thunar-file.{c,h}: Add virtual method accepts_uri_drop() and + method thunar_file_accepts_uri_drop(), which are used to determine + whether it is possible to drop a certain list of ThunarVfsURIs on + a given ThunarFile (using a set of actions specified by the drag + source). + * thunar/thunar-local-file.c: Implement the accepts_uri_drop() method + for local file handling. + * thunar/thunar-progress-dialog.c(thunar_progress_dialog_ask), + (thunar_progress_dialog_error): Be sure to display the progress dialog + prior to opening an error or question dialog. + * thunar-vfs/thunar-vfs-info.c(thunar_vfs_info_rename): Fix gcc4 + warning. + * thunar-vfs/thunar-vfs.symbols: Add missing thunar_vfs_rename symbol. + * thunar/thunar-favourites-model.c(thunar_favourites_model_get_value): + Work-around a compiler bug with newer gcc versions. + * thunar/thunar-standard-view.{c,h}: Turn ThunarStandardView into a + valid drop site with support for text/uri-list drops. + * thunar/Makefile.am, thunar/thunar-dnd.{c,h}: Add DnD helper functions, + which can be used by other modules as well (e.g. for the desktop + view). + +2005-08-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-model.c: Drop the icon caching from the + favourites model as it causes trouble with icon theme changing and + is unnecessary since the ThunarIconFactory already performs quite + well at caching icons. + * thunar/thunar-location-buttons.c: Reload the icons for the location + buttons when the active icon/gtk theme is changed. + +2005-08-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-local-file.c(thunar_local_folder_infos_ready): Do not + compare the newly inserted files, as they are garantied to be + different from each other. + * thunar-vfs/thunar-vfs-info.c(thunar_vfs_info_matches): Move the URI + comparison to the end as that takes most of the time. + * thunar-vfs/thunar-vfs-listdir-job.c(thunar_vfs_listdir_job_execute): + Pre-sort the names in ascending order to get faster inserts for the + usual case where the user sorts its views by name. + +2005-08-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-properties-dialog.c: Adjust the "editability" of the + name entry widget depending on whether the file can be renamed. + * thunar-vfs/thunar-vfs-info.{c,h}: Add methd thunar_vfs_info_rename() + which supports renaming of regular files and .desktop files. + * thunar/thunar-file.{c,h}: Add _thunar_file_cache_rename() to support + ThunarFile implementations that provide the thunar_file_rename() + method. + * thunar/thunar-local-file.c: Add support to rename local files based + on thunar_vfs_info_rename(). + * thunar/thunar-properties-dialog.c: Allow users to rename files using + the name entry widget. + * thunar/thunar-list-model.c(thunar_list_model_file_changed): Re-sort + the model as the file may have changed its name. + * thunar/thunar-list-model.c(thunar_list_model_sort): Avoid the GArray + overhead and try to use stack memory if possible. + * thunar/thunar-standard-view.h, thunar/thunar-details-view.c, + thunar/thunar-icon-view.c: Add virtual methods set_cursor() and + scroll_to_path() to the ThunarStandardView class and implement them + in ThunarDetailsView and ThunarIconView. + * thunar/thunar-standard-view.c: Implement the "Rename" action based + on the inline editing capabilities of ThunarTextRenderer. + +2005-08-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-view.c(thunar_favourites_view_init): Use + auto-sizing for the favourites column. + * thunar/thunar-favourites-model.{c,h}, thunar/thunar-favourites-view.c: + Add support for Gtk+ 2.8 shortcuts, which allow the user to assign + aliases with mutable shortcuts. + +2005-08-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c, thunar/thunar-icon-view.c, + thunar/thunar-standard-view.{c,h}: Turn the name cell renderer into + a property of the ThunarStandardView class, so related functionality + can be easily shared between the icon and details views. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-window-ui.xml: Add + placeholder for alteration actions to the "Edit" menu in the thunar + window and fill this placeholder with the "Rename" action in the + standard view. In addition, add the "Rename" action to the file + context menu. + * thunar/thunar-file.{c,h}: Add rename functionality to the ThunarFile + interface. + * thunar/thunar-standard-view.c(thunar_standard_view_selection_changed): + Enable the "Rename" action if exactly one file is selected and that + file is renameable. + +2005-08-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-model.c: Use GLib linked lists to manage + the favourites. + * thunar/thunar-favourites-model.c: Monitor the bookmarks file for + changes. + +2005-08-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add side pane + selection to the View menu. + +2005-08-29 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Check for Intel MMX Intrinsics header. + * thunarx/thunarx-gdk-pixbuf-extensions.c: Use Intel MMX Intrinsics to + speed up pixbuf operations, if supported by the compiler (the -mmmx + option in gcc). + * thunar/thunar-window.c(thunar_window_action_location_bar_changed): + Apply the location bar patch submitted by Jeffs Franks + <jcfranks@tpg.com.au> in a slightly modified form. + +2005-08-28 Benedikt Meurer <benny@xfce.org> + + * po/POTFILES.in: Remove thunar-vfs-mime.{c,h}. + * po/*.po: Update .po files. + +2005-08-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_sort): Use temporary + storage on the stack, rather than the heap. + * thunar/thunar-list-model.c: Derive from GObject rather than + GtkObject, as we don't need GtkObject's features anymore in + ThunarListModel. + * thunar/thunar-list-model.c(thunar_list_model_class_init): Use + EXO_PARAM_* macros rather than G_PARAM_*. + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_equal): Add a check to + see whether the compared references refer to the same object, which + can happen quite often (in case of a positive match). + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_list_to_string): Prealloc + a buffer of 512 bytes for the URI list string representation. + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_list_free): Use + g_list_foreach() to unref the URIs. + * thunar/thunar-local-file.c(thunar_local_file_get_emblem_names): + Properly verify the parent uri when testing for the Desktop + directory. + * thunar-vfs/thunar-vfs.{c,h}, thunar-vfs/Makefile.am: Drop the + thunar_vfs_mime_info_get() and thunar_vfs_mime_info_get_for_file() + methods, and merge the thunar-vfs-mime initialization into the + thunar-vfs initialization routines. + +2005-08-28 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.{c,h}, thunar/thunar-local-file.c, + thunar/thunar-standard-view.c: Rename can_execute(), can_read() and + can_write() to is_executable(), is_readable() and is_writable() to + get consistent naming. + * thunar-vfs/thunar-vfs-info.{c,h}: Add THUNAR_VFS_FILE_FLAGS_EXECUTABLE + to the ThunarVfsFileFlags, which will be set if a ThunarVfsInfo + can be executed, either as regular binary or as .desktop file. + * thunar-vfs/thunar-vfs-mime-application.c, + thunar-vfs/thunar-vfs-sysdep.{c,h}: Move the Exec parsing code from + ThunarVfsMimeApplication to thunar-vfs-sysdep, so it can be used by + other modules as well. + * thunar-vfs/thunar-vfs-info.{c,h}, thunar-vfs/thunar-vfs.symbols: Add + new method thunar_vfs_info_execute(), which is used to execute + files with a list of URIs. These method can handle both regular + executable files as well as .desktop files. + * thunar/thunar-file.{c,h}, thunar/thunar-launcher.c, + thunar/thunar-local-file.c: Add support to execute files that are + marked as executable by the ThunarVfsInfo module. + * thunar-vfs/thunar-vfs-mime-database.c + (thunar_vfs_mime_database_get_info_locked), + (thunar_vfs_mime_database_get_infos_for_info_locked): Be sure to + always unalias MIME-types prior to returning them from the mime + database instance. This way we don't need to care for unaliasing + when determining the MIME-type comment or MIME-type icon. + * thunar-vfs/thunar-vfs-mime-database.{c,h}, + thunar-vfs/thunar-vfs.symbols: Add new method + thunar_vfs_mime_database_get_infos_for_info() to the public API, to + allow other components to access the subclassing information. + * FAQ, Makefile.am: Add initial items for the list of frequently asked + questions. + * TODO: Remove obsolete items. + +2005-08-27 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.{c,h}: Add support to pass hints from the + ThunarVfsInfo to the upper layers. Use these hints to pass icon and + name information from .desktop files. + * thunar-vfs/thunar-vfs.symbols: Add new symbols. + * thunar/thunar-local-file.c: Use the new hints to display appropriate + names and icons for .desktop files. + +2005-08-27 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-trash.c: Use ThunarVfsMonitor instead of + polling the trash files/ directories manually. + +2005-08-27 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-legacy.c: Add support for MIME-type + aliases and parents to the legacy implementation. + * configure.in.in, thunar-vfs/thunar-vfs-mime-database.c: Add support + for determining the MIME type from an extended attribute on SunOS + and Linux. + +2005-08-22 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c: Add drag support for the path entry icon. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add view + selection to the "View" menu. + * thunar/thunar-icon-view.c(thunar_icon_view_button_press_event): Use + gtk_accelerator_get_default_mod_mask() rather than hardcoding + GDK_CONTROL_MASK. + * thunar/thunar-details-view.c(thunar_details_view_button_press_event): + Add support to open the folder menu by right-clicking on an empty + area in the tree view. + * thunar/thunar-details-view.c: Work-around the problem that GtkTreeView + resets the search column whenever the model changes. + * thunar/thunar-standard-view.c(thunar_standard_view_grab_focus): + Properly forward any grab-focus request to the child view. + * thunar/thunar-marshal.list, thunar/Makefile.am, + thunar/thunar-text-renderer.c: Add initial cell editing support to + the text renderer. We'll need a multiline entry widget for the + icon view. + * thunar/thunar-details-view.c, thunar/thunar-icon-view.c, + thunar/thunar-standard-view.c, thunar/thunar-standard-view.h: Add + drag source support to the standard views. + * thunar/thunar-list-model.c: Don't implement GtkTreeDragSource, as + that's handled by ThunarStandardView now. + +2005-08-20 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job.c(thunar_vfs_job_emit): Use G_VA_COPY to + copy variable argument lists in a portable manner. + +2005-08-19 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.{c,h}: Allow derived classes to add + custom actions to the user interface. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-window-ui.xml: Add + support for custom view item actions. + * thunar/Makefile.am, thunar/thunar-icon-view-ui.xml, + thunar/thunar-icon-view.c: Add support to arrange items within the + icon view. + * thunar/thunar-file.h, thunar/thunar-local-file.c: Provide an emblem + for the desktop folder in regular file listings. + * thunar/thunar-icon-view.c(thunar_icon_view_init): Add 3 pixel padding + in vertical direction to the icon cell, to allow better placement + of the emblems. + * thunar/thunar-icon-renderer.c(thunar_icon_renderer_render): Improve + the emblem placement and drawing code to work-around issues with + most icon themes, that don't provide emblems in the appropriate + sizes. + +2005-08-19 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-statusbar.c: Drop the dependency on X11. + * thunar/thunar-desktop-window.c: Include <gdk/gdkx.h> explicitly (since + that's no longer done by libexo -> libxfcegui4). + +2005-08-18 Benedikt Meurer <benny@xfce.org> + + * thunarx/thunarx-gdk-pixbuf-extensions.{c,h}: Add new function + thunarx_gdk_pixbuf_spotlight(), which is used to create a + special icon for the Gtk prelight state. + * thunar/thunar-icon-renderer.{c,h}, thunar/Makefile.am, + thunar/thunar-details-view.c, po/POTFILES.in: Rename + ThunarDetailsViewIconRenderer to ThunarIconRenderer, as + it will also be used by the icon view now. + * thunar/thunar-text-renderer.{c,h}, thunar/Makefile.am, + thunar/thunar-details-view.c, po/POTFILES.in: Rename + ThunarDetailsViewTextRenderer to ThunarTextRenderer, + as it will also be used by the icon view now. + * thunar/thunar-icon-renderer.{c,h}, thunar/thunar-text-renderer.{c,h}: + Add required functionality to use these renderers with the new + ExoIconView. + * thunar/thunar-icon-view.c: Update to use the new ExoIconView class, + with the modified ThunarIconRenderer and ThunarTextRenderer. + * thunar/thunar-launcher.h, thunar/thunar-open-with-action.h: Use + G_GNUC_MALLOC instead of EXO_GNUC_MALLOC. + * thunar/thunar-window.c(thunar_window_init): Use the icon view by + default for testing now. + * configure.in.in: Bump version to 0.1.2. + * thunar/thunar-window.c(thunar_window_action_about): Switch to + GtkAboutDialog. + +2005-08-18 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_files_added): Speed up + inserts if the order of the files match the current sort order, which + is usually the case with sorting by name. + +2005-08-18 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_set_folder): Speed up + the removal of existing rows when changing folders. It's now O(n) + instead of O(n^2). + * thunar/thunar-list-model.c: The memory chunk used for the rows is + now an object attribute, rather than a global variable. + +2005-08-11 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-application.c + (thunar_vfs_mime_application_new_from_desktop_id): Use "Name" instead + of "GenericName" for the application's name, as the "Name" usually + includes the project name in addition to the functional description + of the application, which provides better results than having several + applications named "Text Editor", etc. + * configure.in.in: Prefer Gamin over FAM to avoid the C++ dependency + if possible. Besides that, Gamin offers several other advantages over + FAM, which makes it better suitable to be used in Thunar. + * po/POTFILES.in: Add missing source files here, and remove obsolete + files. + * Thunar.desktop.in, Makefile.am, configure.in.in, po/POTFILES.in: Add + desktop file for Thunar. + +2005-08-10 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-jobs.{c,h}, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs.{c,h}: Merge thunar-vfs-jobs.[ch] into + thunar-vfs.[ch]. + * thunar-vfs/thunar-vfs-mime-database.c, thunar/thunar-local-folder.c, + thunar-vfs/thunar-vfs-monitor.{c,h}, thunar/thunar-local-file.c: + Rename thunar_vfs_monitor_get() to thunar_vfs_monitor_get_default(). + * thunar-vfs/thunar-vfs-mime-database.{c,h}, + thunar-vfs/thunar-vfs-mime.c, thunar-vfs/thunar-vfs-info.c, + thunar/thunar-launcher.c, thunar/thunar-open-with-action.c, + thunar/thunar-trash-folder.c: Rename thunar_vfs_mime_database_get() + to thunar_vfs_mime_database_get_default(). + * thunar-vfs/, thunar/Makefile.am, tests/Makefile.am, configure.in.in: + Turn libthunar-vfs into a shared library, so we can use it in other + applications/plugins as well. + +2005-08-10 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Bump version to 0.1.1. + * thunar-vfs/thunar-vfs-mime-info.h: Add list handling method + thunar_vfs_mime_info_list_free(). + * thunar-vfs/thunar-vfs-mime-info.c(thunar_vfs_mime_info_get_comment): + Automatically generate a comment for 'application/x-extension-<EXT>' + types if no comment is found on the disk. + * thunar-vfs/thunar-vfs-mime-database.c + (thunar_vfs_mime_database_get_info_for_file): Automatically generate + an 'application/x-extension-<EXT>' type on the fly if all other + checks fail and the file name has an extension. + * thunar-vfs/thunar-vfs-mime-cache.c, + thunar-vfs/thunar-vfs-mime-legacy.c, + thunar-vfs/thunar-vfs-mime-database.c, + thunar-vfs/thunar-vfs-mime-provider.{c,h}: Add provider methods to + unalias mime types and to determine the parents of a given mime + type. Use these information to query additional MIME applications. + +2005-08-10 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-database.c + (thunar_vfs_mime_database_get_default_application): Fall back to the + first available application if no explicit default application is + set by the user. + * thunar/thunar-file.{c,h}, thunar/thunar-launcher.c: Rename + thunar_file_list_dup() to thunar_file_list_copy() to get + consistent naming. + * thunar-vfs/thunar-vfs-mime-application.{c,h}: Add support methods + required for hashing. + * thunar-vfs/thunar-vfs-mime-application.{c,h}: Add methods to launch + an application on a given list of URIs on a specific screen. Implement + the Desktop Entry Specification 0.9.4, except for startup notification + support, which will be added soon. + * thunar/thunar-launcher.c, thunar/thunar-open-with-action.c: Allow + users to open files using the newly added ThunarVfsMimeApplication + functionality. + +2005-08-10 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-database.c: According to the specification + the defaults.list may specify more than one desktop-id per MIME type, + where the first available application should be used. + +2005-08-10 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-info.{c,h}: Add support methods required + for hashing. + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs-mime-application.{c,h}, + thunar-vfs/thunar-vfs-mime-database.{c,h}: Add initial MIME + application support to the MIME database. + * thunar/thunar-launcher.{c,h}: Add ThunarLauncher class, which provides + actions to launch files using appropriate MIME applications. The + ThunarLauncher class will also be used by the desktop view. + * thunar/thunar-open-with-action.{c,h}: Add special action class + ThunarOpenWithAction, which provides a GtkAction implementation, that + - when used as menu - displays a submenu with all available MIME + applications for a given file. + * thunar/thunar-window-ui.xml: Add a placeholder to include the launcher + support in the "File" menu on the main menu bar. + * thunar/thunar-standard-view.c, thunar/thunar-standard-view-ui.xml, + thunar/thunar-icon-view.c, thunar/thunar-details-view.c: Add file + launcher support based on the new ThunarLauncher class. + * thunar/thunar-file.{c,h}: Add methods to handle lists of ThunarFile + items easily. + * thunar/thunar-icon-factory.c(thunar_icon_factory_load_icon): Handle + the case of passing a NULL or empty name properly. + +2005-08-07 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, po/ja.po, THANKS: Add initial japanese translations, + thanks to Daichi Kawahata <daichik@users.sourceforge.net>. This + fixes #1004. + +2005-08-06 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-mime-legacy.c: Add support for the various + globs to the legacy mime provider. + * thunar-vfs/thunar-vfs-mime-database.c(thunar_vfs_mime_database_init): + Read atleast 64 bytes from every file to reliably detect text files. + * thunar-vfs/thunar-vfs-mime-database.c: When looking up the MIME info + for a given file, and the magic check doesn't return a match, we'll + return "application/x-executable" for every regular file that is + atleast 1 byte in size and has the executable bit set, as this is + more precise than "application/octet-stream". + +2005-08-06 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Use AC_TRY_LINK() to avoid trouble with funky + systems. + +2005-08-06 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add some autoconf magic to get posix_madvise() + working with glibc. + +2005-08-06 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.{c,h}: Determine the display_name for + each file info. + * thunar-vfs/thunar-vfs-info.c(thunar_vfs_info_new_for_uri): Hand the + display name to thunar_vfs_mime_database_get_info_for_file(), so + we don't need to determine it again. + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_get_display_name): Don't + use g_filename_display_basename(), because it may returned a somehow + translated file name. + * thunar/thunar-local-file.c: Use the display_name supplied with the + ThunarVfsInfo rather than determining it again. + +2005-08-06 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, thunar-vfs/thunar-vfs-mime-database.c: Add support + to query the MIME type stored in the extended attribute + "user.mime_type" as specified in the Shared MIME-info spec. + * docs/design/mime.xmi, docs/design/Makefile.am: Import description for + the ThunarVFS mime module. + * thunar-vfs/thunar-vfs-mime-cache.c(thunar_vfs_mime_cache_lookup_glob): + Use correct offset when iterating over the GlobEntries. + * thunar-vfs/thunar-vfs-mime-cache.c + (thunar_vfs_mime_cache_lookup_literal): Fix the offset returned for + the MIME-type name. + +2005-08-06 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Check for fnmatch.h and sys/mman.h. Add checks for + working mmap and posix_madvise. + * configure.in.in, thunar-vfs/xdgmime/, thunar-vfs/Makefile.am: Drop + the xdgmime library. + * thunar-vfs/thunar-vfs-mime-cache.{c,h}, + thunar-vfs/thunar-vfs-mime-database.{c,h}, + thunar-vfs/thunar-vfs-mime-info.{c,h}, + thunar-vfs/thunar-vfs-mime-legacy.{c,h}, + thunar-vfs/thunar-vfs-mime-provider.{c,h}, + thunar-vfs/thunar-vfs-mime.{c,h}: Import thread-safe replacement for + the xdgmime library. Works only with very recent shared-mime-info + right now. + * thunar-vfs/Makefile.am: Add new files to the build framework. + * thunar-vfs/thunar-vfs-job.c, thunar-vfs/thunar-vfs-mime.c, + thunar-vfs/thunar-vfs.c, thunar-vfs/thunar-vfs.h, thunar/main.c: Add + ability to shutdown the VFS library. + +2005-08-04 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add "r" in front of the revision for the version + string. + * thunar-vfs/thunar-vfs-job.{c,h}, thunar-vfs/thunar-vfs-listdir-job.c, + thunar-vfs/thunar-vfs-mime.{c,h}, thunar-vfs/thunar-vfs-unlink-job.c, + thunar-vfs/thunar-vfs-uri.{c,h}, thunar-vfs/thunar-vfs-transfer-job.c, + thunar/thunar-progress-dialog.c: Use ExoObject as base class for + ThunarVfsJob, ThunarVfsMimeInfo and ThunarVfsUri, which were fun- + damental types previously. ExoObject does exactly what we need + here, without any additional overhead. In particular, the ref- + counting is atomic, even with GLib < 2.7.4. + * configure.in.in: Connect greek translations, previously committed + by Stavros Giannouris <stavrosg2002@freemail.gr>. + * thunar/thunar-file.c: Use exo-noops for the defaults where possible + instead of providing several fallback implementations. + * configure.in.in: Bump version number to 0.1.0. + +2005-08-03 Benedikt Meurer <benny@xfce.org> + + * thunar/main.c(main): Connect the translation domain and setup the + application name. + * thunar/thunar-standard-view.c(thunar_standard_view_init): Setup the + translation domain for the action group. + * thunar/thunar-window.c(thunar_window_init): Setup the translation + domain for the action group. + * po/hu.po, configure.in.in, THANKS: Add hungarian translations, thanks + to Szervác Attila <sas@321.hu>. + +2005-08-03 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-folder.c(thunar_folder_files_removed): Update docu- + mentation. + * thunar/thunar-local-folder.c(thunar_local_folder_file_destroy): In- + voke the "files-removed" signal when a file in this folder is de- + stroyed. + * thunar/thunar-list-model.c: Do not connect the "destroy" signal of + ThunarFile anymore, but instead we rely on the folder to emit + "files-removed" appropriately. + * thunar/thunar-list-model.c(thunar_list_model_class_init): Increase + the number of preallocated rows. + * po/, Makefile.am, configure.in.in: Add i18n support. + +2005-08-03 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view-text-renderer.c: Calculating the approxi- + mate sizes based on the font metrics requires way too much additional + data memory (because Pango loads the whole fontset for this calcu- + lation), so we base our calculation on a sample text instead. + +2005-08-03 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job.c(thunar_vfs_job_emit_valist): Lower the + Job signal priority to increase the responsiveness of the user + interface. + +2005-08-03 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view-text-renderer.{c,h}: Fast text cell + renderer, which provides less accurate cell area size calculation. + * thunar/Makefile.am: Add ThunarDetailsViewTextRenderer to the build + framework. + * thunar/thunar-details-view.c: Use the new text renderer. + +2005-08-02 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-monitor.c: Implement the + thunar_vfs_monitor_feed() method in a reentrant way. + +2005-08-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c: Add sort_by_name() calls missing from the + initial patch. + +2005-08-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-local-file.c(thunar_local_file_monitor): Actually + reload the file info when the VFS monitor notices a change. + * thunar/thunar-list-model.c: Apply Jens Luedickes patch to add + sub-sorting on the filename. + * thunar-vfs/thunar-vfs-monitor.c: Add missing header files. + * configure.in.in: Drop the kevent related checks. + +2005-08-02 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add check for the FAM/Gamin library. + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs-monitor.{c,h}: Redesign + the VFS monitor to use FAM if available. It also provides an interface + to feed the monitor with external events, which will be used by the + VFS jobs, which know for sure that they changed/created/deleted a + file. The interface is not yet implemented. + * thunar/thunar-file.{c,h}: Add a virtual method reload(), which allows + external entities to trigger a reload on a ThunarFile. + * thunar/thunar-local-file.c: Implement the reload() method. + * thunar/thunar-local-file.c, thunar/thunar-local-folder.c: Add support + for the new VFS monitor. + +2005-08-01 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.{c,h}: Add new method + thunar_list_model_get_paths_for_pattern(), which is used to + generate a list of GtkTreePaths for all rows matching a + certain pattern. + * thunar/thunar-details-view.c, thunar/thunar-icon-view.c, + thunar/thunar-standard-view.h: Add virtual methods select_all(), + unselect_all() and select_path(), and implement them in the details + and icon views. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c, + thunar/thunar-window-ui.xml: Add actions "select-all" and + "select-by-pattern" to the "Edit" menu. + * thunar-vfs/thunar-vfs-trash.c: Cosmetic fix. + +2005-07-31 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-local-folder.c: Properly disconnect all signal handlers + prior to releasing the job. + * TODO: Remove completed items. Add note about the copy&paste behaviour + within the same folder. + * thunar-vfs/thunar-vfs-transfer-job.c + (thunar_vfs_transfer_job_insert_base): Fix the check whether source + and target directory are equal. + * thunar-vfs/thunar-vfs-user.c(thunar_vfs_user_local_class_init): Fix + a crash, where the thunar_vfs_local_user_parent_class wasn't initia- + lized properly. + * thunar/thunar-location-buttons.c: Allow users to automatically enter + directories while dragging a text/uri-list over one of the folder + buttons. + +2005-07-31 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-transfer-job.c: Include <time.h> since we + use the time() library call. g_chmod() will be introduced with GLib + 2.8.0, so adjust the check. + +2005-07-31 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-clipboard-manager.c + (thunar_clipboard_manager_contents_received): Properly clear the + CLIPBOARD selection after a paste on "cutted data". Manually trigger + an "owner-changed" after a successfully initiating the paste operation + if either the Xserver or the GTK+ version doesn't support the XFixes + extension. + * thunar-vfs/thunar-vfs-transfer-job.c, configure.in.in: Add work-around + for systems that lack the lchmod() system call. + * thunar/thunar-standard-view.{c,h}: Query all actions from the group + when initializing the view to speed up access later. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c: + Add a "paste-into-folder" action, which is only available from the + context menu. + * autogen.sh, configure.in.in: Adopt the version numbering scheme from + libexo and ditch the date. + +2005-07-31 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-clipboard-manager.{c,h}: Implement paste support based + on the recent API additions to ThunarApplication. + * thunar/thunar-standard-view.c(thunar_standard_view_action_paste): + Implement the paste action based on the new functionality in + ThunarClipboardManager. + +2005-07-31 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-unlink-job.c: Allocate dirent buffer for + the job instead of the stack on every thunar_vfs_unlink_item_collect + call to reduce the stack overhead for the threads. + * thunar-vfs/thunar-vfs-interactive-job.c: Check the cancellation + state prior to invoking the "ask" signal. + * thunar-vfs/thunar-vfs-interactive-job.{c,h}: Reduce the number + of "percent" signal invokations to one per second to reduce the + overall load on the main thread. + * thunar-vfs/thunar-vfs-job.c(thunar_vfs_job_emit_valist): Lower + the priority of inter-thread signals. + * thunar/thunar-progress-dialog.c(thunar_progress_dialog_init): Use + an ellipsizing label for the progress info message to avoid + automatic resizing of the progress dialog. + * thunar/thunar-application.{c,h}: Add "copy" and "move" actions. Drop + "unlink" action, will be replaced with "trash" and "empty-trash-bin" + later. + * thunar-vfs/thunar-vfs-transfer-job.{c,h}: Import the + ThunarVfsTransferJob class, which can only handle 'file:'-URI + transfers right now. + +2005-07-30 Benedikt Meurer <benny@xfce.org> + + * thunarx/thunarx-gtk-extensions.{c,h}, thunarx/Makefile.am: Add a + helper function thunarx_gtk_action_group_set_action_sensitive(), + which is used to easily change the sensitivity of a GtkAction + within a GtkActionGroup. + * thunar/thunar-window.c, thunar/thunar-standard-view.c: Use the newly + added thunarx_gtk_action_group_set_action_sensitive() method. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add new actions + "open-new-window" and "close-all-windows". + * thunar/thunar-application.{c,h}: Add support for progress dialogs + based on the ThunarVfsInteractiveJob. Turn the ThunarApplication + class into a single-instance class. Add support to open new windows + and querying the list of currently open windows. + * thunar/thunar-progress-dialog.{c,h}: GtkWindow already provides the + "icon-name" property (since Gtk 2.6), no need to duplicate that. + * thunar/main.c: Switch to ThunarApplication. + +2005-07-30 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-clipboard-manager.c, thunar/thunar-favourites-view.c, + thunar/thunar-location-buttons.c, thunar/thunar-statusbar.c: Fix + GCC 4.0 cast warnings, thanks to Jeff Franks <jcfranks@tpg.com.au>. + +2005-07-30 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job.c: Emit signals independant of the + cancellation state of the current job. + * thunar-vfs/thunar-vfs-trash.{c,h}: Add a way to query the absolute + path to the .trashinfo file. Support relative paths and not just + filenames for several trash methods. + * thunar-vfs/thunar-vfs-interactive-job.{c,h}: Import the + ThunarVfsInteractiveJob class, which provides the base for all + jobs, that require extended user interaction. + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs-marshal.list: Add + required marshallers, which are not provided by GObject out of + the box. + * thunar-vfs/thunar-vfs-unlink-job.{c,h}: Import ThunarVfsUnlinkJob + class, which is used to unlink a bunch of local or trashed files. + * thunar-vfs/thunar-vfs-jobs.{c,h}: Add public interface to the + various jobs provided by Thunar-VFS. + * thunar-vfs/thunar-vfs.h: Remove the listdir job from the public + interface. Add the jobs and the interactive job headers. + * thunar/thunar-progress-dialog.{c,h}: Add ThunarProgressDialog class, + which provides a dialog, that monitors the progress of an interactive + and supports the required user interaction. + * thunar/Makefile.am, thunar/thunar-local-folder.c: Catch up with + Thunar-VFS changes. + +2005-07-29 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job.{c,h}, thunar-vfs/thunar-vfs-listdir-job.c: + Move "error" signal to the ThunarVfsJob class. Make proper use of the + virtual finalize method. + * thunar/thunar-local-folder.c: Catch up with the ThunarVfsJob + interface changes. + +2005-07-29 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job.{c,h}: Add a parameter spec for + ThunarVfsJob and derived types. Add support methods to handle + GValues easily. + * thunar-vfs/thunar-vfs-listdir-job.{c,h}, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs.h, thunar/thunar-local-folder.c: Rename the + ThunarVfsJobListdir class to ThunarVfsListdirJob. + +2005-07-25 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-sysdep.{c,h}: Add _thunar_vfs_sysdep_readdir() + as a portable, thread-safe readdir replacement. + * thunar-vfs/thunar-vfs-job-listdir.c(thunar_vfs_job_listdir_execute): + Use _thunar_vfs_sysdep_readdir(). + * thunar-vfs/Makefile.am: Add the sysdep component to the build + framework. + +2005-07-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-desktop-view.c, + thunar/thunar-details-view-icon-renderer.c, + thunar/thunar-favourites-model.c, thunar/thunar-file.{c,h}, + thunar/thunar-list-model.c, thunar/thunar-location-buttons.c, + thunar/thunar-path-entry.c, thunar/thunar-properties-dialog.c, + thunar/thunar-statusbar.c, thunar/thunar-window.c: Do not hardcode + the default icon factory in thunar_file_load_icon. Instead the icon + factory is now a parameter to that function, which permits for proper + multi-screen support. + +2005-07-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-factory.c(thunar_icon_factory_load_icon): Handle + the case where no XSETTINGS manager is running on one of the + connected screens. + +2005-07-24 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.c(thunar_file_load_icon): Actually cache the result + of an icon lookup. + * thunarx/, thunarx/Makefile.am, configure.in.in: Add "thunarx" + namespace, which contains extensions to existing frameworks and + various helper functions that don't fit anywhere else. + * thunarx/thunarx-gdk-pixbuf-extensions.{c,h}: Add a method to colorize + a GdkPixbuf to a given GdkColor. + * thunar/main.c, thunar/thunar-desktop-model.{c,h}, thunar/Makefile.am, + thunar/thunar-desktop-window.{c,h}, thunar/thunar-desktop-view.{c,h}: + Add proof-of-concept for the desktop support. + +2005-07-23 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c: Fix incorrect ThunarVfsMimeInfo -> GObject + casts. + +2005-07-22 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add -O0 if debugging is enabled. + * thunar-vfs/thunar-vfs-job.{c,h}, thunar/thunar-local-folder.c, + thunar-vfs/thunar-vfs-job-listdir.{c,h}: Do the ThunarVfsJob + communication based on GSignals to provide more flexibility for + the various upcoming jobs. + +2005-07-22 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-clipboard-manager.c, thunar/thunar-standard-view.c, + thunar/thunar-window.c: Remove duplicate "const"s. + +2005-07-22 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.{c,h}: Use "const" parameters if possible + to give more hints to the compiler. + * thunar-vfs/thunar-vfs-uri.{c,h}: Add thunar_vfs_uri_get_md5sum() + method to calculate the MD5 digest of an URI. + * thunar/thunar-local-file.c: Preallocate 512 instances of the + ThunarLocalFile class to speed up the creation of new objects. + * thunar/thunar-details-view.c(thunar_details_view_init): Do not + allow reordering of treeview columns. + +2005-07-22 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add --disable-debug option, which can be used to + disable all kinds of debugging support, and thereby may speed up + the whole application in certain cases. + * thunar/thunar-statusbar.c: Use the foreground color from the selected + style instead of hard coding black for the animation. + +2005-07-21 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-view.c: Add support for the LINK DnD action. + * thunar/thunar-location-buttons.c(thunar_location_buttons_init): Use + GDK_ACTION_LINK instead of GDK_ACTION_COPY to avoid accident copying + of directories. + * thunar/thunar-statusbar.{c,h}: Implement the ThunarNavigator + interface. + * thunar/thunar-statusbar.{c,h}: Add a "loading" indicator to the + statusbar. Add support to dnd from the shortcut indicator to the + favourites list. + * thunar/thunar-window.c(thunar_window_init): Connect the statusbar as + a navigator. Forward the "loading" property from the view to the + statusbar. + * configure.in.in: Check for additional headers. Add optional + dependency on cairo. + +2005-07-20 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Rename to "thunar" again, as this is now the main + development line. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.{c,h}: + Add context-menu support to the standard view's action framework. + * thunar/thunar-details-view.c: Implement context-menu support for + right-button click and "Menu"/"<Shift>F10" keyboard shortcuts. + +2005-07-18 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-job-listdir.c(thunar_vfs_job_listdir_execute): + Always ignore the "." and ".." entries for directories. + * thunar/thunar-location-bar.{c,h}: Add virtual method accept_focus(), + which tries to transfer keyboard focus to the location bar if it + provides a way for the user to enter the location as text. Else + the method returns FALSE and the window will open a separate dialog. + * thunar/thunar-location-buttons.c, thunar/thunar-location-entry.c: + Implement the accept_focus() method on the ThunarLocationBar + interface appropriately. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Make the + location bar configurable using the action system. + +2005-07-17 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.c: Do not handle the focus-out-event here, + as it's better to handle it in the upper layers. + * thunar/thunar-path-entry.c(thunar_path_entry_set_current_file): Set + the cursor to the end and queue a redraw on the whole widget. + * thunar/thunar-window.c: Include <thunar/thunar-location-entry.h>. + * thunar/thunar-location-entry.{c,h}, thunar/Makefile.am: Add + ThunarLocationEntry, which implements ThunarLocationBar using a + ThunarPathEntry widget. + +2005-07-17 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-path-entry.{c,h}: Add ThunarPathEntry class, which + implements a widget to which the user can enter paths. The auto + completion support is not yet provided. + * thunar/thunar-location-dialog.{c,h}: Add ThunarLocationDialog class, + which provides a "Open Location"-dialog similar to the one found in + GtkFileChooser. + * thunar/Makefile.am: Add new classes to the build framework. + * thunar/thunar-window-ui.xml, thunar/thunar-window.c: Add "Open + Location" action to the window, which will bring up a + ThunarLocationDialog. + +2005-07-17 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Use "thunar-threaded" instead of "Thunar-threaded". + * tests/test-thunar-vfs-volume-bsd.c(main): Get this test working again. + +2005-07-17 Benedikt Meurer <benny@xfce.org> + + * TODO: Add note to based the ThunarVfsJob communication on the GSignal + mechanism. + * configure.in.in: Set tarname to be "Thunar-threaded". + * thunar-vfs/thunar-vfs-info.{c,h}: Let thunar_vfs_info_list_free() + return NULL. + * thunar-vfs/thunar-vfs-job-listdir.c: Invoke the callback every two + seconds, so for large directories, the user does not need to wait for + the whole folder to be loaded. Also sort the item names prior to + loading the infos. + * thunar/thunar-local-folder.c: Support partial loading, as implemented + for ThunarVfsJobListdir. + +2005-07-17 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-sysv.c: Fix compile warning with wrong + parameters to thunar_vfs_volume_manager_sysv_get_volume_by_info(). + This fixes bug #1083. + +2005-07-17 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/xdgmime/: Import the XDG mime implementation with the + patches from libexo. + * thunar-vfs/: The ThunarVfsInfo framework is now thread-safe, using + the ThunarVfsMime framework provided by ThunarVFS. + * thunar/: Turn Thunar into a threaded application. + +2005-07-16 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-folder.{c,h}: Add a "files-removed" signal, which can + be used by ThunarFolder implementation to solve the reload problem, + and probably other problems as well (like asynchronous loading). + * thunar/thunar-local-folder.c(thunar_local_folder_rescan): Use + "files-removed" instead of destroying the no longer present files, + so we don't accidently terminate other stuff here. + * thunar/thunar-list-model.c: Handle the "files-removed" signal of the + ThunarFolder. + +2005-07-15 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c: Unselect all selected items if the + user clicks on an empty area of the treeview and neither Control + nor Shift is active. + * thunar/thunar-properties-dialog.{c,h}: Add the first draft for the + ThunarPropertiesDialog class, which implements a properties dialog for + a single file. + * thunar/Makefile.am: Add ThunarPropertiesDialog to the build framework. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-standard-view.c, + thunar/thunar-window-ui.xml: Add the "properties" action to the + menu structure, which displays a properties dialog for the selected + file. + +2005-07-15 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume.{c,h}: Extend the ThunarVfsVolumeManager + interface to be able to query the ThunarVfsVolume for a given + ThunarVfsInfo. + * thunar-vfs/thunar-vfs-volume-{bsd,sysv}.c: Catch up with the latest + ThunarVfsVolumeManager changes. + * thunar-vfs/thunar-vfs-volume-bsd.c(thunar_vfs_volume_bsd_new): Add + support for SCSI direct access devices. + * thunar/thunar-file.{c,h}: Add thunar_file_get_volume() to be able + to query the ThunarVfsVolume for a given ThunarFile, if possible. + * thunar/thunar-local-file.c: Implement the newly added get_volume() + method based on the ThunarVfsVolumeManager. + * thunar/thunar-list-model.c: Use the new volume related functionality + to display the free space of the currently active directory in the + statusbar. + +2005-07-15 Benedikt Meurer <benny@xfce.org> + + * docs/papers/HackingOnThunar.odt: Improve the "Hacking on Thunar" + guide. + * thunar-vfs/thunar-vfs-volume.{c,h}: Change the icon lookup mechanism + to return an icon name instead of a GtkIconInfo object. Also allow + the ThunarVfsVolume implementation to specify a custom icon by + overriding the lookup_icon_name() method. Add a new method + get_free_space() which can be used to determine the amount of free + space on a given volume. + * thunar-vfs/thunar-vfs-volume-bsd.c: Catch up with the changes to + ThunarVfsVolume. + * thunar/thunar-favourites-model.c: Cache icons for the favourites and + reload them whenever the file/volume changes. Adopt the new icon + lookup mechanism for ThunarVfsVolume. + +2005-07-14 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view.c(thunar_standard_view_init): Add frame + shadow to the standard views. + +2005-07-13 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-clipboard-manager.c: Fake an "owner-changed" event + for the clipboard if either GDK or the Xserver do not support the + XFixes extension. + * thunar/thunar-standard-view.c: Monitor the associated clipboard for + changes. Enable the "paste" action only if the both the current + directory is writable and the clipboard contents are pastable. + +2005-07-13 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-user.c(thunar_vfs_user_manager_init): Use + direct hashing instead of int hashing. + * thunar/thunar-local-file.c(thunar_local_file_get_emblem_names): If + the file cannot be written, return the "noread" emblem as well. + * thunar/thunar-file.{c,h}: Add can_execute(), can_read() and + can_write() methods, and a default implementation, so not every + class derived from ThunarFile needs to implement these methods of + its own. + * thunar/thunar-standard-view.c(thunar_standard_view_selection_changed): + Update the "cut" and "paste" actions depending on whether the + current directory is writable. + +2005-07-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-vfs-uri.c(thunar_vfs_uri_list_to_string): Use GString + to build the URI list string. + * thunar/thunar-vfs-uri.{c,h}: Add a method thunar_vfs_uri_list_copy() + which duplicates a list of ThunarVfsURIs. + * thunar-vfs/thunar-vfs-volume-bsd.c(thunar_vfs_volume_bsd_finalize): + Properly remove the update timer here. + * thunar/thunar-list-model.c(thunar_list_model_remove): Perform the + GtkTreeModel delete operation prior to notifying the "num-files" + property to make sure the selection of the view is updated before + the standard-view requests the statusbar text for the selection. + * TODO: Add another two issues. + * thunar/thunar-clipboard-manager.{c,h}, thunar/Makefile.am: Add the new + ThunarClipboardManager class, which does the interaction with the + clipboard. + * thunar/thunar-standard-view.{c,h}: Implement Copy/Cut operations based + on the newly added ThunarClipboardManager class. + * thunar/thunar-standard-view-ui.xml, thunar/thunar-window-ui.xml: Add + clipboard operations to the "Edit" menu. + +2005-07-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c: Add a readonly property "ui-manager" to the + ThunarWindow and use property binding to sync the UI manager with + the ThunarView. + +2005-07-12 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-standard-view-ui.xml, thunar/thunar-window-ui.xml: + Specify the name in addition to the action. + +2005-07-11 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-navigator.c(thunar_navigator_class_init): Use + EXO_PARAM_READWRITE instead of G_PARAM_READWRITE. + * thunar/thunar-list-model.c: Fix several bugs related to incorrect + signal registration/removal in the hidden files handling. + * thunar/thunar-view.{c,h}: Add a new "ui-manager" property, which is + set by the surrounding window for the view in question. The view in + turn can hook its own actions - and thereby menu and toolbar items - + into the ui manager, using GtkUIManager's merging capabilities. + * thunar/thunar-window.c(thunar_window_init): Tell the main view about + our UI manager. + * thunar/thunar-window-ui.xml, thunar/thunar-standard-view-ui.xml, + thunar/thunar-standard-view.{c,h}, thunar/Makefile.am: Add initial + support for menu merging to the standard view class - and thereby to + the icon and details view. You can now control the "show-hidden" + property of the main view's model from the menu bar. + +2005-07-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.{c,h}: Readd the get_statusbar_text() method. + * thunar/thunar-favourites-view.c(thunar_favourites_view_row_activated): + Make sure the activated row is not the separator row, as calling + thunar_navigator_change_directory() with NULL for the directory + parameter will lead to a crash. + * thunar/thunar-standard-view.{c,h}, thunar/thunar-details-view.{c,h}, + thunar/thunar-icon-view.{c,h}, thunar/Makefile.am: Add a new abstract + base class ThunarStandardView, which is inherited by ThunarIconView + and ThunarDetailsView. ThunarStandardView itself is derived from + GtkScrolledWindow. This change was made to reduce the amount of + duplicated code in ThunarIconView and ThunarDetailsView, and to + workaround the problem that Gtk style properties don't pickup the + custom properties for certain widgets once you have a derived class. + * thunar/thunar-statusbar.{c,h}: Revert to the previous ThunarStatusbar + implementation, which has a single "text" property that is bound to + the "statusbar-text" property of the active view. + * thunar/thunar-view.{c,h}: ThunarView now inherits (in terms of + interface inheritance) from ThunarNavigator, which will allow for + unified handling in ThunarWindow. In addition, the ThunarView now + provides a "loading" and a "statusbar-text" property (both readonly) + to put the view back in control of the loading process. + +2005-07-07 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.c: Be sure to register the type in a + thread-safe manner. + +2005-07-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-model.{c,h}, thunar/thunar-favourites-view.c: + Also provide a GtkWindow instance to the action list generator, so + actions can fire dialogs if necessary. + +2005-07-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-model.{c,h}, thunar/thunar-favourites-view.c: + Add possibility to remove user-defined shortcuts from the list. + +2005-07-03 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-model.c(thunar_favourites_model_get_value): + The ThunarVfsVolume interface does no longer provide the "name" + property. + * thunar-vfs/thunar-vfs-volume-bsd.c: Read the label from the ISO9660 + volume descriptor block whenever a new medium is inserted and use + this label as name. + +2005-07-02 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window-ui.xml, thunar/Makefile.am, + thunar/thunar-window.c: The UI description for the ThunarWindow is + now placed in a separate XML file for easier editing, and compiled + into the binary using the exo-csource utility. + +2005-07-02 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add checks for functions used in the user module. + * thunar-vfs/thunar-vfs-user.{c,h}: Add a user module to the VFS + library, which is extensible and performs some caching to reduce + the overhead caused by the underlying NSS implementation. + * docs/papers/HackingOnThunar.odt: Add comments about the newly added + ThunarVfsUser module. + * thunar-vfs/thunar-vfs-info.h: Add ThunarVfsUserId and ThunarVfsGroupId + typedefs. + * thunar-vfs/thunar-vfs.h, thunar-vfs/Makefile.am: Add the new + ThunarVfsUser module to the build framework. + * thunar/thunar-file.{c,h}, thunar/thunar-local-file.c, + thunar/thunar-trash-file.c: Add two new methods to the ThunarFile + class - get_group() and get_user() - and add an implementation of + these methods to the local and trash backends. + +2005-06-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view-icon-renderer.c + (thunar_details_view_icon_renderer_render): Add support to render + the primary emblem of the given file. + * thunar/thunar-file.{c,h}: Add support to query the list of emblems + for a given ThunarFile. + * thunar/thunar-local-file.c: Implement the ThunarFile emblem support + for symbolic links. + +2005-06-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view-icon-renderer.{c,h}: Add a custom icon + renderer for the details view. + * thunar/thunar-list-model.{c,h}: Allow consumers of this model to + query the file for a given row. + * thunar/Makefile.am: Add the new ThunarDetailsViewIconRenderer class + to the build framework. + * thunar/thunar-details-view.c(thunar_details_view_init): Use the custom + icon renderer instead of the generic pixbuf renderer provided by Gtk+. + +2005-06-29 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-buttons.c: Make this behave like GtkFileChooser + again. + +2005-06-28 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-bsd.c, thunar-vfs/thunar-vfs-volume.c: + Remove the GObject properties from the ThunarVfsVolume interface. + +2005-06-26 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-info.{c,h}: Do not automatically determine the + link target for ThunarVfsInfo objects. Instead, we'll add a method + to ThunarVfsInfo later, so modules can do this on-demand. This speeds + up loading directories with lots of symlinks within. + * TODO: Remove the ThunarVfsInfo symlink item. + +2005-06-26 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.{c,h}: Don't use a GObject for the + ThunarVfsURI class. GObject is really overhead here, as we don't need + anything of whats provided by GObject. + * TODO: Add note about missing GValue handling for ThunarVfsURI. + * TODO: Add note to fix ThunarVfsInfo to not implicitly query the + link target. + * thunar-vfs/*.[ch], thunar/*.[ch]: Use thunar_vfs_uri_unref() and + thunar_vfs_uri_ref() instead of g_object_unref() and g_object_ref(), + as ThunarVfsURI is no longer a GObject derived type. + * thunar/thunar-window.c: Make loading new directories look and feel + "smoother". Still not perfect. + +2005-06-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-local-file.c: Use a static variable for the VFS monitor + instead of a class variable, that never gets freed with static types. + * thunar/thunar-favourites-model.c: Watch the files in the favourites + list for changes, so that folders that no longer exists are + automatically removed from the list. + +2005-06-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-navigator.c(thunar_navigator_get_type): Do not require + derived classes to inherit GtkWidget. This enables us to let arbitrary + classes implement the ThunarNavigator interface and therefore reduce + the amount of hardcoded knowledge in ThunarWindow. + * thunar/thunar-side-pane.c(thunar_side_pane_get_type): Require derived + classes to inhert GtkWidget. + +2005-06-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c(thunar_details_view_init): Use a + GtkCellRendererText instead of an ExoCellRendererEllipsizedText + for the name column. + * thunar/thunar-details-view.c, thunar/thunar-icon-view.c: Set proper + ATK name and descriptions here. + +2005-06-25 Benedikt Meurer <benny@xfce.org> + + * thunar/main.c(main): Disable thread support for now, as it's not used + and just slows down stuff. + * thunar/thunar-file.{c,h}, thunar/thunar-local-file.{c,h}, + thunar/thunar-local-folder.c, thunar/thunar-trash-file.c: Watch local + directories and trashed files for changes. + +2005-06-25 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-location-buttons.c + (thunar_location_buttons_set_current_directory): Don't display the + real root node - the 'computer:'-node - if a sub-node is active. So + currently we have four distinctive possible roots for the location + buttons bar, which are the home directory of the user, the file system + root node ('file:/'), the trash root ('trash:') and the real computer + root node ('computer:'), which are checked in the given order. + * thunar/thunar-list-model.c(thunar_list_model_get_value): Use slightly + larger icons for the details view. + * thunar/thunar-window.c: Add preliminary menu support with 'Close' + and 'Go up'. + +2005-06-24 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.{c,h}: Add support for the 'computer://' + URI. + * thunar/thunar-trash-folder.c, thunar/thunar-local-folder.c, + thunar/thunar-folder.c: Drop the GObject properties, as they are + mostly useless here. + * thunar/main.c(main): Use thunar_vfs_uri_new() for the optional + command line parameter to be able to open arbitrary URIs from the + command line. + * thunar/Makefile.am: Add new class ThunarComputerFolder to the build + framework. + * thunar/thunar-computer-folder.{c,h}: Add ThunarComputerFolder class, + which implements the 'computer:' URI. This vfolder is the root of all + other root folders, currently 'file:/' and 'trash:'. + * thunar/thunar-file.{c,h}, thunar/thunar-folder.c, + thunar/thunar-list-model.c, thunar/thunar-local-file.c, + thunar/thunar-local-folder.c, thunar/thunar-statusbar.c, + thunar/thunar-trash-file.c, thunar/thunar-trash-folder.c: Add support + for the 'computer:' vfolder as overall root node. Rearrange the + get_size() method to be able to support objects for which no size + is known, currently vfolders and directories in general. The virtual + get_mime_info() method now automatically takes a reference on the + returned object for the caller. + +2005-06-24 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add check for localtime_r. + * thunar/thunar-file.{c,h}: Add support to query accessed, changed and + modified dates of ThunarFiles. + * thunar/thunar-local-file.c, thunar/thunar-trash-file.c: Implement + the virtual get_date() method. + * thunar/thunar-list-model.{c,h}: Add new columns accessed date, + modified date and mime type. Fix the sorting for the mime comment + column. + * thunar/thunar-details-view.c: Display type and date modified columns + as well. + +2005-06-23 Benedikt Meurer <benny@xfce.org> + + * docs/papers/HackingOnThunar.odt, docs/papers/Makefile.am, + configure.in.in, docs/Makefile.am: Add initial draft of the "Hacking + on Thunar" paper. + +2005-06-22 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-local-file.c, thunar/thunar-local-folder.c: If for + some reason the constructor fails, we need to make sure to handle + the floating reference correctly, therefore we call gtk_object_sink() + instead of g_object_unref() in this case now. + +2005-06-22 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-file.c, thunar/thunar-local-folder.c: Add an assertion + to verify that an object has a floating reference before we call + gtk_object_sink() on it. + +2005-06-22 Benedikt Meurer <benny@xfce.org> + + * TODO: Addd new TODO items and remove solved issues. + * thunar/Makefile.am: Add new class ThunarTrashFile to the build + framework. + * thunar-vfs/thunar-vfs-monitor.c(thunar_vfs_monitor_add_info): Do not + use kevent for symlinks, it's way easier to watch them using regular + polling. This shouldn't be a problem anyways, as watching symlinks + is not a common case. + * thunar-vfs/thunar-vfs-trash.{c,h}: Add functionality to handle trash: + URIs and determine the real path for a file in a particular trash + can. + * thunar-vfs/thunar-vfs-trash.c(thunar_vfs_trash_manager_get_trashes): + Fix a typo where the order of arguments to the g_list_prepend() + function was wrong. + * thunar/thunar-trash-file.{c,h}: Add a ThunarTrashFile class, which + represents a trashed file. + * thunar/thunar-trash-folder.c: Add support for listing the contents + of the various trash cans, and also provide a simple proxy mechanism, + that automatically forwards the constructor invokation to the + ThunarTrashFile class if required. The trash can handling must be + improved, see bug #1027. + +2005-06-21 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-window.c(thunar_window_set_current_directory): Use + thunar_file_open_as_folder() to open new folders. + * thunar/thunar-folder.{c,h}: ThunarFolder is now an interface, which + can be implemented in different ways. + * thunar/thunar-local-folder.{c,h}: The previous ThunarFolder is now + named ThunarLocalFolder. + * thunar/thunar-file.{c,h}: Add thunar_file_open_as_folder() virtual + method, which allows the ThunarFile implementation to choose an + appropriate ThunarFolder implementation and thereby removes the + need for the surrounding modules to "guess" the correct ThunarFolder. + * thunar/thunar-local-file.c: Implement the open_as_folder() method + for local files by simply instantiating a ThunarLocalFolder on the + file in question. + * thunar/thunar-trash-folder.{c,h}: The ThunarTrashFile class is now + named ThunarTrashFolder as it really represents the trash toplevel + folder. It also implements the ThunarFolder interface now. The real + folder implementation is missing currently. + * thunar/Makefile.am: Sync the build framework with the changes + described above. + +2005-06-20 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-monitor.c(thunar_vfs_monitor_event): Remove + unused variables. + * thunar/thunar-folder.c: Apply the same optimization concerning signal + id lookups and closure generations as done with ThunarListModel + earlier. + * thunar/thunar-folder.c: Actually react to events on the corresponding + file. We still need a mode in which we'll handle errors in async + folder reloads. + * thunar/thunar-local-file.c: Drop the cached MIME type whenever the + file changes. The MIME type will be recalculated on demand when + needed. + * thunar/thunar-icon-factory.c: Instead of binding to the icon theme + instance's "changed" signal and risking that somebody else already + registered a handler earlier, we use a signal emission hook now, which + is garantied to be fired before any of the signal handlers are + invoked. See the code for details and additional comments. + +2005-06-20 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-local-file.h: Add missing THUNAR_LOCAL_FILE_GET_CLASS(). + * configure.in.in: Add checks for kqueue() and required headers. + * thunar-vfs/thunar-vfs-info.{c,h}: thunar_vfs_info_update() is now + part of the public API as it's used by monitor and will be used + by the ThunarLocalFile implementation later as well. + * thunar-vfs/thunar-vfs-monitor.{c,h}: Add implementation for most + of the ThunarVfsMonitor. The current implementation uses kqueue() + if available with a fallback to regular polling. + +2005-06-20 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c: Instead of resolving the ids for the + "destroy" and "changed" signals on ThunarFile everytime we need to + register it, we query the signal id in the constructor and remember + it. In addition, instead of creating a closure for every signal + registration on a ThunarFile, we create a closure for "changed" and + a closure for "destroy" in the constructor and reuse that closure + everytime we need to register a signal handler. + * thunar/thunar-list-model.c: Watch hidden files for "destroy" condition + as well. + * thunar/thunar-trash-file.c: Emit the "changed" signal whenever the + "empty" property on the trash manager changes. + * thunar/thunar-file.{c,h}: Add a method thunar_file_changed(), which + is used by derived classes to emit the "changed" signal on a given + ThunarFile. + +2005-06-19 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-trash.{c,h}: Import first implementation of a + trash manager into thunar-vfs. Does currently only support the "home + trash", but will be extended to use the volume manager in order to + support foreign trashes as well. + * thunar-vfs/Makefile.am: Add the trash manager to the build framework. + * thunar-vfs/thunar-vfs.h: Include the trash manager header. + * thunar/thunar-trash-file.c: Make use of the experimental trash + manager to display the proper icon depending on whether the trash + is full or empty. + +2005-06-19 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-statusbar.c, thunar/thunar-list-model.c, + thunar/thunar-favourites-model.c: Fix bug, where Thunar crashed when + NULL was returned for a mime info. + * thunar/thunar-file.{c,h}: Turn this into an abstract base class, which + can be implemented in different ways. + * thunar/thunar-local-file.{c,h}: Implementation of the abstract + ThunarFile class for local files handled by the 'file:///' URI + scheme. + * thunar/thunar-trash-file.{c,h}: Implementation of the abstract + ThunarFile class for trashed files handled by the 'trash:///' URI + scheme and the trash can itself. This is currently only a boilerplate + and waiting for the trash backend to show up. + * thunar/Makefile.am: Add new classes to the build framework. + +2005-06-17 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-details-view.c(thunar_details_view_init): Use the + ellipsizing text renderer for the name column and get the sizing + correct. + +2005-06-17 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-view.{c,h}: Further improve the interface to ease the + implementation and reduce the amount of duplicated code in the view + implementations. + * thunar/thunar-details-view.{c,h}: Add a first implementation for a + details view. + * thunar/thunar-icon-view.c: Catch up with the changes to ThunarView. + * thunar/thunar-window.c: Test the new ThunarDetailsView. + * thunar/Makefile.am: Add ThunarDetailsView class to the build + framework. + +2005-06-17 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-view.{c,h}: Adjust the interface for views to be more + like the FilerView interface, which makes things slightly easier and + adds more flexibility for the statusbar. Also the "list-model" + property is now named "model", which is the easiest way for both + ExoIconView and GtkTreeView, and it's safe to name it that way, as + the ThunarView interface is the only way to change models anyways. + * thunar/thunar-list-model.{c,h}: Drop the statusbar text generator. + It's now handled completely within the ThunarStatusbar class, which + provides more flexibility. + * thunar/thunar-statusbar.{c,h}: Each statusbar instance is now + associated with a ThunarView instance and automatically updates the + status text according to the view. + * thunar/thunar-icon-view.c: Implement modified ThunarView interface, + which makes things very easy here for now. + * thunar/thunar-window.c: Catch up with the changes to the other + classes. + +2005-06-15 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-icon-factory.c: Implement the recently used list using + a circular buffer. This saves us from having to memmove() the list + content on every icon lookup. + * thunar/thunar-window.c(thunar_window_set_current_directory): Use + a simple optimization when loading new folders into a view. See the + code comments for details about the trick. + +2005-06-14 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Depend on GLib 2.6 for now. + +2005-06-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-volume-sysv.{c,h}: Add no-op implementation + to make it possible to compile Thunar on non-BSD systems again. + * configure.in.in, thunar-vfs/Makefile.am, + thunar-vfs/thunar-vfs-volume.c, thunar-vfs/thunar-vfs-volume-bsd.c: + Add a rather hacky way to support different system flavours based + on AC_CONFIG_LINKS(). Needs to be replaced by a real solution at + some time. + * TODO: Add note about the wacky AC_CONFIG_LINKS() hacks mentioned + above. + +2005-06-14 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_new_for_path): Add some + code to automatically remove trailing slashes from path names, which + would otherwise confuse the whole file manager. + * thunar/thunar-fallback-icon.{h,png}, thunar/Makefile.am: The fallback + icon is now stored in a C file and automatically generated at compile + time if maintainer mode is enabled, while dist tarballs will ship the + generated C file. + * thunar/thunar-icon-factory.{c,h}: Add new class ThunarIconFactory, + which provides caching of themed icons. The basic concept is based + on the NautilusIconFactory class, but the implementation is simpler + and faster than the implementation found in Nautilus. + * thunar/thunar-file.c: Use the new ThunarIconFactory class and the + new exo_mime_info_lookup_icon_name() method to lookup and cache icons + for files. This speeds up folder loading quite a lot. + * docs/design/overview.xmi: Add ThunarIconFactory diagram. + +2005-06-13 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Add header checks required for the BSD volume + manager implementation. + * thunar/thunar-window.c: Display the current folder's special name. + * thunar/thunar-file.{c,h}: Add property "special-name", which contains + the special name of a given file if any, else it contains the same + value as the "display-name" property. + * thunar/thunar-location-buttons.c: Use the home directory as root. + Don't display a label for the 'Filesystem' node, similar to how it + is done with GtkFileChooser. + * thunar-vfs/thunar-vfs-volume.{c,h}, + thunar-vfs/thunar-vfs-volume-bsd.c: Try more advanced features, like + detecting whether a medium is present for a given volume. This is + currently just testing, based on what is provided by the BSD + interface. The final design may look different, maybe even a + D-BUS based thunar-volume-manager service, which can be run with + special permissions in order to be able to query device stats and + mount volumes. + * thunar/thunar-favourites-model.c: Use the new features provided by + the volume manager to dynamically display volumes when a medium is + inserted. + +2005-06-12 Benedikt Meurer <benny@xfce.org> + + * docs/design/overview.xmi: Refined the basic ideas for the volume + manager, which will provide core functionality required by the + trash system. The ThunarVfsVolume and ThunarVfsVolumeManager concepts + are interfaces now, which will be implemented by the backend (usually + one backend per operating system family). + * tests/data/test-thunar-vfs-volume-bsd.fstab, tests/data/Makefile.am, + tests/test-thunar-vfs-volume-bsd.c, tests/Makefile.am: Add test case + for the BSD specific implementation of the ThunarVfsVolumeManager + module. + * tests/test-thunar-vfs-uri.c: Fix copyright and includes. + * TODO: Add item about possible improvements of the BSD specific + volume manager implementation. + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs.h, configure.in.in: Add + new classes and interfaces to the build framework. + * thunar-vfs/thunar-vfs-volume.{c,h}: Import the basic interfaces to + the volume manager module, with a minimum set of methods and signals, + which will be extended later. + * thunar-vfs/thunar-vfs-volume-bsd.{c,h}: Add first try of an + implementation of the the volume manager interfaces for BSD systems. + +2005-06-11 Benedikt Meurer <benny@xfce.org> + + * docs/design/overview.xmi: Extend the ThunarVfsURI functionality. + * thunar-vfs/thunar-vfs-uri.{c,h}: Add host handling to ThunarVfsURI. + Add support for different URI schemes, currently 'file://' and + 'trash://'. + * thunar/thunar-favourites-model.c, thunar/thunar-favourites-view.c, + thunar/thunar-location-buttons.c: Sync with the little API change + to ThunarVfsURI. + * tests/Makefile.am: Delete core files on `make clean'. + * tests/test-thunar-vfs-uri.c(main): Add test cases for the trash: + scheme. + +2005-06-11 Benedikt Meurer <benny@xfce.org> + + * configure.in.in, Makefile.am, tests/: Import first test program for + ThunarVfsURI validation. + +2005-06-11 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.{c,h}: Add functions to ease the handling + of URI lists, specifically to automatically parse and generate + string representations of URI lists that conform to the + text/uri-list mime type. + * thunar/thunar-location-buttons.c + (thunar_location_buttons_drag_data_get): Use new ThunarVfsURI list + handling functions instead. + * thunar/thunar-favourites-model.c + (thunar_favourites_model_file_destroy): Handle the case where a + directory referenced by a favourite disappears from the backend media. + * thunar/thunar-favourites-model.c + (thunar_favourites_model_file_changed): Remove a given favourite if + the system notices that the favourite's file no longer refers to a + directory. + * thunar/thunar-favourites-model.c(thunar_favourites_model_init): Do + not re-add favourites initially, that do not refer to a directory. + * thunar/thunar-favourites-model.{c,h}: Add a new method + thunar_favourites_model_add(), which is used by the + ThunarFavouritesView to add new favourites to the list and + automatically sync the changes with the Gtk+ bookmarks list. + * thunar/thunar-favourites-view.c: Handle "text/uri-list" drops, + adding new favourites as appropriate. Add note, that the initial + idea is based on the GtkFileChooser written by Red Hat for Gtk+. + * TODO: Remove the 'text/uri-list'-handling for ThunarFavouritesView. + Add item concerning the Trash in the favourites list. + +2005-06-10 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-model.{c,h}, + thunar/thunar-favourites-view.c: Add initial drag&drop-support for + the favourites view. This is currently limited to rearranging + favourites in the list. Support for adding new favourites by + dropping text/uri-list's will be added soon. Also, the + ThunarFavouritesModel also saves changes made by the user back to + the .gtk-bookmarks file now. + * TODO: Add note about missing text/uri-list support in + ThunarFavouritesView, and missing .gtk-bookmarks monitor support. + +2005-06-08 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-model.c: Use a signed gint for the number + of favourites to be compatible with the Gtk+ API. + +2005-06-08 Benedikt Meurer <benny@xfce.org> + + * autogen.sh: Better determine the file dynamically, which is used to + query the sandbox revision. + +2005-06-08 Benedikt Meurer <benny@xfce.org> + + * autogen.sh, configure.in.in: Add build number to the version during + development. + +2005-06-08 Benedikt Meurer <benny@xfce.org> + + * docs/design/overview.xmi: All navigational UI elements in a + ThunarWindow now implement the ThunarNavigator interface, which + defines the "current-directory" property and the "change-directory" + signal. See the ThunarNavigator gtk-docs for details about the + behaviour. + * thunar/thunar-navigator.{h,c}: Provide source code for the current + ThunarNavigator interface. + * thunar/thunar-side-pane.{h,c}, thunar/thunar-favourites-pane.c: + Changed to use ThunarNavigator instead. ThunarSidePane is currently + an empty interface. + * thunar-vfs/thunar-vfs-uri.{h,c}: Add a thunar_vfs_uri_to_string() + method, which transform a ThunarVfsURI into a file:// uri. + * thunar/thunar-location-bar.{h,c}: Provide source code for the + ThunarLocationBar interface, which extends the ThunarNavigator + interface. The ThunarLocationBar interface does not add anything new + currently, but that will change in future revisions. + * thunar/thunar-location-buttons.{c,h}: Add location path buttons + implementation of the ThunarLocationBar interface. The layouting + code was mostly copied from gtkpathbar.c, which was initially + written by Jonathan Blandford. The implementation is not complete + yet, and the layouting code is still very buggy. + * TODO: Add a bunch of TODO items for Thunar 1.0. + +2005-06-07 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-list-model.c(thunar_list_model_set_folder): Fix a bug + where the signals for the ThunarFolder weren't connected if the + folder contained no files initially. + * thunar/thunar-side-pane.c(thunar_side_pane_class_init): Fix typo in + the documentation. + * thunar/thunar-file.{c,h}: Add new method thunar_file_get_parent() to + figure out the parent directory for a given ThunarFile. + +2005-06-06 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_finalize): Use the + parent_class variable set by G_DEFINE_TYPE instead of dynamically + querying the parent class on-demand. + * thunar/thunar-application.c, thunar/thunar-desktop-view.c, + thunar/thunar-favourites-model.c, thunar/thunar-favourites-pane.c, + thunar/thunar-favourites-view.c, thunar/thunar-file.c, + thunar/thunar-folder.c, thunar/thunar-icon-view.c, + thunar/thunar-preferences.c, thunar/thunar-statusbar.c, + thunar/thunar-window.c: G_DEFINE_TYPE and G_DEFINE_TYPE_WITH_CODE + already generate a parent_class variable, so we don't need to do + that manually as well. It looks like this was added with GLib 2.4.x + and I somehow missed that change. Thanks to Jeff Franks for pointing + this out. + +2005-06-05 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.c: Fix a bug in the thunar_vfs_uri_parent() + and thunar_vfs_uri_relative() methods, where the name attribute of + the newly created objects wasn't initialized properly. + * thunar-vfs/thunar-vfs-uri.c(thunar_vfs_uri_equal): Instead of always + comparing the full path of both URIs, a simple optimization was + introduced, which checks the basenames first, if they are equal, + it'll check whether the dirnames have the same length, and as the + last fallback, it'll compare the dirnames char by char. This way we + can optimize the common case - with GHashTable - that two URIs + differ. + +2005-06-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-model.{c,h}: Add new method + thunar_favourites_model_file_for_iter() to be able to easily + determine the ThunarFile for a given favourite. + * thunar/thunar-file.c(thunar_file_class_init): Fix a type in the + "changed" signal definition. + * thunar/thunar-file.c(thunar_file_finalize): Fix a bug where the + ThunarVfsURI was freed first, and then an attempt was made to remove + the ThunarFile from the file_cache using the previously freed + ThunarVfsURI as key. + * thunar/thunar-view.{c,h}: Add the "change-directory" signal, which + is emitted by ThunarIconView and ThunarListView whenever the user + double clicks a folder (or otherwise requests a directory change + from within the view). + * thunar/thunar-list-model.{c,h}: Add a thunar_list_model_new() + default constructor, which does not take a ThunarFolder instance. + * thunar/thunar-icon-view.c: Implement the "change-directory" signal + in ThunarView. + * thunar/thunar-favourites-view.c, thunar/thunar-favourites-pane.c: + Double-clicking a favourite now opens the associated directory (using + the "current-directory" property, which is linked to the + "current-directory" property of ThunarWindow). + * thunar/thunar-window.{c,h}: Add a "current-directory" property, + which describes the directory currently displayed in this window. + Remove the thunar_window_new_with_folder() constructor and replace + it by a default constructor. Automatically synchronize the current + directory with both the view and the side pane. + * thunar/main.c(main): ThunarWindow now uses ThunarFile to refer to + the active directory and so we do here as well. + +2005-06-05 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Bumped version to 0.0.2. + * docs/design/overview.xmi: Fix some issues, see the code changes + below. + * thunar-vfs/Makefile.am: Don't install the thunar-vfs library for + now. Makes debugging easier. + * thunar/Makefile.am: Add new classes to the build framework. + * thunar/thunar-view.{c,h}: Implement first draft for the ThunarView + interface, which is to beimplemented by all views. + * thunar/thunar-icon-view.{c,h}: Implement first draft for the + ThunarIconView class, which implements the ThunarView interface to + provide an icon view of the current folder. + * thunar/thunar-statusbar.{c,h}: Add basic implementation of the + ThunarStatusbar class. In order to avoid an association between the + ThunarView or ThunarListModel classes and the ThunarStatusbar and in + order to provide more flexibility about what is to be displayed in + the statusbar, we use a write-only property "text" for the + ThunarStatusbar, which can be connected to another string property + using the ExoBindings module. + * thunar/thunar-list-model.{c,h}: The number of rows should be a gint + rather than a guint, as that's what GtkTreeModel uses. Add a new + method thunar_list_model_get_statusbar_text(), that will be used by + both ThunarIconView and ThunarListView to determine the proper + statusbar text that should be displayed for a given selection. Add a + new column THUNAR_LIST_MODEL_COLUMN_TYPE, which provides a string + representation of the MIME-Type (using the comment set for the + MIME-Type). The sort function is not yet implemented tho. + +2005-06-05 Benedikt Meurer <benny@xfce.org> + + * thunar/thunar-favourites-model.c(thunar_favourites_model_get_value): + The display_name's of ThunarFile's can be considered static (as the + name cannot change during the ThunarFile's life-time), so we don't + need to take a copy here. + * thunar/thunar-list-model.c(thunar_list_model_get_value): Same here, + the ThunarFile's display_name is static. + * thunar/thunar-file.c: Add the simple caching on the ThunarFile + level. If a ThunarFile for the same ThunarVfsURI is requested + multiple times, the same ThunarFile instance will be used, instead + of allocating a new one. Future versions will extend this scheme + using a smarter caching mechanism. + * thunar/thunar-side-pane.{c,h}: Add implementation for the + ThunarSidePane interface, which is to be implemented by all widgets + that can be placed on the right side. The interface currently + includes only the "current-directory" property, which is the most + important communication mechanism. We'll need some way to pass in + other per-window settings here (e.g. "show-hidden" and such). + Hopefully somebody will pick up the preferences task soon. + * thunar/thunar-favourites-model.{c,h}, + thunar/thunar-favourites-view.{c,h}, + thunar/thunar-favourites-pane.{c,h}: More work on the + ThunarFavourites module. The ThunarFavouritesPane class implements + the ThunarSidePane interface and acts as a bridge to the underlying + ThunarFavouritesView. + * thunar/thunar-window.c: Test the new ThunarFavouritesPane class. + * thunar/Makefile.am: Add the new classes to the build framework. + +2005-06-05 Benedikt Meurer <benny@xfce.org> + + * thunar-vfs/thunar-vfs-uri.{c,h}: Add thunar_vfs_uri_new() + constructor, that creates a new ThunarVfsURI object from a resource + identifier string. + * thunar-vfs/thunar-vfs-uri.{c,h}: Add thunar_vfs_uri_is_home(), which + determines whether a given ThunarVfsURI referes to the home + directory of the current user. + * thunar/thunar-file.c(thunar_file_load_icon): Pay attention to + special icons for the home folder and the file system root. + * thunar/thunar-favourites-model.{c,h}, + thunar/thunar-favourites-view.{c,h}: Add experimental + ThunarFavouritesModel and ThunarFavouritesView classes, that will be + used in the implementation of the ThunarFavouritesPane class. Other + than with the mockups, I've skipped the 'Desktop' favourite for now, + as it does not make much sense. The usablity team should evaluate + this at some time. + * thunar/thunar-window.c: Add ThunarFavouritesView on the left side + for testing. + * thunar/Makefile.am: Add ThunarFavouritesModel and + ThunarFavouritesView to the build system. + +2005-06-04 Benedikt Meurer <benny@xfce.org> + + * configure.in.in: Fix copyright texts. + * docs/design/overview.xmi: Add is_local() and is_root() for + ThunarVfsURI, which were missing. + * thunar-vfs/thunar-vfs-uri.{c,h}: Implemented the missing + thunar_vfs_uri_is_root() and thunar_vfs_uri_parent() methods. + +2005-06-04 Benedikt Meurer <benny@xfce.org> + + * COPYING.LIB: Add license text for the thunar-vfs library (which is + licensed under the LGPL). + * HACKING: Add information for people that plan to hack on Thunar. + * AUTHORS: Add Jeff Franks. + * THANKS: Import the THANKS template. + * README: Add some basic information about Thunar. Needs more details. + * docs/design/overview.xmi: Import the current overview diagram for + Thunar. + * Makefile.am, configure.in.in, docs/Makefile.am, + docs/design/Makefile.am: Include the docs/ tree with the build + framework. + * configure.in.in, thunar/Makefile.am, thunar-vfs/Makefile.am: Link + against GThread (not yet required from what is coded so far). + * configure.in.in: Check for several required header files. + * thunar-vfs/Makefile.am, thunar-vfs/thunar-vfs-info.{c,h}, + thunar-vfs/thunar-vfs-monitor.{c,h}, + thunar-vfs/thunar-vfs-uri.{c,h}, thunar-vfs/thunar-vfs-util.{c,h}, + thunar-vfs/thunar-vfs.h: Add some experimental source code to + implement parts of the VFS module. + * thunar/fallback-icon.h, thunar/fallback-icon.png: Import the + fallback icon. + * thunar/thunar-application.{c,h}: Import Jeff's ThunarApplication + boilerplate (adjusting style as required). + * thunar/thunar-desktop-view.{c,h}: Boilerplate for the + ThunarDesktopView class with the very basic requirements. + * thunar/thunar-file.{c,h}, thunar/thunar-folder.{c,h}: Experimental + implementation of ThunarFile and ThunarFolder based on the + experimental source for the VFS module. + * thunar/thunar-list-model.{c,h}: Sample implementation of the + ThunarListModel class, based on an earlier implementation found in + Filer. + * thunar/thunar-preferences.{c,h}: Template for the ThunarPreferences + class. + * thunar/thunar-window.{c,h}: Quick-and-dirty ThunarWindow + implementation to be able to roughly test the ThunarListModel class. + * thunar/main.c: Add code to start a single ThunarWindow. + * autogen.sh: Copyright fixes. Substitute date to make it easier to + identify snapshots during the early development stages. + +2005-05-30 Benedikt Meurer <benny@xfce.org> + + * Initial import. + +# vi:set ts=8 sw=8 noet ai nocindent: diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 2550dab75..000000000 --- a/INSTALL +++ /dev/null @@ -1,302 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006, 2007, 2008, 2009 Free Software Foundation, Inc. - - This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -Basic Installation -================== - - Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - - 6. Often, you can also type `make uninstall' to remove the installed - files again. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. Run `./configure --help' -for details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - - On MacOS X 10.5 and later systems, you can create libraries and -executables that work on multiple system types--known as "fat" or -"universal" binaries--by specifying multiple `-arch' options to the -compiler but only a single `-arch' option to the preprocessor. Like -this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you -may have to build one architecture at a time and combine the results -using the `lipo' tool if you have problems. - -Installation Names -================== - - By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Particular systems -================== - - On HP-UX, the default C compiler is not ANSI C compatible. If GNU -CC is not installed, it is recommended to use the following options in -order to use an ANSI C compiler: - - ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" - -and if that doesn't work, install pre-built binaries of GCC for HP-UX. - - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot -parse its `<wchar.h>' header file. The option `-nodtk' can be used as -a workaround. If GNU CC is not installed, it is therefore recommended -to try - - ./configure CC="cc" - -and if that doesn't work, try - - ./configure CC="cc -nodtk" - - On Solaris, don't put `/usr/ucb' early in your `PATH'. This -directory contains several dysfunctional programs; working variants of -these programs are available in `/usr/bin'. So, if you need `/usr/ucb' -in your `PATH', put it _after_ `/usr/bin'. - - On Haiku, software installed for all users goes in `/boot/common', -not `/usr/local'. It is recommended to use the following options: - - ./configure --prefix=/boot/common - -Specifying the System Type -========================== - - There may be some features `configure' cannot figure out -automatically, but needs to determine by the type of machine the package -will run on. Usually, assuming the package is built to be run on the -_same_ architectures, `configure' can figure that out, but if it prints -a message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS - KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - - Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - - `configure' recognizes the following options to control how it -operates. - -`--help' -`-h' - Print a summary of all of the options to `configure', and exit. - -`--help=short' -`--help=recursive' - Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--prefix=DIR' - Use DIR as the installation prefix. *Note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. - -`--no-create' -`-n' - Run the configure checks, but stop before creating any output - files. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/Makefile.am b/Makefile.am index 0b9ebe327..433a174a8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,9 +7,7 @@ SUBDIRS = \ po-doc \ tdb \ thunarx \ - thunar-vfs \ thunar \ - tests \ docs \ examples \ plugins diff --git a/README b/README index fd0b1cb81..75def7552 100644 --- a/README +++ b/README @@ -4,6 +4,11 @@ What is it? Thunar is a modern file manager for the Unix/Linux desktop, aiming to be easy-to-use and fast. +THIS BRANCH (migration-to-gio) IS CONSIDERED HIGHLY EXPERIMENTAL! It is +used for the migration from ThunarVFS to GIO as part of a student thesis: + + http://lunar-linux.org/~jannis/migrating-thunar-to-gio/ + Required packages ================= diff --git a/acinclude.m4 b/acinclude.m4 index 19366d943..caa0a415c 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -112,159 +112,3 @@ if test x"$ac_bm_thunar_plugin_wallpaper" = x"yes"; then fi fi ]) - - -dnl # BM_THUNAR_VFS_MONITOR_IMPL() -dnl # -dnl # Determine the file system monitoring to use for -dnl # thunar-vfs. -dnl # -dnl # Sets LIBFAM_CFLAGS and LIBFAM_LIBS and defines -dnl # HAVE_FAM_H and HAVE_LIBFAM if FAM/Gamin were -dnl # found. -dnl # -dnl # Sets $ac_bm_thunar_vfs_monitor_impl to "FAM", -dnl # "Gamin" or "none". -dnl # -AC_DEFUN([BM_THUNAR_VFS_MONITOR_IMPL], -[ -LIBFAM_CFLAGS="" -LIBFAM_LIBS="" -have_libfam=no -ac_bm_thunar_vfs_monitor_impl="none" -XDT_CHECK_PACKAGE([LIBFAM], [gamin], [0.1.0], -[ - have_libfam=yes - ac_bm_thunar_vfs_monitor_impl="Gamin" -], -[ - dnl Fallback to a generic FAM check - AC_CHECK_HEADERS([fam.h], - [ - AC_CHECK_LIB([fam], [FAMOpen], - [ - have_libfam="yes" LIBFAM_LIBS="-lfam" - ac_bm_thunar_vfs_monitor_impl="FAM" - ]) - ]) -]) -if test x"$have_libfam" = x"yes"; then - dnl Define appropriate symbols - AC_DEFINE([HAVE_FAM_H], [1], [Define to 1 if you have the <fam.h> header file.]) - AC_DEFINE([HAVE_LIBFAM], [1], [Define to 1 if the File Alteration Monitor is available.]) - - dnl Check for FAMNoExists (currently Gamin only) - save_LIBS="$LIBS" - LIBS="$LIBS $LIBFAM_LIBS" - AC_CHECK_FUNCS([FAMNoExists]) - LIBS="$save_LIBS" -fi -AC_SUBST([LIBFAM_CFLAGS]) -AC_SUBST([LIBFAM_LIBS]) -]) - - - -dnl # BM_THUNAR_VFS_OS_IMPL() -dnl # -dnl # Determine the operating system support to use -dnl # for thunar-vfs. -dnl # -dnl # Sets ac_bm_thunar_vfs_os_impl to "bsd" or "generic" and -dnl # defines the automake conditional THUNAR_VFS_OS_IMPL_BSD. -dnl # -AC_DEFUN([BM_THUNAR_VFS_OS_IMPL], -[ - dnl # Auto-detect target operating system support - AC_MSG_CHECKING([for operating system support]) - case "$target_os" in - dragonfly*|freebsd*|netbsd*|openbsd*|darwin*) - dnl # The BSD Family is fully supported - ac_bm_thunar_vfs_os_impl=bsd - ;; - - *) - dnl # Otherwise fallback to generic OS support - ac_bm_thunar_vfs_os_impl=generic - esac - AC_MSG_RESULT([$ac_bm_thunar_vfs_os_impl]) - - dnl # Set automake conditionals appropriately - AM_CONDITIONAL([THUNAR_VFS_OS_IMPL_BSD], [test x"$ac_bm_thunar_vfs_os_impl" = x"bsd"]) -]) - - - -dnl # BM_THUNAR_VFS_VOLUME_IMPL() -dnl # -dnl # Determines the volume manager implementation to -dnl # use for thunar-vfs. -dnl # -dnl # Sets ac_bm_thunar_vfs_volume_impl to "freebsd", -dnl # "hal" or "none". -dnl # -AC_DEFUN([BM_THUNAR_VFS_VOLUME_IMPL], -[ - dnl The --with-volume-manager option - AC_ARG_WITH([volume-manager], -AC_HELP_STRING([--with-volume-manager=@<:@auto/freebsd/hal/none@:>@], [The volume manager implementation @<:@default=auto@:>@]), - [], [with_volume_manager=auto]) - - dnl # Check if we should try to auto-detect - if test x"$with_volume_manager" = x"freebsd"; then - ac_bm_thunar_vfs_volume_impl=freebsd - elif test x"$with_volume_manager" = x"hal"; then - ac_bm_thunar_vfs_volume_impl=hal - elif test x"$with_volume_manager" = x"none"; then - ac_bm_thunar_vfs_volume_impl=none - else - dnl # Check if HAL is available - XDT_CHECK_PACKAGE([HAL], [hal-storage], [0.5.0], - [ - dnl # HAL is available, use it - ac_bm_thunar_vfs_volume_impl=hal - ], - [ - dnl # Check operating system type - case "$target_os" in - freebsd*) - dnl # FreeBSD is fully supported - ac_bm_thunar_vfs_volume_impl=freebsd - ;; - *) - dnl # Otherwise no volume support - ac_bm_thunar_vfs_volume_impl=none - ;; - esac - ]) - fi - - dnl # We need HAL >= 0.5.x and D-BUS >= 0.23 for the HAL volume manager - if test x"$ac_bm_thunar_vfs_volume_impl" = x"hal"; then - XDT_CHECK_PACKAGE([EXO_HAL], [exo-hal-1], [0.3.1.13]) - XDT_CHECK_PACKAGE([HAL], [hal-storage], [0.5.0]) - XDT_CHECK_PACKAGE([HAL_DBUS], [dbus-glib-1], [0.23]) - fi - - dnl # Set config.h variables depending on what we're going to use - AC_MSG_CHECKING([for the volume manager implemenation]) - case "$ac_bm_thunar_vfs_volume_impl" in - freebsd) - AC_DEFINE([THUNAR_VFS_VOLUME_IMPL_FREEBSD], [1], [Define to 1 if the FreeBSD volume manager implementation should be used]) - ;; - - hal) - AC_DEFINE([THUNAR_VFS_VOLUME_IMPL_HAL], [1], [Define to 1 if the HAL volume manager implementation should be used]) - ;; - - *) - AC_DEFINE([THUNAR_VFS_VOLUME_IMPL_NONE], [1], [Define to 1 if no volume manager implementation should be used]) - ;; - esac - AC_MSG_RESULT([$ac_bm_thunar_vfs_volume_impl]) - - dnl # Set automake conditionals appropriately - AM_CONDITIONAL([THUNAR_VFS_VOLUME_IMPL_FREEBSD], [test x"$ac_bm_thunar_vfs_volume_impl" = x"freebsd"]) - AM_CONDITIONAL([THUNAR_VFS_VOLUME_IMPL_HAL], [test x"$ac_bm_thunar_vfs_volume_impl" = x"hal"]) - AM_CONDITIONAL([THUNAR_VFS_VOLUME_IMPL_NONE], [test x"$ac_bm_thunar_vfs_volume_impl" = x"none"]) -]) diff --git a/autogen.sh b/autogen.sh index 9bbd6784c..c1ce7d7ea 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,12 +1,23 @@ #!/bin/sh # -# $Id$ +# vi:set et ai sw=2 sts=2 ts=2: */ +#- +# Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> # -# Copyright (c) 2002-2006 -# The Thunar development team. All rights reserved. +# 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. # -# Written for Thunar by Benedikt Meurer <benny@xfce.org>. +# 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. (type xdt-autogen) >/dev/null 2>&1 || { cat >&2 <<EOF @@ -18,22 +29,4 @@ EOF exit 1 } -# verify that po/LINGUAS is present -(test -f po/LINGUAS) >/dev/null 2>&1 || { - cat >&2 <<EOF -autogen.sh: The file po/LINGUAS could not be found. Please check your snapshot - or try to checkout again. -EOF - exit 1 -} - -# substitute revision and linguas -linguas=`sed -e '/^#/d' po/LINGUAS` -revision=`LC_ALL=C svn info $0 | awk '/^Revision: / {printf "%05d\n", $2}'` -sed -e "s/@LINGUAS@/${linguas}/g" \ - -e "s/@REVISION@/${revision}/g" \ - < "configure.in.in" > "configure.in" - -exec xdt-autogen $@ - -# vi:set ts=2 sw=2 et ai: +XDT_AUTOGEN_REQUIRED_VERSION="4.7.0" exec xdt-autogen $@ diff --git a/configure.in.in b/configure.in.in index d94c60830..cea90b504 100644 --- a/configure.in.in +++ b/configure.in.in @@ -1,36 +1,45 @@ -dnl $Id$ -dnl -dnl Copyright (c) 2004-2007 -dnl The Thunar development team. All rights reserved. -dnl -dnl Written for Thunar by Benedikt Meurer <benny@xfce.org>. -dnl +# vi:set et ai sw=2 sts=2 ts=2: */ +#- +# Copyright (c) 2004-2007 Benedikt Meurer <benny@xfce.org> +# Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> +# +# 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. dnl *************************** dnl *** Version information *** dnl *************************** -m4_define([thunar_verinfo], [5:1:3]) -m4_define([thunar_version_api], [1]) +m4_define([thunarx_verinfo], [0:0:0]) +m4_define([thunarx_version_api], [2]) m4_define([thunar_version_major], [1]) m4_define([thunar_version_minor], [0]) m4_define([thunar_version_micro], [1]) m4_define([thunar_version_nano], []) -m4_define([thunar_version_build], [r@REVISION@]) -m4_define([thunar_version_tag], []) -m4_define([thunar_version], [thunar_version_major().thunar_version_minor().thunar_version_micro()ifelse(thunar_version_nano(), [], [], [.thunar_version_nano()])ifelse(thunar_version_tag(), [svn], [thunar_version_tag()-thunar_version_build()], [thunar_version_tag()])]) +m4_define([thunar_version_build], [@REVISION@]) +m4_define([thunar_version_tag], [git]) +m4_define([thunar_version], [thunar_version_major().thunar_version_minor().thunar_version_micro()ifelse(thunar_version_nano(), [], [], [.thunar_version_nano()])ifelse(thunar_version_tag(), [git], [thunar_version_tag()-thunar_version_build()], [thunar_version_tag()])]) dnl ******************************************* dnl *** Debugging support for SVN snapshots *** dnl ******************************************* -m4_define([thunar_debug_default], [ifelse(thunar_version_tag(), [svn], [yes], [minimum])]) +m4_define([thunar_debug_default], [ifelse(thunar_version_tag(), [git], [yes], [minimum])]) dnl *************************** dnl *** Initialize autoconf *** dnl *************************** -AC_COPYRIGHT([Copyright (c) 2004-2009 - The Thunar development team. All rights reserved. - -Written for Thunar by Benedikt Meurer <benny@xfce.org>.]) +AC_COPYRIGHT([Copyright (c) 2004-2009 The Thunar development team. All rights reserved.]) AC_INIT([Thunar], [thunar_version], [http://bugzilla.xfce.org/], [Thunar]) AC_PREREQ([2.50]) AC_CANONICAL_TARGET() @@ -73,13 +82,13 @@ AC_PROG_LIBTOOL() dnl ************************************** dnl *** Substitute version information *** dnl ************************************** -THUNAR_VERINFO=thunar_verinfo() -THUNAR_VERSION_API=thunar_version_api() +THUNARX_VERINFO=thunarx_verinfo() +THUNARX_VERSION_API=thunarx_version_api() THUNAR_VERSION_MAJOR=thunar_version_major() THUNAR_VERSION_MINOR=thunar_version_minor() THUNAR_VERSION_MICRO=thunar_version_micro() -AC_SUBST([THUNAR_VERINFO]) -AC_SUBST([THUNAR_VERSION_API]) +AC_SUBST([THUNARX_VERINFO]) +AC_SUBST([THUNARX_VERSION_API]) AC_SUBST([THUNAR_VERSION_MAJOR]) AC_SUBST([THUNAR_VERSION_MINOR]) AC_SUBST([THUNAR_VERSION_MICRO]) @@ -107,49 +116,17 @@ AC_SYS_LARGEFILE() dnl ********************************** dnl *** Check for standard headers *** dnl ********************************** -AC_CHECK_HEADERS([ctype.h dirent.h errno.h fcntl.h fnmatch.h fstab.h grp.h \ - limits.h locale.h math.h memory.h mntent.h paths.h pwd.h \ - regex.h sched.h setjmp.h signal.h stdarg.h stdlib.h \ - string.h syslog.h sys/xattr.h sys/extattr.h sys/cdio.h \ - sys/mman.h sys/mount.h sys/param.h sys/resource.h sys/stat.h \ - sys/statfs.h sys/statvfs.h sys/time.h sys/ucred.h sys/uio.h \ - sys/vfs.h sys/wait.h time.h wchar.h wctype.h]) +AC_CHECK_HEADERS([ctype.h errno.h fcntl.h grp.h limits.h locale.h memory.h \ + paths.h pwd.h sched.h signal.h stdarg.h stdlib.h string.h \ + sys/mman.h sys/stat.h sys/time.h sys/types.h sys/uio.h \ + sys/wait.h time.h]) dnl ************************************ dnl *** Check for standard functions *** dnl ************************************ AC_FUNC_MMAP() -AC_CHECK_FUNCS([attropen extattr_get_fd fgetxattr futimes getdents getfsspec \ - getfsstat lchmod localeconv localtime_r mbrtowc mkdtemp mkfifo \ - posix_madvise pread pwrite readdir_r sched_yield setgroupent \ - setmntent setpassent setpriority statfs statvfs statvfs1 \ - strcoll strlcpy strptime symlink syslog posix_fadvise]) - -dnl ****************************************** -dnl *** Linux/glibc specified work-arounds *** -dnl ****************************************** -AC_MSG_CHECKING([whether we need _BSD_SOURCE and _XOPEN_SOURCE]) -AC_TRY_LINK([#include <features.h>], -[ - if (__GLIBC_PREREQ (2, 0)); -], -[ - AC_DEFINE([_XOPEN_SOURCE], [600], [Required to unbreak glibc]) - AC_DEFINE([_BSD_SOURCE], [1], [Required to unbreak glibc]) - AC_MSG_RESULT([yes]) -], -[ - AC_MSG_RESULT([no]) -]) - -dnl ************************************************************** -dnl *** Check for f_mntonname in statfs (trash implementation) *** -dnl ************************************************************** -AC_CHECK_MEMBERS([struct statfs.f_mntonname],,, -[ -#include <sys/param.h> -#include <sys/mount.h> -]) +AC_CHECK_FUNCS([localeconv mkdtemp pread pwrite sched_yield setgroupent \ + setpassent strcoll strlcpy strptime symlink]) dnl ****************************** dnl *** Check for i18n support *** @@ -159,39 +136,32 @@ XDT_I18N([@LINGUAS@]) dnl *********************************** dnl *** Check for required packages *** dnl *********************************** -XDT_CHECK_PACKAGE([EXO], [exo-1], [0.3.100]) -XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.12.0]) -XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.12.0]) -XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0]) -XDT_CHECK_PACKAGE([GDK_PIXBUF], [gdk-pixbuf-2.0], [2.10.0]) +XDT_CHECK_PACKAGE([EXO], [exo-1], [0.3.101]) +XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.18.0]) +XDT_CHECK_PACKAGE([GIO], [gio-2.0], [2.18.0]) +XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.18.0]) +XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.14.0]) +XDT_CHECK_PACKAGE([GDK_PIXBUF], [gdk-pixbuf-2.0], [2.14.0]) XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.6.0]) -dnl ********************************************* -dnl *** Check for libpng (with various names) *** -dnl ********************************************* -XDT_CHECK_PACKAGE([LIBPNG], [libpng], [1.2.0], [], -[ - dnl # libpng.pc not found, try with libpng12.pc - XDT_CHECK_PACKAGE([LIBPNG], [libpng12], [1.2.0]) -]) - dnl ******************************************** dnl *** Check for session management support *** dnl ******************************************** XDT_CHECK_LIBSM() dnl ********************************** -dnl *** Optional support for D-BUS *** +dnl *** Optional GIO UNIX features *** dnl ********************************** -XDT_CHECK_OPTIONAL_PACKAGE([DBUS], [dbus-glib-1], - [0.34], [dbus], [D-BUS support]) +XDT_CHECK_OPTIONAL_PACKAGE([GIO_UNIX], [gio-unix-2.0], + [2.18.0], [gio-unix], [GIO UNIX features]) dnl ******************************************************* dnl *** Optional support for gconf (GNOME thumbnailers) *** -dnl ******************************************************* -XDT_CHECK_OPTIONAL_PACKAGE([GCONF], [gconf-2.0], - [2.4.0], [gnome-thumbnailers], - [GNOME thumbnailer support]) +dnl ********************************** +dnl *** Optional support for D-BUS *** +dnl ********************************** +XDT_CHECK_OPTIONAL_PACKAGE([DBUS], [dbus-glib-1], + [0.34], [dbus], [D-BUS support]) dnl ************************************************* dnl *** Optional support for startup notification *** @@ -201,42 +171,6 @@ XDT_CHECK_OPTIONAL_PACKAGE([LIBSTARTUP_NOTIFICATION], [0.4], [startup-notification], [startup notification library]) -dnl ****************************** -dnl *** Check for FreeType 2.x *** -dnl ****************************** -FREETYPE_LIBS="" -FREETYPE_CFLAGS="" -AC_PATH_PROG([FREETYPE_CONFIG], [freetype-config], [no]) -if test x"$FREETYPE_CONFIG" != x"no"; then - AC_MSG_CHECKING([FREETYPE_CFLAGS]) - FREETYPE_CFLAGS="`$FREETYPE_CONFIG --cflags`" - AC_MSG_RESULT([$FREETYPE_CFLAGS]) - - AC_MSG_CHECKING([FREETYPE_LIBS]) - FREETYPE_LIBS="`$FREETYPE_CONFIG --libs`" - AC_MSG_RESULT([$FREETYPE_LIBS]) -fi -AM_CONDITIONAL([HAVE_FREETYPE], [test x"$FREETYPE_CONFIG" != x"no"]) -AC_SUBST([FREETYPE_CFLAGS]) -AC_SUBST([FREETYPE_LIBS]) - -dnl ************************* -dnl *** Check for libjpeg *** -dnl ************************* -LIBJPEG_LIBS="" -LIBJPEG_CFLAGS="" -AC_CHECK_LIB([jpeg], [jpeg_start_decompress], -[ - AC_CHECK_HEADER([jpeglib.h], - [ - LIBJPEG_LIBS="-ljpeg -lm" - AC_DEFINE([HAVE_LIBJPEG], [1], [Define to 1 if libjpeg is found]) - AC_DEFINE([HAVE_JPEGLIB_H], [1], [Define to 1 if jpeglib.h is found]) - ]) -], [-lm]) -AC_SUBST([LIBJPEG_CFLAGS]) -AC_SUBST([LIBJPEG_LIBS]) - dnl ************************* dnl *** Check for gtk-doc *** dnl ************************* @@ -266,76 +200,62 @@ if test x"$enable_xml2po" = x"yes"; then fi AM_CONDITIONAL([ENABLE_XML2PO], [test x"$enable_xml2po" = x"yes"]) -dnl ****************************************** -dnl *** Check for operating system support *** -dnl ****************************************** -BM_THUNAR_VFS_OS_IMPL() - -dnl **************************************************** -dnl *** Check for file system monitor implementation *** -dnl **************************************************** -BM_THUNAR_VFS_MONITOR_IMPL() - -dnl *********************************************** -dnl *** Check for volume manager implementation *** -dnl *********************************************** -BM_THUNAR_VFS_VOLUME_IMPL() - dnl *********************************** dnl *** Check for debugging support *** dnl *********************************** -AC_ARG_ENABLE([debug], -AC_HELP_STRING([--enable-debug=@<:@no/minimum/yes/full@:>@], [Turn on debugging @<:@default=thunar_debug_default@:>@]), - [], [enable_debug=thunar_debug_default]) -AC_MSG_CHECKING([whether to enable debugging support]) -if test x"$enable_debug" = x"full" -o x"$enable_debug" = x"yes"; then - dnl Print the result - AC_MSG_RESULT([$enable_debug]) - - dnl Make sure we detect possible errors (if supported) - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -Wall -Werror" - AC_MSG_CHECKING([whether $CC accepts -Wall -Werror]) - AC_COMPILE_IFELSE(AC_LANG_SOURCE([int x;]), [ - AC_MSG_RESULT([yes]) - PLATFORM_CFLAGS="$PLATFORM_CFLAGS -Wall -Werror" - ], [ - AC_MSG_RESULT([no]) - ]) - CFLAGS="$save_CFLAGS" - - dnl Paranoia for --enable-debug=full - if test x"$enable_debug" = x"full"; then - dnl Enable extensive debugging - PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_ENABLE_DEBUG" - - dnl Use -O0 -g3 if the compiler supports it - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -O0 -g3" - AC_MSG_CHECKING([whether $CC accepts -O0 -g3]) - AC_COMPILE_IFELSE(AC_LANG_SOURCE([int x;]), [ - AC_MSG_RESULT([yes]) - PLATFORM_CFLAGS="$PLATFORM_CFLAGS -O0 -g3" - ], [ - AC_MSG_RESULT([no]) - ]) - CFLAGS="$save_CFLAGS" - fi -else - dnl Print the result - AC_MSG_RESULT([$enable_debug]) - - dnl Disable debugging (release build) - PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DNDEBUG" - - dnl Disable object cast checks - PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_DISABLE_CAST_CHECKS" - - dnl Disable all checks for --enable-debug=no - if test x"$enable_debug" = x"no"; then - PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_DISABLE_ASSERT -DG_DISABLE_CHECKS" - fi -fi +XDT_FEATURE_DEBUG() +#AC_ARG_ENABLE([debug], +#AC_HELP_STRING([--enable-debug=@<:@no/minimum/yes/full@:>@], [Turn on debugging @<:@default=thunar_debug_default@:>@]), +# [], [enable_debug=thunar_debug_default]) +#AC_MSG_CHECKING([whether to enable debugging support]) +#if test x"$enable_debug" = x"full" -o x"$enable_debug" = x"yes"; then +# dnl Print the result +# AC_MSG_RESULT([$enable_debug]) +# +# dnl Make sure we detect possible errors (if supported) +# save_CFLAGS="$CFLAGS" +# CFLAGS="$CFLAGS -Wall -Werror" +# AC_MSG_CHECKING([whether $CC accepts -Wall -Werror]) +# AC_COMPILE_IFELSE(AC_LANG_SOURCE([int x;]), [ +# AC_MSG_RESULT([yes]) +# PLATFORM_CFLAGS="$PLATFORM_CFLAGS -Wall -Werror" +# ], [ +# AC_MSG_RESULT([no]) +# ]) +# CFLAGS="$save_CFLAGS" +# +# dnl Paranoia for --enable-debug=full +# if test x"$enable_debug" = x"full"; then +# dnl Enable extensive debugging +# PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_ENABLE_DEBUG" +# +# dnl Use -O0 -g3 if the compiler supports it +# save_CFLAGS="$CFLAGS" +# CFLAGS="$CFLAGS -O0 -g3" +# AC_MSG_CHECKING([whether $CC accepts -O0 -g3]) +# AC_COMPILE_IFELSE(AC_LANG_SOURCE([int x;]), [ +# AC_MSG_RESULT([yes]) +# PLATFORM_CFLAGS="$PLATFORM_CFLAGS -O0 -g3" +# ], [ +# AC_MSG_RESULT([no]) +# ]) +# CFLAGS="$save_CFLAGS" +# fi +#else +# dnl Print the result +# AC_MSG_RESULT([$enable_debug]) +# +# dnl Disable debugging (release build) +# PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DNDEBUG" +# +# dnl Disable object cast checks +# PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_DISABLE_CAST_CHECKS" +# +# dnl Disable all checks for --enable-debug=no +# if test x"$enable_debug" = x"no"; then +# PLATFORM_CPPFLAGS="$PLATFORM_CPPFLAGS -DG_DISABLE_ASSERT -DG_DISABLE_CHECKS" +# fi +#fi dnl ************************************** dnl *** Check for linker optimizations *** @@ -460,8 +380,6 @@ docs/manual/zh_TW/Thunar.xml docs/manual/zh_TW/images/Makefile docs/papers/Makefile docs/reference/Makefile -docs/reference/thunar-vfs/Makefile -docs/reference/thunar-vfs/version.xml docs/reference/thunarx/Makefile docs/reference/thunarx/version.xml examples/Makefile @@ -483,14 +401,9 @@ po/Makefile.in po-doc/Makefile tdb/Makefile tdb/tdbconfig.h -tests/Makefile -tests/data/Makefile thunar/Makefile -thunar-vfs/Makefile -thunar-vfs/thunar-vfs-1.pc -thunar-vfs/thunar-vfs-config.h thunarx/Makefile -thunarx/thunarx-1.pc +thunarx/thunarx-2.pc thunarx/thunarx-config.h ]) @@ -500,24 +413,21 @@ dnl *************************** echo echo "Build Configuration:" echo -echo "* Operating system support: $ac_bm_thunar_vfs_os_impl" if test x"$DBUS_FOUND" = x"yes"; then echo "* D-BUS support: yes" else echo "* D-BUS support: no" fi -echo "* File System Monitor: $ac_bm_thunar_vfs_monitor_impl" -if test x"$GCONF_FOUND" = x"yes"; then -echo "* GNOME Thumbnailers: yes" +if test x"$GIO_UNIX_FOUND" = x"yes"; then +echo "* GIO UNIX features: yes" else -echo "* GNOME Thumbnailers: no" +echo "* GIO UNIX features: no" fi if test x"$LIBSTARTUP_NOTIFICATION_FOUND" = x"yes"; then echo "* Startup Notification: yes" else echo "* Startup Notification: no" fi -echo "* Volume Manager: $ac_bm_thunar_vfs_volume_impl" echo "* Debug Support: $enable_debug" echo echo "Additional Plugins:" diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am index 7f82cdca9..d95c60c5b 100644 --- a/docs/reference/Makefile.am +++ b/docs/reference/Makefile.am @@ -1,7 +1,6 @@ # $Id$ SUBDIRS = \ - thunar-vfs \ thunarx # vi:set ts=8 sw=8 noet ai nocindent syntax=automake: diff --git a/docs/reference/thunar-vfs/Makefile.am b/docs/reference/thunar-vfs/Makefile.am deleted file mode 100644 index 722118536..000000000 --- a/docs/reference/thunar-vfs/Makefile.am +++ /dev/null @@ -1,70 +0,0 @@ -# $Id$ - -AUTOMAKE_OPTIONS = 1.8 - -# The name of the module. -DOC_MODULE=thunar-vfs - -# The top-level SGML file. -DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml - -# Extra options to supply to gtkdoc-scan -SCAN_OPTIONS=--deprecated-guards="EXO_DISABLE_DEPRECATED" - -# Extra options to pass to gtkdoc-scangobj -SCANGOBJ_OPTIONS= - -# The directory containing the source code. Relative to $(srcdir) -DOC_SOURCE_DIR=../../../thunar-vfs - -# Extra options to supply to gtkdoc-mkdb -MKDB_OPTIONS=--sgml-mode --output-format=xml - -# Extra options to supply to gtkdoc-fixref -FIXXREF_OPTIONS= - -# Used for dependencies -HFILE_GLOB=$(top_srcdir)/thunar-vfs/*.h -CFILE_GLOB=$(top_srcdir)/thunar-vfs/*.c - -# Header files to ignore when scanning -IGNORE_HFILES= \ - thunar-vfs-alias.h \ - thunar-vfs-marshal.h \ - thunar-vfs-volume-manager-bsd.h \ - thunar-vfs-volume-manager-impl.h \ - thunar-vfs-volume-manager-sysv.h - -# Extra files to add when scanning (relative to $srcdir) -EXTRA_HFILES= - -# Images to copy into HTML directory -HTML_IMAGES = - -# Extra SGML files that are included by DOC_MAIN_SGML_FILE -content_files = \ - version.xml - -# CFLAGS and LDFLAGS for compiling scan program. Only needed -# if $(DOC_MODULE).types is non-empty. -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_builddir) \ - $(EXO_CFLAGS) \ - $(GTHREAD_CFLAGS) - -GTKDOC_LIBS = \ - $(EXO_LIBS) \ - $(GTHREAD_LIBS) \ - $(top_builddir)/thunar-vfs/libthunar-vfs-$(THUNAR_VERSION_API).la - -include $(top_srcdir)/gtk-doc.make - -# Other files to distribute -EXTRA_DIST += \ - version.xml.in - -# required for gtk-doc -dist-hook: all - -# vi:set ts=8 sw=8 noet ai nocindent syntax=automake: diff --git a/docs/reference/thunar-vfs/thunar-vfs-docs.sgml b/docs/reference/thunar-vfs/thunar-vfs-docs.sgml deleted file mode 100644 index 7c2219eb9..000000000 --- a/docs/reference/thunar-vfs/thunar-vfs-docs.sgml +++ /dev/null @@ -1,125 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" - "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"[ -<!ENTITY thunar-vfs-group SYSTEM "xml/thunar-vfs-group.xml"> -<!ENTITY thunar-vfs-info SYSTEM "xml/thunar-vfs-info.xml"> -<!ENTITY thunar-vfs-init-shutdown SYSTEM "xml/thunar-vfs-init-shutdown.xml"> -<!ENTITY thunar-vfs-job SYSTEM "xml/thunar-vfs-job.xml"> -<!ENTITY thunar-vfs-jobs SYSTEM "xml/thunar-vfs-jobs.xml"> -<!ENTITY thunar-vfs-mime-action SYSTEM "xml/thunar-vfs-mime-action.xml"> -<!ENTITY thunar-vfs-mime-application SYSTEM "xml/thunar-vfs-mime-application.xml"> -<!ENTITY thunar-vfs-mime-database SYSTEM "xml/thunar-vfs-mime-database.xml"> -<!ENTITY thunar-vfs-mime-handler SYSTEM "xml/thunar-vfs-mime-handler.xml"> -<!ENTITY thunar-vfs-mime-info SYSTEM "xml/thunar-vfs-mime-info.xml"> -<!ENTITY thunar-vfs-monitor SYSTEM "xml/thunar-vfs-monitor.xml"> -<!ENTITY thunar-vfs-operations SYSTEM "xml/thunar-vfs-operations.xml"> -<!ENTITY thunar-vfs-types SYSTEM "xml/thunar-vfs-types.xml"> -<!ENTITY thunar-vfs-path SYSTEM "xml/thunar-vfs-path.xml"> -<!ENTITY thunar-vfs-user SYSTEM "xml/thunar-vfs-user.xml"> -<!ENTITY thunar-vfs-user-manager SYSTEM "xml/thunar-vfs-user-manager.xml"> -<!ENTITY thunar-vfs-util SYSTEM "xml/thunar-vfs-util.xml"> -<!ENTITY thunar-vfs-volume SYSTEM "xml/thunar-vfs-volume.xml"> -<!ENTITY thunar-vfs-volume-manager SYSTEM "xml/thunar-vfs-volume-manager.xml"> - -<!ENTITY version SYSTEM "version.xml"> -<!ENTITY date "December 2007"> -]> - -<book id="index"> - <bookinfo> - <title>Thunar-VFS Reference Manual</title> - <releaseinfo>Version &version;</releaseinfo> - <pubdate>&date;</pubdate> - - <copyright> - <year>2005</year> - <year>2006</year> - <holder>Benedikt Meurer</holder> - </copyright> - - <legalnotice id="legalnotice"> - <para> - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU Free Documentation License, Version 1.1 or - any later version published by the Free Software Foundation; with no - Invariant Sections, with no Front-Cover Texts, and with no Back-Cover - Texts. The complete license text is available from the <ulink - type="http" url="http://www.gnu.org/">Free Software Foundation</ulink>. - </para> - </legalnotice> - - <authorgroup> - <author> - <firstname>Benedikt</firstname> - <surname>Meurer</surname> - <affiliation> - <address><email>benny@xfce.org</email></address> - <orgname>os-cillation</orgname> - <orgdiv>System development</orgdiv> - <jobtitle>Software developer</jobtitle> - </affiliation> - </author> - </authorgroup> - </bookinfo> - - <part id="introduction"> - <title>Introduction</title> - </part> - - <part id="fundamentals"> - <title>Fundamentals</title> - &thunar-vfs-init-shutdown; - &thunar-vfs-types; - &thunar-vfs-path; - &thunar-vfs-info; - &thunar-vfs-util; - </part> - - <part id="jobs"> - <title>Jobs</title> - <para> - This section describes the available jobs that are used to perform file system - operations in an asychronous fashion. Jobs are represented by the <link - linkend="ThunarVfsJob">ThunarVfsJob</link> class, which provides several - signals used to monitor the activity of the job and handle interaction with - the user as required. - </para> - &thunar-vfs-job; - &thunar-vfs-jobs; - </part> - - <part id="filesystem-monitoring"> - <title>Filesystem Monitoring</title> - &thunar-vfs-monitor; - </part> - - <part id="mime-types"> - <title>MIME Types</title> - &thunar-vfs-mime-info; - &thunar-vfs-mime-database; - &thunar-vfs-mime-handler; - &thunar-vfs-mime-application; - &thunar-vfs-mime-action; - </part> - - <part id="users-and-groups-handling"> - <title>Users and Groups Handling</title> - &thunar-vfs-user; - &thunar-vfs-group; - &thunar-vfs-user-manager; - </part> - - <part id="volume-handling"> - <title>Volume Handling</title> - &thunar-vfs-volume; - &thunar-vfs-volume-manager; - </part> - - <index> - <title>Index</title> - </index> -</book> - -<!-- - vi:set ts=2 sw=2 et ai syntax=docbkxml: ---> diff --git a/docs/reference/thunar-vfs/thunar-vfs-overrides.txt b/docs/reference/thunar-vfs/thunar-vfs-overrides.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/reference/thunar-vfs/thunar-vfs-sections.txt b/docs/reference/thunar-vfs/thunar-vfs-sections.txt deleted file mode 100644 index 4256c5376..000000000 --- a/docs/reference/thunar-vfs/thunar-vfs-sections.txt +++ /dev/null @@ -1,449 +0,0 @@ -<INCLUDE>thunar-vfs/thunar-vfs.h</INCLUDE> - - - -<SECTION> -<FILE>thunar-vfs-group</FILE> -<TITLE>ThunarVfsGroup</TITLE> -ThunarVfsGroup -thunar_vfs_group_get_id -thunar_vfs_group_get_name -<SUBSECTION Standard> -ThunarVfsGroupClass -THUNAR_VFS_TYPE_GROUP -THUNAR_VFS_GROUP -THUNAR_VFS_GROUP_CLASS -THUNAR_VFS_IS_GROUP -THUNAR_VFS_IS_GROUP_CLASS -THUNAR_VFS_GROUP_GET_CLASS -<SUBSECTION Private> -thunar_vfs_group_get_type -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-info</FILE> -<TITLE>ThunarVfsInfo</TITLE> -ThunarVfsInfo -thunar_vfs_info_new_for_path -thunar_vfs_info_ref -thunar_vfs_info_unref -thunar_vfs_info_copy -thunar_vfs_info_get_custom_icon -thunar_vfs_info_get_free_space -thunar_vfs_info_get_metadata -thunar_vfs_info_read_link -thunar_vfs_info_execute -thunar_vfs_info_rename -thunar_vfs_info_matches -thunar_vfs_info_list_free -<SUBSECTION Standard> -THUNAR_VFS_TYPE_INFO -<SUBSECTION Private> -thunar_vfs_info_get_type -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-init-shutdown</FILE> -<TITLE>Initialization and Shutdown</TITLE> -thunar_vfs_init -thunar_vfs_shutdown -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-job</FILE> -<TITLE>ThunarVfsJob</TITLE> -ThunarVfsJobResponse -ThunarVfsJob -thunar_vfs_job_launch -thunar_vfs_job_cancel -thunar_vfs_job_cancelled -<SUBSECTION Standard> -ThunarVfsJobClass -THUNAR_VFS_TYPE_JOB -THUNAR_VFS_JOB -THUNAR_VFS_JOB_CLASS -THUNAR_VFS_IS_JOB -THUNAR_VFS_IS_JOB_CLASS -THUNAR_VFS_JOB_GET_CLASS -<SUBSECTION Private> -ThunarVfsJobPrivate -thunar_vfs_job_get_type -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-jobs</FILE> -<TITLE>Jobs</TITLE> -thunar_vfs_listdir -thunar_vfs_create_file -thunar_vfs_create_files -thunar_vfs_copy_file -thunar_vfs_copy_files -thunar_vfs_link_file -thunar_vfs_link_files -thunar_vfs_move_file -thunar_vfs_move_files -thunar_vfs_unlink_file -thunar_vfs_unlink_files -thunar_vfs_make_directory -thunar_vfs_make_directories -thunar_vfs_change_mode -thunar_vfs_change_group -thunar_vfs_change_owner -thunar_vfs_deep_count -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-mime-action</FILE> -<TITLE>ThunarVfsMimeAction</TITLE> -ThunarVfsMimeAction -<SUBSECTION Standard> -ThunarVfsMimeActionClass -THUNAR_VFS_TYPE_MIME_ACTION -THUNAR_VFS_MIME_ACTION -THUNAR_VFS_MIME_ACTION_CLASS -THUNAR_VFS_IS_MIME_ACTION -THUNAR_VFS_IS_MIME_ACTION_CLASS -THUNAR_VFS_MIME_ACTION_GET_CLASS -<SUBSECTION Private> -thunar_vfs_mime_action_get_type -</SECTION> - - -<SECTION> -<FILE>thunar-vfs-mime-application</FILE> -<TITLE>ThunarVfsMimeApplication</TITLE> -ThunarVfsMimeApplication -thunar_vfs_mime_application_new_from_desktop_id -thunar_vfs_mime_application_new_from_file -thunar_vfs_mime_application_is_usercreated -thunar_vfs_mime_application_get_actions -thunar_vfs_mime_application_get_command -thunar_vfs_mime_application_get_desktop_id -thunar_vfs_mime_application_get_flags -thunar_vfs_mime_application_get_mime_types -thunar_vfs_mime_application_get_name -thunar_vfs_mime_application_hash -thunar_vfs_mime_application_equal -<SUBSECTION Standard> -ThunarVfsMimeActionClass -THUNAR_VFS_TYPE_MIME_APPLICATION -THUNAR_VFS_MIME_APPLICATION -THUNAR_VFS_MIME_APPLICATION_CLASS -THUNAR_VFS_IS_MIME_APPLICATION -THUNAR_VFS_IS_MIME_APPLICATION_CLASS -THUNAR_VFS_MIME_APPLICATION_GET_CLASS -<SUBSECTION Private> -thunar_vfs_mime_application_get_type -</SECTION> - - -<SECTION> -<FILE>thunar-vfs-mime-database</FILE> -<TITLE>ThunarVfsMimeDatabase</TITLE> -ThunarVfsMimeDatabase -thunar_vfs_mime_database_get_default -thunar_vfs_mime_database_get_info -thunar_vfs_mime_database_get_info_for_data -thunar_vfs_mime_database_get_info_for_name -thunar_vfs_mime_database_get_info_for_file -thunar_vfs_mime_database_get_infos_for_info -thunar_vfs_mime_database_get_applications -thunar_vfs_mime_database_get_default_application -thunar_vfs_mime_database_set_default_application -thunar_vfs_mime_database_add_application -thunar_vfs_mime_database_remove_application -<SUBSECTION Standard> -ThunarVfsMimeDatabaseClass -THUNAR_VFS_TYPE_MIME_DATABASE -THUNAR_VFS_MIME_DATABASE -THUNAR_VFS_MIME_DATABASE_CLASS -THUNAR_VFS_IS_MIME_DATABASE -THUNAR_VFS_IS_MIME_DATABASE_CLASS -THUNAR_VFS_MIME_DATABASE_GET_CLASS -<SUBSECTION Private> -thunar_vfs_mime_database_get_type -</SECTION> - - -<SECTION> -<FILE>thunar-vfs-mime-handler</FILE> -<TITLE>ThunarVfsMimeHandler</TITLE> -ThunarVfsMimeHandlerFlags -ThunarVfsMimeHandler -thunar_vfs_mime_handler_get_command -thunar_vfs_mime_handler_get_flags -thunar_vfs_mime_handler_get_name -thunar_vfs_mime_handler_exec -thunar_vfs_mime_handler_exec_with_env -thunar_vfs_mime_handler_lookup_icon_name -<SUBSECTION Standard> -ThunarVfsMimeHandlerClass -THUNAR_VFS_TYPE_MIME_HANDLER -THUNAR_VFS_MIME_HANDLER -THUNAR_VFS_MIME_HANDLER_CLASS -THUNAR_VFS_IS_MIME_HANDLER -THUNAR_VFS_IS_MIME_HANDLER_CLASS -THUNAR_VFS_MIME_HANDLER_GET_CLASS -<SUBSECTION Private> -thunar_vfs_mime_handler_get_type -</SECTION> - - -<SECTION> -<FILE>thunar-vfs-mime-info</FILE> -<TITLE>ThunarVfsMimeInfo</TITLE> -ThunarVfsMimeInfo -thunar_vfs_mime_info_new -thunar_vfs_mime_info_ref -thunar_vfs_mime_info_unref -thunar_vfs_mime_info_get_comment -thunar_vfs_mime_info_get_name -thunar_vfs_mime_info_get_media -thunar_vfs_mime_info_get_subtype -thunar_vfs_mime_info_hash -thunar_vfs_mime_info_equal -thunar_vfs_mime_info_lookup_icon_name -thunar_vfs_mime_info_list_free -<SUBSECTION Standard> -THUNAR_VFS_TYPE_MIME_INFO -<SUBSECTION Private> -thunar_vfs_mime_info_get_type -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-monitor</FILE> -<TITLE>ThunarVfsMonitor</TITLE> -ThunarVfsMonitor -ThunarVfsMonitorEvent -ThunarVfsMonitorHandle -ThunarVfsMonitorCallback -thunar_vfs_monitor_get_default -thunar_vfs_monitor_add_directory -thunar_vfs_monitor_add_file -thunar_vfs_monitor_remove -thunar_vfs_monitor_feed -thunar_vfs_monitor_wait -<SUBSECTION Standard> -ThunarVfsMonitorClass -THUNAR_VFS_TYPE_VFS_MONITOR_EVENT -THUNAR_VFS_TYPE_MONITOR -THUNAR_VFS_MONITOR -THUNAR_VFS_MONITOR_CLASS -THUNAR_VFS_IS_MONITOR -THUNAR_VFS_IS_MONITOR_CLASS -THUNAR_VFS_MONITOR_GET_CLASS -<SUBSECTION Private> -thunar_vfs_monitor_event_get_type -thunar_vfs_monitor_get_type -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-operations</FILE> -<TITLE>Operations</TITLE> -thunar_vfs_listdir -thunar_vfs_create_file -thunar_vfs_create_files -thunar_vfs_copy_file -thunar_vfs_copy_files -thunar_vfs_link_file -thunar_vfs_link_files -thunar_vfs_move_file -thunar_vfs_move_files -thunar_vfs_unlink_file -thunar_vfs_unlink_files -thunar_vfs_make_directory -thunar_vfs_make_directories -thunar_vfs_change_mode -thunar_vfs_change_group -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-types</FILE> -<TITLE>Basic Types</TITLE> -ThunarVfsDeepCountFlags -ThunarVfsFileType -ThunarVfsFileMode -ThunarVfsFileFlags -ThunarVfsFileDevice -ThunarVfsFileSize -ThunarVfsFileTime -ThunarVfsGroupId -ThunarVfsUserId -<SUBSECTION Standard> -THUNAR_VFS_TYPE_VFS_FILE_TYPE -THUNAR_VFS_TYPE_VFS_FILE_MODE -THUNAR_VFS_TYPE_VFS_FILE_FLAGS -<SUBSECTION Private> -thunar_vfs_file_type_get_type -thunar_vfs_file_mode_get_type -thunar_vfs_file_flags_get_type -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-path</FILE> -<TITLE>ThunarVfsPath</TITLE> -ThunarVfsPathScheme -ThunarVfsPath -THUNAR_VFS_TYPE_PATH -THUNAR_VFS_TYPE_PATH_LIST -thunar_vfs_path_new -thunar_vfs_path_get_for_home -thunar_vfs_path_get_for_root -thunar_vfs_path_ref -thunar_vfs_path_unref -thunar_vfs_path_hash -thunar_vfs_path_equal -thunar_vfs_path_is_ancestor -thunar_vfs_path_is_home -thunar_vfs_path_is_root -thunar_vfs_path_relative -thunar_vfs_path_get_name -thunar_vfs_path_get_parent -thunar_vfs_path_get_scheme -thunar_vfs_path_dup_string -thunar_vfs_path_to_string -thunar_vfs_path_dup_uri -thunar_vfs_path_to_uri -thunar_vfs_path_list_from_string -thunar_vfs_path_list_to_string -thunar_vfs_path_list_append -thunar_vfs_path_list_prepend -thunar_vfs_path_list_copy -thunar_vfs_path_list_free -<SUBSECTION Private> -thunar_vfs_path_get_type -thunar_vfs_path_list_get_type -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-user</FILE> -<TITLE>ThunarVfsUser</TITLE> -ThunarVfsUser -thunar_vfs_user_get_groups -thunar_vfs_user_get_primary_group -thunar_vfs_user_get_id -thunar_vfs_user_get_name -thunar_vfs_user_get_real_name -thunar_vfs_user_is_me -<SUBSECTION Standard> -ThunarVfsUserClass -THUNAR_VFS_TYPE_USER -THUNAR_VFS_USER -THUNAR_VFS_USER_CLASS -THUNAR_VFS_IS_USER -THUNAR_VFS_IS_USER_CLASS -THUNAR_VFS_USER_GET_CLASS -<SUBSECTION Private> -thunar_vfs_user_get_type -</SECTION> - - -<SECTION> -<FILE>thunar-vfs-user-manager</FILE> -<TITLE>ThunarVfsUserManager</TITLE> -ThunarVfsUserManager -thunar_vfs_user_manager_get_default -thunar_vfs_user_manager_get_group_by_id -thunar_vfs_user_manager_get_user_by_id -thunar_vfs_user_manager_get_all_groups -<SUBSECTION Standard> -ThunarVfsUserManagerClass -THUNAR_VFS_TYPE_USER_MANAGER -THUNAR_VFS_USER_MANAGER -THUNAR_VFS_USER_MANAGER_CLASS -THUNAR_VFS_IS_USER_MANAGER -THUNAR_VFS_IS_USER_MANAGER_CLASS -THUNAR_VFS_USER_MANAGER_GET_CLASS -<SUBSECTION Private> -thunar_vfs_user_manager_get_type -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-util</FILE> -<TITLE>Utility Functions</TITLE> -thunar_vfs_canonicalize_filename -thunar_vfs_expand_filename -thunar_vfs_humanize_size -</SECTION> - - - -<SECTION> -<FILE>thunar-vfs-volume</FILE> -<TITLE>ThunarVfsVolume</TITLE> -ThunarVfsVolumeKind -ThunarVfsVolumeStatus -ThunarVfsVolume -thunar_vfs_volume_get_kind -thunar_vfs_volume_get_name -thunar_vfs_volume_get_status -thunar_vfs_volume_get_mount_point -thunar_vfs_volume_is_mounted -thunar_vfs_volume_is_present -thunar_vfs_volume_is_ejectable -thunar_vfs_volume_is_removable -thunar_vfs_volume_lookup_icon_name -thunar_vfs_volume_eject -thunar_vfs_volume_mount -thunar_vfs_volume_unmount -<SUBSECTION Standard> -ThunarVfsVolumeClass -THUNAR_VFS_TYPE_VFS_VOLUME_KIND -THUNAR_VFS_TYPE_VFS_VOLUME_STATUS -THUNAR_VFS_TYPE_VOLUME -THUNAR_VFS_VOLUME -THUNAR_VFS_VOLUME_CLASS -THUNAR_VFS_IS_VOLUME -THUNAR_VFS_IS_VOLUME_CLASS -THUNAR_VFS_VOLUME_GET_CLASS -<SUBSECTION Private> -thunar_vfs_volume_kind_get_type -thunar_vfs_volume_status_get_type -thunar_vfs_volume_get_type -</SECTION> - - -<SECTION> -<FILE>thunar-vfs-volume-manager</FILE> -<TITLE>ThunarVfsVolumeManager</TITLE> -ThunarVfsVolumeManager -thunar_vfs_volume_manager_get_default -thunar_vfs_volume_manager_get_volume_by_info -thunar_vfs_volume_manager_get_volumes -<SUBSECTION Standard> -ThunarVfsVolumeManagerClass -THUNAR_VFS_TYPE_VOLUME_MANAGER -THUNAR_VFS_VOLUME_MANAGER -THUNAR_VFS_VOLUME_MANAGER_CLASS -THUNAR_VFS_IS_VOLUME_MANAGER -THUNAR_VFS_IS_VOLUME_MANAGER_CLASS -THUNAR_VFS_VOLUME_MANAGER_GET_CLASS -<SUBSECTION Private> -thunar_vfs_volume_manager_get_type -</SECTION> - - - - diff --git a/docs/reference/thunar-vfs/thunar-vfs.types b/docs/reference/thunar-vfs/thunar-vfs.types deleted file mode 100644 index 68bc195fa..000000000 --- a/docs/reference/thunar-vfs/thunar-vfs.types +++ /dev/null @@ -1,17 +0,0 @@ -#include <thunar-vfs/thunar-vfs.h> - -thunar_vfs_group_get_type -thunar_vfs_info_get_type -thunar_vfs_job_get_type -thunar_vfs_mime_action_get_type -thunar_vfs_mime_application_get_type -thunar_vfs_mime_database_get_type -thunar_vfs_mime_handler_get_type -thunar_vfs_mime_info_get_type -thunar_vfs_monitor_get_type -thunar_vfs_path_get_type -thunar_vfs_user_get_type -thunar_vfs_user_manager_get_type -thunar_vfs_volume_get_type -thunar_vfs_volume_manager_get_type - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-group.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-group.sgml deleted file mode 100644 index fb221fc5b..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-group.sgml +++ /dev/null @@ -1,43 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsGroup - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsGroup ##### --> -<para> - -</para> - - -<!-- ##### FUNCTION thunar_vfs_group_get_id ##### --> -<para> - -</para> - -@group: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_group_get_name ##### --> -<para> - -</para> - -@group: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-info.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-info.sgml deleted file mode 100644 index 8ee24e273..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-info.sgml +++ /dev/null @@ -1,158 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsInfo - -<!-- ##### SECTION Short_Description ##### --> -Stores information about files. - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - <link linkend="thunar-vfs-Basic-Types">Basic Types</link> -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsInfo ##### --> -<para> - The Thunar-VFS equivalent of <function>stat(2)</function>, extended with - advanced information like display name and mime type. -</para> - -@type: the file type. -@mode: the file permissions and special mode flags. -@flags: the file flags. -@uid: the owner's user id. -@gid: the owner's group id. -@size: the file size in bytes. -@atime: the time of last access. -@mtime: the time of last modification. -@ctime: the time of last status change. -@device: the file's device. -@mime_info: the file's mime type. -@path: the file's path. -@custom_icon: a custom icon name or %NULL. -@display_name: the file's display name (UTF-8). - -<!-- ##### FUNCTION thunar_vfs_info_new_for_path ##### --> -<para> - -</para> - -@path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_ref ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_unref ##### --> -<para> - -</para> - -@info: - - -<!-- ##### FUNCTION thunar_vfs_info_copy ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_get_custom_icon ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_get_free_space ##### --> -<para> - -</para> - -@info: -@free_space_return: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_get_metadata ##### --> -<para> - -</para> - -@info: -@metadata: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_read_link ##### --> -<para> - -</para> - -@info: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_execute ##### --> -<para> - -</para> - -@info: -@screen: -@path_list: -@working_directory: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_rename ##### --> -<para> - -</para> - -@info: -@name: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_matches ##### --> -<para> - -</para> - -@a: -@b: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_info_list_free ##### --> -<para> - -</para> - -@info_list: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-init-shutdown.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-init-shutdown.sgml deleted file mode 100644 index 81a5d86c3..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-init-shutdown.sgml +++ /dev/null @@ -1,33 +0,0 @@ -<!-- ##### SECTION Title ##### --> -Initialization and Shutdown - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### FUNCTION thunar_vfs_init ##### --> -<para> - -</para> - - - -<!-- ##### FUNCTION thunar_vfs_shutdown ##### --> -<para> - -</para> - - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-interactive-job.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-interactive-job.sgml deleted file mode 100644 index 80f8f14b8..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-interactive-job.sgml +++ /dev/null @@ -1,35 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsInteractiveJob - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### ENUM ThunarVfsInteractiveJobResponse ##### --> -<para> - -</para> - -@THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES: -@THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES_ALL: -@THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_NO: -@THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_CANCEL: - -<!-- ##### STRUCT ThunarVfsInteractiveJob ##### --> -<para> - -</para> - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-job.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-job.sgml deleted file mode 100644 index 26328911c..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-job.sgml +++ /dev/null @@ -1,131 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsJob - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### ENUM ThunarVfsJobResponse ##### --> -<para> - -</para> - -@THUNAR_VFS_JOB_RESPONSE_YES: -@THUNAR_VFS_JOB_RESPONSE_YES_ALL: -@THUNAR_VFS_JOB_RESPONSE_NO: -@THUNAR_VFS_JOB_RESPONSE_CANCEL: -@THUNAR_VFS_JOB_RESPONSE_NO_ALL: -@THUNAR_VFS_JOB_RESPONSE_RETRY: - -<!-- ##### STRUCT ThunarVfsJob ##### --> -<para> - -</para> - - -<!-- ##### SIGNAL ThunarVfsJob::ask ##### --> -<para> - -</para> - -@thunarvfsjob: the object which received the signal. -@arg1: -@arg2: -@Returns: - -<!-- ##### SIGNAL ThunarVfsJob::ask-replace ##### --> -<para> - -</para> - -@thunarvfsjob: the object which received the signal. -@arg1: -@arg2: -@Returns: - -<!-- ##### SIGNAL ThunarVfsJob::error ##### --> -<para> - -</para> - -@thunarvfsjob: the object which received the signal. -@arg1: - -<!-- ##### SIGNAL ThunarVfsJob::finished ##### --> -<para> - -</para> - -@thunarvfsjob: the object which received the signal. - -<!-- ##### SIGNAL ThunarVfsJob::info-message ##### --> -<para> - -</para> - -@thunarvfsjob: the object which received the signal. -@arg1: - -<!-- ##### SIGNAL ThunarVfsJob::infos-ready ##### --> -<para> - -</para> - -@thunarvfsjob: the object which received the signal. -@arg1: -@Returns: - -<!-- ##### SIGNAL ThunarVfsJob::new-files ##### --> -<para> - -</para> - -@thunarvfsjob: the object which received the signal. -@arg1: - -<!-- ##### SIGNAL ThunarVfsJob::percent ##### --> -<para> - -</para> - -@thunarvfsjob: the object which received the signal. -@arg1: - -<!-- ##### FUNCTION thunar_vfs_job_launch ##### --> -<para> - -</para> - -@job: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_job_cancel ##### --> -<para> - -</para> - -@job: - - -<!-- ##### FUNCTION thunar_vfs_job_cancelled ##### --> -<para> - -</para> - -@job: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-jobs.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-jobs.sgml deleted file mode 100644 index 25f873ebb..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-jobs.sgml +++ /dev/null @@ -1,205 +0,0 @@ -<!-- ##### SECTION Title ##### --> -Jobs - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### FUNCTION thunar_vfs_listdir ##### --> -<para> - -</para> - -@path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_create_file ##### --> -<para> - -</para> - -@path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_create_files ##### --> -<para> - -</para> - -@path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_copy_file ##### --> -<para> - -</para> - -@source_path: -@target_path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_copy_files ##### --> -<para> - -</para> - -@source_path_list: -@target_path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_link_file ##### --> -<para> - -</para> - -@source_path: -@target_path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_link_files ##### --> -<para> - -</para> - -@source_path_list: -@target_path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_move_file ##### --> -<para> - -</para> - -@source_path: -@target_path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_move_files ##### --> -<para> - -</para> - -@source_path_list: -@target_path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_unlink_file ##### --> -<para> - -</para> - -@path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_unlink_files ##### --> -<para> - -</para> - -@path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_make_directory ##### --> -<para> - -</para> - -@path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_make_directories ##### --> -<para> - -</para> - -@path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_change_mode ##### --> -<para> - -</para> - -@path: -@dir_mask: -@dir_mode: -@file_mask: -@file_mode: -@recursive: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_change_group ##### --> -<para> - -</para> - -@path: -@gid: -@recursive: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_change_owner ##### --> -<para> - -</para> - -@path: -@uid: -@recursive: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_deep_count ##### --> -<para> - -</para> - -@path: -@flags: -@error: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-action.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-action.sgml deleted file mode 100644 index cd104dda4..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-action.sgml +++ /dev/null @@ -1,27 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsMimeAction - -<!-- ##### SECTION Short_Description ##### --> -Registered desktop actions for #ThunarVfsMimeApplication<!---->s. - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - <link linkend="ThunarVfsMimeApplication">ThunarVfsMimeApplication</link> - and <link linked="ThunarVfsMimeHandler">ThunarVfsMimeHandler</link> -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsMimeAction ##### --> -<para> - The #ThunarVfsMimeAction-struct contains private data only, and should - be accessed using the functions below. -</para> - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-application.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-application.sgml deleted file mode 100644 index 54f197fd0..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-application.sgml +++ /dev/null @@ -1,119 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsMimeApplication - -<!-- ##### SECTION Short_Description ##### --> -Registered Applications for MIME types. - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - <link linkend="ThunarVfsMimeHandler">ThunarVfsMimeHandler</link> - and <link linkend="ThunarVfsMimeAction">ThunarVfsMimeAction</link> -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsMimeApplication ##### --> -<para> - The #ThunarVfsMimeApplication struct contains private data only, and should - be accessed using the functions below. -</para> - - -<!-- ##### FUNCTION thunar_vfs_mime_application_new_from_desktop_id ##### --> -<para> - -</para> - -@desktop_id: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_application_new_from_file ##### --> -<para> - -</para> - -@path: -@desktop_id: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_application_is_usercreated ##### --> -<para> - -</para> - -@mime_application: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_application_get_actions ##### --> -<para> - -</para> - -@mime_application: -@Returns: - - -<!-- ##### MACRO thunar_vfs_mime_application_get_command ##### --> -<para> - -</para> - -@mime_application: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_application_get_desktop_id ##### --> -<para> - -</para> - -@mime_application: -@Returns: - - -<!-- ##### MACRO thunar_vfs_mime_application_get_flags ##### --> -<para> - -</para> - -@mime_application: -@Returns: - - -<!-- ##### MACRO thunar_vfs_mime_application_get_name ##### --> -<para> - -</para> - -@mime_application: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_application_hash ##### --> -<para> - -</para> - -@mime_application: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_application_equal ##### --> -<para> - -</para> - -@a: -@b: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-database.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-database.sgml deleted file mode 100644 index 93ae7f02e..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-database.sgml +++ /dev/null @@ -1,144 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsMimeDatabase - -<!-- ##### SECTION Short_Description ##### --> -Provides access to the MIME database. - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - <link - linkend="thunar-vfs-ThunarVfsMimeApplication">ThunarVfsMimeApplication</link>, - <link linkend="thunar-vfs-ThunarVfsMimeInfo">ThunarVfsMimeInfo</link> -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsMimeDatabase ##### --> -<para> - The #ThunarVfsMimeDatabase-struct contains private data only, and should - be accessed using the functions below. -</para> - - -<!-- ##### FUNCTION thunar_vfs_mime_database_get_default ##### --> -<para> - -</para> - -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_get_info ##### --> -<para> - -</para> - -@database: -@mime_type: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_get_info_for_data ##### --> -<para> - -</para> - -@database: -@data: -@length: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_get_info_for_name ##### --> -<para> - -</para> - -@database: -@name: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_get_info_for_file ##### --> -<para> - -</para> - -@database: -@path: -@name: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_get_infos_for_info ##### --> -<para> - -</para> - -@database: -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_get_applications ##### --> -<para> - -</para> - -@database: -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_get_default_application ##### --> -<para> - -</para> - -@database: -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_set_default_application ##### --> -<para> - -</para> - -@database: -@info: -@application: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_add_application ##### --> -<para> - -</para> - -@database: -@info: -@name: -@exec: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_database_remove_application ##### --> -<para> - -</para> - -@database: -@application: -@error: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-handler.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-handler.sgml deleted file mode 100644 index c2395c242..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-handler.sgml +++ /dev/null @@ -1,120 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsMimeHandler - -<!-- ##### SECTION Short_Description ##### --> -Abstract base class for #ThunarVfsMimeApplication and #ThunarVfsMimeAction. - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - <link linkend="ThunarVfsMimeApplication">ThunarVfsMimeApplication</link> - and <link linked="ThunarVfsMimeAction">ThunarVfsMimeAction</link> -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### ENUM ThunarVfsMimeHandlerFlags ##### --> -<para> - -</para> - -@THUNAR_VFS_MIME_HANDLER_HIDDEN: -@THUNAR_VFS_MIME_HANDLER_REQUIRES_TERMINAL: -@THUNAR_VFS_MIME_HANDLER_SUPPORTS_STARTUP_NOTIFY: -@THUNAR_VFS_MIME_HANDLER_SUPPORTS_MULTI: -@THUNAR_VFS_MIME_HANDLER_SUPPORTS_URIS: - -<!-- ##### STRUCT ThunarVfsMimeHandler ##### --> -<para> - The #ThunarVfsMimeHandler-struct contains private data only, and should - be accessed using the functions below. -</para> - - -<!-- ##### ARG ThunarVfsMimeHandler:command ##### --> -<para> - -</para> - -<!-- ##### ARG ThunarVfsMimeHandler:flags ##### --> -<para> - -</para> - -<!-- ##### ARG ThunarVfsMimeHandler:icon ##### --> -<para> - -</para> - -<!-- ##### ARG ThunarVfsMimeHandler:name ##### --> -<para> - -</para> - -<!-- ##### FUNCTION thunar_vfs_mime_handler_get_command ##### --> -<para> - -</para> - -@mime_handler: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_handler_get_flags ##### --> -<para> - -</para> - -@mime_handler: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_handler_get_name ##### --> -<para> - -</para> - -@mime_handler: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_handler_exec ##### --> -<para> - -</para> - -@mime_handler: -@screen: -@path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_handler_exec_with_env ##### --> -<para> - -</para> - -@mime_handler: -@screen: -@path_list: -@envp: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_handler_lookup_icon_name ##### --> -<para> - -</para> - -@mime_handler: -@icon_theme: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-info.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-info.sgml deleted file mode 100644 index 47edee48e..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-mime-info.sgml +++ /dev/null @@ -1,126 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsMimeInfo - -<!-- ##### SECTION Short_Description ##### --> -Represents a MIME type in the system. - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - <link linkend="ThunarVfsMimeDatabase">ThunarVfsMimeDatabase</link> -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsMimeInfo ##### --> -<para> - The #ThunarVfsMimeInfo struct contains private data only, and should be - accessed using the functions below. -</para> - - -<!-- ##### FUNCTION thunar_vfs_mime_info_new ##### --> -<para> - -</para> - -@name: -@len: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_ref ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_unref ##### --> -<para> - -</para> - -@info: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_get_comment ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_get_name ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_get_media ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_get_subtype ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_hash ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_equal ##### --> -<para> - -</para> - -@a: -@b: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_lookup_icon_name ##### --> -<para> - -</para> - -@info: -@icon_theme: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_mime_info_list_free ##### --> -<para> - -</para> - -@info_list: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-monitor.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-monitor.sgml deleted file mode 100644 index 16bf9c7c1..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-monitor.sgml +++ /dev/null @@ -1,113 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsMonitor - -<!-- ##### SECTION Short_Description ##### --> -Portable file system monitoring class. - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsMonitor ##### --> -<para> - The #ThunarVfsMonitor-struct contains private data only, and should - be accessed using the functions below. -</para> - - -<!-- ##### ENUM ThunarVfsMonitorEvent ##### --> -<para> - -</para> - -@THUNAR_VFS_MONITOR_EVENT_CHANGED: -@THUNAR_VFS_MONITOR_EVENT_CREATED: -@THUNAR_VFS_MONITOR_EVENT_DELETED: - -<!-- ##### STRUCT ThunarVfsMonitorHandle ##### --> -<para> - -</para> - - -<!-- ##### USER_FUNCTION ThunarVfsMonitorCallback ##### --> -<para> - -</para> - -@monitor: -@handle: -@event: -@handle_path: -@event_path: -@user_data: - - -<!-- ##### FUNCTION thunar_vfs_monitor_get_default ##### --> -<para> - -</para> - -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_monitor_add_directory ##### --> -<para> - -</para> - -@monitor: -@path: -@callback: -@user_data: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_monitor_add_file ##### --> -<para> - -</para> - -@monitor: -@path: -@callback: -@user_data: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_monitor_remove ##### --> -<para> - -</para> - -@monitor: -@handle: - - -<!-- ##### FUNCTION thunar_vfs_monitor_feed ##### --> -<para> - -</para> - -@monitor: -@event: -@path: - - -<!-- ##### FUNCTION thunar_vfs_monitor_wait ##### --> -<para> - -</para> - -@monitor: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-operations.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-operations.sgml deleted file mode 100644 index 12c4fa2a7..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-operations.sgml +++ /dev/null @@ -1,182 +0,0 @@ -<!-- ##### SECTION Title ##### --> -Operations - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### FUNCTION thunar_vfs_listdir ##### --> -<para> - -</para> - -@path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_create_file ##### --> -<para> - -</para> - -@path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_create_files ##### --> -<para> - -</para> - -@path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_copy_file ##### --> -<para> - -</para> - -@source_path: -@target_path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_copy_files ##### --> -<para> - -</para> - -@source_path_list: -@target_path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_link_file ##### --> -<para> - -</para> - -@source_path: -@target_path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_link_files ##### --> -<para> - -</para> - -@source_path_list: -@target_path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_move_file ##### --> -<para> - -</para> - -@source_path: -@target_path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_move_files ##### --> -<para> - -</para> - -@source_path_list: -@target_path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_unlink_file ##### --> -<para> - -</para> - -@path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_unlink_files ##### --> -<para> - -</para> - -@path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_make_directory ##### --> -<para> - -</para> - -@path: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_make_directories ##### --> -<para> - -</para> - -@path_list: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_change_mode ##### --> -<para> - -</para> - -@path: -@dir_mask: -@dir_mode: -@file_mask: -@file_mode: -@recursive: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_change_group ##### --> -<para> - -</para> - -@path: -@gid: -@recursive: -@error: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-path.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-path.sgml deleted file mode 100644 index ff2e2d2d9..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-path.sgml +++ /dev/null @@ -1,273 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsPath - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### ENUM ThunarVfsPathScheme ##### --> -<para> - -</para> - -@THUNAR_VFS_PATH_SCHEME_FILE: -@THUNAR_VFS_PATH_SCHEME_TRASH: -@THUNAR_VFS_PATH_SCHEME_MASK: - -<!-- ##### STRUCT ThunarVfsPath ##### --> -<para> - -</para> - - -<!-- ##### MACRO THUNAR_VFS_TYPE_PATH ##### --> -<para> - -</para> - - - -<!-- ##### MACRO THUNAR_VFS_TYPE_PATH_LIST ##### --> -<para> - -</para> - - - -<!-- ##### FUNCTION thunar_vfs_path_new ##### --> -<para> - -</para> - -@identifier: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_get_for_home ##### --> -<para> - -</para> - -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_get_for_root ##### --> -<para> - -</para> - -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_ref ##### --> -<para> - -</para> - -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_unref ##### --> -<para> - -</para> - -@path: - - -<!-- ##### FUNCTION thunar_vfs_path_hash ##### --> -<para> - -</para> - -@path_ptr: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_equal ##### --> -<para> - -</para> - -@path_ptr_a: -@path_ptr_b: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_is_ancestor ##### --> -<para> - -</para> - -@path: -@ancestor: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_is_home ##### --> -<para> - -</para> - -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_is_root ##### --> -<para> - -</para> - -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_relative ##### --> -<para> - -</para> - -@parent: -@name: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_get_name ##### --> -<para> - -</para> - -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_get_parent ##### --> -<para> - -</para> - -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_get_scheme ##### --> -<para> - -</para> - -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_dup_string ##### --> -<para> - -</para> - -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_to_string ##### --> -<para> - -</para> - -@path: -@buffer: -@bufsize: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_dup_uri ##### --> -<para> - -</para> - -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_to_uri ##### --> -<para> - -</para> - -@path: -@buffer: -@bufsize: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_list_from_string ##### --> -<para> - -</para> - -@uri_string: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_list_to_string ##### --> -<para> - -</para> - -@path_list: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_list_append ##### --> -<para> - -</para> - -@path_list: -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_list_prepend ##### --> -<para> - -</para> - -@path_list: -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_list_copy ##### --> -<para> - -</para> - -@path_list: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_path_list_free ##### --> -<para> - -</para> - -@path_list: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-thumb-factory.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-thumb-factory.sgml deleted file mode 100644 index 89e2bffd3..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-thumb-factory.sgml +++ /dev/null @@ -1,97 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsThumbFactory - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsThumbFactory ##### --> -<para> - -</para> - - -<!-- ##### ARG ThunarVfsThumbFactory:size ##### --> -<para> - -</para> - -<!-- ##### FUNCTION thunar_vfs_thumb_factory_new ##### --> -<para> - -</para> - -@size: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_thumb_factory_lookup_thumbnail ##### --> -<para> - -</para> - -@factory: -@uri: -@mtime: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_thumb_factory_can_thumbnail ##### --> -<para> - -</para> - -@factory: -@uri: -@mime_info: -@mtime: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_thumb_factory_has_failed_thumbnail ##### --> -<para> - -</para> - -@factory: -@uri: -@mtime: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_thumb_factory_generate_thumbnail ##### --> -<para> - -</para> - -@factory: -@uri: -@mime_info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_thumb_factory_store_thumbnail ##### --> -<para> - -</para> - -@factory: -@pixbuf: -@uri: -@mtime: -@error: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-thumb.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-thumb.sgml deleted file mode 100644 index 28f9ce04b..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-thumb.sgml +++ /dev/null @@ -1,48 +0,0 @@ -<!-- ##### SECTION Title ##### --> -Thumbnail Functions - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### ENUM ThunarVfsThumbSize ##### --> -<para> - -</para> - -@THUNAR_VFS_THUMB_SIZE_NORMAL: -@THUNAR_VFS_THUMB_SIZE_LARGE: - -<!-- ##### FUNCTION thunar_vfs_thumb_path_for_uri ##### --> -<para> - -</para> - -@uri: -@size: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_thumb_path_is_valid ##### --> -<para> - -</para> - -@thumb_path: -@uri: -@mtime: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-trash-info.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-trash-info.sgml deleted file mode 100644 index 89e38f183..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-trash-info.sgml +++ /dev/null @@ -1,60 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsTrashInfo - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsTrashInfo ##### --> -<para> - -</para> - - -<!-- ##### FUNCTION thunar_vfs_trash_info_copy ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_info_free ##### --> -<para> - -</para> - -@info: - - -<!-- ##### FUNCTION thunar_vfs_trash_info_get_path ##### --> -<para> - -</para> - -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_info_get_deletion_date ##### --> -<para> - -</para> - -@info: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-trash-manager.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-trash-manager.sgml deleted file mode 100644 index c68a0c5c4..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-trash-manager.sgml +++ /dev/null @@ -1,68 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsTrashManager - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsTrashManager ##### --> -<para> - -</para> - - -<!-- ##### ARG ThunarVfsTrashManager:empty ##### --> -<para> - -</para> - -<!-- ##### FUNCTION thunar_vfs_trash_manager_get_default ##### --> -<para> - -</para> - -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_manager_is_empty ##### --> -<para> - -</para> - -@manager: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_manager_get_trashes ##### --> -<para> - -</para> - -@manager: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_manager_resolve_uri ##### --> -<para> - -</para> - -@manager: -@uri: -@path: -@error: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-trash.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-trash.sgml deleted file mode 100644 index c021b0f84..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-trash.sgml +++ /dev/null @@ -1,88 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsTrash - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsTrash ##### --> -<para> - -</para> - - -<!-- ##### ARG ThunarVfsTrash:files ##### --> -<para> - -</para> - -<!-- ##### FUNCTION thunar_vfs_trash_get_id ##### --> -<para> - -</para> - -@trash: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_get_files ##### --> -<para> - -</para> - -@trash: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_get_info ##### --> -<para> - -</para> - -@trash: -@file: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_get_info_path ##### --> -<para> - -</para> - -@trash: -@file: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_get_uri ##### --> -<para> - -</para> - -@trash: -@file: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_trash_get_path ##### --> -<para> - -</para> - -@trash: -@file: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-types.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-types.sgml deleted file mode 100644 index 80ce95b9d..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-types.sgml +++ /dev/null @@ -1,109 +0,0 @@ -<!-- ##### SECTION Title ##### --> -Basic Types - -<!-- ##### SECTION Short_Description ##### --> -Standard Thunar-VFS types, defined for ease-of-use and portability. - -<!-- ##### SECTION Long_Description ##### --> -<para> - Thunar-VFS defines a number of commonly used types to abstract the details - of the underlying system. -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> -Stable - -<!-- ##### ENUM ThunarVfsDeepCountFlags ##### --> -<para> - -</para> - -@THUNAR_VFS_DEEP_COUNT_FLAGS_NONE: -@THUNAR_VFS_DEEP_COUNT_FLAGS_FOLLOW_SYMLINKS: - -<!-- ##### ENUM ThunarVfsFileType ##### --> -<para> - -</para> - -@THUNAR_VFS_FILE_TYPE_PORT: -@THUNAR_VFS_FILE_TYPE_DOOR: -@THUNAR_VFS_FILE_TYPE_SOCKET: -@THUNAR_VFS_FILE_TYPE_SYMLINK: -@THUNAR_VFS_FILE_TYPE_REGULAR: -@THUNAR_VFS_FILE_TYPE_BLOCKDEV: -@THUNAR_VFS_FILE_TYPE_DIRECTORY: -@THUNAR_VFS_FILE_TYPE_CHARDEV: -@THUNAR_VFS_FILE_TYPE_FIFO: -@THUNAR_VFS_FILE_TYPE_UNKNOWN: - -<!-- ##### ENUM ThunarVfsFileMode ##### --> -<para> - -</para> - -@THUNAR_VFS_FILE_MODE_SUID: -@THUNAR_VFS_FILE_MODE_SGID: -@THUNAR_VFS_FILE_MODE_STICKY: -@THUNAR_VFS_FILE_MODE_USR_ALL: -@THUNAR_VFS_FILE_MODE_USR_READ: -@THUNAR_VFS_FILE_MODE_USR_WRITE: -@THUNAR_VFS_FILE_MODE_USR_EXEC: -@THUNAR_VFS_FILE_MODE_GRP_ALL: -@THUNAR_VFS_FILE_MODE_GRP_READ: -@THUNAR_VFS_FILE_MODE_GRP_WRITE: -@THUNAR_VFS_FILE_MODE_GRP_EXEC: -@THUNAR_VFS_FILE_MODE_OTH_ALL: -@THUNAR_VFS_FILE_MODE_OTH_READ: -@THUNAR_VFS_FILE_MODE_OTH_WRITE: -@THUNAR_VFS_FILE_MODE_OTH_EXEC: - -<!-- ##### ENUM ThunarVfsFileFlags ##### --> -<para> - -</para> - -@THUNAR_VFS_FILE_FLAGS_NONE: -@THUNAR_VFS_FILE_FLAGS_SYMLINK: -@THUNAR_VFS_FILE_FLAGS_EXECUTABLE: -@THUNAR_VFS_FILE_FLAGS_HIDDEN: -@THUNAR_VFS_FILE_FLAGS_READABLE: -@THUNAR_VFS_FILE_FLAGS_WRITABLE: - -<!-- ##### TYPEDEF ThunarVfsFileDevice ##### --> -<para> - Datatype to represent the device number of a file. -</para> - - -<!-- ##### TYPEDEF ThunarVfsFileSize ##### --> -<para> - Datatype to represent file sizes (in bytes). The file size - is always represented as a 64bit integer, even on system that - do not support large files. -</para> - - -<!-- ##### TYPEDEF ThunarVfsFileTime ##### --> -<para> - Datatype to represent file times (in seconds). -</para> - - -<!-- ##### TYPEDEF ThunarVfsGroupId ##### --> -<para> - Datatype to represent a group id. -</para> - - -<!-- ##### TYPEDEF ThunarVfsUserId ##### --> -<para> - Datatype to represent a user id. -</para> - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-uri.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-uri.sgml deleted file mode 100644 index 06e3b3a61..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-uri.sgml +++ /dev/null @@ -1,234 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsURI - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsURI ##### --> -<para> - -</para> - - -<!-- ##### ENUM ThunarVfsURIScheme ##### --> -<para> - -</para> - -@THUNAR_VFS_URI_SCHEME_COMPUTER: -@THUNAR_VFS_URI_SCHEME_FILE: -@THUNAR_VFS_URI_SCHEME_TRASH: - -<!-- ##### FUNCTION thunar_vfs_uri_new ##### --> -<para> - -</para> - -@identifier: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_new_for_path ##### --> -<para> - -</para> - -@path: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_ref ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_unref ##### --> -<para> - -</para> - -@uri: - - -<!-- ##### FUNCTION thunar_vfs_uri_is_home ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_is_root ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_get_display_name ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_get_md5sum ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_get_name ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_get_path ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_get_scheme ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_parent ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_relative ##### --> -<para> - -</para> - -@uri: -@name: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_to_string ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_hash ##### --> -<para> - -</para> - -@uri: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_equal ##### --> -<para> - -</para> - -@a: -@b: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_list_from_string ##### --> -<para> - -</para> - -@string: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_list_to_string ##### --> -<para> - -</para> - -@uri_list: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_list_copy ##### --> -<para> - -</para> - -@uri_list: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_uri_list_free ##### --> -<para> - -</para> - -@uri_list: - - -<!-- ##### MACRO thunar_vfs_uri_list_append ##### --> -<para> - -</para> - -@uri_list: -@uri: - - -<!-- ##### MACRO thunar_vfs_uri_list_prepend ##### --> -<para> - -</para> - -@uri_list: -@uri: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-user-manager.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-user-manager.sgml deleted file mode 100644 index 164cbf1a6..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-user-manager.sgml +++ /dev/null @@ -1,62 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsUserManager - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsUserManager ##### --> -<para> - -</para> - - -<!-- ##### FUNCTION thunar_vfs_user_manager_get_default ##### --> -<para> - -</para> - -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_user_manager_get_group_by_id ##### --> -<para> - -</para> - -@manager: -@id: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_user_manager_get_user_by_id ##### --> -<para> - -</para> - -@manager: -@id: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_user_manager_get_all_groups ##### --> -<para> - -</para> - -@manager: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-user.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-user.sgml deleted file mode 100644 index b86dd79e8..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-user.sgml +++ /dev/null @@ -1,79 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsUser - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsUser ##### --> -<para> - -</para> - - -<!-- ##### FUNCTION thunar_vfs_user_get_groups ##### --> -<para> - -</para> - -@user: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_user_get_primary_group ##### --> -<para> - -</para> - -@user: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_user_get_id ##### --> -<para> - -</para> - -@user: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_user_get_name ##### --> -<para> - -</para> - -@user: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_user_get_real_name ##### --> -<para> - -</para> - -@user: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_user_is_me ##### --> -<para> - -</para> - -@user: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-util.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-util.sgml deleted file mode 100644 index db19b1599..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-util.sgml +++ /dev/null @@ -1,49 +0,0 @@ -<!-- ##### SECTION Title ##### --> -Utility Functions - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### FUNCTION thunar_vfs_canonicalize_filename ##### --> -<para> - -</para> - -@filename: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_expand_filename ##### --> -<para> - -</para> - -@filename: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_humanize_size ##### --> -<para> - -</para> - -@size: -@buffer: -@buflen: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume-manager.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume-manager.sgml deleted file mode 100644 index a291a9ad1..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume-manager.sgml +++ /dev/null @@ -1,93 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsVolumeManager - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### STRUCT ThunarVfsVolumeManager ##### --> -<para> - -</para> - -@volumes: - -<!-- ##### SIGNAL ThunarVfsVolumeManager::volume-mounted ##### --> -<para> - -</para> - -@thunarvfsvolumemanager: the object which received the signal. -@arg1: - -<!-- ##### SIGNAL ThunarVfsVolumeManager::volume-pre-unmount ##### --> -<para> - -</para> - -@thunarvfsvolumemanager: the object which received the signal. -@arg1: - -<!-- ##### SIGNAL ThunarVfsVolumeManager::volume-unmounted ##### --> -<para> - -</para> - -@thunarvfsvolumemanager: the object which received the signal. -@arg1: - -<!-- ##### SIGNAL ThunarVfsVolumeManager::volumes-added ##### --> -<para> - -</para> - -@thunarvfsvolumemanager: the object which received the signal. -@arg1: - -<!-- ##### SIGNAL ThunarVfsVolumeManager::volumes-removed ##### --> -<para> - -</para> - -@thunarvfsvolumemanager: the object which received the signal. -@arg1: - -<!-- ##### FUNCTION thunar_vfs_volume_manager_get_default ##### --> -<para> - -</para> - -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_manager_get_volume_by_info ##### --> -<para> - -</para> - -@manager: -@info: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_manager_get_volumes ##### --> -<para> - -</para> - -@manager: -@Returns: - - diff --git a/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume.sgml b/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume.sgml deleted file mode 100644 index 67041b754..000000000 --- a/docs/reference/thunar-vfs/tmpl/thunar-vfs-volume.sgml +++ /dev/null @@ -1,200 +0,0 @@ -<!-- ##### SECTION Title ##### --> -ThunarVfsVolume - -<!-- ##### SECTION Short_Description ##### --> - - -<!-- ##### SECTION Long_Description ##### --> -<para> - -</para> - -<!-- ##### SECTION See_Also ##### --> -<para> - -</para> - -<!-- ##### SECTION Stability_Level ##### --> - - -<!-- ##### ENUM ThunarVfsVolumeKind ##### --> -<para> - -</para> - -@THUNAR_VFS_VOLUME_KIND_UNKNOWN: -@THUNAR_VFS_VOLUME_KIND_CDROM: -@THUNAR_VFS_VOLUME_KIND_CDR: -@THUNAR_VFS_VOLUME_KIND_CDRW: -@THUNAR_VFS_VOLUME_KIND_DVDROM: -@THUNAR_VFS_VOLUME_KIND_DVDRAM: -@THUNAR_VFS_VOLUME_KIND_DVDR: -@THUNAR_VFS_VOLUME_KIND_DVDRW: -@THUNAR_VFS_VOLUME_KIND_DVDPLUSR: -@THUNAR_VFS_VOLUME_KIND_DVDPLUSRW: -@THUNAR_VFS_VOLUME_KIND_FLOPPY: -@THUNAR_VFS_VOLUME_KIND_HARDDISK: -@THUNAR_VFS_VOLUME_KIND_USBSTICK: -@THUNAR_VFS_VOLUME_KIND_AUDIO_PLAYER: -@THUNAR_VFS_VOLUME_KIND_AUDIO_CD: -@THUNAR_VFS_VOLUME_KIND_MEMORY_CARD: -@THUNAR_VFS_VOLUME_KIND_REMOVABLE_DISK: - -<!-- ##### ENUM ThunarVfsVolumeStatus ##### --> -<para> - -</para> - -@THUNAR_VFS_VOLUME_STATUS_MOUNTED: -@THUNAR_VFS_VOLUME_STATUS_PRESENT: -@THUNAR_VFS_VOLUME_STATUS_MOUNTABLE: - -<!-- ##### STRUCT ThunarVfsVolume ##### --> -<para> - -</para> - - -<!-- ##### SIGNAL ThunarVfsVolume::changed ##### --> -<para> - -</para> - -@thunarvfsvolume: the object which received the signal. - -<!-- ##### SIGNAL ThunarVfsVolume::mounted ##### --> -<para> - -</para> - -@thunarvfsvolume: the object which received the signal. - -<!-- ##### SIGNAL ThunarVfsVolume::pre-unmount ##### --> -<para> - -</para> - -@thunarvfsvolume: the object which received the signal. - -<!-- ##### SIGNAL ThunarVfsVolume::unmounted ##### --> -<para> - -</para> - -@thunarvfsvolume: the object which received the signal. - -<!-- ##### FUNCTION thunar_vfs_volume_get_kind ##### --> -<para> - -</para> - -@volume: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_get_name ##### --> -<para> - -</para> - -@volume: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_get_status ##### --> -<para> - -</para> - -@volume: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_get_mount_point ##### --> -<para> - -</para> - -@volume: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_is_mounted ##### --> -<para> - -</para> - -@volume: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_is_present ##### --> -<para> - -</para> - -@volume: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_is_ejectable ##### --> -<para> - -</para> - -@volume: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_is_removable ##### --> -<para> - -</para> - -@volume: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_lookup_icon_name ##### --> -<para> - -</para> - -@volume: -@icon_theme: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_eject ##### --> -<para> - -</para> - -@volume: -@window: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_mount ##### --> -<para> - -</para> - -@volume: -@window: -@error: -@Returns: - - -<!-- ##### FUNCTION thunar_vfs_volume_unmount ##### --> -<para> - -</para> - -@volume: -@window: -@error: -@Returns: - - diff --git a/docs/reference/thunar-vfs/version.xml.in b/docs/reference/thunar-vfs/version.xml.in deleted file mode 100644 index a24f9877a..000000000 --- a/docs/reference/thunar-vfs/version.xml.in +++ /dev/null @@ -1 +0,0 @@ -@PACKAGE_VERSION@ diff --git a/docs/reference/thunarx/Makefile.am b/docs/reference/thunarx/Makefile.am index ab15bea58..92b1b0121 100644 --- a/docs/reference/thunarx/Makefile.am +++ b/docs/reference/thunarx/Makefile.am @@ -52,7 +52,7 @@ INCLUDES = \ $(GTK_CFLAGS) GTKDOC_LIBS = \ - $(top_builddir)/thunarx/libthunarx-$(THUNAR_VERSION_API).la + $(top_builddir)/thunarx/libthunarx-$(THUNARX_VERSION_API).la include $(top_srcdir)/gtk-doc.make diff --git a/docs/reference/thunarx/thunarx-docs.sgml b/docs/reference/thunarx/thunarx-docs.sgml index e8a8bb6c4..042f58ea3 100644 --- a/docs/reference/thunarx/thunarx-docs.sgml +++ b/docs/reference/thunarx/thunarx-docs.sgml @@ -208,8 +208,8 @@ <para> Providers are <link linkend="ThunarxProviderPlugin"><type>ThunarxProviderPlugin</type></link>s loaded from shared libraries - installed in <filename role="directory">$libdir/thunarx-1/</filename>. The shared libraries are linked against the - <systemitem class="library">thunarx-1</systemitem> library. + installed in <filename role="directory">$libdir/thunarx-2/</filename>. The shared libraries are linked against the + <systemitem class="library">thunarx-2</systemitem> library. </para> <para> @@ -317,13 +317,13 @@ thunar_extension_list_types (const GType **types, The following interactive shell session demonstrates how <literal>pkg-config</literal> is used (the actual output on your system will be different): <screen> -$ pkg-config --cflags thunarx-1 --DXTHREADS -DXUSE_MTSAFE_API -I/opt/local/include/thunarx-1 -I/usr/local/include/atk-1.0 \ +$ pkg-config --cflags thunarx-2 +-DXTHREADS -DXUSE_MTSAFE_API -I/opt/local/include/thunarx-2 -I/usr/local/include/atk-1.0 \ -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include -I/usr/X11R6/include/gtk-2.0 \ -I/usr/X11R6/lib/gtk-2.0/include -I/usr/X11R6/include -I/usr/X11R6/include/pango-1.0 \ -I/usr/local/include/freetype2 -I/usr/local/include -$ pkg-config --libs thunarx-1 --Wl,--rpath -Wl,/usr/local/lib -L/usr/local/lib -L/usr/X11R6/lib -L/opt/local/lib -lthunarx-1</screen> +$ pkg-config --libs thunarx-2 +-Wl,--rpath -Wl,/usr/local/lib -L/usr/local/lib -L/usr/X11R6/lib -L/opt/local/lib -lthunarx-2</screen> </para> <para> @@ -332,7 +332,7 @@ $ pkg-config --libs thunarx-1 quotes</emphasis>), then its output will be substituted into the command line before execution. So to compile an extension, you would type the following: <screen> -$ gcc -shared -fPIC -DPIC `pkg-config --cflags --libs thunarx-1` foo.c -o foo.so</screen> +$ gcc -shared -fPIC -DPIC `pkg-config --cflags --libs thunarx-2` foo.c -o foo.so</screen> </para> </sect2> @@ -344,16 +344,16 @@ $ gcc -shared -fPIC -DPIC `pkg-config --cflags --libs thunarx-1` foo.c -o foo.so you can use the following command (as mentioned above, the output will be different on your system): <screen> -$ pkg-config --variable=extensionsdir thunarx-1 -/opt/local/lib/thunarx-1</screen> +$ pkg-config --variable=extensionsdir thunarx-2 +/opt/local/lib/thunarx-2</screen> </para> <para> For example, to install the extension <filename>foo.so</filename> on your system, you would type the following: <screen> -$ install -d `pkg-config --variable=extensionsdir thunarx-1` -$ install -c -m 0755 foo.so `pkg-config --variable=extensionsdir thunarx-1`/foo.so</screen> +$ install -d `pkg-config --variable=extensionsdir thunarx-2` +$ install -c -m 0755 foo.so `pkg-config --variable=extensionsdir thunarx-2`/foo.so</screen> </para> </sect2> </sect1> diff --git a/docs/reference/thunarx/thunarx-sections.txt b/docs/reference/thunarx/thunarx-sections.txt index d03dc9054..85f33d9be 100644 --- a/docs/reference/thunarx/thunarx-sections.txt +++ b/docs/reference/thunarx/thunarx-sections.txt @@ -12,7 +12,9 @@ thunarx_file_info_get_uri_scheme thunarx_file_info_get_mime_type thunarx_file_info_has_mime_type thunarx_file_info_is_directory -thunarx_file_info_get_vfs_info +thunarx_file_info_get_file_info +thunarx_file_info_get_filesystem_info +thunarx_file_info_get_location thunarx_file_info_changed thunarx_file_info_renamed THUNARX_TYPE_FILE_INFO_LIST diff --git a/docs/reference/thunarx/tmpl/thunarx-file-info.sgml b/docs/reference/thunarx/tmpl/thunarx-file-info.sgml index e912baf8e..fb89ab9f9 100644 --- a/docs/reference/thunarx/tmpl/thunarx-file-info.sgml +++ b/docs/reference/thunarx/tmpl/thunarx-file-info.sgml @@ -31,7 +31,9 @@ Stable @get_mime_type: See thunarx_file_info_get_mime_type(). @has_mime_type: See thunarx_file_info_has_mime_type(). @is_directory: See thunarx_file_info_is_directory(). -@get_vfs_info: See thunarx_file_info_get_vfs_info(). +@get_file_info: See thunarx_file_info_get_file_info(). +@get_filesystem_info: See thunarx_filesystem_info_get_filesystem_info(). +@get_location: See thunarx_location_get_location(). @changed: See thunarx_file_info_changed(). @renamed: See thunarx_file_info_renamed(). @@ -120,7 +122,25 @@ Stable @Returns: -<!-- ##### FUNCTION thunarx_file_info_get_vfs_info ##### --> +<!-- ##### FUNCTION thunarx_file_info_get_file_info ##### --> +<para> + +</para> + +@file_info: +@Returns: + + +<!-- ##### FUNCTION thunarx_file_info_get_filesystem_info ##### --> +<para> + +</para> + +@file_info: +@Returns: + + +<!-- ##### FUNCTION thunarx_file_info_get_location ##### --> <para> </para> diff --git a/examples/tex-open-terminal/Makefile.am b/examples/tex-open-terminal/Makefile.am index 01ab1b00b..91679893d 100644 --- a/examples/tex-open-terminal/Makefile.am +++ b/examples/tex-open-terminal/Makefile.am @@ -7,7 +7,7 @@ INCLUDES = \ -DG_LOG_DOMAIN=\"TexOpenTerminal\" \ $(PLATFORM_CPPFLAGS) -extensionsdir = $(libdir)/thunarx-$(THUNAR_VERSION_API) +extensionsdir = $(libdir)/thunarx-$(THUNARX_VERSION_API) extensions_LTLIBRARIES = \ tex-open-terminal.la @@ -21,10 +21,10 @@ tex_open_terminal_la_CFLAGS = \ $(PLATFORM_CFLAGS) tex_open_terminal_la_DEPENDENCIES = \ - $(top_builddir)/thunarx/libthunarx-$(THUNAR_VERSION_API).la + $(top_builddir)/thunarx/libthunarx-$(THUNARX_VERSION_API).la tex_open_terminal_la_LIBADD = \ - $(top_builddir)/thunarx/libthunarx-$(THUNAR_VERSION_API).la \ + $(top_builddir)/thunarx/libthunarx-$(THUNARX_VERSION_API).la \ $(GTK_LIBS) tex_open_terminal_la_LDFLAGS = \ diff --git a/plugins/thunar-apr/Makefile.am b/plugins/thunar-apr/Makefile.am index 338c0c91c..29d0ead4d 100644 --- a/plugins/thunar-apr/Makefile.am +++ b/plugins/thunar-apr/Makefile.am @@ -9,7 +9,7 @@ INCLUDES = \ -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \ $(PLATFORM_CPPFLAGS) -extensionsdir = $(libdir)/thunarx-$(THUNAR_VERSION_API) +extensionsdir = $(libdir)/thunarx-$(THUNARX_VERSION_API) extensions_LTLIBRARIES = \ thunar-apr.la diff --git a/plugins/thunar-apr/README b/plugins/thunar-apr/README index 3d627b2b0..7ae42c127 100644 --- a/plugins/thunar-apr/README +++ b/plugins/thunar-apr/README @@ -24,6 +24,6 @@ shouldn't be a real problem unless you're targeting an embedded system), and so you can pass `--disable-apr-plugin' to configure and the plugin won't be built and installed. Since it is an extension, you can also easily uninstall it afterwards by removing the thunar-apr.so file from -the lib/thunarx-1/ directory of your installation (be sure to quit Thunar +the lib/thunarx-2/ directory of your installation (be sure to quit Thunar before removing files though). diff --git a/plugins/thunar-sbr/Makefile.am b/plugins/thunar-sbr/Makefile.am index 8ca7dabdd..1aabd4154 100644 --- a/plugins/thunar-sbr/Makefile.am +++ b/plugins/thunar-sbr/Makefile.am @@ -8,7 +8,7 @@ INCLUDES = \ -DG_LOG_DOMAIN=\"thunar-sbr\" \ $(PLATFORM_CPPFLAGS) -extensionsdir = $(libdir)/thunarx-$(THUNAR_VERSION_API) +extensionsdir = $(libdir)/thunarx-$(THUNARX_VERSION_API) extensions_LTLIBRARIES = \ thunar-sbr.la diff --git a/plugins/thunar-sbr/README b/plugins/thunar-sbr/README index 2e2e1ccd7..51f6e81c3 100644 --- a/plugins/thunar-sbr/README +++ b/plugins/thunar-sbr/README @@ -16,7 +16,7 @@ extension, it will slightly increase the resource usage of Thunar (this shouldn't be a real problem unless you're targeting an embedded system), and so you can pass `--disable-sbr-plugin' to configure and the plugin won't be built and installed. Since it is an extension, you can also easily uninstall it -afterwards by removing the thunar-sbr.so file from the lib/thunarx-1/ directory +afterwards by removing the thunar-sbr.so file from the lib/thunarx-2/ directory of your installation (be sure to quit Thunar before removing files though). diff --git a/plugins/thunar-sbr/thunar-sbr-date-renamer.c b/plugins/thunar-sbr/thunar-sbr-date-renamer.c index e976bff8f..688d105ef 100644 --- a/plugins/thunar-sbr/thunar-sbr-date-renamer.c +++ b/plugins/thunar-sbr/thunar-sbr-date-renamer.c @@ -2,6 +2,7 @@ /*- * Copyright (c) 2007 Nick Schermer <nick@xfce.org> * Copyright (c) 2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -36,7 +37,6 @@ #include <exo/exo.h> #include <thunar-sbr/thunar-sbr-date-renamer.h> -#include <thunar-vfs/thunar-vfs.h> #ifdef HAVE_EXIF #include <libexif/exif-data.h> @@ -56,28 +56,28 @@ enum -static void thunar_sbr_date_renamer_class_init (ThunarSbrDateRenamerClass *klass); -static void thunar_sbr_date_renamer_init (ThunarSbrDateRenamer *date_renamer); -static void thunar_sbr_date_renamer_finalize (GObject *object); -static void thunar_sbr_date_renamer_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void thunar_sbr_date_renamer_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static gchar *thunar_sbr_get_time_string (ThunarVfsFileTime file_time, - const gchar *custom_format); +static void thunar_sbr_date_renamer_class_init (ThunarSbrDateRenamerClass *klass); +static void thunar_sbr_date_renamer_init (ThunarSbrDateRenamer *date_renamer); +static void thunar_sbr_date_renamer_finalize (GObject *object); +static void thunar_sbr_date_renamer_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void thunar_sbr_date_renamer_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static gchar *thunar_sbr_get_time_string (guint64 file_time, + const gchar *custom_format); #ifdef HAVE_EXIF -static ThunarVfsFileTime thunar_sbr_get_time_from_string (const gchar *string); +static guint64 thunar_sbr_get_time_from_string (const gchar *string); #endif -static ThunarVfsFileTime thunar_sbr_get_time (ThunarxFileInfo *file, - ThunarSbrDateMode mode); -static gchar *thunar_sbr_date_renamer_process (ThunarxRenamer *renamer, - ThunarxFileInfo *file, - const gchar *text, - guint index); +static guint64 thunar_sbr_get_time (ThunarxFileInfo *file, + ThunarSbrDateMode mode); +static gchar *thunar_sbr_date_renamer_process (ThunarxRenamer *renamer, + ThunarxFileInfo *file, + const gchar *text, + guint index); @@ -362,16 +362,19 @@ thunar_sbr_date_renamer_set_property (GObject *object, static gchar * -thunar_sbr_get_time_string (ThunarVfsFileTime file_time, - const gchar *format) +thunar_sbr_get_time_string (guint64 file_time, + const gchar *format) { struct tm *tm; + time_t time; gchar *converted; gchar buffer[1024]; gint length; + time = (time_t) file_time; + /* determine the local file time */ - tm = localtime (&file_time); + tm = localtime (&time); /* conver the format to the current locale */ converted = g_locale_from_utf8 (format, -1, NULL, NULL, NULL); @@ -393,7 +396,7 @@ thunar_sbr_get_time_string (ThunarVfsFileTime file_time, #ifdef HAVE_EXIF -static ThunarVfsFileTime +static guint64 thunar_sbr_get_time_from_string (const gchar *string) { struct tm tm; @@ -435,18 +438,18 @@ thunar_sbr_get_time_from_string (const gchar *string) -static ThunarVfsFileTime +static guint64 thunar_sbr_get_time (ThunarxFileInfo *file, ThunarSbrDateMode mode) { - ThunarVfsInfo *vfs_info; - ThunarVfsFileTime file_time = 0; + GFileInfo *file_info; + guint64 file_time = 0; #ifdef HAVE_EXIF - gchar *uri, *filename; - ExifEntry *exif_entry; - ExifData *exif_data; - gchar exif_buffer[128]; + gchar *uri, *filename; + ExifEntry *exif_entry; + ExifData *exif_data; + gchar exif_buffer[128]; #endif switch (mode) @@ -458,17 +461,23 @@ thunar_sbr_get_time (ThunarxFileInfo *file, case THUNAR_SBR_DATE_MODE_ATIME: case THUNAR_SBR_DATE_MODE_MTIME: - /* get the vfs info */ - vfs_info = thunarx_file_info_get_vfs_info (file); + /* get the file info */ + file_info = thunarx_file_info_get_file_info (file); /* get the time from the info */ if (mode == THUNAR_SBR_DATE_MODE_ATIME) - file_time = vfs_info->atime; + { + file_time = g_file_info_get_attribute_uint64 (file_info, + G_FILE_ATTRIBUTE_TIME_ACCESS); + } else - file_time = vfs_info->mtime; + { + file_time = g_file_info_get_attribute_uint64 (file_info, + G_FILE_ATTRIBUTE_TIME_MODIFIED); + } - /* release the vfs info */ - thunar_vfs_info_unref (vfs_info); + /* release the file info */ + g_object_unref (file_info); break; #ifdef HAVE_EXIF @@ -530,7 +539,7 @@ thunar_sbr_date_renamer_process (ThunarxRenamer *renamer, { ThunarSbrDateRenamer *date_renamer = THUNAR_SBR_DATE_RENAMER (renamer); gchar *string; - ThunarVfsFileTime file_time; + guint64 file_time; const gchar *s; GString *result; guint text_length; diff --git a/plugins/thunar-sendto-email/Makefile.am b/plugins/thunar-sendto-email/Makefile.am index fb9f67e6b..ac66591f3 100644 --- a/plugins/thunar-sendto-email/Makefile.am +++ b/plugins/thunar-sendto-email/Makefile.am @@ -19,11 +19,7 @@ thunar_sendto_email_CFLAGS = \ $(EXO_CFLAGS) \ $(PLATFORM_CFLAGS) -thunar_sendto_email_DEPENDENCIES = \ - $(top_builddir)/thunar-vfs/libthunar-vfs-$(THUNAR_VERSION_API).la - thunar_sendto_email_LDADD = \ - $(top_builddir)/thunar-vfs/libthunar-vfs-$(THUNAR_VERSION_API).la \ $(EXO_LIBS) \ $(PLATFORM_LDFLAGS) diff --git a/plugins/thunar-sendto-email/main.c b/plugins/thunar-sendto-email/main.c index 077a041ed..8edef40c7 100644 --- a/plugins/thunar-sendto-email/main.c +++ b/plugins/thunar-sendto-email/main.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -53,9 +54,23 @@ #include <unistd.h> #endif +#include <glib.h> #include <glib/gstdio.h> +#include <gio/gio.h> -#include <thunar-vfs/thunar-vfs.h> +#include <gtk/gtk.h> + +#include <exo/exo.h> + + + +typedef struct _TseData TseData; + +struct _TseData +{ + GFileInfo *info; + GFile *file; +}; @@ -129,28 +144,33 @@ tse_error (GError *error, static gint tse_ask_compress (GList *infos) { - ThunarVfsFileSize total_size = 0; - ThunarVfsInfo *info; - GtkWidget *message; - GList *lp; - gint response = TSE_RESPONSE_PLAIN; - gint n_archives = 0; - gint n_infos = 0; - guint n; + const gchar *content_type; + TseData *tse_data; + GtkWidget *message; + guint64 total_size = 0; + GList *lp; + gint response = TSE_RESPONSE_PLAIN; + gint n_archives = 0; + gint n_infos = 0; + guint n; /* check the file infos */ for (lp = infos; lp != NULL; lp = lp->next, ++n_infos) { /* need to compress if we have any directories */ - info = (ThunarVfsInfo *) lp->data; - if (info->type == THUNAR_VFS_FILE_TYPE_DIRECTORY) + tse_data = (TseData *) lp->data; + + if (g_file_info_get_file_type (tse_data->info) == G_FILE_TYPE_DIRECTORY) return TSE_RESPONSE_COMPRESS; /* check if the single file is already an archive */ for (n = 0; n < G_N_ELEMENTS (TSE_MIME_TYPES); ++n) { + /* determine the content type */ + content_type = g_file_info_get_content_type (tse_data->info); + /* check if this mime type matches */ - if (strcmp (thunar_vfs_mime_info_get_name (info->mime_info), TSE_MIME_TYPES[n]) == 0) + if (content_type != NULL && g_content_type_is_a (content_type, TSE_MIME_TYPES[n])) { /* yep, that's a match then */ ++n_archives; @@ -159,7 +179,7 @@ tse_ask_compress (GList *infos) } /* add file size to total */ - total_size += info->size; + total_size += g_file_info_get_size (tse_data->info); } /* check if the total size is larger than 200KiB, or we have more than @@ -171,9 +191,10 @@ tse_ask_compress (GList *infos) if (G_LIKELY (n_infos == 1)) { /* ask the user whether to compress the file */ - info = (ThunarVfsInfo *) infos->data; + tse_data = (TseData *) infos->data; message = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, - _("Send \"%s\" as compressed archive?"), info->display_name); + _("Send \"%s\" as compressed archive?"), + g_file_info_get_display_name (tse_data->info)); gtk_dialog_add_button (GTK_DIALOG (message), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button (GTK_DIALOG (message), _("Send _directly"), TSE_RESPONSE_PLAIN); gtk_dialog_add_button (GTK_DIALOG (message), _("Send com_pressed"), TSE_RESPONSE_COMPRESS); @@ -363,11 +384,13 @@ static gboolean tse_compress (GList *infos, gchar **zipfile_return) { - ThunarVfsPath *parent; - ThunarVfsInfo *info; + TseData *tse_data; gboolean succeed = TRUE; GError *error = NULL; + GFile *parent; + GFile *parent_parent; gchar **argv; + gchar *basename; gchar *zipfile; gchar *tmppath; gchar *tmpdir; @@ -391,8 +414,8 @@ tse_compress (GList *infos, if (G_LIKELY (infos != NULL && infos->next == NULL)) { /* determine the name for the ZIP file */ - info = (ThunarVfsInfo *) infos->data; - path = g_strdup (info->display_name); + tse_data = (TseData *) infos->data; + path = g_strdup (g_file_info_get_display_name (tse_data->info)); dot = strrchr (path, '.'); if (G_LIKELY (dot != NULL)) *dot = '\0'; @@ -402,18 +425,31 @@ tse_compress (GList *infos, else { /* determine the name for the ZIP file */ - info = (ThunarVfsInfo *) infos->data; - parent = thunar_vfs_path_get_parent (info->path); - if (!thunar_vfs_path_is_root (parent)) + tse_data = (TseData *) infos->data; + parent = g_file_get_parent (tse_data->file); + + /* we assume the parent exists because we only allow non-root + * files as TseData in main () */ + g_assert (parent != NULL); + + parent_parent = g_file_get_parent (parent); + + if (parent_parent != NULL) { /* use the parent directory's name */ - zipfile = g_strconcat (tmpdir, G_DIR_SEPARATOR_S, thunar_vfs_path_get_name (parent), ".zip", NULL); + basename = g_file_get_basename (parent); + zipfile = g_strconcat (tmpdir, G_DIR_SEPARATOR_S, basename, ".zip", NULL); + g_free (basename); + + g_object_unref (parent_parent); } else { /* use the first file's name */ - zipfile = g_strconcat (tmpdir, G_DIR_SEPARATOR_S, info->display_name, ".zip", NULL); + zipfile = g_strconcat (tmpdir, G_DIR_SEPARATOR_S, g_file_info_get_display_name (tse_data->info), ".zip", NULL); } + + g_object_unref (parent); } /* generate the argument list for the ZIP command */ @@ -425,24 +461,34 @@ tse_compress (GList *infos, for (lp = infos, n = 4; lp != NULL && succeed; lp = lp->next, ++n) { /* create a symlink for the file to the tmp dir */ - info = (ThunarVfsInfo *) lp->data; - path = thunar_vfs_path_dup_string (info->path); - tmppath = g_build_filename (tmpdir, thunar_vfs_path_get_name (info->path), NULL); - succeed = (symlink (path, tmppath) == 0); - if (G_UNLIKELY (!succeed)) + tse_data = (TseData *) lp->data; + path = g_file_get_path (tse_data->file); + + if (path == NULL) { - /* tell the user that we failed to create a symlink for this file */ - error = g_error_new_literal (G_FILE_ERROR, g_file_error_from_errno (errno), g_strerror (errno)); - tse_error (error, _("Failed to create symbolic link for \"%s\""), info->display_name); + error = g_error_new_literal (G_FILE_ERROR, g_file_error_from_errno (ENOTSUP), g_strerror (errno)); + tse_error (error, _("Failed to create symbolic link for \"%s\""), g_file_info_get_display_name (tse_data->info)); g_error_free (error); } else { - /* add the file to the ZIP command line */ - argv[n] = g_path_get_basename (tmppath); + tmppath = g_build_filename (tmpdir, g_file_get_basename (tse_data->file), NULL); + succeed = (symlink (path, tmppath) == 0); + if (G_UNLIKELY (!succeed)) + { + /* tell the user that we failed to create a symlink for this file */ + error = g_error_new_literal (G_FILE_ERROR, g_file_error_from_errno (errno), g_strerror (errno)); + tse_error (error, _("Failed to create symbolic link for \"%s\""), g_file_info_get_display_name (tse_data->info)); + g_error_free (error); + } + else + { + /* add the file to the ZIP command line */ + argv[n] = g_path_get_basename (tmppath); + } + g_free (tmppath); + g_free (path); } - g_free (tmppath); - g_free (path); } /* check if we succeed up to this point */ @@ -489,8 +535,10 @@ tse_compress (GList *infos, int main (int argc, char **argv) { - ThunarVfsInfo *info; - ThunarVfsPath *path; + GFileInfo *info; + TseData *tse_data; + GFile *file; + GFile *parent; GString *mailto; GError *error = NULL; GList *infos = NULL; @@ -513,9 +561,6 @@ main (int argc, char **argv) /* initialize Gtk+ */ gtk_init (&argc, &argv); - /* initialize the ThunarVFS library */ - thunar_vfs_init (); - /* set default icon for dialogs */ gtk_window_set_default_icon_name ("internet-mail"); @@ -526,38 +571,49 @@ main (int argc, char **argv) return EXIT_FAILURE; } - /* determine the ThunarVfsInfos for the files */ + /* determine the GFiles and GFileInfos (bundled as TseData) for the files */ for (n = 1; n < argc; ++n) { - /* try to transform to a ThunarVfsPath */ - path = thunar_vfs_path_new (argv[n], &error); - if (G_UNLIKELY (path == NULL)) + /* try to transform to a GFile */ + file = g_file_new_for_commandline_arg (argv[n]); + + /* verify that we're not trying to send root */ + parent = g_file_get_parent (file); + if (parent == NULL) { -invalid_argument: + error = g_error_new_literal (G_FILE_ERROR, g_file_error_from_errno (EFBIG), g_strerror (EFBIG)); g_fprintf (stderr, "thunar-sendto-email: Invalid argument \"%s\": %s\n", argv[n], error->message); - thunar_vfs_info_list_free (infos); g_error_free (error); + g_object_unref (file); return EXIT_FAILURE; } - - /* verify that we're not trying to send root */ - if (thunar_vfs_path_is_root (path)) + else { - error = g_error_new_literal (G_FILE_ERROR, g_file_error_from_errno (EFBIG), g_strerror (EFBIG)); - thunar_vfs_path_unref (path); - goto invalid_argument; + g_object_unref (parent); } /* try to determine the info */ - info = thunar_vfs_info_new_for_path (path, &error); - thunar_vfs_path_unref (path); + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," + G_FILE_ATTRIBUTE_STANDARD_SIZE "," + G_FILE_ATTRIBUTE_STANDARD_TYPE, + G_FILE_QUERY_INFO_NONE, NULL, &error); /* check if we failed */ if (G_UNLIKELY (info == NULL)) - goto invalid_argument; + { + g_fprintf (stderr, "thunar-sendto-email: Invalid argument \"%s\": %s\n", argv[n], error->message); + g_error_free (error); + g_object_unref (file); + return EXIT_FAILURE; + } + + tse_data = g_slice_new0 (TseData); + tse_data->info = info; + tse_data->file = file; /* add to our list of infos */ - infos = g_list_append (infos, info); + infos = g_list_append (infos, tse_data); } /* check whether to compress the files */ @@ -579,8 +635,8 @@ invalid_argument: attachments = g_new0 (gchar *, g_list_length (infos) + 1); for (lp = infos, n = 0; lp != NULL; lp = lp->next, ++n) { - info = (ThunarVfsInfo *) lp->data; - attachments[n] = thunar_vfs_path_dup_uri (info->path); + tse_data = (TseData *) lp->data; + attachments[n] = g_file_get_uri (tse_data->file); } } @@ -606,10 +662,14 @@ invalid_argument: } /* cleanup */ - thunar_vfs_info_list_free (infos); - - /* shutdown the ThunarVFS library */ - thunar_vfs_shutdown (); + for (lp = infos; lp != NULL; lp = lp->next) + { + tse_data = (TseData *) lp->data; + g_object_unref (tse_data->file); + g_object_unref (tse_data->info); + g_slice_free (TseData, tse_data); + } + g_list_free (infos); return EXIT_SUCCESS; } diff --git a/plugins/thunar-uca/Makefile.am b/plugins/thunar-uca/Makefile.am index 3be34d045..be5986587 100644 --- a/plugins/thunar-uca/Makefile.am +++ b/plugins/thunar-uca/Makefile.am @@ -11,7 +11,7 @@ INCLUDES = \ -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \ $(PLATFORM_CPPFLAGS) -extensionsdir = $(libdir)/thunarx-$(THUNAR_VERSION_API) +extensionsdir = $(libdir)/thunarx-$(THUNARX_VERSION_API) extensions_LTLIBRARIES = \ thunar-uca.la @@ -32,6 +32,7 @@ thunar_uca_la_SOURCES = \ thunar_uca_la_CFLAGS = \ $(EXO_CFLAGS) \ + $(LIBXFCE4UTIL_CFLAGS) \ $(PLATFORM_CFLAGS) thunar_uca_la_LDFLAGS = \ diff --git a/plugins/thunar-uca/README b/plugins/thunar-uca/README index 6494c599f..9a3fda9b8 100644 --- a/plugins/thunar-uca/README +++ b/plugins/thunar-uca/README @@ -10,7 +10,7 @@ extension, it will slightly increase the resource usage of Thunar (this shouldn't be a real problem unless you're targeting an embedded system), and so can you pass `--disable-uca-plugin' to configure and the plugin won't be built and installed. Since it is an extension, you can also easily uninstall it -afterwards by removing the thunar-uca.so file from the lib/thunarx-1/ directory +afterwards by removing the thunar-uca.so file from the lib/thunarx-2/ directory of your installation (be sure to quit Thunar before removing files though). To actually manage the actions open the "Edit" menu in the menu bar of a diff --git a/plugins/thunar-uca/thunar-uca-model.c b/plugins/thunar-uca/thunar-uca-model.c index e8e136ba5..0eaaa3a32 100644 --- a/plugins/thunar-uca/thunar-uca-model.c +++ b/plugins/thunar-uca/thunar-uca-model.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -44,8 +45,13 @@ #include <glib/gi18n-lib.h> #include <glib/gstdio.h> +#include <gio/gio.h> + +#include <gtk/gtk.h> + +#include <libxfce4util/libxfce4util.h> + #include <thunar-uca/thunar-uca-model.h> -#include <thunar-vfs/thunar-vfs.h> @@ -1021,17 +1027,16 @@ thunar_uca_model_match (ThunarUcaModel *uca_model, ThunarUcaTypes types; } ThunarUcaFile; - ThunarVfsMimeDatabase *mime_database; - ThunarUcaModelItem *item; - ThunarUcaFile *files; - ThunarVfsInfo *info; - const gchar *mime_type; - gboolean matches; - GList *mime_infos; - GList *paths = NULL; - GList *lp, *mp; - gint n_files; - gint i, m, n; + ThunarUcaModelItem *item; + ThunarUcaFile *files; + GFileInfo *info; + GFile *location; + const gchar *mime_type; + gboolean matches; + GList *paths = NULL; + GList *lp; + gint n_files; + gint i, m, n; g_return_val_if_fail (THUNAR_UCA_IS_MODEL (uca_model), NULL); @@ -1044,33 +1049,29 @@ thunar_uca_model_match (ThunarUcaModel *uca_model, files = g_new (ThunarUcaFile, n_files); for (lp = file_infos, n = 0; lp != NULL; lp = lp->next, ++n) { - info = thunarx_file_info_get_vfs_info (lp->data); - if (thunar_vfs_path_get_scheme (info->path) != THUNAR_VFS_PATH_SCHEME_FILE) + location = thunarx_file_info_get_location (lp->data); + + if (!g_file_has_uri_scheme (location, "file")) { /* cannot handle non-local files */ - thunar_vfs_info_unref (info); + g_object_unref (location); g_free (files); return NULL; } - mime_type = thunar_vfs_mime_info_get_name (info->mime_info); - files[n].name = thunar_vfs_path_get_name (info->path); + + g_object_unref (location); + + info = thunarx_file_info_get_file_info (lp->data); + + mime_type = g_file_info_get_content_type (info); + + files[n].name = g_file_info_get_name (info); files[n].types = types_from_mime_type (mime_type); - if (G_UNLIKELY (files[n].types == 0)) - { - mime_database = thunar_vfs_mime_database_get_default (); - mime_infos = thunar_vfs_mime_database_get_infos_for_info (mime_database, info->mime_info); - for (mp = mime_infos; mp != NULL; mp = mp->next) - { - mime_type = thunar_vfs_mime_info_get_name (mp->data); - files[n].types |= types_from_mime_type (mime_type); - thunar_vfs_mime_info_unref (mp->data); - } - g_object_unref (G_OBJECT (mime_database)); - g_list_free (mime_infos); - } + if (G_UNLIKELY (files[n].types == 0)) files[n].types = THUNAR_UCA_TYPE_OTHER_FILES; - thunar_vfs_info_unref (info); + + g_object_unref (info); } /* lookup the matching items */ diff --git a/plugins/thunar-uca/thunar-uca-provider.c b/plugins/thunar-uca/thunar-uca-provider.c index 1e6e11910..217e5531b 100644 --- a/plugins/thunar-uca/thunar-uca-provider.c +++ b/plugins/thunar-uca/thunar-uca-provider.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,7 +23,8 @@ #include <config.h> #endif -#include <thunar-vfs/thunar-vfs.h> +#include <glib/gi18n.h> +#include <gio/gio.h> #include <thunar-uca/thunar-uca-chooser.h> #include <thunar-uca/thunar-uca-context.h> @@ -420,26 +422,29 @@ thunar_uca_provider_child_watch (GPid pid, gpointer user_data) { ThunarUcaProvider *uca_provider = THUNAR_UCA_PROVIDER (user_data); - ThunarVfsMonitor *monitor; - ThunarVfsPath *path; + GFileMonitor *monitor; + GError *error = NULL; + GFile *file; GDK_THREADS_ENTER (); /* verify that we still have a valid child_watch_path */ if (G_LIKELY (uca_provider->child_watch_path != NULL)) { - /* determine the corresponding ThunarVfsPath */ - path = thunar_vfs_path_new (uca_provider->child_watch_path, NULL); - if (G_LIKELY (path != NULL)) - { - /* schedule a changed notification on the path */ - monitor = thunar_vfs_monitor_get_default (); - thunar_vfs_monitor_feed (monitor, THUNAR_VFS_MONITOR_EVENT_CHANGED, path); - g_object_unref (G_OBJECT (monitor)); + /* determine the corresponding file */ + file = g_file_new_for_path (uca_provider->child_watch_path); + + /* schedule a changed notification on the path */ + monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, &error); - /* release the ThunarVfsPath */ - thunar_vfs_path_unref (path); + if (monitor != NULL) + { + g_file_monitor_emit_event (monitor, file, file, G_FILE_MONITOR_EVENT_CHANGED); + g_object_unref (monitor); } + + /* release the file */ + g_object_unref (file); } /* need to cleanup */ diff --git a/plugins/thunar-wallpaper/Makefile.am b/plugins/thunar-wallpaper/Makefile.am index 573a8fd57..03d8f5ef4 100644 --- a/plugins/thunar-wallpaper/Makefile.am +++ b/plugins/thunar-wallpaper/Makefile.am @@ -7,7 +7,7 @@ INCLUDES = \ -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \ $(PLATFORM_CPPFLAGS) -extensionsdir = $(libdir)/thunarx-1 +extensionsdir = $(libdir)/thunarx-$(THUNARX_VERSION_API) extensions_LTLIBRARIES = \ thunar-wallpaper-plugin.la @@ -19,13 +19,11 @@ thunar_wallpaper_plugin_la_SOURCES = \ thunar_wallpaper_plugin_la_CFLAGS = \ $(PLATFORM_CFLAGS) \ $(THUNARX_CFLAGS) \ - $(EXO_CFLAGS) \ - $(THUNAR_VFS_CFLAGS) + $(EXO_CFLAGS) thunar_wallpaper_plugin_la_LDFLAGS = \ -avoid-version \ -export-dynamic \ -module \ $(PLATFORM_LDFLAGS) \ - $(THUNARX_LDFLAGS) \ - $(THUNAR_VFS_LDFLAGS) + $(THUNARX_LDFLAGS) diff --git a/plugins/thunar-wallpaper/twp-provider.c b/plugins/thunar-wallpaper/twp-provider.c index 0d4038ea4..f510b380d 100644 --- a/plugins/thunar-wallpaper/twp-provider.c +++ b/plugins/thunar-wallpaper/twp-provider.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2008 Stephan Arts <stephan@xfce.org> * Copyright (c) 2008-2009 Mike Massonnet <mmassonnet@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,10 +23,13 @@ #include <config.h> #endif -#include <thunar-vfs/thunar-vfs.h> +#include <gio/gio.h> + #include <gdk/gdkx.h> #include <X11/Xlib.h> +#include <glib/gi18n.h> + #include "twp-provider.h" @@ -116,14 +120,12 @@ twp_provider_get_file_actions (ThunarxMenuProvider *menu_provider, GtkWidget *window, GList *files) { - Atom xfce_selection_atom; - Atom nautilus_selection_atom; - - ThunarVfsPathScheme scheme; - ThunarVfsInfo *info; - GtkWidget *action = NULL; - GList *actions = NULL; - gchar selection_name[100]; + GtkWidget *action = NULL; + GFile *location; + GList *actions = NULL; + gchar selection_name[100]; + Atom xfce_selection_atom; + Atom nautilus_selection_atom; GdkScreen *gdk_screen = gdk_screen_get_default(); gint xscreen = gdk_screen_get_number(gdk_screen); @@ -133,14 +135,18 @@ twp_provider_get_file_actions (ThunarxMenuProvider *menu_provider, /* we can only set a single wallpaper */ if (files->next == NULL) { - /* check if the file is a local file */ - info = thunarx_file_info_get_vfs_info (files->data); - scheme = thunar_vfs_path_get_scheme (info->path); - thunar_vfs_info_unref (info); + /* get the location of the file */ + location = thunarx_file_info_get_location (files->data); /* unable to handle non-local files */ - if (G_UNLIKELY (scheme != THUNAR_VFS_PATH_SCHEME_FILE)) + if (G_UNLIKELY (!g_file_has_uri_scheme (location, "file"))) + { + g_object_unref (location); return NULL; + } + + /* release the location */ + g_object_unref (location); if (!thunarx_file_info_is_directory (files->data)) { diff --git a/po-doc/LINGUAS b/po-doc/LINGUAS deleted file mode 100644 index 44cba667a..000000000 --- a/po-doc/LINGUAS +++ /dev/null @@ -1,2 +0,0 @@ -# Set of languages supported -da es eu fr gl it ja nl pl ru tr zh_TW diff --git a/po-doc/Makefile.am b/po-doc/Makefile.am index 3af8e5f84..8a2eacb52 100644 --- a/po-doc/Makefile.am +++ b/po-doc/Makefile.am @@ -54,6 +54,7 @@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ docdir = $(top_srcdir)/docs/manual +langs=`cd $(srcdir) && ls *.po 2>/dev/null | sed 's/\(.*\)\.po/\1/'` if ENABLE_XML2PO all-local: $(PACKAGE).pot @@ -63,14 +64,12 @@ $(PACKAGE).pot: $(docdir)/C/$(PACKAGE).xml.in update-po: Makefile $(PACKAGE).pot @echo "*** Updating PO ***" - langs=`sed -e '/^#/d' $(srcdir)/LINGUAS`; \ for lang in $$langs; do \ $(XML2PO) -u $$lang.po $(docdir)/C/$(PACKAGE).xml.in; \ done update-xml: Makefile $(PACKAGE).pot @echo "*** Updating XML ***" - langs=`sed -e '/^#/d' $(srcdir)/LINGUAS`; \ for lang in $$langs; do \ if test -n $(docdir)/$$lang; then \ mkdir -p $(docdir)/$$lang; \ diff --git a/po/LINGUAS b/po/LINGUAS deleted file mode 100644 index a972ca84b..000000000 --- a/po/LINGUAS +++ /dev/null @@ -1,2 +0,0 @@ -# set of available languages (in alphabetic order) -ar ast be ca cs da de dz el en_GB eo es et eu fi fr gl he hu id it ja ka ko ku lt lv mk nb nl nn pa pl pt pt_BR ro ru sk sq sv tr uk ur ur_PK vi zh_CN zh_TW diff --git a/po/POTFILES.in b/po/POTFILES.in index c6efd61e6..8b4321212 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,48 +1,9 @@ -thunar-vfs/thunar-vfs-config.c -thunar-vfs/thunar-vfs-deep-count-job.c -thunar-vfs/thunar-vfs-exec.c -thunar-vfs/thunar-vfs-info.c -thunar-vfs/thunar-vfs-interactive-job.c -thunar-vfs/thunar-vfs-io-jobs.c -thunar-vfs/thunar-vfs-io-local-xfer.c -thunar-vfs/thunar-vfs-io-local.c -thunar-vfs/thunar-vfs-io-ops.c -thunar-vfs/thunar-vfs-io-scandir.c -thunar-vfs/thunar-vfs-io-trash.c -thunar-vfs/thunar-vfs-job.c -thunar-vfs/thunar-vfs-mime-action.c -thunar-vfs/thunar-vfs-mime-application.c -thunar-vfs/thunar-vfs-mime-cache.c -thunar-vfs/thunar-vfs-mime-cleaner.c -thunar-vfs/thunar-vfs-mime-database.c -thunar-vfs/thunar-vfs-mime-handler.c -thunar-vfs/thunar-vfs-mime-info.c -thunar-vfs/thunar-vfs-mime-legacy.c -thunar-vfs/thunar-vfs-mime-parser.c -thunar-vfs/thunar-vfs-mime-provider.c -thunar-vfs/thunar-vfs-mime-sniffer.c -thunar-vfs/thunar-vfs-monitor.c -thunar-vfs/thunar-vfs-os-bsd.c -thunar-vfs/thunar-vfs-os-generic.c -thunar-vfs/thunar-vfs-path.c -thunar-vfs/thunar-vfs-private.c -thunar-vfs/thunar-vfs-simple-job.c -thunar-vfs/thunar-vfs-thumb-jpeg.c -thunar-vfs/thunar-vfs-thumb.c -thunar-vfs/thunar-vfs-transfer-job.c -thunar-vfs/thunar-vfs-user.c -thunar-vfs/thunar-vfs-util.c -thunar-vfs/thunar-vfs-volume-freebsd.c -thunar-vfs/thunar-vfs-volume-hal.c -thunar-vfs/thunar-vfs-volume-manager.c -thunar-vfs/thunar-vfs-volume-none.c -thunar-vfs/thunar-vfs-volume.c -thunar-vfs/thunar-vfs.c - thunar/main.c +thunar/sexy-url-label.c thunar/thunar-abstract-dialog.c thunar/thunar-abstract-icon-view.c thunar/thunar-application.c +thunar/thunar-browser.c thunar/thunar-chooser-button.c thunar/thunar-chooser-dialog.c thunar/thunar-chooser-model.c @@ -55,15 +16,18 @@ thunar/thunar-create-dialog.c thunar/thunar-dbus-client.c thunar/thunar-dbus-service.c thunar/thunar-debug.c +thunar/thunar-deep-count-job.c thunar/thunar-details-view.c thunar/thunar-dialogs.c thunar/thunar-dnd.c thunar/thunar-emblem-chooser.c thunar/thunar-enum-types.c -thunar/thunar-file-monitor.c +thunar/thunar-exec.c thunar/thunar-file.c +thunar/thunar-file-monitor.c thunar/thunar-folder.c thunar/thunar-gdk-extensions.c +thunar/thunar-gio-extensions.c thunar/thunar-gobject-extensions.c thunar/thunar-gtk-extensions.c thunar/thunar-history-action.c @@ -72,6 +36,11 @@ thunar/thunar-ice.c thunar/thunar-icon-factory.c thunar/thunar-icon-renderer.c thunar/thunar-icon-view.c +thunar/thunar-image.c +thunar/thunar-io-jobs.c +thunar/thunar-io-jobs-util.c +thunar/thunar-io-scan-directory.c +thunar/thunar-job.c thunar/thunar-launcher.c thunar/thunar-list-model.c thunar/thunar-location-bar.c @@ -79,13 +48,15 @@ thunar/thunar-location-button.c thunar/thunar-location-buttons.c thunar/thunar-location-dialog.c thunar/thunar-location-entry.c +thunar/thunar-marshal.c thunar/thunar-metafile.c +thunar/thunar-misc-jobs.c thunar/thunar-navigator.c thunar/thunar-pango-extensions.c thunar/thunar-path-entry.c thunar/thunar-permissions-chooser.c -thunar/thunar-preferences-dialog.c thunar/thunar-preferences.c +thunar/thunar-preferences-dialog.c thunar/thunar-progress-dialog.c thunar/thunar-properties-dialog.c thunar/thunar-renamer-dialog.c @@ -94,12 +65,12 @@ thunar/thunar-renamer-pair.c thunar/thunar-renamer-progress.c thunar/thunar-sendto-model.c thunar/thunar-session-client.c -thunar/thunar-settings.desktop.in thunar/thunar-shortcuts-icon-renderer.c thunar/thunar-shortcuts-model.c thunar/thunar-shortcuts-pane.c thunar/thunar-shortcuts-view.c thunar/thunar-side-pane.c +thunar/thunar-simple-job.c thunar/thunar-size-label.c thunar/thunar-standard-view.c thunar/thunar-statusbar.c @@ -107,14 +78,20 @@ thunar/thunar-stock.c thunar/thunar-templates-action.c thunar/thunar-text-renderer.c thunar/thunar-throbber.c -thunar/thunar-thumbnail-generator.c +thunar/thunar-throbber-fallback.c +thunar/thunar-thumbnailer.c +thunar/thunar-thumbnail-frame.c +thunar/thunar-transfer-job.c thunar/thunar-trash-action.c thunar/thunar-tree-model.c thunar/thunar-tree-pane.c thunar/thunar-tree-view.c +thunar/thunar-user.c thunar/thunar-util.c thunar/thunar-view.c thunar/thunar-window.c +thunar/xfce-heading.c +thunar/xfce-titled-dialog.c thunarx/thunarx-property-page.c thunarx/thunarx-provider-plugin.c @@ -156,3 +133,4 @@ plugins/thunar-wallpaper/twp-provider.c Thunar.desktop.in.in Thunar-bulk-rename.desktop.in.in Thunar-folder-handler.desktop.in.in +thunar/thunar-settings.desktop.in diff --git a/po/Thunar.pot b/po/Thunar.pot index 7573d71e6..6f1475ec5 100644 --- a/po/Thunar.pot +++ b/po/Thunar.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2009-01-11 00:20+0100\n" +"POT-Creation-Date: 2009-08-21 05:03+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,420 +17,60 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -#. base directory not readable -#: ../thunar-vfs/thunar-vfs-deep-count-job.c:233 -#, c-format -msgid "Failed to read folder contents" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-exec.c:590 -#, c-format -msgid "Unknown error" -msgstr "" - -#. TRANSLATORS: `Exec' is a field name in a .desktop file. You should leave it as-is. -#: ../thunar-vfs/thunar-vfs-info.c:390 -#, c-format -msgid "No Exec field specified" -msgstr "" - -#. TRANSLATORS: `URL' is a field name in a .desktop file. You should leave it as-is. -#: ../thunar-vfs/thunar-vfs-info.c:409 -#, c-format -msgid "No URL field specified" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-info.c:414 ../thunar-vfs/thunar-vfs-private.c:384 -#, c-format -msgid "Invalid desktop file" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-info.c:422 -#, c-format -msgid "Failed to parse file" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-info.c:503 -#, c-format -msgid "Invalid file name" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-info.c:510 -#, c-format -msgid "Only local files may be renamed" -msgstr "" - -#. tell the user that we're preparing to unlink the files -#: ../thunar-vfs/thunar-vfs-io-jobs.c:81 -msgid "Preparing..." -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-jobs.c:228 -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:542 -#, c-format -msgid "Failed to change permissions of \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-jobs.c:355 -#, c-format -msgid "Failed to change file owner of \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-jobs.c:356 -#, c-format -msgid "Failed to change file group of \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-jobs.c:444 -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:190 -#, c-format -msgid "The file \"%s\" already exists" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-jobs.c:462 -#, c-format -msgid "Failed to create empty file \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:165 -#, c-format -msgid "Failed to open \"%s\" for reading" -msgstr "" - -#. use the generic error message -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:196 -#: ../thunar-vfs/thunar-vfs-io-trash.c:804 -#, c-format -msgid "Failed to open \"%s\" for writing" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:223 -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:291 -#, c-format -msgid "Failed to write data to \"%s\"" -msgstr "" - -#. display an error to the user -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:239 -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:307 -#: ../thunar-vfs/thunar-vfs-io-ops.c:496 ../thunar/thunar-chooser-dialog.c:783 -#, c-format -msgid "Failed to remove \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:274 -#, c-format -msgid "Failed to read data from \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:368 -#, c-format -msgid "copy of %s" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:369 -#: ../thunar/thunar-list-model.c:786 ../thunar/thunar-properties-dialog.c:861 -#, c-format -msgid "link to %s" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:372 -#, c-format -msgid "another copy of %s" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:373 -#, c-format -msgid "another link to %s" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:376 -#, c-format -msgid "third copy of %s" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:377 -#, c-format -msgid "third link to %s" -msgstr "" - -#. if we had no match on the NAMES, try the "%uth copy of %s" pattern -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:416 -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:432 -#, c-format -msgid "%uth copy of %s" -msgid_plural "%uth copy of %s" -msgstr[0] "" -msgstr[1] "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:434 -#, c-format -msgid "%uth link to %s" -msgid_plural "%uth link to %s" -msgstr[0] "" -msgstr[1] "" - -#. unable to stat source file, impossible to copy then -#. the file does not exist, don't try to create a symlink then -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:494 -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:611 -#: ../thunar-vfs/thunar-vfs-io-ops.c:144 -#, c-format -msgid "Failed to determine file info for \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:510 -#: ../thunar-vfs/thunar-vfs-io-ops.c:416 -#, c-format -msgid "Failed to create directory \"%s\"" -msgstr "" - -#. TRANSLATORS: FIFO is an acronym for First In, First Out. You can replace the word with `pipe'. -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:519 -#, c-format -msgid "Failed to create named fifo \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:537 -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:617 -#, c-format -msgid "Failed to create symbolic link \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:550 -#, c-format -msgid "Special files cannot be copied" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-local-xfer.c:630 -#, c-format -msgid "Symbolic links are not supported" -msgstr "" - -#. ...and a special display name -#: ../thunar-vfs/thunar-vfs-io-local.c:396 -#: ../thunar/thunar-shortcuts-view.c:307 -msgid "File System" -msgstr "" - -#. generate a useful error message -#: ../thunar-vfs/thunar-vfs-io-ops.c:223 -#, c-format -msgid "Failed to copy \"%s\" to \"%s\"" -msgstr "" - -#. generate a useful error message -#: ../thunar-vfs/thunar-vfs-io-ops.c:290 -#, c-format -msgid "Failed to link \"%s\" to \"%s\"" -msgstr "" - -#. generate a useful error message -#: ../thunar-vfs/thunar-vfs-io-ops.c:367 -#, c-format -msgid "Failed to move \"%s\" to \"%s\"" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-trash.c:946 -#, c-format -msgid "The URI \"%s\" does not refer to a valid resource in the trash" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-io-trash.c:1123 -msgid "Trash" -msgstr "" - -#. we don't support copying files within the trash -#. we don't support moving files within the trash -#: ../thunar-vfs/thunar-vfs-io-trash.c:1317 -#: ../thunar-vfs/thunar-vfs-io-trash.c:1431 -#, c-format -msgid "Cannot move or copy files within the trash" -msgstr "" - -#. no "ask-replace" handler, fallback to "ask" -#: ../thunar-vfs/thunar-vfs-job.c:401 -#, c-format -msgid "" -"The file \"%s\" already exists. Would you like to replace it?\n" -"\n" -"If you replace an existing file, its contents will be overwritten." -msgstr "" - -#: ../thunar-vfs/thunar-vfs-job.c:897 -msgid "Do you want to overwrite it?" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-job.c:1042 -msgid "Do you want to skip it?" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-database.c:1684 -#, c-format -msgid "Failed to load application from file %s" -msgstr "" - -#. tell the user that we failed to delete the application launcher -#: ../thunar-vfs/thunar-vfs-mime-database.c:1750 -#, c-format -msgid "Failed to remove \"%s\": %s" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-handler.c:132 -msgid "Command" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-handler.c:133 -msgid "The command to run the mime handler" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-handler.c:145 -msgid "Flags" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-handler.c:146 -msgid "The flags for the mime handler" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-handler.c:161 -msgid "Icon" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-handler.c:162 -msgid "The icon of the mime handler" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-handler.c:174 -#: ../thunar/thunar-enum-types.c:118 ../thunar/thunar-renamer-dialog.c:442 -#: ../thunarx/thunarx-renamer.c:177 -msgid "Name" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-handler.c:175 -msgid "The name of the mime handler" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-mime-info.c:234 -#, c-format -msgid "%s document" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-path.c:362 -#, c-format -msgid "The URI \"%s\" is invalid" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-path.c:800 -#, c-format -msgid "Path too long to fit into buffer" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-path.c:903 -#, c-format -msgid "URI too long to fit into buffer" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-private.c:233 -#, c-format -msgid "Operation not supported" -msgstr "" - -#. TRANSLATORS: This error indicates that an URI contains an invalid escaped character (RFC 2396) -#: ../thunar-vfs/thunar-vfs-private.c:335 -#, c-format -msgid "Invalidly escaped characters" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-thumb.c:222 ../thunar/thunar-enum-types.c:121 -msgid "Size" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-thumb.c:223 -msgid "The desired thumbnail size" -msgstr "" - -#. update the progress information -#: ../thunar-vfs/thunar-vfs-transfer-job.c:175 -msgid "Collecting files..." -msgstr "" - -#: ../thunar-vfs/thunar-vfs-util.c:251 -#, c-format -msgid "Invalid path" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-util.c:287 -#, c-format -msgid "Unknown user \"%s\"" -msgstr "" - -#. something went wrong, for sure -#. display an error dialog to inform the user -#: ../thunar-vfs/thunar-vfs-volume-hal.c:297 -#: ../thunar/thunar-location-entry.c:650 -#, c-format -msgid "Failed to determine the mount point for %s" -msgstr "" - -#: ../thunar-vfs/thunar-vfs-volume-hal.c:875 -#, c-format -msgid "Failed to connect to the HAL daemon: %s" -msgstr "" - -#: ../thunar/main.c:54 +#: ../thunar/main.c:58 msgid "Open the bulk rename dialog" msgstr "" -#: ../thunar/main.c:56 +#: ../thunar/main.c:60 msgid "Run in daemon mode" msgstr "" -#: ../thunar/main.c:58 +#: ../thunar/main.c:62 msgid "Run in daemon mode (not supported)" msgstr "" -#: ../thunar/main.c:62 +#: ../thunar/main.c:66 msgid "Quit a running Thunar instance" msgstr "" -#: ../thunar/main.c:64 +#: ../thunar/main.c:68 msgid "Quit a running Thunar instance (not supported)" msgstr "" -#: ../thunar/main.c:66 +#: ../thunar/main.c:70 msgid "Print version information and exit" msgstr "" #. setup application name -#: ../thunar/main.c:88 +#: ../thunar/main.c:123 msgid "Thunar" msgstr "" #. initialize Gtk+ -#: ../thunar/main.c:102 +#: ../thunar/main.c:137 msgid "[FILES...]" msgstr "" -#: ../thunar/main.c:109 +#: ../thunar/main.c:144 #, c-format msgid "Thunar: Failed to open display: %s\n" msgstr "" #. yep, there's an error, so print it -#: ../thunar/main.c:114 +#: ../thunar/main.c:149 #, c-format msgid "Thunar: %s\n" msgstr "" -#: ../thunar/main.c:125 +#: ../thunar/main.c:160 msgid "The Thunar development team. All rights reserved." msgstr "" -#: ../thunar/main.c:126 +#: ../thunar/main.c:161 msgid "Written by Benedikt Meurer <benny@xfce.org>." msgstr "" -#: ../thunar/main.c:127 +#: ../thunar/main.c:162 #, c-format msgid "Please report bugs to <%s>." msgstr "" @@ -488,52 +128,50 @@ msgid "Sort items in descending order" msgstr "" #. display an error message to the user -#: ../thunar/thunar-application.c:409 ../thunar/thunar-application.c:453 +#: ../thunar/thunar-application.c:391 msgid "Failed to launch operation" msgstr "" #. failed to launch exo-eject, inform the user about this -#. display an error to the user -#: ../thunar/thunar-application.c:623 ../thunar/thunar-chooser-dialog.c:534 +#: ../thunar/thunar-application.c:626 #, c-format msgid "Failed to execute \"%s\"" msgstr "" -#. tell the user that we were unable to launch the file specified on the cmdline -#: ../thunar/thunar-application.c:1118 ../thunar/thunar-application.c:1131 +#. tell the user that we were unable to launch the file specified +#: ../thunar/thunar-application.c:1099 ../thunar/thunar-application.c:1220 +#: ../thunar/thunar-launcher.c:1107 ../thunar/thunar-location-entry.c:451 +#: ../thunar/thunar-location-entry.c:479 +#: ../thunar/thunar-shortcuts-view.c:1236 ../thunar/thunar-window.c:1429 #, c-format msgid "Failed to open \"%s\"" msgstr "" -#: ../thunar/thunar-application.c:1133 +#: ../thunar/thunar-application.c:1224 #, c-format msgid "Failed to open \"%s\": %s" msgstr "" -#: ../thunar/thunar-application.c:1170 ../thunar/thunar-application.c:1203 +#: ../thunar/thunar-application.c:1294 ../thunar/thunar-application.c:1327 msgid "Copying files..." msgstr "" -#: ../thunar/thunar-application.c:1237 +#: ../thunar/thunar-application.c:1361 msgid "Creating symbolic links..." msgstr "" -#: ../thunar/thunar-application.c:1277 -msgid "Moving files into the trash..." -msgstr "" - -#: ../thunar/thunar-application.c:1282 +#: ../thunar/thunar-application.c:1402 msgid "Moving files..." msgstr "" -#: ../thunar/thunar-application.c:1362 +#: ../thunar/thunar-application.c:1474 #, c-format msgid "" "Are you sure that you want to\n" "permanently delete \"%s\"?" msgstr "" -#: ../thunar/thunar-application.c:1367 +#: ../thunar/thunar-application.c:1479 #, c-format msgid "" "Are you sure that you want to permanently\n" @@ -544,158 +182,150 @@ msgid_plural "" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-application.c:1387 +#: ../thunar/thunar-application.c:1499 msgid "If you delete a file, it is permanently lost." msgstr "" -#: ../thunar/thunar-application.c:1397 +#: ../thunar/thunar-application.c:1509 msgid "Deleting files..." msgstr "" -#: ../thunar/thunar-application.c:1449 +#: ../thunar/thunar-application.c:1544 +msgid "Moving files into the trash..." +msgstr "" + +#: ../thunar/thunar-application.c:1583 msgid "Creating files..." msgstr "" -#: ../thunar/thunar-application.c:1489 +#: ../thunar/thunar-application.c:1622 msgid "Creating directories..." msgstr "" -#: ../thunar/thunar-application.c:1527 +#: ../thunar/thunar-application.c:1660 msgid "Remove all files and folders from the Trash?" msgstr "" #. append the "Empty Trash" menu action #. add the "Empty Trash" menu item -#: ../thunar/thunar-application.c:1532 ../thunar/thunar-location-buttons.c:171 -#: ../thunar/thunar-shortcuts-view.c:875 ../thunar/thunar-tree-view.c:1122 -#: ../thunar/thunar-window.c:287 ../plugins/thunar-tpa/main.c:49 +#: ../thunar/thunar-application.c:1665 ../thunar/thunar-location-buttons.c:173 +#: ../thunar/thunar-shortcuts-view.c:834 ../thunar/thunar-tree-view.c:1142 +#: ../thunar/thunar-window.c:291 ../plugins/thunar-tpa/main.c:49 msgid "_Empty Trash" msgstr "" -#: ../thunar/thunar-application.c:1536 +#: ../thunar/thunar-application.c:1669 msgid "" "If you choose to empty the Trash, all items in it will be permanently lost. " "Please note that you can also delete them separately." msgstr "" -#: ../thunar/thunar-application.c:1553 +#: ../thunar/thunar-application.c:1686 msgid "Emptying the Trash..." msgstr "" -#: ../thunar/thunar-application.c:1607 +#: ../thunar/thunar-application.c:1732 #, c-format msgid "Failed to determine the original path for \"%s\"" msgstr "" -#: ../thunar/thunar-application.c:1635 -#, c-format -msgid "Create the folder \"%s\"?" -msgstr "" - -#: ../thunar/thunar-application.c:1639 -msgid "C_reate Folder" -msgstr "" - -#: ../thunar/thunar-application.c:1645 -#, c-format -msgid "" -"The folder \"%s\" does not exist anymore, but it is required to restore the " -"file \"%s\" from the trash. Do you want to create the folder again?" -msgstr "" - #. display an error dialog -#: ../thunar/thunar-application.c:1682 +#: ../thunar/thunar-application.c:1749 #, c-format -msgid "Failed to restore \"%s\"" +msgid "Could not restore \"%s\"" msgstr "" -#: ../thunar/thunar-application.c:1689 +#: ../thunar/thunar-application.c:1757 msgid "Restoring files..." msgstr "" #. tell the user that it didn't work -#. display an error to the user -#: ../thunar/thunar-chooser-button.c:275 ../thunar/thunar-chooser-dialog.c:514 +#: ../thunar/thunar-chooser-button.c:268 ../thunar/thunar-chooser-dialog.c:499 #, c-format msgid "Failed to set default application for \"%s\"" msgstr "" -#: ../thunar/thunar-chooser-button.c:360 +#: ../thunar/thunar-chooser-button.c:340 msgid "No application selected" msgstr "" -#: ../thunar/thunar-chooser-button.c:366 +#: ../thunar/thunar-chooser-button.c:347 #, c-format msgid "" "The selected application is used to open this and other files of type \"%s\"." msgstr "" #. add the "Other Application..." choice -#: ../thunar/thunar-chooser-button.c:504 +#: ../thunar/thunar-chooser-button.c:459 msgid "_Other Application..." msgstr "" -#: ../thunar/thunar-chooser-dialog.c:220 ../thunar/thunar-launcher.c:143 +#: ../thunar/thunar-chooser-dialog.c:219 ../thunar/thunar-launcher.c:173 msgid "Open With" msgstr "" #. create the "Custom command" expand -#: ../thunar/thunar-chooser-dialog.c:294 +#: ../thunar/thunar-chooser-dialog.c:291 msgid "Use a _custom command:" msgstr "" -#: ../thunar/thunar-chooser-dialog.c:295 +#: ../thunar/thunar-chooser-dialog.c:292 msgid "" "Use a custom command for an application that is not available from the above " "application list." msgstr "" #. create the "Custom command" button -#: ../thunar/thunar-chooser-dialog.c:314 +#: ../thunar/thunar-chooser-dialog.c:311 msgid "_Browse..." msgstr "" #. create the "Use as default for this kind of file" button -#: ../thunar/thunar-chooser-dialog.c:320 +#: ../thunar/thunar-chooser-dialog.c:317 msgid "Use as _default for this kind of file" msgstr "" #. display an error to the user -#: ../thunar/thunar-chooser-dialog.c:489 +#: ../thunar/thunar-chooser-dialog.c:472 #, c-format msgid "Failed to add new application \"%s\"" msgstr "" +#: ../thunar/thunar-chooser-dialog.c:526 +#, c-format +msgid "Failed to execute application \"%s\"" +msgstr "" + #. append the "Remove Launcher" item -#: ../thunar/thunar-chooser-dialog.c:605 +#: ../thunar/thunar-chooser-dialog.c:598 msgid "_Remove Launcher" msgstr "" #. update the header label -#: ../thunar/thunar-chooser-dialog.c:701 +#: ../thunar/thunar-chooser-dialog.c:683 #, c-format msgid "Open <i>%s</i> and other files of type \"%s\" with:" msgstr "" -#: ../thunar/thunar-chooser-dialog.c:709 +#: ../thunar/thunar-chooser-dialog.c:691 #, c-format msgid "" "Browse the file system to select an application to open files of type \"%s\"." msgstr "" -#: ../thunar/thunar-chooser-dialog.c:715 +#: ../thunar/thunar-chooser-dialog.c:697 #, c-format msgid "" "Change the default application for files of type \"%s\" to the selected " "application." msgstr "" -#: ../thunar/thunar-chooser-dialog.c:762 +#: ../thunar/thunar-chooser-dialog.c:744 #, c-format msgid "Are you sure that you want to remove \"%s\"?" msgstr "" -#: ../thunar/thunar-chooser-dialog.c:768 +#: ../thunar/thunar-chooser-dialog.c:750 msgid "" "This will remove the application launcher that appears in the file context " "menu, but will not uninstall the application itself.\n" @@ -704,58 +334,62 @@ msgid "" "command box in the \"Open With\" dialog of the file manager." msgstr "" -#: ../thunar/thunar-chooser-dialog.c:809 +#. display an error to the user +#: ../thunar/thunar-chooser-dialog.c:765 +#, c-format +msgid "Failed to remove \"%s\"" +msgstr "" + +#: ../thunar/thunar-chooser-dialog.c:791 #: ../plugins/thunar-uca/thunar-uca-editor.c:492 msgid "Select an Application" msgstr "" -#: ../thunar/thunar-chooser-dialog.c:819 +#: ../thunar/thunar-chooser-dialog.c:801 #: ../thunar/thunar-renamer-dialog.c:1090 #: ../plugins/thunar-uca/thunar-uca-editor.c:502 msgid "All Files" msgstr "" -#: ../thunar/thunar-chooser-dialog.c:824 +#: ../thunar/thunar-chooser-dialog.c:806 #: ../plugins/thunar-uca/thunar-uca-editor.c:507 msgid "Executable Files" msgstr "" -#: ../thunar/thunar-chooser-dialog.c:839 +#: ../thunar/thunar-chooser-dialog.c:821 #: ../plugins/thunar-uca/thunar-uca-editor.c:522 msgid "Perl Scripts" msgstr "" -#: ../thunar/thunar-chooser-dialog.c:845 +#: ../thunar/thunar-chooser-dialog.c:827 #: ../plugins/thunar-uca/thunar-uca-editor.c:528 msgid "Python Scripts" msgstr "" -#: ../thunar/thunar-chooser-dialog.c:851 +#: ../thunar/thunar-chooser-dialog.c:833 #: ../plugins/thunar-uca/thunar-uca-editor.c:534 msgid "Ruby Scripts" msgstr "" -#: ../thunar/thunar-chooser-dialog.c:857 +#: ../thunar/thunar-chooser-dialog.c:839 #: ../plugins/thunar-uca/thunar-uca-editor.c:540 msgid "Shell Scripts" msgstr "" -#: ../thunar/thunar-chooser-model.c:324 +#: ../thunar/thunar-chooser-model.c:279 msgid "None available" msgstr "" -#. append the "Recommended Applications:" category -#: ../thunar/thunar-chooser-model.c:365 +#: ../thunar/thunar-chooser-model.c:315 msgid "Recommended Applications" msgstr "" -#. append the "Other Applications:" category -#: ../thunar/thunar-chooser-model.c:368 +#: ../thunar/thunar-chooser-model.c:332 msgid "Other Applications" msgstr "" #. tell the user that we cannot paste -#: ../thunar/thunar-clipboard-manager.c:362 +#: ../thunar/thunar-clipboard-manager.c:359 msgid "There is nothing on the clipboard to paste" msgstr "" @@ -820,9 +454,9 @@ msgstr "" #. the file_time is invalid #. reset page title #. tell the user that we're unable to determine the file info -#: ../thunar/thunar-column-model.c:896 ../thunar/thunar-list-model.c:737 -#: ../thunar/thunar-list-model.c:766 -#: ../thunar/thunar-permissions-chooser.c:269 ../thunar/thunar-util.c:170 +#: ../thunar/thunar-column-model.c:896 ../thunar/thunar-list-model.c:734 +#: ../thunar/thunar-list-model.c:762 +#: ../thunar/thunar-permissions-chooser.c:274 ../thunar/thunar-util.c:255 #: ../plugins/thunar-apr/thunar-apr-desktop-page.c:469 #: ../plugins/thunar-apr/thunar-apr-image-page.c:287 #: ../plugins/thunar-apr/thunar-apr-image-page.c:288 @@ -838,33 +472,33 @@ msgstr "" msgid "Compact view" msgstr "" -#: ../thunar/thunar-create-dialog.c:163 +#: ../thunar/thunar-create-dialog.c:162 msgid "C_reate" msgstr "" -#: ../thunar/thunar-create-dialog.c:178 ../thunar/thunar-dialogs.c:112 +#: ../thunar/thunar-create-dialog.c:177 ../thunar/thunar-dialogs.c:110 msgid "Enter the new name:" msgstr "" #. display an error message -#: ../thunar/thunar-create-dialog.c:520 +#: ../thunar/thunar-create-dialog.c:495 #, c-format msgid "Cannot convert filename \"%s\" to the local encoding" msgstr "" -#: ../thunar/thunar-dbus-service.c:392 +#: ../thunar/thunar-dbus-service.c:393 #, c-format msgid "Invalid filename \"%s\"" msgstr "" #. LaunchFiles() invoked without a valid working directory -#: ../thunar/thunar-dbus-service.c:721 +#: ../thunar/thunar-dbus-service.c:720 #, c-format msgid "The working directory must be an absolute path" msgstr "" #. LaunchFiles() invoked with an empty filename list -#: ../thunar/thunar-dbus-service.c:729 +#: ../thunar/thunar-dbus-service.c:728 #, c-format msgid "Atleast one filename must be specified" msgstr "" @@ -877,266 +511,429 @@ msgstr "" msgid "Configure the columns in the detailed list view" msgstr "" -#: ../thunar/thunar-details-view.c:420 +#: ../thunar/thunar-details-view.c:418 msgid "Detailed directory listing" msgstr "" -#: ../thunar/thunar-details-view.c:421 +#: ../thunar/thunar-details-view.c:419 msgid "Details view" msgstr "" #. create a new dialog window -#: ../thunar/thunar-dialogs.c:84 +#: ../thunar/thunar-dialogs.c:82 #, c-format msgid "Rename \"%s\"" msgstr "" -#: ../thunar/thunar-dialogs.c:91 +#: ../thunar/thunar-dialogs.c:89 msgid "_Rename" msgstr "" -#. display an error message -#: ../thunar/thunar-dialogs.c:161 ../thunar/thunar-properties-dialog.c:1006 -#, c-format -msgid "Failed to rename \"%s\"" -msgstr "" - -#: ../thunar/thunar-dialogs.c:248 +#: ../thunar/thunar-dialogs.c:229 msgid "translator-credits" msgstr "" #. display an error message to the user #. tell the user that we failed -#: ../thunar/thunar-dialogs.c:375 ../thunar/thunar-renamer-dialog.c:976 +#: ../thunar/thunar-dialogs.c:356 ../thunar/thunar-renamer-dialog.c:976 msgid "Failed to open the documentation browser" msgstr "" -#: ../thunar/thunar-dialogs.c:472 +#: ../thunar/thunar-dialogs.c:453 msgid "_Yes" msgstr "" -#: ../thunar/thunar-dialogs.c:476 +#: ../thunar/thunar-dialogs.c:457 msgid "Yes to _all" msgstr "" -#: ../thunar/thunar-dialogs.c:480 +#: ../thunar/thunar-dialogs.c:461 msgid "_No" msgstr "" -#: ../thunar/thunar-dialogs.c:484 +#: ../thunar/thunar-dialogs.c:465 msgid "N_o to all" msgstr "" -#: ../thunar/thunar-dialogs.c:488 +#: ../thunar/thunar-dialogs.c:469 msgid "_Retry" msgstr "" -#: ../thunar/thunar-dialogs.c:493 +#: ../thunar/thunar-dialogs.c:474 msgid "_Cancel" msgstr "" #. setup the confirmation dialog -#: ../thunar/thunar-dialogs.c:573 +#: ../thunar/thunar-dialogs.c:548 msgid "Confirm to replace files" msgstr "" -#: ../thunar/thunar-dialogs.c:579 +#: ../thunar/thunar-dialogs.c:554 msgid "_Skip" msgstr "" -#: ../thunar/thunar-dialogs.c:580 +#: ../thunar/thunar-dialogs.c:555 msgid "Replace _All" msgstr "" -#: ../thunar/thunar-dialogs.c:581 +#: ../thunar/thunar-dialogs.c:556 msgid "_Replace" msgstr "" -#: ../thunar/thunar-dialogs.c:611 +#: ../thunar/thunar-dialogs.c:588 +#, c-format +msgid "This folder already contains a symbolic link \"%s\"." +msgstr "" + +#: ../thunar/thunar-dialogs.c:593 +#, c-format +msgid "This folder already contains a folder \"%s\"." +msgstr "" + +#: ../thunar/thunar-dialogs.c:598 #, c-format msgid "This folder already contains a file \"%s\"." msgstr "" -#: ../thunar/thunar-dialogs.c:619 +#: ../thunar/thunar-dialogs.c:610 +msgid "ReplaceDialogPart1|Do you want to replace the link" +msgstr "" + +#: ../thunar/thunar-dialogs.c:612 +msgid "ReplaceDialogPart1|Do you want to replace the existing folder" +msgstr "" + +#: ../thunar/thunar-dialogs.c:614 msgid "ReplaceDialogPart1|Do you want to replace the existing file" msgstr "" #. #. Fourth box (size, volume, free space) #. -#: ../thunar/thunar-dialogs.c:635 ../thunar/thunar-dialogs.c:660 -#: ../thunar/thunar-properties-dialog.c:440 +#: ../thunar/thunar-dialogs.c:631 ../thunar/thunar-dialogs.c:662 +#: ../thunar/thunar-properties-dialog.c:442 msgid "Size:" msgstr "" -#: ../thunar/thunar-dialogs.c:635 ../thunar/thunar-dialogs.c:660 -#: ../thunar/thunar-properties-dialog.c:401 +#: ../thunar/thunar-dialogs.c:631 ../thunar/thunar-dialogs.c:662 +#: ../thunar/thunar-properties-dialog.c:403 msgid "Modified:" msgstr "" -#: ../thunar/thunar-dialogs.c:644 +#: ../thunar/thunar-dialogs.c:641 +msgid "ReplaceDialogPart2|with the following link?" +msgstr "" + +#: ../thunar/thunar-dialogs.c:643 +msgid "ReplaceDialogPart2|with the following folder?" +msgstr "" + +#: ../thunar/thunar-dialogs.c:645 msgid "ReplaceDialogPart2|with the following file?" msgstr "" -#: ../thunar/thunar-dnd.c:70 +#: ../thunar/thunar-dnd.c:71 msgid "_Copy here" msgstr "" -#: ../thunar/thunar-dnd.c:70 +#: ../thunar/thunar-dnd.c:71 msgid "_Move here" msgstr "" -#: ../thunar/thunar-dnd.c:70 +#: ../thunar/thunar-dnd.c:71 msgid "_Link here" msgstr "" #. display an error to the user #. display an error message to the user -#: ../thunar/thunar-dnd.c:252 ../thunar/thunar-launcher.c:551 +#: ../thunar/thunar-dnd.c:253 ../thunar/thunar-launcher.c:589 #, c-format msgid "Failed to execute file \"%s\"" msgstr "" -#: ../thunar/thunar-enum-types.c:44 +#: ../thunar/thunar-enum-types.c:45 msgid "Name only" msgstr "" -#: ../thunar/thunar-enum-types.c:45 +#: ../thunar/thunar-enum-types.c:46 msgid "Suffix only" msgstr "" -#: ../thunar/thunar-enum-types.c:46 +#: ../thunar/thunar-enum-types.c:47 msgid "Name and Suffix" msgstr "" -#: ../thunar/thunar-enum-types.c:114 +#: ../thunar/thunar-enum-types.c:115 #: ../plugins/thunar-sbr/thunar-sbr-enum-types.c:135 msgid "Date Accessed" msgstr "" -#: ../thunar/thunar-enum-types.c:115 +#: ../thunar/thunar-enum-types.c:116 #: ../plugins/thunar-sbr/thunar-sbr-enum-types.c:136 msgid "Date Modified" msgstr "" -#: ../thunar/thunar-enum-types.c:116 +#: ../thunar/thunar-enum-types.c:117 msgid "Group" msgstr "" -#: ../thunar/thunar-enum-types.c:117 +#: ../thunar/thunar-enum-types.c:118 msgid "MIME Type" msgstr "" -#: ../thunar/thunar-enum-types.c:119 +#: ../thunar/thunar-enum-types.c:119 ../thunar/thunar-renamer-dialog.c:442 +#: ../thunarx/thunarx-renamer.c:177 +msgid "Name" +msgstr "" + +#: ../thunar/thunar-enum-types.c:120 msgid "Owner" msgstr "" #. #. Permissions chooser #. -#: ../thunar/thunar-enum-types.c:120 ../thunar/thunar-properties-dialog.c:513 +#: ../thunar/thunar-enum-types.c:121 ../thunar/thunar-properties-dialog.c:515 msgid "Permissions" msgstr "" -#: ../thunar/thunar-enum-types.c:122 -msgid "Type" +#: ../thunar/thunar-enum-types.c:122 +msgid "Size" +msgstr "" + +#: ../thunar/thunar-enum-types.c:123 +msgid "Type" +msgstr "" + +#: ../thunar/thunar-enum-types.c:124 +msgid "File" +msgstr "" + +#: ../thunar/thunar-enum-types.c:125 +msgid "File Name" +msgstr "" + +#: ../thunar/thunar-exec.c:562 +#, c-format +msgid "Unknown error" +msgstr "" + +#: ../thunar/thunar-file.c:951 +#, c-format +msgid "The root folder has no parent" +msgstr "" + +#: ../thunar/thunar-file.c:1011 +#, c-format +msgid "Failed to parse the desktop file: %s" +msgstr "" + +#: ../thunar/thunar-file.c:1049 +#, c-format +msgid "No Exec field specified" +msgstr "" + +#: ../thunar/thunar-file.c:1070 +#, c-format +msgid "No URL field specified" +msgstr "" + +#: ../thunar/thunar-file.c:1076 +#, c-format +msgid "Invalid desktop file" +msgstr "" + +#. create the "back" action +#: ../thunar/thunar-history.c:193 +msgid "Back" +msgstr "" + +#: ../thunar/thunar-history.c:193 +msgid "Go to the previous visited folder" +msgstr "" + +#. create the "forward" action +#: ../thunar/thunar-history.c:199 +msgid "Forward" +msgstr "" + +#: ../thunar/thunar-history.c:199 +msgid "Go to the next visited folder" +msgstr "" + +#: ../thunar/thunar-icon-factory.c:681 +#, c-format +msgid "Failed to load fallback icon from \"%s\" (%s). Check your installation!" +msgstr "" + +#: ../thunar/thunar-icon-view.c:198 +msgid "Icon based directory listing" +msgstr "" + +#: ../thunar/thunar-icon-view.c:199 +msgid "Icon view" +msgstr "" + +#: ../thunar/thunar-io-jobs.c:160 ../thunar/thunar-io-jobs.c:297 +#, c-format +msgid "The file \"%s\" already exists" +msgstr "" + +#: ../thunar/thunar-io-jobs.c:183 +#, c-format +msgid "Failed to create empty file \"%s\": %s" +msgstr "" + +#: ../thunar/thunar-io-jobs.c:320 +#, c-format +msgid "Failed to create directory \"%s\": %s" +msgstr "" + +#. tell the user that we're preparing to unlink the files +#: ../thunar/thunar-io-jobs.c:384 +msgid "Preparing..." +msgstr "" + +#: ../thunar/thunar-io-jobs.c:446 +#, c-format +msgid "Could not delete file \"%s\": %s" +msgstr "" + +#: ../thunar/thunar-io-jobs.c:594 +#, c-format +msgid "Could not create symbolic link to \"%s\" because it is not a local file" +msgstr "" + +#. generate a useful error message +#: ../thunar/thunar-io-jobs.c:781 +#, c-format +msgid "Failed to change the owner of \"%s\": %s" +msgstr "" + +#: ../thunar/thunar-io-jobs.c:782 +#, c-format +msgid "Failed to change the group of \"%s\": %s" +msgstr "" + +#: ../thunar/thunar-io-jobs.c:938 +#, c-format +msgid "Failed to change the permissions of \"%s\": %s" +msgstr "" + +#. Copy/link name for n <= 3 +#: ../thunar/thunar-io-jobs-util.c:36 +#, c-format +msgid "copy of %s" +msgstr "" + +#: ../thunar/thunar-io-jobs-util.c:36 ../thunar/thunar-list-model.c:779 +#: ../thunar/thunar-properties-dialog.c:907 +#, c-format +msgid "link to %s" msgstr "" -#: ../thunar/thunar-enum-types.c:123 -msgid "File" +#: ../thunar/thunar-io-jobs-util.c:37 +#, c-format +msgid "another copy of %s" msgstr "" -#: ../thunar/thunar-enum-types.c:124 -msgid "File Name" +#: ../thunar/thunar-io-jobs-util.c:37 +#, c-format +msgid "another link to %s" msgstr "" -#: ../thunar/thunar-file.c:743 +#: ../thunar/thunar-io-jobs-util.c:38 #, c-format -msgid "The root folder has no parent" +msgid "third copy of %s" msgstr "" -#. create the "back" action -#: ../thunar/thunar-history.c:193 -msgid "Back" +#: ../thunar/thunar-io-jobs-util.c:38 +#, c-format +msgid "third link to %s" msgstr "" -#: ../thunar/thunar-history.c:193 -msgid "Go to the previous visited folder" +#. Fallback copy/link name for n >= 4 +#: ../thunar/thunar-io-jobs-util.c:41 +#, c-format +msgid "%uth copy of %s" msgstr "" -#. create the "forward" action -#: ../thunar/thunar-history.c:199 -msgid "Forward" +#: ../thunar/thunar-io-jobs-util.c:41 +#, c-format +msgid "%uth link to %s" msgstr "" -#: ../thunar/thunar-history.c:199 -msgid "Go to the next visited folder" +#: ../thunar/thunar-job.c:277 +#, c-format +msgid "" +"The file \"%s\" already exists. Would you like to replace it?\n" +"\n" +"If you replace an existing file, its contents will be overwritten." msgstr "" -#: ../thunar/thunar-icon-factory.c:754 -#, c-format -msgid "Failed to load fallback icon from \"%s\" (%s). Check your installation!" +#: ../thunar/thunar-job.c:357 +msgid "Do you want to overwrite it?" msgstr "" -#: ../thunar/thunar-icon-view.c:198 -msgid "Icon based directory listing" +#: ../thunar/thunar-job.c:411 +msgid "Do you want to create it?" msgstr "" -#: ../thunar/thunar-icon-view.c:199 -msgid "Icon view" +#: ../thunar/thunar-job.c:513 +msgid "Do you want to skip it?" msgstr "" #. append the "Open" menu action -#: ../thunar/thunar-launcher.c:140 ../thunar/thunar-launcher.c:808 -#: ../thunar/thunar-location-buttons.c:168 -#: ../thunar/thunar-shortcuts-view.c:817 ../thunar/thunar-tree-view.c:1063 +#: ../thunar/thunar-launcher.c:170 ../thunar/thunar-launcher.c:846 +#: ../thunar/thunar-location-buttons.c:170 +#: ../thunar/thunar-shortcuts-view.c:785 ../thunar/thunar-tree-view.c:1092 msgid "_Open" msgstr "" #. append the "Open in New Window" menu action -#: ../thunar/thunar-launcher.c:141 ../thunar/thunar-location-buttons.c:169 -#: ../thunar/thunar-shortcuts-view.c:828 ../thunar/thunar-tree-view.c:1075 +#: ../thunar/thunar-launcher.c:171 ../thunar/thunar-location-buttons.c:171 +#: ../thunar/thunar-shortcuts-view.c:796 ../thunar/thunar-tree-view.c:1104 msgid "Open in New Window" msgstr "" -#: ../thunar/thunar-launcher.c:141 +#: ../thunar/thunar-launcher.c:171 msgid "Open the selected directory in a new window" msgstr "" -#: ../thunar/thunar-launcher.c:142 ../thunar/thunar-launcher.c:144 +#: ../thunar/thunar-launcher.c:172 ../thunar/thunar-launcher.c:174 msgid "Open With Other _Application..." msgstr "" -#: ../thunar/thunar-launcher.c:142 ../thunar/thunar-launcher.c:144 -#: ../thunar/thunar-launcher.c:891 +#: ../thunar/thunar-launcher.c:172 ../thunar/thunar-launcher.c:174 +#: ../thunar/thunar-launcher.c:929 msgid "Choose another application with which to open the selected file" msgstr "" -#: ../thunar/thunar-launcher.c:646 +#: ../thunar/thunar-launcher.c:680 #, c-format msgid "Failed to open file \"%s\"" msgstr "" #. we can just tell that n files failed to open -#: ../thunar/thunar-launcher.c:652 +#: ../thunar/thunar-launcher.c:686 #, c-format msgid "Failed to open %d file" msgid_plural "Failed to open %d files" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-launcher.c:688 +#: ../thunar/thunar-launcher.c:725 msgid "Are you sure you want to open all folders?" msgstr "" -#: ../thunar/thunar-launcher.c:690 +#: ../thunar/thunar-launcher.c:727 #, c-format msgid "This will open %d separate file manager window." msgid_plural "This will open %d separate file manager windows." msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-launcher.c:694 +#: ../thunar/thunar-launcher.c:731 #, c-format msgid "Open %d New Window" msgid_plural "Open %d New Windows" @@ -1144,106 +941,100 @@ msgstr[0] "" msgstr[1] "" #. turn "Open" into "Open in n New Windows" -#: ../thunar/thunar-launcher.c:786 +#: ../thunar/thunar-launcher.c:824 #, c-format msgid "Open in %d New Window" msgid_plural "Open in %d New Windows" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-launcher.c:787 +#: ../thunar/thunar-launcher.c:825 #, c-format msgid "Open the selected directory in %d new window" msgid_plural "Open the selected directories in %d new windows" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-launcher.c:807 +#: ../thunar/thunar-launcher.c:845 msgid "_Open in New Window" msgstr "" -#: ../thunar/thunar-launcher.c:810 +#: ../thunar/thunar-launcher.c:848 msgid "Open the selected file" msgid_plural "Open the selected files" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-launcher.c:859 +#: ../thunar/thunar-launcher.c:897 msgid "_Execute" msgstr "" -#: ../thunar/thunar-launcher.c:860 +#: ../thunar/thunar-launcher.c:898 msgid "Execute the selected file" msgid_plural "Execute the selected files" msgstr[0] "" msgstr[1] "" #. turn the "Open" action into "Open With DEFAULT" -#: ../thunar/thunar-launcher.c:866 +#: ../thunar/thunar-launcher.c:904 #, c-format msgid "_Open With \"%s\"" msgstr "" -#: ../thunar/thunar-launcher.c:867 ../thunar/thunar-launcher.c:956 +#: ../thunar/thunar-launcher.c:905 ../thunar/thunar-launcher.c:991 #, c-format msgid "Use \"%s\" to open the selected file" msgid_plural "Use \"%s\" to open the selected files" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-launcher.c:890 +#: ../thunar/thunar-launcher.c:928 msgid "_Open With Other Application..." msgstr "" -#: ../thunar/thunar-launcher.c:899 +#: ../thunar/thunar-launcher.c:937 msgid "_Open With Default Applications" msgstr "" -#: ../thunar/thunar-launcher.c:900 +#: ../thunar/thunar-launcher.c:938 msgid "Open the selected file with the default application" msgid_plural "Open the selected files with the default applications" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-launcher.c:955 +#: ../thunar/thunar-launcher.c:990 #, c-format msgid "Open With \"%s\"" msgstr "" -#. tell the user that we were unable to mount the volume, which is required to send files to it -#. display an error dialog to inform the user -#: ../thunar/thunar-launcher.c:1238 ../thunar/thunar-location-entry.c:639 -#: ../thunar/thunar-shortcuts-view.c:1398 ../thunar/thunar-tree-view.c:976 -#: ../thunar/thunar-tree-view.c:1728 +#: ../thunar/thunar-launcher.c:1425 ../thunar/thunar-location-entry.c:703 +#: ../thunar/thunar-shortcuts-view.c:1266 +#: ../thunar/thunar-shortcuts-view.c:1488 ../thunar/thunar-tree-view.c:1889 #, c-format msgid "Failed to mount \"%s\"" msgstr "" -#: ../thunar/thunar-launcher.c:1305 +#: ../thunar/thunar-launcher.c:1544 msgid "Desktop (Create Link)" msgid_plural "Desktop (Create Links)" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-launcher.c:1306 +#: ../thunar/thunar-launcher.c:1545 msgid "Create a link to the selected file on the desktop" msgid_plural "Create links to the selected files on the desktop" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-launcher.c:1343 ../thunar/thunar-launcher.c:1381 +#: ../thunar/thunar-launcher.c:1582 ../thunar/thunar-launcher.c:1639 #, c-format msgid "Send the selected file to \"%s\"" msgid_plural "Send the selected files to \"%s\"" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-list-model.c:784 ../thunar/thunar-properties-dialog.c:859 -msgid "broken link" -msgstr "" - #. generate a text which includes the size of all items in the folder -#: ../thunar/thunar-list-model.c:2244 +#: ../thunar/thunar-list-model.c:2263 #, c-format msgid "%d item (%s), Free space: %s" msgid_plural "%d items (%s), Free space: %s" @@ -1251,31 +1042,41 @@ msgstr[0] "" msgstr[1] "" #. just the standard text -#: ../thunar/thunar-list-model.c:2253 +#: ../thunar/thunar-list-model.c:2272 #, c-format msgid "%d item, Free space: %s" msgid_plural "%d items, Free space: %s" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-list-model.c:2261 +#: ../thunar/thunar-list-model.c:2280 #, c-format msgid "%d item" msgid_plural "%d items" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-list-model.c:2277 +#: ../thunar/thunar-list-model.c:2299 #, c-format msgid "\"%s\" broken link" msgstr "" -#: ../thunar/thunar-list-model.c:2281 +#: ../thunar/thunar-list-model.c:2303 #, c-format msgid "\"%s\" (%s) link to %s" msgstr "" -#: ../thunar/thunar-list-model.c:2286 +#: ../thunar/thunar-list-model.c:2308 +#, c-format +msgid "\"%s\" shortcut" +msgstr "" + +#: ../thunar/thunar-list-model.c:2312 +#, c-format +msgid "\"%s\" mountable" +msgstr "" + +#: ../thunar/thunar-list-model.c:2319 #, c-format msgid "\"%s\" (%s) %s" msgstr "" @@ -1284,24 +1085,24 @@ msgstr "" #. * where the trashed file/folder was located before it was moved to the trash), otherwise the #. * properties dialog width will be messed up. #. -#: ../thunar/thunar-list-model.c:2297 ../thunar/thunar-properties-dialog.c:362 +#: ../thunar/thunar-list-model.c:2331 ../thunar/thunar-properties-dialog.c:364 msgid "Original Path:" msgstr "" #. append the image dimensions to the statusbar text -#: ../thunar/thunar-list-model.c:2309 +#: ../thunar/thunar-list-model.c:2344 #: ../plugins/thunar-apr/thunar-apr-image-page.c:151 msgid "Image Size:" msgstr "" -#: ../thunar/thunar-list-model.c:2328 +#: ../thunar/thunar-list-model.c:2363 #, c-format msgid "%d item selected (%s)" msgid_plural "%d items selected (%s)" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-list-model.c:2333 +#: ../thunar/thunar-list-model.c:2368 #, c-format msgid "%d item selected" msgid_plural "%d items selected" @@ -1309,67 +1110,66 @@ msgstr[0] "" msgstr[1] "" #. append the "Create Folder" menu action -#: ../thunar/thunar-location-buttons.c:170 -#: ../thunar/thunar-standard-view.c:336 ../thunar/thunar-tree-view.c:1138 +#: ../thunar/thunar-location-buttons.c:172 +#: ../thunar/thunar-standard-view.c:339 ../thunar/thunar-tree-view.c:1158 msgid "Create _Folder..." msgstr "" -#: ../thunar/thunar-location-buttons.c:171 ../thunar/thunar-window.c:287 +#: ../thunar/thunar-location-buttons.c:173 ../thunar/thunar-window.c:291 msgid "Delete all files and folders in the Trash" msgstr "" -#: ../thunar/thunar-location-buttons.c:172 -#: ../thunar/thunar-standard-view.c:342 +#: ../thunar/thunar-location-buttons.c:174 +#: ../thunar/thunar-standard-view.c:345 msgid "Paste Into Folder" msgstr "" -#: ../thunar/thunar-location-buttons.c:173 -#: ../thunar/thunar-renamer-dialog.c:186 ../thunar/thunar-standard-view.c:337 +#: ../thunar/thunar-location-buttons.c:175 +#: ../thunar/thunar-renamer-dialog.c:186 ../thunar/thunar-standard-view.c:340 msgid "_Properties..." msgstr "" -#: ../thunar/thunar-location-buttons.c:274 +#: ../thunar/thunar-location-buttons.c:276 msgid "Spacing" msgstr "" -#: ../thunar/thunar-location-buttons.c:275 +#: ../thunar/thunar-location-buttons.c:277 msgid "The amount of space between the path buttons" msgstr "" -#: ../thunar/thunar-location-buttons.c:1271 +#: ../thunar/thunar-location-buttons.c:1273 #, c-format msgid "Open \"%s\" in this window" msgstr "" -#: ../thunar/thunar-location-buttons.c:1277 +#: ../thunar/thunar-location-buttons.c:1279 #, c-format msgid "Open \"%s\" in a new window" msgstr "" -#: ../thunar/thunar-location-buttons.c:1282 +#: ../thunar/thunar-location-buttons.c:1284 #, c-format msgid "Create a new folder in \"%s\"" msgstr "" -#: ../thunar/thunar-location-buttons.c:1294 +#: ../thunar/thunar-location-buttons.c:1296 #, c-format msgid "" "Move or copy files previously selected by a Cut or Copy command into \"%s\"" msgstr "" -#: ../thunar/thunar-location-buttons.c:1300 +#: ../thunar/thunar-location-buttons.c:1302 #, c-format msgid "View the properties of the folder \"%s\"" msgstr "" -#. ask the user to enter a name for the new folder -#: ../thunar/thunar-location-buttons.c:1340 -#: ../thunar/thunar-standard-view.c:1853 ../thunar/thunar-tree-view.c:1544 +#: ../thunar/thunar-location-buttons.c:1338 +#: ../thunar/thunar-standard-view.c:1838 ../thunar/thunar-tree-view.c:1566 msgid "New Folder" msgstr "" -#: ../thunar/thunar-location-buttons.c:1340 -#: ../thunar/thunar-standard-view.c:1853 ../thunar/thunar-tree-view.c:1544 +#: ../thunar/thunar-location-buttons.c:1339 +#: ../thunar/thunar-standard-view.c:1839 ../thunar/thunar-tree-view.c:1567 msgid "Create New Folder" msgstr "" @@ -1381,217 +1181,216 @@ msgstr "" msgid "_Location:" msgstr "" -#: ../thunar/thunar-location-entry.c:426 ../thunar/thunar-window.c:1470 +#: ../thunar/thunar-location-entry.c:444 #, c-format -msgid "Failed to launch \"%s\"" +msgid "File does not exist" msgstr "" -#: ../thunar/thunar-path-entry.c:259 -msgid "Icon size" +#: ../thunar/thunar-location-entry.c:788 +#, c-format +msgid "Failed to determine the mount point of \"%s\"" +msgstr "" + +#: ../thunar/thunar-misc-jobs.c:84 +#, c-format +msgid "No templates installed" msgstr "" #: ../thunar/thunar-path-entry.c:260 +msgid "Icon size" +msgstr "" + +#: ../thunar/thunar-path-entry.c:261 msgid "The icon size for the path entry" msgstr "" #. 0000 -#: ../thunar/thunar-permissions-chooser.c:242 +#: ../thunar/thunar-permissions-chooser.c:247 msgid "None" msgstr "" #. 0002 -#: ../thunar/thunar-permissions-chooser.c:244 +#: ../thunar/thunar-permissions-chooser.c:249 msgid "Write only" msgstr "" #. 0004 -#: ../thunar/thunar-permissions-chooser.c:246 +#: ../thunar/thunar-permissions-chooser.c:251 msgid "Read only" msgstr "" #. 0006 -#: ../thunar/thunar-permissions-chooser.c:248 +#: ../thunar/thunar-permissions-chooser.c:253 msgid "Read & Write" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:259 +#: ../thunar/thunar-permissions-chooser.c:264 msgid "Owner:" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:277 -#: ../thunar/thunar-permissions-chooser.c:318 +#: ../thunar/thunar-permissions-chooser.c:282 +#: ../thunar/thunar-permissions-chooser.c:323 msgid "Access:" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:300 +#: ../thunar/thunar-permissions-chooser.c:305 msgid "Group:" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:341 +#: ../thunar/thunar-permissions-chooser.c:346 msgid "Others:" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:364 +#: ../thunar/thunar-permissions-chooser.c:369 msgid "Program:" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:370 +#: ../thunar/thunar-permissions-chooser.c:375 msgid "Allow this file to _run as a program" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:390 +#: ../thunar/thunar-permissions-chooser.c:395 msgid "" "Allowing untrusted programs to run\n" "presents a security risk to your system." msgstr "" -#: ../thunar/thunar-permissions-chooser.c:405 +#: ../thunar/thunar-permissions-chooser.c:410 msgid "" "The folder permissions are inconsistent, you\n" "may not be able to work with files in this folder." msgstr "" -#: ../thunar/thunar-permissions-chooser.c:418 +#: ../thunar/thunar-permissions-chooser.c:423 msgid "Correct folder permissions..." msgstr "" -#: ../thunar/thunar-permissions-chooser.c:419 +#: ../thunar/thunar-permissions-chooser.c:424 msgid "Click here to automatically fix the folder permissions." msgstr "" -#: ../thunar/thunar-permissions-chooser.c:430 +#: ../thunar/thunar-permissions-chooser.c:435 msgid "Please wait..." msgstr "" -#: ../thunar/thunar-permissions-chooser.c:435 +#: ../thunar/thunar-permissions-chooser.c:440 msgid "Stop applying permissions recursively." msgstr "" #. allocate the question dialog -#: ../thunar/thunar-permissions-chooser.c:550 +#: ../thunar/thunar-permissions-chooser.c:555 msgid "Question" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:574 +#: ../thunar/thunar-permissions-chooser.c:579 msgid "Apply recursively?" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:580 +#: ../thunar/thunar-permissions-chooser.c:585 msgid "" "Do you want to apply your changes recursively to\n" "all files and subfolders below the selected folder?" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:585 +#: ../thunar/thunar-permissions-chooser.c:590 msgid "Do _not ask me again" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:586 +#: ../thunar/thunar-permissions-chooser.c:591 msgid "" "If you select this option your choice will be remembered and you won't be " "asked again. You can use the preferences dialog to alter your choice " "afterwards." msgstr "" -#. display an error to the user -#: ../thunar/thunar-permissions-chooser.c:666 -msgid "Failed to change group" -msgstr "" - -#. display an error to the user -#: ../thunar/thunar-permissions-chooser.c:719 -#: ../thunar/thunar-permissions-chooser.c:1058 -msgid "Failed to apply new permissions" -msgstr "" - -#: ../thunar/thunar-permissions-chooser.c:901 +#: ../thunar/thunar-permissions-chooser.c:888 msgid "Unknown file owner" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:1032 +#: ../thunar/thunar-permissions-chooser.c:1018 msgid "Correct folder permissions automatically?" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:1034 +#: ../thunar/thunar-permissions-chooser.c:1020 msgid "Correct folder permissions" msgstr "" -#: ../thunar/thunar-permissions-chooser.c:1036 +#: ../thunar/thunar-permissions-chooser.c:1022 msgid "" "The folder permissions will be reset to a consistent state. Only users " "allowed to read the contents of this folder will be allowed to enter the " "folder afterwards." msgstr "" -#: ../thunar/thunar-preferences-dialog.c:227 +#: ../thunar/thunar-preferences-dialog.c:225 msgid "File Manager Preferences" msgstr "" #. #. Display #. -#: ../thunar/thunar-preferences-dialog.c:244 +#: ../thunar/thunar-preferences-dialog.c:242 msgid "Display" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:254 +#: ../thunar/thunar-preferences-dialog.c:252 msgid "Default View" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:266 +#: ../thunar/thunar-preferences-dialog.c:264 msgid "View _new folders using:" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:271 -#: ../thunar/thunar-preferences-dialog.c:302 +#: ../thunar/thunar-preferences-dialog.c:269 +#: ../thunar/thunar-preferences-dialog.c:297 msgid "Icon View" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:272 +#: ../thunar/thunar-preferences-dialog.c:270 msgid "Detailed List View" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:273 +#: ../thunar/thunar-preferences-dialog.c:271 msgid "Compact List View" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:274 +#: ../thunar/thunar-preferences-dialog.c:272 msgid "Last Active View" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:285 +#: ../thunar/thunar-preferences-dialog.c:280 msgid "Sort _folders before files" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:287 +#: ../thunar/thunar-preferences-dialog.c:282 msgid "Select this option to list folders before files when you sort a folder." msgstr "" -#: ../thunar/thunar-preferences-dialog.c:291 +#: ../thunar/thunar-preferences-dialog.c:286 msgid "_Show thumbnails" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:293 +#: ../thunar/thunar-preferences-dialog.c:288 msgid "" "Select this option to display previewable files within a folder as " "automatically generated thumbnail icons." msgstr "" -#: ../thunar/thunar-preferences-dialog.c:314 +#: ../thunar/thunar-preferences-dialog.c:309 msgid "_Text beside icons" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:316 +#: ../thunar/thunar-preferences-dialog.c:311 msgid "" "Select this option to place the icon captions for items beside the icon " "rather than below the icon." msgstr "" -#: ../thunar/thunar-preferences-dialog.c:325 +#: ../thunar/thunar-preferences-dialog.c:320 msgid "Date" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:337 +#: ../thunar/thunar-preferences-dialog.c:332 #: ../plugins/thunar-sbr/thunar-sbr-date-renamer.c:223 msgid "_Format:" msgstr "" @@ -1599,76 +1398,76 @@ msgstr "" #. #. Side Pane #. -#: ../thunar/thunar-preferences-dialog.c:361 +#: ../thunar/thunar-preferences-dialog.c:353 msgid "Side Pane" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:371 +#: ../thunar/thunar-preferences-dialog.c:363 msgid "Shortcuts Pane" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:383 +#: ../thunar/thunar-preferences-dialog.c:375 msgid "_Icon Size:" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:388 -#: ../thunar/thunar-preferences-dialog.c:433 +#: ../thunar/thunar-preferences-dialog.c:380 +#: ../thunar/thunar-preferences-dialog.c:422 msgid "Very Small" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:389 -#: ../thunar/thunar-preferences-dialog.c:434 +#: ../thunar/thunar-preferences-dialog.c:381 +#: ../thunar/thunar-preferences-dialog.c:423 msgid "Smaller" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:390 -#: ../thunar/thunar-preferences-dialog.c:435 +#: ../thunar/thunar-preferences-dialog.c:382 +#: ../thunar/thunar-preferences-dialog.c:424 msgid "Small" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:391 -#: ../thunar/thunar-preferences-dialog.c:436 +#: ../thunar/thunar-preferences-dialog.c:383 +#: ../thunar/thunar-preferences-dialog.c:425 msgid "Normal" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:392 -#: ../thunar/thunar-preferences-dialog.c:437 +#: ../thunar/thunar-preferences-dialog.c:384 +#: ../thunar/thunar-preferences-dialog.c:426 msgid "Large" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:393 -#: ../thunar/thunar-preferences-dialog.c:438 +#: ../thunar/thunar-preferences-dialog.c:385 +#: ../thunar/thunar-preferences-dialog.c:427 msgid "Larger" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:394 -#: ../thunar/thunar-preferences-dialog.c:439 +#: ../thunar/thunar-preferences-dialog.c:386 +#: ../thunar/thunar-preferences-dialog.c:428 msgid "Very Large" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:405 +#: ../thunar/thunar-preferences-dialog.c:394 msgid "Show Icon _Emblems" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:407 +#: ../thunar/thunar-preferences-dialog.c:396 msgid "" "Select this option to display icon emblems in the shortcuts pane for all " "folders for which emblems have been defined in the folders properties dialog." msgstr "" -#: ../thunar/thunar-preferences-dialog.c:416 +#: ../thunar/thunar-preferences-dialog.c:405 msgid "Tree Pane" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:428 +#: ../thunar/thunar-preferences-dialog.c:417 msgid "Icon _Size:" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:450 +#: ../thunar/thunar-preferences-dialog.c:436 msgid "Show Icon E_mblems" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:452 +#: ../thunar/thunar-preferences-dialog.c:438 msgid "" "Select this option to display icon emblems in the tree pane for all folders " "for which emblems have been defined in the folders properties dialog." @@ -1677,25 +1476,25 @@ msgstr "" #. #. Behavior #. -#: ../thunar/thunar-preferences-dialog.c:461 +#: ../thunar/thunar-preferences-dialog.c:447 msgid "Behavior" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:471 +#: ../thunar/thunar-preferences-dialog.c:457 msgid "Navigation" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:483 +#: ../thunar/thunar-preferences-dialog.c:469 msgid "_Single click to activate items" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:503 +#: ../thunar/thunar-preferences-dialog.c:489 msgid "" "Specify the d_elay before an item gets selected\n" "when the mouse pointer is paused over it:" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:515 +#: ../thunar/thunar-preferences-dialog.c:501 msgid "" "When single-click activation is enabled, pausing the mouse pointer over an " "item will automatically select that item after the chosen delay. You can " @@ -1704,184 +1503,183 @@ msgid "" "to select the item without activating it." msgstr "" -#: ../thunar/thunar-preferences-dialog.c:533 +#: ../thunar/thunar-preferences-dialog.c:519 msgid "Disabled" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:539 +#: ../thunar/thunar-preferences-dialog.c:525 msgid "Medium" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:545 +#: ../thunar/thunar-preferences-dialog.c:531 msgid "Long" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:551 +#: ../thunar/thunar-preferences-dialog.c:537 msgid "_Double click to activate items" msgstr "" #. #. Advanced #. -#: ../thunar/thunar-preferences-dialog.c:561 +#: ../thunar/thunar-preferences-dialog.c:547 msgid "Advanced" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:571 +#: ../thunar/thunar-preferences-dialog.c:557 msgid "Folder Permissions" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:583 +#: ../thunar/thunar-preferences-dialog.c:569 msgid "" "When changing the permissions of a folder, you\n" "can also apply the changes to the contents of the\n" "folder. Select the default behavior below:" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:591 +#: ../thunar/thunar-preferences-dialog.c:577 msgid "Ask everytime" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:592 +#: ../thunar/thunar-preferences-dialog.c:578 msgid "Apply to Folder Only" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:593 +#: ../thunar/thunar-preferences-dialog.c:579 msgid "Apply to Folder and Contents" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:606 +#: ../thunar/thunar-preferences-dialog.c:589 msgid "Volume Management" msgstr "" -#: ../thunar/thunar-preferences-dialog.c:634 -msgid "" -"Install the \"thunar-volman\" package to use\n" -"the volume management support in Thunar." -msgstr "" - -#: ../thunar/thunar-preferences-dialog.c:635 -msgid "" -"Build thunar-vfs with HAL support to use\n" -"the volume management support in Thunar." -msgstr "" - #. add check button to enable/disable auto mounting -#: ../thunar/thunar-preferences-dialog.c:646 +#: ../thunar/thunar-preferences-dialog.c:605 msgid "Enable _Volume Management" msgstr "" #. TRANSLATORS: Make sure you place the <a>...</a>-link on the first line, otherwise the user will be unable to click on it -#: ../thunar/thunar-preferences-dialog.c:656 +#: ../thunar/thunar-preferences-dialog.c:615 msgid "" "<a href=\"volman-config:\">Configure</a> the management of removable drives\n" "and media (i.e. how cameras should be handled)." msgstr "" #. tell the user that we failed to come up with the thunar-volman configuration dialog -#: ../thunar/thunar-preferences-dialog.c:717 +#: ../thunar/thunar-preferences-dialog.c:674 msgid "Failed to display the volume management settings" msgstr "" -#: ../thunar/thunar-progress-dialog.c:398 +#: ../thunar/thunar-progress-dialog.c:402 #, c-format msgid "(%lu hour remaining)" msgid_plural "(%lu hours remaining)" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-progress-dialog.c:403 +#: ../thunar/thunar-progress-dialog.c:407 #, c-format msgid "(%lu minute remaining)" msgid_plural "(%lu minutes remaining)" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-progress-dialog.c:408 +#: ../thunar/thunar-progress-dialog.c:412 #, c-format msgid "(%lu second remaining)" msgid_plural "(%lu seconds remaining)" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-properties-dialog.c:259 +#: ../thunar/thunar-properties-dialog.c:261 msgid "General" msgstr "" -#: ../thunar/thunar-properties-dialog.c:283 +#: ../thunar/thunar-properties-dialog.c:285 msgid "Name:" msgstr "" #. #. Second box (kind, open with, link target) #. -#: ../thunar/thunar-properties-dialog.c:308 +#: ../thunar/thunar-properties-dialog.c:310 msgid "Kind:" msgstr "" -#: ../thunar/thunar-properties-dialog.c:330 +#: ../thunar/thunar-properties-dialog.c:332 msgid "Open With:" msgstr "" -#: ../thunar/thunar-properties-dialog.c:344 +#: ../thunar/thunar-properties-dialog.c:346 msgid "Link Target:" msgstr "" #. #. Third box (deleted, modified, accessed) #. -#: ../thunar/thunar-properties-dialog.c:387 +#: ../thunar/thunar-properties-dialog.c:389 msgid "Deleted:" msgstr "" -#: ../thunar/thunar-properties-dialog.c:415 +#: ../thunar/thunar-properties-dialog.c:417 msgid "Accessed:" msgstr "" -#: ../thunar/thunar-properties-dialog.c:453 +#: ../thunar/thunar-properties-dialog.c:455 msgid "Volume:" msgstr "" -#: ../thunar/thunar-properties-dialog.c:477 +#: ../thunar/thunar-properties-dialog.c:479 msgid "Free Space:" msgstr "" #. #. Emblem chooser #. -#: ../thunar/thunar-properties-dialog.c:502 +#: ../thunar/thunar-properties-dialog.c:504 msgid "Emblems" msgstr "" +#. display an error message +#: ../thunar/thunar-properties-dialog.c:658 +#: ../thunar/thunar-standard-view.c:2217 ../thunar/thunar-tree-view.c:1669 +#, c-format +msgid "Failed to rename \"%s\"" +msgstr "" + #. allocate the icon chooser #. allocate the chooser dialog -#: ../thunar/thunar-properties-dialog.c:695 +#: ../thunar/thunar-properties-dialog.c:742 #: ../plugins/thunar-uca/thunar-uca-editor.c:627 #, c-format msgid "Select an Icon for \"%s\"" msgstr "" #. tell the user that we failed to change the icon of the .desktop file -#: ../thunar/thunar-properties-dialog.c:720 +#: ../thunar/thunar-properties-dialog.c:768 #, c-format msgid "Failed to change icon of \"%s\"" msgstr "" #. update the properties dialog title -#: ../thunar/thunar-properties-dialog.c:807 +#: ../thunar/thunar-properties-dialog.c:857 #, c-format msgid "%s - Properties" msgstr "" -#: ../thunar/thunar-renamer-dialog.c:179 ../thunar/thunar-window.c:284 +#: ../thunar/thunar-properties-dialog.c:905 +msgid "broken link" +msgstr "" + +#: ../thunar/thunar-renamer-dialog.c:179 ../thunar/thunar-window.c:288 msgid "_File" msgstr "" -#: ../thunar/thunar-renamer-dialog.c:180 ../thunar/thunar-window.c:286 +#: ../thunar/thunar-renamer-dialog.c:180 ../thunar/thunar-window.c:290 msgid "_Send To" msgstr "" -#: ../thunar/thunar-renamer-dialog.c:181 ../thunar/thunar-standard-view.c:334 +#: ../thunar/thunar-renamer-dialog.c:181 ../thunar/thunar-standard-view.c:337 msgid "File Context Menu" msgstr "" @@ -1901,7 +1699,7 @@ msgstr "" msgid "Clear the file list below" msgstr "" -#: ../thunar/thunar-renamer-dialog.c:185 ../thunar/thunar-window.c:313 +#: ../thunar/thunar-renamer-dialog.c:185 ../thunar/thunar-window.c:317 msgid "_About" msgstr "" @@ -1909,7 +1707,7 @@ msgstr "" msgid "Display information about Thunar Bulk Rename" msgstr "" -#: ../thunar/thunar-renamer-dialog.c:186 ../thunar/thunar-standard-view.c:337 +#: ../thunar/thunar-renamer-dialog.c:186 ../thunar/thunar-standard-view.c:340 msgid "View the properties of the selected file" msgstr "" @@ -1937,7 +1735,7 @@ msgstr "" msgid "Click here to view the documentation for the selected rename operation." msgstr "" -#. TRANSLATORS: You can test this string by temporarily removing thunar-sbr.* from $libdir/thunarx-1/, +#. TRANSLATORS: You can test this string by temporarily removing thunar-sbr.* from $libdir/thunarx-2/, #. * and opening the multi rename dialog by selecting multiple files and pressing F2. #. #: ../thunar/thunar-renamer-dialog.c:633 @@ -2019,17 +1817,7 @@ msgid "" "Do you want to skip this file and continue to rename the remaining files?" msgstr "" -#: ../thunar/thunar-settings.desktop.in.h:1 -msgid "Configure the Thunar file manager" -msgstr "" - -#. set window title and icon -#: ../thunar/thunar-settings.desktop.in.h:2 ../thunar/thunar-window.c:2243 -#: ../Thunar.desktop.in.in.h:2 -msgid "File Manager" -msgstr "" - -#: ../thunar/thunar-shortcuts-model.c:356 +#: ../thunar/thunar-shortcuts-model.c:340 msgid "Desktop" msgstr "" @@ -2045,576 +1833,612 @@ msgid_plural "Add the selected folders to the shortcuts side pane" msgstr[0] "" msgstr[1] "" +#: ../thunar/thunar-shortcuts-view.c:277 +msgid "File System" +msgstr "" + #. append the "Mount Volume" menu action -#: ../thunar/thunar-shortcuts-view.c:842 ../thunar/thunar-tree-view.c:1089 +#: ../thunar/thunar-shortcuts-view.c:810 ../thunar/thunar-tree-view.c:1118 msgid "_Mount Volume" msgstr "" #. append the "Eject Volume" menu action -#: ../thunar/thunar-shortcuts-view.c:852 ../thunar/thunar-tree-view.c:1099 +#: ../thunar/thunar-shortcuts-view.c:820 ../thunar/thunar-tree-view.c:1128 msgid "E_ject Volume" msgstr "" -#. append the "Unmount Volume" menu item -#: ../thunar/thunar-shortcuts-view.c:860 ../thunar/thunar-tree-view.c:1107 -msgid "_Unmount Volume" -msgstr "" - #. append the remove menu item -#: ../thunar/thunar-shortcuts-view.c:932 +#: ../thunar/thunar-shortcuts-view.c:891 msgid "_Remove Shortcut" msgstr "" #. append the rename menu item -#: ../thunar/thunar-shortcuts-view.c:947 +#: ../thunar/thunar-shortcuts-view.c:906 msgid "Re_name Shortcut" msgstr "" -#: ../thunar/thunar-shortcuts-view.c:1215 +#: ../thunar/thunar-shortcuts-view.c:1170 #, c-format msgid "The path \"%s\" does not refer to a directory" msgstr "" #. display an error message to the user -#: ../thunar/thunar-shortcuts-view.c:1234 +#: ../thunar/thunar-shortcuts-view.c:1187 msgid "Failed to add new shortcut" msgstr "" -#. display an error dialog to inform the user -#: ../thunar/thunar-shortcuts-view.c:1352 ../thunar/thunar-tree-view.c:1677 +#: ../thunar/thunar-shortcuts-view.c:1372 +#: ../thunar/thunar-shortcuts-view.c:1409 ../thunar/thunar-tree-view.c:1745 +#: ../thunar/thunar-tree-view.c:1782 #, c-format msgid "Failed to eject \"%s\"" msgstr "" -#. display an error dialog to inform the user -#. display an error dialog -#: ../thunar/thunar-shortcuts-view.c:1442 ../thunar/thunar-tree-view.c:1868 -#, c-format -msgid "Failed to unmount \"%s\"" -msgstr "" - -#: ../thunar/thunar-size-label.c:177 +#: ../thunar/thunar-size-label.c:180 msgid "Click here to stop calculating the total size of the folder." msgstr "" #. tell the user that the operation was canceled -#: ../thunar/thunar-size-label.c:298 +#: ../thunar/thunar-size-label.c:301 msgid "Calculation aborted" msgstr "" #. tell the user that we started calculation -#: ../thunar/thunar-size-label.c:405 +#: ../thunar/thunar-size-label.c:398 msgid "Calculating..." msgstr "" -#: ../thunar/thunar-size-label.c:415 +#: ../thunar/thunar-size-label.c:410 #, c-format msgid "%s Bytes" msgstr "" -#: ../thunar/thunar-size-label.c:507 +#: ../thunar/thunar-size-label.c:502 #, c-format msgid "%u item, totalling %s" msgid_plural "%u items, totalling %s" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-standard-view.c:335 +#: ../thunar/thunar-standard-view.c:338 msgid "Folder Context Menu" msgstr "" -#: ../thunar/thunar-standard-view.c:336 +#: ../thunar/thunar-standard-view.c:339 msgid "Create an empty folder within the current folder" msgstr "" #. append the "Cut" menu action -#: ../thunar/thunar-standard-view.c:338 ../thunar/thunar-tree-view.c:1159 +#: ../thunar/thunar-standard-view.c:341 ../thunar/thunar-tree-view.c:1179 msgid "Cu_t" msgstr "" #. append the "Copy" menu action -#: ../thunar/thunar-standard-view.c:339 ../thunar/thunar-tree-view.c:1171 +#: ../thunar/thunar-standard-view.c:342 ../thunar/thunar-tree-view.c:1191 msgid "_Copy" msgstr "" -#: ../thunar/thunar-standard-view.c:340 +#: ../thunar/thunar-standard-view.c:343 msgid "_Paste" msgstr "" -#: ../thunar/thunar-standard-view.c:340 +#: ../thunar/thunar-standard-view.c:343 msgid "Move or copy files previously selected by a Cut or Copy command" msgstr "" #. append the "Delete" menu action -#: ../thunar/thunar-standard-view.c:341 ../thunar/thunar-tree-view.c:1206 +#: ../thunar/thunar-standard-view.c:344 ../thunar/thunar-tree-view.c:1226 msgid "_Delete" msgstr "" -#: ../thunar/thunar-standard-view.c:342 +#: ../thunar/thunar-standard-view.c:345 msgid "" "Move or copy files previously selected by a Cut or Copy command into the " "selected folder" msgstr "" -#: ../thunar/thunar-standard-view.c:343 +#: ../thunar/thunar-standard-view.c:346 msgid "Select _all Files" msgstr "" -#: ../thunar/thunar-standard-view.c:343 +#: ../thunar/thunar-standard-view.c:346 msgid "Select all files in this window" msgstr "" -#: ../thunar/thunar-standard-view.c:344 +#: ../thunar/thunar-standard-view.c:347 msgid "Select _by Pattern..." msgstr "" -#: ../thunar/thunar-standard-view.c:344 +#: ../thunar/thunar-standard-view.c:347 msgid "Select all files that match a certain pattern" msgstr "" -#: ../thunar/thunar-standard-view.c:345 +#: ../thunar/thunar-standard-view.c:348 msgid "Du_plicate" msgstr "" -#: ../thunar/thunar-standard-view.c:346 ../thunar/thunar-standard-view.c:3426 +#: ../thunar/thunar-standard-view.c:349 ../thunar/thunar-standard-view.c:3468 msgid "Ma_ke Link" msgid_plural "Ma_ke Links" msgstr[0] "" msgstr[1] "" #. append the "Rename" menu action -#: ../thunar/thunar-standard-view.c:347 ../thunar/thunar-tree-view.c:1230 +#: ../thunar/thunar-standard-view.c:350 ../thunar/thunar-tree-view.c:1250 msgid "_Rename..." msgstr "" -#: ../thunar/thunar-standard-view.c:348 +#: ../thunar/thunar-standard-view.c:351 msgid "_Restore" msgstr "" #. add the "Create Document" sub menu action -#: ../thunar/thunar-standard-view.c:610 +#: ../thunar/thunar-standard-view.c:613 msgid "Create _Document" msgstr "" -#: ../thunar/thunar-standard-view.c:1314 +#: ../thunar/thunar-standard-view.c:1310 msgid "Loading folder contents..." msgstr "" -#. ask the user to enter a name for the new empty file -#: ../thunar/thunar-standard-view.c:1802 +#: ../thunar/thunar-standard-view.c:1794 msgid "New Empty File" msgstr "" -#: ../thunar/thunar-standard-view.c:1802 +#: ../thunar/thunar-standard-view.c:1795 msgid "New Empty File..." msgstr "" #. generate a title for the create dialog -#: ../thunar/thunar-standard-view.c:1902 +#: ../thunar/thunar-standard-view.c:1884 #, c-format msgid "Create Document from template \"%s\"" msgstr "" -#: ../thunar/thunar-standard-view.c:2097 +#: ../thunar/thunar-standard-view.c:2083 msgid "Select by Pattern" msgstr "" -#: ../thunar/thunar-standard-view.c:2103 +#: ../thunar/thunar-standard-view.c:2089 msgid "_Select" msgstr "" -#: ../thunar/thunar-standard-view.c:2112 +#: ../thunar/thunar-standard-view.c:2098 msgid "_Pattern:" msgstr "" #. tell the user that the file name provided by the X Direct Save source is invalid -#: ../thunar/thunar-standard-view.c:2549 +#: ../thunar/thunar-standard-view.c:2584 msgid "Invalid filename provided by XDS drag site" msgstr "" #. display an error dialog to the user -#: ../thunar/thunar-standard-view.c:2726 +#: ../thunar/thunar-standard-view.c:2763 #, c-format msgid "Failed to create a link for the URL \"%s\"" msgstr "" -#: ../thunar/thunar-standard-view.c:3059 +#: ../thunar/thunar-standard-view.c:3101 #, c-format msgid "Failed to open directory \"%s\"" msgstr "" -#: ../thunar/thunar-standard-view.c:3386 +#: ../thunar/thunar-standard-view.c:3428 msgid "Prepare the selected file to be moved with a Paste command" msgid_plural "Prepare the selected files to be moved with a Paste command" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-standard-view.c:3394 +#: ../thunar/thunar-standard-view.c:3436 msgid "Prepare the selected file to be copied with a Paste command" msgid_plural "Prepare the selected files to be copied with a Paste command" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-standard-view.c:3405 +#: ../thunar/thunar-standard-view.c:3447 msgid "Delete the selected file" msgid_plural "Delete the selected files" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-standard-view.c:3419 +#: ../thunar/thunar-standard-view.c:3461 msgid "Duplicate the selected file" msgid_plural "Duplicate each selected file" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-standard-view.c:3428 +#: ../thunar/thunar-standard-view.c:3470 msgid "Create a symbolic link for the selected file" msgid_plural "Create a symbolic link for each selected file" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-standard-view.c:3436 +#: ../thunar/thunar-standard-view.c:3478 msgid "Rename the selected file" msgid_plural "Rename the selected files" msgstr[0] "" msgstr[1] "" -#: ../thunar/thunar-standard-view.c:3444 +#: ../thunar/thunar-standard-view.c:3486 msgid "Restore the selected file" msgid_plural "Restore the selected files" msgstr[0] "" msgstr[1] "" -#. tell the user that no templates were found -#: ../thunar/thunar-templates-action.c:397 -msgid "No Templates installed" -msgstr "" - #. add the "Empty File" item -#: ../thunar/thunar-templates-action.c:409 +#: ../thunar/thunar-templates-action.c:505 msgid "_Empty File" msgstr "" -#: ../thunar/thunar-trash-action.c:174 -msgid "T_rash" +#: ../thunar/thunar-transfer-job.c:648 +msgid "Collecting files..." +msgstr "" + +#. update progress information +#: ../thunar/thunar-transfer-job.c:675 +#, c-format +msgid "Trying to restore \"%s\"" +msgstr "" + +#: ../thunar/thunar-transfer-job.c:700 +#, c-format +msgid "" +"The folder \"%s\" does not exist anymore but is required to restore the file " +"\"%s\" from the trash" +msgstr "" + +#: ../thunar/thunar-transfer-job.c:725 +#, c-format +msgid "Failed to restore the folder \"%s\"" +msgstr "" + +#. update progress information +#: ../thunar/thunar-transfer-job.c:742 +#, c-format +msgid "Trying to move \"%s\"" +msgstr "" + +#. update progress information +#: ../thunar/thunar-transfer-job.c:767 +#, c-format +msgid "Could not move \"%s\" directly. Collecting files for copying..." msgstr "" #: ../thunar/thunar-trash-action.c:175 +msgid "T_rash" +msgstr "" + +#: ../thunar/thunar-trash-action.c:176 msgid "Display the contents of the trash can" msgstr "" -#: ../thunar/thunar-tree-model.c:630 +#: ../thunar/thunar-tree-model.c:638 msgid "Loading..." msgstr "" #. append the "Paste Into Folder" menu action -#: ../thunar/thunar-tree-view.c:1188 +#: ../thunar/thunar-tree-view.c:1208 msgid "_Paste Into Folder" msgstr "" #. append the "Properties" menu action -#: ../thunar/thunar-tree-view.c:1289 +#: ../thunar/thunar-tree-view.c:1309 msgid "P_roperties..." msgstr "" +#: ../thunar/thunar-util.c:108 +#, c-format +msgid "Invalid path" +msgstr "" + +#: ../thunar/thunar-util.c:144 +#, c-format +msgid "Unknown user \"%s\"" +msgstr "" + #. TRANSLATORS: file was modified less than one day ago -#: ../thunar/thunar-util.c:119 +#: ../thunar/thunar-util.c:204 msgid "Today" msgstr "" #. TRANSLATORS: file was modified less than one day ago -#: ../thunar/thunar-util.c:124 +#: ../thunar/thunar-util.c:209 #, c-format msgid "Today at %X" msgstr "" #. TRANSLATORS: file was modified less than two days ago -#: ../thunar/thunar-util.c:132 +#: ../thunar/thunar-util.c:217 msgid "Yesterday" msgstr "" #. TRANSLATORS: file was modified less than two days ago -#: ../thunar/thunar-util.c:137 +#: ../thunar/thunar-util.c:222 #, c-format msgid "Yesterday at %X" msgstr "" #. Days from last week -#: ../thunar/thunar-util.c:145 +#: ../thunar/thunar-util.c:230 #, c-format msgid "%A at %X" msgstr "" #. Any other date -#: ../thunar/thunar-util.c:150 +#: ../thunar/thunar-util.c:235 #, c-format msgid "%x at %X" msgstr "" -#: ../thunar/thunar-window.c:285 +#: ../thunar/thunar-window.c:289 msgid "Open New _Window" msgstr "" -#: ../thunar/thunar-window.c:285 +#: ../thunar/thunar-window.c:289 msgid "Open a new Thunar window for the displayed location" msgstr "" -#: ../thunar/thunar-window.c:288 +#: ../thunar/thunar-window.c:292 msgid "Close _All Windows" msgstr "" -#: ../thunar/thunar-window.c:288 +#: ../thunar/thunar-window.c:292 msgid "Close all Thunar windows" msgstr "" -#: ../thunar/thunar-window.c:289 +#: ../thunar/thunar-window.c:293 msgid "_Close" msgstr "" -#: ../thunar/thunar-window.c:289 +#: ../thunar/thunar-window.c:293 msgid "Close this window" msgstr "" -#: ../thunar/thunar-window.c:290 +#: ../thunar/thunar-window.c:294 msgid "_Edit" msgstr "" -#: ../thunar/thunar-window.c:291 +#: ../thunar/thunar-window.c:295 msgid "Pr_eferences..." msgstr "" -#: ../thunar/thunar-window.c:291 +#: ../thunar/thunar-window.c:295 msgid "Edit Thunars Preferences" msgstr "" -#: ../thunar/thunar-window.c:292 +#: ../thunar/thunar-window.c:296 msgid "_View" msgstr "" -#: ../thunar/thunar-window.c:293 +#: ../thunar/thunar-window.c:297 msgid "_Reload" msgstr "" -#: ../thunar/thunar-window.c:293 +#: ../thunar/thunar-window.c:297 msgid "Reload the current folder" msgstr "" -#: ../thunar/thunar-window.c:294 +#: ../thunar/thunar-window.c:298 msgid "_Location Selector" msgstr "" -#: ../thunar/thunar-window.c:295 +#: ../thunar/thunar-window.c:299 msgid "_Side Pane" msgstr "" -#: ../thunar/thunar-window.c:296 +#: ../thunar/thunar-window.c:300 msgid "Zoom I_n" msgstr "" -#: ../thunar/thunar-window.c:296 +#: ../thunar/thunar-window.c:300 msgid "Show the contents in more detail" msgstr "" -#: ../thunar/thunar-window.c:297 +#: ../thunar/thunar-window.c:301 msgid "Zoom _Out" msgstr "" -#: ../thunar/thunar-window.c:297 +#: ../thunar/thunar-window.c:301 msgid "Show the contents in less detail" msgstr "" -#: ../thunar/thunar-window.c:298 +#: ../thunar/thunar-window.c:302 msgid "Normal Si_ze" msgstr "" -#: ../thunar/thunar-window.c:298 +#: ../thunar/thunar-window.c:302 msgid "Show the contents at the normal size" msgstr "" -#: ../thunar/thunar-window.c:299 +#: ../thunar/thunar-window.c:303 msgid "_Go" msgstr "" -#: ../thunar/thunar-window.c:300 +#: ../thunar/thunar-window.c:304 msgid "Open _Parent" msgstr "" -#: ../thunar/thunar-window.c:300 +#: ../thunar/thunar-window.c:304 msgid "Open the parent folder" msgstr "" -#: ../thunar/thunar-window.c:301 +#: ../thunar/thunar-window.c:305 msgid "_Home" msgstr "" -#: ../thunar/thunar-window.c:301 +#: ../thunar/thunar-window.c:305 msgid "Go to the home folder" msgstr "" -#: ../thunar/thunar-window.c:302 +#: ../thunar/thunar-window.c:306 msgid "Go to the desktop folder" msgstr "" -#: ../thunar/thunar-window.c:303 +#: ../thunar/thunar-window.c:307 msgid "Go to the documents folder" msgstr "" -#: ../thunar/thunar-window.c:304 +#: ../thunar/thunar-window.c:308 msgid "Go to the downloads folder" msgstr "" -#: ../thunar/thunar-window.c:305 +#: ../thunar/thunar-window.c:309 msgid "Go to the music folder" msgstr "" -#: ../thunar/thunar-window.c:306 +#: ../thunar/thunar-window.c:310 msgid "Go to the pictures folder" msgstr "" -#: ../thunar/thunar-window.c:307 +#: ../thunar/thunar-window.c:311 msgid "Go to the videos folder" msgstr "" -#: ../thunar/thunar-window.c:308 +#: ../thunar/thunar-window.c:312 msgid "Go to the public folder" msgstr "" -#: ../thunar/thunar-window.c:309 +#: ../thunar/thunar-window.c:313 msgid "T_emplates" msgstr "" -#: ../thunar/thunar-window.c:309 +#: ../thunar/thunar-window.c:313 msgid "Go to the templates folder" msgstr "" -#: ../thunar/thunar-window.c:310 +#: ../thunar/thunar-window.c:314 msgid "_Open Location..." msgstr "" -#: ../thunar/thunar-window.c:310 +#: ../thunar/thunar-window.c:314 msgid "Specify a location to open" msgstr "" -#: ../thunar/thunar-window.c:311 +#: ../thunar/thunar-window.c:315 msgid "_Help" msgstr "" -#: ../thunar/thunar-window.c:312 +#: ../thunar/thunar-window.c:316 msgid "_Contents" msgstr "" -#: ../thunar/thunar-window.c:312 +#: ../thunar/thunar-window.c:316 msgid "Display Thunar user manual" msgstr "" -#: ../thunar/thunar-window.c:313 +#: ../thunar/thunar-window.c:317 msgid "Display information about Thunar" msgstr "" -#: ../thunar/thunar-window.c:318 +#: ../thunar/thunar-window.c:322 msgid "Show _Hidden Files" msgstr "" -#: ../thunar/thunar-window.c:318 +#: ../thunar/thunar-window.c:322 msgid "Toggles the display of hidden files in the current window" msgstr "" -#: ../thunar/thunar-window.c:319 +#: ../thunar/thunar-window.c:323 msgid "_Pathbar Style" msgstr "" -#: ../thunar/thunar-window.c:319 +#: ../thunar/thunar-window.c:323 msgid "Modern approach with buttons that correspond to folders" msgstr "" -#: ../thunar/thunar-window.c:320 +#: ../thunar/thunar-window.c:324 msgid "_Toolbar Style" msgstr "" -#: ../thunar/thunar-window.c:320 +#: ../thunar/thunar-window.c:324 msgid "Traditional approach with location bar and navigation buttons" msgstr "" -#: ../thunar/thunar-window.c:321 +#: ../thunar/thunar-window.c:325 msgid "_Shortcuts" msgstr "" -#: ../thunar/thunar-window.c:321 +#: ../thunar/thunar-window.c:325 msgid "Toggles the visibility of the shortcuts pane" msgstr "" -#: ../thunar/thunar-window.c:322 +#: ../thunar/thunar-window.c:326 msgid "_Tree" msgstr "" -#: ../thunar/thunar-window.c:322 +#: ../thunar/thunar-window.c:326 msgid "Toggles the visibility of the tree pane" msgstr "" -#: ../thunar/thunar-window.c:323 +#: ../thunar/thunar-window.c:327 msgid "St_atusbar" msgstr "" -#: ../thunar/thunar-window.c:323 +#: ../thunar/thunar-window.c:327 msgid "Change the visibility of this window's statusbar" msgstr "" #. #. * add view options #. -#: ../thunar/thunar-window.c:770 +#: ../thunar/thunar-window.c:732 msgid "View as _Icons" msgstr "" -#: ../thunar/thunar-window.c:770 +#: ../thunar/thunar-window.c:732 msgid "Display folder content in an icon view" msgstr "" -#: ../thunar/thunar-window.c:777 +#: ../thunar/thunar-window.c:739 msgid "View as _Detailed List" msgstr "" -#: ../thunar/thunar-window.c:777 +#: ../thunar/thunar-window.c:739 msgid "Display folder content in a detailed list view" msgstr "" -#: ../thunar/thunar-window.c:784 +#: ../thunar/thunar-window.c:746 msgid "View as _Compact List" msgstr "" -#: ../thunar/thunar-window.c:784 +#: ../thunar/thunar-window.c:746 msgid "Display folder content in a compact list view" msgstr "" #. add the label with the root warning -#: ../thunar/thunar-window.c:846 +#: ../thunar/thunar-window.c:808 msgid "Warning, you are using the root account, you may harm your system." msgstr "" -#: ../thunar/thunar-window.c:1870 +#: ../thunar/thunar-window.c:1403 +#, c-format +msgid "Failed to launch \"%s\"" +msgstr "" + +#: ../thunar/thunar-window.c:1876 msgid "Failed to open parent folder" msgstr "" #. display an error to the user -#: ../thunar/thunar-window.c:1896 +#: ../thunar/thunar-window.c:1901 msgid "Failed to open the home folder" msgstr "" -#: ../thunar/thunar-window.c:1951 +#: ../thunar/thunar-window.c:1960 #, c-format msgid "Failed to open folder \"%s\"" msgstr "" #. display the "About Templates" dialog -#: ../thunar/thunar-window.c:2076 +#: ../thunar/thunar-window.c:2074 msgid "About Templates" msgstr "" -#: ../thunar/thunar-window.c:2098 +#: ../thunar/thunar-window.c:2096 msgid "All files in this folder will appear in the \"Create Document\" menu." msgstr "" -#: ../thunar/thunar-window.c:2105 +#: ../thunar/thunar-window.c:2103 msgid "" "If you frequently create certain kinds of documents, make a copy of one and " "put it in this folder. Thunar will add an entry for this document in the " @@ -2624,21 +2448,27 @@ msgid "" "of the document will be created in the directory you are viewing." msgstr "" -#: ../thunar/thunar-window.c:2117 +#: ../thunar/thunar-window.c:2115 msgid "Do _not display this message again" msgstr "" #. display an error to the user -#: ../thunar/thunar-window.c:2162 +#: ../thunar/thunar-window.c:2158 msgid "Failed to display the contents of the trash can" msgstr "" -#: ../thunar/thunar-window.c:2204 +#: ../thunar/thunar-window.c:2200 msgid "" "Thunar is a fast and easy to use file manager\n" "for the Xfce Desktop Environment." msgstr "" +#. set window title and icon +#: ../thunar/thunar-window.c:2239 ../Thunar.desktop.in.in.h:2 +#: ../thunar/thunar-settings.desktop.in.h:2 +msgid "File Manager" +msgstr "" + #: ../thunarx/thunarx-property-page.c:137 msgid "Label" msgstr "" @@ -2836,7 +2666,7 @@ msgstr "" msgid "_At position:" msgstr "" -#: ../plugins/thunar-sbr/thunar-sbr-date-renamer.c:593 +#: ../plugins/thunar-sbr/thunar-sbr-date-renamer.c:602 msgid "Insert Date / Time" msgstr "" @@ -2999,39 +2829,39 @@ msgstr "" msgid "Search & Replace" msgstr "" -#: ../plugins/thunar-sendto-email/main.c:176 +#: ../plugins/thunar-sendto-email/main.c:196 #, c-format msgid "Send \"%s\" as compressed archive?" msgstr "" -#: ../plugins/thunar-sendto-email/main.c:178 -#: ../plugins/thunar-sendto-email/main.c:197 +#: ../plugins/thunar-sendto-email/main.c:199 +#: ../plugins/thunar-sendto-email/main.c:218 msgid "Send _directly" msgstr "" -#: ../plugins/thunar-sendto-email/main.c:179 +#: ../plugins/thunar-sendto-email/main.c:200 msgid "Send com_pressed" msgstr "" -#: ../plugins/thunar-sendto-email/main.c:181 +#: ../plugins/thunar-sendto-email/main.c:202 msgid "" "When sending a file via email, you can either choose to send the file " "directly, as is, or compress the file before attaching it to an email. It is " "highly recommended to compress large files before sending them." msgstr "" -#: ../plugins/thunar-sendto-email/main.c:192 +#: ../plugins/thunar-sendto-email/main.c:213 #, c-format msgid "Send %d file as compressed archive?" msgid_plural "Send %d files as compressed archive?" msgstr[0] "" msgstr[1] "" -#: ../plugins/thunar-sendto-email/main.c:198 +#: ../plugins/thunar-sendto-email/main.c:219 msgid "Send as _archive" msgstr "" -#: ../plugins/thunar-sendto-email/main.c:200 +#: ../plugins/thunar-sendto-email/main.c:221 msgid "" "When sending multiple files via email, you can either choose to send the " "files directly, attaching multiple files to an email, or send all files " @@ -3041,28 +2871,29 @@ msgstr "" #. allocate the progress dialog #. setup the label -#: ../plugins/thunar-sendto-email/main.c:249 -#: ../plugins/thunar-sendto-email/main.c:274 +#: ../plugins/thunar-sendto-email/main.c:270 +#: ../plugins/thunar-sendto-email/main.c:295 msgid "Compressing files..." msgstr "" #. tell the user that the command failed -#: ../plugins/thunar-sendto-email/main.c:299 +#: ../plugins/thunar-sendto-email/main.c:320 #, c-format msgid "ZIP command terminated with error %d" msgstr "" -#: ../plugins/thunar-sendto-email/main.c:385 +#: ../plugins/thunar-sendto-email/main.c:408 msgid "Failed to create temporary directory" msgstr "" -#: ../plugins/thunar-sendto-email/main.c:436 +#: ../plugins/thunar-sendto-email/main.c:470 +#: ../plugins/thunar-sendto-email/main.c:481 #, c-format msgid "Failed to create symbolic link for \"%s\"" msgstr "" #. tell the user that we failed to compress the file(s) -#: ../plugins/thunar-sendto-email/main.c:459 +#: ../plugins/thunar-sendto-email/main.c:505 #, c-format msgid "Failed to compress %d file" msgid_plural "Failed to compress %d files" @@ -3070,7 +2901,7 @@ msgstr[0] "" msgstr[1] "" #. tell the user that we failed -#: ../plugins/thunar-sendto-email/main.c:600 +#: ../plugins/thunar-sendto-email/main.c:656 msgid "Failed to compose new email" msgstr "" @@ -3306,41 +3137,41 @@ msgid "" "files." msgstr "" -#: ../plugins/thunar-uca/thunar-uca-model.c:780 +#: ../plugins/thunar-uca/thunar-uca-model.c:786 #, c-format msgid "Unknown element <%s>" msgstr "" -#: ../plugins/thunar-uca/thunar-uca-model.c:798 +#: ../plugins/thunar-uca/thunar-uca-model.c:804 #, c-format msgid "End element handler called while in root context" msgstr "" -#: ../plugins/thunar-uca/thunar-uca-model.c:886 +#: ../plugins/thunar-uca/thunar-uca-model.c:892 #, c-format msgid "Unknown closing element <%s>" msgstr "" -#: ../plugins/thunar-uca/thunar-uca-model.c:1332 +#: ../plugins/thunar-uca/thunar-uca-model.c:1333 #, c-format msgid "Failed to determine save location for uca.xml" msgstr "" -#: ../plugins/thunar-uca/thunar-uca-model.c:1447 +#: ../plugins/thunar-uca/thunar-uca-model.c:1448 #, c-format msgid "Command not configured" msgstr "" -#: ../plugins/thunar-uca/thunar-uca-provider.c:188 +#: ../plugins/thunar-uca/thunar-uca-provider.c:190 msgid "Configure c_ustom actions..." msgstr "" -#: ../plugins/thunar-uca/thunar-uca-provider.c:189 +#: ../plugins/thunar-uca/thunar-uca-provider.c:191 msgid "" "Setup custom actions that will appear in the file managers context menus" msgstr "" -#: ../plugins/thunar-uca/thunar-uca-provider.c:406 +#: ../plugins/thunar-uca/thunar-uca-provider.c:408 #, c-format msgid "Failed to launch action \"%s\"." msgstr "" @@ -3353,7 +3184,7 @@ msgstr "" msgid "Open Terminal Here" msgstr "" -#: ../plugins/thunar-wallpaper/twp-provider.c:155 +#: ../plugins/thunar-wallpaper/twp-provider.c:161 msgid "Set as wallpaper" msgstr "" @@ -3376,3 +3207,7 @@ msgstr "" #: ../Thunar-folder-handler.desktop.in.in.h:3 msgid "Open the specified folders in Thunar" msgstr "" + +#: ../thunar/thunar-settings.desktop.in.h:1 +msgid "Configure the Thunar file manager" +msgstr "" diff --git a/tests/Makefile.am b/tests/Makefile.am deleted file mode 100644 index 42cb9b38a..000000000 --- a/tests/Makefile.am +++ /dev/null @@ -1,32 +0,0 @@ -# $Id$ - -SUBDIRS = \ - data - -INCLUDES = \ - -I$(top_srcdir) \ - -DEXO_DISABLE_DEPRECATED \ - -DG_LOG_DOMAIN=\"tests\" \ - $(EXO_CFLAGS) \ - $(GTHREAD_CFLAGS) - -TESTS = \ - test-thunar-vfs-path - -check_PROGRAMS = \ - test-thunar-vfs-path - -test_thunar_vfs_path_SOURCES = \ - test-thunar-vfs-path.c - -test_thunar_vfs_path_DEPENDENCIES = \ - $(top_builddir)/thunar-vfs/libthunar-vfs-$(THUNAR_VERSION_API).la - -test_thunar_vfs_path_LDADD = \ - $(GTHREAD_LIBS) \ - $(top_builddir)/thunar-vfs/libthunar-vfs-$(THUNAR_VERSION_API).la - -clean-local: - rm -f *.core core core.* - -# vi:set ts=8 sw=8 noet ai nocindent syntax=automake: diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am deleted file mode 100644 index aa27a7e28..000000000 --- a/tests/data/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -# $Id$ - -noinst_DATA = \ - test-thunar-vfs-volume-bsd.fstab - -EXTRA_DIST = \ - $(noinst_DATA) - -# vi:set ts=8 sw=8 noet ai nocindent syntax=automake: diff --git a/tests/data/test-thunar-vfs-volume-bsd.fstab b/tests/data/test-thunar-vfs-volume-bsd.fstab deleted file mode 100644 index 0f0e60262..000000000 --- a/tests/data/test-thunar-vfs-volume-bsd.fstab +++ /dev/null @@ -1,4 +0,0 @@ -/dev/ad8s1e /usr ufs rw 2 2 -/dev/da4s2f /usr/bin ufs rw 2 2 -/dev/cd5 /usr/lib cd9660 ro 0 0 -/dev/ad4s7b none swap sw 0 0 diff --git a/tests/test-thunar-vfs-path.c b/tests/test-thunar-vfs-path.c deleted file mode 100644 index 1ee89e45c..000000000 --- a/tests/test-thunar-vfs-path.c +++ /dev/null @@ -1,128 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * 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., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#include <thunar-vfs/thunar-vfs.h> - - - -int -main (int argc, char **argv) -{ - ThunarVfsPath *a; - ThunarVfsPath *b; - gchar buffer[THUNAR_VFS_PATH_MAXURILEN]; - gchar *s; - gint n; - - /* initialize GThreads (required for Thunar-VFS initialization) */ - if (!g_thread_supported ()) - g_thread_init (NULL); - - /* initialize Gtk+ (required for Thunar-VFS initialization) */ - gtk_init (&argc, &argv); - - /* initialize the thunar-vfs library */ - thunar_vfs_init (); - - /* verify the root path */ - a = thunar_vfs_path_new ("/", NULL); - b = thunar_vfs_path_get_for_root (); - s = thunar_vfs_path_dup_string (a); - n = thunar_vfs_path_to_string (b, buffer, sizeof (buffer), NULL); - g_assert (a == b); - g_assert (thunar_vfs_path_equal (a, b)); - g_assert (thunar_vfs_path_get_parent (a) == NULL); - g_assert (thunar_vfs_path_get_parent (b) == NULL); - g_assert (thunar_vfs_path_hash (a) == thunar_vfs_path_hash (b)); - g_assert (strcmp (s, buffer) == 0); - g_assert (strcmp (s, "/") == 0); - g_assert (n == strlen (buffer) + 1); - thunar_vfs_path_unref (b); - thunar_vfs_path_unref (a); - g_free (s); - - /* verify the home path */ - a = thunar_vfs_path_new (xfce_get_homedir (), NULL); - b = thunar_vfs_path_get_for_home (); - s = thunar_vfs_path_dup_uri (a); - n = thunar_vfs_path_to_uri (b, buffer, sizeof (buffer), NULL); - g_assert (a == b); - g_assert (thunar_vfs_path_equal (a, b)); - g_assert (thunar_vfs_path_hash (a) == thunar_vfs_path_hash (b)); - g_assert (strcmp (s, buffer) == 0); - g_assert (strncmp (s, "file:///", 8) == 0); - g_assert (n == strlen (buffer) + 1); - thunar_vfs_path_unref (b); - thunar_vfs_path_unref (a); - g_free (s); - - /* verify the URI handling */ - a = thunar_vfs_path_new ("/%test ", NULL); - b = thunar_vfs_path_new ("file:///%25test%20//", NULL); - s = thunar_vfs_path_dup_uri (a); - n = thunar_vfs_path_to_string (b, buffer, sizeof (buffer), NULL); - g_assert (thunar_vfs_path_equal (a, b)); - g_assert (thunar_vfs_path_hash (a) == thunar_vfs_path_hash (b)); - g_assert (strcmp (s, "file:///%25test%20") == 0); - g_assert (strcmp (buffer, "/%test ") == 0); - g_assert (n == strlen (buffer) + 1); - thunar_vfs_path_unref (b); - thunar_vfs_path_unref (a); - g_free (s); - - /* verify the thunar_vfs_path_relative method */ - a = thunar_vfs_path_get_for_home (); - b = thunar_vfs_path_get_parent (a); - g_assert (b != NULL); - thunar_vfs_path_ref (b); - thunar_vfs_path_unref (a); - s = g_path_get_basename (xfce_get_homedir ()); - a = thunar_vfs_path_relative (b, s); - thunar_vfs_path_unref (b); - g_free (s); - b = thunar_vfs_path_get_for_home (); - s = thunar_vfs_path_dup_string (a); - g_assert (a == b); - g_assert (thunar_vfs_path_equal (a, b)); - g_assert (thunar_vfs_path_hash (a) == thunar_vfs_path_hash (b)); - g_assert (strcmp (s, xfce_get_homedir ()) == 0); - thunar_vfs_path_unref (b); - thunar_vfs_path_unref (a); - g_free (s); - - /* shutdown the Thunar-VFS library */ - thunar_vfs_shutdown (); - - return EXIT_SUCCESS; -} - diff --git a/tests/test-thunar-vfs-uri.c b/tests/test-thunar-vfs-uri.c deleted file mode 100644 index a3656b87a..000000000 --- a/tests/test-thunar-vfs-uri.c +++ /dev/null @@ -1,82 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * 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., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#include <thunar-vfs/thunar-vfs.h> - - - -int -main (int argc, char **argv) -{ - ThunarVfsURI *a; - ThunarVfsURI *b; - - g_type_init (); - - /* perform simple validation on "file:///" */ - a = thunar_vfs_uri_new_for_path ("/"); - g_assert (thunar_vfs_uri_is_root (a)); - g_assert (exo_str_is_equal (thunar_vfs_uri_get_name (a), "/")); - g_assert (exo_str_is_equal (thunar_vfs_uri_get_path (a), "/")); - g_assert (thunar_vfs_uri_parent (a) == NULL); - g_assert (exo_str_is_equal (thunar_vfs_uri_to_string (a), "file:///")); - - /* verify that URI parsing works */ - a = thunar_vfs_uri_new_for_path ("/tmp"); - b = thunar_vfs_uri_new ("file:///tmp", NULL); - g_assert (thunar_vfs_uri_equal (a, b)); - g_assert (thunar_vfs_uri_hash (a) == thunar_vfs_uri_hash (b)); - - /* verify thunar_vfs_uri_relative */ - a = thunar_vfs_uri_new_for_path ("/usr"); - b = thunar_vfs_uri_relative (a, "bin"); - g_assert (!thunar_vfs_uri_equal (a, b)); - g_assert (thunar_vfs_uri_equal (a, thunar_vfs_uri_parent (b))); - g_assert (exo_str_is_equal (thunar_vfs_uri_to_string (a), "file:///usr")); - g_assert (exo_str_is_equal (thunar_vfs_uri_to_string (b), "file:///usr/bin")); - - /* verify that trash:// uris work */ - a = thunar_vfs_uri_new ("trash:", NULL); - b = thunar_vfs_uri_new ("trash://", NULL); - g_assert (thunar_vfs_uri_equal (a, b)); - a = thunar_vfs_uri_new ("trash:///", NULL); - g_assert (thunar_vfs_uri_equal (a, b)); - b = thunar_vfs_uri_new ("trash:///file", NULL); - g_assert (!thunar_vfs_uri_equal (a, b)); - b = thunar_vfs_uri_parent (b); - g_assert (thunar_vfs_uri_equal (a, b)); - g_assert (exo_str_is_equal (thunar_vfs_uri_to_string (a), "trash:///")); - - /* verify thunar_vfs_uri_to_string */ - a = thunar_vfs_uri_new ("file:///a ", NULL); - b = thunar_vfs_uri_new ("file:///b+", NULL); - g_assert (exo_str_is_equal (thunar_vfs_uri_to_string (a), "file:///a%20")); - g_assert (exo_str_is_equal (thunar_vfs_uri_to_string (b), "file:///b%2B")); - - return EXIT_SUCCESS; -} - diff --git a/thunar-vfs/Makefile.am b/thunar-vfs/Makefile.am deleted file mode 100644 index b07e3c41c..000000000 --- a/thunar-vfs/Makefile.am +++ /dev/null @@ -1,365 +0,0 @@ -# $Id$ - -INCLUDES = \ - -I$(top_srcdir) \ - -DEXO_DISABLE_DEPRECATED \ - -DG_LOG_DOMAIN=\"thunar-vfs\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \ - -DSN_API_NOT_YET_FROZEN \ - -DTHUNAR_VFS_COMPILATION \ - -DTHUNAR_VFS_VERSION_API=\"$(THUNAR_VERSION_API)\" \ - $(PLATFORM_CPPFLAGS) - -lib_LTLIBRARIES = \ - libthunar-vfs-1.la - -libthunar_vfs_headers = \ - thunar-vfs-config.h \ - thunar-vfs-info.h \ - thunar-vfs-interactive-job.h \ - thunar-vfs-job.h \ - thunar-vfs-mime-action.h \ - thunar-vfs-mime-application.h \ - thunar-vfs-mime-database.h \ - thunar-vfs-mime-handler.h \ - thunar-vfs-mime-info.h \ - thunar-vfs-monitor.h \ - thunar-vfs-path.h \ - thunar-vfs-thumb.h \ - thunar-vfs-types.h \ - thunar-vfs-user.h \ - thunar-vfs-util.h \ - thunar-vfs-volume.h - -libthunar_vfs_io_sources = \ - thunar-vfs-io-jobs.c \ - thunar-vfs-io-jobs.h \ - thunar-vfs-io-local.c \ - thunar-vfs-io-local.h \ - thunar-vfs-io-local-xfer.c \ - thunar-vfs-io-local-xfer.h \ - thunar-vfs-io-ops.c \ - thunar-vfs-io-ops.h \ - thunar-vfs-io-scandir.c \ - thunar-vfs-io-scandir.h \ - thunar-vfs-io-trash.c \ - thunar-vfs-io-trash.h - -libthunar_vfs_os_sources = \ - thunar-vfs-os.h -if THUNAR_VFS_OS_IMPL_BSD -libthunar_vfs_os_sources += \ - thunar-vfs-os-bsd.c -else -libthunar_vfs_os_sources += \ - thunar-vfs-os-generic.c -endif - -libthunar_vfs_public_built_sources = \ - thunar-vfs-enum-types.h - -libthunar_vfs_built_sources = \ - $(libthunar_vfs_public_built_sources) \ - thunar-vfs-alias.h \ - thunar-vfs-aliasdef.c \ - thunar-vfs-enum-types.c \ - thunar-vfs-marshal.c \ - thunar-vfs-marshal.h - -libthunar_vfs_includedir = \ - $(includedir)/thunar-vfs-$(THUNAR_VERSION_API)/thunar-vfs -libthunar_vfs_include_HEADERS = \ - $(libthunar_vfs_headers) \ - $(libthunar_vfs_public_built_sources) \ - thunar-vfs.h - -libthunar_vfs_1_la_SOURCES = \ - $(libthunar_vfs_volume_impl_sources) \ - $(libthunar_vfs_built_sources) \ - $(libthunar_vfs_io_sources) \ - $(libthunar_vfs_os_sources) \ - $(libthunar_vfs_headers) \ - thunar-vfs-config.c \ - thunar-vfs-deep-count-job.c \ - thunar-vfs-deep-count-job.h \ - thunar-vfs-exec.c \ - thunar-vfs-exec.h \ - thunar-vfs-info.c \ - thunar-vfs-interactive-job.c \ - thunar-vfs-job.c \ - thunar-vfs-job-private.h \ - thunar-vfs-mime-action-private.h \ - thunar-vfs-mime-action.c \ - thunar-vfs-mime-application.c \ - thunar-vfs-mime-cache.c \ - thunar-vfs-mime-cache.h \ - thunar-vfs-mime-database.c \ - thunar-vfs-mime-database-private.h \ - thunar-vfs-mime-handler-private.h \ - thunar-vfs-mime-handler.c \ - thunar-vfs-mime-info.c \ - thunar-vfs-mime-legacy.c \ - thunar-vfs-mime-legacy.h \ - thunar-vfs-mime-parser.h \ - thunar-vfs-mime-parser.c \ - thunar-vfs-mime-provider.c \ - thunar-vfs-mime-provider.h \ - thunar-vfs-mime-sniffer.c \ - thunar-vfs-mime-sniffer.h \ - thunar-vfs-monitor.c \ - thunar-vfs-monitor-private.h \ - thunar-vfs-path-private.h \ - thunar-vfs-path.c \ - thunar-vfs-private.c \ - thunar-vfs-private.h \ - thunar-vfs-simple-job.c \ - thunar-vfs-simple-job.h \ - thunar-vfs-thumb-jpeg.c \ - thunar-vfs-thumb-jpeg.h \ - thunar-vfs-thumb-private.h \ - thunar-vfs-thumb.c \ - thunar-vfs-transfer-job.c \ - thunar-vfs-transfer-job.h \ - thunar-vfs-user.c \ - thunar-vfs-util.c \ - thunar-vfs-volume.c \ - thunar-vfs-volume-manager.c \ - thunar-vfs-volume-private.h \ - thunar-vfs.c - -libthunar_vfs_1_la_CFLAGS = \ - $(EXO_CFLAGS) \ - $(GTHREAD_CFLAGS) \ - $(LIBFAM_CFLAGS) \ - $(LIBJPEG_CFLAGS) \ - $(LIBPNG_CFLAGS) \ - $(LIBSTARTUP_NOTIFICATION_CFLAGS) \ - $(PLATFORM_CFLAGS) - -libthunar_vfs_1_la_LDFLAGS = \ - -export-dynamic \ - -export-symbols-regex "^[^_].*" \ - -version-info $(THUNAR_VERINFO) \ - $(PLATFORM_LDFLAGS) - -libthunar_vfs_1_la_LIBADD = \ - $(EXO_LIBS) \ - $(GTHREAD_LIBS) \ - $(LIBFAM_LIBS) \ - $(LIBJPEG_LIBS) \ - $(LIBPNG_LIBS) \ - $(LIBSTARTUP_NOTIFICATION_LIBS) - -libexec_PROGRAMS = \ - thunar-vfs-mime-cleaner-1 \ - thunar-vfs-pixbuf-thumbnailer-1 \ - thunar-vfs-update-thumbnailers-cache-1 - -thunar_vfs_mime_cleaner_1_SOURCES = \ - thunar-vfs-mime-cleaner.c - -thunar_vfs_mime_cleaner_1_CFLAGS = \ - $(LIBXFCE4UTIL_CFLAGS) \ - $(PLATFORM_CFLAGS) - -thunar_vfs_mime_cleaner_1_LDADD = \ - $(LIBXFCE4UTIL_LIBS) - -thunar_vfs_mime_cleaner_1_LDFLAGS = \ - -no-undefined \ - $(PLATFORM_LDFLAGS) - -thunar_vfs_pixbuf_thumbnailer_1_SOURCES = \ - thunar-vfs-pixbuf-thumbnailer.c - -thunar_vfs_pixbuf_thumbnailer_1_CFLAGS = \ - $(EXO_CFLAGS) \ - $(PLATFORM_CFLAGS) - -thunar_vfs_pixbuf_thumbnailer_1_LDADD = \ - $(EXO_LIBS) - -thunar_vfs_pixbuf_thumbnailer_1_LDFLAGS = \ - -no-undefined \ - $(PLATFORM_LDFLAGS) - -thunar_vfs_update_thumbnailers_cache_1_SOURCES = \ - thunar-vfs-update-thumbnailers-cache.c - -thunar_vfs_update_thumbnailers_cache_1_CFLAGS = \ - $(GCONF_CFLAGS) \ - $(GDK_PIXBUF_CFLAGS) \ - $(LIBXFCE4UTIL_CFLAGS) \ - $(PLATFORM_CFLAGS) - -thunar_vfs_update_thumbnailers_cache_1_LDADD = \ - $(GCONF_LIBS) \ - $(GDK_PIXBUF_LIBS) \ - $(LIBXFCE4UTIL_LIBS) - -thunar_vfs_update_thumbnailers_cache_1_LDFLAGS = \ - -no-undefined \ - $(PLATFORM_LDFLAGS) - -## -## The font thumbnailer can only be built if freetype 2.x is available, -## because there's not really a way to make it work w/o freetype. -## -if HAVE_FREETYPE -libexec_PROGRAMS += \ - thunar-vfs-font-thumbnailer-1 - -thunar_vfs_font_thumbnailer_1_SOURCES = \ - thunar-vfs-font-thumbnailer.c - -thunar_vfs_font_thumbnailer_1_CFLAGS = \ - $(FREETYPE_CFLAGS) \ - $(GDK_PIXBUF_CFLAGS) \ - $(PLATFORM_CFLAGS) - -thunar_vfs_font_thumbnailer_1_LDADD = \ - $(FREETYPE_LIBS) \ - $(GDK_PIXBUF_LIBS) - -thunar_vfs_font_thumbnailer_1_LDFLAGS = \ - -no-undefined \ - $(PLATFORM_LDFLAGS) -endif - -desktopdir = $(datadir)/thumbnailers -desktop_in_files = \ - thunar-vfs-font-thumbnailer-1.desktop.in -%.desktop: %.desktop.in - sed -e "s,\@libexecdir\@,$(libexecdir),g" < $< > $@ -desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = thunar-vfs-1.pc - -CLEANFILES = \ - actual-abi \ - expected-abi \ - xgen-tvetc \ - xgen-tveth \ - xgen-tvmc \ - xgen-tvmh \ - $(desktop_DATA) - -EXTRA_DIST = \ - abicheck.sh \ - make-thunar-vfs-alias.pl \ - thunar-vfs.symbols \ - thunar-vfs-alias.h \ - thunar-vfs-aliasdef.c \ - thunar-vfs-marshal.list \ - thunar-vfs-volume-freebsd.c \ - thunar-vfs-volume-freebsd.h \ - thunar-vfs-volume-hal.c \ - thunar-vfs-volume-hal.h \ - thunar-vfs-volume-none.c \ - thunar-vfs-volume-none.h \ - $(desktop_in_files) - -if THUNAR_VFS_VOLUME_IMPL_FREEBSD -libthunar_vfs_volume_impl_sources = \ - thunar-vfs-volume-freebsd.c \ - thunar-vfs-volume-freebsd.h -endif - -if THUNAR_VFS_VOLUME_IMPL_HAL -libthunar_vfs_volume_impl_sources = \ - thunar-vfs-volume-hal.c \ - thunar-vfs-volume-hal.h - -libthunar_vfs_1_la_CFLAGS += \ - $(EXO_HAL_CFLAGS) \ - $(HAL_CFLAGS) \ - $(HAL_DBUS_CFLAGS) - -libthunar_vfs_1_la_LIBADD += \ - $(EXO_HAL_LIBS) \ - $(HAL_LIBS) \ - $(HAL_DBUS_LIBS) -endif - -if THUNAR_VFS_VOLUME_IMPL_NONE -libthunar_vfs_volume_impl_sources = \ - thunar-vfs-volume-none.c \ - thunar-vfs-volume-none.h -endif - -## -## Rules to auto-generate built sources -## -## This is a bit tricky with automake, and non-trivial to implement. The -## rules below seem to work fine and don't seem to break the build, but -## they are only enabled in maintainer mode, so arbitrary users don't get -## trapped in automake's oddities. Therefore we ship the autogenerated -## files as part of the dist tarball. -## -if MAINTAINER_MODE -DISTCLEANFILES = \ - stamp-thunar-vfs-enum-types.h \ - stamp-thunar-vfs-marshal.h \ - thunar-vfs-font-thumbnailer-1.desktop \ - $(libthunar_vfs_built_sources) - -BUILT_SOURCES = \ - $(libthunar_vfs_built_sources) - -if HAVE_GNUC_VISIBILITY -TESTS = \ - abicheck.sh -endif - -thunar-vfs-alias.h: make-thunar-vfs-alias.pl thunar-vfs.symbols - $(PERL) $(srcdir)/make-thunar-vfs-alias.pl < $(srcdir)/thunar-vfs.symbols > thunar-vfs-alias.h - -thunar-vfs-aliasdef.c: make-thunar-vfs-alias.pl thunar-vfs.symbols - $(PERL) $(srcdir)/make-thunar-vfs-alias.pl -def < $(srcdir)/thunar-vfs.symbols > thunar-vfs-aliasdef.c - -thunar-vfs-enum-types.h: stamp-thunar-vfs-enum-types.h - @true -stamp-thunar-vfs-enum-types.h: $(libthunar_vfs_headers) Makefile - ( cd $(srcdir) && glib-mkenums \ - --fhead "#ifndef __THUNAR_VFS_ENUM_TYPES_H__\n#define __THUNAR_VFS_ENUM_TYPES_H__\n#include <exo/exo.h>\nG_BEGIN_DECLS\n" \ - --fprod "/* enumerations from \"@filename@\" */\n" \ - --vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define THUNAR_VFS_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ - --ftail "G_END_DECLS\n\n#endif /* !__THUNAR_VFS_ENUM_TYPES_H__ */" \ - $(libthunar_vfs_headers) ) >> xgen-tveth \ - && ( cmp -s xgen-tveth thunar-vfs-enum-types.h || cp xgen-tveth thunar-vfs-enum-types.h ) \ - && rm -f xgen-tveth \ - && echo timestamp > $(@F) -thunar-vfs-enum-types.c: $(libthunar_vfs_headers) Makefile - ( cd $(srcdir) && glib-mkenums \ - --fhead "#undef GTK_DISABLE_DEPRECATED\n#define GTK_ENABLE_BROKEN\n#include <thunar-vfs/thunar-vfs.h>\n#include <thunar-vfs/thunar-vfs-alias.h>" \ - --fprod "\n/* enumerations from \"@filename@\" */" \ - --vhead "GType\n@enum_name@_get_type (void)\n{\n\tstatic GType type = 0;\n\tif (type == 0) {\n\tstatic const G@Type@Value values[] = {"\ - --vprod "\t{ @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ - --vtail "\t{ 0, NULL, NULL }\n\t};\n\ttype = g_@type@_register_static (\"@EnumName@\", values);\n }\n\treturn type;\n}\n" \ - --ftail "\n#define __THUNAR_VFS_ENUM_TYPES_C__\n#include \"thunar-vfs-aliasdef.c\"\n" \ - $(libthunar_vfs_headers) ) >> xgen-tvetc \ - && cp xgen-tvetc thunar-vfs-enum-types.c \ - && rm -f xgen-tvetc - -thunar-vfs-marshal.h: stamp-thunar-vfs-marshal.h - @true -stamp-thunar-vfs-marshal.h: thunar-vfs-marshal.list Makefile - ( cd $(srcdir) && glib-genmarshal \ - --prefix=_thunar_vfs_marshal \ - --header thunar-vfs-marshal.list \ - | sed -e 's/marshal_data);$$/marshal_data) G_GNUC_INTERNAL;/' ) >> xgen-tvmh \ - && ( cmp -s xgen-tvmh thunar-vfs-marshal.h || cp xgen-tvmh thunar-vfs-marshal.h ) \ - && rm -f xgen-tvmh \ - && echo timestamp > $(@F) - -thunar-vfs-marshal.c: thunar-vfs-marshal.list Makefile - ( cd $(srcdir) && glib-genmarshal \ - --prefix=_thunar_vfs_marshal \ - --body thunar-vfs-marshal.list ) >> xgen-tvmc \ - && cp xgen-tvmc thunar-vfs-marshal.c \ - && rm -f xgen-tvmc -endif - -# vi:set ts=8 sw=8 noet ai nocindent syntax=automake: diff --git a/thunar-vfs/abicheck.sh b/thunar-vfs/abicheck.sh deleted file mode 100755 index 256d9147b..000000000 --- a/thunar-vfs/abicheck.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2004 The GLib Development Team. -# Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. -# - -cpp -P -DINCLUDE_INTERNAL_SYMBOLS -DALL_FILES ${srcdir:-.}/thunar-vfs.symbols | sed -e '/^$/d' -e 's/ G_GNUC.*$//' -e 's/ PRIVATE//' | sort > expected-abi -nm -D .libs/libthunar-vfs-1.so | grep " R\|T " | cut -d ' ' -f 3 | grep -v '^_.*' | sort > actual-abi -diff -u expected-abi actual-abi && rm expected-abi actual-abi diff --git a/thunar-vfs/make-thunar-vfs-alias.pl b/thunar-vfs/make-thunar-vfs-alias.pl deleted file mode 100755 index 566ba6d66..000000000 --- a/thunar-vfs/make-thunar-vfs-alias.pl +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env perl -w -# -# Copyright (c) 2004 The GLib Development Team. -# Copyright (c) 2005 Benedikt Meurer <benny@xfce.org>. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. -# - -my $option_def = 0; - -if (($#ARGV >= 0) && ($ARGV[0] eq "-def")) - { - shift; - $option_def = 1; - } - -print <<EOF; -/* Generated by make-thunar-vfs-alias.pl. Do not edit this file. */ - -#ifdef HAVE_GNUC_VISIBILITY - -#include <glib.h> - -EOF - -if ($option_def) - { - print <<EOF -#undef IN_HEADER -#define IN_HEADER(x) 1 - -#undef IN_SOURCE -#define IN_SOURCE defined - -EOF - } -else - { - print <<EOF -#define IN_HEADER defined -#define IN_SOURCE(x) 1 - -EOF - } - -my $in_comment = 0; -my $in_skipped_section = 0; - -while (<>) - { - # ignore empty lines - next if /^\s*$/; - - # skip comments - if ($_ =~ /^\s*\/\*/) - { - $in_comment = 1; - } - - if ($in_comment) - { - if ($_ =~ /\*\/\s$/) - { - $in_comment = 0; - } - next; - } - - # handle ifdefs - if ($_ =~ /^\#endif/) - { - if (!$in_skipped_section) - { - print $_; - } - - $in_skipped_section = 0; - next; - } - - if ($_ =~ /^\#ifdef\s+(INCLUDE_VARIABLES|INCLUDE_INTERNAL_SYMBOLS|ALL_FILES)/) - { - $in_skipped_section = 1; - } - - if ($in_skipped_section) - { - next; - } - - if ($_ =~ /^\#ifn?def\s+G/) - { - print $_; - next; - } - - if ($_ =~ /^\#if.*(IN_SOURCE|IN_HEADER)/) - { - print $_; - next; - } - - chop; - my $line = $_; - my @words; - my $attributes = ""; - - @words = split (/ /, $line); - my $symbol = shift (@words); - chomp ($symbol); - my $alias = "IA__".$symbol; - - # Drop any Win32 specific .def file syntax, but keep attributes - foreach $word (@words) - { - $attributes = "$attributes $word" unless $word eq "PRIVATE"; - } - - if (!$option_def) - { - print <<EOF -extern __typeof ($symbol) $alias __attribute((visibility("hidden")))$attributes; -\#define $symbol $alias - -EOF - } - else - { - print <<EOF -\#undef $symbol -extern __typeof ($symbol) $symbol __attribute((alias("$alias"), visibility("default"))); - -EOF - } - } - -print <<EOF; - -#endif /* HAVE_GNUC_VISIBILITY */ -EOF - - diff --git a/thunar-vfs/thunar-vfs-1.pc.in b/thunar-vfs/thunar-vfs-1.pc.in deleted file mode 100644 index 67879703c..000000000 --- a/thunar-vfs/thunar-vfs-1.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: thunar-vfs -Description: ThunarVFS library -Requires: exo-1 gthread-2.0 -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lthunar-vfs-@THUNAR_VERSION_API@ -Cflags: -I${includedir}/thunar-vfs-@THUNAR_VERSION_API@ diff --git a/thunar-vfs/thunar-vfs-config.c b/thunar-vfs/thunar-vfs-config.c deleted file mode 100644 index 16f02db0a..000000000 --- a/thunar-vfs/thunar-vfs-config.c +++ /dev/null @@ -1,126 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <thunar-vfs/thunar-vfs-config.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/** - * thunar_vfs_major_version: - * - * The major version number of the - * <systemitem class="library">thunar-vfs</systemitem> library (e.g. in - * version 0.5.1 this is 0). - * - * This variable is in the library, so represents the - * <systemitem class="library">thunar-vfs</systemitem> library you have - * linked against. Contrast with the #THUNAR_VFS_MAJOR_VERSION macro, which - * represents the major version of the - * <systemitem class="library">thunar-vfs</systemitem> headers you have - * included. - **/ -const guint thunar_vfs_major_version = THUNAR_VFS_MAJOR_VERSION; - - - -/** - * thunar_vfs_minor_version: - * - * The minor version number of the - * <systemitem class="library">thunar-vfs</systemitem> library (e.g. in - * version 0.5.1 this is 5). - * - * This variable is in the library, so represents the - * <systemitem class="library">thunar-vfs</systemitem> library you have - * linked against. Contrast with the #THUNAR_VFS_MINOR_VERSION macro, which - * represents the minor version of the - * <systemitem class="library">thunar-vfs</systemitem> headers you have - * included. - **/ -const guint thunar_vfs_minor_version = THUNAR_VFS_MINOR_VERSION; - - - -/** - * thunar_vfs_micro_version: - * - * The micro version number of the - * <systemitem class="library">thunar-vfs</systemitem> library (e.g. in - * version 0.5.1 this is 1). - * - * This variable is in the library, so represents the - * <systemitem class="library">thunar-vfs</systemitem> library you have - * linked against. Contrast with the #THUNAR_VFS_MICRO_VERSION macro, which - * represents the micro version of the - * <systemitem class="library">thunar-vfs</systemitem> headers you have - * included. - **/ -const guint thunar_vfs_micro_version = THUNAR_VFS_MICRO_VERSION; - - - -/** - * thunar_vfs_check_version: - * @required_major : the required major version. - * @required_minor : the required minor version. - * @required_micro : the required micro version. - * - * Checks that the <systemitem class="library">thunar-vfs</systemitem> library - * in use is compatible with the given version. Generally you would pass in - * the constants #THUNAR_VFS_MAJOR_VERSION, #THUNAR_VFS_MINOR_VERSION and - * #THUNAR_VFS_VERSION_MICRO as the three arguments to this function; that produces - * a check that the library in use is compatible with the version of - * <systemitem class="library">thunar-vfs</systemitem> the extension was - * compiled against. - * - * <example> - * <title>Checking the runtime version of the Thunar VFS library</title> - * <programlisting> - * const gchar *mismatch; - * mismatch = thunar_vfs_check_version (THUNAR_VFS_VERSION_MAJOR, - * THUNAR_VFS_VERSION_MINOR, - * THUNAR_VFS_VERSION_MICRO); - * if (G_UNLIKELY (mismatch != NULL)) - * g_error ("Version mismatch: %<!---->s", mismatch); - * </programlisting> - * </example> - * - * Return value: %NULL if the library is compatible with the given version, - * or a string describing the version mismatch. The returned - * string is owned by the library and must not be freed or - * modified by the caller. - **/ -const gchar* -thunar_vfs_check_version (guint required_major, - guint required_minor, - guint required_micro) -{ - return NULL; -} - - - -#define __THUNAR_VFS_CONFIG_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-config.h.in b/thunar-vfs/thunar-vfs-config.h.in deleted file mode 100644 index b172bd925..000000000 --- a/thunar-vfs/thunar-vfs-config.h.in +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_CONFIG_H__ -#define __THUNAR_VFS_CONFIG_H__ - -#include <exo/exo.h> - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -G_BEGIN_DECLS; - -/* verify that G_GNUC_WARN_UNUSED_RESULT is defined */ -#if !defined(G_GNUC_WARN_UNUSED_RESULT) -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -#define G_GNUC_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -#define G_GNUC_WARN_UNUSED_RESULT -#endif /* __GNUC__ */ -#endif /* !defined(G_GNUC_WARN_UNUSED_RESULT) */ - -#define THUNAR_VFS_MAJOR_VERSION @THUNAR_VERSION_MAJOR@ -#define THUNAR_VFS_MINOR_VERSION @THUNAR_VERSION_MINOR@ -#define THUNAR_VFS_MICRO_VERSION @THUNAR_VERSION_MICRO@ - -#define THUNAR_VFS_CHECK_VERSION(major,minor,micro) \ - (THUNAR_VFS_MAJOR_VERSION > (major) \ - || (THUNAR_VFS_MAJOR_VERSION == (major) \ - && THUNAR_VFS_MINOR_VERSION > (minor)) \ - || (THUNAR_VFS_MAJOR_VERSION == (major) \ - && THUNAR_VFS_MINOR_VERSION == (minor) \ - && THUNAR_VFS_MICRO_VERSION >= (micro))) - -extern const guint thunar_vfs_major_version; -extern const guint thunar_vfs_minor_version; -extern const guint thunar_vfs_micro_version; - -const gchar *thunar_vfs_check_version (guint required_major, - guint required_minor, - guint required_micro) G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_CONFIG_H__ */ diff --git a/thunar-vfs/thunar-vfs-deep-count-job.c b/thunar-vfs/thunar-vfs-deep-count-job.c deleted file mode 100644 index 7a3c332b7..000000000 --- a/thunar-vfs/thunar-vfs-deep-count-job.c +++ /dev/null @@ -1,417 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-deep-count-job.h> -#include <thunar-vfs/thunar-vfs-io-trash.h> -#include <thunar-vfs/thunar-vfs-job-private.h> -#include <thunar-vfs/thunar-vfs-marshal.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* use g_lstat() and g_stat() on win32 */ -#if defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_lstat(path, statb) (lstat ((path), (statb))) -#define g_stat(path, statb) (stat ((path), (statb))) -#endif - - - -/* Signal identifiers */ -enum -{ - STATUS_READY, - LAST_SIGNAL, -}; - - - -static void thunar_vfs_deep_count_job_class_init (ThunarVfsJobClass *klass); -static void thunar_vfs_deep_count_job_finalize (GObject *object); -static void thunar_vfs_deep_count_job_execute (ThunarVfsJob *job); -static gboolean thunar_vfs_deep_count_job_process (ThunarVfsDeepCountJob *deep_count_job, - const gchar *dir_path, - struct stat *statb); -static void thunar_vfs_deep_count_job_status_ready (ThunarVfsDeepCountJob *deep_count_job); - - - -struct _ThunarVfsDeepCountJobClass -{ - ThunarVfsJobClass __parent__; - - /* signals */ - void (*status_ready) (ThunarVfsJob *job, - guint64 total_size, - guint file_count, - guint directory_count, - guint unreadable_directory_count); -}; - -struct _ThunarVfsDeepCountJob -{ - ThunarVfsJob __parent__; - - gboolean follow_links; - ThunarVfsPath *path; - - /* the time of the last "status-ready" emission */ - GTimeVal last_time; - - /* status information */ - guint64 total_size; - guint file_count; - guint directory_count; - guint unreadable_directory_count; -}; - - - -static GObjectClass *thunar_vfs_deep_count_job_parent_class; -static guint deep_count_signals[LAST_SIGNAL]; - - - -GType -thunar_vfs_deep_count_job_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_JOB, - "ThunarVfsDeepCountJob", - sizeof (ThunarVfsDeepCountJobClass), - thunar_vfs_deep_count_job_class_init, - sizeof (ThunarVfsDeepCountJob), - NULL, - 0); - } - - return type; -} - - - -static void -thunar_vfs_deep_count_job_class_init (ThunarVfsJobClass *klass) -{ - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_deep_count_job_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_deep_count_job_finalize; - - klass->execute = thunar_vfs_deep_count_job_execute; - - /** - * ThunarVfsDeepCountJob::status-ready: - * @job : a #ThunarVfsJob. - * @total_size : the total size in bytes. - * @file_count : the number of files. - * @directory_count : the number of directories. - * @unreadable_directory_count : the number of unreadable directories. - * - * Emitted by the @job to inform listeners about new status. - **/ - deep_count_signals[STATUS_READY] = - g_signal_new (I_("status-ready"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_NO_HOOKS, - G_STRUCT_OFFSET (ThunarVfsDeepCountJobClass, status_ready), - NULL, NULL, - _thunar_vfs_marshal_VOID__UINT64_UINT_UINT_UINT, - G_TYPE_NONE, 4, - G_TYPE_UINT64, - G_TYPE_UINT, - G_TYPE_UINT, - G_TYPE_UINT); -} - - - -static void -thunar_vfs_deep_count_job_finalize (GObject *object) -{ - ThunarVfsDeepCountJob *deep_count_job = THUNAR_VFS_DEEP_COUNT_JOB (object); - - /* release the base path */ - if (G_LIKELY (deep_count_job->path != NULL)) - thunar_vfs_path_unref (deep_count_job->path); - - (*G_OBJECT_CLASS (thunar_vfs_deep_count_job_parent_class)->finalize) (object); -} - - - -static void -thunar_vfs_deep_count_job_execute (ThunarVfsJob *job) -{ - ThunarVfsDeepCountJob *deep_count_job = THUNAR_VFS_DEEP_COUNT_JOB (job); - struct stat statb; - GError *err = NULL; - gchar *absolute_path; - GList *path_list; - GList *lp; - - /* check if we should count the trash root folder */ - if (G_UNLIKELY (_thunar_vfs_path_is_trash (deep_count_job->path))) - { - /* count the trash root folder as directory */ - deep_count_job->directory_count += 1; - - /* scan the trash root folder */ - path_list = _thunar_vfs_io_trash_scandir (deep_count_job->path, deep_count_job->follow_links, NULL, &err); - } - else - { - /* just count the single item */ - path_list = thunar_vfs_path_list_prepend (NULL, deep_count_job->path); - } - - /* process all paths */ - for (lp = path_list; err == NULL && lp != NULL; lp = lp->next) - { - /* try to translate the path object to an absolute local path */ - absolute_path = _thunar_vfs_path_translate_dup_string (lp->data, THUNAR_VFS_PATH_SCHEME_FILE, &err); - if (G_LIKELY (absolute_path != NULL)) - { - /* try to stat the file (handle broken links properly) */ - if (g_stat (absolute_path, &statb) < 0 && g_lstat (absolute_path, &statb) < 0) - { - /* tell the listeners that the job failed */ - _thunar_vfs_set_g_error_from_errno3 (&err); - } - else if (!S_ISDIR (statb.st_mode)) - { - /* the base path is not a directory */ - deep_count_job->total_size += statb.st_size; - deep_count_job->file_count += 1; - } - else - { - /* process the directory recursively */ - if (!thunar_vfs_deep_count_job_process (deep_count_job, absolute_path, &statb)) - { - /* base directory not readable */ - g_set_error (&err, G_FILE_ERROR, G_FILE_ERROR_IO, _("Failed to read folder contents")); - } - } - - /* release the base path */ - g_free (absolute_path); - } - } - - /* check if we had an error */ - if (G_UNLIKELY (err != NULL)) - { - /* forward the error to the job owner */ - _thunar_vfs_job_error (job, err); - g_error_free (err); - } - else - { - /* emit "status-ready" signal */ - _thunar_vfs_job_emit (THUNAR_VFS_JOB (deep_count_job), deep_count_signals[STATUS_READY], - 0, deep_count_job->total_size, deep_count_job->file_count, - deep_count_job->directory_count, deep_count_job->unreadable_directory_count); - } - - /* release the path_list */ - thunar_vfs_path_list_free (path_list); -} - - - -static gboolean -thunar_vfs_deep_count_job_process (ThunarVfsDeepCountJob *deep_count_job, - const gchar *dir_path, - struct stat *statb) -{ - const gchar *name; - gchar *path; - GDir *dp; - - /* try to open the directory */ - dp = g_dir_open (dir_path, 0, NULL); - if (G_LIKELY (dp == NULL)) - { - /* unreadable directory */ - return FALSE; - } - - /* process all items in this directory */ - while (!thunar_vfs_job_cancelled (THUNAR_VFS_JOB (deep_count_job))) - { - /* determine the next item */ - name = g_dir_read_name (dp); - if (G_UNLIKELY (name == NULL)) - break; - - /* check if we should emit "status-ready" */ - thunar_vfs_deep_count_job_status_ready (deep_count_job); - - /* determine the full path to the item */ - path = g_build_filename (dir_path, name, NULL); - - /* stat the item */ - if (G_LIKELY (g_stat (path, statb) == 0)) - { - /* add the size of this item */ - deep_count_job->total_size += statb->st_size; - - /* check if we have a directory here */ - if (S_ISDIR (statb->st_mode)) - { - /* check if this is a symlink to a folder */ - if (g_lstat (path, statb) == 0 && (!S_ISLNK (statb->st_mode) || deep_count_job->follow_links)) - { - /* process the directory recursively */ - if (thunar_vfs_deep_count_job_process (deep_count_job, path, statb)) - { - /* directory was readable */ - deep_count_job->directory_count += 1; - } - else - { - /* directory was unreadable */ - deep_count_job->unreadable_directory_count += 1; - } - } - else - { - /* count the symlink as file */ - deep_count_job->file_count += 1; - } - } - else - { - /* count it as file */ - deep_count_job->file_count += 1; - } - } - else - { - /* check if we have a broken symlink here */ - if (g_lstat (path, statb) == 0 && S_ISLNK (statb->st_mode)) - { - /* count the broken symlink as file */ - deep_count_job->total_size += statb->st_size; - deep_count_job->file_count += 1; - } - } - - /* release the path */ - g_free (path); - } - - /* close the dir handle */ - g_dir_close (dp); - - /* readable directory */ - return TRUE; -} - - - -static void -thunar_vfs_deep_count_job_status_ready (ThunarVfsDeepCountJob *deep_count_job) -{ - GTimeVal current_time; - - /* check if we should update (at most every 128 files, but not more than fourth per second) */ - if (((deep_count_job->unreadable_directory_count + deep_count_job->directory_count + deep_count_job->file_count) % 128) == 0) - { - /* determine the current time */ - g_get_current_time (¤t_time); - - /* check if more than 250ms elapsed since the last "status-ready" */ - if (((current_time.tv_sec - deep_count_job->last_time.tv_sec) * 1000ull - + (current_time.tv_usec - deep_count_job->last_time.tv_usec) / 1000ull) >= 250ull) - { - /* remember the current time */ - deep_count_job->last_time = current_time; - - /* emit "status-ready" signal */ - _thunar_vfs_job_emit (THUNAR_VFS_JOB (deep_count_job), deep_count_signals[STATUS_READY], - 0, deep_count_job->total_size, deep_count_job->file_count, - deep_count_job->directory_count, deep_count_job->unreadable_directory_count); - } - } -} - - - -/** - * thunar_vfs_deep_count_job_new: - * @path : a #ThunarVfsPath. - * @flags : the #ThunarVfsDeepCountFlags which control the - * behavior of the returned job. - * - * Allocates a new #ThunarVfsDeepCountJob, which counts - * the size of the file at @path or if @path is a directory - * counts the size of all items in the directory and its - * subdirectories. - * - * The caller is responsible to free the returned job - * using g_object_unref() when no longer needed. - * - * Return value: the newly allocated #ThunarVfsDeepCountJob. - **/ -ThunarVfsJob* -thunar_vfs_deep_count_job_new (ThunarVfsPath *path, - ThunarVfsDeepCountFlags flags) -{ - ThunarVfsDeepCountJob *deep_count_job; - - g_return_val_if_fail (path != NULL, NULL); - - /* allocate the new job */ - deep_count_job = g_object_new (THUNAR_VFS_TYPE_DEEP_COUNT_JOB, NULL); - deep_count_job->path = thunar_vfs_path_ref (path); - deep_count_job->follow_links = (flags & THUNAR_VFS_DEEP_COUNT_FLAGS_FOLLOW_SYMLINKS); - - return THUNAR_VFS_JOB (deep_count_job); -} - - - -#define __THUNAR_VFS_DEEP_COUNT_JOB_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-deep-count-job.h b/thunar-vfs/thunar-vfs-deep-count-job.h deleted file mode 100644 index cd261a49e..000000000 --- a/thunar-vfs/thunar-vfs-deep-count-job.h +++ /dev/null @@ -1,51 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_DEEP_COUNT_JOB_H__ -#define __THUNAR_VFS_DEEP_COUNT_JOB_H__ - -#include <thunar-vfs/thunar-vfs-job.h> -#include <thunar-vfs/thunar-vfs-path.h> -#include <thunar-vfs/thunar-vfs-types.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsDeepCountJobClass ThunarVfsDeepCountJobClass; -typedef struct _ThunarVfsDeepCountJob ThunarVfsDeepCountJob; - -#define THUNAR_VFS_TYPE_DEEP_COUNT_JOB (thunar_vfs_deep_count_job_get_type ()) -#define THUNAR_VFS_DEEP_COUNT_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_DEEP_COUNT_JOB, ThunarVfsDeepCountJob)) -#define THUNAR_VFS_DEEP_COUNT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_DEEP_COUNT_JOB, ThunarVfsDeepCountJobClass)) -#define THUNAR_VFS_IS_DEEP_COUNT_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_DEEP_COUNT_JOB)) -#define THUNAR_VFS_IS_DEEP_COUNT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_DEEP_COUNT_JOB)) -#define THUNAR_VFS_DEEP_COUNT_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_DEEP_COUNT_JOB, ThunarVfsDeepCountJobClass)) - -GType thunar_vfs_deep_count_job_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - -ThunarVfsJob *thunar_vfs_deep_count_job_new (ThunarVfsPath *path, - ThunarVfsDeepCountFlags flags) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_DEEP_COUNT_JOB_H__ */ diff --git a/thunar-vfs/thunar-vfs-exec.h b/thunar-vfs/thunar-vfs-exec.h deleted file mode 100644 index 8954a3257..000000000 --- a/thunar-vfs/thunar-vfs-exec.h +++ /dev/null @@ -1,53 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_EXEC_H__ -#define __THUNAR_VFS_EXEC_H__ - -#include <gdk/gdk.h> - -G_BEGIN_DECLS; - -gboolean thunar_vfs_exec_parse (const gchar *exec, - GList *path_list, - const gchar *icon, - const gchar *name, - const gchar *path, - gboolean terminal, - gint *argc, - gchar ***argv, - GError **error) G_GNUC_INTERNAL; - -gboolean thunar_vfs_exec_on_screen (GdkScreen *screen, - const gchar *working_directory, - gchar **argv, - gchar **envp, - GSpawnFlags flags, - gboolean startup_notify, - const gchar *icon_name, - GError **error) G_GNUC_INTERNAL; - -gboolean thunar_vfs_exec_sync (const gchar *command_line, - GError **error, - ...) G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_EXEC_H__ */ diff --git a/thunar-vfs/thunar-vfs-font-thumbnailer-1.desktop.in b/thunar-vfs/thunar-vfs-font-thumbnailer-1.desktop.in deleted file mode 100644 index 8872c1a2a..000000000 --- a/thunar-vfs/thunar-vfs-font-thumbnailer-1.desktop.in +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Version=1.0 -Encoding=UTF-8 -Type=X-Thumbnailer -Name=Thunar Font Thumbnailer -Comment=Creates thumbnails for font files -TryExec=@libexecdir@/thunar-vfs-font-thumbnailer-1 -MimeType=application/x-font-otf;application/x-font-pcf;application/x-font-ttf;application/x-font-type1; -X-Thumbnailer-Exec=@libexecdir@/thunar-vfs-font-thumbnailer-1 -i %i -o %o -s %s - -# vi:set encoding=UTF-8: diff --git a/thunar-vfs/thunar-vfs-font-thumbnailer.c b/thunar-vfs/thunar-vfs-font-thumbnailer.c deleted file mode 100644 index 7b25d2067..000000000 --- a/thunar-vfs/thunar-vfs-font-thumbnailer.c +++ /dev/null @@ -1,434 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org>. - * - * 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., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - * - * Based on code written by James Henstridge <james@daa.com.au> for GNOME. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MATH_H -#include <math.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#include <gdk-pixbuf/gdk-pixbuf.h> - -#include <ft2build.h> -#include FT_FREETYPE_H - - - -/* --- globals --- */ -static gchar *opt_input = NULL; -static gchar *opt_output = NULL; -static gint opt_size = 64; - - - -/* --- command line options --- */ -static GOptionEntry entries[] = -{ - { "input", 'i', 0, G_OPTION_ARG_FILENAME, &opt_input, "Name of file for which to create a thumbnail", "filename", }, - { "output", 'o', 0, G_OPTION_ARG_FILENAME, &opt_output, "Name of the file to put the thumbnail", "filename", }, - { "size", 's', 0, G_OPTION_ARG_INT, &opt_size, "Size of thumbnail in pixels; the thumbnail will be at most N*N pixels large", "N", }, - { NULL, }, -}; - - - -/* --- functions --- */ -static const gchar* -tft_ft_strerror (FT_Error error) -{ -#undef __FTERRORS_H__ -#define FT_ERRORDEF(e,v,s) case e: return s; -#define FT_ERROR_START_LIST -#define FT_ERROR_END_LIST - switch (error) - { -#include FT_ERRORS_H - default: - return "unknown"; - } -} - - - - -static void -tft_render_glyph (GdkPixbuf *pixbuf, - FT_Face face, - FT_UInt glyph, - gint *pen_x, - gint *pen_y) -{ - FT_GlyphSlot slot = face->glyph; - FT_Error error; - guchar *pixels; - guchar pixel; - gint rowstride; - gint height; - gint width; - gint off_x; - gint off_y; - gint off; - gint i, j; - - /* load the glyph */ - error = FT_Load_Glyph (face, glyph, FT_LOAD_DEFAULT); - if (G_UNLIKELY (error != 0)) - { - g_print ("%s: %s: %s\n", g_get_prgname (), "Could not load glyph", tft_ft_strerror (error)); - exit (EXIT_FAILURE); - } - - /* render the glyph */ - error = FT_Render_Glyph (slot, ft_render_mode_normal); - if (G_UNLIKELY (error != 0)) - { - g_print ("%s: %s: %s\n", g_get_prgname (), "Could not render glyph", tft_ft_strerror (error)); - exit (EXIT_FAILURE); - } - - off_x = *pen_x + slot->bitmap_left; - off_y = *pen_y - slot->bitmap_top; - - pixels = gdk_pixbuf_get_pixels (pixbuf); - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - - for (j = 0; j < slot->bitmap.rows; ++j) - { - if (j + off_y < 0 || j + off_y >= height) - continue; - - for (i = 0; i < slot->bitmap.width; ++i) - { - if (i + off_x < 0 || i + off_x >= width) - continue; - - switch (slot->bitmap.pixel_mode) - { - case ft_pixel_mode_mono: - pixel = slot->bitmap.buffer[j * slot->bitmap.pitch + i / 8]; - pixel = 255 - ((pixel >> (7 - i % 8)) & 0x1) * 255; - break; - - case ft_pixel_mode_grays: - pixel = 255 - slot->bitmap.buffer[j * slot->bitmap.pitch + i]; - break; - - default: - pixel = 255; - break; - } - - off = (j + off_y) * rowstride + 3 * (i + off_x); - pixels[off + 0] = pixel; - pixels[off + 1] = pixel; - pixels[off + 2] = pixel; - } - } - - *pen_x += slot->advance.x >> 6; -} - - - -static GdkPixbuf* -tft_scale_ratio (GdkPixbuf *source, - gint dest_size) -{ - gdouble wratio; - gdouble hratio; - gint source_width; - gint source_height; - gint dest_width; - gint dest_height; - - source_width = gdk_pixbuf_get_width (source); - source_height = gdk_pixbuf_get_height (source); - - wratio = (gdouble) source_width / (gdouble) dest_size; - hratio = (gdouble) source_height / (gdouble) dest_size; - - if (hratio > wratio) - { - dest_width = rint (source_width / hratio); - dest_height = dest_size; - } - else - { - dest_width = dest_size; - dest_height = rint (source_height / wratio); - } - - return gdk_pixbuf_scale_simple (source, MAX (dest_width, 1), MAX (dest_height, 1), GDK_INTERP_HYPER); -} - - - -static gboolean -tft_save_pixbuf (GdkPixbuf *pixbuf, - GError **error) -{ - GdkPixbuf *subpixbuf; - GdkPixbuf *scaled; - gboolean seen_pixel; - gboolean succeed; - guchar *pixels; - gint rowstride; - gint height; - gint width; - gint i, j; - gint trim_left; - gint trim_right; - gint trim_top; - gint trim_bottom; - gint offset; - - pixels = gdk_pixbuf_get_pixels (pixbuf); - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - rowstride = gdk_pixbuf_get_rowstride (pixbuf); - - for (i = 0; i < width; ++i) - { - seen_pixel = FALSE; - for (j = 0; j < height; ++j) - { - offset = j * rowstride + 3 * i; - seen_pixel = (pixels[offset + 0] != 0xff || - pixels[offset + 1] != 0xff || - pixels[offset + 2] != 0xff); - if (seen_pixel) - break; - } - - if (seen_pixel) - break; - } - - trim_left = MIN (width, i); - trim_left = MAX (trim_left - 8, 0); - - for (i = width - 1; i >= trim_left; --i) - { - seen_pixel = FALSE; - for (j = 0; j < height; ++j) - { - offset = j * rowstride + 3 * i; - seen_pixel = (pixels[offset + 0] != 0xff || - pixels[offset+1] != 0xff || - pixels[offset+2] != 0xff); - if (seen_pixel) - break; - } - - if (seen_pixel) - break; - } - - trim_right = MAX (trim_left, i); - trim_right = MIN (trim_right + 8, width - 1); - - for (j = 0; j < height; ++j) - { - seen_pixel = FALSE; - for (i = 0; i < width; ++i) - { - offset = j * rowstride + 3 * i; - seen_pixel = (pixels[offset + 0] != 0xff || - pixels[offset + 1] != 0xff || - pixels[offset + 2] != 0xff); - if (seen_pixel) - break; - } - - if (seen_pixel) - break; - } - - trim_top = MIN (height, j); - trim_top = MAX (trim_top - 8, 0); - - for (j = height - 1; j >= trim_top; --j) - { - seen_pixel = FALSE; - for (i = 0; i < width; ++i) - { - offset = j * rowstride + 3 * i; - seen_pixel = (pixels[offset + 0] != 0xff || - pixels[offset + 1] != 0xff || - pixels[offset + 2] != 0xff); - if (seen_pixel) - break; - } - - if (seen_pixel) - break; - } - - trim_bottom = MAX (trim_top, j); - trim_bottom = MIN (trim_bottom + 8, height - 1); - - /* determine the trimmed subpixbuf */ - subpixbuf = gdk_pixbuf_new_subpixbuf (pixbuf, trim_left, trim_top, trim_right - trim_left, trim_bottom - trim_top); - - /* check if we still need to scale down */ - if (gdk_pixbuf_get_width (subpixbuf) > opt_size || gdk_pixbuf_get_height (subpixbuf) > opt_size) - { - scaled = tft_scale_ratio (subpixbuf, opt_size); - g_object_unref (G_OBJECT (subpixbuf)); - subpixbuf = scaled; - } - - succeed = gdk_pixbuf_save (subpixbuf, opt_output, "png", error, NULL); - g_object_unref (G_OBJECT (subpixbuf)); - - return succeed; -} - - - -int -main (int argc, char **argv) -{ - GOptionContext *context; - FT_Library library; - GdkPixbuf *pixbuf; - FT_Error error; - FT_UInt glyph1; - FT_UInt glyph2; - FT_Face face; - GError *err = NULL; - gint pen_x; - gint pen_y; - gint n; - - /* parse the command line options */ - context = g_option_context_new ("- Create font thumbnails"); - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_set_help_enabled (context, TRUE); - if (!g_option_context_parse (context, &argc, &argv, &err)) - { - g_print ("%s: %s\n", g_get_prgname (), err->message); - return EXIT_FAILURE; - } - - /* verify that an input file was specified */ - if (G_UNLIKELY (opt_input == NULL)) - { - g_print ("%s: %s\n", g_get_prgname (), "No input file specified"); - return EXIT_FAILURE; - } - - /* verify that an output file was specified */ - if (G_UNLIKELY (opt_output == NULL)) - { - g_print ("%s: %s\n", g_get_prgname (), "No output file specified"); - return EXIT_FAILURE; - } - - /* verify the specified size */ - if (G_UNLIKELY (opt_size < 1)) - { - g_print ("%s: %s\n", g_get_prgname (), "The specified size is invalid"); - return EXIT_FAILURE; - } - - /* initialize the freetype library */ - error = FT_Init_FreeType (&library); - if (G_UNLIKELY (error != 0)) - { - g_print ("%s: %s: %s\n", g_get_prgname (), "Could not initialize freetype", tft_ft_strerror (error)); - return EXIT_FAILURE; - } - - /* try to open the input file */ - error = FT_New_Face (library, opt_input, 0, &face); - if (G_UNLIKELY (error != 0)) - { - g_print ("%s: %s: %s\n", g_get_prgname (), "Could not open the input file", tft_ft_strerror (error)); - return EXIT_FAILURE; - } - - /* set the pixel size */ - error = FT_Set_Pixel_Sizes (face, 0, opt_size); - if (G_UNLIKELY (error != 0)) - { - g_print ("%s: %s: %s\n", g_get_prgname (), "Could not set the pixel size", tft_ft_strerror (error)); - return EXIT_FAILURE; - } - - /* set the character map */ - for (n = 0; n < face->num_charmaps; ++n) - { - /* check for a desired character map */ - if (face->charmaps[n]->encoding == ft_encoding_latin_1 - || face->charmaps[n]->encoding == ft_encoding_unicode - || face->charmaps[n]->encoding == ft_encoding_apple_roman) - { - /* try to set the character map */ - error = FT_Set_Charmap (face, face->charmaps[n]); - if (G_UNLIKELY (error != 0)) - { - g_print ("%s: %s: %s\n", g_get_prgname (), "Could not set the character map", tft_ft_strerror (error)); - return EXIT_FAILURE; - } - break; - } - } - - /* determine preferred glyphs for the thumbnail (with appropriate fallbacks) */ - glyph1 = FT_Get_Char_Index (face, 'A'); - if (G_UNLIKELY (glyph1 == 0)) - glyph1 = MIN (65, face->num_glyphs - 1); - glyph2 = FT_Get_Char_Index (face, 'a'); - if (G_UNLIKELY (glyph2 == 0)) - glyph2 = MIN (97, face->num_glyphs - 1); - - /* initialize the GType system */ - g_type_init (); - - /* allocate a pixbuf for the thumbnail */ - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, opt_size * 3, (opt_size * 3) / 2); - gdk_pixbuf_fill (pixbuf, 0xffffffff); - - /* initial pen position */ - pen_x = opt_size / 2; - pen_y = opt_size; - - /* render the letters to the pixbuf */ - tft_render_glyph (pixbuf, face, glyph1, &pen_x, &pen_y); - tft_render_glyph (pixbuf, face, glyph2, &pen_x, &pen_y); - - /* save the pixbuf */ - if (!tft_save_pixbuf (pixbuf, &err)) - { - g_print ("%s: %s: %s\n", g_get_prgname (), "Could not save thumbnail", err->message); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/thunar-vfs/thunar-vfs-info.c b/thunar-vfs/thunar-vfs-info.c deleted file mode 100644 index a8e960a05..000000000 --- a/thunar-vfs/thunar-vfs-info.c +++ /dev/null @@ -1,570 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -/* implement thunar-vfs-info's inline functions */ -#define G_IMPLEMENT_INLINES 1 -#define __THUNAR_VFS_INFO_C__ -#include <thunar-vfs/thunar-vfs-info.h> - -#include <thunar-vfs/thunar-vfs-exec.h> -#include <thunar-vfs/thunar-vfs-io-local.h> -#include <thunar-vfs/thunar-vfs-io-trash.h> -#include <thunar-vfs/thunar-vfs-mime-database-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -GType -thunar_vfs_info_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = g_boxed_type_register_static (I_("ThunarVfsInfo"), - (GBoxedCopyFunc) thunar_vfs_info_ref, - (GBoxedFreeFunc) thunar_vfs_info_unref); - } - - return type; -} - - - -/** - * thunar_vfs_info_new_for_path: - * @path : the #ThunarVfsPath of the file whose info should be queried. - * @error : return location for errors or %NULL. - * - * Queries the #ThunarVfsInfo for the given @path. Returns the - * #ThunarVfsInfo if the operation is successfull, else %NULL. - * In the latter case, @error will be set to point to a #GError - * describing the cause of the failure. - * - * Return value: the #ThunarVfsInfo for @path or %NULL. - **/ -ThunarVfsInfo* -thunar_vfs_info_new_for_path (ThunarVfsPath *path, - GError **error) -{ - ThunarVfsInfo *info; - gchar *absolute_path; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - switch (thunar_vfs_path_get_scheme (path)) - { - case THUNAR_VFS_PATH_SCHEME_FILE: - absolute_path = thunar_vfs_path_dup_string (path); - info = _thunar_vfs_io_local_get_info (path, absolute_path, error); - g_free (absolute_path); - break; - - case THUNAR_VFS_PATH_SCHEME_TRASH: - info = _thunar_vfs_io_trash_get_info (path, error); - break; - - default: - g_assert_not_reached (); - info = NULL; - } - - return info; -} - - - -/** - * thunar_vfs_info_unref: - * @info : a #ThunarVfsInfo. - * - * Decrements the reference count on @info by 1 and if - * the reference count drops to zero as a result of this - * operation, the @info will be freed completely. - **/ -void -thunar_vfs_info_unref (ThunarVfsInfo *info) -{ - if (exo_atomic_dec (&info->ref_count)) - { - /* free the display name if dynamically allocated */ - if (info->display_name != thunar_vfs_path_get_name (info->path)) - g_free (info->display_name); - - /* free the custom icon name */ - g_free (info->custom_icon); - - /* drop the public info part */ - thunar_vfs_mime_info_unref (info->mime_info); - thunar_vfs_path_unref (info->path); - - /* release the memory */ - _thunar_vfs_slice_free (ThunarVfsInfo, info); - } -} - - - -/** - * thunar_vfs_info_copy: - * @info : a #ThunarVfsInfo. - * - * Takes a deep copy of the @info and returns - * it. - * - * Return value: a deep copy of @info. - **/ -ThunarVfsInfo* -thunar_vfs_info_copy (const ThunarVfsInfo *info) -{ - ThunarVfsInfo *dst; - - g_return_val_if_fail (info != NULL, NULL); - - dst = _thunar_vfs_slice_new (ThunarVfsInfo); - dst->type = info->type; - dst->mode = info->mode; - dst->flags = info->flags; - dst->uid = info->uid; - dst->gid = info->gid; - dst->size = info->size; - dst->atime = info->atime; - dst->mtime = info->mtime; - dst->ctime = info->ctime; - dst->device = info->device; - dst->mime_info = thunar_vfs_mime_info_ref (info->mime_info); - dst->path = thunar_vfs_path_ref (info->path); - dst->custom_icon = g_strdup (info->custom_icon); - dst->display_name = g_strdup (info->display_name); - dst->ref_count = 1; - - return dst; -} - - - -/** - * thunar_vfs_info_get_free_space: - * @info : a #ThunarVfsInfo. - * @free_space_return : return location for the amount of free space or %NULL. - * - * Determines the amount of free space available on the volume on which the - * file to which @info refers resides. If the system is able to determine the - * amount of free space, it will be placed into the location to which - * @free_space_return points and %TRUE will be returned, else the function - * will return %FALSE indicating that the system is unable to determine the - * amount of free space. - * - * Return value: %TRUE if the amount of free space could be determined, else - * %FALSE: - **/ -gboolean -thunar_vfs_info_get_free_space (const ThunarVfsInfo *info, - ThunarVfsFileSize *free_space_return) -{ - ThunarVfsPath *path; - gboolean succeed = FALSE; - - g_return_val_if_fail (info != NULL, FALSE); - - /* translate the info's path to a file:-URI path */ - path = _thunar_vfs_path_translate (info->path, THUNAR_VFS_PATH_SCHEME_FILE, NULL); - if (G_UNLIKELY (path != NULL)) - { - /* determine the amount of free space for the path */ - succeed = _thunar_vfs_io_local_get_free_space (path, free_space_return); - thunar_vfs_path_unref (path); - } - - return succeed; -} - - - -/** - * thunar_vfs_info_set_custom_icon: - * @info : a #ThunarVfsInfo. - * @custom_icon : the new custom icon for the @info. - * @error : return location for errors or %NULL. - * - * Sets the custom icon for the file referred to by @info to the specified - * @custom_icon, which can be either an absolute path to an image file or - * the name of a themed icon. - * - * The @info must refer to a valid .desktop file, that is, its mime type - * must be application/x-desktop. - * - * Return value: %TRUE if the custom icon of @info was updated successfully, - * %FALSE otherwise. - **/ -gboolean -thunar_vfs_info_set_custom_icon (ThunarVfsInfo *info, - const gchar *custom_icon, - GError **error) -{ - gboolean succeed = FALSE; - gchar *absolute_path; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (custom_icon != NULL, FALSE); - g_return_val_if_fail (info != NULL, FALSE); - - /* determine the absolute path in the file:-URI scheme */ - absolute_path = _thunar_vfs_path_translate_dup_string (info->path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (absolute_path != NULL)) - { - /* update the icon to the new custom_icon */ - succeed = _thunar_vfs_desktop_file_set_value (absolute_path, "Icon", custom_icon, error); - if (G_LIKELY (succeed)) - { - /* release the previous custom_icon */ - g_free (info->custom_icon); - - /* use the new custom_icon for the info */ - info->custom_icon = g_strdup (custom_icon); - } - - /* cleanup */ - g_free (absolute_path); - } - - return succeed; -} - - - -/** - * thunar_vfs_info_get_metadata: - * @info : a #ThunarVfsInfo. - * @metadata : the #ThunarVfsInfoMetadata you are interested in. - * @error : return location for errors or %NULL. - * - * Queries the @metadata for @info and returns a string with the - * data, or %NULL if either @metadata is invalid for @info or an - * error occurred while querying the @metadata. - * - * The caller is responsible to free the returned string using - * g_free() when no longer needed. - * - * Return value: the @metadata for @info or %NULL in case of an - * error. - **/ -gchar* -thunar_vfs_info_get_metadata (const ThunarVfsInfo *info, - ThunarVfsInfoMetadata metadata, - GError **error) -{ - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - switch (thunar_vfs_path_get_scheme (info->path)) - { - case THUNAR_VFS_PATH_SCHEME_FILE: - return _thunar_vfs_io_local_get_metadata (info->path, metadata, error); - - case THUNAR_VFS_PATH_SCHEME_TRASH: - return _thunar_vfs_io_trash_get_metadata (info->path, metadata, error); - - default: - g_assert_not_reached (); - return NULL; - } -} - - - -/** - * thunar_vfs_info_execute: - * @info : a #ThunarVfsInfo. - * @screen : a #GdkScreen or %NULL to use the default #GdkScreen. - * @path_list : the list of #ThunarVfsPath<!---->s to give as parameters - * to the file referred to by @info on execution. - * @working_directory : the working directory in which to execute @info or %NULL. - * @error : return location for errors or %NULL. - * - * Executes the file referred to by @info, given @path_list as parameters, - * on the specified @screen. @info may refer to either a regular, - * executable file, or a <filename>.desktop</filename> file, whose - * type is <literal>Application</literal>. - * - * If @working_directory is %NULL, the directory of the first path in @path_list - * will be used as working directory. If @path_list is also %NULL, the directory - * of @info will be used. - * - * Return value: %TRUE on success, else %FALSE. - **/ -gboolean -thunar_vfs_info_execute (const ThunarVfsInfo *info, - GdkScreen *screen, - GList *path_list, - const gchar *working_directory, - GError **error) -{ - ThunarVfsPath *parent; - const gchar *icon = NULL; - const gchar *name; - const gchar *type; - const gchar *url; - gboolean startup_notify = FALSE; - gboolean terminal; - gboolean result = FALSE; - XfceRc *rc; - gchar *absolute_path; - gchar *path_escaped; - gchar *directory; - gchar **argv = NULL; - gchar *exec; - - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (screen == NULL || GDK_IS_SCREEN (screen), FALSE); - g_return_val_if_fail (working_directory == NULL || g_path_is_absolute (working_directory), FALSE); - - /* fallback to the default screen if none given */ - if (G_UNLIKELY (screen == NULL)) - screen = gdk_screen_get_default (); - - /* determine the absolute path in the file:-URI scheme */ - absolute_path = _thunar_vfs_path_translate_dup_string (info->path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_UNLIKELY (absolute_path == NULL)) - return FALSE; - - /* check if we have a .desktop (and NOT a .directory) file here */ - if (G_UNLIKELY (info->mime_info == _thunar_vfs_mime_application_x_desktop && strcmp (thunar_vfs_path_get_name (info->path), ".directory") != 0)) - { - rc = xfce_rc_simple_open (absolute_path, TRUE); - if (G_LIKELY (rc != NULL)) - { - /* we're only interested in [Desktop Entry] */ - xfce_rc_set_group (rc, "Desktop Entry"); - - /* check if we have an application or a link here */ - type = xfce_rc_read_entry_untranslated (rc, "Type", "Application"); - if (G_LIKELY (exo_str_is_equal (type, "Application"))) - { - /* check if we have a valid Exec field */ - exec = (gchar *) xfce_rc_read_entry_untranslated (rc, "Exec", NULL); - if (G_LIKELY (exec != NULL)) - { - /* parse the Exec field */ - name = xfce_rc_read_entry (rc, "Name", NULL); - icon = xfce_rc_read_entry_untranslated (rc, "Icon", NULL); - terminal = xfce_rc_read_bool_entry (rc, "Terminal", FALSE); - startup_notify = xfce_rc_read_bool_entry (rc, "StartupNotify", FALSE) || xfce_rc_read_bool_entry (rc, "X-KDE-StartupNotify", FALSE); - result = thunar_vfs_exec_parse (exec, path_list, icon, name, absolute_path, terminal, NULL, &argv, error); - } - else - { - /* TRANSLATORS: `Exec' is a field name in a .desktop file. You should leave it as-is. */ - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("No Exec field specified")); - } - } - else if (exo_str_is_equal (type, "Link")) - { - /* check if we have a valid URL field */ - url = xfce_rc_read_entry_untranslated (rc, "URL", NULL); - if (G_LIKELY (url != NULL)) - { - /* pass the URL to exo-open, which will fire up the appropriate viewer */ - argv = g_new (gchar *, 3); - argv[0] = g_strdup ("exo-open"); - argv[1] = g_strdup (url); - argv[2] = NULL; - result = TRUE; - } - else - { - /* TRANSLATORS: `URL' is a field name in a .desktop file. You should leave it as-is. */ - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("No URL field specified")); - } - } - else - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid desktop file")); - } - - /* close the rc file */ - xfce_rc_close (rc); - } - else - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Failed to parse file")); - } - } - else - { - /* fake the Exec line */ - path_escaped = g_shell_quote (absolute_path); - exec = g_strconcat (path_escaped, " %F", NULL); - result = thunar_vfs_exec_parse (exec, path_list, NULL, NULL, NULL, FALSE, NULL, &argv, error); - g_free (path_escaped); - g_free (exec); - } - - if (G_LIKELY (result)) - { - /* determine the working directory */ - if (working_directory != NULL) - { - /* use the supplied working directory */ - directory = g_strdup (working_directory); - } - else if (G_LIKELY (path_list != NULL)) - { - /* use the directory (in the file:-URI scheme) of the first list item */ - parent = thunar_vfs_path_get_parent (path_list->data); - directory = (parent != NULL) ? _thunar_vfs_path_translate_dup_string (parent, THUNAR_VFS_PATH_SCHEME_FILE, NULL) : NULL; - } - else - { - /* use the directory of the executable file */ - directory = g_path_get_dirname (absolute_path); - } - - /* execute the command */ - result = thunar_vfs_exec_on_screen (screen, directory, argv, NULL, G_SPAWN_SEARCH_PATH, startup_notify, icon, error); - - /* release the working directory */ - g_free (directory); - } - - /* clean up */ - g_free (absolute_path); - g_strfreev (argv); - - return result; -} - - - -/** - * thunar_vfs_info_rename: - * @info : a #ThunarVfsInfo. - * @name : the new file name in UTF-8 encoding. - * @error : return location for errors or %NULL. - * - * Tries to rename the file referred to by @info to the - * new @name. - * - * The rename operation is smart in that it checks the - * type of @info first, and if @info refers to a - * <filename>.desktop</filename> file, the file name - * won't be touched, but instead the <literal>Name</literal> - * field of the <filename>.desktop</filename> will be - * changed to @name. Else, if @info refers to a regular - * file or directory, the file will be given a new - * name. - * - * Return value: %TRUE on success, else %FALSE. - **/ -gboolean -thunar_vfs_info_rename (ThunarVfsInfo *info, - const gchar *name, - GError **error) -{ - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (g_utf8_validate (name, -1, NULL), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* validate the name */ - if (*name == '\0' || strchr (name, '/') != NULL) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid file name")); - return FALSE; - } - - /* validate the info */ - if (!_thunar_vfs_path_is_local (info->path)) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Only local files may be renamed")); - return FALSE; - } - - return _thunar_vfs_io_local_rename (info, name, error); -} - - - -/** - * thunar_vfs_info_matches: - * @a : a #ThunarVfsInfo. - * @b : a #ThunarVfsInfo. - * - * Checks whether @a and @b refer to the same file - * and share the same properties. - * - * Return value: %TRUE if @a and @b match. - **/ -gboolean -thunar_vfs_info_matches (const ThunarVfsInfo *a, - const ThunarVfsInfo *b) -{ - g_return_val_if_fail (a != NULL, FALSE); - g_return_val_if_fail (b != NULL, FALSE); - - return a->type == b->type - && a->mode == b->mode - && a->flags == b->flags - && a->uid == b->uid - && a->gid == b->gid - && a->size == b->size - && a->atime == b->atime - && a->mtime == b->mtime - && a->ctime == b->ctime - && a->device == b->device - && a->mime_info == b->mime_info - && thunar_vfs_path_equal (a->path, b->path) - && strcmp (a->display_name, b->display_name) == 0; -} - - - -/** - * thunar_vfs_info_list_free: - * @info_list : a list of #ThunarVfsInfo<!---->s. - * - * Unrefs all #ThunarVfsInfo<!---->s in @info_list and - * frees the list itself. - **/ -void -thunar_vfs_info_list_free (GList *info_list) -{ - g_list_foreach (info_list, (GFunc) thunar_vfs_info_unref, NULL); - g_list_free (info_list); -} - - - -#define __THUNAR_VFS_INFO_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-info.h b/thunar-vfs/thunar-vfs-info.h deleted file mode 100644 index d9171688d..000000000 --- a/thunar-vfs/thunar-vfs-info.h +++ /dev/null @@ -1,218 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_INFO_H__ -#define __THUNAR_VFS_INFO_H__ - -#include <thunar-vfs/thunar-vfs-mime-info.h> -#include <thunar-vfs/thunar-vfs-path.h> -#include <thunar-vfs/thunar-vfs-types.h> - -G_BEGIN_DECLS; - -/** - * ThunarVfsInfoMetadata: - * @THUNAR_VFS_INFO_METADATA_FILE_LINK_TARGET : the target of a symbolic link. - * @THUNAR_VFS_INFO_METADATA_TRASH_ORIGINAL_PATH : the original path of a trashed resource. - * @THUNAR_VFS_INFO_METADATA_TRASH_DELETION_DATE : the deletion date of a trashed resource as date string. - * - * Metadata categories for thunar_vfs_info_get_metadata(). - * - * Since: 0.3.3 - **/ -typedef enum /*< skip >*/ -{ - THUNAR_VFS_INFO_METADATA_FILE_LINK_TARGET = 0, - THUNAR_VFS_INFO_METADATA_TRASH_ORIGINAL_PATH = 64, - THUNAR_VFS_INFO_METADATA_TRASH_DELETION_DATE = 65, -} ThunarVfsInfoMetadata; - - -/** - * THUNAR_VFS_TYPE_INFO: - * - * Returns the type if for #ThunarVfsInfo<!---->s, which is - * a boxed type. - **/ -#define THUNAR_VFS_TYPE_INFO (thunar_vfs_info_get_type ()) - -/* Used to avoid a dependency of thunarx on thunar-vfs */ -#ifndef __THUNAR_VFS_INFO_DEFINED__ -#define __THUNAR_VFS_INFO_DEFINED__ -typedef struct _ThunarVfsInfo ThunarVfsInfo; -#endif - -struct _ThunarVfsInfo -{ - /* File type */ - ThunarVfsFileType type : 8; - - /* File permissions and special mode flags */ - ThunarVfsFileMode mode : 12; - - /* File flags */ - ThunarVfsFileFlags flags : 12; - - /* Owner's user id */ - ThunarVfsUserId uid; - - /* Owner's group id */ - ThunarVfsGroupId gid; - - /* Size in bytes */ - ThunarVfsFileSize size; - - /* time of last access */ - ThunarVfsFileTime atime; - - /* time of last modification */ - ThunarVfsFileTime mtime; - - /* time of last status change */ - ThunarVfsFileTime ctime; - - /* device id */ - ThunarVfsFileDevice device; - - /* file's mime type */ - ThunarVfsMimeInfo *mime_info; - - /* file's absolute path */ - ThunarVfsPath *path; - - /* file's custom icon (path or themed icon name) */ - gchar *custom_icon; - - /* file's display name (UTF-8) */ - gchar *display_name; - - /*< private >*/ - gint ref_count; -}; - -GType thunar_vfs_info_get_type (void) G_GNUC_CONST; - -ThunarVfsInfo *thunar_vfs_info_new_for_path (ThunarVfsPath *path, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_INLINE_FUNC ThunarVfsInfo *thunar_vfs_info_ref (ThunarVfsInfo *info); -void thunar_vfs_info_unref (ThunarVfsInfo *info); - -ThunarVfsInfo *thunar_vfs_info_copy (const ThunarVfsInfo *info) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_INLINE_FUNC const gchar *thunar_vfs_info_get_custom_icon (const ThunarVfsInfo *info) G_GNUC_WARN_UNUSED_RESULT; -gboolean thunar_vfs_info_set_custom_icon (ThunarVfsInfo *info, - const gchar *custom_icon, - GError **error) G_GNUC_WARN_UNUSED_RESULT; - -gboolean thunar_vfs_info_get_free_space (const ThunarVfsInfo *info, - ThunarVfsFileSize *free_space_return) G_GNUC_WARN_UNUSED_RESULT; - -gchar *thunar_vfs_info_get_metadata (const ThunarVfsInfo *info, - ThunarVfsInfoMetadata metadata, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_INLINE_FUNC gchar *thunar_vfs_info_read_link (const ThunarVfsInfo *info, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -gboolean thunar_vfs_info_execute (const ThunarVfsInfo *info, - GdkScreen *screen, - GList *path_list, - const gchar *working_directory, - GError **error); - -gboolean thunar_vfs_info_rename (ThunarVfsInfo *info, - const gchar *name, - GError **error); - -gboolean thunar_vfs_info_matches (const ThunarVfsInfo *a, - const ThunarVfsInfo *b) G_GNUC_WARN_UNUSED_RESULT; - -void thunar_vfs_info_list_free (GList *info_list); - - -/* inline functions implementations */ -#if defined(G_CAN_INLINE) || defined(__THUNAR_VFS_INFO_C__) -/** - * thunar_vfs_info_ref: - * @info : a #ThunarVfsInfo. - * - * Increments the reference count on @info by 1 and - * returns a pointer to @info. - * - * Return value: a pointer to @info. - **/ -G_INLINE_FUNC ThunarVfsInfo* -thunar_vfs_info_ref (ThunarVfsInfo *info) -{ - exo_atomic_inc (&info->ref_count); - return info; -} - -/** - * thunar_vfs_info_get_custom_icon: - * @info : a #ThunarVfsInfo. - * - * Returns the custom icon for @info if there's - * a custom icon, else %NULL. - * - * The custom icon can be a themed icon name or - * an absolute path to an icon file in the local - * file system. - * - * Return value: the custom icon for @info or %NULL. - **/ -G_INLINE_FUNC const gchar* -thunar_vfs_info_get_custom_icon (const ThunarVfsInfo *info) -{ - return info->custom_icon; -} - -/** - * thunar_vfs_info_read_link: - * @info : a #ThunarVfsInfo. - * @error : return location for errors or %NULL. - * - * Reads the contents of the symbolic link to which @info refers to, - * like the POSIX readlink() function. The returned string is in the - * encoding used for filenames. - * - * The caller is responsible to free the returned string using g_free() - * when no longer needed. - * - * Return value: a newly allocated string with the contents of the - * symbolic link, or %NULL if an error occurred. - **/ -G_INLINE_FUNC gchar* -thunar_vfs_info_read_link (const ThunarVfsInfo *info, - GError **error) -{ - return thunar_vfs_info_get_metadata (info, THUNAR_VFS_INFO_METADATA_FILE_LINK_TARGET, error); -} -#endif /* G_CAN_INLINE || __THUNAR_VFS_INFO_C__ */ - - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_INFO_H__ */ diff --git a/thunar-vfs/thunar-vfs-interactive-job.c b/thunar-vfs/thunar-vfs-interactive-job.c deleted file mode 100644 index 2f8d6c770..000000000 --- a/thunar-vfs/thunar-vfs-interactive-job.c +++ /dev/null @@ -1,62 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <thunar-vfs/thunar-vfs-enum-types.h> -#include <thunar-vfs/thunar-vfs-interactive-job.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -GType -thunar_vfs_interactive_job_response_get_type (void) -{ - return THUNAR_VFS_TYPE_VFS_JOB_RESPONSE; -} - - - -GType -thunar_vfs_interactive_job_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_JOB, - "ThunarVfsInteractiveJob", - sizeof (ThunarVfsInteractiveJobClass), - NULL, - sizeof (ThunarVfsInteractiveJob), - NULL, - G_TYPE_FLAG_ABSTRACT); - } - - return type; -} - - - -#define __THUNAR_VFS_INTERACTIVE_JOB_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-interactive-job.h b/thunar-vfs/thunar-vfs-interactive-job.h deleted file mode 100644 index 912171b57..000000000 --- a/thunar-vfs/thunar-vfs-interactive-job.h +++ /dev/null @@ -1,82 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_INTERACTIVE_JOB_H__ -#define __THUNAR_VFS_INTERACTIVE_JOB_H__ - -#include <thunar-vfs/thunar-vfs-job.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsInteractiveJobClass ThunarVfsInteractiveJobClass; -typedef struct _ThunarVfsInteractiveJob ThunarVfsInteractiveJob; - -#define THUNAR_VFS_TYPE_INTERACTIVE_JOB (thunar_vfs_interactive_job_get_type ()) -#define THUNAR_VFS_INTERACTIVE_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_INTERACTIVE_JOB, ThunarVfsInteractiveJob)) -#define THUNAR_VFS_INTERACTIVE_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_INTERACTIVE_JOB, ThunarVfsInteractiveJobClass)) -#define THUNAR_VFS_IS_INTERACTIVE_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_INTERACTIVE_JOB)) -#define THUNAR_VFS_IS_INTERACTIVE_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_INTERACTIVE_JOB)) -#define THUNAR_VFS_INTERACTIVE_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_INTERACTIVE_JOB, ThunarVfsInteractiveJobClass)) - -/** - * ThunarVfsInteractiveJobResponse: - * @THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES : - * @THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES_ALL : - * @THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_NO : - * @THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_CANCEL : - * - * Deprecated: 0.3.3: Use #ThunarVfsJobResponse instead. - **/ -typedef enum /*< skip >*/ -{ - THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES = 1 << 0, - THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_YES_ALL = 1 << 1, - THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_NO = 1 << 2, - THUNAR_VFS_INTERACTIVE_JOB_RESPONSE_CANCEL = 1 << 3, -} ThunarVfsInteractiveJobResponse; - -#define THUNAR_VFS_TYPE_VFS_INTERACTIVE_JOB_RESPONSE (thunar_vfs_interactive_job_response_get_type ()) -GType thunar_vfs_interactive_job_response_get_type (void) G_GNUC_CONST; - -struct _ThunarVfsInteractiveJobClass -{ - /*< private >*/ - ThunarVfsJobClass __parent__; - void (*reserved1) (void); - void (*reserved2) (void); - void (*reserved3) (void); - void (*reserved4) (void); -}; - -struct _ThunarVfsInteractiveJob -{ - /*< private >*/ - ThunarVfsJob __parent__; - guint64 reserved0; /* backward ABI compatibility */ - gpointer reserved1; - guint reserved2 : 1; - guint reserved3 : 1; -}; - -GType thunar_vfs_interactive_job_get_type (void) G_GNUC_CONST; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_INTERACTIVE_JOB_H__ */ diff --git a/thunar-vfs/thunar-vfs-io-jobs.c b/thunar-vfs/thunar-vfs-io-jobs.c deleted file mode 100644 index 8d70812ad..000000000 --- a/thunar-vfs/thunar-vfs-io-jobs.c +++ /dev/null @@ -1,797 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-enum-types.h> -#include <thunar-vfs/thunar-vfs-info.h> -#include <thunar-vfs/thunar-vfs-io-jobs.h> -#include <thunar-vfs/thunar-vfs-io-local.h> -#include <thunar-vfs/thunar-vfs-io-ops.h> -#include <thunar-vfs/thunar-vfs-io-scandir.h> -#include <thunar-vfs/thunar-vfs-io-trash.h> -#include <thunar-vfs/thunar-vfs-monitor-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* use g_chmod(), g_open() and g_stat() on win32 */ -#if defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_chmod(path, mode) (chmod ((path), (mode))) -#define g_open(path, flags, mode) (open ((path), (flags), (mode))) -#define g_stat(path, statb) (stat ((path), (statb))) -#endif - - - -static GList *tvij_collect_nofollow (ThunarVfsJob *job, - GList *base_path_list, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - - - -static GList* -tvij_collect_nofollow (ThunarVfsJob *job, - GList *base_path_list, - GError **error) -{ - GError *err = NULL; - GList *child_path_list; - GList *path_list = NULL; - GList *lp; - - /* tell the user that we're preparing to unlink the files */ - _thunar_vfs_job_info_message (job, _("Preparing...")); - - /* recursively collect the paths */ - for (lp = base_path_list; err == NULL && lp != NULL && !thunar_vfs_job_cancelled (job); lp = lp->next) - { - /* try to scan the path as directory */ - child_path_list = _thunar_vfs_io_scandir (lp->data, &job->cancelled, THUNAR_VFS_IO_SCANDIR_RECURSIVE, &err); - if (G_UNLIKELY (err != NULL)) - { - /* we can safely ignore ENOENT/ENOTDIR errors here */ - if (err->domain == G_FILE_ERROR && (err->code == G_FILE_ERROR_NOENT || err->code == G_FILE_ERROR_NOTDIR)) - { - /* reset the error */ - g_clear_error (&err); - } - } - - /* prepend the new paths to the existing list */ - path_list = thunar_vfs_path_list_prepend (path_list, lp->data); - path_list = g_list_concat (child_path_list, path_list); - } - - /* check if we failed */ - if (G_UNLIKELY (err != NULL)) - { - /* release the collected paths */ - thunar_vfs_path_list_free (path_list); - - /* propagate the error */ - g_propagate_error (error, err); - return NULL; - } - - return path_list; -} - - - -/** - * _thunar_vfs_io_jobs_chmod: - * @job : a #ThunarVfsJob. - * @param_values : exactly six #GValue with the #GList of #ThunarVfsPath<!---->s - * for the files whose mode to changed, the directory mode mask, - * the directory mode, the file mask, the file mode and a boolean - * flag telling whether to recursively process directories. - * @n_param_values : the number of #GValue<!---->s in @param_values, must be exactly - * six for this job. - * @error : return location for errors or %NULL. - * - * See thunar_vfs_change_mode() for details. - * - * The #ThunarVfsPath<!---->s in the first item of @param_values may only include local - * paths with scheme %THUNAR_VFS_PATH_SCHEME_FILE. - * - * Return value: %TRUE if the changing of permissions succeed, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_jobs_chmod (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) -{ - ThunarVfsFileMode file_mask = g_value_get_flags (¶m_values[3]); - ThunarVfsFileMode file_mode = g_value_get_flags (¶m_values[4]); - ThunarVfsFileMode dir_mask = g_value_get_flags (¶m_values[1]); - ThunarVfsFileMode dir_mode = g_value_get_flags (¶m_values[2]); - ThunarVfsFileMode mask; - ThunarVfsFileMode mode; - struct stat statb; - gboolean recursive = g_value_get_boolean (¶m_values[5]); - gboolean retry; - GError *err = NULL; - GList *path_list = g_value_get_boxed (¶m_values[0]); - GList *lp; - gchar *absolute_path; - gchar *display_name; - gint sverrno; - - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[1], THUNAR_VFS_TYPE_VFS_FILE_MODE), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[2], THUNAR_VFS_TYPE_VFS_FILE_MODE), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[3], THUNAR_VFS_TYPE_VFS_FILE_MODE), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[4], THUNAR_VFS_TYPE_VFS_FILE_MODE), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[0], THUNAR_VFS_TYPE_PATH_LIST), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[5], G_TYPE_BOOLEAN), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), FALSE); - _thunar_vfs_return_val_if_fail (n_param_values == 6, FALSE); - -#ifdef G_ENABLE_DEBUG - /* verify that we have only local paths */ - for (lp = path_list; lp != NULL; lp = lp->next) - _thunar_vfs_assert (_thunar_vfs_path_is_local (lp->data)); -#endif - - /* collect the paths for the chmod operation */ - path_list = recursive ? tvij_collect_nofollow (job, path_list, &err) : thunar_vfs_path_list_copy (path_list); - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - /* we know the total list of paths to process now */ - _thunar_vfs_job_total_paths (job, path_list); - - /* change the permissions of all paths */ - for (lp = path_list; lp != NULL && !thunar_vfs_job_cancelled (job); lp = lp->next) - { -retry_chmod: - /* reset the saved errno */ - sverrno = 0; - - /* update the progress information */ - _thunar_vfs_job_process_path (job, lp); - - /* try to stat the file */ - absolute_path = thunar_vfs_path_dup_string (lp->data); - if (g_stat (absolute_path, &statb) == 0) - { - /* different actions depending on the type of the file */ - mask = S_ISDIR (statb.st_mode) ? dir_mask : file_mask; - mode = S_ISDIR (statb.st_mode) ? dir_mode : file_mode; - - /* determine the new mode */ - mode = ((statb.st_mode & ~mask) | mode) & 07777; - - /* try to apply the new mode */ - if (g_chmod (absolute_path, mode) < 0) - goto sverror; - - /* feed a change notification event */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CHANGED, lp->data); - } - else - { -sverror: - /* save the errno */ - sverrno = errno; - } - g_free (absolute_path); - - /* check if we failed (ignoring ENOENT) */ - if (G_UNLIKELY (sverrno != 0 && sverrno != ENOENT)) - { - /* generate an error */ - display_name = _thunar_vfs_path_dup_display_name (lp->data); - _thunar_vfs_set_g_error_from_errno2 (&err, sverrno, _("Failed to change permissions of \"%s\""), display_name); - g_free (display_name); - - /* ask the user whether to skip this one */ - retry = (_thunar_vfs_job_ask_skip (job, "%s", err->message) == THUNAR_VFS_JOB_RESPONSE_RETRY); - - /* reset the error */ - g_clear_error (&err); - - /* check whether to retry */ - if (G_UNLIKELY (retry)) - goto retry_chmod; - } - } - - /* release the path list */ - thunar_vfs_path_list_free (path_list); - - return TRUE; -} - - - -/** - * _thunar_vfs_io_jobs_chown: - * @job : a #ThunarVfsJob. - * @param_values : exactly four #GValue with the #GList of #ThunarVfsPath<!---->s - * for the files whose ownership to changed, the new user id or %-1, - * the new group id or %-1, and a boolean flag telling whether to - * recursively process directories. - * @n_param_values : the number of #GValue<!---->s in @param_values, must be exactly - * four for this job. - * @error : return location for errors or %NULL. - * - * See thunar_vfs_change_group() and thunar_vfs_change_owner() for details. - * - * The #ThunarVfsPath<!---->s in the first item of @param_values may only include local - * paths with scheme %THUNAR_VFS_PATH_SCHEME_FILE. - * - * Return value: %TRUE if the changing of ownership succeed, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_jobs_chown (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) -{ - struct stat statb; - gboolean recursive = g_value_get_boolean (¶m_values[3]); - gboolean retry; - GError *err = NULL; - GList *path_list = g_value_get_boxed (¶m_values[0]); - GList *lp; - gchar *absolute_path; - gchar *display_name; - gint sverrno; - gint uid = g_value_get_int (¶m_values[1]); - gint gid = g_value_get_int (¶m_values[2]); - gint nuid; - gint ngid; - - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[0], THUNAR_VFS_TYPE_PATH_LIST), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[3], G_TYPE_BOOLEAN), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[1], G_TYPE_INT), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[2], G_TYPE_INT), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), FALSE); - _thunar_vfs_return_val_if_fail (uid >= 0 || gid >= 0, FALSE); - _thunar_vfs_return_val_if_fail (n_param_values == 4, FALSE); - -#ifdef G_ENABLE_DEBUG - /* verify that we have only local paths */ - for (lp = path_list; lp != NULL; lp = lp->next) - _thunar_vfs_assert (_thunar_vfs_path_is_local (lp->data)); -#endif - - /* collect the paths for the chown operation */ - path_list = recursive ? tvij_collect_nofollow (job, path_list, &err) : thunar_vfs_path_list_copy (path_list); - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - /* we know the total list of paths to process now */ - _thunar_vfs_job_total_paths (job, path_list); - - /* change the ownership of all paths */ - for (lp = path_list; lp != NULL && !thunar_vfs_job_cancelled (job); lp = lp->next) - { -retry_chown: - /* reset the saved errno */ - sverrno = 0; - - /* update the progress information */ - _thunar_vfs_job_process_path (job, lp); - - /* try to stat the file */ - absolute_path = thunar_vfs_path_dup_string (lp->data); - if (g_stat (absolute_path, &statb) == 0) - { - /* determine the new uid/gid */ - nuid = (uid < 0) ? (gint) statb.st_uid : uid; - ngid = (gid < 0) ? (gint) statb.st_gid : gid; - - /* try to apply the new ownership */ - if (chown (absolute_path, nuid, ngid) < 0) - goto sverror; - - /* feed a change notification event */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CHANGED, lp->data); - } - else - { -sverror: - /* save the errno */ - sverrno = errno; - } - g_free (absolute_path); - - /* check if we failed (ignoring ENOENT) */ - if (G_UNLIKELY (sverrno != 0 && sverrno != ENOENT)) - { - /* generate an error */ - display_name = _thunar_vfs_path_dup_display_name (lp->data); - _thunar_vfs_set_g_error_from_errno2 (&err, sverrno, G_LIKELY (uid >= 0) - ? _("Failed to change file owner of \"%s\"") - : _("Failed to change file group of \"%s\""), - display_name); - g_free (display_name); - - /* ask the user whether to skip/retry this one */ - retry = (_thunar_vfs_job_ask_skip (job, "%s", err->message) == THUNAR_VFS_JOB_RESPONSE_RETRY); - - /* reset the error */ - g_clear_error (&err); - - /* check whether to retry */ - if (G_UNLIKELY (retry)) - goto retry_chown; - } - } - - /* release the path list */ - thunar_vfs_path_list_free (path_list); - - return TRUE; -} - - - -/** - * _thunar_vfs_io_jobs_create: - * @job : a #ThunarVfsJob. - * @param_values : exactly one #GValue with the #GList of #ThunarVfsPath<!---->s - * for which to create new files. - * @n_param_values : the number of #GValue<!---->s in @param_values, must be exactly - * one for this job. - * @error : return location for errors or %NULL. - * - * Creates empty files for all #ThunarVfsPath<!---->s specified in @param_values. - * - * The #ThunarVfsPath<!---->s in @param_values may only include local paths with scheme - * %THUNAR_VFS_PATH_SCHEME_FILE. - * - * Return value: %TRUE if the creation of the files succeed, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_jobs_create (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) -{ - ThunarVfsJobResponse response; - GError *err = NULL; - gchar *absolute_path; - gchar *display_name; - gchar *message; - GList *path_list = g_value_get_boxed (¶m_values[0]); - GList *lp; - gint fd; - - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[0], THUNAR_VFS_TYPE_PATH_LIST), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), FALSE); - _thunar_vfs_return_val_if_fail (n_param_values == 1, FALSE); - -#ifdef G_ENABLE_DEBUG - /* verify that we have only local paths */ - for (lp = path_list; lp != NULL; lp = lp->next) - _thunar_vfs_assert (_thunar_vfs_path_is_local (lp->data)); -#endif - - /* we know the total paths to be processed */ - _thunar_vfs_job_total_paths (job, path_list); - - /* process all paths */ - for (lp = path_list; err == NULL && lp != NULL && !thunar_vfs_job_cancelled (job); lp = lp->next) - { - /* update the progress information */ - _thunar_vfs_job_process_path (job, lp); - - /* determine the absolute path to the path object */ - absolute_path = thunar_vfs_path_dup_string (lp->data); - -again: - /* try to create the file at the given path */ - fd = g_open (absolute_path, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE); - if (G_UNLIKELY (fd < 0)) - { - /* check if the file already exists */ - if (G_UNLIKELY (errno == EEXIST)) - { - /* ask the user whether to override this path */ - display_name = _thunar_vfs_path_dup_display_name (lp->data); - response = _thunar_vfs_job_ask_overwrite (job, _("The file \"%s\" already exists"), display_name); - g_free (display_name); - - /* check if we should overwrite */ - if (G_UNLIKELY (response == THUNAR_VFS_JOB_RESPONSE_YES)) - { - /* try to remove the file (fail if not possible) */ - if (_thunar_vfs_io_ops_remove (lp->data, THUNAR_VFS_IO_OPS_IGNORE_ENOENT, &err)) - { - /* try again */ - goto again; - } - } - } - else - { - /* ask the user whether to skip/retry this path (cancels the job if not) */ - display_name = _thunar_vfs_path_dup_display_name (lp->data); - message = g_strdup_printf (_("Failed to create empty file \"%s\""), display_name); - response = _thunar_vfs_job_ask_skip (job, "%s: %s", message, g_strerror (errno)); - g_free (display_name); - g_free (message); - - /* check whether to retry the create operation */ - if (response == THUNAR_VFS_JOB_RESPONSE_RETRY) - goto again; - } - } - else - { - /* feed a "created" event for the new file */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CREATED, lp->data); - - /* close the file */ - close (fd); - } - - /* cleanup */ - g_free (absolute_path); - } - - /* check if we failed */ - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - /* emit the "new-files" signal with the given path list */ - _thunar_vfs_job_new_files (job, path_list); - - return TRUE; -} - - - -/** - * _thunar_vfs_io_jobs_link: - * @job : a #ThunarVfsJob. - * @param_values : exactly two #GValue<!---->s with the #GList of #ThunarVfsPath<!---->s - * for the source paths and the target paths. - * @n_param_values : the number of #GValue<!---->s in @param_values, must be exactly - * two for this job. - * @error : return location for errors or %NULL. - * - * Creates symbolic links from all #ThunarVfsPath<!---->s in the first parameter of @param_values - * to the corresponding #ThunarVfsPath<!---->s in the second parameter of @param_values. - * - * The #ThunarVfsPath<!---->s in both @param_values may only include local paths with scheme - * %THUNAR_VFS_PATH_SCHEME_FILE. - * - * Return value: %TRUE if the link were created successfully, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_jobs_link (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) -{ - ThunarVfsJobResponse overwrite; - ThunarVfsPath *target_path; - GError *err = NULL; - GList *source_path_list = g_value_get_boxed (¶m_values[0]); - GList *target_path_list = g_value_get_boxed (¶m_values[1]); - GList *sp; - GList *tp; - - _thunar_vfs_return_val_if_fail (g_list_length (source_path_list) == g_list_length (target_path_list), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[0], THUNAR_VFS_TYPE_PATH_LIST), FALSE); - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[1], THUNAR_VFS_TYPE_PATH_LIST), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), FALSE); - _thunar_vfs_return_val_if_fail (n_param_values == 2, FALSE); - - /* we know the total list of paths to process */ - _thunar_vfs_job_total_paths (job, source_path_list); - - /* process all files */ - for (sp = source_path_list, tp = target_path_list; err == NULL && sp != NULL; sp = sp->next, tp = tp->next) - { - /* check if the job was cancelled by the user */ - if (G_UNLIKELY (thunar_vfs_job_cancelled (job))) - break; - - /* update the progress information */ - _thunar_vfs_job_process_path (job, sp); - -again: - /* try to perform the symlink operation */ - if (_thunar_vfs_io_ops_link_file (sp->data, tp->data, &target_path, &err)) - { - /* replace the path on the target path list */ - thunar_vfs_path_unref (tp->data); - tp->data = target_path; - } - else if (G_LIKELY (err->domain == G_FILE_ERROR && err->code == G_FILE_ERROR_EXIST)) - { - /* ask the user whether we should remove the target first */ - overwrite = _thunar_vfs_job_ask_overwrite (job, "%s", err->message); - - /* release the error */ - g_clear_error (&err); - - /* check if we should overwrite the existing file */ - if (G_LIKELY (overwrite == THUNAR_VFS_JOB_RESPONSE_YES)) - { - /* try to remove the target file (fail if not possible) */ - if (_thunar_vfs_io_ops_remove (tp->data, THUNAR_VFS_IO_OPS_IGNORE_ENOENT, &err)) - { - /* try again... */ - goto again; - } - } - } - } - - /* check if we failed */ - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - /* emit the "new-files" signal for the target paths */ - _thunar_vfs_job_new_files (job, target_path_list); - - return TRUE; -} - - - -/** - * _thunar_vfs_io_jobs_listdir: - * @job : a #ThunarVfsJob. - * @param_values : exactly one #GValue with the #ThunarVfsPath of the folder whose - * contents to list. - * @n_param_values : the number of #GValue<!---->s in @param_values, must be exactly - * one for this job. - * @error : return location for errors or %NULL. - * - * Lists the contents of the folder at the #ThunarVfsPath in @param_values. - * - * Return value: %TRUE if the folder contents were successfully listed, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_jobs_listdir (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) -{ - ThunarVfsPath *path = g_value_get_boxed (¶m_values[0]); - GError *err = NULL; - GList *info_list; - - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[0], THUNAR_VFS_TYPE_PATH), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), FALSE); - _thunar_vfs_return_val_if_fail (n_param_values == 1, FALSE); - - /* determine the type of directory to scan */ - switch (thunar_vfs_path_get_scheme (path)) - { - case THUNAR_VFS_PATH_SCHEME_FILE: - info_list = _thunar_vfs_io_local_listdir (path, &err); - break; - - case THUNAR_VFS_PATH_SCHEME_TRASH: - info_list = _thunar_vfs_io_trash_listdir (path, &err); - break; - - default: - _thunar_vfs_set_g_error_not_supported (error); - return FALSE; - } - - /* check if we have any files to report */ - if (G_LIKELY (info_list != NULL)) - { - /* emit the "infos-ready" signal with the given list */ - if (!_thunar_vfs_job_infos_ready (job, info_list)) - { - /* if none of the handlers took over ownership, we still - * own it and we are thereby responsible to release it. - */ - thunar_vfs_info_list_free (info_list); - } - } - else if (err != NULL) - { - /* propagate the error to the caller */ - g_propagate_error (error, err); - return FALSE; - } - - return TRUE; -} - - - -/** - * _thunar_vfs_io_jobs_mkdir: - * @job : a #ThunarVfsJob. - * @param_values : exactly one #GValue with the #GList of #ThunarVfsPath<!---->s - * for which to create new directories. - * @n_param_values : the number of #GValue<!---->s in @param_values, must be exactly - * one for this job. - * @error : return location for errors or %NULL. - * - * Creates new directories for all #ThunarVfsPath<!---->s specified in @param_values. - * - * The #ThunarVfsPath<!---->s in @param_values may only include local paths with scheme - * %THUNAR_VFS_PATH_SCHEME_FILE. - * - * Return value: %TRUE if the creation of the folders succeed, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_jobs_mkdir (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) -{ - GList *path_list = g_value_get_boxed (¶m_values[0]); - GList *lp; - - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[0], THUNAR_VFS_TYPE_PATH_LIST), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), FALSE); - _thunar_vfs_return_val_if_fail (n_param_values == 1, FALSE); - -#ifdef G_ENABLE_DEBUG - /* verify that we have only local paths */ - for (lp = path_list; lp != NULL; lp = lp->next) - _thunar_vfs_assert (_thunar_vfs_path_is_local (lp->data)); -#endif - - /* we know the total list of paths to process */ - _thunar_vfs_job_total_paths (job, path_list); - - /* process all directories */ - for (lp = path_list; lp != NULL && !thunar_vfs_job_cancelled (job); lp = lp->next) - { - /* update the progress information */ - _thunar_vfs_job_process_path (job, lp); - - /* try to create the target directory */ - if (!_thunar_vfs_io_ops_mkdir (lp->data, 0777 & ~umask(0), THUNAR_VFS_IO_OPS_NONE, error)) - return FALSE; - } - - /* emit the "new-files" signal */ - _thunar_vfs_job_new_files (job, path_list); - return TRUE; -} - - - -/** - * _thunar_vfs_io_jobs_unlink: - * @job : a #ThunarVfsJob. - * @param_values : exactly one #GValue with the #GList of #ThunarVfsPath<!---->s - * for the files and folders which should be unlinked recursively. - * @n_param_values : the number of #GValue<!---->s in @param_values, must be exactly - * one for this job. - * @error : return location for errors or %NULL. - * - * Recursively unlinks all #ThunarVfsPath<!---->s specified in @param_values. - * - * Return value: %TRUE if the unlink operation succeed, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_jobs_unlink (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) -{ - gboolean retry; - GError *err = NULL; - GList *path_list; - GList *lp; - - _thunar_vfs_return_val_if_fail (G_VALUE_HOLDS (¶m_values[0], THUNAR_VFS_TYPE_PATH_LIST), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), FALSE); - _thunar_vfs_return_val_if_fail (n_param_values == 1, FALSE); - - /* collect the paths for the removal */ - path_list = tvij_collect_nofollow (job, g_value_get_boxed (¶m_values[0]), &err); - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - /* we know the total list of paths to process */ - _thunar_vfs_job_total_paths (job, path_list); - - /* perform the actual removal of the paths */ - for (lp = path_list; lp != NULL && !thunar_vfs_job_cancelled (job); lp = lp->next) - { - /* update the progress information */ - _thunar_vfs_job_process_path (job, lp); - - /* skip the root folders, which cannot be deleted anyway */ - if (G_LIKELY (!thunar_vfs_path_is_root (lp->data))) - { -again: /* remove the file for the current path */ - if (!_thunar_vfs_io_ops_remove (lp->data, THUNAR_VFS_IO_OPS_IGNORE_ENOENT, &err)) - { - /* ask the user whether to skip the file */ - retry = (_thunar_vfs_job_ask_skip (job, "%s", err->message) == THUNAR_VFS_JOB_RESPONSE_RETRY); - - /* clear the error */ - g_clear_error (&err); - - /* check whether to retry */ - if (G_UNLIKELY (retry)) - goto again; - } - } - } - - /* release the path list */ - thunar_vfs_path_list_free (path_list); - - return TRUE; -} - - - -#define __THUNAR_VFS_IO_JOBS_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-io-jobs.h b/thunar-vfs/thunar-vfs-io-jobs.h deleted file mode 100644 index 1a3cf9f5d..000000000 --- a/thunar-vfs/thunar-vfs-io-jobs.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_IO_JOBS_H__ -#define __THUNAR_VFS_IO_JOBS_H__ - -#include <thunar-vfs/thunar-vfs-job-private.h> - -G_BEGIN_DECLS; - -gboolean _thunar_vfs_io_jobs_chmod (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) G_GNUC_INTERNAL; -gboolean _thunar_vfs_io_jobs_chown (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) G_GNUC_INTERNAL; -gboolean _thunar_vfs_io_jobs_create (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) G_GNUC_INTERNAL; -gboolean _thunar_vfs_io_jobs_mkdir (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) G_GNUC_INTERNAL; -gboolean _thunar_vfs_io_jobs_link (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) G_GNUC_INTERNAL; -gboolean _thunar_vfs_io_jobs_listdir (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) G_GNUC_INTERNAL; -gboolean _thunar_vfs_io_jobs_unlink (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error) G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_IO_JOBS_H__ */ diff --git a/thunar-vfs/thunar-vfs-io-local-xfer.c b/thunar-vfs/thunar-vfs-io-local-xfer.c deleted file mode 100644 index 64201927f..000000000 --- a/thunar-vfs/thunar-vfs-io-local-xfer.c +++ /dev/null @@ -1,638 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -#ifdef HAVE_SYS_MOUNT_H -#include <sys/mount.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef HAVE_SYS_STATFS_H -#include <sys/statfs.h> -#endif -#ifdef HAVE_SYS_STATVFS_H -#include <sys/statvfs.h> -#endif -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef HAVE_SYS_VFS_H -#include <sys/vfs.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <stdio.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-io-local-xfer.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* use g_lstat(), g_mkdir(), g_open() and g_unlink() on win32 */ -#if defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_lstat(path, buffer) (lstat ((path), (buffer))) -#define g_mkdir(path, mode) (mkdir ((path), (mode))) -#define g_open(path, flags, mode) (open ((path), (flags), (mode))) -#define g_unlink(path) (unlink ((path))) -#endif - -#ifndef O_NOFOLLOW -#define O_NOFOLLOW 0 -#endif - - - -static gboolean tvilx_mounted_readonly (gint fd); -static void tvilx_set_error_with_path (GError **error, - const gchar *message, - const gchar *path); -static inline void tvilx_copy_regular (const gchar *source_absolute_path, - const gchar *target_absolute_path, - const struct stat *source_statb, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - GError **error); - - - -static gboolean -tvilx_mounted_readonly (gint fd) -{ -#if defined(HAVE_STATVFS1) - struct statvfs statvfsb; - return (fstatvfs1 (fd, &statvfsb, ST_NOWAIT) == 0 && (statvfsb.f_flag & ST_RDONLY) != 0); -#elif defined(HAVE_STATVFS) - struct statvfs statvfsb; - return (fstatvfs (fd, &statvfsb) == 0 && (statvfsb.f_flag & ST_RDONLY) != 0); -#elif defined(HAVE_STATFS) - struct statfs statfsb; - return (fstatfs (fd, &statfsb) == 0 && (statfsb.f_flags & MNT_RDONLY) != 0); -#else - return FALSE; -#endif -} - - - -static void -tvilx_set_error_with_path (GError **error, - const gchar *message, - const gchar *path) -{ - gchar *display_name; - gchar *format; - gint sverrno; - - /* save the errno value, as it may be modified */ - sverrno = errno; - - /* determine the display name for the path */ - display_name = g_filename_display_name (path); - - /* setup the error */ - format = g_strconcat (message, " (%s)", NULL); - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (sverrno), format, display_name, g_strerror (sverrno)); - g_free (format); - - /* release the display name */ - g_free (display_name); -} - - - -static inline void -tvilx_copy_regular (const gchar *source_absolute_path, - const gchar *target_absolute_path, - const struct stat *source_statb, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - GError **error) -{ -#ifdef HAVE_FUTIMES - struct timeval times[2]; -#endif - mode_t mode; - gchar *display_name; - gchar *buffer; - gsize bufsize; - gint source_fd; - gint target_fd; - gint n, m, l; - - /* try to open the source file for reading */ - source_fd = g_open (source_absolute_path, O_RDONLY, 0000); - if (G_UNLIKELY (source_fd < 0)) - { - tvilx_set_error_with_path (error, _("Failed to open \"%s\" for reading"), source_absolute_path); - return; - } - - /* default to the permissions of the source file */ - mode = source_statb->st_mode; - - /* if the source is located on a rdonly medium or we are not the owner - * of the source file, we automatically chmod +rw the destination file. - */ - if (tvilx_mounted_readonly (source_fd) || source_statb->st_uid != getuid ()) - mode |= (THUNAR_VFS_FILE_MODE_USR_READ | THUNAR_VFS_FILE_MODE_USR_WRITE); - - /* try to open the target file for writing */ - target_fd = g_open (target_absolute_path, O_CREAT | O_EXCL | O_NOFOLLOW | O_WRONLY, mode); - if (G_UNLIKELY (target_fd < 0)) - { - /* translate EISDIR and EMLINK to EEXIST */ - if (G_UNLIKELY (errno == EISDIR || errno == EMLINK)) - errno = EEXIST; - - /* EEXIST gets a better error message */ - if (G_LIKELY (errno == EEXIST)) - { - display_name = g_filename_display_name (target_absolute_path); - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), _("The file \"%s\" already exists"), display_name); - g_free (display_name); - } - else - { - /* use the generic error message */ - tvilx_set_error_with_path (error, _("Failed to open \"%s\" for writing"), target_absolute_path); - } - - goto end1; - } - -#ifdef HAVE_MMAP - /* try mmap() for files not larger than 8MB */ - buffer = (source_statb->st_size <= 8 * 1024 * 1024) - ? mmap (NULL, source_statb->st_size, PROT_READ, MAP_SHARED, source_fd, 0) - : MAP_FAILED; - if (G_LIKELY (buffer != (gchar *) MAP_FAILED)) - { -#ifdef HAVE_POSIX_MADVISE - /* tell the system that the data will be read sequentially */ - posix_madvise (buffer, source_statb->st_size, POSIX_MADV_SEQUENTIAL); -#endif - - /* write the data to the target file */ - for (m = 0, n = source_statb->st_size; m < n; ) - { - l = write (target_fd, buffer + m, n - m); - if (G_UNLIKELY (l < 0)) - { - /* just try again on EAGAIN/EINTR */ - if (G_LIKELY (errno != EAGAIN && errno != EINTR)) - { - tvilx_set_error_with_path (error, _("Failed to write data to \"%s\""), target_absolute_path); - break; - } - } - else - { - /* advance the offset */ - m += l; - } - - /* invoke the callback (FALSE means cancel) */ - if (!((*callback) (m, callback_data))) - { - /* unlink the (not yet completely written) target file */ - if (g_unlink (target_absolute_path) < 0) - { - tvilx_set_error_with_path (error, _("Failed to remove \"%s\""), target_absolute_path); - break; - } - - /* tell the caller that the job was cancelled */ - _thunar_vfs_set_g_error_from_errno (error, EINTR); - break; - } - } - - /* need to unmap prior to close */ - munmap (buffer, source_statb->st_size); - } - else -#endif /* !HAVE_MMAP */ - { -#ifdef HAVE_POSIX_FADVISE - /* tell the system that the data will be read sequentially */ - posix_fadvise (source_fd, 0, 0, POSIX_FADV_SEQUENTIAL); -#endif - - /* allocate the transfer buffer */ - bufsize = 8 * source_statb->st_blksize; - buffer = g_new (gchar, bufsize); - - /* copy the data from the source file to the target file */ - for (;;) - { - /* read a chunk from the source file */ - n = read (source_fd, buffer, bufsize); - if (G_UNLIKELY (n < 0)) - { - /* just try again on EAGAIN/EINTR */ - if (G_LIKELY (errno != EAGAIN && errno != EINTR)) - { - tvilx_set_error_with_path (error, _("Failed to read data from \"%s\""), source_absolute_path); - goto end2; - } - } - else if (n == 0) - break; - - /* write the data to the target file */ - for (m = 0; m < n; ) - { - l = write (target_fd, buffer + m, n - m); - if (G_UNLIKELY (l < 0)) - { - /* just try again on EAGAIN/EINTR */ - if (G_UNLIKELY (errno == EAGAIN || errno == EINTR)) - continue; - - tvilx_set_error_with_path (error, _("Failed to write data to \"%s\""), target_absolute_path); - goto end2; - } - else - { - /* advance the offset */ - m += l; - } - } - - /* invoke the callback (FALSE means cancel) */ - if (!((*callback) (n, callback_data))) - { - /* unlink the (not yet completely written) target file */ - if (g_unlink (target_absolute_path) < 0) - { - tvilx_set_error_with_path (error, _("Failed to remove \"%s\""), target_absolute_path); - goto end2; - } - - /* tell the caller that the job was cancelled */ - _thunar_vfs_set_g_error_from_errno (error, EINTR); - goto end2; - } - } - -end2: /* release the transfer buffer */ - g_free (buffer); - } - - /* set the access/modification time of the target to that of - * the source: http://bugzilla.xfce.org/show_bug.cgi?id=2244 - */ -#ifdef HAVE_FUTIMES - /* set access and modifications using the source_statb */ - times[0].tv_sec = source_statb->st_atime; times[0].tv_usec = 0; - times[1].tv_sec = source_statb->st_mtime; times[1].tv_usec = 0; - - /* apply the new times to the file (ignoring errors here) */ - futimes (target_fd, times); -#endif - - /* close the file descriptors */ - close (target_fd); -end1: - close (source_fd); -} - - - -/** - * _thunar_vfs_io_local_xfer_next_path: - * @source_path : the #ThunarVfsPath of the source file. - * @target_directory_path : the #ThunarVfsPath to the target directory. - * @n : the current step. - * @mode : whether to generate duplicate or link name. - * @error : return location for errors or %NULL. - * - * This method generates the next duplicate/link name for the @source_path - * in @target_directory_path. - * - * The caller is responsible to free the returned #ThunarVfsPath using - * thunar_vfs_path_unref() when no longer needed. - * - * Return value: the @n<!---->th unique #ThunarVfsPath for @source_path in - * @target_directory_path according to @mode. - **/ -ThunarVfsPath* -_thunar_vfs_io_local_xfer_next_path (const ThunarVfsPath *source_path, - ThunarVfsPath *target_directory_path, - guint n, - ThunarVfsIOLocalXferMode mode, - GError **error) -{ - static const gchar NAMES[3][2][19] = - { - { - N_ ("copy of %s"), - N_ ("link to %s"), - }, - { - N_ ("another copy of %s"), - N_ ("another link to %s"), - }, - { - N_ ("third copy of %s"), - N_ ("third link to %s"), - }, - }; - - ThunarVfsPath *target_path; - const gchar *source_name; - gchar *source_display_name; - gchar *target_display_name; - gchar *target_name; - gchar *swap_name; - gchar *tmp_name; - guint m; - - _thunar_vfs_return_val_if_fail (n > 0, NULL); - - /* try to determine the display name for the source file (in UTF-8) */ - source_name = thunar_vfs_path_get_name (source_path); - source_display_name = g_filename_to_utf8 (source_name, -1, NULL, NULL, error); - if (G_UNLIKELY (source_display_name == NULL)) - return NULL; - - /* check if the source display name matches one of the NAMES (when copying) */ - if (G_LIKELY (mode == THUNAR_VFS_IO_LOCAL_XFER_COPY)) - { - /* allocate memory for the new name */ - tmp_name = g_strdup (source_display_name); - - /* try the NAMES */ - for (m = 0; m < 3; ++m) - if (sscanf (source_display_name, gettext (NAMES[m][THUNAR_VFS_IO_LOCAL_XFER_COPY]), tmp_name) == 1) - { - /* swap tmp and source display name */ - swap_name = source_display_name; - source_display_name = tmp_name; - tmp_name = swap_name; - break; - } - - /* if we had no match on the NAMES, try the "%uth copy of %s" pattern */ - if (G_LIKELY (m == 3) && sscanf (source_display_name, _("%uth copy of %s"), &m, tmp_name) == 2) - { - /* swap tmp and source display name */ - swap_name = source_display_name; - source_display_name = tmp_name; - tmp_name = swap_name; - } - - /* cleanup */ - g_free (tmp_name); - } - - /* determine the target display name */ - if (G_LIKELY (n <= 3)) - target_display_name = g_strdup_printf (gettext (NAMES[n - 1][mode]), source_display_name); - else if (mode == THUNAR_VFS_IO_LOCAL_XFER_COPY) - target_display_name = g_strdup_printf (ngettext ("%uth copy of %s", "%uth copy of %s", n), n, source_display_name); - else - target_display_name = g_strdup_printf (ngettext ("%uth link to %s", "%uth link to %s", n), n, source_display_name); - - /* we don't need the source display name anymore */ - g_free (source_display_name); - - /* try to determine the real target name from the display name */ - target_name = g_filename_from_utf8 (target_display_name, -1, NULL, NULL, error); - - /* generate the target path */ - target_path = (target_name != NULL) ? _thunar_vfs_path_child (target_directory_path, target_name) : NULL; - g_free (target_display_name); - g_free (target_name); - return target_path; -} - - - -/** - * _thunar_vfs_io_local_xfer_copy: - * @source_path : the #ThunarVfsPath for the source file. - * @target_path : the #ThunarVfsPath for the target location. - * @callback : the progress callback function. - * @callback_data : data to pass to @callback. - * @merge_directories : %TRUE to merge directories, which means that EEXIST is not - * returned if a directory should be copied and the directory - * int the target location already exists. - * @error : return location for errors or %NULL. - * - * Copies the file from @source_path to @target_path. - * - * Return value: %TRUE if the file was successfully copied, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_local_xfer_copy (const ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - gboolean merge_directories, - GError **error) -{ - struct stat source_statb; - GError *err = NULL; - gchar source_absolute_path[THUNAR_VFS_PATH_MAXSTRLEN]; - gchar target_absolute_path[THUNAR_VFS_PATH_MAXSTRLEN]; -#ifdef HAVE_SYMLINK - gchar *link_target; -#endif - - /* determine the absolute source and target path */ - if (G_UNLIKELY (thunar_vfs_path_to_string (source_path, source_absolute_path, sizeof (source_absolute_path), error) < 0 - || thunar_vfs_path_to_string (target_path, target_absolute_path, sizeof (target_absolute_path), error) < 0)) - { - /* should not happen, but hey... */ - return FALSE; - } - - /* stat the source path */ - if (g_lstat (source_absolute_path, &source_statb) < 0) - { - /* unable to stat source file, impossible to copy then */ - tvilx_set_error_with_path (&err, _("Failed to determine file info for \"%s\""), source_absolute_path); - } - else - { - /* perform the appropriate operation */ - switch ((source_statb.st_mode & S_IFMT) >> 12) - { - case THUNAR_VFS_FILE_TYPE_DIRECTORY: - /* check if the directory exists, or we should not merge */ - if (!g_file_test (target_absolute_path, G_FILE_TEST_IS_DIR) || !merge_directories) - { - /* default to the source dir permissions, but make sure that we can write to newly created directories */ - mode_t target_mode = (source_statb.st_mode & ~S_IFMT) | THUNAR_VFS_FILE_MODE_USR_READ | THUNAR_VFS_FILE_MODE_USR_WRITE; - - /* try to create the directory */ - if (g_mkdir (target_absolute_path, target_mode) < 0) - tvilx_set_error_with_path (&err, _("Failed to create directory \"%s\""), target_absolute_path); - } - break; - -#ifdef HAVE_MKFIFO - case THUNAR_VFS_FILE_TYPE_FIFO: - if (mkfifo (target_absolute_path, source_statb.st_mode) < 0) - { - /* TRANSLATORS: FIFO is an acronym for First In, First Out. You can replace the word with `pipe'. */ - tvilx_set_error_with_path (&err, _("Failed to create named fifo \"%s\""), target_absolute_path); - } - break; -#endif - - case THUNAR_VFS_FILE_TYPE_REGULAR: - /* copying regular files requires some more work */ - tvilx_copy_regular (source_absolute_path, target_absolute_path, &source_statb, callback, callback_data, &err); - break; - -#ifdef HAVE_SYMLINK - case THUNAR_VFS_FILE_TYPE_SYMLINK: - /* try to read the link target */ - link_target = g_file_read_link (source_absolute_path, &err); - if (G_LIKELY (link_target != NULL)) - { - /* try to create the symbolic link */ - if (symlink (link_target, target_absolute_path) < 0) - tvilx_set_error_with_path (&err, _("Failed to create symbolic link \"%s\""), target_absolute_path); - - /* apply the file mode which was found for the source */ -#ifdef HAVE_LCHMOD - else if (lchmod (target_absolute_path, source_statb.st_mode) < 0) - tvilx_set_error_with_path (&err, _("Failed to change permissions of \"%s\""), target_absolute_path); -#endif - } - g_free (link_target); - break; -#endif - - default: - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Special files cannot be copied")); - break; - } - - /* update the progress for all but regular files if we succeed */ - if (err == NULL && !S_ISREG (source_statb.st_mode)) - (*callback) (source_statb.st_size, callback_data); - } - - /* check if we failed */ - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - return TRUE; -} - - - -/** - * _thunar_vfs_io_local_xfer_link: - * @source_path : the #ThunarVfsPath to the source file. - * @target_path : the #ThunarVfsPath to the target location. - * @error : return location for errors or %NULL. - * - * Creates a new symbolic link in @target_path pointing to the - * file at the @source_path. - * - * Return value: %TRUE if the symlink creation succeed, %FALSE - * otherwise. - **/ -gboolean -_thunar_vfs_io_local_xfer_link (const ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError **error) -{ -#ifdef HAVE_SYMLINK - struct stat source_statb; - GError *err = NULL; - gchar source_absolute_path[THUNAR_VFS_PATH_MAXSTRLEN]; - gchar target_absolute_path[THUNAR_VFS_PATH_MAXSTRLEN]; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (source_path), FALSE); - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (target_path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* determine the absolute source and target path */ - if (G_UNLIKELY (thunar_vfs_path_to_string (source_path, source_absolute_path, sizeof (source_absolute_path), error) < 0 - || thunar_vfs_path_to_string (target_path, target_absolute_path, sizeof (target_absolute_path), error) < 0)) - { - /* should not happen, but hey... */ - return FALSE; - } - - /* stat the source path */ - if (g_lstat (source_absolute_path, &source_statb) < 0) - { - /* the file does not exist, don't try to create a symlink then */ - tvilx_set_error_with_path (&err, _("Failed to determine file info for \"%s\""), source_absolute_path); - } - else - { - /* try to create the symlink */ - if (err == NULL && symlink (source_absolute_path, target_absolute_path) < 0) - tvilx_set_error_with_path (error, _("Failed to create symbolic link \"%s\""), target_absolute_path); - } - - /* check if we failed */ - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - return TRUE; -#else - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Symbolic links are not supported")); - return FALSE; -#endif -} - - - -#define __THUNAR_VFS_IO_LOCAL_XFER_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-io-local-xfer.h b/thunar-vfs/thunar-vfs-io-local-xfer.h deleted file mode 100644 index 1f9742b0d..000000000 --- a/thunar-vfs/thunar-vfs-io-local-xfer.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_IO_LOCAL_XFER_H__ -#define __THUNAR_VFS_IO_LOCAL_XFER_H__ - -#include <thunar-vfs/thunar-vfs-io-ops.h> - -G_BEGIN_DECLS; - -/** - * ThunarVfsIOLocalXferMode: - * @THUNAR_VFS_IO_LOCAL_XFER_COPY : generate path for copy. - * @THUNAR_VFS_IO_LOCAL_XFER_LINK : generate path for link. - * - * Modi for _thunar_vfs_io_local_xfer_next_path(). - **/ -typedef enum /*< skip >*/ -{ - THUNAR_VFS_IO_LOCAL_XFER_COPY, - THUNAR_VFS_IO_LOCAL_XFER_LINK, -} ThunarVfsIOLocalXferMode; - -ThunarVfsPath *_thunar_vfs_io_local_xfer_next_path (const ThunarVfsPath *source_path, - ThunarVfsPath *target_directory_path, - guint n, - ThunarVfsIOLocalXferMode mode, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -gboolean _thunar_vfs_io_local_xfer_copy (const ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - gboolean merge_directories, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -gboolean _thunar_vfs_io_local_xfer_link (const ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_IO_LOCAL_XFER_H__ */ diff --git a/thunar-vfs/thunar-vfs-io-local.c b/thunar-vfs/thunar-vfs-io-local.c deleted file mode 100644 index 615a36ce0..000000000 --- a/thunar-vfs/thunar-vfs-io-local.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -#ifdef HAVE_SYS_MOUNT_H -#include <sys/mount.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef HAVE_SYS_STATFS_H -#include <sys/statfs.h> -#endif -#ifdef HAVE_SYS_STATVFS_H -#include <sys/statvfs.h> -#endif -#ifdef HAVE_SYS_VFS_H -#include <sys/vfs.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#include <stdio.h> -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-io-local-xfer.h> -#include <thunar-vfs/thunar-vfs-io-local.h> -#include <thunar-vfs/thunar-vfs-mime-database-private.h> -#include <thunar-vfs/thunar-vfs-os.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* Use g_access(), g_lstat(), g_rename() and g_stat() on win32 */ -#if defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_access(path, mode) (access ((path), (mode))) -#define g_lstat(path, statb) (lstat ((path), (statb))) -#define g_rename(from, to) (rename ((from), (to))) -#define g_stat(path, statb) (stat ((path), (statb))) -#endif - -/* Use native strlcpy() if available */ -#if defined(HAVE_STRLCPY) -#define g_strlcpy(dst, src, size) (strlcpy ((dst), (src), (size))) -#endif - - - -static void thunar_vfs_io_local_listdir_internal (volatile GList **list, - gboolean *failure); - - - -/* we change the current working directory when listing - * directory contents to avoid going through the expensive - * inode lookup (in the kernel) all the time, but since - * the current working directory is a per-process rather - * than a per-thread setting, we need to protect the - * appropriate piece of code with a mutex, so only one - * thread at a time will change the working directory. - */ -G_LOCK_DEFINE_STATIC(_thunar_vfs_io_local_chdir); - - - -static void -thunar_vfs_io_local_listdir_internal (volatile GList **list, - gboolean *failure) -{ - ThunarVfsInfo *info; - GList *lp; - GList *ln; -#if defined(__GNUC__) && (defined(__i386__) || defined(__amd64__) || defined(__x86_64__)) - GList *lr; -#endif - - /* continue processing until the list is done */ - while (TRUE) - { - /* determine the next item from the list */ - lp = (GList *) *list; - if (G_UNLIKELY (lp == NULL)) - return; - - /* determine the next item in the list */ - ln = lp->next; - - /* try to adjust the list head pointer to the next item; since we may not be - * the only one to try that, checking if we actually succeed is required, and - * if not, we'll try again... - * - * IA32 and AMD64 are quite common architectures, so we try to avoid the - * function call overhead for the atomic operation here. - */ -#if defined(__GNUC__) && defined(__i386__) - __asm__ __volatile__ ("lock; cmpxchgl %2, %1" - : "=a" (lr), "=m" (*list) - : "r" (ln), "m" (*list), "0" (lp)); - - if (G_UNLIKELY (lr != lp)) - continue; -#elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) - __asm__ __volatile__ ("lock; cmpxchgq %q2, %1" - : "=a" (lr), "=m" (*list) - : "r" (ln), "m" (*list), "0" (lp)); - - if (G_UNLIKELY (lr != lp)) - continue; -#else - if (!g_atomic_pointer_compare_and_exchange ((volatile gpointer *) list, lp, ln)) - continue; -#endif - - /* try to determine the file info */ - info = _thunar_vfs_io_local_get_info (lp->data, thunar_vfs_path_get_name (lp->data), NULL); - - /* replace the path with the info on the list */ - if (G_LIKELY (info != NULL)) - { - /* just decrease the ref_count on path (info holds a reference now) */ - _thunar_vfs_path_unref_nofree (lp->data); - - /* and link the info instead */ - lp->data = info; - } - else - { - /* no info, may need to free the path... */ - thunar_vfs_path_unref (lp->data); - lp->data = NULL; - - /* ...and indicate that we had a failure */ - *failure = TRUE; - } - } -} - - - -/** - * _thunar_vfs_io_local_get_free_space: - * @path : a #ThunarVfsPath for a file:-URI. - * @free_space_return : return location for the amount of free space or %NULL. - * - * Determines the amount of free space available on the volume on which the - * file to which @path refers resides. If the system is able to determine the - * amount of free space, it will be placed into the location to which - * @free_space_return points and %TRUE will be returned, else the function - * will return %FALSE indicating that the system is unable to determine the - * amount of free space. - * - * Return value: %TRUE if the amount of free space could be determined, else - * %FALSE: - **/ -gboolean -_thunar_vfs_io_local_get_free_space (const ThunarVfsPath *path, - ThunarVfsFileSize *free_space_return) -{ -#if defined(HAVE_STATFS) && !defined(HAVE_STATVFS1) && !defined(__sgi__) && !defined(__sun__) && !defined(__sun) - struct statfs statfsb; -#elif defined(HAVE_STATVFS) || defined(HAVE_STATVFS1) - struct statvfs statfsb; -#endif - gboolean succeed; - gchar absolute_path[THUNAR_VFS_PATH_MAXSTRLEN]; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (path), FALSE); - - /* determine the absolute local path */ - if (thunar_vfs_path_to_string (path, absolute_path, sizeof (absolute_path), NULL) < 0) - return FALSE; - - /* determine the amount of free space for the mount point */ -#if defined(HAVE_STATFS) && !defined(HAVE_STATVFS1) && !defined(__sgi__) && !defined(__sun__) && !defined(__sun) - succeed = (statfs (absolute_path, &statfsb) == 0); /* the good old BSD way */ -#elif defined(HAVE_STATVFS1) - succeed = (statvfs1 (absolute_path, &statfsb, ST_WAIT) == 0); /* the new NetBSD way */ -#elif defined(HAVE_STATVFS) - succeed = (statvfs (absolute_path, &statfsb) == 0); /* the Linux, IRIX, Solaris way */ -#else -#error "Add support for your operating system here" -#endif - - /* return the free space */ - if (G_LIKELY (succeed && free_space_return != NULL)) - *free_space_return = ((ThunarVfsFileSize) statfsb.f_bavail * (ThunarVfsFileSize) statfsb.f_bsize); - - return succeed; -} - - - -/** - * _thunar_vfs_io_local_get_info: - * @path : the #ThunarVfsPath to use for the return info. - * @filename : the absolute, local path to the file or it's relative name (for _thunar_vfs_io_local_listdir()). - * @error : return location for errors or %NULL. - * - * @filename does not need to be the string representation of the - * @path. For example, @path could be a trash path, while @filename - * represents the file refered to by @path, but as a local file system - * path. - * - * The caller is responsible to free the returned object using - * thunar_vfs_info_unref() when no longer needed. - * - * Return value: the #ThunarVfsInfo for the file with the @filename - * or %NULL in case of an error. - **/ -ThunarVfsInfo* -_thunar_vfs_io_local_get_info (ThunarVfsPath *path, - const gchar *filename, - GError **error) -{ - ThunarVfsMimeInfo *fake_mime_info; - ThunarVfsInfo *info; - const guchar *s; - const gchar *name; - const gchar *str; - struct stat lsb; - struct stat sb; - XfceRc *rc; - GList *mime_infos; - GList *lp; - gchar *p; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - _thunar_vfs_return_val_if_fail (path != NULL, NULL); - - /* try to stat the file */ - if (G_UNLIKELY (g_lstat (filename, &lsb) < 0)) - { - _thunar_vfs_set_g_error_from_errno3 (error); - return NULL; - } - - /* allocate a new info object */ - info = _thunar_vfs_slice_new (ThunarVfsInfo); - info->path = thunar_vfs_path_ref (path); - info->ref_count = 1; - - info->custom_icon = NULL; - - /* determine the display name of the file */ - name = thunar_vfs_path_get_name (path); - for (s = (const guchar *) name; *s >= 32 && *s <= 127; ++s) - ; - if (G_LIKELY (*s == '\0')) - { - /* we don't need to perform any transformation if - * the file contains only valid ASCII characters. - */ - info->display_name = (gchar *) name; - } - else - { - /* determine the displayname using various tricks */ - info->display_name = g_filename_display_name (name); - - /* go on until s reaches the end of the string, as - * we need it for the hidden file detection below. - */ - for (; *s != '\0'; ++s) - ; - } - - /* check whether we have a hidden file here */ - if ((s - (const guchar *) name) > 1 && (*name == '.' || *(s - 1) == '~')) - info->flags = THUNAR_VFS_FILE_FLAGS_HIDDEN; - else - info->flags = THUNAR_VFS_FILE_FLAGS_NONE; - - /* determine the POSIX file attributes */ - if (G_LIKELY (!S_ISLNK (lsb.st_mode))) - { - info->type = (lsb.st_mode & S_IFMT) >> 12; - info->mode = lsb.st_mode & 07777; - info->uid = lsb.st_uid; - info->gid = lsb.st_gid; - info->size = lsb.st_size; - info->atime = lsb.st_atime; - info->ctime = lsb.st_ctime; - info->mtime = lsb.st_mtime; - info->device = lsb.st_dev; - } - else - { - /* whatever comes, we have a symlink here */ - info->flags |= THUNAR_VFS_FILE_FLAGS_SYMLINK; - - /* check if it's a broken link */ - if (g_stat (filename, &sb) == 0) - { - info->type = (sb.st_mode & S_IFMT) >> 12; - info->mode = sb.st_mode & 07777; - info->uid = sb.st_uid; - info->gid = sb.st_gid; - info->size = sb.st_size; - info->atime = sb.st_atime; - info->ctime = sb.st_ctime; - info->mtime = sb.st_mtime; - info->device = sb.st_dev; - } - else - { - info->type = THUNAR_VFS_FILE_TYPE_SYMLINK; - info->mode = lsb.st_mode & 07777; - info->uid = lsb.st_uid; - info->gid = lsb.st_gid; - info->size = lsb.st_size; - info->atime = lsb.st_atime; - info->ctime = lsb.st_ctime; - info->mtime = lsb.st_mtime; - info->device = lsb.st_dev; - } - } - - /* check if we can read the file */ - if ((info->mode & 00444) != 0 && g_access (filename, R_OK) == 0) - info->flags |= THUNAR_VFS_FILE_FLAGS_READABLE; - - /* check if we can write to the file */ - if ((info->mode & 00222) != 0 && g_access (filename, W_OK) == 0) - info->flags |= THUNAR_VFS_FILE_FLAGS_WRITABLE; - - /* determine the file's mime type */ - switch (info->type) - { - case THUNAR_VFS_FILE_TYPE_PORT: - info->mime_info = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "inode/port"); - break; - - case THUNAR_VFS_FILE_TYPE_DOOR: - info->mime_info = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "inode/door"); - break; - - case THUNAR_VFS_FILE_TYPE_SOCKET: - info->mime_info = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "inode/socket"); - break; - - case THUNAR_VFS_FILE_TYPE_SYMLINK: - info->mime_info = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "inode/symlink"); - break; - - case THUNAR_VFS_FILE_TYPE_BLOCKDEV: - info->mime_info = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "inode/blockdevice"); - break; - - case THUNAR_VFS_FILE_TYPE_DIRECTORY: - /* mime type for directories is cached */ - info->mime_info = thunar_vfs_mime_info_ref (_thunar_vfs_mime_inode_directory); - - /* check if we have the root folder here */ - if (G_UNLIKELY (filename[0] == G_DIR_SEPARATOR && filename[1] == '\0')) - { - /* root folder gets a special custom icon... */ - info->custom_icon = g_strdup ("gnome-dev-harddisk"); - - /* ...and a special display name */ - info->display_name = g_strdup (_("File System")); - } - break; - - case THUNAR_VFS_FILE_TYPE_CHARDEV: - info->mime_info = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "inode/chardevice"); - break; - - case THUNAR_VFS_FILE_TYPE_FIFO: - info->mime_info = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "inode/fifo"); - break; - - case THUNAR_VFS_FILE_TYPE_REGULAR: - /* determine the MIME-type for the regular file */ - info->mime_info = thunar_vfs_mime_database_get_info_for_file (_thunar_vfs_mime_database, filename, info->display_name); - - /* check if the file is executable (for security reasons - * we only allow execution of well known file types). - */ - if ((info->mode & 0444) != 0 && g_access (filename, X_OK) == 0) - { - /* most executable files are either of type application/x-executable or application/x-shellscript, hence - * we try to avoid the rather expensive get_infos_for_info() call here, checking for these types directly. - */ - if (info->mime_info == _thunar_vfs_mime_application_x_executable || info->mime_info == _thunar_vfs_mime_application_x_shellscript) - { - /* we can "safely" execute this file */ - info->flags |= THUNAR_VFS_FILE_FLAGS_EXECUTABLE; - } - else - { - /* check the associated mime types */ - mime_infos = thunar_vfs_mime_database_get_infos_for_info (_thunar_vfs_mime_database, info->mime_info); - for (lp = mime_infos; lp != NULL; lp = lp->next) - { - if (lp->data == _thunar_vfs_mime_application_x_executable || lp->data == _thunar_vfs_mime_application_x_shellscript) - { - /* we can "safely" execute this file */ - info->flags |= THUNAR_VFS_FILE_FLAGS_EXECUTABLE; - break; - } - } - thunar_vfs_mime_info_list_free (mime_infos); - } - } - - /* check if we have a .desktop (and NOT a .directory) file here */ - if (G_UNLIKELY (info->mime_info == _thunar_vfs_mime_application_x_desktop && strcmp (thunar_vfs_path_get_name (path), ".directory") != 0)) - { - /* try to query the hints from the .desktop file */ - rc = xfce_rc_simple_open (filename, TRUE); - if (G_LIKELY (rc != NULL)) - { - /* we're only interested in the desktop data */ - xfce_rc_set_group (rc, "Desktop Entry"); - - /* check if we have a valid icon info */ - str = xfce_rc_read_entry_untranslated (rc, "Icon", NULL); - if (G_LIKELY (str != NULL && *str != '\0')) - { - /* setup the custom icon */ - info->custom_icon = g_strdup (str); - - /* drop any suffix (e.g. '.png') from themed icons */ - if (!g_path_is_absolute (info->custom_icon)) - { - p = strrchr (info->custom_icon, '.'); - if (G_UNLIKELY (p != NULL)) - *p = '\0'; - } - } - - /* determine the type of the .desktop file */ - str = xfce_rc_read_entry_untranslated (rc, "Type", "Application"); - - /* check if the desktop file refers to an application - * and has a non-NULL Exec field set, or it's a Link - * with a valid URL field. - */ - if (G_LIKELY (exo_str_is_equal (str, "Application")) - && xfce_rc_read_entry (rc, "Exec", NULL) != NULL) - { - info->flags |= THUNAR_VFS_FILE_FLAGS_EXECUTABLE; - } - else if (G_LIKELY (exo_str_is_equal (str, "Link")) - && xfce_rc_read_entry (rc, "URL", NULL) != NULL) - { - info->flags |= THUNAR_VFS_FILE_FLAGS_EXECUTABLE; - } - - /* check if we have a valid name info */ - name = xfce_rc_read_entry (rc, "Name", NULL); - if (G_LIKELY (name != NULL && *name != '\0' && g_utf8_validate (name, -1, NULL) && strchr (name, G_DIR_SEPARATOR) == NULL)) - { - /* check if we declared the file as executable */ - if ((info->flags & THUNAR_VFS_FILE_FLAGS_EXECUTABLE) != 0) - { - /* if the name contains a dir separator, use only the part after - * the dir separator for checking. - */ - str = strrchr (name, G_DIR_SEPARATOR); - if (G_LIKELY (str == NULL)) - str = (gchar *) name; - else - str += 1; - - /* check if the file tries to look like a regular document (i.e. - * a display name of 'file.png'), maybe a virus or other malware. - */ - fake_mime_info = thunar_vfs_mime_database_get_info_for_name (_thunar_vfs_mime_database, str); - if (fake_mime_info != _thunar_vfs_mime_application_octet_stream && fake_mime_info != info->mime_info) - { - /* release the previous mime info */ - thunar_vfs_mime_info_unref (info->mime_info); - - /* set the MIME type of the file to 'x-thunar/suspected-malware' to indicate that - * it's not safe to trust the file content and execute it or otherwise operate on it. - */ - info->mime_info = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "x-thunar/suspected-malware"); - - /* reset the executable flag */ - info->flags &= ~THUNAR_VFS_FILE_FLAGS_EXECUTABLE; - - /* reset the custom icon */ - g_free (info->custom_icon); - info->custom_icon = NULL; - - /* reset the name str, so we display the real file name */ - name = NULL; - } - thunar_vfs_mime_info_unref (fake_mime_info); - } - - /* check if the name str wasn't reset */ - if (G_LIKELY (name != NULL)) - { - /* release the previous display name */ - if (G_UNLIKELY (info->display_name != thunar_vfs_path_get_name (path))) - g_free (info->display_name); - - /* use the name specified by the .desktop file as display name */ - info->display_name = g_strdup (name); - } - } - - /* close the file */ - xfce_rc_close (rc); - } - } - break; - - default: - _thunar_vfs_assert_not_reached (); - break; - } - - return info; -} - - - -/** - * _thunar_vfs_io_local_get_metadata: - * @path : a #ThunarVfsPath to a local file. - * @metadata : a #ThunarVfsInfoMetadata. - * @error : return location for errors or %NULL. - * - * Returns the @metadata for the @path, which must be a local - * path, or %NULL if the @metadata is not available for the - * @path. - * - * The caller is responsible to free the returned string using - * g_free() when no longer needed. - * - * Return value: the @metadata for @path or %NULL. - **/ -gchar* -_thunar_vfs_io_local_get_metadata (ThunarVfsPath *path, - ThunarVfsInfoMetadata metadata, - GError **error) -{ - gchar *absolute_path; - gchar *result = NULL; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (path), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* check the type of metadata we're interested in */ - switch (metadata) - { - case THUNAR_VFS_INFO_METADATA_FILE_LINK_TARGET: - /* read the link target of the file */ - absolute_path = thunar_vfs_path_dup_string (path); - result = g_file_read_link (absolute_path, error); - g_free (absolute_path); - break; - - default: - _thunar_vfs_set_g_error_not_supported (error); - break; - } - - return result; -} - - - -/** - * _thunar_vfs_io_local_listdir: - * @path : the path to the local directory to list its contents. - * @error : return location for errors or %NULL. - * - * Scans the folder pointed to by the specified @path and returns the list of - * #ThunarVfsInfo<!---->s for the files and folders in @path. - * - * The caller is responsible to free the returned list of #ThunarVfsInfo<!---->s - * using thunar_vfs_info_list_free() when no longer needed. - * - * Return value: a #GList of #ThunarVfsInfo<!---->s for the items in the local - * folder pointed to by @path. May be %NULL in case of an error, - * while on the other hand, %NULL may also indicate that the - * folder contains no files. - **/ -GList* -_thunar_vfs_io_local_listdir (ThunarVfsPath *path, - GError **error) -{ - GThreadPool *pool; - gboolean failure = FALSE; - gchar absolute_path[THUNAR_VFS_PATH_MAXSTRLEN]; - gchar *current_dir; - GList *list; - GList *lp; - GList *ln; - gint n; - gint ignore; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (path), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* try to determine the absolute path to the folder */ - n = thunar_vfs_path_to_string (path, absolute_path, THUNAR_VFS_PATH_MAXSTRLEN, error); - if (G_UNLIKELY (n < 0)) - return NULL; - - /* try to scan the specified directory */ - list = _thunar_vfs_os_scandir (path, absolute_path, TRUE, NULL, error); - if (G_UNLIKELY (list == NULL)) - return NULL; - - /* acquire the chdir lock */ - G_LOCK (_thunar_vfs_io_local_chdir); - - /* remember the current working directory */ - current_dir = g_get_current_dir (); - - /* change to the desired directory */ - if (chdir (absolute_path) < 0) - { - /* generate an error */ - _thunar_vfs_set_g_error_from_errno3 (error); - - /* release the paths */ - thunar_vfs_path_list_free (list); - list = NULL; - } - else - { - /* place the concurrent list pointer on the first item */ - lp = list; - - /* allocate a thread pool with max. 3 additional threads */ - pool = g_thread_pool_new ((GFunc) thunar_vfs_io_local_listdir_internal, &failure, 3, FALSE, NULL); - - /* schedule the 3 threads */ - g_thread_pool_push (pool, &lp, NULL); - g_thread_pool_push (pool, &lp, NULL); - g_thread_pool_push (pool, &lp, NULL); - - /* also use this thread to process items */ - thunar_vfs_io_local_listdir_internal ((volatile GList **) &lp, &failure); - - /* join the additional threads */ - g_thread_pool_free (pool, FALSE, TRUE); - - /* change back to the previous working directory */ - ignore = chdir (current_dir); - } - - /* release the chdir lock */ - G_UNLOCK (_thunar_vfs_io_local_chdir); - - /* check if we had a failure */ - if (G_UNLIKELY (failure)) - { - /* need to remove nullified list items */ - for (lp = list; lp != NULL; lp = ln) - { - /* remember the next item */ - ln = lp->next; - - /* check if we need to drop this one */ - if (G_UNLIKELY (lp->data == NULL)) - { - /* unlink the node from the list */ - if (ln != NULL) - ln->prev = lp->prev; - if (lp->prev != NULL) - lp->prev->next = ln; - else - list = ln; - g_list_free_1 (lp); - } - } - } - - /* cleanup */ - g_free (current_dir); - - return list; -} - - - -/** - * _thunar_vfs_io_local_copy_file: - * @source_path : the #ThunarVfsPath to the source file. - * @target_path : the #ThunarVfsPath to the target location. - * @target_path_return : the final #ThunarVfsPath of the target location, which may be - * different than the @target_path. - * @callback : the progress callback, invoked whenever a new chunk of data is copied. - * @callback_data : additional data to pass to @callback. - * @error : return location for errors or %NULL. - * - * Copies the file at the @source_path to the location specified by the - * @target_path. If @source_path and @target_path are equal a new target - * file name is choosen automatically, which indicates that its a copy of - * an existing file. - * - * The final target path, which may be different than @target_path, is - * placed in the location pointed to by @target_path_return. The caller - * is responsible to free the object using thunar_vfs_path_unref(). - * @target_path_return will only be set if %TRUE is returned. - * - * As a special case, if @callback returns %FALSE (which means the - * operation should be cancelled), this method returns %FALSE and - * @error is set to #G_FILE_ERROR_INTR. - * - * Return value: %TRUE if the file was successfully copied, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_local_copy_file (const ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - GError **error) -{ - ThunarVfsPath *path; - GError *err = NULL; - guint n; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (source_path), FALSE); - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (target_path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (target_path_return != NULL, FALSE); - _thunar_vfs_return_val_if_fail (callback != NULL, FALSE); - - /* check if source and target are the same */ - if (G_LIKELY (!thunar_vfs_path_equal (source_path, target_path))) - { - /* not the same, just a simple copy operation */ - if (_thunar_vfs_io_local_xfer_copy (source_path, target_path, callback, callback_data, TRUE, error)) - { - /* target path didn't change */ - *target_path_return = thunar_vfs_path_ref (target_path); - return TRUE; - } - return FALSE; - } - - /* generate a duplicate name for the target path */ - for (n = 1;; ++n) - { - /* try to generate the next duplicate path */ - path = _thunar_vfs_io_local_xfer_next_path (source_path, target_path->parent, n, THUNAR_VFS_IO_LOCAL_XFER_COPY, &err); - if (G_UNLIKELY (path == NULL)) - goto error; - - /* try to copy to the duplicate file */ - if (_thunar_vfs_io_local_xfer_copy (source_path, path, callback, callback_data, FALSE, &err)) - { - /* return the generated target path */ - *target_path_return = path; - return TRUE; - } - - /* release the generated path */ - thunar_vfs_path_unref (path); - - /* check if we cannot continue */ - if (err->domain != G_FILE_ERROR || err->code != G_FILE_ERROR_EXIST) - { -error: /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - /* and once again... */ - g_clear_error (&err); - } - - /* we never get here */ - _thunar_vfs_assert_not_reached (); - return FALSE; -} - - - -/** - * _thunar_vfs_io_local_link_file: - * @source_path : the #ThunarVfsPath to the source file. - * @target_path : the #ThunarVfsPath to the target file. - * @target_path_return : return location for the final target path or %NULL. - * @error : return location for errors or %NULL. - * - * The final target path, which may be different than @target_path, is placed in - * the location pointed to by @target_path_return. The caller is responsible to - * free the object using thunar_vfs_path_unref(). @target_path_return will only - * be set if %TRUE is returned. - * - * Return value: %FALSE if @error is set, else %TRUE. - **/ -gboolean -_thunar_vfs_io_local_link_file (const ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error) -{ - ThunarVfsPath *path; - GError *err = NULL; - guint n; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (source_path), FALSE); - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (target_path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (target_path_return != NULL, FALSE); - - /* check if source and target are the same */ - if (G_LIKELY (!thunar_vfs_path_equal (source_path, target_path))) - { - /* source and target aren't the same, just create the link */ - if (_thunar_vfs_io_local_xfer_link (source_path, target_path, error)) - { - *target_path_return = thunar_vfs_path_ref (target_path); - return TRUE; - } - return FALSE; - } - - /* generate a new link name for the target path */ - for (n = 1;; ++n) - { - /* try to generate the next link path */ - path = _thunar_vfs_io_local_xfer_next_path (source_path, target_path->parent, n, THUNAR_VFS_IO_LOCAL_XFER_LINK, &err); - if (G_UNLIKELY (path == NULL)) - goto error; - - { - } - - /* try to symlink to the new file */ - if (_thunar_vfs_io_local_xfer_link (source_path, path, &err)) - { - /* return the generated target path */ - *target_path_return = path; - return TRUE; - } - - /* release the generated path */ - thunar_vfs_path_unref (path); - - /* check if we cannot continue */ - if (err->domain != G_FILE_ERROR || err->code != G_FILE_ERROR_EXIST) - { -error: /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - /* and once again... */ - g_clear_error (&err); - } - - /* we never get here */ - _thunar_vfs_assert_not_reached (); - return FALSE; -} - - - -/** - * _thunar_vfs_io_local_move_file: - * @source_path : the #ThunarVfsPath to the source file. - * @target_path : the #ThunarVfsPath to the target file. - * @error : return location for errors or %NULL. - * - * Moves the file at the @source_path to the @target_path. - * - * Return value: %TRUE if the file at the @source_path was - * successfully moved to @target_path, %FALSE - * otherwise. - **/ -gboolean -_thunar_vfs_io_local_move_file (const ThunarVfsPath *source_path, - const ThunarVfsPath *target_path, - GError **error) -{ - gboolean succeed; - gchar *source_absolute_path; - gchar *target_absolute_path; - - /* make sure that the target path does not already exist */ - target_absolute_path = thunar_vfs_path_dup_string (target_path); - succeed = (g_access (target_absolute_path, F_OK) < 0); - if (G_LIKELY (succeed)) - { - /* try to rename the source file to the target path */ - source_absolute_path = thunar_vfs_path_dup_string (source_path); - succeed = (g_rename (source_absolute_path, target_absolute_path) == 0); - if (G_UNLIKELY (!succeed)) - { - /* we cannot perform the rename */ - _thunar_vfs_set_g_error_from_errno3 (error); - } - g_free (source_absolute_path); - } - else - { - /* we don't want to override files w/o warning */ - _thunar_vfs_set_g_error_from_errno (error, EEXIST); - } - g_free (target_absolute_path); - - return succeed; -} - - - -/** - * _thunar_vfs_io_local_rename: - * @info : a #ThunarVfsInfo for a local file. - * @name : the new file name in UTF-8 encoding. - * @error : return location for errors or %NULL. - * - * Tries to rename the file referred to by @info to the - * new @name. - * - * The rename operation is smart in that it checks the - * type of @info first, and if @info refers to a - * <filename>.desktop</filename> file, the file name - * won't be touched, but instead the <literal>Name</literal> - * field of the <filename>.desktop</filename> will be - * changed to @name. Else, if @info refers to a regular - * file or directory, the file will be given a new - * name. - * - * Return value: %TRUE on success, else %FALSE. - **/ -gboolean -_thunar_vfs_io_local_rename (ThunarVfsInfo *info, - const gchar *name, - GError **error) -{ - ThunarVfsMimeInfo *mime_info; - gchar src_path[THUNAR_VFS_PATH_MAXSTRLEN]; - gchar *dir_name; - gchar *dst_name; - gchar *dst_path; - - _thunar_vfs_return_val_if_fail (*name != '\0' && strchr (name, G_DIR_SEPARATOR) == NULL, FALSE); - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (info->path), FALSE); - _thunar_vfs_return_val_if_fail (g_utf8_validate (name, -1, NULL), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* determine the source path */ - if (thunar_vfs_path_to_string (info->path, src_path, sizeof (src_path), error) < 0) - return FALSE; - - /* check if we have a .desktop (and NOT a .directory) file here */ - if (G_UNLIKELY (info->mime_info == _thunar_vfs_mime_application_x_desktop && strcmp (thunar_vfs_path_get_name (info->path), ".directory") != 0)) - { - /* try to update the name in the .desktop file */ - if (!_thunar_vfs_desktop_file_set_value (src_path, "Name", name, error)) - return FALSE; - - /* release the previous display name */ - if (G_LIKELY (info->display_name != thunar_vfs_path_get_name (info->path))) - g_free (info->display_name); - - /* apply the new display name */ - info->display_name = g_strdup (name); - } - else - { - /* convert the destination file to local encoding */ - dst_name = g_filename_from_utf8 (name, -1, NULL, NULL, error); - if (G_UNLIKELY (dst_name == NULL)) - return FALSE; - - /* determine the destination path */ - dir_name = g_path_get_dirname (src_path); - dst_path = g_build_filename (dir_name, dst_name, NULL); - g_free (dst_name); - g_free (dir_name); - - /* verify that the rename target does not already exist */ - if (G_UNLIKELY (g_file_test (dst_path, G_FILE_TEST_EXISTS))) - { - /* tell the user that the file already exists */ - errno = EEXIST; -error2: - _thunar_vfs_set_g_error_from_errno3 (error); - g_free (dst_path); - return FALSE; - } - - /* perform the rename */ - if (G_UNLIKELY (g_rename (src_path, dst_path) < 0)) - goto error2; - - /* update the info's display name */ - if (info->display_name != thunar_vfs_path_get_name (info->path)) - g_free (info->display_name); - info->display_name = g_strdup (name); - - /* check if this is a hidden file now */ - if (strlen (name) > 1 && (name[0] == '.' || name[strlen (name) - 1] == '~')) - info->flags |= THUNAR_VFS_FILE_FLAGS_HIDDEN; - else - info->flags &= ~THUNAR_VFS_FILE_FLAGS_HIDDEN; - - /* update the info's path */ - thunar_vfs_path_unref (info->path); - info->path = thunar_vfs_path_new (dst_path, NULL); - - /* if we have a regular file here, then we'll need to determine - * the mime type again, as it may be based on the file name - */ - if (G_LIKELY (info->type == THUNAR_VFS_FILE_TYPE_REGULAR)) - { - mime_info = info->mime_info; - info->mime_info = thunar_vfs_mime_database_get_info_for_file (_thunar_vfs_mime_database, dst_path, info->display_name); - thunar_vfs_mime_info_unref (mime_info); - } - - /* clean up */ - g_free (dst_path); - } - - return TRUE; -} - - - -#define __THUNAR_VFS_IO_LOCAL_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-io-local.h b/thunar-vfs/thunar-vfs-io-local.h deleted file mode 100644 index 8dff1599b..000000000 --- a/thunar-vfs/thunar-vfs-io-local.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_IO_LOCAL_H__ -#define __THUNAR_VFS_IO_LOCAL_H__ - -#include <thunar-vfs/thunar-vfs-info.h> -#include <thunar-vfs/thunar-vfs-io-ops.h> - -G_BEGIN_DECLS; - -gboolean _thunar_vfs_io_local_get_free_space (const ThunarVfsPath *path, - ThunarVfsFileSize *free_space_return) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsInfo *_thunar_vfs_io_local_get_info (ThunarVfsPath *path, - const gchar *filename, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gchar *_thunar_vfs_io_local_get_metadata (ThunarVfsPath *path, - ThunarVfsInfoMetadata metadata, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -GList *_thunar_vfs_io_local_listdir (ThunarVfsPath *path, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_local_copy_file (const ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_local_link_file (const ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_local_move_file (const ThunarVfsPath *source_path, - const ThunarVfsPath *target_path, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_local_rename (ThunarVfsInfo *info, - const gchar *name, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_IO_LOCAL_H__ */ diff --git a/thunar-vfs/thunar-vfs-io-ops.c b/thunar-vfs/thunar-vfs-io-ops.c deleted file mode 100644 index 5082a0c64..000000000 --- a/thunar-vfs/thunar-vfs-io-ops.c +++ /dev/null @@ -1,509 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#include <stdio.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-io-local.h> -#include <thunar-vfs/thunar-vfs-io-ops.h> -#include <thunar-vfs/thunar-vfs-io-trash.h> -#include <thunar-vfs/thunar-vfs-monitor-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-thumb-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* Use g_lstat(), g_mkdir() and g_remove() on win32 */ -#if defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_lstat(path, statb) (lstat ((path), (statb))) -#define g_mkdir(path, mode) (mkdir ((path), (mode))) -#define g_remove(path) (remove ((path))) -#endif - - - -static void tvio_set_g_error_with_paths (GError **error, - const gchar *format, - ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError *err); - - - -static void -tvio_set_g_error_with_paths (GError **error, - const gchar *format, - ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError *err) -{ - gchar *source_display_name; - gchar *target_display_name; - gchar *s; - - /* determine a displayable variant of the source_path */ - s = _thunar_vfs_path_is_local (source_path) ? thunar_vfs_path_dup_string (source_path) : thunar_vfs_path_dup_uri (source_path); - source_display_name = g_filename_display_name (s); - g_free (s); - - /* determine a displayable variant of the target_path */ - s = _thunar_vfs_path_is_local (target_path) ? thunar_vfs_path_dup_string (target_path) : thunar_vfs_path_dup_uri (target_path); - target_display_name = g_filename_display_name (s); - g_free (s); - - /* generate a useful error message */ - s = g_strdup_printf (format, source_display_name, target_display_name); - g_set_error (error, err->domain, err->code, "%s: %s", s, err->message); - g_free (s); - - /* cleanup */ - g_free (target_display_name); - g_free (source_display_name); -} - - - -/** - * _thunar_vfs_io_ops_get_file_size_and_type: - * @path : the #ThunarVfsPath to the file whose size and type - * to determine. - * @size_return : return location for the file size or %NULL. - * @type_return : return location for the file type or %NULL. - * @error : return location for errors or %NULL. - * - * Determines the size and type of the file at @path. - * - * Return value: %TRUE if the size and type was determined successfully, - * %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_ops_get_file_size_and_type (ThunarVfsPath *path, - ThunarVfsFileSize *size_return, - ThunarVfsFileType *type_return, - GError **error) -{ - struct stat statb; - gboolean succeed = FALSE; - gchar *absolute_path; - gchar *uri; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* determine the absolute local path for the path object */ - absolute_path = _thunar_vfs_path_translate_dup_string (path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (absolute_path != NULL)) - { - /* determine the file info for the absolute path */ - succeed = (g_lstat (absolute_path, &statb) == 0); - if (G_LIKELY (succeed)) - { - /* return size and type if requested */ - if (G_LIKELY (size_return != NULL)) - *size_return = statb.st_size; - if (G_LIKELY (type_return != NULL)) - *type_return = (statb.st_mode & S_IFMT) >> 12; - } - else - { - /* generate a useful error message */ - uri = thunar_vfs_path_dup_uri (path); - _thunar_vfs_set_g_error_from_errno2 (error, errno, _("Failed to determine file info for \"%s\""), uri); - g_free (uri); - } - - /* cleanup */ - g_free (absolute_path); - } - - return succeed; -} - - - -/** - * _thunar_vfs_io_ops_copy_file: - * @source_path : the #ThunarVfsPath to the source file. - * @target_path : the #ThunarVfsPath to the target location. - * @target_path_return : the final #ThunarVfsPath of the target location, which may be - * different than the @target_path. - * @callback : the progress callback, invoked whenever a new chunk of data is copied. - * @callback_data : additional data to pass to @callback. - * @error : return location for errors or %NULL. - * - * Copies the file at the @source_path to the location specified by the - * @target_path. The final target location will be returned in @target_path_return. - * - * As a special case, if @callback returns %FALSE, the operation will be cancelled - * and an @error with %G_FILE_ERROR and %G_FILE_ERROR_INTR will be returned. - * - * Return value: %TRUE if the file was successfully copied, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_ops_copy_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - GError **error) -{ - gboolean succeed; - GError *err = NULL; - - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (source_path), FALSE); - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (target_path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (callback != NULL, FALSE); - - /* check if either source or target is trash */ - if (_thunar_vfs_path_is_trash (source_path) || _thunar_vfs_path_is_trash (target_path)) - { - /* copy to or from the trash may result in a new target path */ - succeed = _thunar_vfs_io_trash_copy_file (source_path, target_path, &target_path, callback, callback_data, &err); - } - else if (_thunar_vfs_path_is_local (source_path) && _thunar_vfs_path_is_local (target_path)) - { - /* copying files in the file system */ - succeed = _thunar_vfs_io_local_copy_file (source_path, target_path, &target_path, callback, callback_data, &err); - } - else - { - _thunar_vfs_set_g_error_not_supported (error); - return FALSE; - } - - /* check if we succeed */ - if (G_LIKELY (succeed)) - { - /* schedule a "created" event for the target path */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CREATED, target_path); - - /* return the new target path */ - if (G_LIKELY (target_path_return != NULL)) - *target_path_return = target_path; - else - thunar_vfs_path_unref (target_path); - } - else - { - /* generate a useful error message */ - tvio_set_g_error_with_paths (error, _("Failed to copy \"%s\" to \"%s\""), source_path, target_path, err); - g_error_free (err); - } - - return succeed; -} - - - -/** - * _thunar_vfs_io_ops_link_file: - * @source_path : the #ThunarVfsPath to the source file. - * @target_path : the #ThunarVfsPath to the target location. - * @target_path_return : return location for the final target path or %NULL. - * @error : return location for errors or %NULL. - * - * Creates a symbolic link at @target_path, which points to @source_path. The - * real target path may be different than the suggested @target_path, and will - * be returned in @target_path_return if not %NULL. - * - * The caller is responsible to free the #ThunarVfsPath object returned in - * @target_path_return using thunar_vfs_path_unref() when no longer needed - * if %TRUE is returned. - * - * Return value: %TRUE if the link was successfully created, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_ops_link_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error) -{ - gboolean succeed; - GError *err = NULL; - - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (source_path), FALSE); - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (target_path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* check if either source and target are local */ - if (_thunar_vfs_path_is_local (source_path) && _thunar_vfs_path_is_local (target_path)) - { - /* copying files in the file system */ - succeed = _thunar_vfs_io_local_link_file (source_path, target_path, &target_path, &err); - } - else - { - /* impossible to perform the link operation */ - _thunar_vfs_set_g_error_not_supported (&err); - succeed = FALSE; - } - - /* check if we succeed */ - if (G_LIKELY (succeed)) - { - /* schedule a "created" event for the target path */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CREATED, target_path); - - /* return the new target path */ - if (G_LIKELY (target_path_return != NULL)) - *target_path_return = target_path; - else - thunar_vfs_path_unref (target_path); - } - else - { - /* generate a useful error message */ - tvio_set_g_error_with_paths (error, _("Failed to link \"%s\" to \"%s\""), source_path, target_path, err); - g_error_free (err); - } - - return succeed; -} - - - -/** - * _thunar_vfs_io_ops_move_file: - * @source_path : the #ThunarVfsPath to the source file. - * @target_path : the #ThunarVfsPath to the target location. - * @target_path_return : the final #ThunarVfsPath of the target location, which - * may be different than the @target_path. - * @error : return location for errors or %NULL. - * - * Moves the file at the @source_path to the location specified by the - * @target_path. The final target location is returned in @target_path_return. - * - * Return value: %TRUE if the file was successfully moved, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_ops_move_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error) -{ - gboolean succeed; - GError *err = NULL; - - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (source_path), FALSE); - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (target_path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* check if either source or target is trash */ - if (_thunar_vfs_path_is_trash (source_path) || _thunar_vfs_path_is_trash (target_path)) - { - /* move to or from the trash may result in a new target path */ - succeed = _thunar_vfs_io_trash_move_file (source_path, target_path, &target_path, &err); - } - else if (_thunar_vfs_path_is_local (source_path) && _thunar_vfs_path_is_local (target_path)) - { - /* moving files in the file system */ - succeed = _thunar_vfs_io_local_move_file (source_path, target_path, &err); - - /* local move does not alter the target path */ - if (G_LIKELY (succeed)) - thunar_vfs_path_ref (target_path); - } - else - { - _thunar_vfs_set_g_error_not_supported (error); - return FALSE; - } - - /* check if we succeed */ - if (G_LIKELY (succeed)) - { - /* drop the thumbnails for the source path */ - _thunar_vfs_thumbnail_remove_for_path (source_path); - - /* schedule a "created" event for the target path */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CREATED, target_path); - - /* schedule a "deleted" event for the source path */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_DELETED, source_path); - - /* return the new target path */ - if (G_LIKELY (target_path_return != NULL)) - *target_path_return = target_path; - else - thunar_vfs_path_unref (target_path); - } - else - { - /* generate a useful error message */ - tvio_set_g_error_with_paths (error, _("Failed to move \"%s\" to \"%s\""), source_path, target_path, err); - g_error_free (err); - } - - return succeed; -} - - - -/** - * _thunar_vfs_io_ops_mkdir: - * @path : the #ThunarVfsPath to the directory to create. - * @mode : the new #ThunarVfsFileMode for the directory. - * @flags : see #ThunarVfsIOOpsFlags. - * @error : return location for errors or %NULL. - * - * Creates a new directory at the specified @path with the given @mode. - * - * Return value: %TRUE if the directory was created successfully or the - * directory exists and %THUNAR_VFS_IO_OPS_IGNORE_EEXIST - * was specified in @flags, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_ops_mkdir (ThunarVfsPath *path, - ThunarVfsFileMode mode, - ThunarVfsIOOpsFlags flags, - GError **error) -{ - gboolean succeed; - gchar *absolute_path; - gchar *display_name; - gint sverrno; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* translate the path object to an absolute path */ - absolute_path = _thunar_vfs_path_translate_dup_string (path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_UNLIKELY (absolute_path == NULL)) - return FALSE; - - /* try to create the directory with the given mode */ - succeed = (g_mkdir (absolute_path, mode) == 0 || (errno == EEXIST && (flags & THUNAR_VFS_IO_OPS_IGNORE_EEXIST) != 0)); - if (G_UNLIKELY (!succeed)) - { - /* save the errno value, may be modified */ - sverrno = errno; - - /* generate a useful error message */ - display_name = g_filename_display_name (absolute_path); - _thunar_vfs_set_g_error_from_errno2 (error, sverrno, _("Failed to create directory \"%s\""), display_name); - g_free (display_name); - } - else if (G_LIKELY (errno != EEXIST)) - { - /* schedule a "created" event for the directory path */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CREATED, path); - } - - /* cleanup */ - g_free (absolute_path); - - return succeed; -} - - - -/** - * _thunar_vfs_io_ops_remove: - * @path : the #ThunarVfsPath to the file to remove. - * @flags : see #ThunarVfsIOOpsFlags. - * @error : return location for errors or %NULL. - * - * Removes the file or folder at the specified @path. - * - * Return value: %TRUE if the file was successfully - * removed, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_ops_remove (ThunarVfsPath *path, - ThunarVfsIOOpsFlags flags, - GError **error) -{ - gboolean succeed; - GError *err = NULL; - gchar *message; - gchar *display_name; - gchar *absolute_path; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* remove using the appropriate backend */ - switch (thunar_vfs_path_get_scheme (path)) - { - case THUNAR_VFS_PATH_SCHEME_FILE: - absolute_path = thunar_vfs_path_dup_string (path); - succeed = (g_remove (absolute_path) == 0); - if (G_UNLIKELY (!succeed)) - _thunar_vfs_set_g_error_from_errno3 (&err); - g_free (absolute_path); - break; - - case THUNAR_VFS_PATH_SCHEME_TRASH: - succeed = _thunar_vfs_io_trash_remove (path, &err); - break; - - default: - _thunar_vfs_set_g_error_not_supported (error); - return FALSE; - } - - /* drop the thumbnails if the removal succeed */ - if (G_LIKELY (succeed)) - { - /* drop the thumbnails for the removed file */ - _thunar_vfs_thumbnail_remove_for_path (path); - - /* tell the monitor about the removed file */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_DELETED, path); - } - else if ((flags & THUNAR_VFS_IO_OPS_IGNORE_ENOENT) != 0 && err->domain == G_FILE_ERROR && err->code == G_FILE_ERROR_NOENT) - { - /* we should ignore ENOENT errors */ - g_error_free (err); - succeed = TRUE; - } - else - { - /* generate a useful error message */ - display_name = _thunar_vfs_path_dup_display_name (path); - message = g_strdup_printf (_("Failed to remove \"%s\""), display_name); - g_set_error (error, err->domain, err->code, "%s: %s", message, err->message); - g_free (display_name); - g_error_free (err); - g_free (message); - } - - return succeed; -} - - - -#define __THUNAR_VFS_IO_OPS_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-io-ops.h b/thunar-vfs/thunar-vfs-io-ops.h deleted file mode 100644 index 2dfa18d82..000000000 --- a/thunar-vfs/thunar-vfs-io-ops.h +++ /dev/null @@ -1,92 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_IO_OPS_H__ -#define __THUNAR_VFS_IO_OPS_H__ - -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-types.h> - -G_BEGIN_DECLS; - -/** - * ThunarVfsIOOpsFlags: - * @THUNAR_VFS_IO_OPS_NONE : no special behaviour. - * @THUNAR_VFS_IO_OPS_IGNORE_EEXIST : ignore EEXIST errors (for _thunar_vfs_io_ops_mkdir()). - * @THUNAR_VFS_IO_OPS_IGNORE_ENOENT : ignore ENOENT errors (for _thunar_vfs_io_ops_remove()). - * - * Flags for I/O operations. - **/ -typedef enum /*< flags, skip >*/ -{ - THUNAR_VFS_IO_OPS_NONE = 0L, - THUNAR_VFS_IO_OPS_IGNORE_EEXIST = (1L << 0), - THUNAR_VFS_IO_OPS_IGNORE_ENOENT = (1L << 1), -} ThunarVfsIOOpsFlags; - -/** - * ThunarVfsIOOpsProgressCallback: - * @chunk_size : the size of the next completed chunk of copied data. - * @callback_data : callback data specified for _thunar_vfs_io_ops_copy_file(). - * - * Invoked during _thunar_vfs_io_ops_copy_file() to notify the caller - * about the progress of the operation. - * - * Return value: %FALSE to cancel the operation, %TRUE to continue. - **/ -typedef gboolean (*ThunarVfsIOOpsProgressCallback) (ThunarVfsFileSize chunk_size, - gpointer callback_data); - -gboolean _thunar_vfs_io_ops_get_file_size_and_type (ThunarVfsPath *path, - ThunarVfsFileSize *size_return, - ThunarVfsFileType *type_return, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -gboolean _thunar_vfs_io_ops_copy_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_ops_link_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_ops_move_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -gboolean _thunar_vfs_io_ops_mkdir (ThunarVfsPath *path, - ThunarVfsFileMode mode, - ThunarVfsIOOpsFlags flags, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -gboolean _thunar_vfs_io_ops_remove (ThunarVfsPath *path, - ThunarVfsIOOpsFlags flags, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_IO_OPS_H__ */ diff --git a/thunar-vfs/thunar-vfs-io-scandir.c b/thunar-vfs/thunar-vfs-io-scandir.c deleted file mode 100644 index 174cf235b..000000000 --- a/thunar-vfs/thunar-vfs-io-scandir.c +++ /dev/null @@ -1,173 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-io-scandir.h> -#include <thunar-vfs/thunar-vfs-io-trash.h> -#include <thunar-vfs/thunar-vfs-os.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -static GList *tvis_collect (ThunarVfsPath *path, - volatile gboolean *cancelled, - gboolean recursive, - gboolean follow_links, - gchar *buffer, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - - - -static GList* -tvis_collect (ThunarVfsPath *path, - volatile gboolean *cancelled, - gboolean recursive, - gboolean follow_links, - gchar *buffer, - GError **error) -{ - GError *err = NULL; - GList *directories = NULL; - GList *child_path_list; - GList *path_list; - GList *lp; - - /* scan the directory, according to the path scheme */ - switch (thunar_vfs_path_get_scheme (path)) - { - case THUNAR_VFS_PATH_SCHEME_FILE: - if (thunar_vfs_path_to_string (path, buffer, THUNAR_VFS_PATH_MAXSTRLEN, error) >= 0) - path_list = _thunar_vfs_os_scandir (path, buffer, follow_links, recursive ? &directories : NULL, error); - else - path_list = NULL; - break; - - case THUNAR_VFS_PATH_SCHEME_TRASH: - path_list = _thunar_vfs_io_trash_scandir (path, follow_links, recursive ? &directories : NULL, error); - break; - - default: - _thunar_vfs_set_g_error_not_supported (error); - return NULL; - } - - /* perform the recursion */ - for (lp = directories; lp != NULL; lp = lp->next) - { - /* check if the user cancelled the scanning */ - if (G_UNLIKELY (cancelled != NULL && *cancelled)) - { - /* user cancellation is EINTR */ - _thunar_vfs_set_g_error_from_errno (error, EINTR); -error: - thunar_vfs_path_list_free (path_list); - path_list = NULL; - break; - } - - child_path_list = tvis_collect (lp->data, cancelled, TRUE, follow_links, buffer, &err); - if (G_UNLIKELY (err != NULL)) - { - /* we can ignore certain errors here */ - if (G_UNLIKELY (err->domain != G_FILE_ERROR || (err->code != G_FILE_ERROR_ACCES && err->code != G_FILE_ERROR_NOTDIR - && err->code != G_FILE_ERROR_NOENT && err->code != G_FILE_ERROR_PERM))) - { - /* propagate the error */ - g_propagate_error (error, err); - goto error; - } - - /* ignored that error */ - g_clear_error (&err); - } - - /* append the paths to our list */ - path_list = g_list_concat (child_path_list, path_list); - } - - /* cleanup */ - g_list_free (directories); - - return path_list; -} - - - -/** - * _thunar_vfs_io_scandir: - * @path : the #ThunarVfsPath of the directory to scan. - * @cancelled : pointer to a volatile boolean variable, which if - * %TRUE means to cancel the scan operation. May be - * %NULL in which case the scanner cannot be - * cancelled. - * @flags : scanner flags. - * @error : return location for errors or %NULL. - * - * The caller is responsible to free the returned list - * using thunar_vfs_path_list_free() when no longer - * needed. - * - * If @cancelled becomes true during the scan operation, %NULL - * will be returned and @error will be set to %G_FILE_ERROR_INTR. - * - * Return value: - **/ -GList* -_thunar_vfs_io_scandir (ThunarVfsPath *path, - volatile gboolean *cancelled, - ThunarVfsIOScandirFlags flags, - GError **error) -{ - gchar buffer[THUNAR_VFS_PATH_MAXSTRLEN]; - - _thunar_vfs_return_val_if_fail (path != NULL, NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* try to collect the paths */ - return tvis_collect (path, cancelled, - (flags & THUNAR_VFS_IO_SCANDIR_RECURSIVE), - (flags & THUNAR_VFS_IO_SCANDIR_FOLLOW_LINKS), - buffer, error); -} - - - -#define __THUNAR_VFS_IO_SCANDIR_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-io-scandir.h b/thunar-vfs/thunar-vfs-io-scandir.h deleted file mode 100644 index f5772a61a..000000000 --- a/thunar-vfs/thunar-vfs-io-scandir.h +++ /dev/null @@ -1,53 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_IO_SCANDIR_H__ -#define __THUNAR_VFS_IO_SCANDIR_H__ - -#include <thunar-vfs/thunar-vfs-path.h> -#include <thunar-vfs/thunar-vfs-types.h> - -G_BEGIN_DECLS; - -/** - * ThunarVfsIOScandirFlags: - * @THUNAR_VFS_IO_SCANDIR_RECURSIVE : scan directories recursively. - * @THUNAR_VFS_IO_SCANDIR_FOLLOW_LINKS : follow symbolic links to directories. - * - * Flags for _thnar_vfs_io_scandir(). - **/ -typedef enum /*< flags, skip >*/ -{ - THUNAR_VFS_IO_SCANDIR_RECURSIVE = (1L << 0), - THUNAR_VFS_IO_SCANDIR_FOLLOW_LINKS = (1L << 1), -} ThunarVfsIOScandirFlags; - -GList *_thunar_vfs_io_scandir (ThunarVfsPath *path, - volatile gboolean *cancelled, - ThunarVfsIOScandirFlags flags, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_IO_SCANDIR_H__ */ diff --git a/thunar-vfs/thunar-vfs-io-trash.c b/thunar-vfs/thunar-vfs-io-trash.c deleted file mode 100644 index 8ca037055..000000000 --- a/thunar-vfs/thunar-vfs-io-trash.c +++ /dev/null @@ -1,1748 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -#ifdef HAVE_SYS_MOUNT_H -#include <sys/mount.h> -#endif -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#include <stdio.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_SYSLOG_H -#include <syslog.h> -#endif -#ifdef HAVE_TIME_H -#include <time.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-io-local.h> -#include <thunar-vfs/thunar-vfs-io-trash.h> -#include <thunar-vfs/thunar-vfs-mime-database-private.h> -#include <thunar-vfs/thunar-vfs-monitor-private.h> -#include <thunar-vfs/thunar-vfs-os.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* Use g_mkdir(), g_open(), g_remove(), g_lstat(), and g_unlink() on win32 */ -#if defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_mkdir(path, mode) (mkdir ((path), (mode))) -#define g_open(path, flags, mode) (open ((path), (flags), (mode))) -#define g_remove(path) (remove ((path))) -#define g_lstat(path, statb) (lstat ((path), (statb))) -#define g_unlink(path) (unlink ((path))) -#endif - - - -static inline gboolean tvit_initialize_trash_dir (const gchar *trash_dir) G_GNUC_WARN_UNUSED_RESULT; -static void tvit_rescan_mount_points (void); -static inline gchar *tvit_resolve_original_path (guint trash_id, - const gchar *original_path_escaped, - const gchar *relative_path, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -static guint tvit_resolve_trash_dir_to_id (const gchar *trash_dir) G_GNUC_WARN_UNUSED_RESULT; -static gchar *tvit_trash_dir_for_mount_point (const gchar *top_dir, - gboolean create) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - - - -/* representation of a trash directory */ -typedef struct -{ - gchar *top_dir; /* toplevel directory for the trash (mount point or home dir) */ - gchar *trash_dir; /* absolute path to the trash directory with "files" and "info" */ - time_t mtime; /* the last modification time of the "files" folder */ - guint empty : 1; /* %TRUE if the trash is empty */ -} ThunarVfsIOTrash; - -/* list of all known ThunarVfsIOTrashes */ -static ThunarVfsIOTrash *_thunar_vfs_io_trashes; -static guint _thunar_vfs_io_n_trashes; - -/* the trash rescan timer id */ -static guint _thunar_vfs_io_trash_timer_id; - -/* the device of the home folder */ -static dev_t _thunar_vfs_io_trash_homedev; - -/* the trash subsystem lock */ -G_LOCK_DEFINE_STATIC (_thunar_vfs_io_trash); - - - -static inline gboolean -tvit_initialize_trash_dir (const gchar *trash_dir) -{ - const gchar *name; - struct stat statb; - gboolean result = FALSE; - gchar *files_dir; - gchar *info_dir; - gchar *basename; - gchar *dirname; - GDir *dp; - - /* try to create the directory with the appropriate permissions */ - if (G_LIKELY (g_mkdir (trash_dir, 0700) == 0)) - { - /* check if the trash dir is usable */ - if (G_LIKELY (g_lstat (trash_dir, &statb) == 0)) - { - /* the trash_dir must be owned by user now, with rwx for user only */ - if (G_LIKELY (statb.st_uid == getuid () && (statb.st_mode & 0777) == 0700)) - { - /* we want to be smart, and we need to be smarter - * than file systems like msdosfs, which translate - * for example ".Trash-200" to "trash-20", which - * we don't want to support, so be sure the - * directory now contains an entry with our name. - */ - dirname = g_path_get_dirname (trash_dir); - dp = g_dir_open (dirname, 0, NULL); - if (G_LIKELY (dp != NULL)) - { - /* determine the basename to look for */ - basename = g_path_get_basename (trash_dir); - do - { - /* compare the next entry */ - name = g_dir_read_name (dp); - if (G_LIKELY (name != NULL)) - result = (strcmp (name, basename) == 0); - } - while (name != NULL && !result); - g_free (basename); - } - g_free (dirname); - - /* check if the entry was present */ - if (G_LIKELY (result)) - { - /* create the infos and files directories */ - info_dir = g_build_filename (trash_dir, "info", NULL); - files_dir = g_build_filename (trash_dir, "files", NULL); - result = (g_mkdir (info_dir, 0700) == 0 && g_mkdir (files_dir, 0700) == 0); - g_free (files_dir); - g_free (info_dir); - } - } - - if (G_UNLIKELY (!result)) - { - /* Not good, e.g. USB key. Delete the trash directory again. - * I'm paranoid, it would be better to find a solution that allows - * to trash directly onto the USB key, but I don't see how that would - * pass the security checks. It would also make the USB key appears as - * empty when it's in fact full... - * - * Thanks to the KDE guys for this tip! - */ - rmdir (trash_dir); - } - } - } - - return result; -} - - - -static void -tvit_rescan_mount_points (void) -{ - ExoMountPoint *mount_point; - GSList *mount_points; - GSList *lp; - gchar *trash_dir; - guint trash_id; - - /* determine the currently active mount points */ - mount_points = exo_mount_point_list_active (NULL); - for (lp = mount_points; lp != NULL; lp = lp->next) - { - /* skip pseudo file systems as we won't find trash directories - * there, and of course skip read-only file systems, as we - * cannot trash to them anyway... - */ - mount_point = (ExoMountPoint *) lp->data; - if (strncmp (mount_point->device, "/dev/", 5) == 0 - && (mount_point->flags & EXO_MOUNT_POINT_READ_ONLY) == 0) - { - /* lookup the trash directory for this mount point */ - trash_dir = tvit_trash_dir_for_mount_point (mount_point->folder, FALSE); - if (G_UNLIKELY (trash_dir != NULL)) - { - /* check if the trash dir was already registered */ - trash_id = tvit_resolve_trash_dir_to_id (trash_dir); - if (G_UNLIKELY (trash_id == 0)) - { - /* allocate space for the new trash directory */ - trash_id = _thunar_vfs_io_n_trashes++; - _thunar_vfs_io_trashes = g_renew (ThunarVfsIOTrash, - _thunar_vfs_io_trashes, - _thunar_vfs_io_n_trashes); - - /* register the new trash directory */ - _thunar_vfs_io_trashes[trash_id].top_dir = g_strdup (mount_point->folder); - _thunar_vfs_io_trashes[trash_id].trash_dir = trash_dir; - _thunar_vfs_io_trashes[trash_id].mtime = (time_t) -1; - } - else - { - /* cleanup */ - g_free (trash_dir); - } - } - } - exo_mount_point_free (mount_point); - } - g_slist_free (mount_points); -} - - - -static inline gchar* -tvit_resolve_original_path (guint trash_id, - const gchar *original_path_escaped, - const gchar *relative_path, - GError **error) -{ - gchar *original_path_unescaped; - gchar *absolute_path = NULL; - gchar *top_dir; - - /* unescape the path according to RFC 2396 */ - original_path_unescaped = _thunar_vfs_unescape_rfc2396_string (original_path_escaped, -1, "/", FALSE, error); - if (G_UNLIKELY (original_path_unescaped == NULL)) - return NULL; - - /* check if we have a relative path here */ - if (!g_path_is_absolute (original_path_unescaped)) - { - /* determine the toplevel directory for the trash-id */ - top_dir = _thunar_vfs_io_trash_get_top_dir (trash_id, error); - if (G_LIKELY (top_dir != NULL)) - absolute_path = g_build_filename (top_dir, original_path_unescaped, relative_path, NULL); - g_free (original_path_unescaped); - g_free (top_dir); - } - else - { - /* generate the absolute with the relative part */ - absolute_path = g_build_filename (original_path_unescaped, relative_path, NULL); - g_free (original_path_unescaped); - } - - return absolute_path; -} - - - -static guint -tvit_resolve_trash_dir_to_id (const gchar *trash_dir) -{ - guint id; - - for (id = 1; id < _thunar_vfs_io_n_trashes; ++id) - if (strcmp (_thunar_vfs_io_trashes[id].trash_dir, trash_dir) == 0) - return id; - - /* fallback to home trash! */ - return 0; -} - - - -static gchar* -tvit_trash_dir_for_mount_point (const gchar *top_dir, - gboolean create) -{ - struct stat statb; - gchar *trash_dir; - gchar *dir; - uid_t uid; - - /* determine our UID */ - uid = getuid (); - - /* try with $top_dir/.Trash directory first (created by the administrator) */ - dir = g_build_filename (top_dir, ".Trash", NULL); - if (g_lstat (dir, &statb) == 0) - { - /* must be a directory owned by root with sticky bit and wx for 'others' */ - if (statb.st_uid == 0 && S_ISDIR (statb.st_mode) && (statb.st_mode & (S_ISVTX | S_IWOTH | S_IXOTH)) == (S_ISVTX | S_IWOTH | S_IXOTH)) - { - /* check if $top_dir/.Trash/$uid exists */ - trash_dir = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%u", dir, (guint) uid); - if (g_lstat (trash_dir, &statb) == 0) - { - /* must be a directory owned by user with rwx only for user */ - if (statb.st_uid == uid && S_ISDIR (statb.st_mode) && (statb.st_mode & 0777) == 0700) - { -use_trash_dir: /* release the root dir */ - g_free (dir); - - /* jap, that's our trash directory then */ - return trash_dir; - } - else - { -#ifdef HAVE_SYSLOG - /* the specification says the system administrator SHOULD be informed, and so we do */ - syslog (LOG_PID | LOG_USER | LOG_WARNING, "Trash directory %s exists, but didn't pass the security checks, can't use it", trash_dir); -#endif - } - } - else if (create && errno == ENOENT && tvit_initialize_trash_dir (trash_dir)) - { - /* jap, successfully created */ - goto use_trash_dir; - } - g_free (trash_dir); - } - else - { -#ifdef HAVE_SYSLOG - /* the specification says the system administrator SHOULD be informed, and so we do */ - syslog (LOG_PID | LOG_USER | LOG_WARNING, "Root trash directory %s exists, but didn't pass the security checks, can't use it", dir); -#endif - } - } - g_free (dir); - - /* try with $top_dir/.Trash-$uid instead */ - trash_dir = g_strdup_printf ("%s" G_DIR_SEPARATOR_S ".Trash-%u", top_dir, (guint) uid); - if (g_lstat (trash_dir, &statb) == 0) - { - /* must be a directory owned by user with rwx only for user */ - if (statb.st_uid == uid && S_ISDIR (statb.st_mode) && (statb.st_mode & 0777) == 0700) - { - /* jap, found it */ - return trash_dir; - } - else - { -#ifdef HAVE_SYSLOG - /* the specification says the system administrator SHOULD be informed, and so we do */ - syslog (LOG_PID | LOG_USER | LOG_WARNING, "Trash directory %s exists, but didn't pass the security checks, can't use it", trash_dir); -#endif - } - } - else if (create && errno == ENOENT && tvit_initialize_trash_dir (trash_dir)) - { - /* jap, found it */ - return trash_dir; - } - g_free (trash_dir); - - /* no usable trash dir */ - return NULL; -} - - - -/** - * _thunar_vfs_io_trash_scan: - * - * Initially scans the trash directories if _thunar_vfs_io_trash_rescan() - * was not called so far. - **/ -void -_thunar_vfs_io_trash_scan (void) -{ - /* scan the trash if not already done */ - if (G_UNLIKELY (_thunar_vfs_io_trash_timer_id == 0)) - _thunar_vfs_io_trash_rescan (); -} - - - -/** - * _thunar_vfs_io_trash_rescan: - * - * Rescans all trash directories and emits a changed event for - * the trash root folder if any of the trash directories changed. - * - * Return value: always %TRUE due to implementation details. - **/ -gboolean -_thunar_vfs_io_trash_rescan (void) -{ - struct stat statb; - time_t mtime; - gchar *files_dir; - guint n; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_io_trashes != NULL, FALSE); - - /* acquire the trash subsystem lock */ - G_LOCK (_thunar_vfs_io_trash); - - /* check if we already scheduled the trash scan timer */ - if (G_UNLIKELY (_thunar_vfs_io_trash_timer_id == 0)) - { - /* initially scan the active mount points */ - tvit_rescan_mount_points (); - - /* schedule a timer to regularly scan the trash directories */ - _thunar_vfs_io_trash_timer_id = g_timeout_add (5 * 1000, (GSourceFunc) _thunar_vfs_io_trash_rescan, NULL); - } - - /* scan all known trash directories */ - for (n = 0; n < _thunar_vfs_io_n_trashes; ++n) - { - /* determine the absolute path to the "files" directory */ - files_dir = g_build_filename (_thunar_vfs_io_trashes[n].trash_dir, "files", NULL); - - /* check if the "files" directory was changed */ - mtime = (g_lstat (files_dir, &statb) == 0) ? statb.st_mtime : 0; - if (_thunar_vfs_io_trashes[n].mtime != mtime) - { - /* remember the new mtime */ - _thunar_vfs_io_trashes[n].mtime = mtime; - - /* check if the directory is empty now */ - _thunar_vfs_io_trashes[n].empty = _thunar_vfs_os_is_dir_empty (files_dir); - - /* schedule a "changed" event for the trash root folder */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CHANGED, _thunar_vfs_path_trash_root); - } - - /* cleanup */ - g_free (files_dir); - } - - /* release the trash subsystem lock */ - G_UNLOCK (_thunar_vfs_io_trash); - - /* keep the timer alive */ - return TRUE; -} - - - -/** - * _thunar_vfs_io_trash_rescan_mounts: - * - * Rescans all currently mounted devices to see if a new trash directory - * is available on one of the active mount points. This method is called - * by the #ThunarVfsVolume<!---->s whenever a change is noticed. - **/ -void -_thunar_vfs_io_trash_rescan_mounts (void) -{ - G_LOCK (_thunar_vfs_io_trash); - tvit_rescan_mount_points (); - G_UNLOCK (_thunar_vfs_io_trash); -} - - - -/** - * _thunar_vfs_io_trash_get_top_dir: - * @trash_id : the id of the trash, whose absolute toplevel directory to return. - * @error : return location for errors or %NULL. - * - * Returns the absolute path to the toplevel directory for the - * trash with the specified @trash_id, or %NULL if the @trash_id - * is invalid. - * - * The caller is responsible to free the returned string using - * g_free() when no longer needed. - * - * Return value: the absolute path to the toplevel directory for - * the trash with the specified @trash_id, or %NULL - * in case of an error. - **/ -gchar* -_thunar_vfs_io_trash_get_top_dir (guint trash_id, - GError **error) -{ - gchar *top_dir; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* acquire the trash subsystem lock */ - G_LOCK (_thunar_vfs_io_trash); - - /* check if the trash-id is valid */ - if (G_LIKELY (trash_id < _thunar_vfs_io_n_trashes)) - { - /* just return the absolute path to the trash's top dir */ - top_dir = g_strdup (_thunar_vfs_io_trashes[trash_id].top_dir); - } - else - { - /* the trash-id is invalid */ - _thunar_vfs_set_g_error_from_errno (error, ENOENT); - top_dir = NULL; - } - - /* release the trash subsystem lock */ - G_UNLOCK (_thunar_vfs_io_trash); - - return top_dir; -} - - - -/** - * _thunar_vfs_io_trash_get_trash_dir: - * @trash_id : the id of the trash, whose absolute path to return. - * @error : return location for errors or %NULL. - * - * Returns the absolute path to the trash directory for the trash - * with the specified @trash_id, or %NULL if the @trash_id is - * invalid. - * - * The caller is responsible to free the returned string using - * g_free() when no longer needed. - * - * Return value: the absolute path to the trash directory with - * the specified @trash_id, or %NULL on error. - **/ -gchar* -_thunar_vfs_io_trash_get_trash_dir (guint trash_id, - GError **error) -{ - gchar *trash_dir; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* acquire the trash subsystem lock */ - G_LOCK (_thunar_vfs_io_trash); - - /* check if the trash-id is valid */ - if (G_LIKELY (trash_id < _thunar_vfs_io_n_trashes)) - { - /* just return the absolute path to the trash */ - trash_dir = g_strdup (_thunar_vfs_io_trashes[trash_id].trash_dir); - } - else - { - /* the trash-id is invalid */ - _thunar_vfs_set_g_error_from_errno (error, ENOENT); - trash_dir = NULL; - } - - /* release the trash subsystem lock */ - G_UNLOCK (_thunar_vfs_io_trash); - - return trash_dir; -} - - - -/** - * _thunar_vfs_io_trash_get_trash_info: - * @path : a valid trash:-URI, which is not the trash root path. - * @original_path_return : return location for the original path or %NULL. - * @deletion_date_return : return location for the deletion date or %NULL. - * @error : return location for errors or %NULL. - * - * Reads the <filename>.trashinfo</filename> file for the @path and sets - * @original_path_return and @deletion_date_return appropriately. - * - * Return value: %TRUE if the info was determined successfully, %FALSE on error. - **/ -gboolean -_thunar_vfs_io_trash_get_trash_info (const ThunarVfsPath *path, - gchar **original_path_return, - gchar **deletion_date_return, - GError **error) -{ - GKeyFile *key_file; - GError *err = NULL; - gchar *original_path; - gchar *relative_path; - gchar *info_file; - gchar *trash_dir; - gchar *file_id = NULL; - guint trash_id; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* try to parse the trash path */ - if (!_thunar_vfs_io_trash_path_parse (path, &trash_id, &file_id, &relative_path, error)) - return FALSE; - - /* determine the .trashinfo file for the path */ - trash_dir = _thunar_vfs_io_trash_get_trash_dir (trash_id, &err); - info_file = (trash_dir != NULL) ? g_strconcat (trash_dir, G_DIR_SEPARATOR_S "info" G_DIR_SEPARATOR_S, file_id, ".trashinfo", NULL) : NULL; - g_free (trash_dir); - - /* check if we have a path */ - if (G_LIKELY (info_file != NULL)) - { - /* parse the .trashinfo file */ - key_file = g_key_file_new (); - if (g_key_file_load_from_file (key_file, info_file, 0, &err)) - { - /* query the original path if requested */ - if (G_LIKELY (original_path_return != NULL)) - { - /* read the original path from the .trashinfo file */ - original_path = g_key_file_get_string (key_file, "Trash Info", "Path", &err); - if (G_LIKELY (original_path != NULL)) - { - /* determine the absolute path for the original path */ - *original_path_return = tvit_resolve_original_path (trash_id, original_path, relative_path, &err); - g_free (original_path); - } - } - - /* query the deletion date if requested */ - if (err == NULL && deletion_date_return != NULL) - *deletion_date_return = g_key_file_get_string (key_file, "Trash Info", "DeletionDate", &err); - } - g_key_file_free (key_file); - } - - /* propagate a possible error */ - if (G_UNLIKELY (err != NULL)) - g_propagate_error (error, err); - - /* cleanup */ - g_free (relative_path); - g_free (info_file); - g_free (file_id); - - return (err == NULL); -} - - - -/** - * _thunar_vfs_io_trash_new_trash_info: - * @original_path : the original, local path of the file to delete. - * @trash_id_return : return location for the trash id. - * @file_id_return : return location for the file id. - * @error : return location for errors or %NULL. - * - * Generates a new <filename>.trashinfo</filename> file for the file - * at the @original_path and returns the trash-id of the target trash - * in @trash_id_return and the file-id of the target trash file in - * @file_id_return. The caller is responsible to free the string - * returned in @file_id_return using g_free() when no longer needed. - * - * Return value: %TRUE if the <filename>.trashinfo</filename> was - * successfully generated, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_trash_new_trash_info (const ThunarVfsPath *original_path, - guint *trash_id_return, - gchar **file_id_return, - GError **error) -{ - const gchar *original_name = thunar_vfs_path_get_name (original_path); - struct stat statb; - gchar absolute_path[THUNAR_VFS_PATH_MAXSTRLEN]; - gchar deletion_date[128]; - gchar *mount_point = NULL; - gchar *trash_dir = NULL; - gchar *original_uri; - gchar *info_dir; - gchar *content; - guint trash_id = 0; - guint n; - gint fd; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_local (original_path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (trash_id_return != NULL, FALSE); - _thunar_vfs_return_val_if_fail (file_id_return != NULL, FALSE); - - /* determine the absolute path of the original file */ - if (thunar_vfs_path_to_string (original_path, absolute_path, sizeof (absolute_path), error) < 0) - return FALSE; - - /* acquire the trash lock */ - G_LOCK (_thunar_vfs_io_trash); - - /* check if this is file should be trashed to the home trash (also done if stat fails) */ - if (g_lstat (absolute_path, &statb) == 0 && statb.st_dev != _thunar_vfs_io_trash_homedev) - { - /* determine the mount point for the original file which is - * about to be deleted, and from the mount point we try to - * resolve the ID of the responsible trash directory. - */ -#if defined(HAVE_STATFS) && defined(HAVE_STRUCT_STATFS_F_MNTONNAME) - /* this is rather easy on BSDs (surprise)... */ - struct statfs statfsb; - if (statfs (absolute_path, &statfsb) == 0) - mount_point = g_strdup (statfsb.f_mntonname); -#else - /* ...and really messy otherwise (surprise!) */ - GSList *mount_points, *lp; - dev_t dev = statb.st_dev; - - /* check if any of the mount points matches (really should) */ - mount_points = exo_mount_point_list_active (NULL); - for (lp = mount_points; lp != NULL; lp = lp->next) - { - /* stat this mount point, and check if it's the device we're searching */ - if (stat (((ExoMountPoint *) lp->data)->folder, &statb) == 0 && (statb.st_dev == dev)) - { - /* got it, remember the folder of the mount point */ - mount_point = g_strdup (((ExoMountPoint *) lp->data)->folder); - break; - } - } - g_slist_foreach (mount_points, (GFunc) exo_mount_point_free, NULL); - g_slist_free (mount_points); -#endif - - /* check if we have a mount point */ - if (G_LIKELY (mount_point != NULL)) - { - /* determine the trash directory for the mount point, - * creating the directory if it does not already exists - */ - trash_dir = tvit_trash_dir_for_mount_point (mount_point, TRUE); - if (G_LIKELY (trash_dir != NULL)) - trash_id = tvit_resolve_trash_dir_to_id (trash_dir); - } - - /* check if rescanning might help */ - if (trash_dir != NULL && trash_id == 0) - { - /* maybe we need to rescan the mount points */ - tvit_rescan_mount_points (); - - /* try to lookup the trash-id again */ - trash_id = tvit_resolve_trash_dir_to_id (trash_dir); - } - - /* cleanup */ - g_free (mount_point); - g_free (trash_dir); - } - - /* validate the trash-id to ensure we won't crash */ - _thunar_vfs_assert (trash_id < _thunar_vfs_io_n_trashes); - - /* determine the info sub directory for this trash */ - info_dir = g_build_filename (_thunar_vfs_io_trashes[trash_id].trash_dir, "info", NULL); - - /* release the trash lock */ - G_UNLOCK (_thunar_vfs_io_trash); - - /* generate a unique file-id */ - g_snprintf (absolute_path, sizeof (absolute_path), "%s" G_DIR_SEPARATOR_S "%s.trashinfo", info_dir, original_name); - for (n = 1;; ++n) - { - /* exclusively create the .trashinfo file */ - fd = g_open (absolute_path, O_CREAT | O_EXCL | O_WRONLY, 0600); - if (G_LIKELY (fd >= 0)) - break; - - /* check if we need to create the info directory */ - if (G_UNLIKELY (errno == ENOENT)) - { - /* try to create the info directory */ - if (!xfce_mkdirhier (info_dir, 0700, error)) - goto err1; - - /* try again with same .trashinfo name */ - continue; - } - - /* check if the error cannot be recovered */ - if (G_UNLIKELY (errno != EEXIST)) - { -err0: /* spit out a useful error message */ - content = g_filename_display_name (absolute_path); - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO, _("Failed to open \"%s\" for writing"), content); - g_free (content); -err1: - g_free (info_dir); - return FALSE; - } - - /* generate a new unique .trashinfo file name and try again */ - g_snprintf (absolute_path, sizeof (absolute_path), "%s" G_DIR_SEPARATOR_S "%s$%u.trashinfo", info_dir, original_name, n); - } - - /* stat the file to get the deletion date from the filesystem (NFS, ...) */ - if (fstat (fd, &statb) < 0) - { -err2: /* should not happen */ - g_unlink (absolute_path); - close (fd); - goto err0; - } - - /* generate the .trashinfo content */ - original_uri = thunar_vfs_path_dup_uri (original_path); - strftime (deletion_date, sizeof (deletion_date), "%FT%T", localtime (&statb.st_mtime)); - content = g_strdup_printf ("[Trash Info]\nPath=%s\nDeletionDate=%s\n", - original_uri + (sizeof ("file://") - 1), - deletion_date); - g_free (original_uri); - - /* try to save the content (all at once) */ - if (write (fd, content, strlen (content)) != (ssize_t) strlen (content)) - { - /* no space left, etc. */ - g_free (content); - goto err2; - } - - /* strip off the .trashinfo from the info_file */ - absolute_path[strlen (absolute_path) - (sizeof (".trashinfo") - 1)] = '\0'; - - /* return the file-id and trash-id */ - *file_id_return = g_path_get_basename (absolute_path); - *trash_id_return = trash_id; - - /* cleanup */ - g_free (content); - g_free (info_dir); - close (fd); - - return TRUE; -} - - - -/** - * _thunar_vfs_io_trash_path_new - * @trash_id : the id of the trash can. - * @file_id : the id of the file in the trash. - * @relative_path : the relative path or the empty string. - * - * The caller is responsible to free the returned #ThunarVfsPath using - * thunar_vfs_path_unref() when no longer needed. - * - * Returns a new #ThunarVfsPath that represents the trash resource in - * the trash directory with the specified @trash_id, whose basename is - * @file_id, at the given @relative_path. - * - * Return value: the #ThunarVfsPath for the specified trash resource. - **/ -ThunarVfsPath* -_thunar_vfs_io_trash_path_new (guint trash_id, - const gchar *file_id, - const gchar *relative_path) -{ - ThunarVfsPath *parent; - ThunarVfsPath *path; - gchar *name; - - _thunar_vfs_return_val_if_fail (strchr (file_id, '/') == NULL, NULL); - _thunar_vfs_return_val_if_fail (relative_path != NULL, NULL); - - /* generate the path to the trash subfolder */ - name = g_strdup_printf ("%u-%s", trash_id, file_id); - parent = _thunar_vfs_path_new_relative (_thunar_vfs_path_trash_root, name); - g_free (name); - - /* generate the relative path */ - path = _thunar_vfs_path_new_relative (parent, relative_path); - _thunar_vfs_path_unref_nofree (parent); - - return path; -} - - - -/** - * _thunar_vfs_io_trash_path_parse: - * @path : a valid trash:-URI path, but not the "trash:///" root path. - * @trash_id_return : return location for the trash-id or %NULL. - * @file_id_return : return location for the file-id or %NULL. - * @relative_path_return : return location for the relative part or %NULL. - * @error : return location for errors or %NULL. - * - * The relative component of @path may be %NULL if the @path refers to a toplevel - * trash directory, i.e. "trash:///1-file". In this case %TRUE is returned, and - * @relative_path_return will be set to %NULL. - * - * The caller is responsible to free the strings placed in @file_id_return and - * @relative_path_return using g_free() when no longer needed. - * - * Return value: %TRUE if the @path was parsed successfully, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_trash_path_parse (const ThunarVfsPath *path, - guint *trash_id_return, - gchar **file_id_return, - gchar **relative_path_return, - GError **error) -{ - typedef struct _TrashPathItem - { - const ThunarVfsPath *path; - struct _TrashPathItem *next; - } TrashPathItem; - - const ThunarVfsPath *parent; - TrashPathItem *item; - TrashPathItem *root = NULL; - const gchar *name; - const gchar *s; - gchar *t; - gchar *uri; - guint trash_id; - guint n; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* cannot parse the trash root path */ - if (G_UNLIKELY (path->parent == NULL)) - { -invalid_uri: - uri = thunar_vfs_path_dup_uri (path); - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("The URI \"%s\" does not refer to a valid resource in the trash"), uri); - g_free (uri); - return FALSE; - } - - /* determine the paths up to, but not including, the root path */ - for (parent = path; parent->parent != NULL; parent = parent->parent) - { - item = g_newa (TrashPathItem, 1); - item->path = parent; - item->next = root; - root = item; - } - - /* try to parse the first path component (<trashId>-<fileId>) */ - name = thunar_vfs_path_get_name (root->path); - trash_id = strtoul (name, (gpointer) &s, 10); - if (G_UNLIKELY (s == name || s[0] != '-' || s[1] == '\0')) - goto invalid_uri; - - /* return the trash/file id */ - if (G_LIKELY (trash_id_return != NULL)) - *trash_id_return = trash_id; - if (G_LIKELY (file_id_return != NULL)) - *file_id_return = g_strdup (s + 1); - - /* return the relative path if requested */ - if (G_LIKELY (relative_path_return != NULL)) - { - /* check if we have a relative component */ - if (G_LIKELY (path != root->path)) - { - /* we don't care for the root item anymore */ - root = root->next; - - /* allocate memory to store the relative part */ - for (item = root, n = 0; item != NULL; item = item->next) - n += 1 + strlen (thunar_vfs_path_get_name (item->path)); - *relative_path_return = g_malloc (n); - - /* actually store the relative part */ - for (item = root, t = *relative_path_return; item != NULL; item = item->next) - { - if (item != root) - *t++ = G_DIR_SEPARATOR; - for (s = thunar_vfs_path_get_name (item->path); *s != '\0'; ) - *t++ = *s++; - } - *t = '\0'; - } - else - { - /* no relative component */ - *relative_path_return = NULL; - } - } - - return TRUE; -} - - - -/** - * _thunar_vfs_io_trash_path_resolve: - * @path : a valid trash:-URI, but not the trash root path. - * @error : return location for errors or %NULL. - * - * Resolves the trash @path to the absolute local path to the - * specified resource. Returns %NULL if the @path is invalid. - * - * The caller is responsible to free the returned string using - * g_free() when no longer needed. - * - * Return value: the absolute, local path to the trash resource - * at the given @path, or %NULL on error. - **/ -gchar* -_thunar_vfs_io_trash_path_resolve (const ThunarVfsPath *path, - GError **error) -{ - gchar *absolute_path = NULL; - gchar *relative_path; - gchar *trash_dir; - gchar *file_id; - guint trash_id; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (path), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* try to parse the trash path */ - if (_thunar_vfs_io_trash_path_parse (path, &trash_id, &file_id, &relative_path, error)) - { - /* lookup the trash directory for the trash-id */ - trash_dir = _thunar_vfs_io_trash_get_trash_dir (trash_id, error); - if (G_LIKELY (trash_dir != NULL)) - { - /* generate the absolute path to the file in the trash */ - absolute_path = g_build_filename (trash_dir, "files", file_id, relative_path, NULL); - g_free (trash_dir); - } - - /* cleanup */ - g_free (relative_path); - g_free (file_id); - } - - return absolute_path; -} - - - -/** - * _thunar_vfs_io_trash_get_info: - * @path : a valid trash:-URI for which to determine the file info. - * @error : return location for errors or %NULL. - * - * Determines the #ThunarVfsInfo for the trashed file at the specified - * @path. - * - * The caller is responsible to free the returned #ThunarVfsInfo - * using thunar_vfs_info_unref() when no longer needed. - * - * Return value: the #ThunarVfsInfo for the specified @path, or %NULL - * in case of an error. - **/ -ThunarVfsInfo* -_thunar_vfs_io_trash_get_info (ThunarVfsPath *path, - GError **error) -{ - ThunarVfsFileTime mtime; - ThunarVfsInfo *info; - gboolean empty; - gchar *absolute_path; - gchar *original_path; - guint n; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (path), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* check if path is the trash root directory */ - if (thunar_vfs_path_is_root (path)) - { - /* innitially scan the trash directories */ - _thunar_vfs_io_trash_scan (); - - /* acquire the trash subsystem lock */ - G_LOCK (_thunar_vfs_io_trash); - - /* determine the mtime of the trash and check if its empty */ - for (empty = TRUE, mtime = 0, n = 0; n < _thunar_vfs_io_n_trashes; ++n) - { - /* atleast one trash dir not empty -> trash not empty */ - if (G_LIKELY (!_thunar_vfs_io_trashes[n].empty)) - empty = FALSE; - - /* most recent mtime -> mtime for the trash */ - if (G_LIKELY (_thunar_vfs_io_trashes[n].mtime > mtime)) - mtime = _thunar_vfs_io_trashes[n].mtime; - } - - /* release the trash subsystem lock */ - G_UNLOCK (_thunar_vfs_io_trash); - - /* allocate info for the trash root folder */ - info = _thunar_vfs_slice_new0 (ThunarVfsInfo); - info->type = THUNAR_VFS_FILE_TYPE_DIRECTORY; - info->mode = THUNAR_VFS_FILE_MODE_USR_ALL; - info->flags = THUNAR_VFS_FILE_FLAGS_READABLE | THUNAR_VFS_FILE_FLAGS_WRITABLE; - info->uid = getuid (); - info->gid = getgid (); - info->size = empty ? 0 : 4096; - info->atime = mtime; - info->mtime = mtime; - info->ctime = mtime; - info->mime_info = thunar_vfs_mime_info_ref (_thunar_vfs_mime_inode_directory); - info->path = thunar_vfs_path_ref (_thunar_vfs_path_trash_root); - info->custom_icon = g_strdup (empty ? "gnome-fs-trash-empty" : "gnome-fs-trash-full"); - info->display_name = g_strdup (_("Trash")); - info->ref_count = 1; - } - else - { - /* read the information from the disk using the absolute path */ - absolute_path = _thunar_vfs_io_trash_path_resolve (path, error); - info = (absolute_path != NULL) ? _thunar_vfs_io_local_get_info (path, absolute_path, error) : NULL; - g_free (absolute_path); - - /* check if we can adjust the name to the original one */ - if (info != NULL && thunar_vfs_path_is_root (path->parent) && info->display_name == thunar_vfs_path_get_name (path)) - { - /* try to determine the original path */ - if (_thunar_vfs_io_trash_get_trash_info (path, &original_path, NULL, NULL)) - { - /* use the original name as display name for the file */ - info->display_name = g_path_get_basename (original_path); - g_free (original_path); - } - } - } - - return info; -} - - - -/** - * _thunar_vfs_io_trash_get_metadata: - * @path : the #ThunarVfsPath of the file for which to return the @metadata. - * @metadata : the #ThunarVfsInfoMetadata you are interested in. - * @error : return location for errors or %NULL. - * - * Similar to _thunar_vfs_io_local_get_metadata(), but works on trashed resources. - * - * The caller is responsible to free the returned string using g_free() when no - * longer needed. - * - * Return value: the @metadata string or %NULL. - **/ -gchar* -_thunar_vfs_io_trash_get_metadata (ThunarVfsPath *path, - ThunarVfsInfoMetadata metadata, - GError **error) -{ - ThunarVfsPath *local_path; - gchar *result = NULL; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (path), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - switch (metadata) - { - case THUNAR_VFS_INFO_METADATA_FILE_LINK_TARGET: - local_path = _thunar_vfs_path_translate (path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (local_path != NULL)) - { - result = _thunar_vfs_io_local_get_metadata (local_path, metadata, error); - thunar_vfs_path_unref (local_path); - } - break; - - case THUNAR_VFS_INFO_METADATA_TRASH_ORIGINAL_PATH: - if (!_thunar_vfs_io_trash_get_trash_info (path, &result, NULL, error)) - result = NULL; - break; - - case THUNAR_VFS_INFO_METADATA_TRASH_DELETION_DATE: - if (!_thunar_vfs_io_trash_get_trash_info (path, NULL, &result, error)) - result = NULL; - break; - - default: - _thunar_vfs_set_g_error_not_supported (error); - break; - } - - return result; -} - - - -/** - * _thunar_vfs_io_trash_listdir: - * @path : a valid trash:-URI for the trash folder, whose contents to list. - * @error : return location for errors, or %NULL. - * - * Returns the files in the trash folder @path or %NULL if either no files - * are present in the folder at @path, or an error occurred, in which case - * the @error will be set to point to a #GError describing the cause. - * - * The caller is responsible to free the returned #GList of #ThunarVfsInfo<!---->s - * using thunar_vfs_info_list_free() when no longer needed. - * - * Return value: the #ThunarVfsInfo<!---->s for the files in the folder at @path. - **/ -GList* -_thunar_vfs_io_trash_listdir (ThunarVfsPath *path, - GError **error) -{ - ThunarVfsInfo *info; - GList *list; - GList *sp; - GList *tp; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (path), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* scan the paths in the folder */ - list = _thunar_vfs_io_trash_scandir (path, TRUE, NULL, error); - if (G_LIKELY (list != NULL)) - { - /* associate file infos with the paths in the folder */ - for (sp = tp = list; sp != NULL; sp = sp->next) - { - /* try to determine the file info */ - info = _thunar_vfs_io_trash_get_info (sp->data, NULL); - - /* replace the path with the info on the list */ - if (G_LIKELY (info != NULL)) - { - /* just decrease the ref_count on path (info holds a reference now) */ - _thunar_vfs_path_unref_nofree (sp->data); - - /* add the info to the list */ - tp->data = info; - tp = tp->next; - } - else - { - /* no info, may need to free the path */ - thunar_vfs_path_unref (sp->data); - } - } - - /* release the not-filled list items (only non-NULL in case of an info error) */ - if (G_UNLIKELY (tp != NULL)) - { - if (G_LIKELY (tp->prev != NULL)) - tp->prev->next = NULL; - else - list = NULL; - g_list_free (tp); - } - } - - return list; -} - - - -/** - * _thunar_vfs_io_trash_copy_file: - * @source_path : the #ThunarVfsPath of the source file. - * @target_path : the #ThunarVfsPath of the target location. - * @target_path_return : return location for the final #ThunarVfsPath to which - * the file was copied. - * @callback : see #ThunarVfsIOOpsProgressCallback. - * @callback_data : additional user data for @callback. - * @error : return location for errors or %NULL. - * - * Copies a file from or to the trash. Cannot currently handle copying files - * within the trash. - * - * See the description of _thunar_vfs_io_ops_copy_file() for further details. - * - * Return value: %TRUE if succeed, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_trash_copy_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - GError **error) -{ - ThunarVfsPath *source_local_path; - ThunarVfsPath *target_local_path; - gboolean succeed = FALSE; - gchar *file_id; - guint trash_id; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (source_path) || _thunar_vfs_path_is_trash (target_path), FALSE); - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (source_path), FALSE); - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (target_path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (target_path_return != NULL, FALSE); - _thunar_vfs_return_val_if_fail (callback != NULL, FALSE); - - /* check if we're moving to or from the trash */ - if (_thunar_vfs_path_is_trash (source_path) && _thunar_vfs_path_is_trash (target_path)) - { - /* we don't support copying files within the trash */ - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO, _("Cannot move or copy files within the trash")); - } - else if (_thunar_vfs_path_is_trash (source_path)) /* copying out of the trash */ - { - /* translate the source path to a local path */ - source_local_path = _thunar_vfs_path_translate (source_path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (source_local_path != NULL)) - { - /* try to copy the file out of the trash using the generic copy logic for local files */ - succeed = _thunar_vfs_io_ops_copy_file (source_local_path, target_path, NULL, callback, callback_data, error); - thunar_vfs_path_unref (source_local_path); - - /* target path is the same for local paths */ - if (G_LIKELY (succeed)) - *target_path_return = thunar_vfs_path_ref (target_path); - } - } - else if (!thunar_vfs_path_is_root (target_path->parent)) /* copying into a trash subfolder */ - { - /* translate the target path to a local path */ - target_local_path = _thunar_vfs_path_translate (target_path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (target_local_path != NULL)) - { - /* try to copy the file into the trash */ - succeed = _thunar_vfs_io_ops_copy_file (source_path, target_local_path, NULL, callback, callback_data, error); - thunar_vfs_path_unref (target_local_path); - - /* target path is the same for non-toplevel trash */ - if (G_LIKELY (succeed)) - *target_path_return = thunar_vfs_path_ref (target_path); - } - } - else /* copying to the toplevel trash folder */ - { - /* generate a new .trashinfo file */ - if (_thunar_vfs_io_trash_new_trash_info (source_path, &trash_id, &file_id, error)) - { - /* determine the new target path in the trash */ - target_path = _thunar_vfs_io_trash_path_new (trash_id, file_id, ""); - - /* translate the target path to a local path */ - target_local_path = _thunar_vfs_path_translate (target_path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (target_local_path != NULL)) - { - /* try to copy the file info the trash (ensuring that the "files" directory exists) */ - succeed = (_thunar_vfs_io_ops_mkdir (target_local_path->parent, 0700, THUNAR_VFS_IO_OPS_IGNORE_EEXIST, error) - && _thunar_vfs_io_ops_copy_file (source_path, target_local_path, NULL, callback, callback_data, error)); - thunar_vfs_path_unref (target_local_path); - } - - /* check if we failed */ - if (G_UNLIKELY (!succeed)) - { - /* drop the file from the trash and release the target path */ - if (!_thunar_vfs_io_trash_remove (target_path, NULL)) - g_warning ("Failed to remove stale trash handle %s in %u", file_id, trash_id); - thunar_vfs_path_unref (target_path); - } - else - { - /* schedule a changed notification on the trash root folder (parent of this path) */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CHANGED, target_path->parent); - - /* return the new target path */ - *target_path_return = target_path; - } - - /* cleanup */ - g_free (file_id); - } - } - - return succeed; -} - - - -/** - * _thunar_vfs_io_trash_move_file: - * @source_path : the #ThunarVfsPath of the source file. - * @target_path : the #ThunarVfsPath of the target location. - * @target_path_return : return location for the final #ThunarVfsPath to which - * the file was moved. - * @error : return location for errors or %NULL. - * - * Moves a file from or to the trash. Cannot currently handle moving files - * within the trash. - * - * See the description of _thunar_vfs_io_ops_move_file() for further details. - * - * Return value: %TRUE if succeed, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_io_trash_move_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error) -{ - ThunarVfsPath *source_local_path; - ThunarVfsPath *target_local_path; - gboolean succeed = FALSE; - gchar *file_id; - guint trash_id; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (source_path) || _thunar_vfs_path_is_trash (target_path), FALSE); - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (source_path), FALSE); - _thunar_vfs_return_val_if_fail (!thunar_vfs_path_is_root (target_path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (target_path_return != NULL, FALSE); - - /* check if we're moving to or from the trash */ - if (_thunar_vfs_path_is_trash (source_path) && _thunar_vfs_path_is_trash (target_path)) - { - /* we don't support moving files within the trash */ - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO, _("Cannot move or copy files within the trash")); - } - else if (_thunar_vfs_path_is_trash (source_path)) /* moving out of the trash */ - { - /* translate the source path to a local path */ - source_local_path = _thunar_vfs_path_translate (source_path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (source_local_path != NULL)) - { - /* try to move the file out of the trash and remove the associated .trashinfo file */ - succeed = (_thunar_vfs_io_local_move_file (source_local_path, target_path, error) - && _thunar_vfs_io_trash_remove (source_path, error)); - thunar_vfs_path_unref (source_local_path); - - /* target path is the same for local paths */ - if (G_LIKELY (succeed)) - *target_path_return = thunar_vfs_path_ref (target_path); - } - } - else if (!thunar_vfs_path_is_root (target_path->parent)) /* moving into a trash subfolder */ - { - /* translate the target path to a local path */ - target_local_path = _thunar_vfs_path_translate (target_path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (target_local_path != NULL)) - { - /* try to move the file into the trash */ - succeed = _thunar_vfs_io_local_move_file (source_path, target_local_path, error); - thunar_vfs_path_unref (target_local_path); - - /* target path is the same for non-toplevel trash */ - if (G_LIKELY (succeed)) - *target_path_return = thunar_vfs_path_ref (target_path); - } - } - else /* moving to the toplevel trash folder */ - { - /* generate a new .trashinfo file */ - if (_thunar_vfs_io_trash_new_trash_info (source_path, &trash_id, &file_id, error)) - { - /* determine the new target path in the trash */ - target_path = _thunar_vfs_io_trash_path_new (trash_id, file_id, ""); - - /* translate the target path to a local path */ - target_local_path = _thunar_vfs_path_translate (target_path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (target_local_path != NULL)) - { - /* try to move the file info the trash (ensuring that the "files" directory exists) */ - succeed = (_thunar_vfs_io_ops_mkdir (target_local_path->parent, 0700, THUNAR_VFS_IO_OPS_IGNORE_EEXIST, error) - && _thunar_vfs_io_local_move_file (source_path, target_local_path, error)); - thunar_vfs_path_unref (target_local_path); - } - - /* check if we failed */ - if (G_UNLIKELY (!succeed)) - { - /* drop the file from the trash and release the target path */ - if (!_thunar_vfs_io_trash_remove (target_path, NULL)) - g_warning ("Failed to remove stale trash handle %s in %u", file_id, trash_id); - thunar_vfs_path_unref (target_path); - } - else - { - /* schedule a changed notification on the trash root folder (parent of this path) */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CHANGED, target_path->parent); - - /* return the new target path */ - *target_path_return = target_path; - } - - /* cleanup */ - g_free (file_id); - } - } - - return succeed; -} - - - -/** - * _thunar_vfs_io_trash_remove: - * @path : the #ThunarVfsPath to the trash resource to remove. - * @error : return location for errors or %NULL. - * - * Removes the file or folder from the trash that is identified - * by the specified @path. - * - * Return value: %TRUE if the removal was successfull, %FALSE - * otherwise. - **/ -gboolean -_thunar_vfs_io_trash_remove (ThunarVfsPath *path, - GError **error) -{ - GError *err = NULL; - gchar *absolute_path; - gchar *relative_path; - gchar *trash_dir; - gchar *file_id; - guint trash_id; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (path), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* try to parse the trash path */ - if (!_thunar_vfs_io_trash_path_parse (path, &trash_id, &file_id, &relative_path, error)) - return FALSE; - - /* determine the trash directory for the trash-id */ - trash_dir = _thunar_vfs_io_trash_get_trash_dir (trash_id, &err); - if (G_LIKELY (trash_dir != NULL)) - { - /* try to remove the file or folder in the trash */ - absolute_path = g_build_filename (trash_dir, "files", file_id, relative_path, NULL); - if (g_remove (absolute_path) < 0 && errno != ENOENT) - _thunar_vfs_set_g_error_from_errno3 (&err); - g_free (absolute_path); - - /* check if need to remove the matching .trashinfo file */ - if (G_LIKELY (err == NULL) && relative_path == NULL) - { - /* determine the path for the .trashinfo file and unlink it (ignoring errors) */ - absolute_path = g_strconcat (trash_dir, G_DIR_SEPARATOR_S "info" G_DIR_SEPARATOR_S, file_id, ".trashinfo", NULL); - g_unlink (absolute_path); - g_free (absolute_path); - - /* schedule a changed notification on the trash root folder (parent of this path) */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CHANGED, path->parent); - } - } - - /* cleanup */ - g_free (relative_path); - g_free (trash_dir); - g_free (file_id); - - /* check if we failed */ - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - return TRUE; -} - - - -/** - * _thunar_vfs_io_trash_scandir: - * @path : the #ThunarVfsPath to a directory in the trash. May - * also be the trash root folder itself. - * @follow_links : %TRUE to follow symlinks to directories. - * @directories_return : pointer to a list into which the direct subfolders - * found during scanning will be placed (for recursive - * scanning), or %NULL if you are not interested in a - * separate list of subfolders. Note that the returned - * list items need to be freed, but the #ThunarVfsPath<!---->s - * in the list do not have an extra reference. - * @error : return location for errors or %NULL. - * - * Scans the trash directory at @path and returns the #ThunarVfsPath<!---->s in the - * directory. - * - * The list returned in @directories_return, if not %NULL, must be freed using - * g_list_free() when no longer needed. - * - * The returned list of #ThunarVfsPath<!---->s must be freed by the caller using - * thunar_vfs_path_list_unref() when no longer needed. - * - * Return value: the list of #ThunarVfsPath<!---->s in the folder at the @path, - * or %NULL in case of an error. Note that %NULL may also mean that - * the folder is empty. - **/ -GList* -_thunar_vfs_io_trash_scandir (ThunarVfsPath *path, - gboolean follow_links, - GList **directories_return, - GError **error) -{ - const gchar *name; - gchar *absolute_path; - gchar *file_path; - GList *path_list = NULL; - guint n; - GDir *dp; - - _thunar_vfs_return_val_if_fail (_thunar_vfs_path_is_trash (path), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* scanning a directory in the trash is easy */ - if (!thunar_vfs_path_is_root (path)) - { - /* determine the absolute local path to the directory */ - absolute_path = _thunar_vfs_io_trash_path_resolve (path, error); - if (G_LIKELY (absolute_path != NULL)) - { - /* scan the local directory, generating trash paths */ - path_list = _thunar_vfs_os_scandir (path, absolute_path, follow_links, directories_return, error); - g_free (absolute_path); - } - } - else - { - /* unconditionally scan for trash directories to notice new - * (hot-plugged) trash directories on removable drives and media. - */ - _thunar_vfs_io_trash_rescan_mounts (); - - /* unconditionally rescan the trash directories */ - _thunar_vfs_io_trash_rescan (); - - /* acquire the trash subsystem lock */ - G_LOCK (_thunar_vfs_io_trash); - - /* process all trash directories */ - for (n = 0; n < _thunar_vfs_io_n_trashes; ++n) - { - /* determine the paths for the trashed files in this trash directory */ - absolute_path = g_build_filename (_thunar_vfs_io_trashes[n].trash_dir, "files", NULL); - dp = g_dir_open (absolute_path, 0, NULL); - if (G_LIKELY (dp != NULL)) - { - /* process all items in this folder */ - for (;;) - { - /* determine the name of the next item */ - name = g_dir_read_name (dp); - if (G_UNLIKELY (name == NULL)) - break; - - /* add a path for this item */ - path_list = g_list_prepend (path_list, _thunar_vfs_io_trash_path_new (n, name, "")); - - /* check if we should return directories in a special list */ - if (G_UNLIKELY (directories_return != NULL)) - { - /* check if we have a directory (according to the follow_links policy) */ - file_path = g_build_filename (absolute_path, name, NULL); - if (g_file_test (file_path, G_FILE_TEST_IS_DIR) && (follow_links || !g_file_test (file_path, G_FILE_TEST_IS_SYMLINK))) - *directories_return = g_list_prepend (*directories_return, path_list->data); - g_free (file_path); - } - } - g_dir_close (dp); - } - g_free (absolute_path); - } - - /* release the trash subsystem lock */ - G_UNLOCK (_thunar_vfs_io_trash); - } - - return path_list; -} - - - -/** - * _thunar_vfs_io_trash_init: - * - * Initializes the trash subsystem. - **/ -void -_thunar_vfs_io_trash_init (void) -{ - const gchar *home_dir; - struct stat statb; - - /* determine the home folder path */ - home_dir = g_get_home_dir (); - - /* determine the device of the home folder */ - if (stat (home_dir, &statb) == 0) - _thunar_vfs_io_trash_homedev = statb.st_dev; - - /* setup the home trash */ - _thunar_vfs_io_n_trashes = 1; - _thunar_vfs_io_trashes = g_new (ThunarVfsIOTrash, 1); - _thunar_vfs_io_trashes->top_dir = g_strdup (home_dir); - _thunar_vfs_io_trashes->trash_dir = g_build_filename (g_get_user_data_dir (), "Trash", NULL); - _thunar_vfs_io_trashes->mtime = 0; - _thunar_vfs_io_trashes->empty = TRUE; -} - - - -/** - * _thunar_vfs_io_trash_shutdown: - * - * Shuts down the trash subsystem. - **/ -void -_thunar_vfs_io_trash_shutdown (void) -{ - /* check if we have a pending trash rescan timer */ - if (G_LIKELY (_thunar_vfs_io_trash_timer_id != 0)) - { - /* kill the pending trash rescan timer */ - g_source_remove (_thunar_vfs_io_trash_timer_id); - _thunar_vfs_io_trash_timer_id = 0; - } - - /* free the active trashes */ - while (_thunar_vfs_io_n_trashes-- > 0) - { - /* release top and trash dir */ - g_free (_thunar_vfs_io_trashes[_thunar_vfs_io_n_trashes].top_dir); - g_free (_thunar_vfs_io_trashes[_thunar_vfs_io_n_trashes].trash_dir); - } - g_free (_thunar_vfs_io_trashes); - _thunar_vfs_io_trashes = NULL; -} - - - -#define __THUNAR_VFS_IO_TRASH_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-io-trash.h b/thunar-vfs/thunar-vfs-io-trash.h deleted file mode 100644 index 676991a49..000000000 --- a/thunar-vfs/thunar-vfs-io-trash.h +++ /dev/null @@ -1,92 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_IO_TRASH_H__ -#define __THUNAR_VFS_IO_TRASH_H__ - -#include <thunar-vfs/thunar-vfs-info.h> -#include <thunar-vfs/thunar-vfs-io-ops.h> - -G_BEGIN_DECLS; - -void _thunar_vfs_io_trash_scan (void) G_GNUC_INTERNAL; -gboolean _thunar_vfs_io_trash_rescan (void) G_GNUC_INTERNAL; -void _thunar_vfs_io_trash_rescan_mounts (void) G_GNUC_INTERNAL; - -gchar *_thunar_vfs_io_trash_get_top_dir (guint trash_id, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gchar *_thunar_vfs_io_trash_get_trash_dir (guint trash_id, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_trash_get_trash_info (const ThunarVfsPath *path, - gchar **original_path_return, - gchar **deletion_date_return, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -gboolean _thunar_vfs_io_trash_new_trash_info (const ThunarVfsPath *original_path, - guint *trash_id_return, - gchar **file_id_return, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsPath *_thunar_vfs_io_trash_path_new (guint trash_id, - const gchar *file_id, - const gchar *relative_path) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_trash_path_parse (const ThunarVfsPath *path, - guint *trash_id_return, - gchar **file_id_return, - gchar **relative_path_return, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gchar *_thunar_vfs_io_trash_path_resolve (const ThunarVfsPath *path, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsInfo *_thunar_vfs_io_trash_get_info (ThunarVfsPath *path, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gchar *_thunar_vfs_io_trash_get_metadata (ThunarVfsPath *path, - ThunarVfsInfoMetadata metadata, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -GList *_thunar_vfs_io_trash_listdir (ThunarVfsPath *path, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_trash_copy_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - ThunarVfsIOOpsProgressCallback callback, - gpointer callback_data, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_trash_move_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gboolean _thunar_vfs_io_trash_remove (ThunarVfsPath *path, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -GList *_thunar_vfs_io_trash_scandir (ThunarVfsPath *path, - gboolean follow_links, - GList **directories_return, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -void _thunar_vfs_io_trash_init (void) G_GNUC_INTERNAL; -void _thunar_vfs_io_trash_shutdown (void) G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_IO_TRASH_H__ */ diff --git a/thunar-vfs/thunar-vfs-job-private.h b/thunar-vfs/thunar-vfs-job-private.h deleted file mode 100644 index b5ffcf14c..000000000 --- a/thunar-vfs/thunar-vfs-job-private.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_JOB_PRIVATE_H__ -#define __THUNAR_VFS_JOB_PRIVATE_H__ - -#include <thunar-vfs/thunar-vfs-config.h> -#include <thunar-vfs/thunar-vfs-job.h> - -G_BEGIN_DECLS; - -/* generic routines for synchronous signal emission */ -void _thunar_vfs_job_emit_valist (ThunarVfsJob *job, - guint signal_id, - GQuark signal_detail, - va_list var_args) G_GNUC_INTERNAL; -void _thunar_vfs_job_emit (ThunarVfsJob *job, - guint signal_id, - GQuark signal_detail, - ...) G_GNUC_INTERNAL; - -/* generic routines for asynchronous signal emission */ -void _thunar_vfs_job_notify_valist (ThunarVfsJob *job, - guint signal_id, - GQuark signal_detail, - va_list var_args) G_GNUC_INTERNAL; -void _thunar_vfs_job_notify (ThunarVfsJob *job, - guint signal_id, - GQuark signal_detail, - ...) G_GNUC_INTERNAL; - -/* special routines for signal emission */ -ThunarVfsJobResponse _thunar_vfs_job_ask_valist (ThunarVfsJob *job, - const gchar *format, - va_list var_args, - const gchar *question, - ThunarVfsJobResponse choices) G_GNUC_INTERNAL; -ThunarVfsJobResponse _thunar_vfs_job_ask_overwrite (ThunarVfsJob *job, - const gchar *format, - ...) G_GNUC_INTERNAL G_GNUC_PRINTF (2, 3); -ThunarVfsJobResponse _thunar_vfs_job_ask_replace (ThunarVfsJob *job, - ThunarVfsPath *src_path, - ThunarVfsPath *dst_path) G_GNUC_INTERNAL; -ThunarVfsJobResponse _thunar_vfs_job_ask_skip (ThunarVfsJob *job, - const gchar *format, - ...) G_GNUC_INTERNAL G_GNUC_PRINTF (2, 3); -void _thunar_vfs_job_error (ThunarVfsJob *job, - GError *error) G_GNUC_INTERNAL; -void _thunar_vfs_job_info_message (ThunarVfsJob *job, - const gchar *format) G_GNUC_INTERNAL; -gboolean _thunar_vfs_job_infos_ready (ThunarVfsJob *job, - GList *info_list) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -void _thunar_vfs_job_new_files (ThunarVfsJob *job, - const GList *path_list) G_GNUC_INTERNAL; -void _thunar_vfs_job_percent (ThunarVfsJob *job, - gdouble percent) G_GNUC_INTERNAL; - -/* special routines for path based jobs */ -void _thunar_vfs_job_total_paths (ThunarVfsJob *job, - GList *total_paths) G_GNUC_INTERNAL; -void _thunar_vfs_job_process_path (ThunarVfsJob *job, - GList *path_list_item) G_GNUC_INTERNAL; - -/* initialization and shutdown routines */ -void _thunar_vfs_job_init (void) G_GNUC_INTERNAL; -void _thunar_vfs_job_shutdown (void) G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_JOB_PRIVATE_H__ */ diff --git a/thunar-vfs/thunar-vfs-job.c b/thunar-vfs/thunar-vfs-job.c deleted file mode 100644 index c24beb6ba..000000000 --- a/thunar-vfs/thunar-vfs-job.c +++ /dev/null @@ -1,1309 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -/* implement thunar-vfs-job's inline functions */ -#define G_IMPLEMENT_INLINES 1 -#define __THUNAR_VFS_JOB_C__ -#include <thunar-vfs/thunar-vfs-job.h> - -#include <gobject/gvaluecollector.h> - -#include <thunar-vfs/thunar-vfs-enum-types.h> -#include <thunar-vfs/thunar-vfs-job-private.h> -#include <thunar-vfs/thunar-vfs-marshal.h> -#include <thunar-vfs/thunar-vfs-monitor-private.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -#define THUNAR_VFS_JOB_SOURCE(source) ((ThunarVfsJobSource *) (source)) -#define THUNAR_VFS_JOB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), THUNAR_VFS_TYPE_JOB, ThunarVfsJobPrivate)) - - - -/* Signal identifiers */ -enum -{ - ASK, - ASK_REPLACE, - ERROR, - FINISHED, - INFO_MESSAGE, - INFOS_READY, - NEW_FILES, - PERCENT, - LAST_SIGNAL, -}; - - - -typedef struct _ThunarVfsJobEmitAsync ThunarVfsJobEmitAsync; -typedef struct _ThunarVfsJobEmitSync ThunarVfsJobEmitSync; -typedef struct _ThunarVfsJobSource ThunarVfsJobSource; - - - -static void thunar_vfs_job_class_init (ThunarVfsJobClass *klass); -static void thunar_vfs_job_init (ThunarVfsJob *job); -static ThunarVfsJobResponse thunar_vfs_job_real_ask (ThunarVfsJob *job, - const gchar *message, - ThunarVfsJobResponse choices); -static ThunarVfsJobResponse thunar_vfs_job_real_ask_replace (ThunarVfsJob *job, - ThunarVfsInfo *src_info, - ThunarVfsInfo *dst_info); -static void thunar_vfs_job_execute (gpointer data, - gpointer user_data); -static gboolean thunar_vfs_job_source_prepare (GSource *source, - gint *timeout); -static gboolean thunar_vfs_job_source_check (GSource *source); -static gboolean thunar_vfs_job_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data); -static void thunar_vfs_job_source_finalize (GSource *source); - - - -struct _ThunarVfsJobPrivate -{ - ThunarVfsJobEmitAsync *emit_async; - ThunarVfsJobEmitSync *emit_sync; - gboolean running; - - /* for ask_overwrite()/ask_skip() */ - guint ask_overwrite_all : 1; - guint ask_overwrite_none : 1; - guint ask_skip_all : 1; - - /* for total_paths()/process_path() */ - GList *total_paths; -}; - -struct _ThunarVfsJobEmitAsync /* an asychronous notification */ -{ - ThunarVfsJobEmitAsync *next; - guint signal_id; - GQuark signal_detail; - guint n_values; - GValue *values; -}; - -struct _ThunarVfsJobEmitSync /* a synchronous signal */ -{ - guint signal_id; - GQuark signal_detail; - va_list var_args; - volatile gboolean pending; -}; - -struct _ThunarVfsJobSource -{ - GSource source; - ThunarVfsJob *job; -}; - - - -static GSourceFuncs thunar_vfs_job_source_funcs = -{ - thunar_vfs_job_source_prepare, - thunar_vfs_job_source_check, - thunar_vfs_job_source_dispatch, - thunar_vfs_job_source_finalize, - NULL, -}; - -static GObjectClass *thunar_vfs_job_parent_class; -static guint job_signals[LAST_SIGNAL]; -static GThreadPool *job_pool = NULL; -static GCond *job_cond = NULL; -static GMutex *job_mutex = NULL; -static volatile guint jobs_running = 0; - - - -GType -thunar_vfs_job_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsJob", - sizeof (ThunarVfsJobClass), - thunar_vfs_job_class_init, - sizeof (ThunarVfsJob), - thunar_vfs_job_init, - G_TYPE_FLAG_ABSTRACT); - } - - return type; -} - - - -static gboolean -_thunar_vfs_job_ask_accumulator (GSignalInvocationHint *ihint, - GValue *return_accu, - const GValue *handler_return, - gpointer data) -{ - g_value_copy (handler_return, return_accu); - return FALSE; -} - - - -static void -thunar_vfs_job_class_init (ThunarVfsJobClass *klass) -{ - /* add our private data for this class */ - g_type_class_add_private (klass, sizeof (ThunarVfsJobPrivate)); - - /* determine the parent class */ - thunar_vfs_job_parent_class = g_type_class_peek_parent (klass); - - klass->ask = thunar_vfs_job_real_ask; - klass->ask_replace = thunar_vfs_job_real_ask_replace; - - /** - * ThunarVfsJob::ask: - * @job : a #ThunarVfsJob. - * @message : question to display to the user. - * @choices : a combination of #ThunarVfsInteractiveJobResponse<!---->s. - * - * The @message is garantied to contain valid UTF-8. - * - * Return value: the selected choice. - **/ - job_signals[ASK] = - g_signal_new (I_("ask"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_NO_HOOKS | G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsJobClass, ask), - _thunar_vfs_job_ask_accumulator, NULL, - _thunar_vfs_marshal_FLAGS__STRING_FLAGS, - THUNAR_VFS_TYPE_VFS_JOB_RESPONSE, - 2, G_TYPE_STRING, - THUNAR_VFS_TYPE_VFS_JOB_RESPONSE); - - /** - * ThunarVfsJob::ask-replace: - * @job : a #ThunarVfsJob. - * @src_info : the #ThunarVfsInfo of the source file. - * @dst_info : the #ThunarVfsInfo of the destination file, that - * may be replaced with the source file. - * - * Emitted to ask the user whether the destination file should - * be replaced by the source file. - * - * Return value: the selected choice. - * - * Since: 0.8.1 - **/ - job_signals[ASK_REPLACE] = - g_signal_new (I_("ask-replace"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_NO_HOOKS | G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsJobClass, ask_replace), - _thunar_vfs_job_ask_accumulator, NULL, - _thunar_vfs_marshal_FLAGS__BOXED_BOXED, - THUNAR_VFS_TYPE_VFS_JOB_RESPONSE, - 2, THUNAR_VFS_TYPE_INFO, - THUNAR_VFS_TYPE_INFO); - - /** - * ThunarVfsJob::error: - * @job : a #ThunarVfsJob. - * @error : a #GError describing the cause. - * - * Emitted whenever an error occurs while executing the - * @job. - **/ - job_signals[ERROR] = - g_signal_new (I_("error"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_NO_HOOKS, 0, NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - /** - * ThunarVfsJob::finished: - * @job : a #ThunarVfsJob. - * - * This signal will be automatically emitted once the - * @job finishes its execution, no matter whether @job - * completed successfully or was cancelled by the - * user. - **/ - job_signals[FINISHED] = - g_signal_new (I_("finished"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_NO_HOOKS, 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * ThunarVfsJob::info-message: - * @job : a #ThunarVfsJob. - * @message : information to be displayed about @job. - * - * This signal is emitted to display information about the - * @job. Examples of messages are "Preparing..." or - * "Cleaning up...". - * - * The @message is garantied to contain valid UTF-8, so - * it can be displayed by #GtkWidget<!---->s out of the - * box. - **/ - job_signals[INFO_MESSAGE] = - g_signal_new (I_("info-message"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_NO_HOOKS, 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - /** - * ThunarVfsJob::infos-ready: - * @job : a #ThunarVfsJob. - * @info_list : a list of #ThunarVfsInfo<!---->s. - * - * This signal is used by #ThunarVfsJob<!---->s returned by - * the thunar_vfs_listdir() function whenever there's a bunch - * of #ThunarVfsInfo<!---->s ready. This signal is garantied - * to be never emitted with an @info_list parameter of %NULL. - * - * To allow some further optimizations on the handler-side, - * the handler is allowed to take over ownership of the - * @info_list, i.e. it can reuse the @infos list and just replace - * the data elements with it's own objects based on the - * #ThunarVfsInfo<!---->s contained within the @info_list (and - * of course properly unreffing the previously contained infos). - * If a handler takes over ownership of @info_list it must return - * %TRUE here, and no further handlers will be run. Else, if - * the handler doesn't want to take over ownership of @infos, - * it must return %FALSE, and other handlers will be run. Use - * this feature with care, and only if you can be sure that - * you are the only handler connected to this signal for a - * given job! - * - * Return value: %TRUE if the handler took over ownership of - * @info_list, else %FALSE. - **/ - job_signals[INFOS_READY] = - g_signal_new (I_("infos-ready"), - G_TYPE_FROM_CLASS (klass), G_SIGNAL_NO_HOOKS, - 0, g_signal_accumulator_true_handled, NULL, - _thunar_vfs_marshal_BOOLEAN__POINTER, - G_TYPE_BOOLEAN, 1, G_TYPE_POINTER); - - /** - * ThunarVfsJob::new-files: - * @job : a #ThunarVfsJob. - * @path_list : a list of #ThunarVfsPath<!---->s that were created by @job. - * - * This signal is emitted by the @job right before the @job is terminated - * and informs the application about the list of created files in @path_list. - * @path_list contains only the toplevel path items, that were specified by - * the application on creation of the @job. - **/ - job_signals[NEW_FILES] = - g_signal_new (I_("new-files"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_NO_HOOKS, 0, NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - /** - * ThunarVfsJob::percent: - * @job : a #ThunarVfsJob. - * @percent : the percentage of completeness. - * - * This signal is emitted to present the state - * of the overall progress. - * - * The @percent value is garantied to be in the - * range 0.0 to 100.0. - **/ - job_signals[PERCENT] = - g_signal_new (I_("percent"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_NO_HOOKS, 0, NULL, NULL, - g_cclosure_marshal_VOID__DOUBLE, - G_TYPE_NONE, 1, G_TYPE_DOUBLE); -} - - - -static void -thunar_vfs_job_init (ThunarVfsJob *job) -{ - job->priv = THUNAR_VFS_JOB_GET_PRIVATE (job); -} - - - -static ThunarVfsJobResponse -thunar_vfs_job_real_ask (ThunarVfsJob *job, - const gchar *message, - ThunarVfsJobResponse choices) -{ - return THUNAR_VFS_JOB_RESPONSE_CANCEL; -} - - - -static ThunarVfsJobResponse -thunar_vfs_job_real_ask_replace (ThunarVfsJob *job, - ThunarVfsInfo *src_info, - ThunarVfsInfo *dst_info) -{ - ThunarVfsJobResponse response; - gchar *display_name; - gchar *s; - - /* determine a displayable variant of the dst */ - s = _thunar_vfs_path_is_local (dst_info->path) ? thunar_vfs_path_dup_string (dst_info->path) : thunar_vfs_path_dup_uri (dst_info->path); - display_name = g_filename_display_name (s); - g_free (s); - - /* no "ask-replace" handler, fallback to "ask" */ - s = g_strdup_printf (_("The file \"%s\" already exists. Would you like to replace it?\n\n" - "If you replace an existing file, its contents will be overwritten."), - display_name); - g_signal_emit (G_OBJECT (job), - job_signals[ASK], 0, s, - THUNAR_VFS_JOB_RESPONSE_YES - | THUNAR_VFS_JOB_RESPONSE_YES_ALL - | THUNAR_VFS_JOB_RESPONSE_NO - | THUNAR_VFS_JOB_RESPONSE_NO_ALL - | THUNAR_VFS_JOB_RESPONSE_CANCEL, - &response); - - /* cleanup */ - g_free (display_name); - g_free (s); - - return response; -} - - - -static void -thunar_vfs_job_execute (gpointer data, - gpointer user_data) -{ - ThunarVfsJobEmitAsync *emit_async; - ThunarVfsJob *job = THUNAR_VFS_JOB (data); - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_vfs_return_if_fail (job->priv->running); - - /* perform the real work */ - (*THUNAR_VFS_JOB_GET_CLASS (job)->execute) (job); - - /* mark the job as done */ - job->priv->running = FALSE; - - /* release pending asynchronous emissions */ - while (job->priv->emit_async) - { - /* drop the first asynchronous emission */ - emit_async = job->priv->emit_async; - job->priv->emit_async = emit_async->next; - _thunar_vfs_g_value_array_free (emit_async->values, emit_async->n_values); - _thunar_vfs_slice_free (ThunarVfsJobEmitAsync, emit_async); - } - - /* wake up the main event loop */ - g_main_context_wakeup (NULL); -} - - - -static gboolean -thunar_vfs_job_source_prepare (GSource *source, - gint *timeout) -{ - if (thunar_vfs_job_source_check (source)) - { - *timeout = 0; - return TRUE; - } - else - { - /* need to check for async emissions */ - *timeout = 200; - return FALSE; - } -} - - - -static gboolean -thunar_vfs_job_source_check (GSource *source) -{ - ThunarVfsJob *job = THUNAR_VFS_JOB_SOURCE (source)->job; - - /* check if the job is done or has a pending async or sync emission */ - return (!job->priv->running - || job->priv->emit_async != NULL - || job->priv->emit_sync != NULL); -} - - - -static gboolean -thunar_vfs_job_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - ThunarVfsJobEmitAsync *emit_async; - ThunarVfsJobEmitSync *emit_sync; - ThunarVfsJob *job = THUNAR_VFS_JOB_SOURCE (source)->job; - - /* process all pending async signal emissions */ - while (job->priv->emit_async != NULL) - { - /* remove the first async emission from the list */ - g_mutex_lock (job_mutex); - emit_async = job->priv->emit_async; - job->priv->emit_async = emit_async->next; - g_mutex_unlock (job_mutex); - - /* emit the asynchronous signal */ - GDK_THREADS_ENTER (); - g_signal_emitv (emit_async->values, emit_async->signal_id, emit_async->signal_detail, NULL); - GDK_THREADS_LEAVE (); - - /* release the async signal descriptor */ - _thunar_vfs_g_value_array_free (emit_async->values, emit_async->n_values); - _thunar_vfs_slice_free (ThunarVfsJobEmitAsync, emit_async); - } - - /* check if the job is done */ - if (!job->priv->running) - { - /* emit the "finished" signal */ - GDK_THREADS_ENTER (); - g_signal_emit (G_OBJECT (job), job_signals[FINISHED], 0); - GDK_THREADS_LEAVE (); - - /* drop the source */ - return FALSE; - } - - /* check if the job has a pending synchronous emission */ - if (G_LIKELY (job->priv->emit_sync != NULL)) - { - /* determine and reset the emission details */ - g_mutex_lock (job_mutex); - emit_sync = job->priv->emit_sync; - job->priv->emit_sync = NULL; - g_mutex_unlock (job_mutex); - - /* emit the signal */ - GDK_THREADS_ENTER (); - g_signal_emit_valist (job, emit_sync->signal_id, emit_sync->signal_detail, emit_sync->var_args); - GDK_THREADS_LEAVE (); - - /* tell the other thread, that we're done */ - g_mutex_lock (job_mutex); - emit_sync->pending = FALSE; - g_cond_broadcast (job_cond); - g_mutex_unlock (job_mutex); - } - - /* keep the source alive */ - return TRUE; -} - - - -static void -thunar_vfs_job_source_finalize (GSource *source) -{ - ThunarVfsJob *job = THUNAR_VFS_JOB_SOURCE (source)->job; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_JOB (job)); - - /* decrement the number of running jobs */ - jobs_running -= 1; - - /* release the job reference */ - GDK_THREADS_ENTER (); - g_object_unref (G_OBJECT (job)); - GDK_THREADS_LEAVE (); -} - - - -/** - * thunar_vfs_job_launch: - * @job : a #ThunarVfsJob. - * - * This functions schedules @job to be run as soon - * as possible, in a separate thread. - * - * Return value: a pointer to @job. - **/ -ThunarVfsJob* -thunar_vfs_job_launch (ThunarVfsJob *job) -{ - GSource *source; - - g_return_val_if_fail (THUNAR_VFS_IS_JOB (job), NULL); - g_return_val_if_fail (!job->priv->running, NULL); - g_return_val_if_fail (job_pool != NULL, NULL); - - /* allocate and initialize the watch source */ - source = g_source_new (&thunar_vfs_job_source_funcs, sizeof (ThunarVfsJobSource)); - g_source_set_priority (source, G_PRIORITY_HIGH); - - /* connect the source to the job */ - THUNAR_VFS_JOB_SOURCE (source)->job = g_object_ref (G_OBJECT (job)); - - /* increment the number of running jobs */ - jobs_running += 1; - - /* mark the job as running */ - job->priv->running = TRUE; - - /* schedule a thread to handle the job */ - g_thread_pool_push (job_pool, job, NULL); - - /* attach the source to the main context */ - g_source_attach (source, NULL); - - /* the main context now keeps the reference */ - g_source_unref (source); - - return job; -} - - - -/** - * thunar_vfs_job_cancel: - * @job : a #ThunarVfsJob. - * - * Attempts to cancel the operation currently - * performed by @job. Even after the cancellation - * of @job, it may still emit signals, so you - * must take care of disconnecting all handlers - * appropriately if you cannot handle signals - * after cancellation. - **/ -void -thunar_vfs_job_cancel (ThunarVfsJob *job) -{ - g_return_if_fail (THUNAR_VFS_IS_JOB (job)); - job->cancelled = TRUE; -} - - - -/** - * _thunar_vfs_job_emit_valist: - * @job : a #ThunarVfsJob. - * @signal_id : the id of the signal to emit on @job. - * @signal_detail : the detail. - * @var_args : a list of paramters to be passed to the signal, - * folled by a location for the return value. If - * the return type of the signals is %G_TYPE_NONE, - * the return value location can be omitted. - * - * Emits the signal identified by @signal_id on @job in - * the context of the main thread. This method doesn't - * return until the signal was emitted. - **/ -void -_thunar_vfs_job_emit_valist (ThunarVfsJob *job, - guint signal_id, - GQuark signal_detail, - va_list var_args) -{ - ThunarVfsJobEmitSync emit_sync; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_vfs_return_if_fail (job->priv->emit_sync == NULL); - _thunar_vfs_return_if_fail (job->priv->running); - - /* prepare the synchronous emission */ - emit_sync.signal_id = signal_id; - emit_sync.signal_detail = signal_detail; - emit_sync.pending = TRUE; - - /* copy the variable argument list (portable) */ - G_VA_COPY (emit_sync.var_args, var_args); - - /* emit the signal using our source */ - g_mutex_lock (job_mutex); - job->priv->emit_sync = &emit_sync; - g_main_context_wakeup (NULL); - while (G_UNLIKELY (emit_sync.pending)) - g_cond_wait (job_cond, job_mutex); - g_mutex_unlock (job_mutex); -} - - - -/** - * _thunar_vfs_job_emit: - * @job : a #ThunarVfsJob. - * @signal_id : the id of the signal to emit on qjob. - * @signal_detail : the signal detail. - * @... : a list of parameters to be passed to the signal. - * - * Convenience wrapper for thunar_vfs_job_emit_valist(). - **/ -void -_thunar_vfs_job_emit (ThunarVfsJob *job, - guint signal_id, - GQuark signal_detail, - ...) -{ - va_list var_args; - - va_start (var_args, signal_detail); - _thunar_vfs_job_emit_valist (job, signal_id, signal_detail, var_args); - va_end (var_args); -} - - - -/** - * @job : a #ThunarVfsJob. - * @signal_id : the id of the signal to emit on @job. - * @signal_detail : the detail. - * @var_args : a list of paramters to be passed to the signal. - * - * Emits the signal identified by @signal_id on @job in - * the context of the main thread. This method returns - * immediately, and does not wait for the signal to be - * emitted. - **/ -void -_thunar_vfs_job_notify_valist (ThunarVfsJob *job, - guint signal_id, - GQuark signal_detail, - va_list var_args) -{ - ThunarVfsJobEmitAsync *emit_async; - GSignalQuery signal_query; - gchar *error_message; - guint n; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_vfs_return_if_fail (job->priv->running); - - /* acquire the job subsystem lock */ - g_mutex_lock (job_mutex); - - /* check if we already have an async emission for the signal */ - for (emit_async = job->priv->emit_async; emit_async != NULL; emit_async = emit_async->next) - if (emit_async->signal_id == signal_id && emit_async->signal_detail == signal_detail) - break; - - /* override an existing emission */ - if (G_UNLIKELY (emit_async != NULL)) - { - /* release the previous values */ - _thunar_vfs_g_value_array_free (emit_async->values, emit_async->n_values); - } - else - { - /* allocate a new asynchronous emission */ - emit_async = _thunar_vfs_slice_new (ThunarVfsJobEmitAsync); - emit_async->signal_id = signal_id; - emit_async->signal_detail = signal_detail; - - /* add to the list */ - emit_async->next = job->priv->emit_async; - job->priv->emit_async = emit_async; - } - - /* query the signal information */ - g_signal_query (signal_id, &signal_query); - - /* allocate the parameter values */ - emit_async->n_values = signal_query.n_params + 1; - emit_async->values = g_new0 (GValue, emit_async->n_values); - - /* initialize the job parameter */ - g_value_init (emit_async->values, THUNAR_VFS_TYPE_JOB); - g_value_set_object (emit_async->values, job); - - /* add the remaining parameters */ - for (n = 0; n < signal_query.n_params; ++n) - { - /* collect the value from the stack */ - g_value_init (emit_async->values + n + 1, signal_query.param_types[n]); - G_VALUE_COLLECT (emit_async->values + n + 1, var_args, 0, &error_message); - - /* check if an error occurred */ - if (G_UNLIKELY (error_message != NULL)) - { - g_error ("%s: %s", G_STRLOC, error_message); - g_free (error_message); - } - } - - /* release the job subsystem lock */ - g_mutex_unlock (job_mutex); -} - - - -/** - * _thunar_vfs_job_emit: - * @job : a #ThunarVfsJob. - * @signal_id : the id of the signal to emit on qjob. - * @signal_detail : the signal detail. - * @... : a list of parameters to be passed to the signal. - * - * Convenience wrapper for thunar_vfs_job_notify_valist(). - **/ -void -_thunar_vfs_job_notify (ThunarVfsJob *job, - guint signal_id, - GQuark signal_detail, - ...) -{ - va_list var_args; - - va_start (var_args, signal_detail); - _thunar_vfs_job_notify_valist (job, signal_id, signal_detail, var_args); - va_end (var_args); -} - - - -/** - * _thunar_vfs_job_ask_valist: - * @job : a #ThunarVfsJob. - * @format : a printf(3)-style format string. - * @var_args : argument list for the @format. - * @question : the question text to append or %NULL. - * @choices : the possible choices. - * - * Sends the formatted question to the @job owner and awaits - * its answer. - * - * Return value: the response from the @job owner. - **/ -ThunarVfsJobResponse -_thunar_vfs_job_ask_valist (ThunarVfsJob *job, - const gchar *format, - va_list var_args, - const gchar *question, - ThunarVfsJobResponse choices) -{ - ThunarVfsJobResponse response; - gchar *message; - gchar *text; - - _thunar_vfs_return_val_if_fail (g_utf8_validate (format, -1, NULL), THUNAR_VFS_JOB_RESPONSE_CANCEL); - - /* send the question and wait for the answer */ - text = g_strdup_vprintf (format, var_args); - message = (question != NULL) ? g_strconcat (text, ".\n\n", question, NULL) : g_strconcat (text, ".", NULL); - _thunar_vfs_job_emit (job, job_signals[ASK], 0, message, choices, &response); - g_free (message); - g_free (text); - - /* cancel the job as per users request */ - if (G_UNLIKELY (response == THUNAR_VFS_JOB_RESPONSE_CANCEL)) - thunar_vfs_job_cancel (job); - - return response; -} - - - -/** - * _thunar_vfs_job_ask_overwrite: - * @job : a #ThunarVfsJob. - * @format : a printf(3)-style format string. - * @... : arguments for the @format. - * - * Asks the user whether to overwrite a certain file as described by - * the specified @format string. - * - * The return value may be %THUNAR_VFS_JOB_RESPONSE_CANCEL if the user - * cancelled the @job, or %THUNAR_VFS_JOB_RESPONSE_YES if the user - * wants to overwrite or %THUNAR_VFS_JOB_RESPONSE_NO if the user wants - * to keep the file, which does not necessarily mean to cancel the - * @job (whether the @job will be cancelled depends on the semantics - * of the @job). - * - * Return value: the response of the user. - **/ -ThunarVfsJobResponse -_thunar_vfs_job_ask_overwrite (ThunarVfsJob *job, - const gchar *format, - ...) -{ - ThunarVfsJobResponse response; - va_list var_args; - - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), THUNAR_VFS_JOB_RESPONSE_CANCEL); - - /* check if the user already cancelled the job */ - if (G_UNLIKELY (job->cancelled)) - return THUNAR_VFS_JOB_RESPONSE_CANCEL; - - /* check if the user said "Overwrite All" earlier */ - if (G_UNLIKELY (job->priv->ask_overwrite_all)) - return THUNAR_VFS_JOB_RESPONSE_YES; - - /* check if the user said "Overwrite None" earlier */ - if (G_UNLIKELY (job->priv->ask_overwrite_none)) - return THUNAR_VFS_JOB_RESPONSE_NO; - - /* ask the user using the provided format string */ - va_start (var_args, format); - response = _thunar_vfs_job_ask_valist (job, format, var_args, - _("Do you want to overwrite it?"), - THUNAR_VFS_JOB_RESPONSE_YES - | THUNAR_VFS_JOB_RESPONSE_YES_ALL - | THUNAR_VFS_JOB_RESPONSE_NO - | THUNAR_VFS_JOB_RESPONSE_NO_ALL - | THUNAR_VFS_JOB_RESPONSE_CANCEL); - va_end (var_args); - - /* translate the response */ - switch (response) - { - case THUNAR_VFS_JOB_RESPONSE_YES_ALL: - job->priv->ask_overwrite_all = TRUE; - response = THUNAR_VFS_JOB_RESPONSE_YES; - break; - - case THUNAR_VFS_JOB_RESPONSE_NO_ALL: - job->priv->ask_overwrite_none = TRUE; - response = THUNAR_VFS_JOB_RESPONSE_NO; - break; - - default: - break; - } - - return response; -} - - - -/** - * _thunar_vfs_job_ask_replace: - * @job : a #ThunarVfsJob. - * @src_path : the #ThunarVfsPath to the source file. - * @dst_path : the #ThunarVfsPath to the destination file. - * - * Return value: - **/ -ThunarVfsJobResponse -_thunar_vfs_job_ask_replace (ThunarVfsJob *job, - ThunarVfsPath *src_path, - ThunarVfsPath *dst_path) -{ - ThunarVfsJobResponse response; - ThunarVfsInfo *dst_info; - ThunarVfsInfo *src_info; - - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_vfs_return_val_if_fail (dst_path != NULL, THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_vfs_return_val_if_fail (src_path != NULL, THUNAR_VFS_JOB_RESPONSE_CANCEL); - - /* check if the user already cancelled the job */ - if (G_UNLIKELY (job->cancelled)) - return THUNAR_VFS_JOB_RESPONSE_CANCEL; - - /* check if the user said "Overwrite All" earlier */ - if (G_UNLIKELY (job->priv->ask_overwrite_all)) - return THUNAR_VFS_JOB_RESPONSE_YES; - - /* check if the user said "Overwrite None" earlier */ - if (G_UNLIKELY (job->priv->ask_overwrite_none)) - return THUNAR_VFS_JOB_RESPONSE_NO; - - /* determine the info of the source file (skip if disappeared) */ - src_info = thunar_vfs_info_new_for_path (src_path, NULL); - if (G_UNLIKELY (src_info == NULL)) - return THUNAR_VFS_JOB_RESPONSE_NO; - - /* determine the info of the target file (retry if disappeared) */ - dst_info = thunar_vfs_info_new_for_path (dst_path, NULL); - if (G_UNLIKELY (dst_info == NULL)) - { - thunar_vfs_info_unref (src_info); - return THUNAR_VFS_JOB_RESPONSE_RETRY; - } - - /* ask the user whether to replace the dst file with the src file */ - _thunar_vfs_job_emit (job, job_signals[ASK_REPLACE], 0, src_info, dst_info, &response); - - /* translate the response */ - switch (response) - { - case THUNAR_VFS_JOB_RESPONSE_YES_ALL: - job->priv->ask_overwrite_all = TRUE; - response = THUNAR_VFS_JOB_RESPONSE_YES; - break; - - case THUNAR_VFS_JOB_RESPONSE_NO_ALL: - job->priv->ask_overwrite_none = TRUE; - response = THUNAR_VFS_JOB_RESPONSE_NO; - break; - - case THUNAR_VFS_JOB_RESPONSE_CANCEL: - /* cancel the job as per users request */ - thunar_vfs_job_cancel (job); - break; - - default: - break; - } - - /* cleanup */ - thunar_vfs_info_unref (src_info); - thunar_vfs_info_unref (dst_info); - - return response; -} - - - -/** - * _thunar_vfs_job_ask_skip: - * @job : a #ThunarVfsJob. - * @format : a printf(3)-style format string. - * @... : arguments for the @format. - * - * Asks the user whether to skip a certain file as described by - * @format. - * - * Return value: %THUNAR_VFS_JOB_RESPONSE_CANCEL to cancel the - * @job, %THUNAR_VFS_JOB_RESPONSE_YES to skip - * the file or %THUNAR_VFS_JOB_RESPONSE_RETRY - * to retry the operation. - **/ -ThunarVfsJobResponse -_thunar_vfs_job_ask_skip (ThunarVfsJob *job, - const gchar *format, - ...) -{ - ThunarVfsJobResponse response; - va_list var_args; - - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_JOB (job), THUNAR_VFS_JOB_RESPONSE_CANCEL); - - /* check if the user already cancelled the job */ - if (G_UNLIKELY (job->cancelled)) - return THUNAR_VFS_JOB_RESPONSE_CANCEL; - - /* check if the user said "Skip All" earlier */ - if (G_UNLIKELY (job->priv->ask_skip_all)) - return THUNAR_VFS_JOB_RESPONSE_YES; - - /* ask the user using the provided format string */ - va_start (var_args, format); - response = _thunar_vfs_job_ask_valist (job, format, var_args, - _("Do you want to skip it?"), - THUNAR_VFS_JOB_RESPONSE_YES - | THUNAR_VFS_JOB_RESPONSE_YES_ALL - | THUNAR_VFS_JOB_RESPONSE_CANCEL - | THUNAR_VFS_JOB_RESPONSE_RETRY); - va_end (var_args); - - /* evaluate the response */ - switch (response) - { - case THUNAR_VFS_JOB_RESPONSE_YES_ALL: - job->priv->ask_skip_all = TRUE; - response = THUNAR_VFS_JOB_RESPONSE_YES; - break; - - case THUNAR_VFS_JOB_RESPONSE_YES: - case THUNAR_VFS_JOB_RESPONSE_CANCEL: - case THUNAR_VFS_JOB_RESPONSE_RETRY: - break; - - default: - _thunar_vfs_assert_not_reached (); - return FALSE; - } - - return response; -} - - - -/** - * _thunar_vfs_job_error: - * @job : a #ThunarVfsJob. - * @error : a #GError describing the error cause. - * - * Emits the ::error signal on @job with the given @error. Whether - * or not the @job continues after emitting the error depends on - * the particular implementation of @job, but most jobs will - * terminate instantly after emitting an error. - **/ -void -_thunar_vfs_job_error (ThunarVfsJob *job, - GError *error) -{ - _thunar_vfs_return_if_fail (error != NULL && g_utf8_validate (error->message, -1, NULL)); - _thunar_vfs_job_emit (job, job_signals[ERROR], 0, error); -} - - - -/** - * _thunar_vfs_job_info_message: - * @job : a #ThunarVfsJob. - * @message : the info message. - * - * Emits the ::info-message signal on @job with the info @message. - **/ -void -_thunar_vfs_job_info_message (ThunarVfsJob *job, - const gchar *message) -{ - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_vfs_return_if_fail (g_utf8_validate (message, -1, NULL)); - - _thunar_vfs_job_notify (job, job_signals[INFO_MESSAGE], 0, message); -} - - - -/** - * _thunar_vfs_job_infos_ready: - * @job : a #ThunarVfsJob. - * @info_list : a #GList of #ThunarVfsInfo<!---->s. - * - * Emits the ::infos-ready signal on @job with the given @info_list. - * - * Return value: %TRUE if any of the signal handlers took over - * ownership of the @info_list, %FALSE if the caller - * is responsible to free the @info_list. - **/ -gboolean -_thunar_vfs_job_infos_ready (ThunarVfsJob *job, - GList *info_list) -{ - gboolean handled = FALSE; - _thunar_vfs_return_val_if_fail (info_list != NULL, FALSE); - _thunar_vfs_job_emit (job, job_signals[INFOS_READY], 0, info_list, &handled); - return handled; -} - - - -/** - * thunar_vfs_job_new_files: - * @job : a #ThunarVfsJob. - * @path_list : the #ThunarVfsPath<!---->s that were created by the @job. - * - * Emits the ::new-files signal on @job with the @path_list. - **/ -void -_thunar_vfs_job_new_files (ThunarVfsJob *job, - const GList *path_list) -{ - /* check if any paths were supplied */ - if (G_LIKELY (path_list != NULL)) - { - /* wait for the monitor to process all pending events */ - thunar_vfs_monitor_wait (_thunar_vfs_monitor); - - /* emit the new-files signal */ - _thunar_vfs_job_emit (job, job_signals[NEW_FILES], 0, path_list); - } -} - - - -/** - * _thunar_vfs_job_percent: - * @job : a #ThunarVfsJob. - * @percent : the percentage of completion (in the range of 0.0 to 100.0). - * - * Emits the ::percent signal on @job with @percent. - **/ -void -_thunar_vfs_job_percent (ThunarVfsJob *job, - gdouble percent) -{ - /* clamp the value to the range 0.0 to 100.0 */ - if (G_UNLIKELY (percent < 0.0)) - percent = 0.0; - else if (G_UNLIKELY (percent > 100.0)) - percent = 100.0; - - /* notify about the new percentage */ - _thunar_vfs_job_notify (job, job_signals[PERCENT], 0, percent); -} - - - -/** - * _thunar_vfs_job_total_paths: - * @job : a #ThunarVfsJob. - * @total_paths : the total #GList of #ThunarVfsPath<!---->s to be processed - * by the @job. - * - * Use this method for jobs that work based on #ThunarVfsPath<!---->s - * to initialize the total paths and item count. - * - * Afterwards call _thunar_vfs_job_process_path() for every path that - * you begin to process. - * - * The @total_paths list must be valid for all invocations of the - * _thunar_vfs_job_process_path() method, otherwise the behaviour - * will be undefined. - **/ -void -_thunar_vfs_job_total_paths (ThunarVfsJob *job, - GList *total_paths) -{ - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_JOB (job)); - job->priv->total_paths = total_paths; -} - - - - -/** - * _thunar_vfs_job_process_path: - * @job : a #ThunarVfsJob. - * @path_list_item : the next #GList item in the list of - * #ThunarVfsPath<!---->s previously passed - * to _thunar_vfs_job_total_paths(). - * - * Use this method after setting the path list using - * _thunar_vfs_job_total_paths() to update both the - * info message and the percent for the @job. - * - * @path_list_item must be a list item in the path list previously - * set via _thunar_vfs_job_total_paths(). - **/ -void -_thunar_vfs_job_process_path (ThunarVfsJob *job, - GList *path_list_item) -{ - GList *lp; - gchar *display_name; - guint n_processed; - guint n_total; - - _thunar_vfs_return_if_fail (g_list_position (job->priv->total_paths, path_list_item) >= 0); - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_JOB (job)); - - /* update the info message to the path name */ - display_name = _thunar_vfs_path_dup_display_name (path_list_item->data); - _thunar_vfs_job_info_message (job, display_name); - g_free (display_name); - - /* verify that we have total_paths set */ - if (G_LIKELY (job->priv->total_paths != NULL)) - { - /* determine the number of processed paths */ - for (lp = job->priv->total_paths, n_processed = 0; lp != path_list_item; lp = lp->next, ++n_processed) - ; - - /* emit only if n_processed is a multiple of 8 */ - if ((n_processed % 8) == 0) - { - /* determine the total number of paths */ - for (n_total = n_processed; lp != NULL; lp = lp->next, ++n_total) - ; - - /* update the progress status */ - _thunar_vfs_job_percent (job, (n_processed * 100.0) / n_total); - } - } -} - - - -/** - * _thunar_vfs_job_init: - * - * Initializes the jobs module of the Thunar-VFS - * library. - **/ -void -_thunar_vfs_job_init (void) -{ - _thunar_vfs_return_if_fail (job_pool == NULL); - - /* allocate the synchronization entities */ - job_cond = g_cond_new (); - job_mutex = g_mutex_new (); - - /* allocate the shared thread pool */ - job_pool = g_thread_pool_new (thunar_vfs_job_execute, NULL, 8, FALSE, NULL); -} - - - -/** - * _thunar_vfs_job_shutdown: - * - * Shuts down the jobs module of the Thunar-VFS - * library. - **/ -void -_thunar_vfs_job_shutdown (void) -{ - _thunar_vfs_return_if_fail (job_pool != NULL); - - /* wait for all jobs to terminate */ - while (G_UNLIKELY (jobs_running > 0)) - g_main_context_iteration (NULL, TRUE); - - /* release the thread pool */ - g_thread_pool_free (job_pool, FALSE, TRUE); - job_pool = NULL; - - /* release the synchronization entities */ - g_mutex_free (job_mutex); - g_cond_free (job_cond); -} - - - -#define __THUNAR_VFS_JOB_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-job.h b/thunar-vfs/thunar-vfs-job.h deleted file mode 100644 index 8d768256a..000000000 --- a/thunar-vfs/thunar-vfs-job.h +++ /dev/null @@ -1,124 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_JOB_H__ -#define __THUNAR_VFS_JOB_H__ - -#include <thunar-vfs/thunar-vfs-info.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsJobPrivate ThunarVfsJobPrivate; -typedef struct _ThunarVfsJobClass ThunarVfsJobClass; -typedef struct _ThunarVfsJob ThunarVfsJob; - -#define THUNAR_VFS_TYPE_JOB (thunar_vfs_job_get_type ()) -#define THUNAR_VFS_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_JOB, ThunarVfsJob)) -#define THUNAR_VFS_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_JOB, ThunarVfsJobClass)) -#define THUNAR_VFS_IS_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_JOB)) -#define THUNAR_VFS_IS_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_JOB)) -#define THUNAR_VFS_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_JOB, ThunarVfsJobClass)) - -/** - * ThunarVfsJobResponse: - * @THUNAR_VFS_JOB_RESPONSE_YES : - * @THUNAR_VFS_JOB_RESPONSE_YES_ALL : - * @THUNAR_VFS_JOB_RESPONSE_NO : - * @THUNAR_VFS_JOB_RESPONSE_NO_ALL : - * @THUNAR_VFS_JOB_RESPONSE_CANCEL : - * @THUNAR_VFS_JOB_RESPONSE_RETRY : - * - * Possible responses for the ThunarVfsJob::ask signal. - **/ -typedef enum /*< flags >*/ -{ - THUNAR_VFS_JOB_RESPONSE_YES = 1 << 0, - THUNAR_VFS_JOB_RESPONSE_YES_ALL = 1 << 1, - THUNAR_VFS_JOB_RESPONSE_NO = 1 << 2, - THUNAR_VFS_JOB_RESPONSE_CANCEL = 1 << 3, - THUNAR_VFS_JOB_RESPONSE_NO_ALL = 1 << 4, - THUNAR_VFS_JOB_RESPONSE_RETRY = 1 << 5, -} ThunarVfsJobResponse; - -struct _ThunarVfsJobClass -{ - /*< private >*/ - GObjectClass __parent__; - - /*< public >*/ - - /* virtual methods */ - void (*execute) (ThunarVfsJob *job); - - /* signals */ - void (*finished) (ThunarVfsJob *job); - ThunarVfsJobResponse (*ask) (ThunarVfsJob *job, - const gchar *message, - ThunarVfsJobResponse choices); - ThunarVfsJobResponse (*ask_replace) (ThunarVfsJob *job, - ThunarVfsInfo *src_info, - ThunarVfsInfo *dst_info); - - /*< private >*/ - void (*reserved1) (void); - void (*reserved2) (void); -}; - -struct _ThunarVfsJob -{ - /*< private >*/ - GObject __parent__; - volatile gboolean cancelled; - ThunarVfsJobPrivate *priv; -}; - -GType thunar_vfs_job_get_type (void) G_GNUC_CONST; -ThunarVfsJob *thunar_vfs_job_launch (ThunarVfsJob *job); -void thunar_vfs_job_cancel (ThunarVfsJob *job); -G_INLINE_FUNC gboolean thunar_vfs_job_cancelled (const ThunarVfsJob *job); - - -/* inline function implementations */ -#if defined(G_CAN_INLINE) || defined(__THUNAR_VFS_JOB_C__) -/** - * thunar_vfs_job_cancelled: - * @job : a #ThunarVfsJob. - * - * Checks whether @job was previously cancelled - * by a call to thunar_vfs_job_cancel(). - * - * Return value: %TRUE if @job is cancelled. - **/ -G_INLINE_FUNC gboolean -thunar_vfs_job_cancelled (const ThunarVfsJob *job) -{ - g_return_val_if_fail (THUNAR_VFS_IS_JOB (job), FALSE); - return job->cancelled; -} -#endif /* G_CAN_INLINE || __THUNAR_VFS_JOB_C__ */ - - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_JOB_H__ */ diff --git a/thunar-vfs/thunar-vfs-marshal.list b/thunar-vfs/thunar-vfs-marshal.list deleted file mode 100644 index 2fa4d7db7..000000000 --- a/thunar-vfs/thunar-vfs-marshal.list +++ /dev/null @@ -1,4 +0,0 @@ -BOOLEAN:POINTER -FLAGS:BOXED,BOXED -FLAGS:STRING,FLAGS -VOID:UINT64,UINT,UINT,UINT diff --git a/thunar-vfs/thunar-vfs-mime-action-private.h b/thunar-vfs/thunar-vfs-mime-action-private.h deleted file mode 100644 index d0f71c0f0..000000000 --- a/thunar-vfs/thunar-vfs-mime-action-private.h +++ /dev/null @@ -1,50 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_MIME_ACTION_PRIVATE_H__ -#define __THUNAR_VFS_MIME_ACTION_PRIVATE_H__ - -#include <thunar-vfs/thunar-vfs-mime-action.h> -#include <thunar-vfs/thunar-vfs-mime-handler-private.h> - -G_BEGIN_DECLS; - -struct _ThunarVfsMimeActionClass -{ - ThunarVfsMimeHandlerClass __parent__; -}; - -struct _ThunarVfsMimeAction -{ - ThunarVfsMimeHandler __parent__; -}; - -ThunarVfsMimeAction *_thunar_vfs_mime_action_new (const gchar *command, - const gchar *name, - const gchar *icon, - ThunarVfsMimeHandlerFlags flags) G_GNUC_INTERNAL G_GNUC_MALLOC; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_ACTION_PRIVATE_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-action.c b/thunar-vfs/thunar-vfs-mime-action.c deleted file mode 100644 index 742b31961..000000000 --- a/thunar-vfs/thunar-vfs-mime-action.c +++ /dev/null @@ -1,92 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <thunar-vfs/thunar-vfs-mime-action-private.h> -#include <thunar-vfs/thunar-vfs-mime-action.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -GType -thunar_vfs_mime_action_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - static const GTypeInfo info = - { - sizeof (ThunarVfsMimeActionClass), - NULL, - NULL, - NULL, - NULL, - NULL, - sizeof (ThunarVfsMimeAction), - 0, - NULL, - NULL, - }; - - type = g_type_register_static (THUNAR_VFS_TYPE_MIME_HANDLER, I_("ThunarVfsMimeAction"), &info, 0); - } - - return type; -} - - - -/** - * _thunar_vfs_mime_action_new: - * @command : the command for the mime action. - * @name : the name for the mime action. - * @icon : the icon for the mime action or %NULL. - * @flags : the #ThunarVfsMimeHandlerFlags for the mime action. - * - * Allocates a new #ThunarVfsMimeAction with the given - * parameters. - * - * Return value: the newly allocated #ThunarVfsMimeAction. - **/ -ThunarVfsMimeAction* -_thunar_vfs_mime_action_new (const gchar *command, - const gchar *name, - const gchar *icon, - ThunarVfsMimeHandlerFlags flags) -{ - g_return_val_if_fail (g_utf8_validate (name, -1, NULL), NULL); - g_return_val_if_fail (command != NULL, NULL); - - return g_object_new (THUNAR_VFS_TYPE_MIME_ACTION, - "command", command, - "flags", flags, - "icon", icon, - "name", name, - NULL); -} - - - -#define __THUNAR_VFS_MIME_ACTION_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-mime-action.h b/thunar-vfs/thunar-vfs-mime-action.h deleted file mode 100644 index 223f8ec7e..000000000 --- a/thunar-vfs/thunar-vfs-mime-action.h +++ /dev/null @@ -1,46 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_MIME_ACTION_H__ -#define __THUNAR_VFS_MIME_ACTION_H__ - -#include <thunar-vfs/thunar-vfs-mime-handler.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsMimeActionClass ThunarVfsMimeActionClass; -typedef struct _ThunarVfsMimeAction ThunarVfsMimeAction; - -#define THUNAR_VFS_TYPE_MIME_ACTION (thunar_vfs_mime_action_get_type ()) -#define THUNAR_VFS_MIME_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_MIME_ACTION, ThunarVfsMimeAction)) -#define THUNAR_VFS_MIME_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_MIME_ACTION, ThunarVfsMimeActionClass)) -#define THUNAR_VFS_IS_MIME_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_MIME_ACTION)) -#define THUNAR_VFS_IS_MIME_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_MIME_ACTION)) -#define THUNAR_VFS_MIME_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_MIME_ACTION, ThunarVfsMimeActionClass)) - -GType thunar_vfs_mime_action_get_type (void) G_GNUC_CONST; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_ACTION_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-application.c b/thunar-vfs/thunar-vfs-mime-application.c deleted file mode 100644 index a80b3cf73..000000000 --- a/thunar-vfs/thunar-vfs-mime-application.c +++ /dev/null @@ -1,497 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#include <thunar-vfs/thunar-vfs-exec.h> -#include <thunar-vfs/thunar-vfs-mime-action-private.h> -#include <thunar-vfs/thunar-vfs-mime-application.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-util.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -static void thunar_vfs_mime_application_class_init (ThunarVfsMimeApplicationClass *klass); -static void thunar_vfs_mime_application_finalize (GObject *object); - - - -struct _ThunarVfsMimeApplicationClass -{ - ThunarVfsMimeHandlerClass __parent__; -}; - -struct _ThunarVfsMimeApplication -{ - ThunarVfsMimeHandler __parent__; - - GList *actions; - gchar *desktop_id; - gchar **mime_types; -}; - - - -static GObjectClass *thunar_vfs_mime_application_parent_class; - - - -GType -thunar_vfs_mime_application_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_MIME_HANDLER, - "ThunarVfsMimeApplication", - sizeof (ThunarVfsMimeApplicationClass), - thunar_vfs_mime_application_class_init, - sizeof (ThunarVfsMimeApplication), - NULL, - 0); - } - - return type; -} - - - -static void -thunar_vfs_mime_application_class_init (ThunarVfsMimeApplicationClass *klass) -{ - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_mime_application_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_mime_application_finalize; -} - - - -static void -thunar_vfs_mime_application_finalize (GObject *object) -{ - ThunarVfsMimeApplication *mime_application = THUNAR_VFS_MIME_APPLICATION (object); - - /* release the mime actions */ - g_list_foreach (mime_application->actions, (GFunc) g_object_unref, NULL); - g_list_free (mime_application->actions); - - /* release our attributes */ - g_strfreev (mime_application->mime_types); - g_free (mime_application->desktop_id); - - (*G_OBJECT_CLASS (thunar_vfs_mime_application_parent_class)->finalize) (object); -} - - - -/** - * thunar_vfs_mime_application_new_from_desktop_id: - * @desktop_id : the id of an application's .desktop file. - * - * Generates a #ThunarVfsMimeApplication instance for the application - * referenced by @desktop_id. Returns %NULL if @desktop_id is not valid. - * - * The caller is responsible to free the returned instance using - * g_object_unref() when no longer needed. - * - * Return value: the #ThunarVfsMimeApplication for @desktop_id or %NULL. - **/ -ThunarVfsMimeApplication* -thunar_vfs_mime_application_new_from_desktop_id (const gchar *desktop_id) -{ - ThunarVfsMimeApplication *application = NULL; - gchar *spec; - gchar *path = NULL; - gchar *s; - - g_return_val_if_fail (desktop_id != NULL, NULL); - - /* lookup the .desktop file by the given desktop-id */ - s = spec = g_build_filename ("applications", desktop_id, NULL); - do - { - path = xfce_resource_lookup (XFCE_RESOURCE_DATA, spec); - if (G_LIKELY (path != NULL)) - break; - - for (; *s != '\0' && *s != '-'; ++s) ; - if (G_LIKELY (*s == '-')) - *s++ = G_DIR_SEPARATOR; - } - while (*s != '\0'); - g_free (spec); - - /* check if we found a file */ - if (G_UNLIKELY (path == NULL)) - return NULL; - - /* try to load the application from the path */ - application = thunar_vfs_mime_application_new_from_file (path, desktop_id); - - /* cleanup */ - g_free (path); - - return application; -} - - - -/** - * thunar_vfs_mime_application_new_from_file: - * @path : the absolute path to the desktop file. - * @desktop_id : the desktop-id of the file. - * - * Generates a new #ThunarVfsMimeApplication for the application - * described by @path and @desktop_id. - * - * The caller is responsible to free the returned instance using - * g_object_unref() when no longer needed. - * - * You should really seldomly use this function and always - * prefer thunar_vfs_mime_application_new_from_desktop_id(). - * - * Return value: the #ThunarVfsMimeApplication for @desktop_id - * or %NULL. - **/ -ThunarVfsMimeApplication* -thunar_vfs_mime_application_new_from_file (const gchar *path, - const gchar *desktop_id) -{ - ThunarVfsMimeHandlerFlags flags = 0; - ThunarVfsMimeApplication *application = NULL; - ThunarVfsMimeAction *action; - const gchar *tryexec; - const gchar *exec; - const gchar *icon; - const gchar *name; - gboolean present; - XfceRc *rc; - gchar *command; - gchar **actions; - gchar *group; - gchar **ms; - gchar **mt; - guint n; - - g_return_val_if_fail (g_path_is_absolute (path), NULL); - g_return_val_if_fail (desktop_id != NULL && *desktop_id != '\0', NULL); - - /* try to open the .desktop file */ - rc = xfce_rc_simple_open (path, TRUE); - if (G_UNLIKELY (rc == NULL)) - return NULL; - - /* parse the file */ - xfce_rc_set_group (rc, "Desktop Entry"); - name = xfce_rc_read_entry (rc, "Name", NULL); - exec = xfce_rc_read_entry_untranslated (rc, "Exec", NULL); - icon = xfce_rc_read_entry_untranslated (rc, "Icon", NULL); - - /* check if we have a TryExec field */ - tryexec = xfce_rc_read_entry_untranslated (rc, "TryExec", NULL); - tryexec = (tryexec != NULL) ? tryexec : exec; - if (G_LIKELY (tryexec != NULL && g_shell_parse_argv (tryexec, NULL, &mt, NULL))) - { - /* check if we have an absolute path to an existing file */ - present = g_file_test (mt[0], G_FILE_TEST_EXISTS); - - /* else, we may have a program in $PATH */ - if (G_LIKELY (!present)) - { - command = g_find_program_in_path (mt[0]); - present = (command != NULL); - g_free (command); - } - - /* cleanup */ - g_strfreev (mt); - - /* if the program is not present, there's no reason to allocate a MimeApplication for it */ - if (G_UNLIKELY (!present)) - { - xfce_rc_close (rc); - return NULL; - } - } - - /* generate the application object */ - if (G_LIKELY (exec != NULL && name != NULL && g_utf8_validate (name, -1, NULL))) - { - /* we assume %f if the application hasn't set anything else, - * as that's also what KDE and Gnome do in this case. - */ - if (strstr (exec, "%f") == NULL && strstr (exec, "%F") == NULL && strstr (exec, "%u") == NULL && strstr (exec, "%U") == NULL) - command = g_strconcat (exec, " %f", NULL); - else - command = g_strdup (exec); - - /* determine the flags for the application */ - if (G_UNLIKELY (xfce_rc_read_bool_entry (rc, "Terminal", FALSE))) - flags |= THUNAR_VFS_MIME_HANDLER_REQUIRES_TERMINAL; - if (xfce_rc_read_bool_entry (rc, "Hidden", FALSE) || xfce_rc_read_bool_entry (rc, "NoDisplay", FALSE)) - flags |= THUNAR_VFS_MIME_HANDLER_HIDDEN; - if (xfce_rc_read_bool_entry (rc, "StartupNotify", FALSE) || xfce_rc_read_bool_entry (rc, "X-KDE-StartupNotify", FALSE)) - flags |= THUNAR_VFS_MIME_HANDLER_SUPPORTS_STARTUP_NOTIFY; - if ((strstr (command, "%F") != NULL) || (strstr (command, "%U") != NULL)) - flags |= THUNAR_VFS_MIME_HANDLER_SUPPORTS_MULTI; - if ((strstr (command, "%u") != NULL) || (strstr (command, "%U") != NULL)) - flags |= THUNAR_VFS_MIME_HANDLER_SUPPORTS_URIS; - - /* allocate a new application instance */ - application = g_object_new (THUNAR_VFS_TYPE_MIME_APPLICATION, "command", command, "flags", flags, "icon", icon, "name", name, NULL); - application->desktop_id = g_strdup (desktop_id); - - /* determine the list of mime types supported by the application */ - application->mime_types = xfce_rc_read_list_entry (rc, "MimeType", ";"); - if (G_LIKELY (application->mime_types != NULL)) - { - /* strip off the useless mime types */ - for (ms = mt = application->mime_types; *ms != NULL; ++ms) - { - /* ignore empty entries, GNOME pseudo mime types and KDE junk */ - if (**ms == '\0' || g_str_equal (*ms, "x-directory/gnome-default-handler") || strncmp (*ms, "print/", 6) == 0) - g_free (*ms); - else - *mt++ = *ms; - } - - /* verify that we have atleast one mime type left */ - if (G_UNLIKELY (mt == application->mime_types)) - { - g_free (application->mime_types); - application->mime_types = NULL; - } - else - { - /* be sure to zero-terminate the new list */ - *mt = NULL; - } - } - - /* determine the list of desktop actions supported by the application */ - actions = xfce_rc_read_list_entry (rc, "Actions", ";"); - if (G_UNLIKELY (actions != NULL)) - { - /* add ThunarVfsMimeAction's for all specified desktop actions */ - for (n = 0; actions[n] != NULL; ++n) - { - /* determine the group name */ - group = g_strconcat ("Desktop Action ", actions[n], NULL); - if (xfce_rc_has_group (rc, group)) - { - /* determine the attributes for the action */ - xfce_rc_set_group (rc, group); - name = xfce_rc_read_entry (rc, "Name", NULL); - exec = xfce_rc_read_entry_untranslated (rc, "Exec", NULL); - icon = xfce_rc_read_entry_untranslated (rc, "Icon", NULL); - - /* check if the required attributes were given */ - if (exec != NULL && name != NULL && g_utf8_validate (name, -1, NULL)) - { - /* check if the actions support multiple files */ - if ((strstr (exec, "%F") != NULL) || (strstr (exec, "%U") != NULL)) - flags |= THUNAR_VFS_MIME_HANDLER_SUPPORTS_MULTI; - else - flags &= ~THUNAR_VFS_MIME_HANDLER_SUPPORTS_MULTI; - - /* check if the actions support URIs */ - if ((strstr (exec, "%u") != NULL) || (strstr (exec, "%U") != NULL)) - flags |= THUNAR_VFS_MIME_HANDLER_SUPPORTS_URIS; - else - flags &= ~THUNAR_VFS_MIME_HANDLER_SUPPORTS_URIS; - - /* don't trust application maintainers! :-) */ - flags &= ~THUNAR_VFS_MIME_HANDLER_SUPPORTS_STARTUP_NOTIFY; - - /* allocate and add the mime action instance */ - action = _thunar_vfs_mime_action_new (exec, name, (icon != NULL) ? icon : THUNAR_VFS_MIME_HANDLER (application)->icon, flags); - application->actions = g_list_append (application->actions, action); - } - } - - /* release the group name */ - g_free (group); - } - - /* cleanup */ - g_strfreev (actions); - } - - /* cleanup */ - g_free (command); - } - - /* close the file */ - xfce_rc_close (rc); - - return application; -} - - - -/** - * thunar_vfs_mime_application_is_usercreated: - * @mime_application : a #ThunarVfsMimeApplication. - * - * Returns %TRUE if the @mime_application was created by the user - * using a file manager, i.e. through the "Open With" dialog in - * Thunar. - * - * Return value: %TRUE if @mime_application is usercreated. - **/ -gboolean -thunar_vfs_mime_application_is_usercreated (const ThunarVfsMimeApplication *mime_application) -{ - g_return_val_if_fail (THUNAR_VFS_IS_MIME_APPLICATION (mime_application), FALSE); - return (strstr (mime_application->desktop_id, "-usercreated") != NULL); -} - - - -/** - * thunar_vfs_mime_application_get_actions: - * @mime_application : a #ThunarVfsMimeApplication. - * - * Returns the list of #ThunarVfsMimeAction<!---->s available - * for the @mime_application. The #ThunarVfsMimeAction<!---->s - * are an implementation of the desktop actions mentioned in - * the desktop entry specification. - * - * The caller is responsible to free the returned list using - * <informalexample><programlisting> - * g_list_foreach (list, (GFunc) g_object_unref, NULL); - * g_list_free (list); - * </programlisting></informalexample> - * when no longer needed. - * - * Return value: the list of #ThunarVfsMimeAction<!---->s - * for the @mime_application. - **/ -GList* -thunar_vfs_mime_application_get_actions (ThunarVfsMimeApplication *mime_application) -{ - GList *mime_actions; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_APPLICATION (mime_application), NULL); - - /* take a deep copy of the mime actions list */ - mime_actions = g_list_copy (mime_application->actions); - g_list_foreach (mime_actions, (GFunc) g_object_ref, NULL); - - return mime_actions; -} - - - -/** - * thunar_vfs_mime_application_get_desktop_id: - * @mime_application : a #ThunarVfsMimeApplication. - * - * Returns the desktop-id of @mime_application. - * - * Return value: the desktop-id of @mime_application. - **/ -const gchar* -thunar_vfs_mime_application_get_desktop_id (const ThunarVfsMimeApplication *mime_application) -{ - g_return_val_if_fail (THUNAR_VFS_IS_MIME_APPLICATION (mime_application), NULL); - return mime_application->desktop_id; -} - - - -/** - * thunar_vfs_mime_application_get_mime_types: - * @mime_application : a #ThunarVfsMimeApplication. - * - * Returns the list of MIME-types supported by @application - * or %NULL if the @mime_application doesn't support any MIME-types - * at all. - * - * The returned %NULL-terminated string array is owned by - * @mime_application and must not be free by the caller. - * - * Return value: the list of supported MIME-types for @mime_application. - **/ -const gchar* const* -thunar_vfs_mime_application_get_mime_types (const ThunarVfsMimeApplication *mime_application) -{ - g_return_val_if_fail (THUNAR_VFS_IS_MIME_APPLICATION (mime_application), NULL); - return (gconstpointer) mime_application->mime_types; -} - - - -/** - * thunar_vfs_mime_application_hash: - * @mime_application : a #ThunarVfsMimeApplication. - * - * Converts @mime_application to a hash value. It can be - * passed to g_hash_table_new() as the @hash_func parameter, - * when using #ThunarVfsMimeApplication<!---->s as keys - * in a #GHashTable. - * - * Return value: a hash value corresponding to the key. - **/ -guint -thunar_vfs_mime_application_hash (gconstpointer mime_application) -{ - g_return_val_if_fail (THUNAR_VFS_IS_MIME_APPLICATION (mime_application), 0); - return g_str_hash (THUNAR_VFS_MIME_APPLICATION (mime_application)->desktop_id); -} - - - -/** - * thunar_vfs_mime_application_equal: - * @a : a #ThunarVfsMimeApplication. - * @b : a #ThunarVfsMimeApplication. - * - * Checks whether @a and @b refer to the same application. - * - * Return value: %TRUE if @a and @b are equal. - **/ -gboolean -thunar_vfs_mime_application_equal (gconstpointer a, - gconstpointer b) -{ - return exo_str_is_equal (THUNAR_VFS_MIME_APPLICATION (a)->desktop_id, - THUNAR_VFS_MIME_APPLICATION (b)->desktop_id); -} - - - -#define __THUNAR_VFS_MIME_APPLICATION_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-mime-application.h b/thunar-vfs/thunar-vfs-mime-application.h deleted file mode 100644 index 314c0b561..000000000 --- a/thunar-vfs/thunar-vfs-mime-application.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_MIME_APPLICATION_H__ -#define __THUNAR_VFS_MIME_APPLICATION_H__ - -#include <thunar-vfs/thunar-vfs-config.h> -#include <thunar-vfs/thunar-vfs-mime-handler.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsMimeApplicationClass ThunarVfsMimeApplicationClass; -typedef struct _ThunarVfsMimeApplication ThunarVfsMimeApplication; - -#define THUNAR_VFS_TYPE_MIME_APPLICATION (thunar_vfs_mime_application_get_type ()) -#define THUNAR_VFS_MIME_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_MIME_APPLICATION, ThunarVfsMimeApplication)) -#define THUNAR_VFS_MIME_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_MIME_APPLICATION, ThunarVfsMimeApplicationClass)) -#define THUNAR_VFS_IS_MIME_APPLICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_MIME_APPLICATION)) -#define THUNAR_VFS_IS_MIME_APPLICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_MIME_APPLICATION)) -#define THUNAR_VFS_MIME_APPLICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_MIME_APPLICATION, ThunarVfsMimeApplicationClass)) - -GType thunar_vfs_mime_application_get_type (void) G_GNUC_CONST; - -ThunarVfsMimeApplication *thunar_vfs_mime_application_new_from_desktop_id (const gchar *desktop_id) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsMimeApplication *thunar_vfs_mime_application_new_from_file (const gchar *path, - const gchar *desktop_id) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -gboolean thunar_vfs_mime_application_is_usercreated (const ThunarVfsMimeApplication *mime_application) G_GNUC_WARN_UNUSED_RESULT; - -GList *thunar_vfs_mime_application_get_actions (ThunarVfsMimeApplication *mime_application) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -const gchar *thunar_vfs_mime_application_get_desktop_id (const ThunarVfsMimeApplication *mime_application) G_GNUC_WARN_UNUSED_RESULT; -const gchar * const *thunar_vfs_mime_application_get_mime_types (const ThunarVfsMimeApplication *mime_application) G_GNUC_WARN_UNUSED_RESULT; - -guint thunar_vfs_mime_application_hash (gconstpointer mime_application) G_GNUC_WARN_UNUSED_RESULT; -gboolean thunar_vfs_mime_application_equal (gconstpointer a, - gconstpointer b) G_GNUC_WARN_UNUSED_RESULT; - -/** - * thunar_vfs_mime_application_get_command: - * @mime_application : a #ThunarVfsMimeApplication. - * - * Returns the command for @mime_application. - * - * Return value: the command for @mime_application. - **/ -#define thunar_vfs_mime_application_get_command(mime_application) (thunar_vfs_mime_handler_get_command (THUNAR_VFS_MIME_HANDLER ((mime_application)))) - -/** - * thunar_vfs_mime_application_get_flags: - * @mime_application : a #ThunarVfsMimeApplication. - * - * Returns the #ThunarVfsMimeHandlerFlags for @mime_handler. - * - * Return value: the flags for @mime_application. - **/ -#define thunar_vfs_mime_application_get_flags(mime_application) (thunar_vfs_mime_handler_get_flags (THUNAR_VFS_MIME_HANDLER ((mime_application)))) - -/** - * thunar_vfs_mime_application_get_name: - * @mime_application : a #ThunarVfsMimeApplication. - * - * Returns the name for @mime_application. - * - * Return value: the name for @mime_application. - **/ -#define thunar_vfs_mime_application_get_name(mime_application) (thunar_vfs_mime_handler_get_name (THUNAR_VFS_MIME_HANDLER ((mime_application)))) - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_APPLICATION_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-cache.c b/thunar-vfs/thunar-vfs-mime-cache.c deleted file mode 100644 index fb937498d..000000000 --- a/thunar-vfs/thunar-vfs-mime-cache.c +++ /dev/null @@ -1,583 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Based on code initially written by Matthias Clasen <mclasen@redhat.com> - * for the xdgmime library. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_FNMATCH_H -#include <fnmatch.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-mime-cache.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* use g_open() on win32 */ -#if GLIB_CHECK_VERSION(2,6,0) && defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_open(path, flags, mode) (open ((path), (flags), (mode))) -#endif - - - -#define CACHE_MAJOR_VERSION (1) -#define CACHE_MINOR_VERSION (0) - -#define CACHE_READ16(cache, offset) (GUINT16_FROM_BE (*((guint16 *) ((cache) + (offset))))) -#define CACHE_READ32(cache, offset) (GUINT32_FROM_BE (*((guint32 *) ((cache) + (offset))))) - - - -static void thunar_vfs_mime_cache_class_init (ThunarVfsMimeCacheClass *klass); -static void thunar_vfs_mime_cache_finalize (GObject *object); -static const gchar *thunar_vfs_mime_cache_lookup_data (ThunarVfsMimeProvider *provider, - gconstpointer data, - gsize length, - gint *priority); -static const gchar *thunar_vfs_mime_cache_lookup_literal (ThunarVfsMimeProvider *provider, - const gchar *filename); -static const gchar *thunar_vfs_mime_cache_lookup_suffix (ThunarVfsMimeProvider *provider, - const gchar *suffix, - gboolean ignore_case); -static const gchar *thunar_vfs_mime_cache_lookup_glob (ThunarVfsMimeProvider *provider, - const gchar *filename); -static const gchar *thunar_vfs_mime_cache_lookup_alias (ThunarVfsMimeProvider *provider, - const gchar *alias); -static guint thunar_vfs_mime_cache_lookup_parents (ThunarVfsMimeProvider *provider, - const gchar *mime_type, - gchar **parents, - guint max_parents); -static GList *thunar_vfs_mime_cache_get_stop_characters (ThunarVfsMimeProvider *provider); -static gsize thunar_vfs_mime_cache_get_max_buffer_extents (ThunarVfsMimeProvider *provider); - - - -struct _ThunarVfsMimeCacheClass -{ - ThunarVfsMimeProviderClass __parent__; -}; - -struct _ThunarVfsMimeCache -{ - ThunarVfsMimeProvider __parent__; - - gchar *buffer; - gsize bufsize; -}; - - - -static GObjectClass *thunar_vfs_mime_cache_parent_class; - - - -GType -thunar_vfs_mime_cache_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_MIME_PROVIDER, - "ThunarVfsMimeCache", - sizeof (ThunarVfsMimeCacheClass), - thunar_vfs_mime_cache_class_init, - sizeof (ThunarVfsMimeCache), - NULL, - 0); - } - - return type; -} - - - -static void -thunar_vfs_mime_cache_class_init (ThunarVfsMimeCacheClass *klass) -{ - ThunarVfsMimeProviderClass *thunarvfs_mime_provider_class; - GObjectClass *gobject_class; - - thunar_vfs_mime_cache_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_mime_cache_finalize; - - thunarvfs_mime_provider_class = THUNAR_VFS_MIME_PROVIDER_CLASS (klass); - thunarvfs_mime_provider_class->lookup_data = thunar_vfs_mime_cache_lookup_data; - thunarvfs_mime_provider_class->lookup_literal = thunar_vfs_mime_cache_lookup_literal; - thunarvfs_mime_provider_class->lookup_suffix = thunar_vfs_mime_cache_lookup_suffix; - thunarvfs_mime_provider_class->lookup_glob = thunar_vfs_mime_cache_lookup_glob; - thunarvfs_mime_provider_class->lookup_alias = thunar_vfs_mime_cache_lookup_alias; - thunarvfs_mime_provider_class->lookup_parents = thunar_vfs_mime_cache_lookup_parents; - thunarvfs_mime_provider_class->get_stop_characters = thunar_vfs_mime_cache_get_stop_characters; - thunarvfs_mime_provider_class->get_max_buffer_extents = thunar_vfs_mime_cache_get_max_buffer_extents; -} - - - -static void -thunar_vfs_mime_cache_finalize (GObject *object) -{ -#ifdef HAVE_MMAP - ThunarVfsMimeCache *cache = THUNAR_VFS_MIME_CACHE (object); - - if (G_LIKELY (cache->buffer != NULL)) - munmap (cache->buffer, cache->bufsize); -#endif - - (*G_OBJECT_CLASS (thunar_vfs_mime_cache_parent_class)->finalize) (object); -} - - - -static gboolean -cache_magic_matchlet_compare_to_data (const gchar *buffer, - guint32 offset, - gconstpointer data, - gsize length) -{ - gboolean valid_matchlet; - guint32 range_start = CACHE_READ32 (buffer, offset); - guint32 range_length = CACHE_READ32 (buffer, offset + 4); - guint32 data_length = CACHE_READ32 (buffer, offset + 12); - guint32 data_offset = CACHE_READ32 (buffer, offset + 16); - guint32 mask_offset = CACHE_READ32 (buffer, offset + 20); - guint32 i, j; - - for (i = range_start; i <= range_start + range_length; i++) - { - valid_matchlet = TRUE; - - if (i + data_length > length) - return FALSE; - - if (mask_offset) - { - for (j = 0; j < data_length; j++) - if ((buffer[data_offset + j] & buffer[mask_offset + j]) != ((((gchar *) data)[j + i]) & buffer[mask_offset + j])) - { - valid_matchlet = FALSE; - break; - } - } - else - { - for (j = 0; j < data_length; j++) - if (buffer[data_offset + j] != ((gchar *) data)[j + i]) - { - valid_matchlet = FALSE; - break; - } - } - - if (valid_matchlet) - return TRUE; - } - - return FALSE; -} - - - -static gboolean -cache_magic_matchlet_compare (const gchar *buffer, - guint32 offset, - gconstpointer data, - gsize length) -{ - guint32 n_children = CACHE_READ32 (buffer, offset + 24); - guint32 child_offset = CACHE_READ32 (buffer, offset + 28); - guint32 i; - - if (cache_magic_matchlet_compare_to_data (buffer, offset, data, length)) - { - if (n_children == 0) - return TRUE; - - for (i = 0; i < n_children; i++) - if (cache_magic_matchlet_compare (buffer, child_offset + 32 * i, data, length)) - return TRUE; - } - - return FALSE; -} - - - -static const gchar* -thunar_vfs_mime_cache_lookup_data (ThunarVfsMimeProvider *provider, - gconstpointer data, - gsize length, - gint *priority) -{ - const gchar *buffer = THUNAR_VFS_MIME_CACHE (provider)->buffer; - guint32 matchlet_offset; - guint32 offset; - guint32 n, m; - - offset = CACHE_READ32 (buffer, 24); - n = CACHE_READ32 (buffer, offset); - offset = CACHE_READ32 (buffer, offset + 8); - - for (; n-- > 0; offset += 16) - { - matchlet_offset = CACHE_READ32 (buffer, offset + 12); - for (m = CACHE_READ32 (buffer, offset + 8); m-- > 0; matchlet_offset += 32) - if (cache_magic_matchlet_compare (buffer, matchlet_offset, data, length)) - { - if (G_LIKELY (priority != NULL)) - *priority = (gint) CACHE_READ32 (buffer, offset); - return buffer + CACHE_READ32 (buffer, offset + 4); - } - } - - return NULL; -} - - - -static const gchar* -thunar_vfs_mime_cache_lookup_literal (ThunarVfsMimeProvider *provider, - const gchar *filename) -{ - const gchar *buffer = THUNAR_VFS_MIME_CACHE (provider)->buffer; - guint32 list_offset = CACHE_READ32 (buffer, 12); - guint32 n_entries = CACHE_READ32 (buffer, list_offset); - guint32 offset; - gint min; - gint mid; - gint max; - gint cmp; - - for (min = 0, max = (gint) n_entries - 1; max >= min; ) - { - mid = (min + max) / 2; - - offset = CACHE_READ32 (buffer, list_offset + 4 + 8 * mid); - cmp = strcmp (buffer + offset, filename); - - if (cmp < 0) - min = mid + 1; - else if (cmp > 0) - max = mid - 1; - else - return buffer + CACHE_READ32 (buffer, list_offset + 4 + 8 * mid + 4); - } - - return NULL; -} - - - -static const gchar* -cache_node_lookup_suffix (const gchar *buffer, - guint32 n_entries, - guint32 offset, - const gchar *suffix, - gboolean ignore_case) -{ - const gchar *type; - gunichar character; - gunichar match_char; - gint min, max, mid; - -next: - character = g_utf8_get_char (suffix); - if (ignore_case) - character = g_unichar_tolower (character); - - for (min = 0, max = (gint) n_entries - 1; max >= min; ) - { - mid = (min + max) / 2; - - match_char = (gunichar) CACHE_READ32 (buffer, offset + 16 * mid); - - if (match_char < character) - min = mid + 1; - else if (match_char > character) - max = mid - 1; - else - { - suffix = g_utf8_next_char (suffix); - if (*suffix == '\0') - { - /* need to verify the type here, as the stopchars may be - * misleading, which in turn may lead to the problem of - * returning '' here, which in turn will cause the mime - * database to return application/octet-stream for those - * files! - */ - type = buffer + CACHE_READ32 (buffer, offset + 16 * mid + 4); - if (G_LIKELY (*type != '\0')) - return type; - } - else - { - /* We emulate a recursive call to cache_node_lookup_suffix() - * here. This optimization works because the algorithm is - * tail-recursive. The goto is not necessarily nice, but it - * works for our purpose and doesn't decrease readability. - * If we'd use a recursive call here, the code would look - * like this: - * - * return cache_node_lookup_suffix (buffer, CACHE_READ32 (buffer, offset + 16 * mid + 8), - * CACHE_READ32 (buffer, offset + 16 * mid + 12), - * suffix, ignore_case); - */ - n_entries = CACHE_READ32 (buffer, offset + 16 * mid + 8); - offset = CACHE_READ32 (buffer, offset + 16 * mid + 12); - goto next; - } - } - } - - return NULL; -} - - - -static const gchar* -thunar_vfs_mime_cache_lookup_suffix (ThunarVfsMimeProvider *provider, - const gchar *suffix, - gboolean ignore_case) -{ - const gchar *buffer = THUNAR_VFS_MIME_CACHE (provider)->buffer; - guint32 offset = CACHE_READ32 (buffer, 16); - - g_return_val_if_fail (g_utf8_validate (suffix, -1, NULL), NULL); - - return cache_node_lookup_suffix (buffer, CACHE_READ32 (buffer, offset), - CACHE_READ32 (buffer, offset + 4), - suffix, ignore_case); -} - - - -static const gchar* -thunar_vfs_mime_cache_lookup_glob (ThunarVfsMimeProvider *provider, - const gchar *filename) -{ - const gchar *buffer = THUNAR_VFS_MIME_CACHE (provider)->buffer; - guint32 list_offset = CACHE_READ32 (buffer, 20); - guint32 n_entries = CACHE_READ32 (buffer, list_offset); - guint32 n; - - for (n = 0; n < n_entries; ++n) - if (fnmatch (buffer + CACHE_READ32 (buffer, list_offset + 4 + 8 * n), filename, 0) == 0) - return buffer + CACHE_READ32 (buffer, list_offset + 4 + 8 * n + 4); - - return NULL; -} - - - -static const gchar* -thunar_vfs_mime_cache_lookup_alias (ThunarVfsMimeProvider *provider, - const gchar *alias) -{ - const gchar *buffer = THUNAR_VFS_MIME_CACHE (provider)->buffer; - guint32 list_offset = CACHE_READ32 (buffer, 4); - gint max; - gint mid; - gint min; - gint n; - - for (max = ((gint) CACHE_READ32 (buffer, list_offset)) - 1, min = 0; max >= min; ) - { - mid = (min + max) / 2; - - n = strcmp (buffer + CACHE_READ32 (buffer, list_offset + 4 + 8 * mid), alias); - if (n < 0) - min = mid + 1; - else if (n > 0) - max = mid - 1; - else - return buffer + CACHE_READ32 (buffer, list_offset + 4 + 8 * mid + 4); - } - - return NULL; -} - - - -static guint -thunar_vfs_mime_cache_lookup_parents (ThunarVfsMimeProvider *provider, - const gchar *mime_type, - gchar **parents, - guint max_parents) -{ - const gchar *buffer = THUNAR_VFS_MIME_CACHE (provider)->buffer; - guint32 parents_offset; - guint32 list_offset = CACHE_READ32 (buffer, 8); - guint32 n_entries = CACHE_READ32 (buffer, list_offset); - guint32 n_parents; - guint32 i, j, l; - - for (i = j = 0; i < n_entries && j < max_parents; ++i) - if (strcmp (buffer + CACHE_READ32 (buffer, list_offset + 4 + 8 * i), mime_type) == 0) - { - parents_offset = CACHE_READ32 (buffer, list_offset + 4 + 8 * i + 4); - n_parents = CACHE_READ32 (buffer, parents_offset); - - for (l = 0; l < n_parents && j < max_parents; ++l, ++j) - parents[j] = (gchar *) (buffer + CACHE_READ32 (buffer, parents_offset + 4 + 4 * l)); - } - - return j; -} - - - -static GList* -thunar_vfs_mime_cache_get_stop_characters (ThunarVfsMimeProvider *provider) -{ - const gchar *buffer = THUNAR_VFS_MIME_CACHE (provider)->buffer; - gunichar character; - guint32 offset = CACHE_READ32 (buffer, 16); - guint32 n = CACHE_READ32 (buffer, offset); - GList *list = NULL; - - for (offset = CACHE_READ32 (buffer, offset + 4); n-- > 0; offset += 16) - { - /* query the suffix start character */ - character = (gunichar) CACHE_READ32 (buffer, offset); - if (G_UNLIKELY (character >= 128)) - continue; - - /* prepend the character to the list (if not already present) */ - if (G_UNLIKELY (g_list_find (list, GUINT_TO_POINTER (character)) == NULL)) - list = g_list_prepend (list, GUINT_TO_POINTER (character)); - } - - return list; -} - - - -static gsize -thunar_vfs_mime_cache_get_max_buffer_extents (ThunarVfsMimeProvider *provider) -{ - const gchar *buffer = THUNAR_VFS_MIME_CACHE (provider)->buffer; - - /* get the MAX_EXTENTS entry from the MagicList */ - return CACHE_READ32 (buffer, CACHE_READ32 (buffer, 24) + 4); -} - - - -/** - * thunar_vfs_mime_cache_new: - * @directory : the mime base directory. - * - * Creates a new #ThunarVfsMimeCache for @directory. Returns - * %NULL if for some reason, @directory could not be opened - * as a #ThunarVfsMimeCache. - * - * The caller is responsible to call g_object_unref() - * on the returned instance. - * - * Return value: a #ThunarVfsMimeCache for @directory or %NULL. - **/ -ThunarVfsMimeProvider* -thunar_vfs_mime_cache_new (const gchar *directory) -{ - ThunarVfsMimeCache *cache = NULL; - -#ifdef HAVE_MMAP - struct stat stat; - gchar *buffer; - gchar *path; - gint fd; - - /* try to open the mime.cache file */ - path = g_build_filename (directory, "mime.cache", NULL); - fd = g_open (path, O_RDONLY, 0); - g_free (path); - - if (G_UNLIKELY (fd < 0)) - return NULL; - - /* stat the file to get proper size info */ - if (fstat (fd, &stat) < 0 || stat.st_size < 4) - goto done; - - /* try to map the file into memory */ - buffer = (gchar *) mmap (NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (G_UNLIKELY (buffer == MAP_FAILED)) - goto done; - - /* check that we actually support the file version */ - if (CACHE_READ16 (buffer, 0) != CACHE_MAJOR_VERSION || CACHE_READ16 (buffer, 2) != CACHE_MINOR_VERSION) - { - munmap (buffer, stat.st_size); - goto done; - } - - /* allocate a new cache provider */ - cache = g_object_new (THUNAR_VFS_TYPE_MIME_CACHE, NULL); - cache->buffer = buffer; - cache->bufsize = stat.st_size; - - /* tell the system that we'll use this buffer quite often */ -#ifdef HAVE_POSIX_MADVISE - posix_madvise (buffer, stat.st_size, POSIX_MADV_WILLNEED); -#endif - - /* cleanup */ -done: - if (G_LIKELY (fd >= 0)) - close (fd); -#endif /* !HAVE_MMAP */ - - return (ThunarVfsMimeProvider *) cache; -} - - - -#define __THUNAR_VFS_MIME_CACHE_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-mime-cache.h b/thunar-vfs/thunar-vfs-mime-cache.h deleted file mode 100644 index a229eb22f..000000000 --- a/thunar-vfs/thunar-vfs-mime-cache.h +++ /dev/null @@ -1,44 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_MIME_CACHE_H__ -#define __THUNAR_VFS_MIME_CACHE_H__ - -#include <thunar-vfs/thunar-vfs-mime-provider.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsMimeCacheClass ThunarVfsMimeCacheClass; -typedef struct _ThunarVfsMimeCache ThunarVfsMimeCache; - -#define THUNAR_VFS_TYPE_MIME_CACHE (thunar_vfs_mime_cache_get_type ()) -#define THUNAR_VFS_MIME_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_MIME_CACHE, ThunarVfsMimeCache)) -#define THUNAR_VFS_MIME_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_MIME_CACHE, ThunarVfsMimeCacheClass)) -#define THUNAR_VFS_IS_MIME_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_MIME_CACHE)) -#define THUNAR_VFS_IS_MIME_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_MIME_CACHE)) -#define THUNAR_VFS_MIME_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_MIME_CACHE, ThunarVfsMimeCacheClass)) - -GType thunar_vfs_mime_cache_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - -ThunarVfsMimeProvider *thunar_vfs_mime_cache_new (const gchar *directory) G_GNUC_INTERNAL G_GNUC_MALLOC; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_CACHE_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-cleaner.c b/thunar-vfs/thunar-vfs-mime-cleaner.c deleted file mode 100644 index e7d76e3f5..000000000 --- a/thunar-vfs/thunar-vfs-mime-cleaner.c +++ /dev/null @@ -1,491 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * 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., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/******************************************************************************** - * WHAT IS THIS? * - * * - * thunar-vfs-mime-cleaner is a small utility program, used to cleanup the * - * $XDG_DATA_HOME/applications/ folder, in which both Thunar and Nautilus * - * create <app>-usercreated.desktop files when the user enters a custom * - * command to open a file. These .desktop files aren't removed by the package * - * manager when the associated applications are removed, so we do this manu- * - * ally using this simple tool. * - * * - * In addition, the defaults.list file will be cleaned and references to dead * - * desktop-ids will be removed from the list. * - ********************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_REGEX_H -#include <regex.h> -#endif -#include <stdio.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <glib/gstdio.h> -#include <libxfce4util/libxfce4util.h> - - - -static gboolean -check_exec (const gchar *exec) -{ - gboolean result = TRUE; - gchar *command; - gchar **argv; - - /* exec = NULL is invalid */ - if (G_UNLIKELY (exec == NULL)) - return FALSE; - - /* try to parse the "Exec" line */ - if (g_shell_parse_argv (exec, NULL, &argv, NULL)) - { - /* check if argv[0] is an absolute path to an existing file */ - result = (g_path_is_absolute (argv[0]) && g_file_test (argv[0], G_FILE_TEST_EXISTS)); - - /* otherwise, argv[0] must be a program in $PATH */ - if (G_LIKELY (!result)) - { - /* search in $PATH for argv[0] */ - command = g_find_program_in_path (argv[0]); - result = (command != NULL); - g_free (command); - } - - /* release the argv */ - g_strfreev (argv); - } - - return result; -} - - - -static GHashTable* -load_defaults_list (const gchar *directory) -{ - const gchar *type; - const gchar *ids; - GHashTable *defaults_list; - gchar **id_list; - gchar line[2048]; - gchar *path; - gchar *lp; - FILE *fp; - gint n; - gint m; - - /* allocate a new hash table for the defaults.list */ - defaults_list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_strfreev); - - /* determine the path to the defaults.list */ - path = g_build_filename (directory, "defaults.list", NULL); - - /* try to open the defaults.list file */ - fp = fopen (path, "r"); - if (G_LIKELY (fp != NULL)) - { - /* process the file */ - while (fgets (line, sizeof (line), fp) != NULL) - { - /* skip everything that doesn't look like a mime type line */ - for (lp = line; g_ascii_isspace (*lp); ++lp) ; - if (G_UNLIKELY (*lp < 'a' || *lp > 'z')) - continue; - - /* lookup the '=' */ - for (type = lp++; *lp != '\0' && *lp != '='; ++lp) ; - if (G_UNLIKELY (*lp != '=')) - continue; - *lp++ = '\0'; - - /* extract the application id list */ - for (ids = lp; g_ascii_isgraph (*lp); ++lp) ; - if (G_UNLIKELY (ids == lp)) - continue; - *lp = '\0'; - - /* parse the id list */ - id_list = g_strsplit (ids, ";", -1); - for (m = n = 0; id_list[m] != NULL; ++m) - { - if (G_UNLIKELY (id_list[m][0] == '\0')) - g_free (id_list[m]); - else - id_list[n++] = id_list[m]; - } - id_list[n] = NULL; - - /* verify that the id list is not empty */ - if (G_UNLIKELY (id_list[0] == NULL)) - { - g_free (id_list); - continue; - } - - /* insert the line into the hash table */ - g_hash_table_insert (defaults_list, g_strdup (type), id_list); - } - - /* close the file */ - fclose (fp); - } - - /* cleanup */ - g_free (path); - - return defaults_list; -} - - - -static gboolean -check_desktop_id (const gchar *id) -{ - GKeyFile *key_file; - gboolean result; - gchar *path; - - /* check if we can load a .desktop file for the given desktop-id */ - key_file = g_key_file_new (); - path = g_build_filename ("applications", id, NULL); - result = g_key_file_load_from_data_dirs (key_file, path, NULL, G_KEY_FILE_NONE, NULL); - g_key_file_free (key_file); - g_free (path); - - return result; -} - - - -typedef struct -{ - GHashTable *replacements; - FILE *fp; -} SaveDescriptor; - - - -static void -save_defaults_list_one (const gchar *type, - gchar **ids, - SaveDescriptor *save_descriptor) -{ - const gchar *replacement_id; - gint i, j, k; - - /* perform the required transformations on the id list */ - for (i = j = 0; ids[i] != NULL; ++i) - { - /* check if we have a replacement for this id */ - replacement_id = g_hash_table_lookup (save_descriptor->replacements, ids[i]); - if (G_UNLIKELY (replacement_id != NULL)) - { - g_free (ids[i]); - ids[i] = g_strdup (replacement_id); - } - - /* check if this id was already present on the list */ - for (k = 0; k < j; ++k) - if (strcmp (ids[k], ids[i]) == 0) - break; - - /* we don't need to keep it, if it was already present */ - if (G_UNLIKELY (k < j)) - { - g_free (ids[i]); - } - else if (!check_desktop_id (ids[i])) - { - /* we also don't keep references to dead desktop-ids around */ - g_free (ids[i]); - } - else - { - /* keep it around */ - ids[j++] = ids[i]; - } - } - - /* null-terminate the list */ - ids[j] = NULL; - - /* no need to store an empty list */ - if (G_LIKELY (ids[0] != NULL)) - { - fprintf (save_descriptor->fp, "%s=%s", type, ids[0]); - for (i = 1; ids[i] != NULL; ++i) - fprintf (save_descriptor->fp, ";%s", ids[i]); - fprintf (save_descriptor->fp, "\n"); - } -} - - - -static void -save_defaults_list (const gchar *directory, - GHashTable *defaults_list, - GHashTable *replacements) -{ - SaveDescriptor save_descriptor; - gchar *defaults_list_path; - gchar *path; - FILE *fp; - gint fd; - - /* determine the path to the defaults.list */ - defaults_list_path = g_build_filename (directory, "defaults.list", NULL); - - /* write the default applications list to a temporary file */ - path = g_strdup_printf ("%s.XXXXXX", defaults_list_path); - fd = g_mkstemp (path); - if (G_LIKELY (fd >= 0)) - { - /* wrap the descriptor in a file pointer */ - fp = fdopen (fd, "w"); - - /* initialize the save descriptor */ - save_descriptor.replacements = replacements; - save_descriptor.fp = fp; - - /* write the default application list content */ - fprintf (fp, "[Default Applications]\n"); - g_hash_table_foreach (defaults_list, (GHFunc) save_defaults_list_one, &save_descriptor); - fclose (fp); - - /* try to atomically rename the file */ - if (G_UNLIKELY (g_rename (path, defaults_list_path) < 0)) - { - /* tell the user that we failed */ - fprintf (stderr, "thunar-vfs-mime-cleaner: Failed to write defaults.list: %s\n", g_strerror (errno)); - - /* be sure to remove the temporary file */ - g_unlink (path); - } - } - - /* cleanup */ - g_free (defaults_list_path); - g_free (path); -} - - - -int -main (int argc, char **argv) -{ - const gchar *other_name; - const gchar *exec; - const gchar *name; - const gchar *mt1; - const gchar *mt2; - GHashTable *defaults_list; - GHashTable *replacements; - GHashTable *usercreated; - regex_t regex; - XfceRc *other_rc; - XfceRc *rc; - GError *error = NULL; - gchar *directory; - gchar *command; - gchar *mt; - GList *obsolete = NULL; - GList *lp; - GDir *dp; - - /* determine the $XDG_DATA_HOME/applications directory */ - directory = xfce_resource_save_location (XFCE_RESOURCE_DATA, "applications/", TRUE); - if (G_UNLIKELY (directory == NULL)) - { - fprintf (stderr, "thunar-vfs-mime-cleaner: Failed to determine the user's applications directory.\n"); - return EXIT_FAILURE; - } - - /* verify that we can enter that directory */ - if (G_UNLIKELY (chdir (directory) < 0)) - { - fprintf (stderr, "thunar-vfs-mime-cleaner: Failed to enter directory %s: %s\n", directory, g_strerror (errno)); - return EXIT_FAILURE; - } - - /* compile the regular expression to match usercreated .desktop files */ - if (regcomp (®ex, "^.*-usercreated(-[0-9]+)?\\.desktop", REG_EXTENDED) < 0) - { - fprintf (stderr, "thunar-vfs-mime-cleaner: Failed to compile regular expression: %s\n", g_strerror (errno)); - return EXIT_FAILURE; - } - - /* try to open the new current directory */ - dp = g_dir_open (".", 0, &error); - if (G_UNLIKELY (dp == NULL)) - { - fprintf (stderr, "thunar-vfs-mime-cleaner: Failed to open directory %s: %s\n", directory, error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - /* load the defaults.list file */ - defaults_list = load_defaults_list (directory); - - /* allocate a hash table used to combine the <app>-usercreated.desktop files */ - usercreated = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - /* allocate a hash table for the replacements (old.desktop -> new.desktop) */ - replacements = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - /* process the directory contents, collecting obsolete files */ - for (;;) - { - /* determine the next file name */ - name = g_dir_read_name (dp); - if (G_UNLIKELY (name == NULL)) - break; - - /* check if the file name matches */ - if (regexec (®ex, name, 0, NULL, 0) != 0) - continue; - - /* try to open that file */ - rc = xfce_rc_simple_open (name, TRUE); - if (G_UNLIKELY (rc == NULL)) - continue; - - /* we care only for the [Desktop Entry] group */ - xfce_rc_set_group (rc, "Desktop Entry"); - - /* determine the "Exec" value */ - exec = xfce_rc_read_entry_untranslated (rc, "Exec", NULL); - if (G_LIKELY (!check_exec (exec))) - { - /* this one is obsolete */ - obsolete = g_list_append (obsolete, g_strdup (name)); - } - else if (G_LIKELY (exec != NULL)) - { - /* check if already present in the usercreated hash table */ - other_name = g_hash_table_lookup (usercreated, exec); - other_rc = (other_name != NULL) ? xfce_rc_simple_open (other_name, FALSE) : NULL; - if (G_UNLIKELY (other_rc != NULL)) - { - /* two files with the same "Exec" line, we can combine them by merging the MimeType */ - mt1 = xfce_rc_read_entry_untranslated (other_rc, "MimeType", NULL); - mt2 = xfce_rc_read_entry_untranslated (rc, "MimeType", NULL); - - /* combine the MimeTypes to a single list */ - if (G_LIKELY (mt1 != NULL && mt1[strlen (mt1) - 1] == ';')) - mt = g_strconcat (mt1, mt2, NULL); - else if (G_LIKELY (mt1 != NULL)) - mt = g_strconcat (mt1, ";", mt2, NULL); - else - mt = g_strdup (mt2); - - /* store the new entry (if any) to the other file */ - if (G_LIKELY (mt != NULL)) - { - xfce_rc_write_entry (other_rc, "MimeType", mt); - g_free (mt); - } - - /* remember the replacement for later */ - g_hash_table_insert (replacements, g_strdup (name), g_strdup (other_name)); - - /* no need to keep the new file around, now that we merged the stuff */ - if (g_unlink (name) < 0 && errno != ENOENT) - fprintf (stderr, "thunar-vfs-mime-cleaner: Failed to unlink %s: %s\n", name, g_strerror (errno)); - - /* close the other rc file */ - xfce_rc_close (other_rc); - } - else - { - /* just add this one to the usercreated hash table */ - g_hash_table_insert (usercreated, g_strdup (exec), g_strdup (name)); - } - } - - /* close the file */ - xfce_rc_close (rc); - } - - /* write a defaults.list, replacing merged desktop-ids and dropping dead ones */ - save_defaults_list (directory, defaults_list, replacements); - - /* release the regular expression */ - regfree (®ex); - - /* close the directory handle */ - g_dir_close (dp); - - /* check if we have any obsolete files */ - if (G_UNLIKELY (obsolete != NULL)) - { - /* remove all obsolete files from the directory */ - for (lp = obsolete; lp != NULL; lp = lp->next) - { - /* try to remove the file */ - if (G_UNLIKELY (g_unlink (lp->data) < 0 && errno != ENOENT)) - { - fprintf (stderr, "thunar-vfs-mime-cleaner: Failed to unlink %s: %s\n", (gchar *) lp->data, g_strerror (errno)); - return EXIT_FAILURE; - } - g_free (lp->data); - } - g_list_free (obsolete); - - /* run update-desktop-database on the applications folder */ - command = g_strdup_printf ("update-desktop-database %s", directory); - if (!g_spawn_command_line_sync (command, NULL, NULL, NULL, &error)) - { - fprintf (stderr, "thunar-vfs-mime-cleaner: Failed to execute %s: %s\n", command, error->message); - g_error_free (error); - return EXIT_FAILURE; - } - g_free (command); - } - - /* cleanup */ - g_hash_table_destroy (defaults_list); - g_hash_table_destroy (replacements); - g_hash_table_destroy (usercreated); - g_free (directory); - - return EXIT_SUCCESS; -} diff --git a/thunar-vfs/thunar-vfs-mime-database-private.h b/thunar-vfs/thunar-vfs-mime-database-private.h deleted file mode 100644 index ebb4619fc..000000000 --- a/thunar-vfs/thunar-vfs-mime-database-private.h +++ /dev/null @@ -1,42 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_MIME_DATABASE_PRIVATE_H__ -#define __THUNAR_VFS_MIME_DATABASE_PRIVATE_H__ - -#include <thunar-vfs/thunar-vfs-mime-database.h> - -G_BEGIN_DECLS; - -/* shared mime database and mime infos */ -extern ThunarVfsMimeDatabase *_thunar_vfs_mime_database G_GNUC_INTERNAL; -extern ThunarVfsMimeInfo *_thunar_vfs_mime_inode_directory G_GNUC_INTERNAL; -extern ThunarVfsMimeInfo *_thunar_vfs_mime_application_x_desktop G_GNUC_INTERNAL; -extern ThunarVfsMimeInfo *_thunar_vfs_mime_application_x_executable G_GNUC_INTERNAL; -extern ThunarVfsMimeInfo *_thunar_vfs_mime_application_x_shellscript G_GNUC_INTERNAL; -extern ThunarVfsMimeInfo *_thunar_vfs_mime_application_octet_stream G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_DATABASE_PRIVATE_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-database.c b/thunar-vfs/thunar-vfs-mime-database.c deleted file mode 100644 index 86a9c5823..000000000 --- a/thunar-vfs/thunar-vfs-mime-database.c +++ /dev/null @@ -1,1839 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Based on code initially written by Matthias Clasen <mclasen@redhat.com> - * for the xdgmime library. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_EXTATTR_H -#include <sys/extattr.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef HAVE_SYS_XATTR_H -#include <sys/xattr.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#include <stdio.h> -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-mime-cache.h> -#include <thunar-vfs/thunar-vfs-mime-database-private.h> -#include <thunar-vfs/thunar-vfs-mime-legacy.h> -#include <thunar-vfs/thunar-vfs-mime-sniffer.h> -#include <thunar-vfs/thunar-vfs-monitor-private.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* use g_open(), g_rename() and g_unlink() on win32 */ -#if GLIB_CHECK_VERSION(2,6,0) && defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_open(path, flags, mode) (open ((path), (flags), (mode))) -#define g_rename(oldfilename, newfilename) (rename ((oldfilename), (newfilename))) -#define g_unlink(path) (unlink ((path))) -#endif - - - -/* the interval in which thunar-vfs-mime-cleaner is invoked (in ms) */ -#define THUNAR_VFS_MIME_DATABASE_CLEANUP_INTERVAL (5 * 60 * 1000) - - - -typedef struct _ThunarVfsMimeDesktopStore ThunarVfsMimeDesktopStore; -typedef struct _ThunarVfsMimeProviderData ThunarVfsMimeProviderData; - - - -#define THUNAR_VFS_MIME_DESKTOP_STORE(store) ((ThunarVfsMimeDesktopStore *) (store)) -#define THUNAR_VFS_MIME_PROVIDER_DATA(data) ((ThunarVfsMimeProviderData *) (data)) - - - -static void thunar_vfs_mime_database_class_init (ThunarVfsMimeDatabaseClass *klass); -static void thunar_vfs_mime_database_init (ThunarVfsMimeDatabase *database); -static void thunar_vfs_mime_database_finalize (GObject *object); -static ThunarVfsMimeApplication *thunar_vfs_mime_database_get_application_locked (ThunarVfsMimeDatabase *database, - const gchar *desktop_id); -static ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_locked (ThunarVfsMimeDatabase *database, - const gchar *mime_type); -static ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_for_data_locked (ThunarVfsMimeDatabase *database, - gconstpointer data, - gsize length); -static ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_for_name_locked (ThunarVfsMimeDatabase *database, - const gchar *name); -static GList *thunar_vfs_mime_database_get_infos_for_info_locked (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info); -static void thunar_vfs_mime_database_initialize_providers (ThunarVfsMimeDatabase *database); -static void thunar_vfs_mime_database_shutdown_providers (ThunarVfsMimeDatabase *database); -static void thunar_vfs_mime_database_initialize_stores (ThunarVfsMimeDatabase *database); -static void thunar_vfs_mime_database_shutdown_stores (ThunarVfsMimeDatabase *database); -static void thunar_vfs_mime_database_store_changed (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data); -static void thunar_vfs_mime_database_store_parse_file (ThunarVfsMimeDatabase *database, - ThunarVfsPath *path, - GHashTable *table); -static gboolean thunar_vfs_mime_database_icon_theme_changed (GSignalInvocationHint *ihint, - guint n_param_values, - const GValue *param_values, - gpointer user_data); -static gboolean thunar_vfs_mime_database_cleanup_timer (gpointer user_data); -static void thunar_vfs_mime_database_cleanup_timer_destroy (gpointer user_data); - - - -struct _ThunarVfsMimeDatabaseClass -{ - GObjectClass __parent__; -}; - -struct _ThunarVfsMimeDatabase -{ - GObject __parent__; - - GMutex *lock; - - /* GtkIconTheme changed hook id */ - gulong changed_hook_id; - - /* mime detection support */ - GHashTable *infos; - GList *providers; - gsize max_buffer_extents; - gchar *stopchars; - - /* commonly used mime types */ - ThunarVfsMimeInfo *application_octet_stream; - ThunarVfsMimeInfo *text_plain; - - /* mime applications support */ - ThunarVfsMimeDesktopStore *stores; - guint n_stores; - GHashTable *applications; - - /* the thunar-vfs-mime-cleaner timer id */ - gint cleanup_timer_id; -}; - -struct _ThunarVfsMimeDesktopStore -{ - ThunarVfsMonitorHandle *defaults_list_handle; - GHashTable *defaults_list; - ThunarVfsMonitorHandle *mimeinfo_cache_handle; - GHashTable *mimeinfo_cache; -}; - -struct _ThunarVfsMimeProviderData -{ - ThunarVfsPath *path; - ThunarVfsMimeProvider *provider; -}; - - - -static GObjectClass *thunar_vfs_mime_database_parent_class; - - - -GType -thunar_vfs_mime_database_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsMimeDatabase", - sizeof (ThunarVfsMimeDatabaseClass), - thunar_vfs_mime_database_class_init, - sizeof (ThunarVfsMimeDatabase), - thunar_vfs_mime_database_init, - 0); - } - - return type; -} - - - -static void -thunar_vfs_mime_database_class_init (ThunarVfsMimeDatabaseClass *klass) -{ - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_mime_database_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_mime_database_finalize; -} - - - -static void -thunar_vfs_mime_database_init (ThunarVfsMimeDatabase *database) -{ - gpointer klass; - - /* create the lock for this object */ - database->lock = g_mutex_new (); - - /* allocate the hash table for the mime infos */ - database->infos = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) thunar_vfs_mime_info_unref); - - /* grab references on commonly used mime infos */ - database->application_octet_stream = thunar_vfs_mime_database_get_info_locked (database, "application/octet-stream"); - database->text_plain = thunar_vfs_mime_database_get_info_locked (database, "text/plain"); - - /* allocate the applications cache */ - database->applications = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); - - /* initialize the MIME providers */ - thunar_vfs_mime_database_initialize_providers (database); - - /* connect emission hook for the "changed" signal on the GtkIconTheme class. We use the emission - * hook to reset the icon names of all mime infos at once. - */ - klass = g_type_class_ref (GTK_TYPE_ICON_THEME); - database->changed_hook_id = g_signal_add_emission_hook (g_signal_lookup ("changed", GTK_TYPE_ICON_THEME), - 0, thunar_vfs_mime_database_icon_theme_changed, - database, NULL); - g_type_class_unref (klass); -} - - - -static void -thunar_vfs_mime_database_finalize (GObject *object) -{ - ThunarVfsMimeDatabase *database = THUNAR_VFS_MIME_DATABASE (object); - - /* cancel any pending cleanup timer */ - if (G_LIKELY (database->cleanup_timer_id > 0)) - g_source_remove (database->cleanup_timer_id); - - /* remove the "changed" emission hook from the GtkIconTheme class */ - g_signal_remove_emission_hook (g_signal_lookup ("changed", GTK_TYPE_ICON_THEME), database->changed_hook_id); - - /* shutdown the MIME desktop stores (if initialized) */ - if (G_LIKELY (database->stores != NULL)) - thunar_vfs_mime_database_shutdown_stores (database); - - /* release the MIME providers */ - thunar_vfs_mime_database_shutdown_providers (database); - - /* free all cached applications */ - g_hash_table_destroy (database->applications); - - /* free commonly used mime infos */ - thunar_vfs_mime_info_unref (database->application_octet_stream); - thunar_vfs_mime_info_unref (database->text_plain); - - /* free all mime infos */ - g_hash_table_destroy (database->infos); - - /* release the mutex for this object */ - g_mutex_free (database->lock); - - /* call the parent's finalize method */ - (*G_OBJECT_CLASS (thunar_vfs_mime_database_parent_class)->finalize) (object); -} - - - -static ThunarVfsMimeApplication* -thunar_vfs_mime_database_get_application_locked (ThunarVfsMimeDatabase *database, - const gchar *desktop_id) -{ - ThunarVfsMimeApplication *application; - - /* check if we have that application cached */ - application = g_hash_table_lookup (database->applications, desktop_id); - if (G_UNLIKELY (application == NULL)) - { - /* try to load the application from disk */ - application = thunar_vfs_mime_application_new_from_desktop_id (desktop_id); - if (G_LIKELY (application != NULL)) - { - /* add the application to the cache (we don't take a copy of the desktop-id here) */ - g_hash_table_insert (database->applications, (gchar *) thunar_vfs_mime_application_get_desktop_id (application), application); - } - } - - /* take an additional reference for the caller */ - if (G_LIKELY (application != NULL)) - g_object_ref (G_OBJECT (application)); - - return application; -} - - - -static ThunarVfsMimeInfo* -thunar_vfs_mime_database_get_info_locked (ThunarVfsMimeDatabase *database, - const gchar *mime_type) -{ - ThunarVfsMimeProvider *provider; - ThunarVfsMimeInfo *info; - const gchar *p; - GList *lp; - guint n; - - /* unalias the mime type */ - for (lp = database->providers; lp != NULL; lp = lp->next) - { - provider = THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider; - if (G_LIKELY (provider != NULL)) - { - p = thunar_vfs_mime_provider_lookup_alias (provider, mime_type); - if (G_UNLIKELY (p != NULL && strcmp (mime_type, p) != 0)) - { - mime_type = p; - break; - } - } - } - - /* check if we have a cached version of the mime type */ - info = g_hash_table_lookup (database->infos, mime_type); - if (G_UNLIKELY (info == NULL)) - { - /* count the number of slashes in the mime_type */ - for (n = 0, p = mime_type; *p != '\0'; ++p) - if (G_UNLIKELY (*p == '/')) - ++n; - - /* fallback to 'application/octet-stream' if the type is invalid */ - if (G_UNLIKELY (n != 1)) - return thunar_vfs_mime_info_ref (database->application_octet_stream); - - /* allocate the MIME info instance */ - info = thunar_vfs_mime_info_new (mime_type, (p - mime_type)); - - /* insert the mime type into the cache (w/o taking a copy on the name) */ - g_hash_table_insert (database->infos, (gpointer) thunar_vfs_mime_info_get_name (info), info); - } - - /* take a reference for the caller */ - return thunar_vfs_mime_info_ref (info); -} - - - -static ThunarVfsMimeInfo* -thunar_vfs_mime_database_get_info_for_data_locked (ThunarVfsMimeDatabase *database, - gconstpointer data, - gsize length) -{ - ThunarVfsMimeProvider *provider; - ThunarVfsMimeInfo *info = NULL; - const gchar *type_best; - const gchar *type; - GList *lp; - gint prio_best; - gint prio; - - if (G_UNLIKELY (length == 0)) - { - /* empty files are considered to be textfiles, so - * newly created (empty) files can be opened in - * a text editor. - */ - info = thunar_vfs_mime_info_ref (database->text_plain); - } - else - { - /* perform a 'best fit' lookup on all active providers */ - for (type_best = NULL, prio_best = -1, lp = database->providers; lp != NULL; lp = lp->next) - { - provider = THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider; - if (G_LIKELY (provider != NULL)) - { - type = thunar_vfs_mime_provider_lookup_data (provider, data, length, &prio); - if (G_LIKELY (type != NULL && prio > prio_best)) - { - prio_best = prio; - type_best = type; - } - } - } - - if (G_LIKELY (type_best != NULL)) - { - /* lookup the info for the best type (if any) */ - info = thunar_vfs_mime_database_get_info_locked (database, type_best); - } - else if (thunar_vfs_mime_sniffer_looks_like_text (data, length)) - { - /* we have valid UTF-8 text here! */ - info = thunar_vfs_mime_info_ref (database->text_plain); - } - } - - return info; -} - - - -static ThunarVfsMimeInfo* -thunar_vfs_mime_database_get_info_for_name_locked (ThunarVfsMimeDatabase *database, - const gchar *name) -{ - ThunarVfsMimeProvider *provider; - const gchar *type = NULL; - const gchar *ptr; - GList *lp; - - /* try the literals first */ - for (lp = database->providers; lp != NULL && type == NULL; lp = lp->next) - { - provider = THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider; - if (G_LIKELY (provider != NULL)) - type = thunar_vfs_mime_provider_lookup_literal (provider, name); - } - - /* next the suffixes */ - if (G_LIKELY (type == NULL)) - { - ptr = strpbrk (name, database->stopchars); - while (ptr != NULL) - { - /* case-sensitive first */ - for (lp = database->providers; lp != NULL && type == NULL; lp = lp->next) - { - provider = THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider; - if (G_LIKELY (provider != NULL)) - type = thunar_vfs_mime_provider_lookup_suffix (provider, ptr, FALSE); - } - - /* case-insensitive next */ - if (G_UNLIKELY (type == NULL)) - { - for (lp = database->providers; lp != NULL && type == NULL; lp = lp->next) - { - provider = THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider; - if (G_LIKELY (provider != NULL)) - type = thunar_vfs_mime_provider_lookup_suffix (provider, ptr, TRUE); - } - } - - /* check if we got a type */ - if (G_LIKELY (type != NULL)) - break; - - ptr = strpbrk (ptr + 1, database->stopchars); - } - } - - /* the glob match comes last */ - if (G_UNLIKELY (type == NULL)) - { - for (lp = database->providers; lp != NULL && type == NULL; lp = lp->next) - { - provider = THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider; - if (G_LIKELY (provider != NULL)) - type = thunar_vfs_mime_provider_lookup_glob (provider, name); - } - } - - return (type != NULL) ? thunar_vfs_mime_database_get_info_locked (database, type) : NULL; -} - - - -static GList* -thunar_vfs_mime_database_get_infos_for_info_locked (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info) -{ - ThunarVfsMimeProvider *provider; - ThunarVfsMimeInfo *parent_info; - const gchar *name = thunar_vfs_mime_info_get_name (info); - gchar *parents[128]; - GList *infos; - GList *lp; - guint n, m; - - /* the info itself is of course on the list */ - infos = g_list_prepend (NULL, thunar_vfs_mime_info_ref (info)); - - /* lookup all parents on every provider */ - for (lp = database->providers; lp != NULL; lp = lp->next) - { - provider = THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider; - if (G_LIKELY (provider != NULL)) - { - /* ask this provider for the parents list */ - n = thunar_vfs_mime_provider_lookup_parents (provider, name, parents, G_N_ELEMENTS (parents)); - if (G_UNLIKELY (n == 0)) - continue; - - /* process the parents */ - for (m = 0; m < n; ++m) - { - /* append the type if we don't have it already */ - parent_info = thunar_vfs_mime_database_get_info_locked (database, parents[m]); - if (G_LIKELY (g_list_find (infos, parent_info) == NULL)) - infos = g_list_append (infos, parent_info); - else - thunar_vfs_mime_info_unref (parent_info); - } - } - } - - /* all text/xxxx types are subtype of text/plain */ - if (G_UNLIKELY (strncmp ("text/", thunar_vfs_mime_info_get_name (info), 5) == 0)) - { - /* append text/plain if we don't have it already */ - if (g_list_find (infos, database->text_plain) == NULL) - infos = g_list_append (infos, thunar_vfs_mime_info_ref (database->text_plain)); - } - - /* everything is subtype of application/octet-stream */ - if (g_list_find (infos, database->application_octet_stream) == NULL) - infos = g_list_append (infos, thunar_vfs_mime_info_ref (database->application_octet_stream)); - - return infos; -} - - - -static void -thunar_vfs_mime_database_initialize_providers (ThunarVfsMimeDatabase *database) -{ - ThunarVfsMimeProviderData *data; - const gchar *s; - GList *stopchars = NULL; - GList *lp; - gchar *directory; - gchar **basedirs; - gchar *p; - gchar c; - gint n; - - /* process all "mime" directories */ - basedirs = xfce_resource_dirs (XFCE_RESOURCE_DATA); - for (n = 0; basedirs[n] != NULL; ++n) - { - /* determine the path for the MIME directory */ - directory = g_build_filename (basedirs[n], "mime", NULL); - - /* allocate the provider data for the directory */ - data = _thunar_vfs_slice_new (ThunarVfsMimeProviderData); - data->path = thunar_vfs_path_new (directory, NULL); - - /* try to allocate a provider for the directory */ - data->provider = thunar_vfs_mime_cache_new (directory); - if (G_UNLIKELY (data->provider == NULL)) - data->provider = thunar_vfs_mime_legacy_new (directory); - - /* add the provider to our list */ - database->providers = g_list_append (database->providers, data); - - /* collect the stopchars for this provider */ - if (G_LIKELY (data->provider != NULL)) - stopchars = g_list_concat (stopchars, thunar_vfs_mime_provider_get_stop_characters (data->provider)); - - /* collect the max buffer extents for this provider */ - if (G_LIKELY (data->provider != NULL)) - database->max_buffer_extents = MAX (database->max_buffer_extents, thunar_vfs_mime_provider_get_max_buffer_extents (data->provider)); - - /* cleanup */ - g_free (directory); - } - g_strfreev (basedirs); - - /* clamp the max buffer extents to [64..256] to make - * sure we don't try insane values (everything below - * 64 bytes would be useless for the UTF-8 check). - */ - database->max_buffer_extents = CLAMP (database->max_buffer_extents, 64, 256); - - /* collect the stop characters */ - database->stopchars = g_new (gchar, g_list_length (stopchars) + 1); - for (lp = stopchars, p = database->stopchars; lp != NULL; lp = lp->next) - { - /* check if we have that character already */ - c = (gchar) GPOINTER_TO_UINT (lp->data); - for (s = database->stopchars; s < p; ++s) - if (G_UNLIKELY (*s == c)) - break; - - /* insert the stopchar */ - if (G_LIKELY (s == p)) - *p++ = c; - } - g_list_free (stopchars); - *p = '\0'; -} - - - -static void -thunar_vfs_mime_database_shutdown_providers (ThunarVfsMimeDatabase *database) -{ - GList *lp; - - /* free the providers */ - for (lp = database->providers; lp != NULL; lp = lp->next) - { - if (G_LIKELY (THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider != NULL)) - g_object_unref (THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->provider); - thunar_vfs_path_unref (THUNAR_VFS_MIME_PROVIDER_DATA (lp->data)->path); - _thunar_vfs_slice_free (ThunarVfsMimeProviderData, lp->data); - } - g_list_free (database->providers); - - /* free the stopchars */ - g_free (database->stopchars); -} - - - -static void -thunar_vfs_mime_database_initialize_stores (ThunarVfsMimeDatabase *database) -{ - ThunarVfsMimeDesktopStore *store; - ThunarVfsPath *base_path; - ThunarVfsPath *path; - gchar **basedirs; - guint n; - - /* count all base data directories (with possible "applications" subdirs) */ - basedirs = xfce_resource_dirs (XFCE_RESOURCE_DATA); - for (n = 0; basedirs[n] != NULL; ++n) - ; - - /* allocate memory for the stores */ - database->n_stores = n; - database->stores = g_new (ThunarVfsMimeDesktopStore, n); - - /* initialize the stores */ - for (n = 0, store = database->stores; basedirs[n] != NULL; ++n, ++store) - { - /* determine the base path */ - path = thunar_vfs_path_new (basedirs[n], NULL); - base_path = _thunar_vfs_path_child (path, "applications"); - _thunar_vfs_path_unref_nofree (path); - - /* setup the defaults.list */ - path = _thunar_vfs_path_child (base_path, "defaults.list"); - store->defaults_list = g_hash_table_new_full (thunar_vfs_mime_info_hash, - thunar_vfs_mime_info_equal, - (GDestroyNotify) thunar_vfs_mime_info_unref, - (GDestroyNotify) g_strfreev); - store->defaults_list_handle = thunar_vfs_monitor_add_file (_thunar_vfs_monitor, path, thunar_vfs_mime_database_store_changed, database); - thunar_vfs_mime_database_store_parse_file (database, path, store->defaults_list); - _thunar_vfs_path_unref_nofree (path); - - /* setup the mimeinfo.cache */ - path = _thunar_vfs_path_child (base_path, "mimeinfo.cache"); - store->mimeinfo_cache = g_hash_table_new_full (thunar_vfs_mime_info_hash, - thunar_vfs_mime_info_equal, - (GDestroyNotify) thunar_vfs_mime_info_unref, - (GDestroyNotify) g_strfreev); - store->mimeinfo_cache_handle = thunar_vfs_monitor_add_file (_thunar_vfs_monitor, path, thunar_vfs_mime_database_store_changed, database); - thunar_vfs_mime_database_store_parse_file (database, path, store->mimeinfo_cache); - _thunar_vfs_path_unref_nofree (path); - - /* release the base path */ - _thunar_vfs_path_unref_nofree (base_path); - } - g_strfreev (basedirs); - - /* launch the clean up timer if it's not already running */ - if (G_LIKELY (database->cleanup_timer_id == 0)) - { - /* start the timer, which invokes thunar-vfs-mime-cleaner from time to time to cleanup the - * user's mime database directories, so we don't keep old junk around for too long. - */ - database->cleanup_timer_id = g_timeout_add_full (G_PRIORITY_LOW, THUNAR_VFS_MIME_DATABASE_CLEANUP_INTERVAL, - thunar_vfs_mime_database_cleanup_timer, database, - thunar_vfs_mime_database_cleanup_timer_destroy); - } -} - - - -static void -thunar_vfs_mime_database_shutdown_stores (ThunarVfsMimeDatabase *database) -{ - ThunarVfsMimeDesktopStore *store; - guint n; - - /* release all stores */ - for (n = 0, store = database->stores; n < database->n_stores; ++n, ++store) - { - /* release the defaults.list part */ - thunar_vfs_monitor_remove (_thunar_vfs_monitor, store->defaults_list_handle); - g_hash_table_destroy (store->defaults_list); - - /* release the mimeinfo.cache part */ - thunar_vfs_monitor_remove (_thunar_vfs_monitor, store->mimeinfo_cache_handle); - g_hash_table_destroy (store->mimeinfo_cache); - } - -#ifdef G_ENABLE_DEBUG - memset (database->stores, 0xaa, database->n_stores * sizeof (*store)); -#endif - - /* free the memory allocated to the stores */ - g_free (database->stores); -} - - - -static void -thunar_vfs_mime_database_store_changed (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data) -{ - ThunarVfsMimeDesktopStore *store; - ThunarVfsMimeDatabase *database = THUNAR_VFS_MIME_DATABASE (user_data); - guint n; - - /* lookup the store that changed */ - g_mutex_lock (database->lock); - for (n = 0, store = database->stores; n < database->n_stores; ++n, ++store) - { - /* lookup a store that has this handle */ - if (store->defaults_list_handle == handle) - { - /* clear any cached values */ - g_hash_table_foreach_remove (store->defaults_list, (GHRFunc) exo_noop_true, NULL); - - /* reload the store's defaults.list */ - thunar_vfs_mime_database_store_parse_file (database, _thunar_vfs_monitor_handle_get_path (store->defaults_list_handle), store->defaults_list); - - /* and now we're done */ - break; - } - else if (store->mimeinfo_cache_handle == handle) - { - /* clear the applications cache (as running update-desktop-database usually - * means that new applications are available) - */ - g_hash_table_foreach_remove (database->applications, (GHRFunc) exo_noop_true, NULL); - - /* clear any cached values */ - g_hash_table_foreach_remove (store->mimeinfo_cache, (GHRFunc) exo_noop_true, NULL); - - /* reload the store's mimeinfo.cache */ - thunar_vfs_mime_database_store_parse_file (database, _thunar_vfs_monitor_handle_get_path (store->mimeinfo_cache_handle), store->mimeinfo_cache); - - /* and now we're done */ - break; - } - } - g_mutex_unlock (database->lock); -} - - - -static void -thunar_vfs_mime_database_store_parse_file (ThunarVfsMimeDatabase *database, - ThunarVfsPath *path, - GHashTable *table) -{ - ThunarVfsMimeInfo *info; - const gchar *type; - const gchar *ids; - gchar absolute_path[THUNAR_VFS_PATH_MAXSTRLEN]; - gchar **id_list; - gchar line[4096]; - gchar *lp; - FILE *fp; - gint n; - gint m; - - /* determine the absolute path */ - if (thunar_vfs_path_to_string (path, absolute_path, sizeof (absolute_path), NULL) < 0) - return; - - /* try to open the file */ - fp = fopen (absolute_path, "r"); - if (G_UNLIKELY (fp == NULL)) - return; - - /* process the file */ - while (fgets (line, sizeof (line), fp) != NULL) - { - /* skip everything that doesn't look like a mime type line */ - for (lp = line; g_ascii_isspace (*lp); ++lp) ; - if (G_UNLIKELY (*lp < 'a' || *lp > 'z')) - continue; - - /* lookup the '=' */ - for (type = lp++; *lp != '\0' && *lp != '='; ++lp) ; - if (G_UNLIKELY (*lp != '=')) - continue; - *lp++ = '\0'; - - /* extract the application id list */ - for (ids = lp; g_ascii_isgraph (*lp); ++lp) ; - if (G_UNLIKELY (ids == lp)) - continue; - *lp = '\0'; - - /* parse the id list */ - id_list = g_strsplit (ids, ";", -1); - for (m = n = 0; id_list[m] != NULL; ++m) - { - if (G_UNLIKELY (id_list[m][0] == '\0')) - g_free (id_list[m]); - else - id_list[n++] = id_list[m]; - } - id_list[n] = NULL; - - /* verify that the id list is not empty */ - if (G_UNLIKELY (id_list[0] == NULL)) - { - g_free (id_list); - continue; - } - - /* lookup the mime info for the type */ - info = thunar_vfs_mime_database_get_info_locked (database, type); - if (G_UNLIKELY (info == NULL)) - { - g_strfreev (id_list); - continue; - } - - /* insert the association for the desktop store */ - g_hash_table_insert (table, info, id_list); - } - - /* close the file */ - fclose (fp); -} - - - -static void -invalidate_icon_name (gpointer key, - gpointer value, - gpointer user_data) -{ - _thunar_vfs_mime_info_invalidate_icon_name (value); -} - - - -static gboolean -thunar_vfs_mime_database_icon_theme_changed (GSignalInvocationHint *ihint, - guint n_param_values, - const GValue *param_values, - gpointer user_data) -{ - ThunarVfsMimeDatabase *database = THUNAR_VFS_MIME_DATABASE (user_data); - - /* invalidate all cached icon names */ - g_mutex_lock (database->lock); - g_hash_table_foreach (database->infos, invalidate_icon_name, NULL); - g_mutex_unlock (database->lock); - - /* keep the emission hook alive */ - return TRUE; -} - - - -static gboolean -thunar_vfs_mime_database_cleanup_timer (gpointer user_data) -{ - /* invoke thunar-vfs-mime-cleaner */ - g_spawn_command_line_async (LIBEXECDIR "/thunar-vfs-mime-cleaner-" THUNAR_VFS_VERSION_API, NULL); - - /* keep the timer alive */ - return TRUE; -} - - - -static void -thunar_vfs_mime_database_cleanup_timer_destroy (gpointer user_data) -{ - THUNAR_VFS_MIME_DATABASE (user_data)->cleanup_timer_id = 0; -} - - - -/** - * thunar_vfs_mime_database_get_default: - * - * Returns a reference on the shared #ThunarVfsMimeDatabase - * instance. The caller is responsible to call g_object_unref() - * on the returned object when no longer needed. - * - * Return value: the shared #ThunarVfsMimeDatabase. - **/ -ThunarVfsMimeDatabase* -thunar_vfs_mime_database_get_default (void) -{ - return g_object_ref (G_OBJECT (_thunar_vfs_mime_database)); -} - - - -/** - * thunar_vfs_mime_database_get_info: - * @database : a #ThunarVfsMimeDatabase. - * @mime_type : the string representation of the mime type. - * - * Determines the #ThunarVfsMimeInfo which corresponds to @mime_type - * in database. The caller is responsible to call thunar_vfs_mime_info_unref() - * on the returned instance. - * - * Return value: the #ThunarVfsMimeInfo corresponding to @mime_type in @database. - **/ -ThunarVfsMimeInfo* -thunar_vfs_mime_database_get_info (ThunarVfsMimeDatabase *database, - const gchar *mime_type) -{ - ThunarVfsMimeInfo *info; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL); - g_return_val_if_fail (mime_type != NULL, NULL); - - g_mutex_lock (database->lock); - info = thunar_vfs_mime_database_get_info_locked (database, mime_type); - g_mutex_unlock (database->lock); - - return info; -} - - - -/** - * thunar_vfs_mime_database_get_info_for_data: - * @database : a #ThunarVfsMimeDatabase. - * @data : the data to check. - * @length : the length of @data in bytes. - * - * Determines the #ThunarVfsMimeInfo for @data in @database. The - * caller is responsible to call thunar_vfs_mime_info_unref() on - * the returned instance. - * - * Return value: the #ThunarVfsMimeInfo determined for @data. - **/ -ThunarVfsMimeInfo* -thunar_vfs_mime_database_get_info_for_data (ThunarVfsMimeDatabase *database, - gconstpointer data, - gsize length) -{ - ThunarVfsMimeInfo *info; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL); - - /* try to determine a MIME type based on the data */ - g_mutex_lock (database->lock); - info = thunar_vfs_mime_database_get_info_for_data_locked (database, data, length); - g_mutex_unlock (database->lock); - - /* fallback to 'application/octet-stream' if we could not determine any type */ - if (G_UNLIKELY (info == NULL)) - info = thunar_vfs_mime_info_ref (database->application_octet_stream); - - return info; -} - - - -/** - * thunar_vfs_mime_database_get_info_for_name: - * @database : a #ThunarVfsMimeDatabase. - * @name : a filename (must be valid UTF-8!). - * - * Determines the #ThunarVfsMimeInfo for the filename given - * in @name from @database. The caller is responsible to - * call thunar_vfs_mime_info_unref() on the returned instance. - * - * The @name must be a valid filename in UTF-8 encoding - * and it may not contained any slashes! - * - * Return value: the #ThunarVfsMimeInfo for @name in @database. - **/ -ThunarVfsMimeInfo* -thunar_vfs_mime_database_get_info_for_name (ThunarVfsMimeDatabase *database, - const gchar *name) -{ - ThunarVfsMimeInfo *info; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL); - g_return_val_if_fail (g_utf8_validate (name, -1, NULL), NULL); - g_return_val_if_fail (strchr (name, '/') == NULL, NULL); - g_return_val_if_fail (*name != '\0', NULL); - - /* try to determine the info from the name */ - g_mutex_lock (database->lock); - info = thunar_vfs_mime_database_get_info_for_name_locked (database, name); - g_mutex_unlock (database->lock); - - /* fallback to 'application/octet-stream' */ - if (G_UNLIKELY (info == NULL)) - info = thunar_vfs_mime_info_ref (database->application_octet_stream); - - /* we got it */ - return info; -} - - - -/** - * thunar_vfs_mime_database_get_info_for_file: - * @database : a #ThunarVfsMimeDatabase. - * @path : the path to a file in the local filesystem (in the filesystem encoding). - * @name : the basename of @path in UTF-8 encoding or %NULL. - * - * Determines the #ThunarVfsMimeInfo for @path in @database. The - * caller is responsible to free the returned instance using - * thunar_vfs_mime_info_unref(). - * - * The @name parameter is optional. If the caller already knows the - * basename of @path in UTF-8 encoding, it should be specified here - * to speed up the lookup process. - * - * Return value: the #ThunarVfsMimeInfo for @path in @database. - **/ -ThunarVfsMimeInfo* -thunar_vfs_mime_database_get_info_for_file (ThunarVfsMimeDatabase *database, - const gchar *path, - const gchar *name) -{ - ThunarVfsMimeInfo *info; - struct stat stat; - const gchar *p; - gssize nbytes; - gchar *basename; - gchar *buffer; - gchar *type; - gsize buflen; - gint fd; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL); - g_return_val_if_fail (path != NULL && *path != '\0', NULL); - g_return_val_if_fail (name == NULL || g_utf8_validate (name, -1, NULL), NULL); - - /* determine the basename in UTF-8 if not already given by the caller */ - if (G_UNLIKELY (name == NULL)) - { - buffer = g_path_get_basename (path); - name = basename = g_filename_display_name (buffer); - g_free (buffer); - } - else - { - basename = NULL; - } - - /* try to determine the type from the name first */ - g_mutex_lock (database->lock); - info = thunar_vfs_mime_database_get_info_for_name_locked (database, name); - g_mutex_unlock (database->lock); - -#ifdef HAVE_ATTROPEN - /* check if we have a valid mime type stored in the extattr (SunOS) */ - if (G_UNLIKELY (info == NULL)) - { - fd = attropen (path, "user.mime_type", O_RDONLY); - if (G_UNLIKELY (fd >= 0)) - { - if (fstat (fd, &stat) == 0) - { - buffer = g_newa (gchar, stat.st_size + 1); - nbytes = read (fd, buffer, stat.st_size); - if (G_LIKELY (nbytes >= 3)) - { - buffer[nbytes] = '\0'; - info = thunar_vfs_mime_database_get_info (database, buffer); - } - } - close (fd); - } - } -#endif - - /* try to determine the type from the file content */ - if (G_UNLIKELY (info == NULL)) - { - fd = g_open (path, O_RDONLY, 0); - if (G_LIKELY (fd >= 0)) - { -#ifdef HAVE_EXTATTR_GET_FD - /* check if we have a valid mime type stored in the extattr (TrustedBSD) */ - nbytes = extattr_get_fd (fd, EXTATTR_NAMESPACE_USER, "mime_type", NULL, 0); - if (G_UNLIKELY (nbytes >= 3)) - { - buffer = g_newa (gchar, nbytes + 1); - nbytes = extattr_get_fd (fd, EXTATTR_NAMESPACE_USER, "mime_type", buffer, nbytes); - if (G_LIKELY (nbytes >= 3)) - { - buffer[nbytes] = '\0'; - info = thunar_vfs_mime_database_get_info (database, buffer); - } - } -#elif defined(HAVE_FGETXATTR) - /* check for valid mime type stored in the extattr (Linux) */ -#if defined(__APPLE__) && defined(__MACH__) - nbytes = fgetxattr (fd, "user.mime_type", NULL, 0, 0, 0); -#else - nbytes = fgetxattr (fd, "user.mime_type", NULL, 0); -#endif - if (G_UNLIKELY (nbytes >= 3)) - { - buffer = g_newa (gchar, nbytes + 1); -#if defined(__APPLE__) && defined(__MACH__) - nbytes = fgetxattr (fd, "user.mime_type", buffer, nbytes, 0, 0); -#else - nbytes = fgetxattr (fd, "user.mime_type", buffer, nbytes); -#endif - - if (G_LIKELY (nbytes >= 3)) - { - buffer[nbytes] = '\0'; - info = thunar_vfs_mime_database_get_info (database, buffer); - } - } -#endif - - /* stat the file and verify that we have a regular file */ - if (G_LIKELY (info == NULL && fstat (fd, &stat) == 0 && S_ISREG (stat.st_mode))) - { - /* read the beginning from the file */ - buflen = MIN (stat.st_size, database->max_buffer_extents); - buffer = g_newa (gchar, buflen); - nbytes = read (fd, buffer, buflen); - - /* try to determine a type from the buffer contents */ - if (G_LIKELY (nbytes >= 0)) - { - g_mutex_lock (database->lock); - - /* the regular magic check first */ - info = thunar_vfs_mime_database_get_info_for_data_locked (database, buffer, nbytes); - - /* then if magic doesn't tell us anything and the file is marked, - * as executable, we just guess "application/x-executable", which - * is atleast more precise than "application/octet-stream". - */ - if (G_UNLIKELY (info == NULL && (stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) - info = thunar_vfs_mime_database_get_info_locked (database, "application/x-executable"); - - g_mutex_unlock (database->lock); - } - } - - /* cleanup */ - close (fd); - } - - /* if we have exactly a dot and a non-empty extension, we - * can generate a 'application/x-extension-<EXT>' on the fly - * or if no extension is found, we'll use the whole filename - * for '<EXT>'. - */ - if (G_UNLIKELY (info == NULL)) - { - /* check if the filename has an extension */ - p = strrchr (name, '.'); - if (G_UNLIKELY (p != NULL && *++p != '\0')) - { - /* use the file extension for the type */ - buffer = g_utf8_strdown (p, -1); - } - else - { - /* use the whole filename for the type as suggested by jrb */ - buffer = g_utf8_strdown (name, -1); - } - - /* generate a new mime type */ - type = g_strconcat ("application/x-extension-", buffer, NULL); - info = thunar_vfs_mime_database_get_info (database, type); - g_free (buffer); - g_free (type); - } - } - - /* cleanup */ - if (G_UNLIKELY (basename != NULL)) - g_free (basename); - - /* we got it */ - return info; -} - - - -/** - * thunar_vfs_mime_database_get_infos_for_info: - * @database : a #ThunarVfsMimeDatabase. - * @info : a #ThunarVfsMimeInfo. - * - * Returns a list of all #ThunarVfsMimeInfo<!---->s, - * that are related to @info in @database. Currently - * this is the list of parent MIME-types for @info, - * as defined in the Shared Mime Database. - * - * Note that the returned list will also include - * a reference @info itself. In addition, this - * method also handles details specified by the - * Shared Mime Database Specification like the - * fact that every "text/xxxx" MIME-type is a - * subclass of "text/plain" and every MIME-type - * is a subclass of "application/octet-stream". - * - * The caller is responsible to free the returned - * list using #thunar_vfs_mime_info_list_free() - * when done with it. - * - * Return value: the list of #ThunarVfsMimeInfo<!---->s - * related to @info. - **/ -GList* -thunar_vfs_mime_database_get_infos_for_info (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info) -{ - GList *infos; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL); - - g_mutex_lock (database->lock); - infos = thunar_vfs_mime_database_get_infos_for_info_locked (database, info); - g_mutex_unlock (database->lock); - - return infos; -} - - - -/** - * thunar_vfs_mime_database_get_applications: - * @database : a #ThunarVfsMimeDatabase. - * @info : a #ThunarVfsMimeInfo. - * - * Looks up all #ThunarVfsMimeApplication<!---->s in @database, which - * claim to be able to open files whose MIME-type is represented by - * @info. - * - * The caller is responsible to free the returned list using - * something like: - * <informalexample><programlisting> - * g_list_foreach (list, (GFunc) g_object_unref, NULL); - * g_list_free (list); - * </programlisting></informalexample> - * - * Return value: the list of #ThunarVfsMimeApplication<!---->s, that - * can handle @info. - **/ -GList* -thunar_vfs_mime_database_get_applications (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info) -{ - ThunarVfsMimeDesktopStore *store; - ThunarVfsMimeApplication *application; - const gchar *command; - const gchar **id; - GList *applications = NULL; - GList *infos; - GList *lp; - GList *p; - guint n; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL); - - g_mutex_lock (database->lock); - - /* determine the mime infos for info */ - infos = thunar_vfs_mime_database_get_infos_for_info_locked (database, info); - - /* be sure to initialize the MIME desktop stores first */ - if (G_UNLIKELY (database->stores == NULL)) - thunar_vfs_mime_database_initialize_stores (database); - - /* lookup the default applications for the infos */ - for (lp = infos; lp != NULL; lp = lp->next) - { - for (n = database->n_stores, store = database->stores; n-- > 0; ++store) - { - /* lookup the application ids */ - id = g_hash_table_lookup (store->defaults_list, lp->data); - if (G_LIKELY (id == NULL)) - continue; - - /* merge the applications */ - for (; *id != NULL; ++id) - { - /* lookup the application for the id */ - application = thunar_vfs_mime_database_get_application_locked (database, *id); - if (G_UNLIKELY (application == NULL)) - continue; - - /* check if we already have an application with an equal command - * (thanks again Nautilus for the .desktop file mess). - */ - command = thunar_vfs_mime_application_get_command (application); - for (p = applications; p != NULL; p = p->next) - if (g_str_equal (thunar_vfs_mime_application_get_command (p->data), command)) - break; - - /* merge the application */ - if (G_LIKELY (p == NULL)) - applications = g_list_append (applications, application); - else - g_object_unref (G_OBJECT (application)); - } - } - } - - /* lookup the other applications */ - for (lp = infos; lp != NULL; lp = lp->next) - { - for (n = database->n_stores, store = database->stores; n-- > 0; ++store) - { - /* lookup the application ids */ - id = g_hash_table_lookup (store->mimeinfo_cache, lp->data); - if (G_UNLIKELY (id == NULL)) - continue; - - /* merge the applications */ - for (; *id != NULL; ++id) - { - /* lookup the application for the id */ - application = thunar_vfs_mime_database_get_application_locked (database, *id); - if (G_UNLIKELY (application == NULL)) - continue; - - /* check if we already have an application with an equal command - * (thanks again Nautilus for the .desktop file mess). - */ - command = thunar_vfs_mime_application_get_command (application); - for (p = applications; p != NULL; p = p->next) - if (g_str_equal (thunar_vfs_mime_application_get_command (p->data), command)) - break; - - /* merge the application */ - if (G_LIKELY (p == NULL)) - applications = g_list_append (applications, application); - else - g_object_unref (G_OBJECT (application)); - } - } - } - - g_mutex_unlock (database->lock); - - /* free the temporary list of mime infos */ - thunar_vfs_mime_info_list_free (infos); - - return applications; -} - - - -/** - * thunar_vfs_mime_database_get_default_application: - * @database : a #ThunarVfsMimeDatabase. - * @info : a #ThunarVfsMimeInfo. - * - * Returns the default #ThunarVfsMimeApplication to handle - * files of type @info or %NULL if no default application - * is set for @info. - * - * The caller is responsible to free the returned instance - * using g_object_unref() when no longer needed. - * - * Return value: the default #ThunarVfsMimeApplication for - * @info or %NULL. - **/ -ThunarVfsMimeApplication* -thunar_vfs_mime_database_get_default_application (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info) -{ - ThunarVfsMimeDesktopStore *store; - ThunarVfsMimeApplication *application = NULL; - const gchar **id; - GList *applications; - GList *infos; - GList *lp; - guint n; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL); - - g_mutex_lock (database->lock); - - /* be sure to initialize the MIME desktop stores first */ - if (G_UNLIKELY (database->stores == NULL)) - thunar_vfs_mime_database_initialize_stores (database); - - infos = thunar_vfs_mime_database_get_infos_for_info_locked (database, info); - for (lp = infos; application == NULL && lp != NULL; lp = lp->next) - { - for (n = database->n_stores, store = database->stores; application == NULL && n-- > 0; ++store) - { - id = g_hash_table_lookup (store->defaults_list, lp->data); - if (G_LIKELY (id == NULL)) - continue; - - /* test all applications (use first match) */ - for (; application == NULL && *id != NULL; ++id) - application = thunar_vfs_mime_database_get_application_locked (database, *id); - } - } - - g_mutex_unlock (database->lock); - - /* free the temporary list of mime infos */ - thunar_vfs_mime_info_list_free (infos); - - /* if we don't have a default application set, we simply - * use the first available application here. - */ - if (G_LIKELY (application == NULL)) - { - /* query all apps for this mime type */ - applications = thunar_vfs_mime_database_get_applications (database, info); - if (G_LIKELY (applications != NULL)) - { - /* use the first available application */ - application = applications->data; - g_list_foreach (applications->next, (GFunc) g_object_unref, NULL); - g_list_free (applications); - } - } - - return application; -} - - - -static void -defaults_list_write (ThunarVfsMimeInfo *info, - gchar **ids, - FILE *fp) -{ - guint n; - - fprintf (fp, "%s=%s", thunar_vfs_mime_info_get_name (info), ids[0]); - for (n = 1; ids[n] != NULL; ++n) - fprintf (fp, ";%s", ids[n]); - fprintf (fp, "\n"); -} - - - -/** - * thunar_vfs_mime_database_set_default_application: - * @database : a #ThunarVfsMimeDatabase. - * @info : a valid #ThunarVfsMimeInfo for @database. - * @application : a #ThunarVfsMimeApplication. - * @error : return location for errors or %NULL. - * - * Sets @application to be the default #ThunarVfsMimeApplication to open files - * of type @info in @database. - * - * Return value: %TRUE if the operation was successfull, else %FALSE. - **/ -gboolean -thunar_vfs_mime_database_set_default_application (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info, - ThunarVfsMimeApplication *application, - GError **error) -{ - ThunarVfsMimeDesktopStore *store; - ThunarVfsPath *parent; - gboolean succeed = FALSE; - gchar absolute_path[THUNAR_VFS_PATH_MAXSTRLEN]; - gchar **pids; - gchar **nids; - gchar *path; - guint n, m; - FILE *fp; - gint fd; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* acquire the lock on the database */ - g_mutex_lock (database->lock); - - /* be sure to initialize the MIME desktop stores first */ - if (G_UNLIKELY (database->stores == NULL)) - thunar_vfs_mime_database_initialize_stores (database); - - /* grab the user's desktop applications store */ - store = database->stores; - - /* verify that the applications/ directory exists */ - parent = thunar_vfs_path_get_parent (_thunar_vfs_monitor_handle_get_path (store->defaults_list_handle)); - if (thunar_vfs_path_to_string (parent, absolute_path, sizeof (absolute_path), NULL) > 0) - succeed = xfce_mkdirhier (absolute_path, 0700, error); - - /* associate the application with the info */ - if (G_LIKELY (succeed)) - { - /* generate the new application id list */ - pids = g_hash_table_lookup (store->defaults_list, info); - if (G_UNLIKELY (pids == NULL)) - { - /* generate a new list that contains only the application */ - nids = g_new (gchar *, 2); - nids[0] = g_strdup (thunar_vfs_mime_application_get_desktop_id (application)); - nids[1] = NULL; - } - else - { - /* count the number of previously associated application ids */ - for (n = 0; pids[n] != NULL; ++n) - ; - - /* allocate a new list and prepend the application */ - nids = g_new (gchar *, n + 2); - nids[0] = g_strdup (thunar_vfs_mime_application_get_desktop_id (application)); - - /* append the previously associated application ids */ - for (m = 0, n = 1; pids[m] != NULL; ++m) - if (strcmp (pids[m], nids[0]) != 0) - nids[n++] = g_strdup (pids[m]); - - /* null-terminate the new application id list */ - nids[n] = NULL; - } - - /* activate the new application id list */ - g_hash_table_replace (store->defaults_list, thunar_vfs_mime_info_ref (info), nids); - - /* determine the absolute path to the defaults.list file */ - if (thunar_vfs_path_to_string (_thunar_vfs_monitor_handle_get_path (store->defaults_list_handle), absolute_path, sizeof (absolute_path), error) < 0) - { - succeed = FALSE; - goto done; - } - - /* write the default applications list to a temporary file */ - path = g_strdup_printf ("%s.XXXXXX", absolute_path); - fd = g_mkstemp (path); - if (G_LIKELY (fd >= 0)) - { - /* wrap the descriptor in a file pointer */ - fp = fdopen (fd, "w"); - - /* write the default application list content */ - fprintf (fp, "[Default Applications]\n"); - g_hash_table_foreach (store->defaults_list, (GHFunc) defaults_list_write, fp); - fclose (fp); - - /* try to atomically rename the file */ - if (G_UNLIKELY (g_rename (path, absolute_path) < 0)) - { - /* tell the caller that we failed */ - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), "%s", g_strerror (errno)); - succeed = FALSE; - - /* be sure to remove the temporary file */ - g_unlink (path); - } - } - else - { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), "%s", g_strerror (errno)); - succeed = FALSE; - } - g_free (path); - } - -done: - /* release the lock on the database */ - g_mutex_unlock (database->lock); - - return succeed; -} - - - -/** - * thunar_vfs_mime_database_add_application: - * @database : a #ThunarVfsMimeDatabase. - * @info : a #ThunarVfsMimeInfo. - * @name : the name for the application. - * @exec : the command for the application. - * @error : return location for errors or %NULL. - * - * Adds a new #ThunarVfsMimeApplication to the @database, whose - * name is @name and command is @exec, and which can be used to - * open files of type @info. - * - * The caller is responsible to free the returned object - * using g_object_unref() when no longer needed. - * - * Return value: the newly created #ThunarVfsMimeApplication - * or %NULL on error. - **/ -ThunarVfsMimeApplication* -thunar_vfs_mime_database_add_application (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info, - const gchar *name, - const gchar *exec, - GError **error) -{ - ThunarVfsMimeApplication *application = NULL; - gboolean succeed; - gchar *desktop_id; - gchar *directory; - gchar *command; - gchar *file; - guint n; - FILE *fp; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), NULL); - g_return_val_if_fail (info != NULL, NULL); - g_return_val_if_fail (g_utf8_validate (name, -1, NULL), NULL); - g_return_val_if_fail (exec != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* determine a file name for the new applications .desktop file */ - directory = xfce_resource_save_location (XFCE_RESOURCE_DATA, "applications/", TRUE); - file = g_strconcat (directory, G_DIR_SEPARATOR_S, name, "-usercreated.desktop", NULL); - for (n = 1; g_file_test (file, G_FILE_TEST_EXISTS); ++n) - { - g_free (file); - file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s-usercreated-%u.desktop", directory, name, n); - } - - /* open the .desktop file for writing */ - fp = fopen (file, "w"); - if (G_UNLIKELY (fp == NULL)) - { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), "%s", g_strerror (errno)); - } - else - { - /* write the content and close the file */ - fprintf (fp, "[Desktop Entry]\n"); - fprintf (fp, "Encoding=UTF-8\n"); - fprintf (fp, "Type=Application\n"); - fprintf (fp, "NoDisplay=true\n"); - fprintf (fp, "Name=%s\n", name); - fprintf (fp, "Exec=%s\n", exec); - fprintf (fp, "MimeType=%s\n", thunar_vfs_mime_info_get_name (info)); - fclose (fp); - - /* update the mimeinfo.cache file for the directory */ - command = g_strdup_printf ("update-desktop-database \"%s\"", directory); - succeed = g_spawn_command_line_sync (command, NULL, NULL, NULL, error); - g_free (command); - - /* check if the update was successfull */ - if (G_LIKELY (succeed)) - { - /* load the application from the .desktop file */ - desktop_id = g_path_get_basename (file); - application = thunar_vfs_mime_application_new_from_file (file, desktop_id); - g_free (desktop_id); - - /* this shouldn't happen, but you never know */ - if (G_UNLIKELY (application == NULL)) - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO, _("Failed to load application from file %s"), file); - } - } - - /* cleanup */ - g_free (directory); - g_free (file); - - return application; -} - - - -/** - * thunar_vfs_mime_database_remove_application: - * @database : a #ThunarVfsMimeDatabase. - * @application : a #ThunarVfsMimeApplication. - * @error : return location for errors or %NULL. - * - * Undoes the effect of thunar_vfs_mime_database_add_application() by removing - * the user created @application from the @database. The @application must be - * user created, and the removal will fail if its not (for example if its a - * system-wide installed application launcher). See the documentation for - * thunar_vfs_mime_application_is_usercreated() for details. - * - * Return value: %TRUE if the removal was successfull, %FALSE otherwise and - * @error will be set. - **/ -gboolean -thunar_vfs_mime_database_remove_application (ThunarVfsMimeDatabase *database, - ThunarVfsMimeApplication *application, - GError **error) -{ - const gchar *desktop_id; - gboolean succeed = FALSE; - gchar *directory; - gchar *command; - gchar *file; - - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (THUNAR_VFS_IS_MIME_DATABASE (database), FALSE); - g_return_val_if_fail (THUNAR_VFS_IS_MIME_APPLICATION (application), FALSE); - - /* verify that the application is usercreated */ - if (!thunar_vfs_mime_application_is_usercreated (application)) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, "%s", g_strerror (EINVAL)); - return FALSE; - } - - /* determine the desktop-id of the application */ - desktop_id = thunar_vfs_mime_application_get_desktop_id (application); - - /* determine the save location for applications */ - directory = xfce_resource_save_location (XFCE_RESOURCE_DATA, "applications/", TRUE); - if (G_UNLIKELY (directory == NULL)) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR, "%s", g_strerror (ENOTDIR)); - return FALSE; - } - - /* try to delete the desktop file */ - file = g_build_filename (directory, desktop_id, NULL); - if (G_UNLIKELY (g_unlink (file) < 0)) - { - /* tell the user that we failed to delete the application launcher */ - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Failed to remove \"%s\": %s"), file, g_strerror (errno)); - } - else - { - /* update the mimeinfo.cache file for the directory */ - command = g_strdup_printf ("update-desktop-database \"%s\"", directory); - succeed = g_spawn_command_line_sync (command, NULL, NULL, NULL, error); - g_free (command); - - /* check if we succeed */ - if (G_LIKELY (succeed)) - { - /* clear the application cache */ - g_mutex_lock (database->lock); - g_hash_table_foreach_remove (database->applications, (GHRFunc) exo_noop_true, NULL); - g_mutex_unlock (database->lock); - } - } - - /* cleanup */ - g_free (directory); - g_free (file); - - return succeed; -} - - - -/** - * _thunar_vfs_mime_database: - * - * The shared reference to the global mime database. Only valid between - * calls to thunar_vfs_init() and thunar_vfs_shutdown(). - **/ -ThunarVfsMimeDatabase *_thunar_vfs_mime_database = NULL; - - - -/** - * _thunar_vfs_mime_inode_directory: - * - * The shared #ThunarVfsMimeInfo instance for "inode/directory". Only valid - * between calls to thunar_vfs_init() and thunar_vfs_shutdown(). - **/ -ThunarVfsMimeInfo *_thunar_vfs_mime_inode_directory = NULL; - - - -/** - * _thunar_vfs_mime_application_x_desktop: - * - * The shared #ThunarVfsMimeInfo instance for "application/x-desktop". Only valid - * between calls to thunar_vfs_init() and thunar_vfs_shutdown(). - **/ -ThunarVfsMimeInfo *_thunar_vfs_mime_application_x_desktop = NULL; - - - -/** - * _thunar_vfs_mime_application_x_executable: - * - * The shared #ThunarVfsMimeInfo instance for "application/x-executable". Only valid - * between calls to thunar_vfs_init() and thunar_vfs_shutdown(). - **/ -ThunarVfsMimeInfo *_thunar_vfs_mime_application_x_executable = NULL; - - - -/** - * _thunar_vfs_mime_application_x_shellscript: - * - * The shared #ThunarVfsMimeInfo instance for "application/x-shellscript". Only valid - * between calls to thunar_vfs_init() and thunar_vfs_shutdown(). - **/ -ThunarVfsMimeInfo *_thunar_vfs_mime_application_x_shellscript = NULL; - - - -/** - * _thunar_vfs_mime_application_octet_stream: - * - * The shared #ThunarVfsMimeInfo instance for "application/octet-stream". Only valid - * between calls to thunar_vfs_init() and thunar_vfs_shutdown(). - **/ -ThunarVfsMimeInfo *_thunar_vfs_mime_application_octet_stream = NULL; - - - -#define __THUNAR_VFS_MIME_DATABASE_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-mime-database.h b/thunar-vfs/thunar-vfs-mime-database.h deleted file mode 100644 index f3e49ad3a..000000000 --- a/thunar-vfs/thunar-vfs-mime-database.h +++ /dev/null @@ -1,76 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_MIME_DATABASE_H__ -#define __THUNAR_VFS_MIME_DATABASE_H__ - -#include <thunar-vfs/thunar-vfs-mime-application.h> -#include <thunar-vfs/thunar-vfs-mime-info.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsMimeDatabaseClass ThunarVfsMimeDatabaseClass; -typedef struct _ThunarVfsMimeDatabase ThunarVfsMimeDatabase; - -#define THUNAR_VFS_TYPE_MIME_DATABASE (thunar_vfs_mime_database_get_type ()) -#define THUNAR_VFS_MIME_DATABASE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_MIME_DATABASE, ThunarVfsMimeDatabase)) -#define THUNAR_VFS_MIME_DATABASE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_MIME_DATABASE, ThunarVfsMimeDatabaseClass)) -#define THUNAR_VFS_IS_MIME_DATABASE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_MIME_DATABASE)) -#define THUNAR_VFS_IS_MIME_DATABASE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_MIME_DATABASE)) -#define THUNAR_VFS_MIME_DATABASE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_MIME_DATABASE, ThunarVfsMimeDatabaseClass)) - -GType thunar_vfs_mime_database_get_type (void) G_GNUC_CONST; - -ThunarVfsMimeDatabase *thunar_vfs_mime_database_get_default (void) G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info (ThunarVfsMimeDatabase *database, - const gchar *mime_type) G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_for_data (ThunarVfsMimeDatabase *database, - gconstpointer data, - gsize length) G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_for_name (ThunarVfsMimeDatabase *database, - const gchar *name) G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsMimeInfo *thunar_vfs_mime_database_get_info_for_file (ThunarVfsMimeDatabase *database, - const gchar *path, - const gchar *name) G_GNUC_WARN_UNUSED_RESULT; - -GList *thunar_vfs_mime_database_get_infos_for_info (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info) G_GNUC_WARN_UNUSED_RESULT; - -GList *thunar_vfs_mime_database_get_applications (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info) G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsMimeApplication *thunar_vfs_mime_database_get_default_application (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info) G_GNUC_WARN_UNUSED_RESULT; -gboolean thunar_vfs_mime_database_set_default_application (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info, - ThunarVfsMimeApplication *application, - GError **error) G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsMimeApplication *thunar_vfs_mime_database_add_application (ThunarVfsMimeDatabase *database, - ThunarVfsMimeInfo *info, - const gchar *name, - const gchar *exec, - GError **error) G_GNUC_WARN_UNUSED_RESULT; -gboolean thunar_vfs_mime_database_remove_application (ThunarVfsMimeDatabase *database, - ThunarVfsMimeApplication *application, - GError **error) G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_DATABASE_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-handler-private.h b/thunar-vfs/thunar-vfs-mime-handler-private.h deleted file mode 100644 index cabd9ec4e..000000000 --- a/thunar-vfs/thunar-vfs-mime-handler-private.h +++ /dev/null @@ -1,50 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_MIME_HANDLER_PRIVATE_H__ -#define __THUNAR_VFS_MIME_HANDLER_PRIVATE_H__ - -#include <thunar-vfs/thunar-vfs-mime-handler.h> - -G_BEGIN_DECLS; - -struct _ThunarVfsMimeHandlerClass -{ - GObjectClass __parent__; -}; - -struct _ThunarVfsMimeHandler -{ - GObject __parent__; - - ThunarVfsMimeHandlerFlags flags; - gchar *binary_name; - gchar *command; - gchar *name; - gchar *icon; -}; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_HANDLER_PRIVATE_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-handler.c b/thunar-vfs/thunar-vfs-mime-handler.c deleted file mode 100644 index c480dd608..000000000 --- a/thunar-vfs/thunar-vfs-mime-handler.c +++ /dev/null @@ -1,571 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#include <thunar-vfs/thunar-vfs-enum-types.h> -#include <thunar-vfs/thunar-vfs-exec.h> -#include <thunar-vfs/thunar-vfs-mime-handler-private.h> -#include <thunar-vfs/thunar-vfs-mime-handler.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/* Property identifiers */ -enum -{ - PROP_0, - PROP_COMMAND, - PROP_FLAGS, - PROP_ICON, - PROP_NAME, -}; - - - -static void thunar_vfs_mime_handler_class_init (ThunarVfsMimeHandlerClass *klass); -static void thunar_vfs_mime_handler_finalize (GObject *object); -static void thunar_vfs_mime_handler_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void thunar_vfs_mime_handler_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static gboolean thunar_vfs_mime_handler_execute (const ThunarVfsMimeHandler *mime_handler, - GdkScreen *screen, - GList *path_list, - gchar **envp, - GError **error); -static gboolean thunar_vfs_mime_handler_get_argv (const ThunarVfsMimeHandler *mime_handler, - GList *path_list, - gint *argc, - gchar ***argv, - GError **error); -static void thunar_vfs_mime_handler_set_command (ThunarVfsMimeHandler *mime_handler, - const gchar *command); -static void thunar_vfs_mime_handler_set_flags (ThunarVfsMimeHandler *mime_handler, - ThunarVfsMimeHandlerFlags flags); -static const gchar *thunar_vfs_mime_handler_get_icon (const ThunarVfsMimeHandler *mime_handler); -static void thunar_vfs_mime_handler_set_icon (ThunarVfsMimeHandler *mime_handler, - const gchar *icon); -static void thunar_vfs_mime_handler_set_name (ThunarVfsMimeHandler *mime_handler, - const gchar *name); - - - -static GObjectClass *thunar_vfs_mime_handler_parent_class; - - - -GType -thunar_vfs_mime_handler_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsMimeHandler", - sizeof (ThunarVfsMimeHandlerClass), - thunar_vfs_mime_handler_class_init, - sizeof (ThunarVfsMimeHandler), - NULL, - 0); - } - - return type; -} - - - -static void -thunar_vfs_mime_handler_class_init (ThunarVfsMimeHandlerClass *klass) -{ - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_mime_handler_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_mime_handler_finalize; - gobject_class->get_property = thunar_vfs_mime_handler_get_property; - gobject_class->set_property = thunar_vfs_mime_handler_set_property; - - /** - * ThunarVfsMimeHandler:command: - * - * The command line for this #ThunarVfsMimeHandler. - **/ - g_object_class_install_property (gobject_class, - PROP_COMMAND, - g_param_spec_string ("command", - _("Command"), - _("The command to run the mime handler"), - NULL, - EXO_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /** - * ThunarVfsMimeHandler:flags: - * - * The #ThunarVfsMimeHandlerFlags for this #ThunarVfsMimeHandler. - **/ - g_object_class_install_property (gobject_class, - PROP_FLAGS, - g_param_spec_flags ("flags", - _("Flags"), - _("The flags for the mime handler"), - THUNAR_VFS_TYPE_VFS_MIME_HANDLER_FLAGS, - 0, - EXO_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /** - * ThunarVfsMimeHandler:icon: - * - * The icon of this #ThunarVfsMimeHandler, which can be either - * %NULL in which case no icon is known, an absolute path to - * an icon file, or a named icon. - **/ - g_object_class_install_property (gobject_class, - PROP_ICON, - g_param_spec_string ("icon", - _("Icon"), - _("The icon of the mime handler"), - NULL, - EXO_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /** - * ThunarVfsMimeHandler:name: - * - * The name of this #ThunarVfsMimeHandler. - **/ - g_object_class_install_property (gobject_class, - PROP_NAME, - g_param_spec_string ("name", - _("Name"), - _("The name of the mime handler"), - NULL, - EXO_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} - - - -static void -thunar_vfs_mime_handler_finalize (GObject *object) -{ - ThunarVfsMimeHandler *mime_handler = THUNAR_VFS_MIME_HANDLER (object); - - /* release the attributes */ - g_free (mime_handler->binary_name); - g_free (mime_handler->command); - g_free (mime_handler->name); - g_free (mime_handler->icon); - - (*G_OBJECT_CLASS (thunar_vfs_mime_handler_parent_class)->finalize) (object); -} - - - -static void -thunar_vfs_mime_handler_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - ThunarVfsMimeHandler *mime_handler = THUNAR_VFS_MIME_HANDLER (object); - - switch (prop_id) - { - case PROP_COMMAND: - g_value_set_string (value, thunar_vfs_mime_handler_get_command (mime_handler)); - break; - - case PROP_FLAGS: - g_value_set_flags (value, thunar_vfs_mime_handler_get_flags (mime_handler)); - break; - - case PROP_ICON: - g_value_set_string (value, thunar_vfs_mime_handler_get_icon (mime_handler)); - break; - - case PROP_NAME: - g_value_set_string (value, thunar_vfs_mime_handler_get_name (mime_handler)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - - -static void -thunar_vfs_mime_handler_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - ThunarVfsMimeHandler *mime_handler = THUNAR_VFS_MIME_HANDLER (object); - - switch (prop_id) - { - case PROP_COMMAND: - thunar_vfs_mime_handler_set_command (mime_handler, g_value_get_string (value)); - break; - - case PROP_FLAGS: - thunar_vfs_mime_handler_set_flags (mime_handler, g_value_get_flags (value)); - break; - - case PROP_ICON: - thunar_vfs_mime_handler_set_icon (mime_handler, g_value_get_string (value)); - break; - - case PROP_NAME: - thunar_vfs_mime_handler_set_name (mime_handler, g_value_get_string (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - - -static gboolean -thunar_vfs_mime_handler_execute (const ThunarVfsMimeHandler *mime_handler, - GdkScreen *screen, - GList *path_list, - gchar **envp, - GError **error) -{ - ThunarVfsPath *parent; - gboolean result; - gchar *working_directory; - gchar **argv; - gint argc; - - /* parse the command line */ - if (!thunar_vfs_mime_handler_get_argv (mime_handler, path_list, &argc, &argv, error)) - return FALSE; - - /* use the first paths base directory as working directory for the application */ - parent = (path_list != NULL) ? thunar_vfs_path_get_parent (path_list->data) : NULL; - working_directory = (parent != NULL) ? _thunar_vfs_path_translate_dup_string (parent, THUNAR_VFS_PATH_SCHEME_FILE, NULL) : NULL; - - /* try to spawn the application */ - result = thunar_vfs_exec_on_screen (screen, working_directory, argv, envp, G_SPAWN_SEARCH_PATH, - mime_handler->flags & THUNAR_VFS_MIME_HANDLER_SUPPORTS_STARTUP_NOTIFY, - mime_handler->icon, error); - - /* cleanup */ - g_free (working_directory); - g_strfreev (argv); - - return result; -} - - - -static gboolean -thunar_vfs_mime_handler_get_argv (const ThunarVfsMimeHandler *mime_handler, - GList *path_list, - gint *argc, - gchar ***argv, - GError **error) -{ - return thunar_vfs_exec_parse (mime_handler->command, path_list, mime_handler->icon, mime_handler->name, NULL, - (mime_handler->flags & THUNAR_VFS_MIME_HANDLER_REQUIRES_TERMINAL) != 0, - argc, argv, error); -} - - - -static void -thunar_vfs_mime_handler_set_command (ThunarVfsMimeHandler *mime_handler, - const gchar *command) -{ - gchar **argv; - gint argc; - - /* release the previous command and binary name */ - g_free (mime_handler->binary_name); - g_free (mime_handler->command); - - /* determine the new binary name */ - if (command != NULL && g_shell_parse_argv (command, &argc, &argv, NULL)) - { - /* yep, we have a new binary name */ - mime_handler->binary_name = g_path_get_basename (argv[0]); - g_strfreev (argv); - } - else - { - /* no binary name */ - mime_handler->binary_name = NULL; - } - - /* determine the new command */ - mime_handler->command = g_strdup (command); -} - - - -static void -thunar_vfs_mime_handler_set_flags (ThunarVfsMimeHandler *mime_handler, - ThunarVfsMimeHandlerFlags flags) -{ - mime_handler->flags = flags; -} - - - -static const gchar* -thunar_vfs_mime_handler_get_icon (const ThunarVfsMimeHandler *mime_handler) -{ - return mime_handler->icon; -} - - - -static void -thunar_vfs_mime_handler_set_icon (ThunarVfsMimeHandler *mime_handler, - const gchar *icon) -{ - gint icon_len; - - /* release the previous icon */ - g_free (mime_handler->icon); - - /* setup the new icon */ - mime_handler->icon = g_strdup (icon); - - /* strip off known suffixes for image files if a themed icon is specified */ - if (mime_handler->icon != NULL && !g_path_is_absolute (mime_handler->icon)) - { - /* check if the icon name ends in .png */ - icon_len = strlen (mime_handler->icon); - if (G_LIKELY (icon_len > 4) && strcmp (mime_handler->icon + (icon_len - 4), ".png") == 0) - mime_handler->icon[icon_len - 4] = '\0'; - } -} - - - -static void -thunar_vfs_mime_handler_set_name (ThunarVfsMimeHandler *mime_handler, - const gchar *name) -{ - g_free (mime_handler->name); - mime_handler->name = g_strdup (name); -} - - - -/** - * thunar_vfs_mime_handler_get_command: - * @mime_handler : a #ThunarVfsMimeHandler. - * - * Returns the command associated with @mime_handler. - * - * Return value: the command associated with @mime_handler. - **/ -const gchar* -thunar_vfs_mime_handler_get_command (const ThunarVfsMimeHandler *mime_handler) -{ - g_return_val_if_fail (THUNAR_VFS_IS_MIME_HANDLER (mime_handler), NULL); - return mime_handler->command; -} - - - -/** - * thunar_vfs_mime_handler_get_flags: - * @mime_handler : a #ThunarVfsMimeHandler. - * - * Returns the #ThunarVfsMimeHandlerFlags for @mime_handler. - * - * Return value: the #ThunarVfsMimeHandlerFlags for @mime_handler. - **/ -ThunarVfsMimeHandlerFlags -thunar_vfs_mime_handler_get_flags (const ThunarVfsMimeHandler *mime_handler) -{ - g_return_val_if_fail (THUNAR_VFS_IS_MIME_HANDLER (mime_handler), 0); - return mime_handler->flags; -} - - - -/** - * thunar_vfs_mime_handler_get_name: - * @mime_handler : a #ThunarVfsMimeHandler. - * - * Returns the name of @mime_handler. - * - * Return value: the name of @mime_handler. - **/ -const gchar* -thunar_vfs_mime_handler_get_name (const ThunarVfsMimeHandler *mime_handler) -{ - g_return_val_if_fail (THUNAR_VFS_IS_MIME_HANDLER (mime_handler), NULL); - return mime_handler->name; -} - - - -/** - * thunar_vfs_mime_handler_exec: - * @mime_handler : a #ThunarVfsMimeHandler. - * @screen : a #GdkScreen or %NULL to use the default screen. - * @path_list : a list of #ThunarVfsPath<!---->s to open. - * @error : return location for errors or %NULL. - * - * Wrapper to thunar_vfs_mime_handler_exec_with_env(), which - * simply passes a %NULL pointer for the environment variables. - * - * Return value: %TRUE if the execution succeed, else %FALSE. - **/ -gboolean -thunar_vfs_mime_handler_exec (const ThunarVfsMimeHandler *mime_handler, - GdkScreen *screen, - GList *path_list, - GError **error) -{ - g_return_val_if_fail (THUNAR_VFS_IS_MIME_HANDLER (mime_handler), FALSE); - g_return_val_if_fail (screen == NULL || GDK_IS_SCREEN (screen), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - return thunar_vfs_mime_handler_exec_with_env (mime_handler, screen, path_list, NULL, error); -} - - - -/** - * thunar_vfs_mime_handler_exec_with_env: - * @mime_handler : a #ThunarVfsMimeHandler. - * @screen : a #GdkScreen or %NULL to use the default screen. - * @path_list : a list of #ThunarVfsPath<!---->s to open. - * @envp : child's environment or %NULL to inherit parent's. - * @error : return location for errors or %NULL. - * - * Executes @mime_handler on @screen using the given @path_list. If - * @path_list contains more than one #ThunarVfsPath and @mime_handler - * doesn't support opening multiple documents at once, one - * instance of @mime_handler will be spawned for every #ThunarVfsPath - * given in @path_list. - * - * Return value: %TRUE if the execution succeed, else %FALSE. - **/ -gboolean -thunar_vfs_mime_handler_exec_with_env (const ThunarVfsMimeHandler *mime_handler, - GdkScreen *screen, - GList *path_list, - gchar **envp, - GError **error) -{ - gboolean succeed = TRUE; - GList list; - GList *lp; - - g_return_val_if_fail (THUNAR_VFS_IS_MIME_HANDLER (mime_handler), FALSE); - g_return_val_if_fail (screen == NULL || GDK_IS_SCREEN (screen), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* fallback to the default screen if no screen is given */ - if (G_UNLIKELY (screen == NULL)) - screen = gdk_screen_get_default (); - - /* check whether the application can open multiple documents at once */ - if (G_LIKELY ((mime_handler->flags & THUNAR_VFS_MIME_HANDLER_SUPPORTS_MULTI) == 0 && path_list != NULL)) - { - /* fake an empty list */ - list.next = NULL; - list.prev = NULL; - - /* spawn a new instance for each path item */ - for (lp = path_list; lp != NULL && succeed; lp = lp->next) - { - /* "insert" into faked list */ - list.data = lp->data; - - /* spawn the instance */ - succeed = thunar_vfs_mime_handler_execute (mime_handler, screen, &list, envp, error); - } - } - else - { - /* spawn a single instance for all path items */ - succeed = thunar_vfs_mime_handler_execute (mime_handler, screen, path_list, envp, error); - } - - return succeed; -} - - - -/** - * thunar_vfs_mime_handler_lookup_icon_name: - * @mime_handler : a #ThunarVfsMimeHandler. - * @icon_theme : a #GtkIconTheme. - * - * Looks up the icon name for @mime_handler in - * @icon_theme. Returns %NULL if no suitable - * icon is present in @icon_theme. - * - * The returned icon can be either a named icon in - * @icon_theme or an absolute path to an icon file, - * or %NULL. - * - * Return value: the icon name for @mime_handler or - * %NULL. - **/ -const gchar* -thunar_vfs_mime_handler_lookup_icon_name (const ThunarVfsMimeHandler *mime_handler, - GtkIconTheme *icon_theme) -{ - g_return_val_if_fail (THUNAR_VFS_IS_MIME_HANDLER (mime_handler), NULL); - g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL); - - if (mime_handler->icon != NULL && (g_path_is_absolute (mime_handler->icon) || gtk_icon_theme_has_icon (icon_theme, mime_handler->icon))) - return mime_handler->icon; - else if (mime_handler->binary_name != NULL && gtk_icon_theme_has_icon (icon_theme, mime_handler->binary_name)) - return mime_handler->binary_name; - else - return NULL; -} - - - -#define __THUNAR_VFS_MIME_HANDLER_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-mime-handler.h b/thunar-vfs/thunar-vfs-mime-handler.h deleted file mode 100644 index 876d37be5..000000000 --- a/thunar-vfs/thunar-vfs-mime-handler.h +++ /dev/null @@ -1,82 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_MIME_HANDLER_H__ -#define __THUNAR_VFS_MIME_HANDLER_H__ - -#include <exo/exo.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsMimeHandlerClass ThunarVfsMimeHandlerClass; -typedef struct _ThunarVfsMimeHandler ThunarVfsMimeHandler; - -#define THUNAR_VFS_TYPE_MIME_HANDLER (thunar_vfs_mime_handler_get_type ()) -#define THUNAR_VFS_MIME_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_MIME_HANDLER, ThunarVfsMimeHandler)) -#define THUNAR_VFS_MIME_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_MIME_HANDLER, ThunarVfsMimeHandlerClass)) -#define THUNAR_VFS_IS_MIME_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_MIME_HANDLER)) -#define THUNAR_VFS_IS_MIME_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_MIME_HANDLER)) -#define THUNAR_VFS_MIME_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_MIME_HANDLER, ThunarVfsMimeHandlerClass)) - -/** - * ThunarVfsMimeHandlerFlags: - * @THUNAR_VFS_MIME_HANDLER_HIDDEN : the handler should not be displayed in the menu system. - * @THUNAR_VFS_MIME_HANDLER_REQUIRES_TERMINAL : the handler must be run in a terminal. - * @THUNAR_VFS_MIME_HANDLER_SUPPORTS_STARTUP_NOTIFY : the handler supports startup notification. - * @THUNAR_VFS_MIME_HANDLER_SUPPORTS_MULTI : the handler supports opening multiple documents at once (%F or %U). - * @THUNAR_VFS_MIME_HANDLER_SUPPORTS_URIS : the handler supports opening URIs (%u or %U). - * - * Various flags associated with a #ThunarVfsMimeHandler. - **/ -typedef enum /*< flags >*/ -{ - THUNAR_VFS_MIME_HANDLER_HIDDEN = (1 << 0L), - THUNAR_VFS_MIME_HANDLER_REQUIRES_TERMINAL = (1 << 1L), - THUNAR_VFS_MIME_HANDLER_SUPPORTS_STARTUP_NOTIFY = (1 << 2L), - THUNAR_VFS_MIME_HANDLER_SUPPORTS_MULTI = (1 << 3L), - THUNAR_VFS_MIME_HANDLER_SUPPORTS_URIS = (1 << 4L), -} ThunarVfsMimeHandlerFlags; - -GType thunar_vfs_mime_handler_get_type (void) G_GNUC_CONST; - -const gchar *thunar_vfs_mime_handler_get_command (const ThunarVfsMimeHandler *mime_handler); -ThunarVfsMimeHandlerFlags thunar_vfs_mime_handler_get_flags (const ThunarVfsMimeHandler *mime_handler); -const gchar *thunar_vfs_mime_handler_get_name (const ThunarVfsMimeHandler *mime_handler); - -gboolean thunar_vfs_mime_handler_exec (const ThunarVfsMimeHandler *mime_handler, - GdkScreen *screen, - GList *path_list, - GError **error); -gboolean thunar_vfs_mime_handler_exec_with_env (const ThunarVfsMimeHandler *mime_handler, - GdkScreen *screen, - GList *path_list, - gchar **envp, - GError **error); - -const gchar *thunar_vfs_mime_handler_lookup_icon_name (const ThunarVfsMimeHandler *mime_handler, - GtkIconTheme *icon_theme); - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_HANDLER_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-info.c b/thunar-vfs/thunar-vfs-mime-info.c deleted file mode 100644 index 7c8fe0cfe..000000000 --- a/thunar-vfs/thunar-vfs-mime-info.c +++ /dev/null @@ -1,518 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -/* implement thunar-vfs-mime-info's inline functions */ -#define G_IMPLEMENT_INLINES 1 -#define __THUNAR_VFS_MIME_INFO_C__ -#include <thunar-vfs/thunar-vfs-mime-info.h> - -#include <thunar-vfs/thunar-vfs-mime-parser.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/* special mime type to gnome icon mapping */ -static const struct -{ - const gchar subtype[12]; - const gchar icon[19]; -} GNOME_INODE_ICONNAMES[] = -{ - { "blockdevice", "gnome-fs-blockdev" }, - { "chardevice", "gnome-fs-chardev" }, - { "directory", "gnome-fs-directory" }, - { "fifo", "gnome-fs-fifo" }, - { "socket", "gnome-fs-socket" }, -}; - -/* first fallback gnome icon name */ -static const gchar GNOME_FS_REGULAR[] = "gnome-fs-regular"; - -/* second fallback gnome icon name */ -static const gchar GNOME_MIME_APPLICATION_OCTET_STREAM[] = "gnome-mime-application-octet-stream"; - -/* generic standard icon names (Icon Naming Spec 0.8) */ -static const gchar XDG_GENERIC_ICONNAMES[][18] = -{ - "audio-x-generic", - "font-x-generic", - "image-x-generic", - "package-x-generic", - "text-x-generic", - "video-x-generic", -}; - - - - -/* Checks whether info has a static constant icon name, that doesn't - * need to be freed using g_free(). - */ -static inline gboolean -icon_name_is_static (const gchar *icon_name) -{ - guint n; - for (n = 0; n < G_N_ELEMENTS (GNOME_INODE_ICONNAMES); ++n) - if (icon_name == GNOME_INODE_ICONNAMES[n].icon) - return TRUE; - for (n = 0; n < G_N_ELEMENTS (XDG_GENERIC_ICONNAMES); ++n) - if (icon_name == XDG_GENERIC_ICONNAMES[n]) - return TRUE; - return (icon_name == GNOME_FS_REGULAR || icon_name == GNOME_MIME_APPLICATION_OCTET_STREAM); -} - - - -GType -thunar_vfs_mime_info_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = g_boxed_type_register_static (I_("ThunarVfsMimeInfo"), - (GBoxedCopyFunc) thunar_vfs_mime_info_ref, - (GBoxedFreeFunc) thunar_vfs_mime_info_unref); - } - - return type; -} - - - -/** - * thunar_vfs_mime_info_new: - * @name : the mime type name. - * @len : the length of @name or %-1 if zero-terminated. - * - * Allocates a new #ThunarVfsMimeInfo object with an - * initial reference count of one and sets it to the - * given @name. - * - * Note that no checking is performed on the given @name. - * You should not normally use this function, but use - * thunar_vfs_mime_database_get_info() instead. - * - * In addition, if you allocate #ThunarVfsMimeInfo<!---->s - * using this function, you cannot mix them with the objects - * allocated in a #ThunarVfsMimeDatabase, because the - * #ThunarVfsMimeDatabase and associated functions assume - * that #ThunarVfsMimeInfo objects are unique. - * - * Return value: the newly allocated #ThunarVfsMimeInfo. - **/ -ThunarVfsMimeInfo* -thunar_vfs_mime_info_new (const gchar *name, - gssize len) -{ - ThunarVfsMimeInfo *info; - - if (G_UNLIKELY (len < 0)) - len = strlen (name); - - /* allocate the new object */ - info = _thunar_vfs_slice_alloc (sizeof (*info) + len + 1); - info->ref_count = 1; - info->comment = NULL; - info->icon_name = NULL; - - /* set the name */ - memcpy (((gchar *) info) + sizeof (*info), name, len + 1); - - return info; -} - - - -/** - * thunar_vfs_mime_info_unref: - * @info : a #ThunarVfsMimeInfo. - * - * Decrements the reference count on @info and releases - * the resources allocated for @info once the reference - * count drops to zero. - **/ -void -thunar_vfs_mime_info_unref (ThunarVfsMimeInfo *info) -{ - if (G_UNLIKELY (info == NULL)) - return; - - if (exo_atomic_dec (&info->ref_count)) - { - /* free the comment */ - if (info->comment != NULL && info->comment != thunar_vfs_mime_info_get_name (info)) - { -#ifdef G_ENABLE_DEBUG - memset (info->comment, 0xaa, strlen (info->comment) + 1); -#endif - g_free (info->comment); - } - - /* free the icon name if it isn't one of the statics */ - if (G_LIKELY (!icon_name_is_static (info->icon_name))) - { -#ifdef G_ENABLE_DEBUG - if (G_LIKELY (info->icon_name != NULL)) - memset (info->icon_name, 0xaa, strlen (info->icon_name) + 1); -#endif - g_free (info->icon_name); - } - - /* free the info struct (need to determine the block size for the slice allocator) */ - _thunar_vfs_slice_free1 (sizeof (*info) + strlen (((const gchar *) info) + sizeof (*info)) + 1, info); - } -} - - - -/** - * thunar_vfs_mime_info_get_comment: - * @info : a #ThunarVfsMimeInfo. - * - * Determines the description for the given @info. - * - * Note that this method MUST NOT be called from threads other than - * the main thread, because it's not thread-safe! - * - * Return value: the comment associated with the @info or the empty string - * if no comment was provided. - */ -const gchar* -thunar_vfs_mime_info_get_comment (ThunarVfsMimeInfo *info) -{ - const gchar *name; - gchar *path; - gchar *spec; - - if (G_UNLIKELY (info->comment == NULL)) - { - name = thunar_vfs_mime_info_get_name (info); - spec = g_strdup_printf ("mime/%s.xml", name); - path = xfce_resource_lookup (XFCE_RESOURCE_DATA, spec); - g_free (spec); - - if (G_LIKELY (path != NULL)) - { - info->comment = _thunar_vfs_mime_parser_load_comment_from_file (path, NULL); - g_free (path); - } - - if (G_UNLIKELY (info->comment == NULL)) - { - /* we handle 'application/x-extension-<EXT>' special here */ - if (G_UNLIKELY (strncmp (name, "application/x-extension-", 24) == 0)) - info->comment = g_strdup_printf (_("%s document"), name + 24); - else - info->comment = (gchar *) name; - } - } - - return info->comment; -} - - - -/** - * thunar_vfs_mime_info_get_media: - * @info : a #ThunarVfsMimeInfo. - * - * Returns the media portion of the MIME type, e.g. if your - * #ThunarVfsMimeInfo instance refers to "text/plain", invoking - * this method will return "text". - * - * The caller is responsible to free the returned string - * using g_free() when no longer needed. - * - * Return value: the media portion of the MIME type. - **/ -gchar* -thunar_vfs_mime_info_get_media (const ThunarVfsMimeInfo *info) -{ - const gchar *name; - const gchar *p; - - /* lookup the slash character */ - name = thunar_vfs_mime_info_get_name (info); - for (p = name; *p != '/' && *p != '\0'; ++p) - ; - - return g_strndup (name, p - name); -} - - - -/** - * thunar_vfs_mime_info_get_subtype: - * @info : a #ThunarVfsMimeInfo. - * - * Returns the subtype portion of the MIME type, e.g. if @info - * refers to "application/octect-stream", this method will - * return "octect-stream". - * - * The caller is responsible to free the returned string - * using g_free() when no longer needed. - * - * Return value: the subtype portion of @info. - **/ -gchar* -thunar_vfs_mime_info_get_subtype (const ThunarVfsMimeInfo *info) -{ - const gchar *name; - const gchar *p; - - /* lookup the slash character */ - name = thunar_vfs_mime_info_get_name (info); - for (p = name; *p != '/' && *p != '\0'; ++p) - ; - - /* skip the slash character */ - if (G_LIKELY (*p == '/')) - ++p; - - return g_strdup (p); -} - - - -/** - * thunar_vfs_mime_info_hash: - * @info : a #ThunarVfsMimeInfo. - * - * Calculates a hash value for @info. - * - * Return value: a hash value for @info. - **/ -guint -thunar_vfs_mime_info_hash (gconstpointer info) -{ - const gchar *name; - guint h; - - name = thunar_vfs_mime_info_get_name (info); - for (h = *name; *++name != '\0'; ) - h = (h << 5) - h + *name; - - return h; -} - - - -/** - * thunar_vfs_mime_info_equal: - * @a : a #ThunarVfsMimeInfo. - * @b : a #ThunarVfsMimeInfo. - * - * Compares @a and @b and returns %TRUE if both - * are equal. - * - * Return value: %TRUE if @a and @b are equal. - **/ -gboolean -thunar_vfs_mime_info_equal (gconstpointer a, - gconstpointer b) -{ - const gchar *a_name = thunar_vfs_mime_info_get_name (a); - const gchar *b_name = thunar_vfs_mime_info_get_name (b); - - return (a == b) || G_UNLIKELY (strcmp (a_name, b_name) == 0); -} - - - -/** - * thunar_vfs_mime_info_lookup_icon_name: - * @info : a #ThunarVfsMimeInfo. - * @icon_theme : the #GtkIconTheme on which to perform the lookup. - * - * Tries to determine the name of a suitable icon for @info - * in @icon_theme. The returned icon name can then be used - * in calls to gtk_icon_theme_lookup_icon() or - * gtk_icon_theme_load_icon(). - * - * The returned icon name is owned by @info and MUST NOT be freed - * by the caller. - * - * Note that this method MUST NOT be called from threads other than - * the main thread, because it's not thread-safe! - * - * Return value: a suitable icon name for @info in @icon_theme. - **/ -const gchar* -thunar_vfs_mime_info_lookup_icon_name (ThunarVfsMimeInfo *info, - GtkIconTheme *icon_theme) -{ - const gchar *subtype; - const gchar *name; - const gchar *p; - gchar *icon_name; - gchar *media; - guint n; - - g_return_val_if_fail (info != NULL, NULL); - g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL); - - /* determine the icon name if we don't already have it cached */ - if (G_UNLIKELY (info->icon_name == NULL)) - { - /* determine media and subtype */ - name = thunar_vfs_mime_info_get_name (info); - for (p = name + 1; *p != '/' && *p != '\0'; ++p); - media = g_newa (gchar, p - name + 1); - memcpy (media, name, p - name); - media[p - name] = '\0'; - subtype = G_LIKELY (*p == '/') ? p + 1 : p; - - /* inode mime types are special */ - if (G_UNLIKELY (media[0] == 'i' && media[1] == 'n' && media[2] == 'o' && media[3] == 'd' && media[4] == 'e' && media[5] == '\0')) - { - /* use the GNOME icon names for now, they'll be mapped for some time */ - for (n = 0; n < G_N_ELEMENTS (GNOME_INODE_ICONNAMES); ++n) - if (strcmp (subtype, GNOME_INODE_ICONNAMES[n].subtype) == 0) - if (gtk_icon_theme_has_icon (icon_theme, GNOME_INODE_ICONNAMES[n].icon)) - { - info->icon_name = (gchar *) GNOME_INODE_ICONNAMES[n].icon; - break; - } - - /* fallback is always application/octet-stream */ - if (n == G_N_ELEMENTS (GNOME_INODE_ICONNAMES)) - info->icon_name = (gchar *) GNOME_MIME_APPLICATION_OCTET_STREAM; - } - else - { - /* try icon names from the icon naming spec first */ - icon_name = g_strconcat (media, "-", subtype, NULL); - if (!gtk_icon_theme_has_icon (icon_theme, icon_name)) - { - /* release the failed icon_name */ - g_free (icon_name); - - /* retry with "<media>-x-generic" */ - icon_name = g_strconcat (media, "-x-generic", NULL); - if (!gtk_icon_theme_has_icon (icon_theme, icon_name)) - { - /* release the failed icon_name */ - g_free (icon_name); - - /* fallback to "gnome-mime-<media>-<subtype>" icon naming scheme */ - icon_name = g_strconcat ("gnome-mime-", media, "-", subtype, NULL); - if (!gtk_icon_theme_has_icon (icon_theme, icon_name)) - { - /* fallback to the generic "gnome-mime-<media>" */ - icon_name[11 + ((subtype - 1) - name)] = '\0'; - if (!gtk_icon_theme_has_icon (icon_theme, icon_name)) - { - /* release the failed icon_name */ - g_free (icon_name); - - /* fallback to "gnome-fs-regular" if available, otherwise application/octet-stream */ - if (gtk_icon_theme_has_icon (icon_theme, GNOME_FS_REGULAR)) - icon_name = (gchar *) GNOME_FS_REGULAR; - else - icon_name = (gchar *) GNOME_MIME_APPLICATION_OCTET_STREAM; - } - } - } - else - { - /* "<media>-x-generic" matched, check if we can use a static icon_name */ - for (n = 0; n < G_N_ELEMENTS (XDG_GENERIC_ICONNAMES); ++n) - if (strcmp (icon_name, XDG_GENERIC_ICONNAMES[n]) == 0) - { - /* release our duplicate */ - g_free (icon_name); - - /* use the static icon name instead */ - icon_name = (gchar *) XDG_GENERIC_ICONNAMES[n]; - break; - } - } - } - - /* use the determined icon_name */ - info->icon_name = icon_name; - } - - /* verify the icon name */ - _thunar_vfs_assert (info->icon_name != NULL); - _thunar_vfs_assert (info->icon_name[0] != '\0'); - } - - return info->icon_name; -} - - - -/** - * thunar_vfs_mime_info_list_free: - * @info_list : a #GList of #ThunarVfsMimeInfo<!---->s - * - * Frees the list and all #ThunarVfsMimeInfo<!---->s - * contained within the list. - **/ -void -thunar_vfs_mime_info_list_free (GList *info_list) -{ - g_list_foreach (info_list, (GFunc) thunar_vfs_mime_info_unref, NULL); - g_list_free (info_list); -} - - - -/** - * _thunar_vfs_mime_info_invalidate_icon_name: - * @info : a #ThunarVfsMimeInfo. - * - * Invalidates the cached icon name for @info. - * - * Note that this method MUST NOT be called from threads other than - * the main thread, because it's not thread-safe! - **/ -void -_thunar_vfs_mime_info_invalidate_icon_name (ThunarVfsMimeInfo *info) -{ - if (!icon_name_is_static (info->icon_name)) - { -#ifdef G_ENABLE_DEBUG - if (G_LIKELY (info->icon_name != NULL)) - memset (info->icon_name, 0xaa, strlen (info->icon_name)); -#endif - g_free (info->icon_name); - } - info->icon_name = NULL; -} - - - -#define __THUNAR_VFS_MIME_INFO_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-mime-info.h b/thunar-vfs/thunar-vfs-mime-info.h deleted file mode 100644 index 45290aaf5..000000000 --- a/thunar-vfs/thunar-vfs-mime-info.h +++ /dev/null @@ -1,106 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_MIME_INFO_H__ -#define __THUNAR_VFS_MIME_INFO_H__ - -#include <thunar-vfs/thunar-vfs-config.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsMimeInfo ThunarVfsMimeInfo; -struct _ThunarVfsMimeInfo -{ - /*< private >*/ - gint ref_count; - gchar *comment; - gchar *icon_name; -}; - - -#define THUNAR_VFS_TYPE_MIME_INFO (thunar_vfs_mime_info_get_type ()) - -GType thunar_vfs_mime_info_get_type (void) G_GNUC_CONST; - -ThunarVfsMimeInfo *thunar_vfs_mime_info_new (const gchar *name, - gssize len) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_INLINE_FUNC ThunarVfsMimeInfo *thunar_vfs_mime_info_ref (ThunarVfsMimeInfo *info); -void thunar_vfs_mime_info_unref (ThunarVfsMimeInfo *info); - -const gchar *thunar_vfs_mime_info_get_comment (ThunarVfsMimeInfo *info); -G_INLINE_FUNC const gchar *thunar_vfs_mime_info_get_name (const ThunarVfsMimeInfo *info); - -gchar *thunar_vfs_mime_info_get_media (const ThunarVfsMimeInfo *info) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gchar *thunar_vfs_mime_info_get_subtype (const ThunarVfsMimeInfo *info) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -guint thunar_vfs_mime_info_hash (gconstpointer info); -gboolean thunar_vfs_mime_info_equal (gconstpointer a, - gconstpointer b); - -const gchar *thunar_vfs_mime_info_lookup_icon_name (ThunarVfsMimeInfo *info, - GtkIconTheme *icon_theme); - -void thunar_vfs_mime_info_list_free (GList *info_list); - - -#if defined(THUNAR_VFS_COMPILATION) -void _thunar_vfs_mime_info_invalidate_icon_name (ThunarVfsMimeInfo *info) G_GNUC_INTERNAL; -#endif - - -/* inline function implementations */ -#if defined(G_CAN_INLINE) || defined(__THUNAR_VFS_MIME_INFO_C__) -/** - * thunar_vfs_mime_info_ref: - * @info : a #ThunarVfsMimeInfo. - * - * Increments the reference count on @info and returns - * the reference to @info. - * - * Return value: a reference to @info. - **/ -G_INLINE_FUNC ThunarVfsMimeInfo* -thunar_vfs_mime_info_ref (ThunarVfsMimeInfo *info) -{ - exo_atomic_inc (&info->ref_count); - return info; -} - -/** - * thunar_vfs_mime_info_get_name: - * @info : a #ThunarVfsMimeInfo. - * - * Returns the full qualified name of the MIME type - * described by the @info object. - * - * Return value: the name of @info. - **/ -G_INLINE_FUNC const gchar* -thunar_vfs_mime_info_get_name (const ThunarVfsMimeInfo *info) -{ - return ((const gchar *) info) + sizeof (*info); -} -#endif /* G_CAN_INLINE || __THUNAR_VFS_MIME_INFO_C__ */ - - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_INFO_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-legacy.c b/thunar-vfs/thunar-vfs-mime-legacy.c deleted file mode 100644 index e2c732467..000000000 --- a/thunar-vfs/thunar-vfs-mime-legacy.c +++ /dev/null @@ -1,1183 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Based on code initially written by Matthias Clasen <mclasen@redhat.com> - * for the xdgmime library. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_FNMATCH_H -#include <fnmatch.h> -#endif -#ifdef HAVE_LIMITS_H -#include <limits.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#include <stdio.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#include <thunar-vfs/thunar-vfs-mime-legacy.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -#define THUNAR_VFS_MIME_LEGACY_GLOB(obj) ((ThunarVfsMimeLegacyGlob *) (obj)) -#define THUNAR_VFS_MIME_LEGACY_SUFFIX(obj) ((ThunarVfsMimeLegacySuffix *) (obj)) -#define THUNAR_VFS_MIME_LEGACY_MATCH(obj) ((ThunarVfsMimeLegacyMatch *) (obj)) -#define THUNAR_VFS_MIME_LEGACY_MATCHLET(obj) ((ThunarVfsMimeLegacyMatchlet *) (obj)) - - - -typedef struct _ThunarVfsMimeLegacyGlob ThunarVfsMimeLegacyGlob; -typedef struct _ThunarVfsMimeLegacySuffix ThunarVfsMimeLegacySuffix; -typedef struct _ThunarVfsMimeLegacyMatch ThunarVfsMimeLegacyMatch; -typedef struct _ThunarVfsMimeLegacyMatchlet ThunarVfsMimeLegacyMatchlet; -typedef enum _ThunarVfsMimeLegacyMagic ThunarVfsMimeLegacyMagic; - - - -static void thunar_vfs_mime_legacy_class_init (ThunarVfsMimeLegacyClass *klass); -static void thunar_vfs_mime_legacy_init (ThunarVfsMimeLegacy *legacy); -static void thunar_vfs_mime_legacy_finalize (GObject *object); -static const gchar *thunar_vfs_mime_legacy_lookup_data (ThunarVfsMimeProvider *provider, - gconstpointer data, - gsize length, - gint *priority); -static const gchar *thunar_vfs_mime_legacy_lookup_literal (ThunarVfsMimeProvider *provider, - const gchar *filename); -static const gchar *thunar_vfs_mime_legacy_lookup_suffix (ThunarVfsMimeProvider *provider, - const gchar *suffix, - gboolean ignore_case); -static const gchar *thunar_vfs_mime_legacy_lookup_glob (ThunarVfsMimeProvider *provider, - const gchar *filename); -static const gchar *thunar_vfs_mime_legacy_lookup_alias (ThunarVfsMimeProvider *provider, - const gchar *alias); -static guint thunar_vfs_mime_legacy_lookup_parents (ThunarVfsMimeProvider *provider, - const gchar *mime_type, - gchar **parents, - guint max_parents); -static GList *thunar_vfs_mime_legacy_get_stop_characters (ThunarVfsMimeProvider *provider); -static gsize thunar_vfs_mime_legacy_get_max_buffer_extents (ThunarVfsMimeProvider *provider); -static void thunar_vfs_mime_legacy_parse_aliases (ThunarVfsMimeLegacy *legacy, - const gchar *directory); -static gboolean thunar_vfs_mime_legacy_parse_globs (ThunarVfsMimeLegacy *legacy, - const gchar *directory); -static void thunar_vfs_mime_legacy_parse_subclasses (ThunarVfsMimeLegacy *legacy, - const gchar *directory); -static void thunar_vfs_mime_legacy_parse_magic (ThunarVfsMimeLegacy *legacy, - const gchar *directory); -static ThunarVfsMimeLegacyMagic thunar_vfs_mime_legacy_parse_magic_header (ThunarVfsMimeLegacy *legacy, - ThunarVfsMimeLegacyMatch *match, - FILE *fp); -static ThunarVfsMimeLegacyMagic thunar_vfs_mime_legacy_parse_magic_line (ThunarVfsMimeLegacy *legacy, - ThunarVfsMimeLegacyMatch *match, - FILE *fp); - - - -struct _ThunarVfsMimeLegacyClass -{ - ThunarVfsMimeProviderClass __parent__; -}; - -struct _ThunarVfsMimeLegacy -{ - ThunarVfsMimeProvider __parent__; - - GStringChunk *string_chunk; - GMemChunk *suffix_chunk; - GMemChunk *glob_chunk; - GMemChunk *match_chunk; - GMemChunk *matchlet_chunk; - - GHashTable *literals; - ThunarVfsMimeLegacySuffix *suffixes; - GList *globs; - - GHashTable *aliases; - GHashTable *parents; - - GList *matches; - gsize max_buffer_extents; -}; - -struct _ThunarVfsMimeLegacyGlob -{ - const gchar *pattern; - const gchar *mime_type; -}; - -struct _ThunarVfsMimeLegacySuffix -{ - ThunarVfsMimeLegacySuffix *child; - ThunarVfsMimeLegacySuffix *next; - const gchar *mime_type; - gunichar character; -}; - -struct _ThunarVfsMimeLegacyMatch -{ - const gchar *mime_type; - gint priority; - GList *matchlets; -}; - -struct _ThunarVfsMimeLegacyMatchlet -{ - gint indent; - gint offset; - gint value_length; - guchar *value; - guchar *mask; - glong range_length; - guint word_size; -}; - -enum _ThunarVfsMimeLegacyMagic -{ - THUNAR_VFS_MIME_LEGACY_MAGIC_SECTION, - THUNAR_VFS_MIME_LEGACY_MAGIC_MAGIC, - THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR, - THUNAR_VFS_MIME_LEGACY_MAGIC_EOF, -}; - - - -static GObjectClass *thunar_vfs_mime_legacy_parent_class; - - - -GType -thunar_vfs_mime_legacy_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_MIME_PROVIDER, - "ThunarVfsMimeLegacy", - sizeof (ThunarVfsMimeLegacyClass), - thunar_vfs_mime_legacy_class_init, - sizeof (ThunarVfsMimeLegacy), - thunar_vfs_mime_legacy_init, - 0); - } - - return type; -} - - - -static void -thunar_vfs_mime_legacy_class_init (ThunarVfsMimeLegacyClass *klass) -{ - ThunarVfsMimeProviderClass *thunarvfs_mime_provider_class; - GObjectClass *gobject_class; - - thunar_vfs_mime_legacy_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_mime_legacy_finalize; - - thunarvfs_mime_provider_class = THUNAR_VFS_MIME_PROVIDER_CLASS (klass); - thunarvfs_mime_provider_class->lookup_data = thunar_vfs_mime_legacy_lookup_data; - thunarvfs_mime_provider_class->lookup_literal = thunar_vfs_mime_legacy_lookup_literal; - thunarvfs_mime_provider_class->lookup_suffix = thunar_vfs_mime_legacy_lookup_suffix; - thunarvfs_mime_provider_class->lookup_glob = thunar_vfs_mime_legacy_lookup_glob; - thunarvfs_mime_provider_class->lookup_alias = thunar_vfs_mime_legacy_lookup_alias; - thunarvfs_mime_provider_class->lookup_parents = thunar_vfs_mime_legacy_lookup_parents; - thunarvfs_mime_provider_class->get_stop_characters = thunar_vfs_mime_legacy_get_stop_characters; - thunarvfs_mime_provider_class->get_max_buffer_extents = thunar_vfs_mime_legacy_get_max_buffer_extents; -} - - - -static void -thunar_vfs_mime_legacy_init (ThunarVfsMimeLegacy *legacy) -{ - legacy->string_chunk = g_string_chunk_new (1024); - legacy->glob_chunk = g_mem_chunk_create (ThunarVfsMimeLegacyGlob, 32, G_ALLOC_ONLY); - legacy->suffix_chunk = g_mem_chunk_create (ThunarVfsMimeLegacySuffix, 128, G_ALLOC_ONLY); - legacy->match_chunk = g_mem_chunk_create (ThunarVfsMimeLegacyMatch, 16, G_ALLOC_ONLY); - legacy->matchlet_chunk = g_mem_chunk_create (ThunarVfsMimeLegacyMatchlet, 32, G_ALLOC_ONLY); - - legacy->literals = g_hash_table_new (g_str_hash, g_str_equal); - - legacy->aliases = g_hash_table_new (g_str_hash, g_str_equal); - legacy->parents = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_list_free); -} - - - -static void -thunar_vfs_mime_legacy_finalize (GObject *object) -{ - ThunarVfsMimeLegacy *legacy = THUNAR_VFS_MIME_LEGACY (object); - GList *lp; - - /* free match and matchlet lists */ - for (lp = legacy->matches; lp != NULL; lp = lp->next) - g_list_free (THUNAR_VFS_MIME_LEGACY_MATCH (lp->data)->matchlets); - g_list_free (legacy->matches); - - /* free parents hash table */ - g_hash_table_destroy (legacy->parents); - - /* free aliases hash table */ - g_hash_table_destroy (legacy->aliases); - - /* free the list of globs */ - g_list_free (legacy->globs); - - /* free literals hash table */ - g_hash_table_destroy (legacy->literals); - - /* free chunks */ - g_string_chunk_free (legacy->string_chunk); - g_mem_chunk_destroy (legacy->suffix_chunk); - g_mem_chunk_destroy (legacy->glob_chunk); - g_mem_chunk_destroy (legacy->match_chunk); - g_mem_chunk_destroy (legacy->matchlet_chunk); - - (*G_OBJECT_CLASS (thunar_vfs_mime_legacy_parent_class)->finalize) (object); -} - - - -static gboolean -tvml_matchlet_compare_to_data (ThunarVfsMimeLegacyMatchlet *matchlet, - gconstpointer data, - gsize length) -{ - gboolean valid_matchlet; - gint i, j; - - for (i = matchlet->offset; i < matchlet->offset + matchlet->range_length; i++) - { - valid_matchlet = TRUE; - - if (i + matchlet->value_length > (gint) length) - return FALSE; - - if (matchlet->mask) - { - for (j = 0; j < matchlet->value_length; j++) - if ((matchlet->value[j] & matchlet->mask[j]) != ((((const guchar *) data)[j + i]) & matchlet->mask[j])) - { - valid_matchlet = FALSE; - break; - } - } - else - { - for (j = 0; j < matchlet->value_length; j++) - if (matchlet->value[j] != ((const guchar *) data)[j + i]) - { - valid_matchlet = FALSE; - break; - } - } - - if (valid_matchlet) - return TRUE; - } - - return FALSE; -} - - - -static gboolean -tvml_matchlet_compare_level (GList *matchlet_list, - gconstpointer data, - gsize length, - gint indent) -{ - while (matchlet_list != NULL && THUNAR_VFS_MIME_LEGACY_MATCHLET (matchlet_list->data)->indent == indent) - { - if (tvml_matchlet_compare_to_data (matchlet_list->data, data, length)) - { - if (matchlet_list->next == NULL || THUNAR_VFS_MIME_LEGACY_MATCHLET (matchlet_list->next->data)->indent <= indent) - return TRUE; - - if (tvml_matchlet_compare_level (matchlet_list->next, data, length, indent + 1)) - return TRUE; - } - - do - { - matchlet_list = matchlet_list->next; - } - while (matchlet_list != NULL && THUNAR_VFS_MIME_LEGACY_MATCHLET (matchlet_list->data)->indent > indent); - } - - return FALSE; -} - - - -static const gchar* -thunar_vfs_mime_legacy_lookup_data (ThunarVfsMimeProvider *provider, - gconstpointer data, - gsize length, - gint *priority) -{ - ThunarVfsMimeLegacy *legacy = THUNAR_VFS_MIME_LEGACY (provider); - GList *lp; - - for (lp = legacy->matches; lp != NULL; lp = lp->next) - if (tvml_matchlet_compare_level (THUNAR_VFS_MIME_LEGACY_MATCH (lp->data)->matchlets, data, length, 0)) - { - if (G_LIKELY (priority != NULL)) - *priority = THUNAR_VFS_MIME_LEGACY_MATCH (lp->data)->priority; - return THUNAR_VFS_MIME_LEGACY_MATCH (lp->data)->mime_type; - } - - return NULL; -} - - - -static const gchar* -thunar_vfs_mime_legacy_lookup_literal (ThunarVfsMimeProvider *provider, - const gchar *filename) -{ - return g_hash_table_lookup (THUNAR_VFS_MIME_LEGACY (provider)->literals, filename); -} - - - -static ThunarVfsMimeLegacySuffix* -suffix_insert (ThunarVfsMimeLegacy *legacy, - ThunarVfsMimeLegacySuffix *suffix_node, - const gchar *pattern, - const gchar *mime_type) -{ - ThunarVfsMimeLegacySuffix *previous; - ThunarVfsMimeLegacySuffix *node; - gboolean found_node = FALSE; - gunichar character; - - character = g_utf8_get_char (pattern); - - if (suffix_node == NULL || character < suffix_node->character) - { - node = g_chunk_new0 (ThunarVfsMimeLegacySuffix, legacy->suffix_chunk); - node->next = suffix_node; - node->character = character; - suffix_node = node; - } - else if (character == suffix_node->character) - { - node = suffix_node; - } - else - { - for (previous = suffix_node, node = previous->next; node != NULL; previous = node, node = node->next) - { - if (character < node->character) - { - node = g_chunk_new0 (ThunarVfsMimeLegacySuffix, legacy->suffix_chunk); - node->next = previous->next; - node->character = character; - previous->next = node; - found_node = TRUE; - break; - } - else if (character == node->character) - { - found_node = TRUE; - break; - } - } - - if (!found_node) - { - node = g_chunk_new0 (ThunarVfsMimeLegacySuffix, legacy->suffix_chunk); - node->next = previous->next; - node->character = character; - previous->next = node; - } - } - - pattern = g_utf8_next_char (pattern); - if (G_UNLIKELY (*pattern == '\0')) - node->mime_type = mime_type; - else - node->child = suffix_insert (legacy, node->child, pattern, mime_type); - - return suffix_node; -} - - - -static const gchar* -suffix_lookup (ThunarVfsMimeLegacySuffix *suffix_node, - const gchar *filename, - gboolean ignore_case) -{ - ThunarVfsMimeLegacySuffix *node; - gunichar character; - - if (G_UNLIKELY (suffix_node == NULL)) - return NULL; - - character = g_utf8_get_char (filename); - if (G_UNLIKELY (ignore_case)) - character = g_unichar_tolower (character); - - for (node = suffix_node; node != NULL && character >= node->character; node = node->next) - if (character == node->character) - { - filename = g_utf8_next_char (filename); - if (*filename == '\0') - return node->mime_type; - else - return suffix_lookup (node->child, filename, ignore_case); - } - - return NULL; -} - - - -static const gchar* -thunar_vfs_mime_legacy_lookup_suffix (ThunarVfsMimeProvider *provider, - const gchar *suffix, - gboolean ignore_case) -{ - return suffix_lookup (THUNAR_VFS_MIME_LEGACY (provider)->suffixes, suffix, ignore_case); -} - - - -static const gchar* -thunar_vfs_mime_legacy_lookup_glob (ThunarVfsMimeProvider *provider, - const gchar *filename) -{ - GList *lp; - - for (lp = THUNAR_VFS_MIME_LEGACY (provider)->globs; lp != NULL; lp = lp->next) - if (fnmatch (THUNAR_VFS_MIME_LEGACY_GLOB (lp->data)->pattern, filename, 0) == 0) - return THUNAR_VFS_MIME_LEGACY_GLOB (lp->data)->mime_type; - - return NULL; -} - - - -static const gchar* -thunar_vfs_mime_legacy_lookup_alias (ThunarVfsMimeProvider *provider, - const gchar *alias) -{ - return g_hash_table_lookup (THUNAR_VFS_MIME_LEGACY (provider)->aliases, alias); -} - - - -static guint -thunar_vfs_mime_legacy_lookup_parents (ThunarVfsMimeProvider *provider, - const gchar *mime_type, - gchar **parents, - guint max_parents) -{ - GList *lp; - guint n = 0; - - /* determine the known parents for the MIME-type */ - lp = g_hash_table_lookup (THUNAR_VFS_MIME_LEGACY (provider)->parents, mime_type); - for (; lp != NULL && n < max_parents; lp = lp->next, ++n, ++parents) - *parents = lp->data; - - return n; -} - - - -static GList* -thunar_vfs_mime_legacy_get_stop_characters (ThunarVfsMimeProvider *provider) -{ - ThunarVfsMimeLegacySuffix *node; - GList *stopchars = NULL; - - for (node = THUNAR_VFS_MIME_LEGACY (provider)->suffixes; node != NULL; node = node->next) - if (node->character < 128u) - stopchars = g_list_prepend (stopchars, GUINT_TO_POINTER (node->character)); - - return stopchars; -} - - - -static gsize -thunar_vfs_mime_legacy_get_max_buffer_extents (ThunarVfsMimeProvider *provider) -{ - return THUNAR_VFS_MIME_LEGACY (provider)->max_buffer_extents; -} - - - -static void -thunar_vfs_mime_legacy_parse_aliases (ThunarVfsMimeLegacy *legacy, - const gchar *directory) -{ - gchar line[2048]; - gchar *alias; - gchar *name; - gchar *path; - gchar *lp; - FILE *fp; - - /* try to open the "aliases" file */ - path = g_build_filename (directory, "aliases", NULL); - fp = fopen (path, "r"); - g_free (path); - - /* check if we succeed */ - if (G_UNLIKELY (fp == NULL)) - return; - - /* parse all aliases */ - while (fgets (line, sizeof (line), fp) != NULL) - { - /* skip whitespace/comments */ - for (lp = line; g_ascii_isspace (*lp); ++lp); - if (G_UNLIKELY (*lp == '\0' || *lp == '#')) - continue; - - /* extract the alias name */ - for (alias = lp; *lp != '\0' && !g_ascii_isspace (*lp); ++lp); - if (G_UNLIKELY (*lp == '\0' || alias == lp)) - continue; - *lp++ = '\0'; - - /* skip whitespace */ - for (; G_UNLIKELY (g_ascii_isspace (*lp)); ++lp); - if (G_UNLIKELY (*lp == '\0')) - continue; - - /* extract the MIME-type name */ - for (name = lp; *lp != '\0' && *lp != '\n' && *lp != '\r'; ++lp); - if (G_UNLIKELY (name == lp)) - continue; - *lp = '\0'; - - /* insert the alias into the string chunk */ - alias = g_string_chunk_insert_const (legacy->string_chunk, alias); - - /* insert the MIME-type name into the string chunk */ - name = g_string_chunk_insert_const (legacy->string_chunk, name); - - /* insert the association into the aliases hash table */ - g_hash_table_insert (legacy->aliases, alias, name); - } - - fclose (fp); -} - - - -static gboolean -thunar_vfs_mime_legacy_parse_globs (ThunarVfsMimeLegacy *legacy, - const gchar *directory) -{ - ThunarVfsMimeLegacyGlob *glob; - gchar line[2048]; - gchar *pattern; - gchar *path; - gchar *name; - gchar *lp; - FILE *fp; - - /* try to open the "globs" file */ - path = g_build_filename (directory, "globs", NULL); - fp = fopen (path, "r"); - g_free (path); - - /* cannot continue */ - if (G_UNLIKELY (fp == NULL)) - return FALSE; - - /* parse all globs */ - while (fgets (line, sizeof (line), fp) != NULL) - { - /* skip whitespace/comments */ - for (lp = line; g_ascii_isspace (*lp); ++lp); - if (*lp == '\0' || *lp == '#') - continue; - - /* extract the MIME-type name */ - for (name = lp; *lp != '\0' && *lp != ':'; ++lp); - if (*lp == '\0' || name == lp) - continue; - - /* extract the pattern */ - for (*lp = '\0', pattern = ++lp; *lp != '\0' && *lp != '\n' && *lp != '\r'; ++lp); - *lp = '\0'; - if (*pattern == '\0') - continue; - - /* insert the name into the string chunk */ - name = g_string_chunk_insert_const (legacy->string_chunk, name); - - /* determine the type of the pattern */ - if (strpbrk (pattern, "*?[") == NULL) - { - g_hash_table_insert (legacy->literals, g_string_chunk_insert (legacy->string_chunk, pattern), name); - } - else if (pattern[0] == '*' && pattern[1] == '.' && strpbrk (pattern + 2, "*?[") == NULL) - { - legacy->suffixes = suffix_insert (legacy, legacy->suffixes, pattern + 1, name); - } - else - { - glob = g_chunk_new (ThunarVfsMimeLegacyGlob, legacy->glob_chunk); - glob->pattern = g_string_chunk_insert (legacy->string_chunk, pattern); - glob->mime_type = name; - legacy->globs = g_list_append (legacy->globs, glob); - } - } - - fclose (fp); - - return TRUE; -} - - - -static void -thunar_vfs_mime_legacy_parse_subclasses (ThunarVfsMimeLegacy *legacy, - const gchar *directory) -{ - gchar line[2048]; - GList *parents; - gchar *subclass; - gchar *name; - gchar *path; - gchar *lp; - FILE *fp; - - /* try to open the "subclasses" file */ - path = g_build_filename (directory, "subclasses", NULL); - fp = fopen (path, "r"); - g_free (path); - - /* check if we succeed */ - if (G_UNLIKELY (fp == NULL)) - return; - - /* parse all subclasses */ - while (fgets (line, sizeof (line), fp) != NULL) - { - /* skip whitespace/comments */ - for (lp = line; g_ascii_isspace (*lp); ++lp); - if (G_UNLIKELY (*lp == '\0' || *lp == '#')) - continue; - - /* extract the subclass name */ - for (subclass = lp; *lp != '\0' && !g_ascii_isspace (*lp); ++lp); - if (G_UNLIKELY (*lp == '\0' || subclass == lp)) - continue; - *lp++ = '\0'; - - /* skip whitespace */ - for (; G_UNLIKELY (g_ascii_isspace (*lp)); ++lp); - if (G_UNLIKELY (*lp == '\0')) - continue; - - /* extract the MIME-type name */ - for (name = lp; *lp != '\0' && *lp != '\n' && *lp != '\r'; ++lp); - if (G_UNLIKELY (name == lp)) - continue; - *lp = '\0'; - - /* insert the subclass into the string chunk */ - subclass = g_string_chunk_insert_const (legacy->string_chunk, subclass); - - /* insert the MIME-type name into the string chunk */ - name = g_string_chunk_insert_const (legacy->string_chunk, name); - - /* add the MIME-type name to the list of parents for the subclass */ - parents = g_hash_table_lookup (legacy->parents, subclass); - if (G_UNLIKELY (parents != NULL)) - parents = g_list_copy (parents); - parents = g_list_append (parents, name); - g_hash_table_insert (legacy->parents, subclass, parents); - } - - fclose (fp); -} - - - -static gint -thunar_vfs_mime_legacy_match_compare (gconstpointer a, - gconstpointer b) -{ - return (-1) * (THUNAR_VFS_MIME_LEGACY_MATCH (a)->priority - THUNAR_VFS_MIME_LEGACY_MATCH (b)->priority); -} - - - -static void -thunar_vfs_mime_legacy_parse_magic (ThunarVfsMimeLegacy *legacy, - const gchar *directory) -{ - ThunarVfsMimeLegacyMatch *match = NULL; - ThunarVfsMimeLegacyMagic state; - gchar header[12]; - gchar *path; - GList *lp; - FILE *fp; - gint c; - gint n; - - /* try to open the "magic" file */ - path = g_build_filename (directory, "magic", NULL); - fp = fopen (path, "r"); - g_free (path); - - /* check if we succeed */ - if (G_UNLIKELY (fp == NULL)) - return; - - /* check the header */ - if (fread (header, 1, 12, fp) == 12 && memcmp ("MIME-Magic\0\n", header, 12) == 0) - { - /* parse the file */ - for (state = THUNAR_VFS_MIME_LEGACY_MAGIC_SECTION; state != THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; ) - { - switch (state) - { - case THUNAR_VFS_MIME_LEGACY_MAGIC_SECTION: - match = g_chunk_new0 (ThunarVfsMimeLegacyMatch, legacy->match_chunk); - state = thunar_vfs_mime_legacy_parse_magic_header (legacy, match, fp); - if (state == THUNAR_VFS_MIME_LEGACY_MAGIC_EOF || state == THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR) - match = NULL; - break; - - case THUNAR_VFS_MIME_LEGACY_MAGIC_MAGIC: - state = thunar_vfs_mime_legacy_parse_magic_line (legacy, match, fp); - if ((state == THUNAR_VFS_MIME_LEGACY_MAGIC_EOF && match->mime_type != NULL) - || (state == THUNAR_VFS_MIME_LEGACY_MAGIC_SECTION)) - { - /* determine new max buffer extents */ - for (lp = match->matchlets; lp != NULL; lp = lp->next) - { - /* calculate matchlet extent */ - n = THUNAR_VFS_MIME_LEGACY_MATCHLET (lp->data)->value_length - + THUNAR_VFS_MIME_LEGACY_MATCHLET (lp->data)->range_length - + THUNAR_VFS_MIME_LEGACY_MATCHLET (lp->data)->offset; - - /* check if new max */ - if (n > (gint) legacy->max_buffer_extents) - legacy->max_buffer_extents = n; - } - - /* add to internal match list */ - legacy->matches = g_list_insert_sorted (legacy->matches, match, thunar_vfs_mime_legacy_match_compare); - } - else if (state == THUNAR_VFS_MIME_LEGACY_MAGIC_EOF || state == THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR) - match = NULL; - break; - - case THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR: - for (;;) - { - c = getc_unlocked (fp); - if (c == EOF) - { - state = THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - break; - } - else if (c == '\n') - { - state = THUNAR_VFS_MIME_LEGACY_MAGIC_SECTION; - break; - } - } - break; - - default: - /* should never be reached */ - g_assert_not_reached (); - } - } - } - - /* close the file */ - fclose (fp); -} - - - -/* Reads in a hunk of data until a newline character or a '\000' is hit. The - * returned string is null terminated, and doesn't include the newline. - */ -static guchar* -tvml_read_to_newline (FILE *fp, - gboolean *eof) -{ - guchar *retval; - gint len = 128; - gint pos = 0; - gint c; - - retval = g_malloc (len); - *eof = FALSE; - - for (;;) - { - c = getc_unlocked (fp); - if (c == EOF) - { - *eof = TRUE; - break; - } - else if (c == '\n' || c == '\0') - break; - - retval[pos++] = (guchar) c; - if (pos % 128 == 127) - { - len = len + 128; - retval = g_realloc (retval, len); - } - } - - retval[pos] = '\0'; - return retval; -} - - - -/* Returns the number read from the file, or -1 if no number could be read. - */ -static glong -tvml_read_a_number (FILE *fp, - gboolean *eof) -{ - gchar number_string[64]; - glong retval = -1; - gint pos = 0; - gint c; - - *eof = FALSE; - - for (;;) - { - c = getc_unlocked (fp); - if (c == EOF) - { - *eof = TRUE; - break; - } - else if (!g_ascii_isdigit (c)) - { - ungetc (c, fp); - break; - } - - number_string[pos] = (gchar) c; - pos++; - if (pos == sizeof (number_string) - 1) - break; - } - - if (G_LIKELY (pos > 0)) - { - number_string[pos] = '\0'; - errno = 0; - retval = strtol (number_string, NULL, 10); - - if ((retval < INT_MIN) || (retval > INT_MAX) || (errno != 0)) - return -1; - } - - return retval; -} - - - -static ThunarVfsMimeLegacyMagic -thunar_vfs_mime_legacy_parse_magic_header (ThunarVfsMimeLegacy *legacy, - ThunarVfsMimeLegacyMatch *match, - FILE *fp) -{ - /* Headers are of the format: - * [<priority>:<mime-type>] - */ - - gboolean eof = FALSE; - gchar *buffer; - gchar *bp; - gint c; - - c = getc_unlocked (fp); - if (c == EOF) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - else if (c != '[') - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - - match->priority = tvml_read_a_number (fp, &eof); - if (G_UNLIKELY (eof)) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - else if (match->priority == -1) - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - - c = getc_unlocked (fp); - if (c == EOF) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - else if (c != ':') - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - - buffer = (gchar *) tvml_read_to_newline (fp, &eof); - if (G_UNLIKELY (eof)) - { - g_free (buffer); - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - } - - for (bp = buffer; *bp != ']' && *bp != '\0' && *bp != '\n'; ++bp) - ; - if (*bp != ']') - { - g_free (buffer); - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - } - *bp = '\0'; - - match->mime_type = g_string_chunk_insert_const (legacy->string_chunk, buffer); - g_free (buffer); - - return THUNAR_VFS_MIME_LEGACY_MAGIC_MAGIC; -} - - - -static ThunarVfsMimeLegacyMagic -thunar_vfs_mime_legacy_parse_magic_line (ThunarVfsMimeLegacy *legacy, - ThunarVfsMimeLegacyMatch *match, - FILE *fp) -{ - /* Lines are of the format: - * [ indent ] ">" start-offset "=" value - * [ "&" mask ] [ "~" word-size ] [ "+" range-length ] "\n" - */ - - ThunarVfsMimeLegacyMatchlet *matchlet; - gboolean eof = FALSE; - gchar *buffer; - gint bytes_read; - gint indent = 0; - gint c, i; - - /* sniff the buffer to make sure it's a valid line */ - c = getc_unlocked (fp); - if (c == EOF) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - else if (c == '[') - { - ungetc (c, fp); - return THUNAR_VFS_MIME_LEGACY_MAGIC_SECTION; - } - else if (c == '\n') - return THUNAR_VFS_MIME_LEGACY_MAGIC_MAGIC; - - /* At this point, it must be a digit or a '>' */ - if (g_ascii_isdigit (c)) - { - ungetc (c, fp); - indent = tvml_read_a_number (fp, &eof); - if (G_UNLIKELY (eof)) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - else if (G_UNLIKELY (indent == -1)) - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - c = getc_unlocked (fp); - if (c == EOF) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - } - - if (c != '>') - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - - matchlet = g_chunk_new0 (ThunarVfsMimeLegacyMatchlet, legacy->matchlet_chunk); - matchlet->indent = indent; - matchlet->range_length = 1; - matchlet->word_size = 1; - matchlet->offset = tvml_read_a_number (fp, &eof); - - if (G_UNLIKELY (eof)) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - else if (matchlet->offset == -1) - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - - c = getc_unlocked (fp); - if (c == EOF) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - else if (c != '=') - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - - /* Next two bytes determine how long the value is */ - c = getc_unlocked (fp); - if (c == EOF) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - matchlet->value_length = (c & 0xFF) << 8; - - c = getc_unlocked (fp); - if (c == EOF) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - matchlet->value_length += (c & 0xFF); - - buffer = g_alloca (matchlet->value_length); - bytes_read = fread (buffer, 1, matchlet->value_length, fp); - if (bytes_read != matchlet->value_length) - return feof (fp) ? THUNAR_VFS_MIME_LEGACY_MAGIC_EOF : THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - matchlet->value = (guchar *) g_string_chunk_insert_len (legacy->string_chunk, buffer, matchlet->value_length); - - c = getc_unlocked (fp); - if (c == '&') - { - /* reuse previously allocated buffer, as it's also value_length size */ - bytes_read = fread (buffer, 1, matchlet->value_length, fp); - if (bytes_read != matchlet->value_length) - return feof (fp) ? THUNAR_VFS_MIME_LEGACY_MAGIC_EOF : THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - - matchlet->mask = (guchar *) g_string_chunk_insert_len (legacy->string_chunk, buffer, matchlet->value_length); - - c = getc_unlocked (fp); - } - - if (c == '~') - { - matchlet->word_size = tvml_read_a_number (fp, &eof); - if (G_UNLIKELY (eof)) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - if (matchlet->word_size != 0 && matchlet->word_size != 1 && matchlet->word_size != 2 && matchlet->word_size != 4) - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - c = getc_unlocked (fp); - } - - if (c == '+') - { - matchlet->range_length = tvml_read_a_number (fp, &eof); - if (G_UNLIKELY (eof)) - return THUNAR_VFS_MIME_LEGACY_MAGIC_EOF; - else if (matchlet->range_length == -1) - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - c = getc_unlocked (fp); - } - - if (c == '\n') - { - /* We clean up the matchlet, byte swapping if needed */ - if (matchlet->word_size > 1) - { - if (matchlet->value_length % matchlet->word_size != 0) - return THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; - - if (G_BYTE_ORDER != G_BIG_ENDIAN) - { - for (i = 0; i < matchlet->value_length; i += matchlet->word_size) - { - if (matchlet->word_size == 2) - *((guint16 *) matchlet->value + i) = GUINT16_FROM_BE (*((guint16 *) (matchlet->value + i))); - else if (matchlet->word_size == 4) - *((guint32 *) matchlet->value + i) = GUINT32_FROM_BE (*((guint32 *) (matchlet->value + i))); - if (matchlet->mask) - { - if (matchlet->word_size == 2) - *((guint16 *) matchlet->mask + i) = GUINT16_FROM_BE (*((guint16 *) (matchlet->mask + i))); - else if (matchlet->word_size == 4) - *((guint32 *) matchlet->mask + i) = GUINT32_FROM_BE (*((guint32 *) (matchlet->mask + i))); - - } - } - } - } - - match->matchlets = g_list_append (match->matchlets, matchlet); - - return THUNAR_VFS_MIME_LEGACY_MAGIC_MAGIC; - } - - return (c == EOF) ? THUNAR_VFS_MIME_LEGACY_MAGIC_EOF : THUNAR_VFS_MIME_LEGACY_MAGIC_ERROR; -} - - - -/** - * thunar_vfs_mime_legacy_new: - * @directory : an XDG mime base directory. - * - * Allocates a new #ThunarVfsMimeLegacy for @directory and - * returns the instance on success, or %NULL on error. - * - * The caller is responsible to free the returned instance - * using g_object_unref(). - * - * Return value: the newly allocated #ThunarVfsMimeLegacy - * instance or %NULL on error. - **/ -ThunarVfsMimeProvider* -thunar_vfs_mime_legacy_new (const gchar *directory) -{ - ThunarVfsMimeLegacy *legacy; - - /* allocate the new object */ - legacy = g_object_new (THUNAR_VFS_TYPE_MIME_LEGACY, NULL); - - /* try to parse the globs file */ - if (!thunar_vfs_mime_legacy_parse_globs (legacy, directory)) - { - g_object_unref (legacy); - return NULL; - } - - /* parse the aliases file (optional) */ - thunar_vfs_mime_legacy_parse_aliases (legacy, directory); - - /* parse the subclasses file (optional) */ - thunar_vfs_mime_legacy_parse_subclasses (legacy, directory); - - /* parse the magic file (optional) */ - thunar_vfs_mime_legacy_parse_magic (legacy, directory); - - /* we got it */ - return THUNAR_VFS_MIME_PROVIDER (legacy); -} - - - -#define __THUNAR_VFS_MIME_LEGACY_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-mime-legacy.h b/thunar-vfs/thunar-vfs-mime-legacy.h deleted file mode 100644 index c30cb1780..000000000 --- a/thunar-vfs/thunar-vfs-mime-legacy.h +++ /dev/null @@ -1,44 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_MIME_LEGACY_H__ -#define __THUNAR_VFS_MIME_LEGACY_H__ - -#include <thunar-vfs/thunar-vfs-mime-provider.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsMimeLegacyClass ThunarVfsMimeLegacyClass; -typedef struct _ThunarVfsMimeLegacy ThunarVfsMimeLegacy; - -#define THUNAR_VFS_TYPE_MIME_LEGACY (thunar_vfs_mime_legacy_get_type ()) -#define THUNAR_VFS_MIME_LEGACY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_MIME_LEGACY, ThunarVfsMimeLegacy)) -#define THUNAR_VFS_MIME_LEGACY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_MIME_LEGACY, ThunarVfsMimeLegacyClass)) -#define THUNAR_VFS_IS_MIME_LEGACY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_MIME_LEGACY)) -#define THUNAR_VFS_IS_MIME_LEGACY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_MIME_LEGACY)) -#define THUNAR_VFS_MIME_LEGACY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_MIME_LEGACY, ThunarVfsMimeLegacyClass)) - -GType thunar_vfs_mime_legacy_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - -ThunarVfsMimeProvider *thunar_vfs_mime_legacy_new (const gchar *directory) G_GNUC_INTERNAL G_GNUC_MALLOC; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_LEGACY_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-parser.c b/thunar-vfs/thunar-vfs-mime-parser.c deleted file mode 100644 index a28b7df00..000000000 --- a/thunar-vfs/thunar-vfs-mime-parser.c +++ /dev/null @@ -1,257 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_LOCALE_H -#include <locale.h> -#endif - -#include <thunar-vfs/thunar-vfs-mime-parser.h> - - - -typedef enum -{ - PARSER_STATE_START, - PARSER_STATE_MIMETYPE, - PARSER_STATE_COMMENT, - PARSER_STATE_UNKNOWN, -} ParserState; - -typedef XFCE_GENERIC_STACK(ParserState) ParserStateStack; - -typedef struct -{ - ParserStateStack *stack; - guint comment_match; - gboolean comment_use; - GString *comment; - const gchar *locale; -} Parser; - - - -static void start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); - - - -static GMarkupParser markup_parser = -{ - start_element_handler, - end_element_handler, - text_handler, - NULL, - NULL, -}; - - - -static void -start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - Parser *parser = (Parser *) user_data; - guint match; - guint n; - - switch (xfce_stack_top (parser->stack)) - { - case PARSER_STATE_START: - if (exo_str_is_equal (element_name, "mime-type")) - { - xfce_stack_push (parser->stack, PARSER_STATE_MIMETYPE); - } - else - goto unknown_element; - break; - - case PARSER_STATE_MIMETYPE: - if (exo_str_is_equal (element_name, "comment")) - { - for (n = 0; attribute_names[n] != NULL; ++n) - if (exo_str_is_equal (attribute_names[n], "xml:lang")) - break; - - if (G_UNLIKELY (attribute_names[n] == NULL)) - { - parser->comment_use = (parser->comment_match <= XFCE_LOCALE_NO_MATCH); - } - else - { - match = xfce_locale_match (parser->locale, attribute_values[n]); - if (parser->comment_match < match) - { - parser->comment_match = match; - parser->comment_use = TRUE; - } - else - { - parser->comment_use = FALSE; - } - } - - if (parser->comment_use) - g_string_truncate (parser->comment, 0); - - xfce_stack_push (parser->stack, PARSER_STATE_COMMENT); - } - else - xfce_stack_push (parser->stack, PARSER_STATE_UNKNOWN); - break; - - default: - xfce_stack_push (parser->stack, PARSER_STATE_UNKNOWN); - break; - } - - return; - -unknown_element: - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Unknown element <%s>", element_name); - return; -} - - - -static void -end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - Parser *parser = (Parser *) user_data; - - switch (xfce_stack_top (parser->stack)) - { - case PARSER_STATE_START: - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "End element handler called while in root context"); - return; - - case PARSER_STATE_MIMETYPE: - if (!exo_str_is_equal (element_name, "mime-type")) - goto unknown_element; - break; - - case PARSER_STATE_COMMENT: - if (!exo_str_is_equal (element_name, "comment")) - goto unknown_element; - break; - - default: - break; - } - - xfce_stack_pop (parser->stack); - return; - -unknown_element: - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Unknown closing element <%s>", element_name); - return; -} - - - -static void -text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - Parser *parser = (Parser *) user_data; - - switch (xfce_stack_top (parser->stack)) - { - case PARSER_STATE_COMMENT: - if (parser->comment_use) - g_string_append_len (parser->comment, text, text_len); - break; - - default: - break; - } -} - - - -gchar* -_thunar_vfs_mime_parser_load_comment_from_file (const gchar *filename, - GError **error) -{ - GMarkupParseContext *context; - Parser parser; - gchar *content; - gsize content_len; - gboolean comment_free = TRUE; - gchar *comment = NULL; - - if (!g_file_get_contents (filename, &content, &content_len, error)) - return NULL; - - parser.comment_match = XFCE_LOCALE_NO_MATCH; - parser.comment = g_string_new (""); - parser.locale = setlocale (LC_MESSAGES, NULL); - - parser.stack = xfce_stack_new (ParserStateStack); - xfce_stack_push (parser.stack, PARSER_STATE_START); - - context = g_markup_parse_context_new (&markup_parser, 0, &parser, NULL); - - if (!g_markup_parse_context_parse (context, content, content_len, error)) - goto done; - - if (!g_markup_parse_context_end_parse (context, error)) - goto done; - - comment = parser.comment->str; - comment_free = FALSE; - -done: - g_markup_parse_context_free (context); - g_string_free (parser.comment, comment_free); - xfce_stack_free (parser.stack); - g_free (content); - - return comment; -} diff --git a/thunar-vfs/thunar-vfs-mime-parser.h b/thunar-vfs/thunar-vfs-mime-parser.h deleted file mode 100644 index 5b2de70bf..000000000 --- a/thunar-vfs/thunar-vfs-mime-parser.h +++ /dev/null @@ -1,33 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_MIME_PARSER_H__ -#define __THUNAR_VFS_MIME_PARSER_H__ - -#include <thunar-vfs/thunar-vfs-config.h> - -G_BEGIN_DECLS; - -gchar *_thunar_vfs_mime_parser_load_comment_from_file (const gchar *filename, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_PARSER_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-provider.c b/thunar-vfs/thunar-vfs-mime-provider.c deleted file mode 100644 index 96d431af1..000000000 --- a/thunar-vfs/thunar-vfs-mime-provider.c +++ /dev/null @@ -1,60 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <thunar-vfs/thunar-vfs-mime-provider.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -GType -thunar_vfs_mime_provider_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - static const GTypeInfo info = - { - sizeof (ThunarVfsMimeProviderClass), - NULL, - NULL, - NULL, - NULL, - NULL, - sizeof (ThunarVfsMimeProvider), - 0, - NULL, - NULL, - }; - - type = g_type_register_static (G_TYPE_OBJECT, I_("ThunarVfsMimeProvider"), &info, G_TYPE_FLAG_ABSTRACT); - } - - return type; -} - - - -#define __THUNAR_VFS_MIME_PROVIDER_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-mime-provider.h b/thunar-vfs/thunar-vfs-mime-provider.h deleted file mode 100644 index 9f8c0d5d2..000000000 --- a/thunar-vfs/thunar-vfs-mime-provider.h +++ /dev/null @@ -1,210 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_MIME_PROVIDER_H__ -#define __THUNAR_VFS_MIME_PROVIDER_H__ - -#include <exo/exo.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsMimeProviderClass ThunarVfsMimeProviderClass; -typedef struct _ThunarVfsMimeProvider ThunarVfsMimeProvider; - -#define THUNAR_VFS_TYPE_MIME_PROVIDER (thunar_vfs_mime_provider_get_type ()) -#define THUNAR_VFS_MIME_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_MIME_PROVIDER, ThunarVfsMimeProvider)) -#define THUNAR_VFS_MIME_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_MIME_PROVIDER, ThunarVfsMimeProviderClass)) -#define THUNAR_VFS_IS_MIME_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_MIME_PROVIDER)) -#define THUNAR_VFS_IS_MIME_PROVIDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_MIME_PROVIDER)) -#define THUNAR_VFS_MIME_PROVIDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_MIME_PROVIDER, ThunarVfsMimeProviderClass)) - -struct _ThunarVfsMimeProviderClass -{ - GObjectClass __parent__; - - const gchar *(*lookup_data) (ThunarVfsMimeProvider *provider, - gconstpointer data, - gsize length, - gint *priority); - - const gchar *(*lookup_literal) (ThunarVfsMimeProvider *provider, - const gchar *filename); - const gchar *(*lookup_suffix) (ThunarVfsMimeProvider *provider, - const gchar *suffix, - gboolean ignore_case); - const gchar *(*lookup_glob) (ThunarVfsMimeProvider *provider, - const gchar *filename); - - const gchar *(*lookup_alias) (ThunarVfsMimeProvider *provider, - const gchar *alias); - - guint (*lookup_parents) (ThunarVfsMimeProvider *provider, - const gchar *mime_type, - gchar **parents, - guint max_parents); - - GList *(*get_stop_characters) (ThunarVfsMimeProvider *provider); - gsize (*get_max_buffer_extents) (ThunarVfsMimeProvider *provider); -}; - -struct _ThunarVfsMimeProvider -{ - GObject __parent__; -}; - -GType thunar_vfs_mime_provider_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - -/** - * thunar_vfs_mime_provider_lookup_data: - * @provider : a #ThunarVfsMimeProvider. - * @data : pointer to the data. - * @length : length of @data in bytes. - * @priority : return location for the priority or %NULL. - * - * The location pointed to by @priority (if not %NULL) will only - * be set to a meaningfull value if this method returns a - * non-%NULL value. - * - * Return value: a pointer to the MIME type or %NULL. - **/ -static inline const gchar* -thunar_vfs_mime_provider_lookup_data (ThunarVfsMimeProvider *provider, - gconstpointer data, - gsize length, - gint *priority) -{ - return (*THUNAR_VFS_MIME_PROVIDER_GET_CLASS (provider)->lookup_data) (provider, data, length, priority); -} - -/** - * thunar_vfs_mime_provider_lookup_literal: - * @provider : a #ThunarVfsMimeProvider. - * @filename : a filename. - * - * Return value: a pointer to the MIME type or %NULL. - **/ -static inline const gchar* -thunar_vfs_mime_provider_lookup_literal (ThunarVfsMimeProvider *provider, - const gchar *filename) -{ - return (*THUNAR_VFS_MIME_PROVIDER_GET_CLASS (provider)->lookup_literal) (provider, filename); -} - -/** - * thunar_vfs_mime_provider_lookup_suffix: - * @provider : a #ThunarVfsMimeProvider. - * @suffix : a filename suffix. - * @ignore_case : %TRUE to perform case-insensitive comparison. - * - * Return value: a pointer to the MIME type or %NULL. - **/ -static inline const gchar* -thunar_vfs_mime_provider_lookup_suffix (ThunarVfsMimeProvider *provider, - const gchar *suffix, - gboolean ignore_case) -{ - return (*THUNAR_VFS_MIME_PROVIDER_GET_CLASS (provider)->lookup_suffix) (provider, suffix, ignore_case); -} - -/** - * thunar_vfs_mime_provider_lookup_glob: - * @provider : a #ThunarVfsMimeProvider. - * @filename : a filename. - * - * Return value: a pointer to the MIME type or %NULL. - **/ -static inline const gchar* -thunar_vfs_mime_provider_lookup_glob (ThunarVfsMimeProvider *provider, - const gchar *filename) -{ - return (*THUNAR_VFS_MIME_PROVIDER_GET_CLASS (provider)->lookup_glob) (provider, filename); -} - -/** - * thunar_vfs_mime_provider_lookup_alias: - * @provider : a #ThunarVfsMimeProvider. - * @alias : a valid mime type. - * - * Unaliases the @alias using the alias table found in @provider. - * - * Return value: the unaliased mime type or %NULL if @alias - * is not a valid mime type alias. - */ -static inline const gchar* -thunar_vfs_mime_provider_lookup_alias (ThunarVfsMimeProvider *provider, - const gchar *alias) -{ - return (*THUNAR_VFS_MIME_PROVIDER_GET_CLASS (provider)->lookup_alias) (provider, alias); -} - -/** - * thunar_vfs_mime_provider_lookup_parents: - * @provider : a #ThunarVfsMimeProvider. - * @mime_type : a valid mime type. - * @parents : buffer to store the parents to. - * @max_parents : the maximum number of parents that should be stored to @parents. - * - * Looks up up to @max_parents parent types of @mime_type in @provider and - * stores them to @parents. Returns the list of mime parents. - * - * Return value: the list of mime parents. - **/ -static inline guint -thunar_vfs_mime_provider_lookup_parents (ThunarVfsMimeProvider *provider, - const gchar *mime_type, - gchar **parents, - guint max_parents) -{ - return (*THUNAR_VFS_MIME_PROVIDER_GET_CLASS (provider)->lookup_parents) (provider, mime_type, parents, max_parents); -} - -/** - * thunar_vfs_mime_provider_get_stop_characters: - * @provider : a #ThunarVfsMimeProvider. - * - * Returns the list of stop characters for all suffix entries in @provider as - * a #GList of #gunichar<!---->s. The caller is responsible to free the list - * using g_list_free(). - * - * Return value: the list of stop characters for the suffix entries in @provider. - **/ -static inline GList* -thunar_vfs_mime_provider_get_stop_characters (ThunarVfsMimeProvider *provider) -{ - return (*THUNAR_VFS_MIME_PROVIDER_GET_CLASS (provider)->get_stop_characters) (provider); -} - -/** - * thunar_vfs_mime_provider_get_max_buffer_extents: - * @provider : a #ThunarVfsMimeProvider. - * - * Returns the max buffer extents required for a data lookup in @provider. - * - * Return value: the max buffer extents for @provider. - **/ -static inline gsize -thunar_vfs_mime_provider_get_max_buffer_extents (ThunarVfsMimeProvider *provider) -{ - return (*THUNAR_VFS_MIME_PROVIDER_GET_CLASS (provider)->get_max_buffer_extents) (provider); -} - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_PROVIDER_H__ */ diff --git a/thunar-vfs/thunar-vfs-mime-sniffer.c b/thunar-vfs/thunar-vfs-mime-sniffer.c deleted file mode 100644 index 7bed0d896..000000000 --- a/thunar-vfs/thunar-vfs-mime-sniffer.c +++ /dev/null @@ -1,118 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Based on code initially written by James Youngman <jay@gnu.org> - * and Pavel Cisler <pavel@eazel.com>. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_WCHAR_H -#include <wchar.h> -#endif -#ifdef HAVE_WCTYPE_H -#include <wctype.h> -#endif - -#include <thunar-vfs/thunar-vfs-mime-sniffer.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/** - * thunar_vfs_mime_sniffer_looks_like_text: - * @data : the input data (most probably file content). - * @length : the number of bytes in @data. - * - * Checks whether @data can be considered valid text, e.g. - * valid UTF-8 or valid multi-byte string. If so, %TRUE is - * returned, else %FALSE is returned. - * - * Return value: %TRUE if @data looks like text, else %FALSE. - **/ -gboolean -thunar_vfs_mime_sniffer_looks_like_text (const gchar *data, - gsize length) -{ - const gchar *end; -#ifdef HAVE_MBRTOWC - const gchar *send; - const gchar *src; - mbstate_t ms; - wchar_t wc; - gsize wlen; -#endif - gint remaining; - - /* check if we have valid UTF8 here */ - if (!g_utf8_validate (data, length, &end)) - { - /* Check whether the string was truncated in the middle of a valid - * UTF8 character, or if we really have an invalid UTF8 string. - */ - remaining = length - (end - data); - if (g_utf8_get_char_validated (end, remaining) == (gunichar)-2) - return TRUE; - -#ifdef HAVE_MBRTOWC - /* let's see, maybe we have a valid multi-byte text here */ - memset (&ms, 0, sizeof (ms)); - for (src = data, send = data + length; src < send; src += wlen) - { - /* Don't allow embedded zeros in textfiles */ - if (*src == '\0') - return FALSE; - - /* check for illegal mutli-byte sequence */ - wlen = mbrtowc (&wc, src, send - src, &ms); - if (G_UNLIKELY (wlen == (gsize) (-1))) - return FALSE; - - /* Check for incomplete multi-byte character before - * end. Probably cut off char which is ok. - */ - if (wlen == (gsize) (-2)) - return TRUE; - - /* Don't allow embedded zeros in textfiles */ - if (G_UNLIKELY (wlen == 0)) - return FALSE; - - /* Check for neither printable or whitespace */ - if (!iswspace (wc) && !iswprint (wc)) - return FALSE; - } -#endif - } - - return TRUE; -} - - - -#define __THUNAR_VFS_MIME_SNIFFER_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-mime-sniffer.h b/thunar-vfs/thunar-vfs-mime-sniffer.h deleted file mode 100644 index fedc6f24e..000000000 --- a/thunar-vfs/thunar-vfs-mime-sniffer.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_MIME_SNIFFER_H__ -#define __THUNAR_VFS_MIME_SNIFFER_H__ - -#include <glib.h> - -G_BEGIN_DECLS; - -gboolean thunar_vfs_mime_sniffer_looks_like_text (const gchar *data, - gsize length) G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MIME_SNIFFER_H__ */ diff --git a/thunar-vfs/thunar-vfs-monitor-private.h b/thunar-vfs/thunar-vfs-monitor-private.h deleted file mode 100644 index 7c5e779fb..000000000 --- a/thunar-vfs/thunar-vfs-monitor-private.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_MONITOR_PRIVATE_H__ -#define __THUNAR_VFS_MONITOR_PRIVATE_H__ - -#include <thunar-vfs/thunar-vfs-monitor.h> - -G_BEGIN_DECLS; - -/* shared monitor instance */ -extern ThunarVfsMonitor *_thunar_vfs_monitor G_GNUC_INTERNAL; - -/* internal routines */ -ThunarVfsPath *_thunar_vfs_monitor_handle_get_path (const ThunarVfsMonitorHandle *handle) G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MONITOR_PRIVATE_H__ */ diff --git a/thunar-vfs/thunar-vfs-monitor.c b/thunar-vfs/thunar-vfs-monitor.c deleted file mode 100644 index 6fdccc648..000000000 --- a/thunar-vfs/thunar-vfs-monitor.c +++ /dev/null @@ -1,851 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_FAM_H -#include <fam.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#include <thunar-vfs/thunar-vfs-monitor-private.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/* minimum timer interval for feeded events (in ms) */ -#define THUNAR_VFS_MONITOR_TIMER_INTERVAL_FEED (10) - -/* minimum timer interval for FAM events (in ms) */ -#define THUNAR_VFS_MONITOR_TIMER_INTERVAL_FAM (200) - -/* tagging for notifications, so we can make sure that - * (slow) FAM events don't override properly feeded events. - */ -#define THUNAR_VFS_MONITOR_TAG_FAM (0) -#define THUNAR_VFS_MONITOR_TAG_FEED (1) - - - -typedef struct _ThunarVfsMonitorNotification ThunarVfsMonitorNotification; - - - -static void thunar_vfs_monitor_class_init (ThunarVfsMonitorClass *klass); -static void thunar_vfs_monitor_init (ThunarVfsMonitor *monitor); -static void thunar_vfs_monitor_finalize (GObject *object); -static void thunar_vfs_monitor_queue_notification (ThunarVfsMonitor *monitor, - gint reqnum, - gint tag, - ThunarVfsMonitorEvent event, - const gchar *filename); -static gboolean thunar_vfs_monitor_notifications_timer (gpointer user_data); -#ifdef HAVE_LIBFAM -static void thunar_vfs_monitor_fam_cancel (ThunarVfsMonitor *monitor); -static gboolean thunar_vfs_monitor_fam_process_events (ThunarVfsMonitor *monitor); -static gboolean thunar_vfs_monitor_fam_watch (GIOChannel *channel, - GIOCondition condition, - gpointer user_data); -#endif -static gboolean thunar_vfs_monitor_is_excluded_path (ThunarVfsMonitor *monitor, - ThunarVfsPath *path); - - - -struct _ThunarVfsMonitorClass -{ - GObjectClass __parent__; -}; - -struct _ThunarVfsMonitor -{ - GObject __parent__; - - GSList *handles; - - gint notifications_timer_id; - ThunarVfsMonitorNotification *notifications; - - /* the monitor lock and cond */ - GCond *cond; - GMutex *lock; - - /* the current handle request number */ - gint current_reqnum; - -#ifdef HAVE_LIBFAM - /* FAM/Gamin support */ - FAMConnection fc; - gint fc_watch_id; -#endif -}; - -struct _ThunarVfsMonitorHandle -{ - ThunarVfsMonitorCallback callback; - gpointer user_data; - ThunarVfsPath *path; - guint directory : 1; - -#ifdef HAVE_LIBFAM - FAMRequest fr; -#else - struct - { - gint reqnum; - } fr; -#endif -}; - -struct _ThunarVfsMonitorNotification -{ - gint reqnum; /* the unique request number of the handle */ - gint tag; /* the notification source tag */ - gchar *filename; /* the name/path of the file that changed or NULL if the handle path should be used */ - ThunarVfsMonitorEvent event; /* the type of the event */ - ThunarVfsMonitorNotification *next; /* the pointer to the next notification in the queue */ -}; - - - -static GObjectClass *thunar_vfs_monitor_parent_class; - - - -GType -thunar_vfs_monitor_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsMonitor", - sizeof (ThunarVfsMonitorClass), - thunar_vfs_monitor_class_init, - sizeof (ThunarVfsMonitor), - thunar_vfs_monitor_init, - 0); - } - - return type; -} - - - -static void -thunar_vfs_monitor_class_init (ThunarVfsMonitorClass *klass) -{ - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_monitor_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_monitor_finalize; -} - - - -static void -thunar_vfs_monitor_init (ThunarVfsMonitor *monitor) -{ - /* initialize the monitor */ - monitor->cond = g_cond_new (); - monitor->lock = g_mutex_new (); - -#ifdef HAVE_LIBFAM - if (FAMOpen2 (&monitor->fc, PACKAGE_NAME) == 0) - { - GIOChannel *channel; - - channel = g_io_channel_unix_new (FAMCONNECTION_GETFD (&monitor->fc)); - monitor->fc_watch_id = g_io_add_watch (channel, G_IO_ERR | G_IO_HUP | G_IO_IN, - thunar_vfs_monitor_fam_watch, monitor); - g_io_channel_unref (channel); - -#ifdef HAVE_FAMNOEXISTS - /* luckily gamin offers a way to avoid the FAMExists events */ - FAMNoExists (&monitor->fc); -#endif - } - else - { - monitor->fc_watch_id = -1; - } -#endif -} - - - -static void -thunar_vfs_monitor_finalize (GObject *object) -{ - ThunarVfsMonitorNotification *notification; - ThunarVfsMonitor *monitor = THUNAR_VFS_MONITOR (object); - GSList *lp; - -#ifdef HAVE_LIBFAM - if (monitor->fc_watch_id >= 0) - thunar_vfs_monitor_fam_cancel (monitor); -#endif - - /* drop the notifications timer source */ - if (G_UNLIKELY (monitor->notifications_timer_id != 0)) - g_source_remove (monitor->notifications_timer_id); - - /* drop all pending notifications */ - while (monitor->notifications != NULL) - { - notification = monitor->notifications; - monitor->notifications = notification->next; - g_free (notification); - } - - /* drop all handles */ - for (lp = monitor->handles; lp != NULL; lp = lp->next) - { - /* release the path and the handle memory */ - thunar_vfs_path_unref (((ThunarVfsMonitorHandle *) lp->data)->path); - _thunar_vfs_slice_free (ThunarVfsMonitorHandle, lp->data); - } - g_slist_free (monitor->handles); - - /* release the monitor lock */ - g_mutex_free (monitor->lock); - g_cond_free (monitor->cond); - - (*G_OBJECT_CLASS (thunar_vfs_monitor_parent_class)->finalize) (object); -} - - - -static void -thunar_vfs_monitor_queue_notification (ThunarVfsMonitor *monitor, - gint reqnum, - gint tag, - ThunarVfsMonitorEvent event, - const gchar *filename) -{ - ThunarVfsMonitorNotification *notification; - ThunarVfsMonitorNotification *position; - guint timeout; - gint length; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); - _thunar_vfs_return_if_fail (reqnum > 0 && reqnum <= monitor->current_reqnum); - - /* check if we already have a matching notification */ - for (notification = monitor->notifications; notification != NULL; notification = notification->next) - if (notification->reqnum == reqnum && exo_str_is_equal (filename, notification->filename) && notification->tag == tag && notification->event == event) - return; - - /* allocate a new notification */ - if (G_LIKELY (filename != NULL)) - { - length = strlen (filename); - notification = g_malloc (sizeof (ThunarVfsMonitorNotification) + length + 1); - notification->filename = ((gchar *) notification) + sizeof (ThunarVfsMonitorNotification); - memcpy (notification->filename, filename, length + 1); - } - else - { - notification = g_new (ThunarVfsMonitorNotification, 1); - notification->filename = NULL; - } - - /* prepare the notification */ - notification->reqnum = reqnum; - notification->tag = tag; - notification->event = event; - - /* and append it to the list */ - if (monitor->notifications == NULL) - { - /* we have a new head */ - monitor->notifications = notification; - notification->next = NULL; - } - else - { - /* lookup the position where to insert the notification, making sure that FAM events will be sorted after feeded ones... */ - for (position = monitor->notifications; position->next != NULL && position->tag >= tag; position = position->next) - ; - - /* ...and insert the notification */ - notification->next = position->next; - position->next = notification; - } - - /* schedule the notification timer if not already active */ - if (G_UNLIKELY (monitor->notifications_timer_id == 0)) - { - /* use a shorter timeout for feeded events */ - timeout = (tag == THUNAR_VFS_MONITOR_TAG_FEED) - ? THUNAR_VFS_MONITOR_TIMER_INTERVAL_FEED - : THUNAR_VFS_MONITOR_TIMER_INTERVAL_FAM; - - /* schedule the timer source with the timeout */ - monitor->notifications_timer_id = g_timeout_add (timeout, thunar_vfs_monitor_notifications_timer, monitor); - } -} - - - -static gboolean -thunar_vfs_monitor_notifications_timer (gpointer user_data) -{ - ThunarVfsMonitorNotification *notification; - ThunarVfsMonitorHandle *handle; - ThunarVfsMonitor *monitor = THUNAR_VFS_MONITOR (user_data); - ThunarVfsPath *path; - GSList *lp; - - /* take an additional reference on the monitor, * so we don't accidently - * release the monitor while processing the notifications. - */ - g_object_ref (G_OBJECT (monitor)); - - /* aquire the lock on the monitor */ - g_mutex_lock (monitor->lock); - - /* reset the timer id */ - monitor->notifications_timer_id = 0; - - /* process all pending notifications */ - while (monitor->notifications != NULL) - { - /* grab the first notification from the queue */ - notification = monitor->notifications; - monitor->notifications = notification->next; - - /* lookup the handle for the current notification */ - for (lp = monitor->handles; lp != NULL; lp = lp->next) - if (((ThunarVfsMonitorHandle *) lp->data)->fr.reqnum == notification->reqnum) - break; - - /* check if there's a valid handle */ - if (G_LIKELY (lp != NULL)) - { - /* grab the handle pointer */ - handle = lp->data; - - /* determine the event path for the notification */ - if (G_UNLIKELY (notification->filename == NULL)) - path = thunar_vfs_path_ref (handle->path); - else if (G_UNLIKELY (*notification->filename != '/')) - path = _thunar_vfs_path_child (handle->path, notification->filename); - else - path = thunar_vfs_path_new (notification->filename, NULL); - - /* invoke the callback (w/o the monitor lock) */ - GDK_THREADS_ENTER (); - g_mutex_unlock (monitor->lock); - (*handle->callback) (monitor, handle, notification->event, handle->path, path, handle->user_data); - g_mutex_lock (monitor->lock); - GDK_THREADS_LEAVE (); - - /* cleanup */ - thunar_vfs_path_unref (path); - } - - /* release the current notification */ - g_free (notification); - } - - /* notify all waiting parties */ - g_cond_broadcast (monitor->cond); - - /* release the lock on the monitor */ - g_mutex_unlock (monitor->lock); - - /* drop the additional reference on the monitor */ - g_object_unref (G_OBJECT (monitor)); - - /* drop the timer source */ - return FALSE; -} - - - -#ifdef HAVE_LIBFAM -static void -thunar_vfs_monitor_fam_cancel (ThunarVfsMonitor *monitor) -{ - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); - _thunar_vfs_return_if_fail (monitor->fc_watch_id >= 0); - - /* close the FAM connection */ - FAMClose (&monitor->fc); - - /* remove the I/O watch */ - g_source_remove (monitor->fc_watch_id); - monitor->fc_watch_id = -1; -} - - - -static gboolean -thunar_vfs_monitor_fam_process_events (ThunarVfsMonitor *monitor) -{ - ThunarVfsMonitorEvent event; - FAMEvent fe; - - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_MONITOR (monitor), FALSE); - - /* process all pending FAM events */ - while (FAMPending (&monitor->fc)) - { - /* query the next pending event */ - if (G_UNLIKELY (FAMNextEvent (&monitor->fc, &fe) < 0)) - { - /* terminate the FAM connection */ - thunar_vfs_monitor_fam_cancel (monitor); - - /* thats it, no more FAM */ - return FALSE; - } - - /* translate the event code */ - switch (fe.code) - { - case FAMChanged: - event = THUNAR_VFS_MONITOR_EVENT_CHANGED; - break; - - case FAMCreated: - event = THUNAR_VFS_MONITOR_EVENT_CREATED; - break; - - case FAMDeleted: - event = THUNAR_VFS_MONITOR_EVENT_DELETED; - break; - - default: - /* ignore all other events */ - continue; - } - - /* schedule a notification for the monitor */ - thunar_vfs_monitor_queue_notification (monitor, fe.fr.reqnum, THUNAR_VFS_MONITOR_TAG_FAM, event, fe.filename); - } - - return TRUE; -} - - - -static gboolean -thunar_vfs_monitor_fam_watch (GIOChannel *channel, - GIOCondition condition, - gpointer user_data) -{ - ThunarVfsMonitor *monitor = THUNAR_VFS_MONITOR (user_data); - gboolean result = FALSE; - - /* acquire the monitor lock */ - g_mutex_lock (monitor->lock); - - /* check for an error on the FAM connection */ - if (G_UNLIKELY ((condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) != 0)) - { - /* terminate the FAM connection */ - thunar_vfs_monitor_fam_cancel (monitor); - } - else - { - /* process all pending FAM events */ - result = thunar_vfs_monitor_fam_process_events (monitor); - } - - /* release the monitor lock */ - g_mutex_unlock (monitor->lock); - - return result; -} -#endif - - - -/** - * thunar_vfs_monitor_is_excluded_path: - * @monitor : a #ThunarVfsMonitor. - * @path : a #ThunarVfsPath - * - * Checks whether the path is among the paths to be excluded from - * monitoring. - * - * Return value: %TRUE if @path should be excluded from monitoring, - * %FALSE otherwise. - **/ -static gboolean -thunar_vfs_monitor_is_excluded_path (ThunarVfsMonitor *monitor, - ThunarVfsPath *path) -{ - gboolean excluded = FALSE; - gchar *path_string; - - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_MONITOR (monitor), FALSE); - _thunar_vfs_return_val_if_fail (path != NULL, FALSE); - -#ifdef HAVE_LINUX - /* Turn path into a string */ - path_string = thunar_vfs_path_dup_string (path); - - if (G_LIKELY (path_string != NULL)) - { - /* check if the path is in /proc or /dev */ - if (strncmp (path_string, "/proc/", 6) == 0 - || strncmp (path_string, "/dev/", 5) == 0) - excluded = TRUE; - - /* cleanup */ - g_free (path_string); - } -#endif - - return excluded; -} - - - -/** - * thunar_vfs_monitor_get_default: - * - * Returns the shared #ThunarVfsMonitor instance. The caller - * is responsible to call g_object_unref() on the returned - * object when no longer needed. - * - * Return value: a reference to the shared #ThunarVfsMonitor - * instance. - **/ -ThunarVfsMonitor* -thunar_vfs_monitor_get_default (void) -{ - return g_object_ref (G_OBJECT (_thunar_vfs_monitor)); -} - - - -/** - * thunar_vfs_monitor_add_directory: - * @monitor : a #ThunarVfsMonitor. - * @path : the #ThunarVfsPath of the directory that should be watched. - * @callback : the callback function to invoke. - * @user_data : additional data to pass to @callback. - * - * Registers @path as directory for @monitor. @monitor will invoke - * @callback whenever it notices a change to the directory to which - * @path refers or any of the files within the directory. - * - * The returned #ThunarVfsMonitorHandle can be used to remove - * the @path from @monitor using thunar_vfs_monitor_remove(). - * - * Return value: the #ThunarVfsMonitorHandle for the new watch. - **/ -ThunarVfsMonitorHandle* -thunar_vfs_monitor_add_directory (ThunarVfsMonitor *monitor, - ThunarVfsPath *path, - ThunarVfsMonitorCallback callback, - gpointer user_data) -{ - ThunarVfsMonitorHandle *handle; -#ifdef HAVE_LIBFAM - gchar *absolute_path; -#endif - - g_return_val_if_fail (THUNAR_VFS_IS_MONITOR (monitor), NULL); - g_return_val_if_fail (callback != NULL, NULL); - g_return_val_if_fail (path != NULL, NULL); - - if (G_UNLIKELY (_thunar_vfs_path_is_local (path) - && thunar_vfs_monitor_is_excluded_path (monitor, path))) - return NULL; - - /* acquire the monitor lock */ - g_mutex_lock (monitor->lock); - - /* allocate a new handle */ - handle = _thunar_vfs_slice_new (ThunarVfsMonitorHandle); - handle->path = thunar_vfs_path_ref (path); - handle->callback = callback; - handle->user_data = user_data; - handle->directory = TRUE; - handle->fr.reqnum = ++monitor->current_reqnum; - -#ifdef HAVE_LIBFAM - if (G_LIKELY (monitor->fc_watch_id >= 0 && _thunar_vfs_path_is_local (path))) - { - /* schedule the watch on the FAM daemon */ - absolute_path = thunar_vfs_path_dup_string (path); - if (FAMMonitorDirectory2 (&monitor->fc, absolute_path, &handle->fr) < 0) - thunar_vfs_monitor_fam_cancel (monitor); - g_free (absolute_path); - } -#endif - - /* add the handle to the monitor */ - monitor->handles = g_slist_prepend (monitor->handles, handle); - - /* release the monitor lock */ - g_mutex_unlock (monitor->lock); - - return handle; -} - - - -/** - * thunar_vfs_monitor_add_file: - * @monitor : a #ThunarVfsMonitor. - * @path : the #ThunarVfsPath of the file that should be watched. - * @callback : the callback function to invoke. - * @user_data : additional data to pass to @callback. - * - * Registers @path as file with @monitor. @monitor will then invoke - * @callback whenever it notices a change to the file to which - * @path refers. - * - * The returned #ThunarVfsMonitorHandle can be used to remove - * the @path from @monitor using thunar_vfs_monitor_remove(). - * - * Return value: the #ThunarVfsMonitorHandle for the new watch. - **/ -ThunarVfsMonitorHandle* -thunar_vfs_monitor_add_file (ThunarVfsMonitor *monitor, - ThunarVfsPath *path, - ThunarVfsMonitorCallback callback, - gpointer user_data) -{ - ThunarVfsMonitorHandle *handle; -#ifdef HAVE_LIBFAM - gchar *absolute_path; -#endif - - g_return_val_if_fail (THUNAR_VFS_IS_MONITOR (monitor), NULL); - g_return_val_if_fail (callback != NULL, NULL); - g_return_val_if_fail (path != NULL, NULL); - - if (G_UNLIKELY (_thunar_vfs_path_is_local (path) - && thunar_vfs_monitor_is_excluded_path (monitor, path))) - return NULL; - - /* acquire the monitor lock */ - g_mutex_lock (monitor->lock); - - /* allocate a new handle */ - handle = _thunar_vfs_slice_new (ThunarVfsMonitorHandle); - handle->path = thunar_vfs_path_ref (path); - handle->callback = callback; - handle->user_data = user_data; - handle->directory = FALSE; - handle->fr.reqnum = ++monitor->current_reqnum; - -#ifdef HAVE_LIBFAM - if (G_LIKELY (monitor->fc_watch_id >= 0 && _thunar_vfs_path_is_local (path))) - { - /* schedule the watch on the FAM daemon */ - absolute_path = thunar_vfs_path_dup_string (path); - if (FAMMonitorFile2 (&monitor->fc, absolute_path, &handle->fr) < 0) - thunar_vfs_monitor_fam_cancel (monitor); - g_free (absolute_path); - } -#endif - - /* add the handle to the monitor */ - monitor->handles = g_slist_prepend (monitor->handles, handle); - - /* release the monitor lock */ - g_mutex_unlock (monitor->lock); - - return handle; -} - - - -/** - * thunar_vfs_monitor_remove: - * @monitor : a #ThunarVfsMonitor. - * @handle : a valid #ThunarVfsMonitorHandle for @monitor. - * - * Removes @handle from @monitor. - **/ -void -thunar_vfs_monitor_remove (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle) -{ - g_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); - g_return_if_fail (handle == NULL || g_slist_find (monitor->handles, handle) != NULL); - - /* leave when the handle is null */ - if (G_UNLIKELY (handle == NULL)) - return; - - /* acquire the monitor lock */ - g_mutex_lock (monitor->lock); - -#ifdef HAVE_LIBFAM - /* drop the FAM request from the daemon */ - if (G_LIKELY (monitor->fc_watch_id >= 0 && _thunar_vfs_path_is_local (handle->path))) - { - /* make sure there are no pending events before removing the request. - * if we don't do this, fam will lock up when a lot of requests are - * removed in a short time (collapse a treeview node for example) */ - if (thunar_vfs_monitor_fam_process_events (monitor)) - { - if (FAMCancelMonitor (&monitor->fc, &handle->fr) < 0) - thunar_vfs_monitor_fam_cancel (monitor); - } - } -#endif - - /* unlink the handle */ - monitor->handles = g_slist_remove (monitor->handles, handle); - - /* release the path */ - thunar_vfs_path_unref (handle->path); - - /* release the handle */ - _thunar_vfs_slice_free (ThunarVfsMonitorHandle, handle); - - /* release the monitor lock */ - g_mutex_unlock (monitor->lock); -} - - - -/** - * thunar_vfs_monitor_feed: - * @monitor : a #ThunarVfsMonitor. - * @event : the #ThunarVfsMonitorEvent that should be emulated. - * @path : the #ThunarVfsPath on which @event took place. - * - * Explicitly injects the given @event into @monitor<!---->s event - * processing logic. - **/ -void -thunar_vfs_monitor_feed (ThunarVfsMonitor *monitor, - ThunarVfsMonitorEvent event, - ThunarVfsPath *path) -{ - ThunarVfsMonitorHandle *handle; - ThunarVfsPath *parent; - GSList *lp; - - g_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); - g_return_if_fail (event == THUNAR_VFS_MONITOR_EVENT_CHANGED - || event == THUNAR_VFS_MONITOR_EVENT_CREATED - || event == THUNAR_VFS_MONITOR_EVENT_DELETED); - - /* acquire the lock on the monitor */ - g_mutex_lock (monitor->lock); - - /* schedule notifications for all handles affected directly by this event */ - for (lp = monitor->handles; lp != NULL; lp = lp->next) - { - handle = (ThunarVfsMonitorHandle *) lp->data; - if (thunar_vfs_path_equal (handle->path, path)) - thunar_vfs_monitor_queue_notification (monitor, handle->fr.reqnum, THUNAR_VFS_MONITOR_TAG_FEED, event, NULL); - } - - /* schedule notifications for all directory handles affected indirectly */ - if (G_LIKELY (!thunar_vfs_path_is_root (path))) - { - parent = thunar_vfs_path_get_parent (path); - for (lp = monitor->handles; lp != NULL; lp = lp->next) - { - handle = (ThunarVfsMonitorHandle *) lp->data; - if (handle->directory && thunar_vfs_path_equal (handle->path, parent)) - thunar_vfs_monitor_queue_notification (monitor, handle->fr.reqnum, THUNAR_VFS_MONITOR_TAG_FEED, event, thunar_vfs_path_get_name (path)); - } - } - - /* release the lock on the monitor */ - g_mutex_unlock (monitor->lock); -} - - - -/** - * thunar_vfs_monitor_wait: - * @monitor : a #ThunarVfsMonitor. - * - * Suspends the execution of the current thread until the - * @monitor has processed all currently pending events. The - * calling thread must own a reference on the @monitor! - * - * This method should never be called from the main thread - * or you'll lock up your application!! - **/ -void -thunar_vfs_monitor_wait (ThunarVfsMonitor *monitor) -{ - static const GTimeVal tv = { 2, 0 }; - - g_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); - - g_mutex_lock (monitor->lock); - while (g_atomic_int_get (&monitor->notifications_timer_id) != 0) - g_cond_timed_wait (monitor->cond, monitor->lock, (GTimeVal *) &tv); - g_mutex_unlock (monitor->lock); -} - - - -/** - * _thunar_vfs_monitor: - * - * The shared #ThunarVfsMonitor instance, which is used by all modules that - * need to watch files for changes or manually need to feed changes into the - * monitor. Only valid between class to thunar_vfs_init() and - * thunar_vfs_shutdown(). - **/ -ThunarVfsMonitor *_thunar_vfs_monitor = NULL; - - - -/** - * _thunar_vfs_monitor_handle_get_path: - * @handle : a #ThunarVfsMonitorHandle. - * - * Returns the #ThunarVfsPath for the @handle. Note that no additional - * reference is taken on the returned path. - * - * Return value: the #ThunarVfsPath for @handle. - **/ -ThunarVfsPath* -_thunar_vfs_monitor_handle_get_path (const ThunarVfsMonitorHandle *handle) -{ - return handle->path; -} - - - -#define __THUNAR_VFS_MONITOR_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-monitor.h b/thunar-vfs/thunar-vfs-monitor.h deleted file mode 100644 index cb1b0908f..000000000 --- a/thunar-vfs/thunar-vfs-monitor.h +++ /dev/null @@ -1,106 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_MONITOR_H__ -#define __THUNAR_VFS_MONITOR_H__ - -#include <thunar-vfs/thunar-vfs-path.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsMonitorClass ThunarVfsMonitorClass; -typedef struct _ThunarVfsMonitor ThunarVfsMonitor; - -#define THUNAR_VFS_TYPE_MONITOR (thunar_vfs_monitor_get_type ()) -#define THUNAR_VFS_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_MONITOR, ThunarVfsMonitor)) -#define THUNAR_VFS_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_MONITOR, ThunarVfsMonitorClass)) -#define THUNAR_VFS_IS_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_MONITOR)) -#define THUNAR_VFS_IS_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_MONITOR)) -#define THUNAR_VFS_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_MONITOR, ThunarVfsMonitorClass)) - -/** - * ThunarVfsMonitorEvent: - * @THUNAR_VFS_MONITOR_EVENT_CHANGED : a file or directory was changed. - * @THUNAR_VFS_MONITOR_EVENT_CREATED : a file or directory was created. - * @THUNAR_VFS_MONITOR_EVENT_DELETED : a file or directory was deleted. - * - * Describes an event that occurred on a #ThunarVfsMonitorHandle. - **/ -typedef enum -{ - THUNAR_VFS_MONITOR_EVENT_CHANGED, - THUNAR_VFS_MONITOR_EVENT_CREATED, - THUNAR_VFS_MONITOR_EVENT_DELETED, -} ThunarVfsMonitorEvent; - -/** - * ThunarVfsMonitorHandle: - * - * A handle on a file system entity, which is currently watched - * by a #ThunarVfsMonitor. - **/ -typedef struct _ThunarVfsMonitorHandle ThunarVfsMonitorHandle; - -/** - * ThunarVfsMonitorCallback: - * @monitor : a #ThunarVfsMonitor. - * @handle : a #ThunarVfsMonitorHandle. - * @event : the event that occurred. - * @handle_path : the #ThunarVfsPath that was specified when registering the @handle. - * @event_path : the #ThunarVfsPath on which the @event occurred. - * @user_data : the user data that was specified when registering the @handle with the @monitor. - * - * The prototype for callback functions that will be called by a #ThunarVfsMonitor - * whenever one of its associated #ThunarVfsMonitorHandle<!---->s notice a - * change. - **/ -typedef void (*ThunarVfsMonitorCallback) (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data); - -GType thunar_vfs_monitor_get_type (void) G_GNUC_CONST; - -ThunarVfsMonitor *thunar_vfs_monitor_get_default (void) G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsMonitorHandle *thunar_vfs_monitor_add_directory (ThunarVfsMonitor *monitor, - ThunarVfsPath *path, - ThunarVfsMonitorCallback callback, - gpointer user_data); - -ThunarVfsMonitorHandle *thunar_vfs_monitor_add_file (ThunarVfsMonitor *monitor, - ThunarVfsPath *path, - ThunarVfsMonitorCallback callback, - gpointer user_data); - -void thunar_vfs_monitor_remove (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle); - -void thunar_vfs_monitor_feed (ThunarVfsMonitor *monitor, - ThunarVfsMonitorEvent event, - ThunarVfsPath *path); - -void thunar_vfs_monitor_wait (ThunarVfsMonitor *monitor); - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_MONITOR_H__ */ diff --git a/thunar-vfs/thunar-vfs-os-bsd.c b/thunar-vfs/thunar-vfs-os-bsd.c deleted file mode 100644 index 52d5e8898..000000000 --- a/thunar-vfs/thunar-vfs-os-bsd.c +++ /dev/null @@ -1,322 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-os.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/** - * _thunar_vfs_os_is_dir_empty: - * @absolute_path : an absolute path to a folder. - * - * Returns %TRUE if the directory at the @absolute_path - * does not contain any files or folders, or if the - * @absolute_path does not refer to a directory. Otherwise - * if the @absolute_path contains atleast one entry except - * '.' and '..', %FALSE is returned. - * - * Return value: %TRUE if the directory at @absolute_path - * is empty. - **/ -gboolean -_thunar_vfs_os_is_dir_empty (const gchar *absolute_path) -{ - struct dirent *dp; -#ifndef HAVE_GETDENTS - glong basep = 0; -#endif - gchar dbuf[8 * DIRBLKSIZ]; - gint size = 0; - gint loc = 0; - gint fd; - - /* try to open the directory */ - fd = open (absolute_path, O_NONBLOCK | O_RDONLY); - if (G_LIKELY (fd >= 0)) - { - /* read the directory content */ - for (;;) - { - /* check if we need to fill the buffer again */ - if (loc >= size) - { -#ifdef HAVE_GETDENTS - /* read the next chunk (no base pointer needed) */ - size = getdents (fd, dbuf, sizeof (dbuf)); -#else - /* read the next chunk (OpenBSD fallback) */ - size = getdirentries (fd, dbuf, sizeof (dbuf), &basep); -#endif - - /* check for eof/error */ - if (size <= 0) - break; - loc = 0; - } - - /* grab the pointer to the next entry */ - dp = (struct dirent *) (dbuf + loc); - if (G_UNLIKELY (((gulong) dp & 0x03) != 0)) - { -invalid: - size = 0; - break; - } - - /* verify the next record length */ - if (G_UNLIKELY (dp->d_reclen <= 0 || dp->d_reclen > sizeof (dbuf) + 1 - loc)) - goto invalid; - - /* adjust the location pointer */ - loc += dp->d_reclen; - - /* verify the inode */ - if (G_UNLIKELY (dp->d_fileno == 0)) - continue; - -#ifdef DT_WHT - /* verify the type (OpenBSD lacks whiteout) */ - if (G_UNLIKELY (dp->d_type == DT_WHT)) - continue; -#endif - - /* ignore '.' and '..' entries */ - if (G_UNLIKELY (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))) - continue; - - /* jep, the directory is not empty */ - break; - } - - /* close the directory */ - close (fd); - } - - return (size <= 0); -} - - - -/** - * _thunar_vfs_os_scandir: - * @path : the #ThunarVfsPath for the directory, which does - * not need to be a local path. The returned path - * list will be made of paths relative to this one. - * @absolute_path : the absolute local path of the directory to scan. - * @follow_links : %TRUE to follow symlinks to directories. - * @directories_return : pointer to a list into which the direct subfolders - * found during scanning will be placed (for recursive - * scanning), or %NULL if you are not interested in a - * separate list of subfolders. Note that the returned - * list items need to be freed, but the #ThunarVfsPath<!---->s - * in the list do not have an extra reference. - * @error : return location for errors or %NULL. - * - * Note that folders in a filesystem mounted via mount_union(8) may - * not be handled properly in all cases. But since mount_union(8) do - * not seem to be widely used today, we will ignore the fact and wait - * for the first user to complain. - * - * The list returned in @directories_return, if not %NULL, must be freed using - * g_list_free() when no longer needed. - * - * The returned list of #ThunarVfsPath<!---->s must be freed by the caller using - * thunar_vfs_path_list_unref() when no longer needed. - * - * Return value: the list of #ThunarVfsPath<!---->s in the folder at the @absolute_path, - * or %NULL in case of an error. Note that %NULL may also mean that the - * folder is empty. - **/ -GList* -_thunar_vfs_os_scandir (ThunarVfsPath *path, - const gchar *absolute_path, - gboolean follow_links, - GList **directories_return, - GError **error) -{ - struct dirent *dp; - struct stat statb; -#ifndef HAVE_GETDENTS - glong basep = 0; -#endif - GList *path_list = NULL; - gchar *filename; - gchar *dbuf; - guint dlen; - gint size; - gint loc; - gint fd; - - _thunar_vfs_return_val_if_fail (g_path_is_absolute (absolute_path), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* try to open the file (the file name is placed in handle->fname) */ - fd = open (absolute_path, (follow_links ? 0 : O_NOFOLLOW) | O_NONBLOCK | O_RDONLY); - if (G_UNLIKELY (fd < 0)) - { - /* translate EMLINK to ENOTDIR */ - _thunar_vfs_set_g_error_from_errno (error, (errno == EMLINK) ? ENOTDIR : errno); - return NULL; - } - - /* stat the file */ - if (G_UNLIKELY (fstat (fd, &statb) < 0)) - { -error0: - _thunar_vfs_set_g_error_from_errno3 (error); - goto done; - } - - /* verify that we have a directory here */ - if (G_UNLIKELY (!S_ISDIR (statb.st_mode))) - { - _thunar_vfs_set_g_error_from_errno (error, ENOTDIR); - goto done; - } - - /* verify that we can enter the directory (else - * we won't get any useful infos about the dir - * contents either, so no need to continue). See - * http://bugzilla.xfce.org/show_bug.cgi?id=1408. - */ - if (G_UNLIKELY ((statb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != (S_IXUSR | S_IXGRP | S_IXOTH) && (access (absolute_path, X_OK) < 0))) - { - _thunar_vfs_set_g_error_from_errno (error, EACCES); - goto done; - } - - /* close the directory on exec */ - if (G_UNLIKELY (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)) - goto error0; - - /* calculate the directory buffer size */ - dlen = statb.st_blksize * 8; - if (G_UNLIKELY ((dlen % DIRBLKSIZ) != 0)) - dlen = ((dlen + DIRBLKSIZ - 1) / DIRBLKSIZ) * DIRBLKSIZ; - - /* allocate the directory buffer */ - dbuf = g_new (gchar, dlen); - - /* read the directory content */ - for (loc = size = 0;;) - { - /* check if we need to fill the buffer again */ - if (loc >= size) - { -#ifdef HAVE_GETDENTS - /* read the next chunk (no need for a base pointer) */ - size = getdents (fd, dbuf, dlen); -#else - /* read the next chunk (OpenBSD fallback) */ - size = getdirentries (fd, dbuf, dlen, &basep); -#endif - - /* check for eof/error */ - if (size <= 0) - break; - loc = 0; - } - - /* grab the pointer to the next entry */ - dp = (struct dirent *) (dbuf + loc); - if (G_UNLIKELY (((gulong) dp & 0x03) != 0)) - break; - - /* verify the next record length */ - if (G_UNLIKELY (dp->d_reclen <= 0 || dp->d_reclen > dlen + 1 - loc)) - break; - - /* adjust the location pointer */ - loc += dp->d_reclen; - - /* verify the inode */ - if (G_UNLIKELY (dp->d_fileno == 0)) - continue; - -#ifdef DT_WHT - /* verify the type (OpenBSD lacks whiteout) */ - if (G_UNLIKELY (dp->d_type == DT_WHT)) - continue; -#endif - - /* ignore '.' and '..' entries */ - if (G_UNLIKELY (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))) - continue; - - /* add the child path to the path list */ - path_list = g_list_prepend (path_list, _thunar_vfs_path_child (path, dp->d_name)); - - /* check if we want to collect children for recursive scanning */ - if (G_UNLIKELY (directories_return != NULL)) - { - /* DT_UNKNOWN must be handled for certain file systems */ - if (G_UNLIKELY (dp->d_type == DT_UNKNOWN)) - { - /* stat the child (according to the FOLLOW_LINKS policy) to see if we have a directory here */ - filename = g_build_filename (absolute_path, dp->d_name, NULL); - if ((follow_links ? stat (filename, &statb) : lstat (filename, &statb)) == 0 && S_ISDIR (statb.st_mode)) - dp->d_type = DT_DIR; - g_free (filename); - } - - /* check if we have a directory */ - if (dp->d_type == DT_DIR) - *directories_return = g_list_prepend (*directories_return, path_list->data); - } - } - - /* release the directory buffer */ - g_free (dbuf); - -done: - close (fd); - return path_list; -} - - - -#define __THUNAR_VFS_OS_BSD_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-os-generic.c b/thunar-vfs/thunar-vfs-os-generic.c deleted file mode 100644 index 966415c3d..000000000 --- a/thunar-vfs/thunar-vfs-os-generic.c +++ /dev/null @@ -1,225 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-os.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* Use g_access() on win32 */ -#if GLIB_CHECK_VERSION(2,8,0) && defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_access(path, mode) (access ((path), (mode))) -#endif - -/* !@#$%^&* IRIX and Solaris */ -#if defined(__sgi__) && !defined(dirfd) -#define dirfd(dp) (((DIR *) (dp))->__dd_fd) -#elif (defined(__sun__) || defined(__sun)) && !defined(dirfd) -#define dirfd(dp) (((DIR *) (dp))->dd_fd) -#endif - - - -/** - * _thunar_vfs_os_is_dir_empty: - * @absolute_path : an absolute path to a folder. - * - * Returns %TRUE if the directory at the @absolute_path - * does not contain any files or folders, or if the - * @absolute_path does not refer to a directory. Otherwise - * if the @absolute_path contains atleast one entry except - * '.' and '..', %FALSE is returned. - * - * Return value: %TRUE if the directory at @absolute_path - * is empty. - **/ -gboolean -_thunar_vfs_os_is_dir_empty (const gchar *absolute_path) -{ - struct dirent *dp; - DIR *dirp; - - dirp = opendir (absolute_path); - if (G_LIKELY (dirp != NULL)) - { - /* ignore '.' and '..' */ - dp = readdir (dirp); - dp = readdir (dirp); - dp = readdir (dirp); - closedir (dirp); - return (dp == NULL); - } - - return TRUE; -} - - - -/** - * _thunar_vfs_os_scandir: - * @path : the #ThunarVfsPath for the directory, which does - * not need to be a local path. The returned path - * list will be made of paths relative to this one. - * @absolute_path : the absolute local path of the directory to scan. - * @follow_links : %TRUE to follow symlinks to directories. - * @directories_return : pointer to a list into which the direct subfolders - * found during scanning will be placed (for recursive - * scanning), or %NULL if you are not interested in a - * separate list of subfolders. Note that the returned - * list items need to be freed, but the #ThunarVfsPath<!---->s - * in the list do not have an extra reference. - * @error : return location for errors or %NULL. - * - * The list returned in @directories_return, if not %NULL, must be freed using - * g_list_free() when no longer needed. - * - * The returned list of #ThunarVfsPath<!---->s must be freed by the caller using - * thunar_vfs_path_list_unref() when no longer needed. - * - * Return value: the list of #ThunarVfsPath<!---->s in the folder at the @absolute_path, - * or %NULL in case of an error. Note that %NULL may also mean that the - * folder is empty. - **/ -GList* -_thunar_vfs_os_scandir (ThunarVfsPath *path, - const gchar *absolute_path, - gboolean follow_links, - GList **directories_return, - GError **error) -{ - struct dirent *dp; - struct stat fstatb; - struct stat statb; - GList *path_list = NULL; - gchar *filename; - DIR *dirp; - - _thunar_vfs_return_val_if_fail (g_path_is_absolute (absolute_path), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* try to open the directory */ - dirp = opendir (absolute_path); - if (G_UNLIKELY (dirp == NULL)) - { - _thunar_vfs_set_g_error_from_errno3 (error); - return NULL; - } - - /* stat the just opened directory */ - if (fstat (dirfd (dirp), &fstatb) < 0) - goto error; - - /* verify that the directory is really the directory we want - * to open. If not, we've probably detected a race condition, - * so we'll better stop rather than doing anything stupid - * (remember, this method is also used in collecting - * files for the unlink job!!). Better safe than sorry! - */ - if (G_UNLIKELY (!follow_links)) - { - /* stat the path (without following links) */ - if (lstat (absolute_path, &statb) < 0) - goto error; - - /* check that we have the same file here */ - if (fstatb.st_ino != statb.st_ino || fstatb.st_dev != statb.st_dev) - { - errno = ENOTDIR; - goto error; - } - } - - /* verify that we can enter the directory (else - * we won't get any useful infos about the dir - * contents either, so no need to continue). See - * http://bugzilla.xfce.org/show_bug.cgi?id=1408. - */ - if ((fstatb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != (S_IXUSR | S_IXGRP | S_IXOTH) && (g_access (absolute_path, X_OK) < 0)) - { - errno = EACCES; - goto error; - } - - /* read the directory content */ - for (;;) - { - /* read the next directory entry */ - dp = readdir (dirp); - if (G_UNLIKELY (dp == NULL)) - break; - - /* ignore '.' and '..' entries */ - if (G_UNLIKELY (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))) - continue; - - /* add the child path to the path list */ - path_list = g_list_prepend (path_list, _thunar_vfs_path_child (path, dp->d_name)); - - /* check if we want to collect children for recursive scanning */ - if (G_UNLIKELY (directories_return != NULL)) - { - /* determine the absolute path to the child */ - filename = g_build_filename (absolute_path, dp->d_name, NULL); - - /* check if we have a directory here (according to the FOLLOW_LINKS policy) */ - if ((follow_links ? stat (filename, &statb) : lstat (filename, &statb)) == 0 && S_ISDIR (statb.st_mode)) - *directories_return = g_list_prepend (*directories_return, path_list->data); - - /* cleanup */ - g_free (filename); - } - } - -done: - closedir (dirp); - return path_list; - -error: - _thunar_vfs_set_g_error_from_errno3 (error); - goto done; -} - - - -#define __THUNAR_VFS_OS_GENERIC_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-os.h b/thunar-vfs/thunar-vfs-os.h deleted file mode 100644 index 2fd88cd17..000000000 --- a/thunar-vfs/thunar-vfs-os.h +++ /dev/null @@ -1,42 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_OS_H__ -#define __THUNAR_VFS_OS_H__ - -#include <thunar-vfs/thunar-vfs-path-private.h> - -G_BEGIN_DECLS; - -gboolean _thunar_vfs_os_is_dir_empty (const gchar *absolute_path) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -GList *_thunar_vfs_os_scandir (ThunarVfsPath *path, - const gchar *absolute_path, - gboolean follow_links, - GList **directories_return, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_OS_H__ */ diff --git a/thunar-vfs/thunar-vfs-path-private.h b/thunar-vfs/thunar-vfs-path-private.h deleted file mode 100644 index 4698b5a46..000000000 --- a/thunar-vfs/thunar-vfs-path-private.h +++ /dev/null @@ -1,101 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_PATH_PRIVATE_H__ -#define __THUNAR_VFS_PATH_PRIVATE_H__ - -#include <thunar-vfs/thunar-vfs-path.h> - -G_BEGIN_DECLS; - -/* Support macros for compilers that don't support proper inlining */ -#if !defined(G_CAN_INLINE) && !defined(__THUNAR_VFS_PATH_C__) && !defined(__THUNAR_VFS_INFO_C__) - -#define thunar_vfs_path_ref(path) (exo_atomic_inc (&(THUNAR_VFS_PATH ((path))->ref_count)), path) -#define thunar_vfs_path_is_root(path) (THUNAR_VFS_PATH ((path))->parent == NULL) -#define thunar_vfs_path_get_name(path) (((const gchar *) path) + sizeof (ThunarVfsPath)) -#define thunar_vfs_path_get_parent(path) (THUNAR_VFS_PATH ((path))->parent) -#define thunar_vfs_path_get_scheme(path) (THUNAR_VFS_PATH ((path))->ref_count & THUNAR_VFS_PATH_SCHEME_MASK) - -#endif /* !defined(G_CAN_INLINE) && !defined(__THUNAR_VFS_PATH_C__) && !defined(__THUNAR_VFS_INFO_C__) */ - -/* global shared variables */ -extern ThunarVfsPath *_thunar_vfs_path_trash_root G_GNUC_INTERNAL; - -/* initialization/shutdown routines */ -void _thunar_vfs_path_init (void) G_GNUC_INTERNAL; -void _thunar_vfs_path_shutdown (void) G_GNUC_INTERNAL; - -/* internal support methods */ -ThunarVfsPath *_thunar_vfs_path_new_relative (ThunarVfsPath *parent, - const gchar *relative_path) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsPath *_thunar_vfs_path_child (ThunarVfsPath *parent, - const gchar *name) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gchar *_thunar_vfs_path_dup_display_name (const ThunarVfsPath *path) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsPath *_thunar_vfs_path_translate (ThunarVfsPath *src_path, - ThunarVfsPathScheme dst_scheme, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gchar *_thunar_vfs_path_translate_dup_string (ThunarVfsPath *src_path, - ThunarVfsPathScheme dst_scheme, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -/** - * _thunar_vfs_path_unref_nofree: - * @path : a #ThunarVfsPath. - * - * Decrements the reference count on @path without checking whether the - * reference count reached zero and thereby freeing the @path resources. - * Use this method with care and only if you are absolutely sure that - * the reference count is larger than one. Otherwise you'll leak the - * @path memory. - **/ -#define _thunar_vfs_path_unref_nofree(path) \ -G_STMT_START{ \ - (void)exo_atomic_dec (&(THUNAR_VFS_PATH ((path))->ref_count)); \ -}G_STMT_END - -/** - * _thunar_vfs_path_is_local: - * @path : a #ThunarVfsPath. - * - * Returns %TRUE if the @path<!---->s scheme is %THUNAR_VFS_PATH_SCHEME_FILE. - * - * Return value: %TRUE if @path is %THUNAR_VFS_PATH_SCHEME_FILE. - **/ -#define _thunar_vfs_path_is_local(path) (thunar_vfs_path_get_scheme ((path)) == THUNAR_VFS_PATH_SCHEME_FILE) - -/** - * _thunar_vfs_path_is_trash: - * @path : a #ThunarVfsPath. - * - * Returns %TRUE if the @path<!---->s scheme is %THUNAR_VFS_PATH_SCHEME_TRASH. - * - * Return value: %TRUE if @path is %THUNAR_VFS_PATH_SCHEME_TRASH. - **/ -#define _thunar_vfs_path_is_trash(path) (thunar_vfs_path_get_scheme ((path)) == THUNAR_VFS_PATH_SCHEME_TRASH) - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_PATH_PRIVATE_H__ */ - diff --git a/thunar-vfs/thunar-vfs-path.c b/thunar-vfs/thunar-vfs-path.c deleted file mode 100644 index ea9f08fcf..000000000 --- a/thunar-vfs/thunar-vfs-path.c +++ /dev/null @@ -1,1483 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -/* implement thunar-vfs-path's inline functions */ -#define G_IMPLEMENT_INLINES 1 -#define __THUNAR_VFS_PATH_C__ -#include <thunar-vfs/thunar-vfs-path.h> - -#include <thunar-vfs/thunar-vfs-io-trash.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-util.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/* Masks to handle the 4-byte aligned path names */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -#define THUNAR_VFS_PATH_MASK (((gsize) 0xffu) << ((sizeof (gsize) - 1) * 8)) -#define THUNAR_VFS_PATH_ROOT (0x2fu) -#elif G_BYTE_ORDER == G_BIG_ENDIAN -#define THUNAR_VFS_PATH_MASK (0xffu) -#define THUNAR_VFS_PATH_ROOT (((gsize) 0x2fu) << ((sizeof (gsize) - 1) * 8)) -#else -#error "Unsupported endianess" -#endif - - - -static guint thunar_vfs_path_escape_uri_length (const ThunarVfsPath *path); -static guint thunar_vfs_path_escape_uri (const ThunarVfsPath *path, - gchar *buffer); - - - -/* A table of the ASCII chars from space (32) to DEL (127) */ -static const guchar ACCEPTABLE_URI_CHARS[96] = { - /* ! " # $ % & ' ( ) * + , - . / */ - 0x00,0x3F,0x20,0x20,0x28,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x2A,0x28,0x3F,0x3F,0x1C, - /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ - 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x20, - /* @ A B C D E F G H I J K L M N O */ - 0x38,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, - /* P Q R S T U V W X Y Z [ \ ] ^ _ */ - 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F, - /* ` a b c d e f g h i j k l m n o */ - 0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, - /* p q r s t u v w x y z { | } ~ DEL */ - 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20 -}; - -/* List of hexadecimal characters */ -static const gchar HEX_CHARS[16] = "0123456789ABCDEF"; - -#define ACCEPTABLE_URI_CHAR(c) ((c) >= 32 && (c) < 128 && (ACCEPTABLE_URI_CHARS[(c) - 32] & 0x08)) - - - -/* Debugging support in ThunarVfsPath */ -#ifdef G_ENABLE_DEBUG - -G_LOCK_DEFINE_STATIC (debug_paths); -static GList *debug_paths = NULL; - -#define THUNAR_VFS_PATH_DEBUG_INSERT(path) \ -G_STMT_START{ \ - G_LOCK (debug_paths); \ - debug_paths = g_list_prepend (debug_paths, (path)); \ - G_UNLOCK (debug_paths); \ -}G_STMT_END - -#define THUNAR_VFS_PATH_DEBUG_REMOVE(path) \ -G_STMT_START{ \ - G_LOCK (debug_paths); \ - debug_paths = g_list_remove (debug_paths, (path)); \ - G_UNLOCK (debug_paths); \ -}G_STMT_END - -#define THUNAR_VFS_PATH_DEBUG_SHUTDOWN() \ -G_STMT_START{ \ - if (G_UNLIKELY (debug_paths != NULL)) \ - { \ - GList *lp; \ - gchar *uri; \ - gint n; \ - G_LOCK (debug_paths); \ - g_print ("--- Leaked a total of %u ThunarVfsPath objects:\n", g_list_length (debug_paths)); \ - for (lp = debug_paths; lp != NULL; lp = lp->next) \ - { \ - uri = thunar_vfs_path_dup_string (lp->data); \ - n = ((ThunarVfsPath *) lp->data)->ref_count; \ - g_print ("--> %s (%d)\n", uri, (n & ~THUNAR_VFS_PATH_SCHEME_MASK)); \ - g_free (uri); \ - } \ - G_UNLOCK (debug_paths); \ - } \ -}G_STMT_END - -#else /* !G_ENABLE_DEBUG */ - -#define THUNAR_VFS_PATH_DEBUG_INSERT(path) G_STMT_START{ (void)0; }G_STMT_END -#define THUNAR_VFS_PATH_DEBUG_REMOVE(path) G_STMT_START{ (void)0; }G_STMT_END -#define THUNAR_VFS_PATH_DEBUG_SHUTDOWN() G_STMT_START{ (void)0; }G_STMT_END - -#endif /* !G_ENABLE_DEBUG */ - - - -/* components of the path to the users home folder */ -static ThunarVfsPath **home_components; -static guint n_home_components; - -/** - * _thunar_vfs_path_trash_root: - * - * The shared instance of the #ThunarVfsPath that points to the - * trash root folder. - **/ -ThunarVfsPath *_thunar_vfs_path_trash_root = NULL; - - - -static guint -thunar_vfs_path_escape_uri_length (const ThunarVfsPath *path) -{ - const guchar *s; - guint base_length; - guint length; - - /* determine the base length for the scheme (file:/// or trash:///) */ - length = base_length = _thunar_vfs_path_is_local (path) ? 8 : 9; - - /* determine the length for the path part */ - for (; path->parent != NULL; path = path->parent) - { - /* prepend a path separator */ - if (length > base_length) - length += 1; - - for (s = (const guchar *) thunar_vfs_path_get_name (path); *s != '\0'; ++s) - length += ACCEPTABLE_URI_CHAR (*s) ? 1 : 3; - } - - return length; -} - - - -static guint -thunar_vfs_path_escape_uri (const ThunarVfsPath *path, - gchar *buffer) -{ - typedef struct _ThunarVfsPathItem - { - const ThunarVfsPath *path; - struct _ThunarVfsPathItem *next; - } ThunarVfsPathItem; - - ThunarVfsPathItem *item; - ThunarVfsPathItem *root = NULL; - const gchar *s; - guchar c; - gchar *t; - - /* prepend 'trash:///' or 'file:///' string (using a simple optimization on i386/ppc) */ - if (G_LIKELY (thunar_vfs_path_get_scheme (path) == THUNAR_VFS_PATH_SCHEME_FILE)) - { -#if defined(__GNUC__) && (defined(__i386__) || defined(__ppc__)) - ((guint32 *) buffer)[0] = ((const guint32 *) "file:///")[0]; - ((guint32 *) buffer)[1] = ((const guint32 *) "file:///")[1]; -#else - /* hopefully the compiler will be able to optimize this */ - buffer[0] = 'f'; buffer[1] = 'i'; - buffer[2] = 'l'; buffer[3] = 'e'; - buffer[4] = ':'; buffer[5] = '/'; - buffer[6] = '/'; buffer[7] = '/'; -#endif - t = buffer + 8; - } - else - { -#if defined(__GNUC__) && (defined(__i386__) || defined(__ppc__)) - ((guint32 *) buffer)[0] = ((const guint32 *) "trash://")[0]; - ((guint32 *) buffer)[1] = ((const guint32 *) "trash://")[1]; -#else - /* hopefully the compiler will be able to optimize this */ - buffer[0] = 't'; buffer[1] = 'r'; - buffer[2] = 'a'; buffer[3] = 's'; - buffer[4] = 'h'; buffer[5] = ':'; - buffer[6] = '/'; buffer[7] = '/'; -#endif - buffer[8] = '/'; - t = buffer + 9; - } - - /* generate the path item list (reverse parent relation) */ - for (; path->parent != NULL; path = path->parent) - { - item = g_newa (ThunarVfsPathItem, 1); - item->path = path; - item->next = root; - root = item; - } - - /* generate the uri */ - for (item = root; item != NULL; item = item->next) - { - /* append a '/' character */ - if (G_LIKELY (item != root)) - *t++ = '/'; - - /* copy the path component name */ - for (s = thunar_vfs_path_get_name (item->path); *s != '\0'; ++s) - { - c = *((const guchar *) s); - if (G_UNLIKELY (!ACCEPTABLE_URI_CHAR (c))) - { - *t++ = '%'; - *t++ = HEX_CHARS[c >> 4]; - *t++ = HEX_CHARS[c & 15]; - } - else - { - *t++ = *s; - } - } - } - - /* zero-terminate the URI */ - *t = '\0'; - - return (t - buffer) + 1; -} - - - -GType -thunar_vfs_path_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = g_boxed_type_register_static (I_("ThunarVfsPath"), - (GBoxedCopyFunc) thunar_vfs_path_ref, - (GBoxedFreeFunc) thunar_vfs_path_unref); - } - - return type; -} - - - -GType -thunar_vfs_path_list_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = g_boxed_type_register_static (I_("ThunarVfsPathList"), - (GBoxedCopyFunc) thunar_vfs_path_list_copy, - (GBoxedFreeFunc) thunar_vfs_path_list_free); - } - - return type; -} - - - -/** - * thunar_vfs_path_new: - * @identifier : an URI identifier or an absolute path. - * @error : return location for errors or %NULL. - * - * Returns a #ThunarVfsPath that represents the given - * @identifier or %NULL on error. In the latter case - * @error will be set to point to an #GError describing - * the problem. - * - * The caller is responsible to free the returned - * object using thunar_vfs_path_unref() when no - * longer needed. - * - * Return value: the #ThunarVfsPath for @identifier - * or %NULL on error. - **/ -ThunarVfsPath* -thunar_vfs_path_new (const gchar *identifier, - GError **error) -{ - ThunarVfsPath *path = home_components[0]; /* default to file system root */ - const gchar *s; - const gchar *s1; - const gchar *s2; - gchar *filename; - gchar *t; - guint n; - - /* check if we have an absolute path or an URI */ - if (G_UNLIKELY (*identifier != G_DIR_SEPARATOR)) - { - /* treat the identifier as URI */ - filename = g_filename_from_uri (identifier, NULL, NULL); - if (G_UNLIKELY (filename == NULL)) - { - /* hey, but maybe it's a trash:-URI */ - if (G_LIKELY (identifier[0] == 't' && identifier[1] == 'r' && identifier[2] == 'a' - && identifier[3] == 's' && identifier[4] == 'h' && identifier[5] == ':')) - { - /* skip slashes (yes, not dir separators) */ - for (s = identifier + 6; *s == '/'; ++s) - ; - - /* start at the trash root folder */ - path = _thunar_vfs_path_trash_root; - - /* check if it's the trash root folder */ - if (G_LIKELY (*s == '\0')) - return thunar_vfs_path_ref (path); - - /* try to interpret the file part */ - t = g_strconcat ("file:/", s, NULL); - filename = g_filename_from_uri (t, NULL, NULL); - g_free (t); - } - } - - /* check if the URI is invalid */ - if (G_UNLIKELY (filename == NULL)) - { - g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI, _("The URI \"%s\" is invalid"), identifier); - return NULL; - } - } - else - { - /* canonicalize the absolute path, to remove additional slashes and dots */ - filename = thunar_vfs_canonicalize_filename (identifier); - } - - /* parse the filename to a ThunarVfsPath */ - s = filename + 1; - - /* local paths may be relative to a home component */ - if (G_LIKELY (path == home_components[0])) - { - /* start at the root path */ - for (n = 1; n < n_home_components; ++n) - { - /* skip additional slashes */ - for (; G_UNLIKELY (*s == G_DIR_SEPARATOR); ++s) - ; - - /* check if we have reached the end of the filename */ - if (G_UNLIKELY (*s == '\0')) - break; - - /* check if the path component equals the next home path component */ - for (s1 = thunar_vfs_path_get_name (home_components[n]), s2 = s; *s1 != '\0' && *s1 == *s2; ++s1, ++s2) - ; - if (*s1 != '\0' || (*s2 != '\0' && *s2 != G_DIR_SEPARATOR)) - break; - - /* go on with the next home path component */ - path = home_components[n]; - s = s2; - } - } - - /* determine the subpath (takes appropriate references) */ - path = _thunar_vfs_path_new_relative (path, s); - - /* cleanup */ - g_free (filename); - - return path; -} - - - -/** - * thunar_vfs_path_get_for_home: - * - * Returns the #ThunarVfsPath that represents - * the current users home directory. - * - * The caller is responsible to free the - * returned object using thunar_vfs_path_unref() - * when no longer needed. - * - * Return value: the #ThunarVfsPath for the - * current users home directory. - **/ -ThunarVfsPath* -thunar_vfs_path_get_for_home (void) -{ - return thunar_vfs_path_ref (home_components[n_home_components - 1]); -} - - - -/** - * thunar_vfs_path_get_for_root: - * - * Returns the #ThunarVfsPath that represents the - * file systems root folder. - * - * The caller is responsible to free the returned - * object using thunar_vfs_path_unref() when no - * longer needed. - * - * Return value: the #ThunarVfsPath for the file - * systems root directory. - **/ -ThunarVfsPath* -thunar_vfs_path_get_for_root (void) -{ - return thunar_vfs_path_ref (home_components[0]); -} - - - -/** - * thunar_vfs_path_get_for_trash: - * - * Returns the #ThunarVfsPath that represents the - * trash root folder. - * - * The caller is responsible to free the returned - * object using thunar_vfs_path_unref() when no - * longer needed. - * - * Return value: the #ThunarVfsPath for the trash - * root folder. - **/ -ThunarVfsPath* -thunar_vfs_path_get_for_trash (void) -{ - return thunar_vfs_path_ref (_thunar_vfs_path_trash_root); -} - - - -/** - * thunar_vfs_path_unref: - * @path : a #ThunarVfsPath. - * - * Decreases the reference count on @path and - * frees the resources allocated for @path - * once the reference count drops to zero. - **/ -void -thunar_vfs_path_unref (ThunarVfsPath *path) -{ - ThunarVfsPath *parent; - const gsize *p; - - while (path != NULL && (g_atomic_int_exchange_and_add (&path->ref_count, -1) & ~THUNAR_VFS_PATH_SCHEME_MASK) == 1) - { - /* verify that we don't free the paths for trash root or home components */ -#ifdef G_ENABLE_DEBUG - if (G_UNLIKELY (path == _thunar_vfs_path_trash_root)) - { - /* the trash root path may not be freed */ - g_error (G_STRLOC ": Attempt to free the trash root path detected"); - } - else - { - /* same for the home component paths */ - guint n; - for (n = 0; n < n_home_components; ++n) - if (G_UNLIKELY (path == home_components[n])) - break; - - /* check if one of the home components matched */ - if (G_UNLIKELY (n < n_home_components)) - { - /* none of the home component paths can be freed this way */ - g_error (G_STRLOC ": Attempt to free the home component path \"%s\" detected", thunar_vfs_path_get_name (path)); - } - } -#endif - - /* remember the parent path */ - parent = path->parent; - - /* remove the path from the debug list */ - THUNAR_VFS_PATH_DEBUG_REMOVE (path); - - /* release the path resources (we need to determine the size for the slice allocator) */ - for (p = (const gsize *) thunar_vfs_path_get_name (path); (*p & THUNAR_VFS_PATH_MASK) != 0u; ++p) - ; - _thunar_vfs_slice_free1 (((const guint8 *) (p + 1)) - ((const guint8 *) path), path); - - /* continue with the parent */ - path = parent; - } -} - - - -/** - * thunar_vfs_path_hash: - * @path_ptr : a #ThunarVfsPath. - * - * Generates a hash value for the given @path_ptr. - * - * Return value: the hash value for @path_ptr. - **/ -guint -thunar_vfs_path_hash (gconstpointer path_ptr) -{ - const gchar *p = thunar_vfs_path_get_name (path_ptr); - guint h = *p + thunar_vfs_path_get_scheme (path_ptr); - - /* hash the last path component (which cannot be empty) */ - while (*++p != '\0') - h = (h << 5) - h + *p; - - return h; -} - - - -/** - * thunar_vfs_path_equal: - * @path_ptr_a : first #ThunarVfsPath. - * @path_ptr_b : second #ThunarVfsPath. - * - * Checks whether @path_ptr_a and @path_ptr_b refer - * to the same local path. - * - * Return value: %TRUE if @path_ptr_a and @path_ptr_b - * are equal. - **/ -gboolean -thunar_vfs_path_equal (gconstpointer path_ptr_a, - gconstpointer path_ptr_b) -{ - const ThunarVfsPath *path_a = path_ptr_a; - const ThunarVfsPath *path_b = path_ptr_b; - const gsize *a; - const gsize *b; - - /* compare the schemes */ - if (thunar_vfs_path_get_scheme (path_a) != thunar_vfs_path_get_scheme (path_b)) - return FALSE; - -again: - /* check if the paths are the same object */ - if (G_UNLIKELY (path_a == path_b)) - return TRUE; - - /* compare the last path component */ - a = (const gsize *) thunar_vfs_path_get_name (path_a); - b = (const gsize *) thunar_vfs_path_get_name (path_b); - for (;;) - { - if (*a != *b) - return FALSE; - else if ((*a & THUNAR_VFS_PATH_MASK) == 0u) - break; - - ++a; - ++b; - } - - /* compare the parent path components */ - if (G_LIKELY (path_a->parent != NULL && path_b->parent != NULL)) - { - path_a = path_a->parent; - path_b = path_b->parent; - goto again; - } - - /* verify that both paths have no parents then */ - return (path_a->parent == NULL && path_b->parent == NULL); -} - - - -/** - * thunar_vfs_path_relative: - * @parent : a #ThunarVfsPath. - * @name : a valid filename in the local file system encoding. - * - * Returns a #ThunarVfsPath for the file @name relative to - * @parent. @name must be a valid filename in the local file - * system encoding and it may not contain any slashes. - * - * The caller is responsible to free the returned object - * using thunar_vfs_path_unref() when no longer needed. - * - * Return value: the path to @name relative to @parent. - **/ -ThunarVfsPath* -thunar_vfs_path_relative (ThunarVfsPath *parent, - const gchar *name) -{ - g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (name != NULL, NULL); - g_return_val_if_fail (*name != '\0', NULL); - g_return_val_if_fail (strchr (name, '/') == NULL, NULL); - - /* let _thunar_vfs_path_child() do it's work */ - return _thunar_vfs_path_child (parent, name); -} - - - -/** - * thunar_vfs_path_is_ancestor: - * @path : a #ThunarVfsPath. - * @ancestor : another #ThunarVfsPath. - * - * Determines whether @path is somewhere below @ancestor, - * possible with intermediate folders. - * - * Return value: %TRUE if @ancestor contains @path as a - * child, grandchild, great grandchild, etc. - **/ -gboolean -thunar_vfs_path_is_ancestor (const ThunarVfsPath *path, - const ThunarVfsPath *ancestor) -{ - g_return_val_if_fail (path != NULL, FALSE); - g_return_val_if_fail (ancestor != NULL, FALSE); - - for (path = path->parent; path != NULL; path = path->parent) - if (thunar_vfs_path_equal (path, ancestor)) - return TRUE; - - return FALSE; -} - - - -/** - * thunar_vfs_path_is_home: - * @path : a #ThunarVfsPath. - * - * Checks whether @path refers to the users home - * directory. - * - * Return value: %TRUE if @path refers to the users - * home directory. - **/ -gboolean -thunar_vfs_path_is_home (const ThunarVfsPath *path) -{ - g_return_val_if_fail (path != NULL, FALSE); - return (path == home_components[n_home_components - 1]); -} - - - -/** - * thunar_vfs_path_dup_string: - * @path : a #ThunarVfsPath. - * - * Like thunar_vfs_path_to_string(), this function transform - * the @path to its string representation, but unlike - * thunar_vfs_path_to_string(), this function automatically - * allocates the required amount of memory from the heap. - * The returned string must be freed by the caller when - * no longer needed. - * - * Return value: the string representation of @path. - **/ -gchar* -thunar_vfs_path_dup_string (const ThunarVfsPath *path) -{ - const ThunarVfsPath *p; - gchar *s; - guint n; - - /* determine the number of bytes required to - * store the path's string representation. - */ - for (n = 0, p = path; p != NULL; p = p->parent) - n += strlen (thunar_vfs_path_get_name (p)) + 2; - - /* allocate the buffer to store the string */ - s = g_malloc (n); - - /* store the path string to the buffer */ - thunar_vfs_path_to_string (path, s, n, NULL); - - /* return the string buffer */ - return s; -} - - - -/** - * thunar_vfs_path_to_string: - * @path : a #ThunarVfsPath. - * @buffer : the buffer to store the path string to. - * @bufsize : the size of @buffer in bytes. - * @error : return location for errors or %NULL. - * - * Stores the @path into the string pointed to by @buffer, - * so it can be used for system path operations. Returns - * the number of bytes stored to @buffer or a negative - * value if @bufsize is too small to store the whole @path. - * In the latter case @error will be set to point to an - * error describing the problem. - * - * If @buffer is allocated on the stack, it is suggested - * to use #THUNAR_VFS_PATH_MAXSTRLEN for the buffer size - * in most cases. The stack should never be used in recursive - * functions; use thunar_vfs_path_dup_string() instead there. - * - * Return value: the number of bytes (including the null - * byte) stored to @buffer or a negative - * value if @buffer cannot hold the whole - * @path. - **/ -gssize -thunar_vfs_path_to_string (const ThunarVfsPath *path, - gchar *buffer, - gsize bufsize, - GError **error) -{ - typedef struct _ThunarVfsPathItem - { - const gchar *name; - struct _ThunarVfsPathItem *next; - } ThunarVfsPathItem; - - ThunarVfsPathItem *items = NULL; - ThunarVfsPathItem *item; - const gchar *name; - gchar *bp; - guint n; - - g_return_val_if_fail (buffer != NULL, -1); - g_return_val_if_fail (bufsize > 0, -1); - g_return_val_if_fail (error == NULL || *error == NULL, -1); - - /* the root element is a special case to ease the processing */ - if (G_UNLIKELY (path->parent == NULL)) - { - if (G_UNLIKELY (bufsize < 2)) - goto error; - buffer[0] = G_DIR_SEPARATOR; - buffer[1] = '\0'; - return 2; - } - - /* determine the buffer size required for the path buffer */ - for (n = 1; path->parent != NULL; path = path->parent) - { - /* add the path to the item list */ - item = g_newa (ThunarVfsPathItem, 1); - item->name = thunar_vfs_path_get_name (path); - item->next = items; - items = item; - - /* add the size constraint (including the '/') */ - n += strlen (item->name) + 1; - } - - /* verify the buffer size */ - if (G_UNLIKELY (bufsize < n)) - { -error: - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NAMETOOLONG, - _("Path too long to fit into buffer")); - return -1; - } - - /* generate the path string */ - for (bp = buffer, item = items; item != NULL; item = item->next) - { - /* prepend the path separator */ - *bp++ = G_DIR_SEPARATOR; - - /* append the component name */ - for (name = item->name; *name != '\0'; ) - *bp++ = *name++; - } - - /* append the string terminator */ - *bp = '\0'; - - /* return the number of bytes written to the buffer */ - return n; -} - - - -/** - * thunar_vfs_path_dup_uri: - * @path : a #ThunarVfsPath. - * - * Similar to thunar_vfs_path_to_uri(), but automatically - * allocates memory on the heap instead of using a user - * supplied buffer for the URI. - * - * The caller is responsible to free the returned string - * using g_free() when no longer needed. - * - * Return value: the escaped URI for @path. - **/ -gchar* -thunar_vfs_path_dup_uri (const ThunarVfsPath *path) -{ - gchar *s; - guint m; - guint n; - - g_return_val_if_fail (path != NULL, NULL); - - /* calculate the length of the uri string */ - n = thunar_vfs_path_escape_uri_length (path) + 1; - - /* escape the path to an uri string */ - s = g_malloc (sizeof (gchar) * n); - m = thunar_vfs_path_escape_uri (path, s); - - /* verify the result */ - _thunar_vfs_assert (strlen (s) == m - 1); - _thunar_vfs_assert (m == n); - - return s; -} - - - -/** - * thunar_vfs_path_to_uri: - * @path : a #ThunarVfsPath. - * @buffer : the buffer to store the URI string to. - * @bufsize : the size of @buffer in bytes. - * @error : return location for errors or %NULL. - * - * Escapes @path according to the rules of the file URI - * specification and stores the escaped URI to @buffer. - * Returns the number of bytes stored to @buffer or a - * negative value if @bufsize is too small to store the - * escaped URI. In the latter case @error will be set to - * point to an #GError describing the problem. - * - * When using the stack for @buffer, it is suggested to - * use #THUNAR_VFS_PATH_MAXURILEN for the buffer size in - * most cases. The stack should never be used in recursive - * functions; use thunar_vfs_path_dup_uri() instead there. - * - * Return value: the number of bytes (including the null - * byte) stored to @buffer or a negative - * value if @buffer cannot hold the URI. - **/ -gssize -thunar_vfs_path_to_uri (const ThunarVfsPath *path, - gchar *buffer, - gsize bufsize, - GError **error) -{ - guint n; - guint m; - - g_return_val_if_fail (path != NULL, -1); - g_return_val_if_fail (buffer != NULL, -1); - g_return_val_if_fail (error == NULL || *error == NULL, -1); - - /* verify that the buffer is large enough */ - n = thunar_vfs_path_escape_uri_length (path) + 1; - if (G_UNLIKELY (bufsize < n)) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NAMETOOLONG, - _("URI too long to fit into buffer")); - return -1; - } - - /* copy the URI to the buffer */ - m = thunar_vfs_path_escape_uri (path, buffer); - - /* verify the result */ - _thunar_vfs_assert (strlen (buffer) == m - 1); - _thunar_vfs_assert (m == n); - - return n; -} - - - -/** - * thunar_vfs_path_list_from_string: - * @uri_string : a string representation of an URI list. - * @error : return location for errors. - * - * Splits an URI list conforming to the text/uri-list - * mime type defined in RFC 2483 into individual URIs, - * discarding any comments and whitespace. - * - * If all URIs were successfully parsed into #ThunarVfsPath - * objects, the list of parsed URIs will be returned, and - * you'll need to call thunar_vfs_path_list_free() to - * release the list resources. Else if the parsing fails - * at some point, %NULL will be returned and @error will - * be set to describe the cause. - * - * Note, that if @string contains no URIs, this function - * will also return %NULL, but @error won't be set. So - * take care when checking for an error condition! - * - * Return value: the list of #ThunarVfsPath's or %NULL. - **/ -GList* -thunar_vfs_path_list_from_string (const gchar *uri_string, - GError **error) -{ - ThunarVfsPath *path; - const gchar *s; - const gchar *t; - GList *path_list = NULL; - gchar *identifier; - - for (s = uri_string; s != NULL; ) - { - if (*s != '#') - { - while (g_ascii_isspace (*s)) - ++s; - - for (t = s; *t != '\0' && *t != '\n' && *t != '\r'; ++t) - ; - - if (t > s) - { - for (t--; t > s && g_ascii_isspace (*t); t--) - ; - - if (t > s) - { - /* try to parse the URI */ - identifier = g_strndup (s, t - s + 1); - path = thunar_vfs_path_new (identifier, error); - g_free (identifier); - - /* check if we succeed */ - if (G_UNLIKELY (path == NULL)) - { - thunar_vfs_path_list_free (path_list); - return NULL; - } - else - { - /* append the newly parsed path */ - path_list = g_list_append (path_list, path); - } - } - } - } - - for (; *s != '\0' && *s != '\n'; ++s) - ; - - if (*s++ == '\0') - break; - } - - return path_list; -} - - - -/** - * thunar_vfs_path_list_to_string: - * @path_list : a list of #ThunarVfsPath<!---->s. - * - * Free the returned value using g_free() when you - * are done with it. - * - * Return value: the string representation of @path_list conforming to the - * text/uri-list mime type defined in RFC 2483. - **/ -gchar* -thunar_vfs_path_list_to_string (GList *path_list) -{ - gchar *buffer; - gsize bufsize = 512; - gsize bufpos = 0; - GList *lp; - guint n; - - /* allocate initial buffer */ - buffer = g_malloc (bufsize + 1); - - for (lp = path_list; lp != NULL; lp = lp->next) - { - for (;;) - { - /* determine the size required to store the URI and the line break */ - n = thunar_vfs_path_escape_uri_length (lp->data) + 2; - if (n > (bufsize - bufpos)) - { - /* automatically increase the buffer */ - bufsize += 512; - buffer = g_realloc (buffer, bufsize + 1); - continue; - } - - /* append the URI to the buffer */ - n = thunar_vfs_path_escape_uri (lp->data, buffer + bufpos); - - /* shift the buffer position */ - bufpos += (n - 1); - - /* append a line break */ - buffer[bufpos++] = '\r'; - buffer[bufpos++] = '\n'; - - /* sanity checks */ - _thunar_vfs_assert (bufpos <= bufsize); - break; - } - } - - /* zero terminate the string */ - buffer[bufpos] = '\0'; - - return buffer; -} - - - -/** - * thunar_vfs_path_list_copy: - * @path_list : a list of #ThunarVfsPath<!---->s. - * - * Takes a deep copy of @path_list and returns the - * result. The caller is responsible to free the - * returned list using thunar_vfs_path_list_free(). - * - * Return value: a deep copy of @path_list. - **/ -GList* -thunar_vfs_path_list_copy (GList *path_list) -{ - GList *list; - GList *lp; - - for (list = NULL, lp = g_list_last (path_list); lp != NULL; lp = lp->prev) - list = g_list_prepend (list, thunar_vfs_path_ref (lp->data)); - - return list; -} - - - -/** - * thunar_vfs_path_list_free: - * @path_list : a list of #ThunarVfsPath<!---->s. - * - * Frees the #ThunarVfsPath<!---->s in @path_list and - * the @path_list itself. - **/ -void -thunar_vfs_path_list_free (GList *path_list) -{ - GList *lp; - for (lp = path_list; lp != NULL; lp = lp->next) - thunar_vfs_path_unref (lp->data); - g_list_free (path_list); -} - - - -/** - * _thunar_vfs_path_init: - * - * Intialize the #ThunarVfsPath module. - **/ -void -_thunar_vfs_path_init (void) -{ - ThunarVfsPath *path; - const gchar *s; - gchar *offset; - gchar **components; - gchar **component; - guint n_bytes; - guint n = 0; - gchar *t; - - _thunar_vfs_return_if_fail (home_components == NULL); - _thunar_vfs_return_if_fail (n_home_components == 0); - - /* include the root element */ - n_bytes = sizeof (ThunarVfsPath) + sizeof (gsize); - n_home_components = 1; - - /* split the home path into its components */ - components = g_strsplit (g_get_home_dir (), "/", -1); - for (component = components; *component != NULL; ++component) - if (G_LIKELY (**component != '\0')) - { - n_bytes += sizeof (ThunarVfsPath) + ((strlen (*component) + sizeof (gsize)) / sizeof (gsize)) * sizeof (gsize); - n_home_components += 1; - } - - /* allocate the memory (including the pointer table overhead) */ - home_components = g_malloc (n_bytes + n_home_components * sizeof (ThunarVfsPath *)); - offset = ((gchar *) home_components) + n_home_components * sizeof (ThunarVfsPath *); - - /* add the root node */ - path = (gpointer) offset; - path->ref_count = 1; - path->parent = NULL; - home_components[0] = path; - *((gsize *) thunar_vfs_path_get_name (path)) = THUNAR_VFS_PATH_ROOT; - offset += sizeof (ThunarVfsPath) + sizeof (gsize); - - /* add the remaining path components */ - for (component = components; *component != NULL; ++component) - if (G_LIKELY (**component != '\0')) - { - /* setup the path basics */ - path = (gpointer) offset; - path->ref_count = 1; - path->parent = home_components[n]; - home_components[++n] = path; - - /* calculate the offset for the next home path component */ - offset += sizeof (ThunarVfsPath) + ((strlen (*component) + sizeof (gsize)) / sizeof (gsize)) * sizeof (gsize); - - /* copy the path */ - for (s = *component, t = (gchar *) thunar_vfs_path_get_name (path); *s != '\0'; ) - *t++ = *s++; - - /* fill the path with zeros */ - while (t < offset) - *t++ = '\0'; - } - - /* verify state */ - g_assert (n_home_components == n + 1); - - /* allocate the trash root path */ - _thunar_vfs_path_trash_root = g_malloc (sizeof (ThunarVfsPath) + sizeof (gsize)); - _thunar_vfs_path_trash_root->ref_count = 1 | THUNAR_VFS_PATH_SCHEME_TRASH; - _thunar_vfs_path_trash_root->parent = NULL; - *((gsize *) thunar_vfs_path_get_name (_thunar_vfs_path_trash_root)) = THUNAR_VFS_PATH_ROOT; - - /* cleanup */ - g_strfreev (components); -} - - - -/** - * _thunar_vfs_path_shutdown: - * - * Shutdown the #ThunarVfsPath module. - **/ -void -_thunar_vfs_path_shutdown (void) -{ - guint n; - - _thunar_vfs_return_if_fail (home_components != NULL); - _thunar_vfs_return_if_fail (n_home_components != 0); - - /* print out the list of leaked paths */ - THUNAR_VFS_PATH_DEBUG_SHUTDOWN (); - - for (n = 0; n < n_home_components; ++n) - g_assert (home_components[n]->ref_count == 1); - - g_free (home_components); - home_components = NULL; - n_home_components = 0; - - g_assert (_thunar_vfs_path_trash_root->ref_count == (1 | THUNAR_VFS_PATH_SCHEME_TRASH)); - g_free (_thunar_vfs_path_trash_root); - _thunar_vfs_path_trash_root = NULL; -} - - - -/** - * _thunar_vfs_path_new_relative: - * @parent : the parent path. - * @relative_path : a relative path, or the empty string. - * - * Creates a new #ThunarVfsPath, which represents the subpath of @parent, - * identified by the @relative_path. If @relative_path is the empty string, - * a new reference to @parent will be returned. - * - * The caller is responsible to free the returned #ThunarVfsPath object - * using thunar_vfs_path_unref() when no longer needed. - * - * Return value: the #ThunarVfsPath object to the subpath of @parent - * identified by @relative_path. - **/ -ThunarVfsPath* -_thunar_vfs_path_new_relative (ThunarVfsPath *parent, - const gchar *relative_path) -{ - ThunarVfsPath *path = parent; - const gchar *s1; - const gchar *s = relative_path; - gchar *t; - guint n; - - _thunar_vfs_return_val_if_fail (relative_path != NULL, NULL); - _thunar_vfs_return_val_if_fail (parent != NULL, NULL); - - /* skip additional slashes */ - for (; G_UNLIKELY (*s == G_DIR_SEPARATOR); ++s) - ; - - /* generate the additional path components (if any) */ - while (*s != '\0') - { - /* remember the current path as parent path */ - parent = path; - - /* determine the length of the path component in bytes */ - for (s1 = s + 1; *s1 != '\0' && *s1 != G_DIR_SEPARATOR; ++s1) - ; - n = (((s1 - s) + sizeof (gsize)) / sizeof (gsize)) * sizeof (gsize) - + sizeof (ThunarVfsPath); - - /* allocate memory for the new path component */ - path = _thunar_vfs_slice_alloc (n); - path->ref_count = thunar_vfs_path_get_scheme (parent); - path->parent = thunar_vfs_path_ref (parent); - - /* insert the path into the debug list */ - THUNAR_VFS_PATH_DEBUG_INSERT (path); - - /* zero out the last word to have the name zero-terminated */ - *(((gsize *) (((gchar *) path) + n)) - 1) = 0; - - /* copy the path component name */ - for (t = (gchar *) thunar_vfs_path_get_name (path); *s != '\0' && *s != G_DIR_SEPARATOR; ) - *t++ = *s++; - - /* skip additional slashes */ - for (; G_UNLIKELY (*s == G_DIR_SEPARATOR); ++s) - ; - } - - /* return a reference to the path */ - return thunar_vfs_path_ref (path); -} - - - -/** - * _thunar_vfs_path_child: - * @parent : a #ThunarVfsPath. - * @name : a valid filename in the local file system encoding. - * - * Internal implementation of thunar_vfs_path_relative(), that performs - * no external sanity checking of it's parameters. - * - * Returns a #ThunarVfsPath for the file @name relative to - * @parent. @name must be a valid filename in the local file - * system encoding and it may not contain any slashes. - * - * The caller is responsible to free the returned object - * using thunar_vfs_path_unref() when no longer needed. - * - * Return value: the child path to @name relative to @parent. - **/ -ThunarVfsPath* -_thunar_vfs_path_child (ThunarVfsPath *parent, - const gchar *name) -{ - ThunarVfsPath *path; - const gchar *s; - gchar *t; - gint n; - - _thunar_vfs_return_val_if_fail (parent != NULL, NULL); - _thunar_vfs_return_val_if_fail (name != NULL, NULL); - _thunar_vfs_return_val_if_fail (*name != '\0', NULL); - _thunar_vfs_return_val_if_fail (strchr (name, '/') == NULL, NULL); - - /* check if parent is one of the home path components */ - for (n = n_home_components - 2; n >= 0; --n) - if (G_UNLIKELY (home_components[n] == parent)) - { - /* check if the name equals the home path child component */ - if (strcmp (name, thunar_vfs_path_get_name (home_components[n + 1])) == 0) - return thunar_vfs_path_ref (home_components[n + 1]); - break; - } - - /* determine the length of the name in bytes */ - for (s = name + 1; *s != '\0'; ++s) - ; - n = (((s - name) + sizeof (gsize)) / sizeof (gsize)) * sizeof (gsize) - + sizeof (ThunarVfsPath); - - /* allocate memory for the new path component */ - path = _thunar_vfs_slice_alloc (n); - path->ref_count = 1 | thunar_vfs_path_get_scheme (parent); - path->parent = thunar_vfs_path_ref (parent); - - /* insert the path into the debug list */ - THUNAR_VFS_PATH_DEBUG_INSERT (path); - - /* zero out the last word to have the name zero-terminated */ - *(((gsize *) (((gchar *) path) + n)) - 1) = 0; - - /* copy the path component name */ - for (s = name, t = (gchar *) thunar_vfs_path_get_name (path); *s != '\0'; ) - *t++ = *s++; - - return path; -} - - - -/** - * _thunar_vfs_path_dup_display_name: - * @path : a #ThunarVfsPath. - * - * Returns the display name for the @path<!---->s name. That said, - * the method is similar to thunar_vfs_path_get_name(), but the - * returned string is garantied to be valid UTF-8. - * - * The caller is responsible to free the returned string using - * g_free() when no longer needed. - * - * Return value: a displayable variant of the @path<!---->s name. - **/ -gchar* -_thunar_vfs_path_dup_display_name (const ThunarVfsPath *path) -{ - return g_filename_display_name (thunar_vfs_path_get_name (path)); -} - - - -/** - * _thunar_vfs_path_translate: - * @src_path : the source #ThunarVfsPath. - * @dst_scheme : the destination #ThunarVfsPathScheme. - * @error : return location for errors or %NULL. - * - * Translates the @src_path to the specified @dst_scheme if possible. - * - * If the @src_path is already in the @dst_scheme, a new reference - * on @src_path will be returned. - * - * The caller is responsible to free the returned #ThunarVfsPath using - * thunar_vfs_path_unref() when no longer needed. - * - * Return value: the #ThunarVfsPath that corresponds to @src_path in the - * @dst_scheme, or %NULL on error. - **/ -ThunarVfsPath* -_thunar_vfs_path_translate (ThunarVfsPath *src_path, - ThunarVfsPathScheme dst_scheme, - GError **error) -{ - ThunarVfsPathScheme src_scheme; - ThunarVfsPath *dst_path = NULL; - gchar *absolute_path; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* check if the src_path is already in dst_scheme */ - src_scheme = thunar_vfs_path_get_scheme (src_path); - if (G_LIKELY (dst_scheme == src_scheme)) - return thunar_vfs_path_ref (src_path); - - /* we can translate trash:-URIs to file:-URIs */ - if (src_scheme == THUNAR_VFS_PATH_SCHEME_TRASH && dst_scheme == THUNAR_VFS_PATH_SCHEME_FILE) - { - /* resolve the local path to the trash resource */ - absolute_path = _thunar_vfs_io_trash_path_resolve (src_path, error); - if (G_LIKELY (absolute_path != NULL)) - { - /* generate a file:-URI path for the trash resource */ - dst_path = thunar_vfs_path_new (absolute_path, error); - g_free (absolute_path); - } - } - else - { - /* cannot perform the translation */ - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, "%s", g_strerror (EINVAL)); - } - - return dst_path; -} - - - -/** - * _thunar_vfs_path_translate_dup_string: - * @src_path : the source #ThunarVfsPath. - * @dst_scheme : the destination #ThunarVfsPathScheme. - * @error : return location for errors or %NULL. - * - * Uses _thunar_vfs_path_translate() and thunar_vfs_path_dup_string() - * to generate the string representation of the @src_path in the - * @dst_scheme. - * - * The caller is responsible to free the returned string using - * g_free() when no longer needed. - * - * Return value: the string representation of the @src_path in the - * @dst_scheme, or %NULL in case of an error. - **/ -gchar* -_thunar_vfs_path_translate_dup_string (ThunarVfsPath *src_path, - ThunarVfsPathScheme dst_scheme, - GError **error) -{ - ThunarVfsPath *dst_path; - gchar *dst_string; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* handle the common case first */ - if (G_LIKELY (dst_scheme == THUNAR_VFS_PATH_SCHEME_FILE)) - { - if (_thunar_vfs_path_is_local (src_path)) - return thunar_vfs_path_dup_string (src_path); - else if (_thunar_vfs_path_is_trash (src_path)) - return _thunar_vfs_io_trash_path_resolve (src_path, error); - } - - /* translate the source path to the destination scheme */ - dst_path = _thunar_vfs_path_translate (src_path, dst_scheme, error); - if (G_LIKELY (dst_path != NULL)) - { - /* determine the string representation */ - dst_string = thunar_vfs_path_dup_string (dst_path); - thunar_vfs_path_unref (dst_path); - } - else - { - /* we failed to translate */ - dst_string = NULL; - } - - return dst_string; -} - - - -#define __THUNAR_VFS_PATH_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-path.h b/thunar-vfs/thunar-vfs-path.h deleted file mode 100644 index 4949f257d..000000000 --- a/thunar-vfs/thunar-vfs-path.h +++ /dev/null @@ -1,279 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_PATH_H__ -#define __THUNAR_VFS_PATH_H__ - -#include <thunar-vfs/thunar-vfs-config.h> - -G_BEGIN_DECLS; - -/** - * ThunarVfsPathScheme: - * @THUNAR_VFS_PATH_SCHEME_FILE : path to local files. - * @THUNAR_VFS_PATH_SCHEME_TRASH : path to files in the trash can. - * @THUNAR_VFS_PATH_SCHEME_MASK : bit mask for path scheme, an - * implementation detail, should - * not be used outside ThunarVFS. - * - * The scheme, or the type, of resource a #ThunarVfsPath refers to. - * This currently includes local files which are accessible via - * standard Unix paths, and trashed files, which are accessible - * via trash:-URIs. - * - * Since: 0.3.3 - **/ -typedef enum /*< skip >*/ -{ - THUNAR_VFS_PATH_SCHEME_FILE = 0x00000000, - THUNAR_VFS_PATH_SCHEME_TRASH = 0x40000000, - THUNAR_VFS_PATH_SCHEME_MASK = 0x40000000, -} ThunarVfsPathScheme; - -/** - * THUNAR_VFS_PATH_MAXSTRLEN: - * - * The maximum length of a path string in bytes that - * can be handled by #ThunarVfsPath objects. - **/ -#if defined(PATH_MAX) -#define THUNAR_VFS_PATH_MAXSTRLEN (PATH_MAX + 1) -#else -#define THUNAR_VFS_PATH_MAXSTRLEN (4 * 1024 + 1) -#endif - -/** - * THUNAR_VFS_PATH_MAXURILEN: - * - * The maximum length of an URI string in bytes that - * will be produced by thunar_vfs_path_to_uri() and - * friends. - **/ -#define THUNAR_VFS_PATH_MAXURILEN (THUNAR_VFS_PATH_MAXSTRLEN * 3 - 2) - -/** - * THUNAR_VFS_TYPE_PATH: - * - * Returns the type id of the #ThunarVfsPath type, which is a boxed - * type. - **/ -#define THUNAR_VFS_TYPE_PATH (thunar_vfs_path_get_type ()) - -/** - * THUNAR_VFS_TYPE_PATH_LIST: - * - * Returns the type id for #GList<!---->s of #ThunarVfsPath<!---->s, - * which is a boxed type. - * - * Since: 0.3.3 - **/ -#define THUNAR_VFS_TYPE_PATH_LIST (thunar_vfs_path_list_get_type ()) - -#define THUNAR_VFS_PATH(obj) ((ThunarVfsPath *) (obj)) -typedef struct _ThunarVfsPath ThunarVfsPath; -struct _ThunarVfsPath -{ - /*< private >*/ - gint ref_count; - ThunarVfsPath *parent; -}; - -GType thunar_vfs_path_get_type (void) G_GNUC_CONST; -GType thunar_vfs_path_list_get_type (void) G_GNUC_CONST; - -ThunarVfsPath *thunar_vfs_path_new (const gchar *identifier, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsPath *thunar_vfs_path_get_for_home (void) G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsPath *thunar_vfs_path_get_for_root (void) G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsPath *thunar_vfs_path_get_for_trash (void) G_GNUC_WARN_UNUSED_RESULT; - -G_INLINE_FUNC ThunarVfsPath *thunar_vfs_path_ref (ThunarVfsPath *path); -void thunar_vfs_path_unref (ThunarVfsPath *path); - -guint thunar_vfs_path_hash (gconstpointer path_ptr); -gboolean thunar_vfs_path_equal (gconstpointer path_ptr_a, - gconstpointer path_ptr_b); - -ThunarVfsPath *thunar_vfs_path_relative (ThunarVfsPath *parent, - const gchar *name) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -gboolean thunar_vfs_path_is_ancestor (const ThunarVfsPath *path, - const ThunarVfsPath *ancestor); -gboolean thunar_vfs_path_is_home (const ThunarVfsPath *path); -G_INLINE_FUNC gboolean thunar_vfs_path_is_root (const ThunarVfsPath *path); - -G_INLINE_FUNC const gchar *thunar_vfs_path_get_name (const ThunarVfsPath *path); -G_INLINE_FUNC ThunarVfsPath *thunar_vfs_path_get_parent (const ThunarVfsPath *path); -G_INLINE_FUNC ThunarVfsPathScheme thunar_vfs_path_get_scheme (const ThunarVfsPath *path); - -gchar *thunar_vfs_path_dup_string (const ThunarVfsPath *path) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gssize thunar_vfs_path_to_string (const ThunarVfsPath *path, - gchar *buffer, - gsize bufsize, - GError **error); - -gchar *thunar_vfs_path_dup_uri (const ThunarVfsPath *path) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gssize thunar_vfs_path_to_uri (const ThunarVfsPath *path, - gchar *buffer, - gsize bufsize, - GError **error); - - -GList *thunar_vfs_path_list_from_string (const gchar *uri_string, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gchar *thunar_vfs_path_list_to_string (GList *path_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -G_INLINE_FUNC GList *thunar_vfs_path_list_append (GList *path_list, - ThunarVfsPath *path) G_GNUC_WARN_UNUSED_RESULT; -G_INLINE_FUNC GList *thunar_vfs_path_list_prepend (GList *path_list, - ThunarVfsPath *path) G_GNUC_WARN_UNUSED_RESULT; -GList *thunar_vfs_path_list_copy (GList *path_list) G_GNUC_WARN_UNUSED_RESULT; -void thunar_vfs_path_list_free (GList *path_list); - - -/* inline function implementations */ -#if defined(G_CAN_INLINE) || defined(__THUNAR_VFS_PATH_C__) -/** - * thunar_vfs_path_ref: - * @path : a #ThunarVfsPath. - * - * Increments the reference count on @path - * and returns a reference to @path. - * - * Return value: a reference to @path. - **/ -G_INLINE_FUNC ThunarVfsPath* -thunar_vfs_path_ref (ThunarVfsPath *path) -{ - exo_atomic_inc (&path->ref_count); - return path; -} - -/** - * thunar_vfs_path_is_root: - * @path : a #ThunarVfsPath. - * - * Checks whether path refers to the root directory. - * - * Return value: %TRUE if @path refers to the root - * directory. - **/ -G_INLINE_FUNC gboolean -thunar_vfs_path_is_root (const ThunarVfsPath *path) -{ - return (path->parent == NULL); -} - -/** - * thunar_vfs_path_get_name: - * @path : a #ThunarVfsPath. - * - * Returns the base name of the @path in the local - * file system encoding. - * - * Return value: the base name of @path. - **/ -G_INLINE_FUNC const gchar* -thunar_vfs_path_get_name (const ThunarVfsPath *path) -{ - return ((const gchar *) path) + sizeof (*path); -} - -/** - * thunar_vfs_path_get_parent: - * @path : a #ThunarVfsPath. - * - * Returns the #ThunarVfsPath that refers to the parent - * directory of @path or %NULL if @path refers to the - * root file system node. - * - * No additional reference is taken on the parent, so - * you'll need to call thunar_vfs_path_ref() yourself - * if you need to keep a reference. - * - * Return value: the parent of @path or %NULL. - **/ -G_INLINE_FUNC ThunarVfsPath* -thunar_vfs_path_get_parent (const ThunarVfsPath *path) -{ - return path->parent; -} - -/** - * thunar_vfs_path_get_scheme: - * @path : a #ThunarVfsPath. - * - * Returns the #ThunarVfsPathScheme of the specified - * @path. - * - * Return value: the scheme of the @path. - * - * Since: 0.3.3 - **/ -G_INLINE_FUNC ThunarVfsPathScheme -thunar_vfs_path_get_scheme (const ThunarVfsPath *path) -{ - return (path->ref_count & THUNAR_VFS_PATH_SCHEME_MASK); -} - -/** - * thunar_vfs_path_list_append: - * @path_list : a list of #ThunarVfsPath<!---->s. - * @path : a #ThunarVfsPath. - * - * Appends @path to the @path_list while taking - * an additional reference for @path. - * - * Return value: pointer to the extended @path_list. - **/ -G_INLINE_FUNC GList* -thunar_vfs_path_list_append (GList *path_list, - ThunarVfsPath *path) -{ - thunar_vfs_path_ref (path); - return g_list_append (path_list, path); -} - -/** - * thunar_vfs_path_list_prepend: - * @path_list : a list of #ThunarVfsPath<!---->s. - * @path : a #ThunarVfsPath. - * - * Similar to thunar_vfs_path_list_append(), but - * prepends the @path to the @path_list. - * - * Return value: pointer to the extended @path_list. - **/ -G_INLINE_FUNC GList* -thunar_vfs_path_list_prepend (GList *path_list, - ThunarVfsPath *path) -{ - thunar_vfs_path_ref (path); - return g_list_prepend (path_list, path); -} -#endif /* G_CAN_INLINE || __THUNAR_VFS_PATH_C__ */ - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_PATH_H__ */ diff --git a/thunar-vfs/thunar-vfs-pixbuf-thumbnailer.c b/thunar-vfs/thunar-vfs-pixbuf-thumbnailer.c deleted file mode 100644 index 5e71986fa..000000000 --- a/thunar-vfs/thunar-vfs-pixbuf-thumbnailer.c +++ /dev/null @@ -1,85 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2004-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/******************************************************************************** - * WHAT IS THIS? * - * * - * Fast thumbnail generator for image formats supported by gdk-pixbuf. Uses * - * mmap() if available to offer fast loading of images up to 8MB. The generated * - * thumbnail is stored into a local file, usually a temporary file, as speci- * - * fied by the 3rd parameter. * - ********************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#include <exo/exo.h> - - - -int -main (int argc, char **argv) -{ - GdkPixbuf *pixbuf; - GError *err = NULL; - glong size; - - /* check the command line parameters */ - if (G_UNLIKELY (argc != 4)) - { - fprintf (stderr, "Usage: %s <size> <input-file> <output-file>\n", argv[0]); - return EXIT_FAILURE; - } - - /* determine the size */ - size = strtol (argv[1], NULL, 10); - if (G_UNLIKELY (size < 1 || size > 256)) - { - fprintf (stderr, "%s: Invalid size %ld.\n", argv[0], size); - return EXIT_FAILURE; - } - - /* initialize the GType system */ - g_type_init (); - - /* try to load the input image file */ - pixbuf = exo_gdk_pixbuf_new_from_file_at_max_size (argv[2], size, size, TRUE, &err); - if (G_UNLIKELY (pixbuf == NULL)) - { - fprintf (stderr, "%s: %s.\n", argv[0], err->message); - return EXIT_FAILURE; - } - /* try to save to the target location */ - if (!gdk_pixbuf_save (pixbuf, argv[3], "png", &err, NULL)) - { - fprintf (stderr, "%s: Failed to write file %s: %s\n", argv[0], argv[3], err->message); - return EXIT_FAILURE; - } - - /* we did it */ - return EXIT_SUCCESS; -} - diff --git a/thunar-vfs/thunar-vfs-private.c b/thunar-vfs/thunar-vfs-private.c deleted file mode 100644 index b3c8493e0..000000000 --- a/thunar-vfs/thunar-vfs-private.c +++ /dev/null @@ -1,438 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STDARG_H -#include <stdarg.h> -#endif -#include <stdio.h> -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -/* Use g_fopen() on win32 */ -#if defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_fopen(filename, mode) (fopen ((filename), (mode))) -#endif - -#include <thunar-vfs/thunar-vfs-monitor.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/** - * _thunar_vfs_g_type_register_simple: - * @type_parent : the parent #GType. - * @type_name_static : the name of the new type, allocated on static storage, - * must not change during the lifetime of the process. - * @class_size : the size of the class structure in bytes. - * @class_init : the class initialization function or %NULL. - * @instance_size : the size of the instance structure in bytes. - * @instance_init : the constructor function or %NULL. - * @flags : the #GTypeFlags or %0. - * - * Simple wrapper for g_type_register_static(), used to reduce the - * number of relocations required for the various #GTypeInfo<!---->s. - * - * Return value: the newly registered #GType. - **/ -GType -_thunar_vfs_g_type_register_simple (GType type_parent, - const gchar *type_name_static, - guint class_size, - gpointer class_init, - guint instance_size, - gpointer instance_init, - GTypeFlags flags) -{ - /* setup the type info on the stack */ - GTypeInfo info = - { - class_size, - NULL, - NULL, - (GClassInitFunc) class_init, - NULL, - NULL, - instance_size, - 0, - (GInstanceInitFunc) instance_init, - NULL, - }; - - /* register the new type */ - return g_type_register_static (type_parent, I_(type_name_static), &info, 0); -} - - - -/** - * _thunar_vfs_g_value_array_free: - * @values : an array of #GValue<!---->s. - * @n_values : the number of #GValue<!---->s in @values. - * - * Calls g_value_unset() for all items in @values and frees - * the @values using g_free(). - **/ -void -_thunar_vfs_g_value_array_free (GValue *values, - guint n_values) -{ - _thunar_vfs_return_if_fail (values != NULL); - - while (n_values-- > 0) - g_value_unset (values + n_values); - g_free (values); -} - - - -/** - * _thunar_vfs_check_only_local: - * @path_list : a #GList of #ThunarVfsPath<!---->s. - * @error : return location for errors or %NULL. - * - * Verifies that all #ThunarVfsPath<!---->s in the @path_list are - * local paths with scheme %THUNAR_VFS_PATH_SCHEME_FILE. If the - * check fails, @error will be initialized to an #GError with - * %G_FILE_ERROR_INVAL and %FALSE will be returned. - * - * Return value: %TRUE if the check succeeds, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_check_only_local (GList *path_list, - GError **error) -{ - GList *lp; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* check all paths in the path_list */ - for (lp = path_list; lp != NULL; lp = lp->next) - if (!_thunar_vfs_path_is_local (lp->data)) - break; - - /* check if any path failed the check */ - if (G_UNLIKELY (lp != NULL)) - { - _thunar_vfs_set_g_error_not_supported (error); - return FALSE; - } - - return TRUE; -} - - - -/** - * _thunar_vfs_set_g_error_from_errno: - * @error : pointer to a #GError to set, or %NULL. - * @serrno : the errno value to set the @error to. - * - * If @error is not %NULL it will be initialized to the errno - * value in @serrno. - **/ -void -_thunar_vfs_set_g_error_from_errno (GError **error, - gint serrno) -{ - /* allocate a GError for the specified errno value */ - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (serrno), "%s", g_strerror (serrno)); -} - - - -/** - * _thunar_vfs_set_g_error_from_errno2: - * @error : pointer to a #GError to set, or %NULL. - * @serrno : the errno value to set the @error to. - * @format : a printf(3)-style format string. - * @... : arguments for the @format string. - * - * Similar to _thunar_vfs_set_g_error_from_errno(), but - * allows to specify an additional string for the error - * message text. - **/ -void -_thunar_vfs_set_g_error_from_errno2 (GError **error, - gint serrno, - const gchar *format, - ...) -{ - va_list var_args; - gchar *message; - - /* allocate a GError for the specified errno value */ - va_start (var_args, format); - message = g_strdup_vprintf (format, var_args); - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (serrno), - "%s: %s", message, g_strerror (serrno)); - va_end (var_args); - g_free (message); -} - - - -/** - * _thunar_vfs_set_g_error_from_errno3: - * @error : pointer to a #GError to set, or %NULL. - * - * Similar to _thunar_vfs_set_g_error_from_errno(), but uses - * the global errno value for this thread instead of taking - * the errno value from a parameter. - **/ -void -_thunar_vfs_set_g_error_from_errno3 (GError **error) -{ - /* allocate a GError for the global errno value */ - _thunar_vfs_set_g_error_from_errno (error, errno); -} - - - -/** - * _thunar_vfs_set_g_error_not_supported: - * @error : pointer to a #GError to set, or %NULL. - * - * Sets @error to point to a #GError telling that a - * certain operation is not supported. - **/ -void -_thunar_vfs_set_g_error_not_supported (GError **error) -{ - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOSYS, _("Operation not supported")); -} - - - -static inline gint -unescape_character (const gchar *s) -{ - gint first_digit; - gint second_digit; - - first_digit = g_ascii_xdigit_value (s[0]); - if (first_digit < 0) - return -1; - - second_digit = g_ascii_xdigit_value (s[1]); - if (second_digit < 0) - return -1; - - return (first_digit << 4) | second_digit; -} - - - -/** - * _thunar_vfs_unescape_rfc2396_string: - * @escaped_string : the escaped string. - * @escaped_len : the length of @escaped_string or %-1. - * @illegal_escaped_characters : the characters that may not appear escaped - * in @escaped_string. - * @ascii_must_not_be_escaped : %TRUE to disallow escaped ASCII characters. - * @error : return location for errors or %NULL. - * - * Unescapes the @escaped_string according to RFC 2396. - * - * Return value: the unescaped string or %NULL in case of an error. - **/ -gchar* -_thunar_vfs_unescape_rfc2396_string (const gchar *escaped_string, - gssize escaped_len, - const gchar *illegal_escaped_characters, - gboolean ascii_must_not_be_escaped, - GError **error) -{ - const gchar *s; - gchar *unescaped_string; - gchar *t; - gint c; - - _thunar_vfs_return_val_if_fail (illegal_escaped_characters != NULL, NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* verify that we have a valid string */ - if (G_UNLIKELY (escaped_string == NULL)) - return NULL; - - /* determine the length on-demand */ - if (G_UNLIKELY (escaped_len < 0)) - escaped_len = strlen (escaped_string); - - /* proces the escaped string */ - unescaped_string = g_malloc (escaped_len + 1); - for (s = escaped_string, t = unescaped_string;; ++s) - { - /* determine the next character */ - c = *s; - if (c == '\0') - break; - - /* handle escaped characters */ - if (G_UNLIKELY (c == '%')) - { - /* catch partial escape sequence past the end of the substring */ - if (s[1] == '\0' || s[2] == '\0') - goto error; - - /* unescape the character */ - c = unescape_character (s + 1); - - /* catch bad escape sequences and NUL characters */ - if (c <= 0) - goto error; - - /* catch escaped ASCII */ - if (ascii_must_not_be_escaped && c > 0x1f && c <= 0x7f) - goto error; - - /* catch other illegal escaped characters */ - if (strchr (illegal_escaped_characters, c) != NULL) - goto error; - - s += 2; - } - - *t++ = c; - } - *t = '\0'; - - return unescaped_string; - -error: - /* TRANSLATORS: This error indicates that an URI contains an invalid escaped character (RFC 2396) */ - g_set_error (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI, _("Invalidly escaped characters")); - g_free (unescaped_string); - return NULL; -} - - - -/** - * _thunar_vfs_desktop_file_set_value: - * @filename : the absolute path to a .desktop file. - * @key : the key in the @filename to update. - * @value : the new value for the @key. - * @error : return location for errors or %NULL. - * - * Sets the @key in @filename to @value. If @key appears localized in @filename, - * it will be set in the current locale if present, falling back to the unlocalized - * setting. - * - * Return value: %TRUE if the @key in the @filename was successfully updated to - * @value, %FALSE otherwise. - **/ -gboolean -_thunar_vfs_desktop_file_set_value (const gchar *filename, - const gchar *key, - const gchar *value, - GError **error) -{ - const gchar * const *locale; - GKeyFile *key_file; - gsize data_length; - gchar *data; - gchar *key_localized; - FILE *fp; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (g_utf8_validate (key, -1, NULL), FALSE); - _thunar_vfs_return_val_if_fail (g_path_is_absolute (filename), FALSE); - - /* try to open the .desktop file */ - key_file = g_key_file_new (); - if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, error)) - { -err0: g_key_file_free (key_file); - return FALSE; - } - - /* check if the file is valid */ - if (G_UNLIKELY (!g_key_file_has_group (key_file, "Desktop Entry"))) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid desktop file")); - goto err0; - } - - /* save the new value (localized if required) */ - for (locale = g_get_language_names (); *locale != NULL; ++locale) - { - key_localized = g_strdup_printf ("%s[%s]", key, *locale); - if (g_key_file_has_key (key_file, "Desktop Entry", key_localized, NULL)) - { - g_key_file_set_string (key_file, "Desktop Entry", key_localized, value); - g_free (key_localized); - break; - } - g_free (key_localized); - } - - /* fallback to unlocalized value */ - if (G_UNLIKELY (*locale == NULL)) - g_key_file_set_string (key_file, "Desktop Entry", key, value); - - /* serialize the key_file to a buffer */ - data = g_key_file_to_data (key_file, &data_length, error); - g_key_file_free (key_file); - if (G_UNLIKELY (data == NULL)) - return FALSE; - - /* try to open the file for writing */ - fp = g_fopen (filename, "w"); - if (G_UNLIKELY (fp == NULL)) - { - _thunar_vfs_set_g_error_from_errno3 (error); -err1: g_free (data); - return FALSE; - } - - /* write the data back to the file */ - if (fwrite (data, data_length, 1, fp) != 1) - { - _thunar_vfs_set_g_error_from_errno3 (error); - fclose (fp); - goto err1; - } - - /* cleanup */ - g_free (data); - fclose (fp); - - return TRUE; -} - - - -#define __THUNAR_VFS_PRIVATE_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-private.h b/thunar-vfs/thunar-vfs-private.h deleted file mode 100644 index c0c3ee4a3..000000000 --- a/thunar-vfs/thunar-vfs-private.h +++ /dev/null @@ -1,126 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_PRIVATE_H__ -#define __THUNAR_VFS_PRIVATE_H__ - -#include <thunar-vfs/thunar-vfs-config.h> - -G_BEGIN_DECLS; - -/* support macros for debugging */ -#ifndef NDEBUG -#define _thunar_vfs_assert(expr) g_assert (expr) -#define _thunar_vfs_assert_not_reached() g_assert_not_reached () -#define _thunar_vfs_return_if_fail(expr) g_return_if_fail (expr) -#define _thunar_vfs_return_val_if_fail(expr, val) g_return_val_if_fail (expr, (val)) -#else -#define _thunar_vfs_assert(expr) G_STMT_START{ (void)0; }G_STMT_END -#define _thunar_vfs_assert_not_reached() G_STMT_START{ (void)0; }G_STMT_END -#define _thunar_vfs_return_if_fail(expr) G_STMT_START{ (void)0; }G_STMT_END -#define _thunar_vfs_return_val_if_fail(expr, val) G_STMT_START{ (void)0; }G_STMT_END -#endif - -/* support macros for the slice allocator */ -#if GLIB_CHECK_VERSION(2,10,0) -#define _thunar_vfs_slice_alloc(block_size) (g_slice_alloc ((block_size))) -#define _thunar_vfs_slice_alloc0(block_size) (g_slice_alloc0 ((block_size))) -#define _thunar_vfs_slice_free1(block_size, mem_block) G_STMT_START{ g_slice_free1 ((block_size), (mem_block)); }G_STMT_END -#define _thunar_vfs_slice_new(type) (g_slice_new (type)) -#define _thunar_vfs_slice_new0(type) (g_slice_new0 (type)) -#define _thunar_vfs_slice_free(type, ptr) G_STMT_START{ g_slice_free (type, (ptr)); }G_STMT_END -#else -#define _thunar_vfs_slice_alloc(block_size) (g_malloc ((block_size))) -#define _thunar_vfs_slice_alloc0(block_size) (g_malloc0 ((block_size))) -#define _thunar_vfs_slice_free1(block_size, mem_block) G_STMT_START{ g_free ((mem_block)); }G_STMT_END -#define _thunar_vfs_slice_new(type) (g_new (type, 1)) -#define _thunar_vfs_slice_new0(type) (g_new0 (type, 1)) -#define _thunar_vfs_slice_free(type, ptr) G_STMT_START{ g_free ((ptr)); }G_STMT_END -#endif - -/* avoid trivial g_value_get_*() function calls */ -#ifdef NDEBUG -#define g_value_get_boolean(v) (((const GValue *) (v))->data[0].v_int) -#define g_value_get_char(v) (((const GValue *) (v))->data[0].v_int) -#define g_value_get_uchar(v) (((const GValue *) (v))->data[0].v_uint) -#define g_value_get_int(v) (((const GValue *) (v))->data[0].v_int) -#define g_value_get_uint(v) (((const GValue *) (v))->data[0].v_uint) -#define g_value_get_long(v) (((const GValue *) (v))->data[0].v_long) -#define g_value_get_ulong(v) (((const GValue *) (v))->data[0].v_ulong) -#define g_value_get_int64(v) (((const GValue *) (v))->data[0].v_int64) -#define g_value_get_uint64(v) (((const GValue *) (v))->data[0].v_uint64) -#define g_value_get_enum(v) (((const GValue *) (v))->data[0].v_long) -#define g_value_get_flags(v) (((const GValue *) (v))->data[0].v_ulong) -#define g_value_get_float(v) (((const GValue *) (v))->data[0].v_float) -#define g_value_get_double(v) (((const GValue *) (v))->data[0].v_double) -#define g_value_get_string(v) (((const GValue *) (v))->data[0].v_pointer) -#define g_value_get_param(v) (((const GValue *) (v))->data[0].v_pointer) -#define g_value_get_boxed(v) (((const GValue *) (v))->data[0].v_pointer) -#define g_value_get_pointer(v) (((const GValue *) (v))->data[0].v_pointer) -#define g_value_get_object(v) (((const GValue *) (v))->data[0].v_pointer) -#endif - -/* GType registration routines */ -GType _thunar_vfs_g_type_register_simple (GType type_parent, - const gchar *type_name_static, - guint class_size, - gpointer class_init, - guint instance_size, - gpointer instance_init, - GTypeFlags flags) G_GNUC_INTERNAL; - -/* GType value routines */ -void _thunar_vfs_g_value_array_free (GValue *values, - guint n_values) G_GNUC_INTERNAL; - -/* path scheme checking routines */ -gboolean _thunar_vfs_check_only_local (GList *path_list, - GError **error) G_GNUC_INTERNAL; - -/* error reporting routines */ -void _thunar_vfs_set_g_error_from_errno (GError **error, - gint serrno) G_GNUC_INTERNAL; -void _thunar_vfs_set_g_error_from_errno2 (GError **error, - gint serrno, - const gchar *format, - ...) G_GNUC_INTERNAL G_GNUC_PRINTF (3, 4); -void _thunar_vfs_set_g_error_from_errno3 (GError **error) G_GNUC_INTERNAL; -void _thunar_vfs_set_g_error_not_supported (GError **error) G_GNUC_INTERNAL; - -/* RFC 2396 support routines */ -gchar *_thunar_vfs_unescape_rfc2396_string (const gchar *escaped_string, - gssize escaped_len, - const gchar *illegal_escaped_characters, - gboolean ascii_must_not_be_escaped, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -/* .desktop file handling */ -gboolean _thunar_vfs_desktop_file_set_value (const gchar *filename, - const gchar *key, - const gchar *value, - GError **error) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_PRIVATE_H__ */ diff --git a/thunar-vfs/thunar-vfs-simple-job.c b/thunar-vfs/thunar-vfs-simple-job.c deleted file mode 100644 index ba1cd8f3b..000000000 --- a/thunar-vfs/thunar-vfs-simple-job.c +++ /dev/null @@ -1,203 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STDARG_H -#include <stdarg.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#include <thunar-vfs/thunar-vfs-interactive-job.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-simple-job.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -#include <gobject/gvaluecollector.h> - - - -static void thunar_vfs_simple_job_class_init (ThunarVfsSimpleJobClass *klass); -static void thunar_vfs_simple_job_finalize (GObject *object); -static void thunar_vfs_simple_job_execute (ThunarVfsJob *job); - - - -struct _ThunarVfsSimpleJobClass -{ - ThunarVfsInteractiveJobClass __parent__; -}; - -struct _ThunarVfsSimpleJob -{ - ThunarVfsInteractiveJob __parent__; - ThunarVfsSimpleJobFunc func; - GValue *param_values; - guint n_param_values; -}; - - - -static GObjectClass *thunar_vfs_simple_job_parent_class; - - - -GType -thunar_vfs_simple_job_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_INTERACTIVE_JOB, - "ThunarVfsSimpleJob", - sizeof (ThunarVfsSimpleJobClass), - thunar_vfs_simple_job_class_init, - sizeof (ThunarVfsSimpleJob), - NULL, 0); - } - - return type; -} - - - -static void -thunar_vfs_simple_job_class_init (ThunarVfsSimpleJobClass *klass) -{ - ThunarVfsJobClass *thunarvfs_job_class; - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_simple_job_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_simple_job_finalize; - - thunarvfs_job_class = THUNAR_VFS_JOB_CLASS (klass); - thunarvfs_job_class->execute = thunar_vfs_simple_job_execute; -} - - - -static void -thunar_vfs_simple_job_finalize (GObject *object) -{ - ThunarVfsSimpleJob *simple_job = THUNAR_VFS_SIMPLE_JOB (object); - - /* release the param values */ - _thunar_vfs_g_value_array_free (simple_job->param_values, simple_job->n_param_values); - - (*G_OBJECT_CLASS (thunar_vfs_simple_job_parent_class)->finalize) (object); -} - - - -static void -thunar_vfs_simple_job_execute (ThunarVfsJob *job) -{ - ThunarVfsSimpleJob *simple_job = THUNAR_VFS_SIMPLE_JOB (job); - GError *error = NULL; - - /* try to execute the job using the supplied function */ - if (!(*simple_job->func) (job, simple_job->param_values, simple_job->n_param_values, &error)) - { - /* forward the error to the client */ - _thunar_vfs_job_error (job, error); - g_error_free (error); - } -} - - - -/** - * thunar_vfs_simple_job_launch: - * @func : the #ThunarVfsSimpleJobFunc to execute the job. - * @n_param_values : the number of parameters to pass to the @func. - * @... : a list of #GType and parameter pairs (exactly - * @n_param_values pairs) that are passed to @func. - * - * Allocates a new #ThunarVfsSimpleJob, which executes the specified - * @func with the specified parameters. - * - * For example the listdir @func expects a #ThunarVfsPath for the - * folder to list, so the call to thunar_vfs_simple_job_launch() - * would look like this: - * - * <informalexample><programlisting> - * thunar_vfs_simple_job_launch (_thunar_vfs_io_jobs_listdir, 1, - * THUNAR_VFS_TYPE_PATH, path); - * </programlisting></informalexample> - * - * The caller is responsible to release the returned object using - * thunar_vfs_job_unref() when no longer needed. - * - * Return value: the launched #ThunarVfsJob. - **/ -ThunarVfsJob* -thunar_vfs_simple_job_launch (ThunarVfsSimpleJobFunc func, - guint n_param_values, - ...) -{ - ThunarVfsSimpleJob *simple_job; - va_list var_args; - GValue *value; - gchar *error_message; - - /* allocate and initialize the simple job */ - simple_job = g_object_new (THUNAR_VFS_TYPE_SIMPLE_JOB, NULL); - simple_job->func = func; - simple_job->param_values = g_new0 (GValue, n_param_values); - simple_job->n_param_values = n_param_values; - - /* collect the parameters */ - va_start (var_args, n_param_values); - for (value = simple_job->param_values; value < simple_job->param_values + n_param_values; ++value) - { - /* initialize the value to hold the next parameter */ - g_value_init (value, va_arg (var_args, GType)); - - /* collect the value from the stack */ - G_VALUE_COLLECT (value, var_args, 0, &error_message); - - /* check if an error occurred */ - if (G_UNLIKELY (error_message != NULL)) - { - g_error ("%s: %s", G_STRLOC, error_message); - g_free (error_message); - } - } - va_end (var_args); - - /* launch the job */ - return thunar_vfs_job_launch (THUNAR_VFS_JOB (simple_job)); -} - - - -#define __THUNAR_VFS_SIMPLE_JOB_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-simple-job.h b/thunar-vfs/thunar-vfs-simple-job.h deleted file mode 100644 index a33b71296..000000000 --- a/thunar-vfs/thunar-vfs-simple-job.h +++ /dev/null @@ -1,67 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_SIMPLE_JOB_H__ -#define __THUNAR_VFS_SIMPLE_JOB_H__ - -#include <thunar-vfs/thunar-vfs-job-private.h> - -G_BEGIN_DECLS; - -/** - * ThunarVfsSimpleJobFunc: - * @job : a #ThunarVfsJob. - * @param_values : the #GValue<!---->s passed to thunar_vfs_simple_job_launch(). - * @n_param_values : the number of #GValue<!---->s passed in @param_values. - * @error : return location for errors. - * - * Used by the #ThunarVfsSimpleJob to process the @job. See thunar_vfs_simple_job_launch() - * for further details. - * - * Return value: %TRUE on success, %FALSE in case of an error. - **/ -typedef gboolean (*ThunarVfsSimpleJobFunc) (ThunarVfsJob *job, - const GValue *param_values, - guint n_param_values, - GError **error); - -typedef struct _ThunarVfsSimpleJobClass ThunarVfsSimpleJobClass; -typedef struct _ThunarVfsSimpleJob ThunarVfsSimpleJob; - -#define THUNAR_VFS_TYPE_SIMPLE_JOB (thunar_vfs_simple_job_get_type ()) -#define THUNAR_VFS_SIMPLE_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_SIMPLE_JOB, ThunarVfsSimpleJob)) -#define THUNAR_VFS_SIMPLE_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_SIMPLE_JOB, ThunarVfsSimpleJobClass)) -#define THUNAR_VFS_IS_SIMPLE_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_SIMPLE_JOB)) -#define THUNAR_VFS_IS_SIMPLE_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_SIMPLE_JOB)) -#define THUNAR_VFS_SIMPLE_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_SIMPLE_JOB, ThunarVfsSimpleJobClass)) - -GType thunar_vfs_simple_job_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - -ThunarVfsJob *thunar_vfs_simple_job_launch (ThunarVfsSimpleJobFunc func, - guint n_param_values, - ...) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_SIMPLE_JOB_H__ */ diff --git a/thunar-vfs/thunar-vfs-thumb-jpeg.c b/thunar-vfs/thunar-vfs-thumb-jpeg.c deleted file mode 100644 index c49b59d53..000000000 --- a/thunar-vfs/thunar-vfs-thumb-jpeg.c +++ /dev/null @@ -1,657 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * Based on code written by Alexander Larsson <alexl@redhat.com> - * for libgnomeui. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_SETJMP_H -#include <setjmp.h> -#endif -#include <stdio.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef HAVE_JPEGLIB_H -#undef HAVE_STDDEF_H -#undef HAVE_STDLIB_H -#include<jpeglib.h> -#endif - -#include <thunar-vfs/thunar-vfs-thumb-jpeg.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -#if defined(HAVE_LIBJPEG) && defined(HAVE_MMAP) -typedef struct -{ - struct jpeg_error_mgr mgr; - jmp_buf setjmp_buffer; -} TvtjErrorHandler; - - - -static void -fatal_error_handler (j_common_ptr cinfo) -{ - TvtjErrorHandler *handler = (TvtjErrorHandler *) cinfo->err; - longjmp (handler->setjmp_buffer, 1); -} - - - -static gboolean -tvtj_fill_input_buffer (j_decompress_ptr cinfo) -{ - struct jpeg_source_mgr *source = cinfo->src; - - /* return a fake EOI marker so we will eventually terminate */ - if (G_LIKELY (source->bytes_in_buffer == 0)) - { - static const JOCTET FAKE_EOI[2] = - { - (JOCTET) 0xff, - (JOCTET) JPEG_EOI, - }; - - source->next_input_byte = FAKE_EOI; - source->bytes_in_buffer = G_N_ELEMENTS (FAKE_EOI); - } - - return TRUE; -} - - - -static void -tvtj_skip_input_data (j_decompress_ptr cinfo, - glong num_bytes) -{ - struct jpeg_source_mgr *source = cinfo->src; - - if (G_LIKELY (num_bytes > 0)) - { - num_bytes = MIN (num_bytes, (glong) source->bytes_in_buffer); - - source->next_input_byte += num_bytes; - source->bytes_in_buffer -= num_bytes; - } -} - - - -static inline gint -tvtj_denom (gint width, - gint height, - gint size) -{ - if (width > size * 8 && height > size * 8) - return 8; - else if (width > size * 4 && height > size * 4) - return 4; - else if (width > size * 2 && height > size * 2) - return 2; - else - return 1; -} - - - -static inline void -tvtj_convert_cmyk_to_rgb (j_decompress_ptr cinfo, - guchar *line) -{ - guchar *p; - gint c, k, m, n, y; - - g_return_if_fail (cinfo != NULL); - g_return_if_fail (cinfo->output_components == 4); - g_return_if_fail (cinfo->out_color_space == JCS_CMYK); - - for (n = cinfo->output_width, p = line; n > 0; --n, p += 4) - { - c = p[0]; - m = p[1]; - y = p[2]; - k = p[3]; - - if (cinfo->saw_Adobe_marker) - { - p[0] = k * c / 255; - p[1] = k * m / 255; - p[2] = k * y / 255; - } - else - { - p[0] = (255 - k) * (255 - c) / 255; - p[1] = (255 - k) * (255 - m) / 255; - p[2] = (255 - k) * (255 - y) / 255; - } - - p[3] = 255; - } -} - - - -static GdkPixbuf* -tvtj_jpeg_load (const JOCTET *content, - gsize length, - gint size) -{ - struct jpeg_decompress_struct cinfo; - struct jpeg_source_mgr source; - TvtjErrorHandler handler; - guchar *lines[1]; - guchar *buffer = NULL; - guchar *pixels = NULL; - guchar *p; - gint out_num_components; - guint n; - - /* setup JPEG error handling */ - cinfo.err = jpeg_std_error (&handler.mgr); - handler.mgr.error_exit = fatal_error_handler; - handler.mgr.output_message = (gpointer) exo_noop; - if (setjmp (handler.setjmp_buffer)) - goto error; - - /* setup the source */ - source.bytes_in_buffer = length; - source.next_input_byte = content; - source.init_source = (gpointer) exo_noop; - source.fill_input_buffer = tvtj_fill_input_buffer; - source.skip_input_data = tvtj_skip_input_data; - source.resync_to_restart = jpeg_resync_to_restart; - source.term_source = (gpointer) exo_noop; - - /* setup the JPEG decompress struct */ - jpeg_create_decompress (&cinfo); - cinfo.src = &source; - - /* read the JPEG header from the file */ - jpeg_read_header (&cinfo, TRUE); - - /* configure the JPEG decompress struct */ - cinfo.scale_num = 1; - cinfo.scale_denom = tvtj_denom (cinfo.image_width, cinfo.image_height, size); - cinfo.dct_method = JDCT_FASTEST; - cinfo.do_fancy_upsampling = FALSE; - - /* calculate the output dimensions */ - jpeg_calc_output_dimensions (&cinfo); - - /* verify the JPEG color space */ - if (cinfo.out_color_space != JCS_GRAYSCALE - && cinfo.out_color_space != JCS_CMYK - && cinfo.out_color_space != JCS_RGB) - { - /* we don't support this color space */ - goto error; - } - - /* start the decompression */ - jpeg_start_decompress (&cinfo); - - /* allocate the pixel buffer and extra space for grayscale data */ - if (G_LIKELY (cinfo.num_components != 1)) - { - pixels = g_malloc (cinfo.output_width * cinfo.output_height * cinfo.num_components); - out_num_components = cinfo.num_components; - lines[0] = pixels; - } - else - { - pixels = g_malloc (cinfo.output_width * cinfo.output_height * 3); - buffer = g_malloc (cinfo.output_width); - out_num_components = 3; - lines[0] = buffer; - } - - /* process the JPEG data */ - for (p = pixels; cinfo.output_scanline < cinfo.output_height; ) - { - jpeg_read_scanlines (&cinfo, lines, 1); - - /* convert the data to RGB */ - if (cinfo.num_components == 1) - { - for (n = 0; n < cinfo.output_width; ++n) - { - p[n * 3 + 0] = buffer[n]; - p[n * 3 + 1] = buffer[n]; - p[n * 3 + 2] = buffer[n]; - } - p += cinfo.output_width * 3; - } - else - { - if (cinfo.out_color_space == JCS_CMYK) - tvtj_convert_cmyk_to_rgb (&cinfo, lines[0]); - lines[0] += cinfo.output_width * cinfo.num_components; - } - } - - /* release the grayscale buffer */ - g_free (buffer); - buffer = NULL; - - /* finish the JPEG decompression */ - jpeg_finish_decompress (&cinfo); - jpeg_destroy_decompress (&cinfo); - - /* generate a pixbuf for the pixel data */ - return gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, - (cinfo.out_color_components == 4), 8, - cinfo.output_width, cinfo.output_height, - cinfo.output_width * out_num_components, - (GdkPixbufDestroyNotify) g_free, NULL); - -error: - jpeg_destroy_decompress (&cinfo); - g_free (buffer); - g_free (pixels); - return NULL; -} - - - -typedef struct -{ - const guchar *data_ptr; - guint data_len; - - guint thumb_compression; - union - { - struct /* thumbnail JPEG */ - { - guint length; - guint offset; - } thumb_jpeg; - struct /* thumbnail TIFF */ - { - guint length; - guint offset; - guint interp; - guint height; - guint width; - } thumb_tiff; - } thumb; - - gboolean big_endian; -} TvtjExif; - - - -static guint -tvtj_exif_get_ushort (const TvtjExif *exif, - const guchar *data) -{ - if (G_UNLIKELY (exif->big_endian)) - return ((data[0] << 8) | data[1]); - else - return ((data[1] << 8) | data[0]); -} - - - -static guint -tvtj_exif_get_ulong (const TvtjExif *exif, - const guchar *data) -{ - if (G_UNLIKELY (exif->big_endian)) - return ((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]); - else - return ((data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]); -} - - - -static void -tvtj_exif_parse_ifd (TvtjExif *exif, - const guchar *ifd_ptr, - guint ifd_len, - GSList *ifd_previous_list) -{ - const guchar *subifd_ptr; - GSList ifd_list; - guint subifd_off; - guint value; - guint tag; - guint n; - - /* make sure we have a valid IFD here */ - if (G_UNLIKELY (ifd_len < 2)) - return; - - /* make sure we don't recurse into IFDs that are already being processed */ - if (g_slist_find (ifd_previous_list, ifd_ptr) != NULL) - return; - ifd_list.next = ifd_previous_list; - ifd_list.data = (gpointer) ifd_ptr; - - /* determine the number of entries */ - n = tvtj_exif_get_ushort (exif, ifd_ptr); - - /* advance to the IFD content */ - ifd_ptr += 2; - ifd_len -= 2; - - /* validate the number of entries */ - if (G_UNLIKELY (n * 12 > ifd_len)) - n = ifd_len / 12; - - /* process all IFD entries */ - for (; n > 0; ifd_ptr += 12, --n) - { - /* determine the tag of this entry */ - tag = tvtj_exif_get_ushort (exif, ifd_ptr); - if (tag == 0x8769 || tag == 0xa005) - { - /* check if we have a valid sub IFD offset here */ - subifd_off = tvtj_exif_get_ulong (exif, ifd_ptr + 8); - subifd_ptr = exif->data_ptr + subifd_off; - if (G_LIKELY (subifd_off < exif->data_len)) - { - /* process the sub IFD recursively */ - tvtj_exif_parse_ifd (exif, subifd_ptr, exif->data_len - subifd_off, &ifd_list); - } - } - else if (tag == 0x0103) - { - /* verify that we have an ushort here (format 3) */ - if (tvtj_exif_get_ushort (exif, ifd_ptr + 2) == 3) - { - /* determine the thumbnail compression */ - exif->thumb_compression = tvtj_exif_get_ushort (exif, ifd_ptr + 8); - } - } - else if (tag == 0x0100 || tag == 0x0101 || tag == 0x0106 || tag == 0x0111 || tag == 0x0117) - { - /* this can be either ushort or ulong */ - if (tvtj_exif_get_ushort (exif, ifd_ptr + 2) == 3) - value = tvtj_exif_get_ushort (exif, ifd_ptr + 8); - else if (tvtj_exif_get_ushort (exif, ifd_ptr + 2) == 4) - value = tvtj_exif_get_ulong (exif, ifd_ptr + 8); - else - value = 0; - - /* and remember it appropriately */ - if (tag == 0x0100) - exif->thumb.thumb_tiff.width = value; - else if (tag == 0x0100) - exif->thumb.thumb_tiff.height = value; - else if (tag == 0x0106) - exif->thumb.thumb_tiff.interp = value; - else if (tag == 0x0111) - exif->thumb.thumb_tiff.offset = value; - else - exif->thumb.thumb_tiff.length = value; - } - else if (tag == 0x0201 || tag == 0x0202) - { - /* verify that we have an ulong here (format 4) */ - if (tvtj_exif_get_ushort (exif, ifd_ptr + 2) == 4) - { - /* determine the value (thumbnail JPEG offset or length) */ - value = tvtj_exif_get_ulong (exif, ifd_ptr + 8); - - /* and remember it appropriately */ - if (G_LIKELY (tag == 0x201)) - exif->thumb.thumb_jpeg.offset = value; - else - exif->thumb.thumb_jpeg.length = value; - } - } - } - - /* check for link to next IFD */ - subifd_off = tvtj_exif_get_ulong (exif, ifd_ptr); - if (subifd_off != 0 && subifd_off < exif->data_len) - { - /* parse next IFD recursively as well */ - tvtj_exif_parse_ifd (exif, exif->data_ptr + subifd_off, exif->data_len - subifd_off, &ifd_list); - } -} - - - -static GdkPixbuf* -tvtj_exif_extract_thumbnail (const guchar *data, - guint length, - gint size) -{ - TvtjExif exif; - guint offset; - - /* make sure we have enough data */ - if (G_UNLIKELY (length < 6 + 8)) - return NULL; - - /* validate Exif header */ - if (memcmp (data, "Exif\0\0", 6) != 0) - return NULL; - - /* advance to TIFF header */ - data += 6; - length -= 6; - - /* setup Exif data struct */ - memset (&exif, 0, sizeof (exif)); - exif.data_ptr = data; - exif.data_len = length; - - /* determine byte order */ - if (memcmp (data, "II", 2) == 0) - exif.big_endian = FALSE; - else if (memcmp (data, "MM", 2) == 0) - exif.big_endian = TRUE; - else - return NULL; - - /* validate the TIFF header */ - if (tvtj_exif_get_ushort (&exif, data + 2) != 0x2a) - return NULL; - - /* determine the first IFD offset */ - offset = tvtj_exif_get_ulong (&exif, data + 4); - - /* validate the offset */ - if (G_LIKELY (offset < length)) - { - /* parse the first IFD (recursively parses the remaining...) */ - tvtj_exif_parse_ifd (&exif, data + offset, length - offset, NULL); - - /* check thumbnail compression type */ - if (G_LIKELY (exif.thumb_compression == 6)) /* JPEG */ - { - /* check if we have a valid thumbnail JPEG */ - if (exif.thumb.thumb_jpeg.offset > 0 && exif.thumb.thumb_jpeg.length > 0 - && exif.thumb.thumb_jpeg.offset + exif.thumb.thumb_jpeg.length <= length) - { - /* try to load the embedded thumbnail JPEG */ - return tvtj_jpeg_load (data + exif.thumb.thumb_jpeg.offset, exif.thumb.thumb_jpeg.length, size); - } - } - else if (exif.thumb_compression == 1) /* Uncompressed */ - { - /* check if we have a valid thumbnail (current only RGB interpretations) */ - if (G_LIKELY (exif.thumb.thumb_tiff.interp == 2) - && exif.thumb.thumb_tiff.offset > 0 && exif.thumb.thumb_tiff.length > 0 - && exif.thumb.thumb_tiff.offset + exif.thumb.thumb_tiff.length <= length - && exif.thumb.thumb_tiff.height * exif.thumb.thumb_tiff.width == exif.thumb.thumb_tiff.length) - { - /* plain RGB data, just what we need for a GdkPixbuf */ - return gdk_pixbuf_new_from_data (g_memdup (data + exif.thumb.thumb_tiff.offset, exif.thumb.thumb_tiff.length), - GDK_COLORSPACE_RGB, FALSE, 8, exif.thumb.thumb_tiff.width, - exif.thumb.thumb_tiff.height, exif.thumb.thumb_tiff.width, - (GdkPixbufDestroyNotify) g_free, NULL); - } - } - } - - return NULL; -} - - - -static GdkPixbuf* -tvtj_jpeg_load_thumbnail (const JOCTET *content, - gsize length, - gint size) -{ - guint marker_len; - guint marker; - gsize n; - - /* valid JPEG headers begin with SOI (Start Of Image) */ - if (G_LIKELY (length >= 2 && content[0] == 0xff && content[1] == 0xd8)) - { - /* search for an EXIF marker */ - for (length -= 2, n = 2; n < length; ) - { - /* check for valid marker start */ - if (G_UNLIKELY (content[n++] != 0xff)) - break; - - /* determine the next marker */ - marker = content[n]; - - /* skip additional padding */ - if (G_UNLIKELY (marker == 0xff)) - continue; - - /* stop at SOS marker */ - if (marker == 0xda) - break; - - /* advance */ - ++n; - - /* check if valid */ - if (G_UNLIKELY (n + 2 >= length)) - break; - - /* determine the marker length */ - marker_len = (content[n] << 8) | content[n + 1]; - - /* check if we have an exif marker here */ - if (marker == 0xe1 && n + marker_len <= length) - { - /* try to extract the Exif thumbnail */ - return tvtj_exif_extract_thumbnail (content + n + 2, marker_len - 2, size); - } - - /* try next one then */ - n += marker_len; - } - } - - return NULL; -} -#endif - - - -/** - * thunar_vfs_thumb_jpeg_load: - * @path - * @size - * - * Return value: - **/ -GdkPixbuf* -thunar_vfs_thumb_jpeg_load (const gchar *path, - gint size) -{ -#if defined(HAVE_LIBJPEG) && defined(HAVE_MMAP) - struct stat statb; - GdkPixbuf *pixbuf = NULL; - JOCTET *content; - gint fd; - - /* try to open the file at the given path */ - fd = open (path, O_RDONLY); - if (G_LIKELY (fd >= 0)) - { - /* determine the status of the file */ - if (G_LIKELY (fstat (fd, &statb) == 0 && statb.st_size > 0)) - { - /* try to mmap the file */ - content = (JOCTET *) mmap (NULL, statb.st_size, PROT_READ, MAP_SHARED, fd, 0); - - /* verify that the mmap was successful */ - if (G_LIKELY (content != (JOCTET *) MAP_FAILED)) - { - /* try to load an embedded thumbnail first */ - pixbuf = tvtj_jpeg_load_thumbnail (content, statb.st_size, size); - if (G_LIKELY (pixbuf == NULL)) - { - /* fall back to loading and scaling the image itself */ - pixbuf = tvtj_jpeg_load (content, statb.st_size, size); - } - } - - /* unmap the file content */ - munmap ((void *) content, statb.st_size); - } - - /* close the file */ - close (fd); - } - - return pixbuf; -#else - return NULL; -#endif -} - - - -#define __THUNAR_VFS_THUMB_JPEG_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-thumb-jpeg.h b/thunar-vfs/thunar-vfs-thumb-jpeg.h deleted file mode 100644 index 06d5d1034..000000000 --- a/thunar-vfs/thunar-vfs-thumb-jpeg.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_THUMB_JPEG_H__ -#define __THUNAR_VFS_THUMB_JPEG_H__ - -#include <thunar-vfs/thunar-vfs-config.h> - -G_BEGIN_DECLS; - -GdkPixbuf *thunar_vfs_thumb_jpeg_load (const gchar *path, - gint size) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_THUMB_JPEG_H__ */ diff --git a/thunar-vfs/thunar-vfs-thumb-private.h b/thunar-vfs/thunar-vfs-thumb-private.h deleted file mode 100644 index cf492511e..000000000 --- a/thunar-vfs/thunar-vfs-thumb-private.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined(THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file is not part of the public API." -#endif - -#ifndef __THUNAR_VFS_THUMB_PRIVATE_H__ -#define __THUNAR_VFS_THUMB_PRIVATE_H__ - -#include <thunar-vfs/thunar-vfs-thumb.h> - -G_BEGIN_DECLS; - -/* Support routines for thumbnail cleanup */ -void _thunar_vfs_thumbnail_remove_for_path (const ThunarVfsPath *path) G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_THUMB_PRIVATE_H__ */ diff --git a/thunar-vfs/thunar-vfs-thumb.c b/thunar-vfs/thunar-vfs-thumb.c deleted file mode 100644 index 7789849fb..000000000 --- a/thunar-vfs/thunar-vfs-thumb.c +++ /dev/null @@ -1,1251 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2004-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#ifdef HAVE_SYS_RESOURCE_H -#include <sys/resource.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#include <stdio.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <png.h> - -#include <thunar-vfs/thunar-vfs-enum-types.h> -#include <thunar-vfs/thunar-vfs-monitor-private.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-thumb-jpeg.h> -#include <thunar-vfs/thunar-vfs-thumb-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - -/* use g_open(), g_rename() and g_unlink() on win32 */ -#if defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_open(filename, flags, mode) (open ((filename), (flags), (mode))) -#define g_rename(oldfilename, newfilename) (rename ((oldfilename), (newfilename))) -#define g_unlink(filename) (unlink ((filename))) -#endif - - - -/* thumbnailers cache support */ -#define CACHE_MAJOR_VERSION (1) -#define CACHE_MINOR_VERSION (0) -#define CACHE_READ32(cache, offset) (GUINT32_FROM_BE (*((guint32 *) ((cache) + (offset))))) - -/* fallback cache if the loading fails */ -static const guint32 CACHE_FALLBACK[4] = -{ -#if G_BYTE_ORDER == G_BIG_ENDIAN - CACHE_MAJOR_VERSION, - CACHE_MINOR_VERSION, - 0, - 0, -#else - GUINT32_SWAP_LE_BE_CONSTANT (CACHE_MAJOR_VERSION), - GUINT32_SWAP_LE_BE_CONSTANT (CACHE_MINOR_VERSION), - GUINT32_SWAP_LE_BE_CONSTANT (0), - GUINT32_SWAP_LE_BE_CONSTANT (0), -#endif -}; - - - -/* Property identifiers */ -enum -{ - PROP_0, - PROP_SIZE, -}; - - - -static void thunar_vfs_thumb_factory_class_init (ThunarVfsThumbFactoryClass *klass); -static void thunar_vfs_thumb_factory_init (ThunarVfsThumbFactory *factory); -static void thunar_vfs_thumb_factory_finalize (GObject *object); -static void thunar_vfs_thumb_factory_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void thunar_vfs_thumb_factory_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static gboolean thunar_vfs_thumb_factory_cache_lookup (ThunarVfsThumbFactory *factory, - const gchar *mime_type, - gint mime_type_len, - gchar **script_return) G_GNUC_WARN_UNUSED_RESULT; -static void thunar_vfs_thumb_factory_cache_load (ThunarVfsThumbFactory *factory, - const gchar *cache_file); -static void thunar_vfs_thumb_factory_cache_unload (ThunarVfsThumbFactory *factory); -static void thunar_vfs_thumb_factory_cache_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data); -static void thunar_vfs_thumb_factory_cache_update (ThunarVfsThumbFactory *factory); -static gboolean thunar_vfs_thumb_factory_cache_timer (gpointer user_data); -static void thunar_vfs_thumb_factory_cache_timer_destroy (gpointer user_data); -static void thunar_vfs_thumb_factory_cache_watch (GPid pid, - gint status, - gpointer user_data); -static void thunar_vfs_thumb_factory_cache_watch_destroy (gpointer user_data); - - - -struct _ThunarVfsThumbFactoryClass -{ - GObjectClass __parent__; -}; - -struct _ThunarVfsThumbFactory -{ - GObject __parent__; - - gchar *base_path; - gchar *fail_path; - ThunarVfsThumbSize size; - - gchar *cache; - guint cache_size; - GMutex *cache_lock; - guint cache_timer_id; - guint cache_watch_id; - guint cache_was_mapped : 1; - ThunarVfsMonitorHandle *cache_handle; -}; - - - -static GObjectClass *thunar_vfs_thumb_factory_parent_class; - - - -GType -thunar_vfs_thumb_factory_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsThumbFactory", - sizeof (ThunarVfsThumbFactoryClass), - thunar_vfs_thumb_factory_class_init, - sizeof (ThunarVfsThumbFactory), - thunar_vfs_thumb_factory_init, - 0); - } - - return type; -} - - - -static void -thunar_vfs_thumb_factory_class_init (ThunarVfsThumbFactoryClass *klass) -{ - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_thumb_factory_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_thumb_factory_finalize; - gobject_class->get_property = thunar_vfs_thumb_factory_get_property; - gobject_class->set_property = thunar_vfs_thumb_factory_set_property; - - /** - * ThunarVfsThumbFactory::size: - * - * The #ThunarVfsThumbSize at which thumbnails should be - * looked up and saved for this #ThunarVfsThumbFactory. - **/ - g_object_class_install_property (gobject_class, - PROP_SIZE, - g_param_spec_enum ("size", - _("Size"), - _("The desired thumbnail size"), - THUNAR_VFS_TYPE_VFS_THUMB_SIZE, - THUNAR_VFS_THUMB_SIZE_NORMAL, - G_PARAM_CONSTRUCT_ONLY | EXO_PARAM_READWRITE)); -} - - - -static void -thunar_vfs_thumb_factory_init (ThunarVfsThumbFactory *factory) -{ - ThunarVfsPath *cache_path; - gchar *cache_file; - - /* pre-allocate the failed path, so we don't need to do that on every method call */ - factory->fail_path = g_strconcat (xfce_get_homedir (), - G_DIR_SEPARATOR_S ".thumbnails" - G_DIR_SEPARATOR_S "fail" - G_DIR_SEPARATOR_S "thunar-vfs" - G_DIR_SEPARATOR_S, NULL); - - /* we default to normal size here, so we don't need to override the constructor */ - factory->base_path = g_strconcat (xfce_get_homedir (), G_DIR_SEPARATOR_S ".thumbnails" G_DIR_SEPARATOR_S "normal" G_DIR_SEPARATOR_S, NULL); - factory->size = THUNAR_VFS_THUMB_SIZE_NORMAL; - - /* allocate the cache mutex */ - factory->cache_lock = g_mutex_new (); - - /* determine the thumbnailers.cache file */ - cache_file = xfce_resource_save_location (XFCE_RESOURCE_CACHE, "Thunar/thumbnailers.cache", FALSE); - - /* monitor the thumbnailers.cache file for changes */ - cache_path = thunar_vfs_path_new (cache_file, NULL); - factory->cache_handle = thunar_vfs_monitor_add_file (_thunar_vfs_monitor, cache_path, thunar_vfs_thumb_factory_cache_monitor, factory); - _thunar_vfs_path_unref_nofree (cache_path); - - /* initially load the thumbnailers.cache file */ - thunar_vfs_thumb_factory_cache_load (factory, cache_file); - - /* schedule a timer to update the thumbnailers.cache every 5 minutes */ - factory->cache_timer_id = g_timeout_add_full (G_PRIORITY_LOW, 5 * 60 * 1000, thunar_vfs_thumb_factory_cache_timer, - factory, thunar_vfs_thumb_factory_cache_timer_destroy); - - /* cleanup */ - g_free (cache_file); -} - - - -static void -thunar_vfs_thumb_factory_finalize (GObject *object) -{ - ThunarVfsThumbFactory *factory = THUNAR_VFS_THUMB_FACTORY (object); - - /* be sure to unload the cache file */ - thunar_vfs_thumb_factory_cache_unload (factory); - - /* stop any pending cache sources */ - if (G_LIKELY (factory->cache_timer_id != 0)) - g_source_remove (factory->cache_timer_id); - if (G_UNLIKELY (factory->cache_watch_id != 0)) - g_source_remove (factory->cache_watch_id); - - /* unregister the monitor handle */ - thunar_vfs_monitor_remove (_thunar_vfs_monitor, factory->cache_handle); - - /* release the cache lock */ - g_mutex_free (factory->cache_lock); - - /* free the thumbnail paths */ - g_free (factory->base_path); - g_free (factory->fail_path); - - (*G_OBJECT_CLASS (thunar_vfs_thumb_factory_parent_class)->finalize) (object); -} - - - -static void -thunar_vfs_thumb_factory_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - ThunarVfsThumbFactory *factory = THUNAR_VFS_THUMB_FACTORY (object); - - switch (prop_id) - { - case PROP_SIZE: - g_value_set_enum (value, factory->size); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - - -static void -thunar_vfs_thumb_factory_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - ThunarVfsThumbFactory *factory = THUNAR_VFS_THUMB_FACTORY (object); - - switch (prop_id) - { - case PROP_SIZE: - if (G_UNLIKELY (g_value_get_enum (value) == THUNAR_VFS_THUMB_SIZE_LARGE)) - { - /* free the previous base path */ - g_free (factory->base_path); - - /* setup the new base path */ - factory->base_path = g_strconcat (xfce_get_homedir (), G_DIR_SEPARATOR_S ".thumbnails" G_DIR_SEPARATOR_S "large" G_DIR_SEPARATOR_S, NULL); - factory->size = THUNAR_VFS_THUMB_SIZE_LARGE; - } - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - - -static gboolean -thunar_vfs_thumb_factory_cache_lookup (ThunarVfsThumbFactory *factory, - const gchar *mime_type, - gint mime_type_len, - gchar **script_return) -{ - const gchar *cache; - gint max; - gint mid; - gint min; - gint n; - - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory), FALSE); - _thunar_vfs_return_val_if_fail (mime_type_len > 0, FALSE); - _thunar_vfs_return_val_if_fail (mime_type != NULL, FALSE); - - /* acquire the cache lock */ - g_mutex_lock (factory->cache_lock); - - /* binary search on the mime types */ - for (cache = factory->cache, max = ((gint) CACHE_READ32 (cache, 8)) - 1, min = 0; max >= min; ) - { - mid = (min + max) / 2; - - /* compare the string length */ - n = (gint) (CACHE_READ32 (cache, 16 + 8 * mid)) - mime_type_len; - if (G_UNLIKELY (n == 0)) - { - /* compare the strings themselves */ - n = strcmp (cache + CACHE_READ32 (cache, 16 + 8 * mid + 4), mime_type); - } - - /* where to search next */ - if (n < 0) - min = mid + 1; - else if (n > 0) - max = mid - 1; - else - { - /* check if we should return the script */ - if (G_UNLIKELY (script_return != NULL)) - *script_return = g_strdup (cache + CACHE_READ32 (cache + CACHE_READ32 (cache, 12) + mid * 4, 0)); - - /* we found it */ - break; - } - } - - /* release the cache lock */ - g_mutex_unlock (factory->cache_lock); - - return (max >= min); -} - - - -static void -thunar_vfs_thumb_factory_cache_load (ThunarVfsThumbFactory *factory, - const gchar *cache_file) -{ - struct stat statb; - gssize m; - gsize n; - gint fd; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory)); - _thunar_vfs_return_if_fail (g_path_is_absolute (cache_file)); - _thunar_vfs_return_if_fail (factory->cache == NULL); - - /* try to open the thumbnailers.cache file */ - fd = g_open (cache_file, O_RDONLY, 0000); - if (G_LIKELY (fd >= 0)) - { - /* stat the file to get proper size info */ - if (fstat (fd, &statb) == 0 && statb.st_size >= 16) - { - /* remember the size of the cache */ - factory->cache_size = statb.st_size; - -#ifdef HAVE_MMAP - /* try to mmap() the file into memory */ - factory->cache = mmap (NULL, statb.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (G_LIKELY (factory->cache != MAP_FAILED)) - { - /* remember that mmap() succeed */ - factory->cache_was_mapped = TRUE; - -#ifdef HAVE_POSIX_MADVISE - /* tell the system that we'll use this buffer quite often */ - posix_madvise (factory->cache, statb.st_size, POSIX_MADV_WILLNEED); -#endif - } - else -#endif - { - /* remember that mmap() failed */ - factory->cache_was_mapped = FALSE; - - /* allocate memory for the cache */ - factory->cache = g_malloc (statb.st_size); - - /* read the cache file */ - for (n = 0; n < statb.st_size; n += m) - { - /* read the next chunk */ - m = read (fd, factory->cache + n, statb.st_size - n); - if (G_UNLIKELY (m <= 0)) - { - /* reset the cache */ - g_free (factory->cache); - factory->cache = NULL; - break; - } - } - } - } - - /* close the file handle */ - close (fd); - } - - /* check if the cache was loaded successfully */ - if (G_LIKELY (factory->cache != NULL)) - { - /* check that we actually support the file version */ - if (CACHE_READ32 (factory->cache, 0) != CACHE_MAJOR_VERSION || CACHE_READ32 (factory->cache, 4) != CACHE_MINOR_VERSION) - thunar_vfs_thumb_factory_cache_unload (factory); - } - else - { - /* run the thunar-vfs-update-thumbnailers-cache-1 utility */ - thunar_vfs_thumb_factory_cache_update (factory); - } - - /* use the fallback cache if the loading failed */ - if (G_UNLIKELY (factory->cache == NULL)) - { - factory->cache = (gchar *) CACHE_FALLBACK; - factory->cache_size = 16; - } -} - - - -static void -thunar_vfs_thumb_factory_cache_unload (ThunarVfsThumbFactory *factory) -{ - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory)); - _thunar_vfs_return_if_fail (factory->cache != NULL); - - /* check if any cache is loaded (and not using the fallback cache) */ - if (factory->cache != (gchar *) CACHE_FALLBACK) - { -#ifdef HAVE_MMAP - /* check if mmap() succeed */ - if (factory->cache_was_mapped) - { - /* just unmap the memory */ - munmap (factory->cache, factory->cache_size); - } - else -#endif - { - /* need to release the memory */ - g_free (factory->cache); - } - } - - /* reset the cache pointer */ - factory->cache = NULL; -} - - - -static void -thunar_vfs_thumb_factory_cache_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data) -{ - ThunarVfsThumbFactory *factory = THUNAR_VFS_THUMB_FACTORY (user_data); - gchar *cache_file; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory)); - _thunar_vfs_return_if_fail (factory->cache_handle == handle); - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); - - /* check the event */ - if (G_UNLIKELY (event == THUNAR_VFS_MONITOR_EVENT_DELETED)) - { - /* some idiot deleted the cache file, regenerate it */ - thunar_vfs_thumb_factory_cache_update (factory); - } - else - { - /* determine the thumbnailers.cache file */ - cache_file = thunar_vfs_path_dup_string (handle_path); - - /* the thumbnailers.cache file was changed, reload it */ - g_mutex_lock (factory->cache_lock); - thunar_vfs_thumb_factory_cache_unload (factory); - thunar_vfs_thumb_factory_cache_load (factory, cache_file); - g_mutex_unlock (factory->cache_lock); - - /* release the file path */ - g_free (cache_file); - } -} - - - -static void -thunar_vfs_thumb_factory_cache_update (ThunarVfsThumbFactory *factory) -{ - gchar *argv[2] = { LIBEXECDIR G_DIR_SEPARATOR_S "/thunar-vfs-update-thumbnailers-cache-1", NULL }; - GPid pid; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory)); - - /* check if we're already updating the cache */ - if (G_LIKELY (factory->cache_watch_id == 0)) - { - /* try to spawn the command */ - if (g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL)) - { - /* add a child watch for the updater process */ - factory->cache_watch_id = g_child_watch_add_full (G_PRIORITY_LOW, pid, thunar_vfs_thumb_factory_cache_watch, - factory, thunar_vfs_thumb_factory_cache_watch_destroy); - -#ifdef HAVE_SETPRIORITY - /* decrease the priority of the updater process */ - setpriority (PRIO_PROCESS, pid, 10); -#endif - } - } -} - - - -static gboolean -thunar_vfs_thumb_factory_cache_timer (gpointer user_data) -{ - /* run the thunar-vfs-update-thumbnailers-cache-1 utility... */ - thunar_vfs_thumb_factory_cache_update (THUNAR_VFS_THUMB_FACTORY (user_data)); - - /* ...and keep the timer running */ - return TRUE; -} - - - -static void -thunar_vfs_thumb_factory_cache_timer_destroy (gpointer user_data) -{ - THUNAR_VFS_THUMB_FACTORY (user_data)->cache_timer_id = 0; -} - - - -static void -thunar_vfs_thumb_factory_cache_watch (GPid pid, - gint status, - gpointer user_data) -{ - ThunarVfsThumbFactory *factory = THUNAR_VFS_THUMB_FACTORY (user_data); - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory)); - - /* a return value of 33 means that the thumbnailers.cache was updated by the - * thunar-vfs-update-thumbnailers-cache-1 utilitiy and must be reloaded. - */ - if (WIFEXITED (status) && WEXITSTATUS (status) == 33) - { - /* schedule a "changed" event for the thumbnailers.cache */ - thunar_vfs_monitor_feed (_thunar_vfs_monitor, THUNAR_VFS_MONITOR_EVENT_CHANGED, - _thunar_vfs_monitor_handle_get_path (factory->cache_handle)); - } - - /* close the PID (win32) */ - g_spawn_close_pid (pid); -} - - - -static void -thunar_vfs_thumb_factory_cache_watch_destroy (gpointer user_data) -{ - THUNAR_VFS_THUMB_FACTORY (user_data)->cache_watch_id = 0; -} - - - -/** - * thunar_vfs_thumb_factory_new: - * @size : the desired #ThunarVfsThumbSize. - * - * Allocates a new #ThunarVfsThumbFactory, that is able to - * load and store thumbnails in the given @size. - * - * The caller is responsible to free the returned object - * using g_object_unref() when no longer needed. - * - * Return value: the newly allocated #ThunarVfsThumbFactory. - **/ -ThunarVfsThumbFactory* -thunar_vfs_thumb_factory_new (ThunarVfsThumbSize size) -{ - return g_object_new (THUNAR_VFS_TYPE_THUMB_FACTORY, "size", size, NULL); -} - - - -/** - * thunar_vfs_thumb_factory_lookup: - * @factory : a #ThunarVfsThumbFactory. - * @info : the #ThunarVfsInfo of the original file. - * - * Looks up the path to a thumbnail for @info in @factory and returns - * the absolute path to the thumbnail file if a valid thumbnail is - * found. Else %NULL is returned. - * - * The usage of this method is thread-safe. - * - * Return value: the path to a valid thumbnail for @info in @factory - * or %NULL if no valid thumbnail was found. - **/ -gchar* -thunar_vfs_thumb_factory_lookup_thumbnail (ThunarVfsThumbFactory *factory, - const ThunarVfsInfo *info) -{ - gchar uri[THUNAR_VFS_PATH_MAXURILEN]; - gchar *path; - gchar *md5; - - g_return_val_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory), NULL); - g_return_val_if_fail (info != NULL, NULL); - - /* determine the URI for the path */ - if (thunar_vfs_path_to_uri (info->path, uri, sizeof (uri), NULL) >= 0) - { - /* determine the path to the thumbnail for the factory */ - md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1); - path = g_strconcat (factory->base_path, md5, ".png", NULL); - g_free (md5); - - /* check if the path contains a valid thumbnail */ - if (thunar_vfs_thumbnail_is_valid (path, uri, info->mtime)) - return path; - - /* no valid thumbnail in the global repository */ - g_free (path); - } - - return NULL; -} - - - -/** - * thunar_vfs_thumb_factory_can_thumbnail: - * @factory : a #ThunarVfsThumbFactory. - * @info : the #ThunarVfsInfo of a file. - * - * Checks if @factory can generate a thumbnail for - * the file specified by @info. - * - * The usage of this method is thread-safe. - * - * Return value: %TRUE if @factory can generate a thumbnail for @info. - **/ -gboolean -thunar_vfs_thumb_factory_can_thumbnail (ThunarVfsThumbFactory *factory, - const ThunarVfsInfo *info) -{ - ThunarVfsPath *path; - const gchar *name; - gint name_len; - - g_return_val_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory), FALSE); - g_return_val_if_fail (info != NULL, FALSE); - - /* we can only handle thumbnails for regular files */ - if (G_UNLIKELY (info->type != THUNAR_VFS_FILE_TYPE_REGULAR)) - return FALSE; - - /* we really don't want to generate a thumbnail for a thumbnail */ - for (path = info->path; path != NULL; path = thunar_vfs_path_get_parent (path)) - { - name = thunar_vfs_path_get_name (path); - if (*name == '.' && (strcmp (name + 1, "thumbnails") == 0 || strcmp (name + 1, "thumblocal") == 0)) - return FALSE; - } - - /* determine the length of the mime type */ - name = thunar_vfs_mime_info_get_name (info->mime_info); - name_len = strlen (name); - - /* image/jpeg should never be a problem, otherwise check if we have a thumbnailer in the cache */ - if (G_LIKELY (name_len == 10 && memcmp (name, "image/jpeg", 10) == 0) - || thunar_vfs_thumb_factory_cache_lookup (factory, name, name_len, NULL)) - return !thunar_vfs_thumb_factory_has_failed_thumbnail (factory, info); - - /* we cannot handle the mime type */ - return FALSE; -} - - - -/** - * thunar_vfs_thumb_factory_has_failed_thumbnail: - * @factory : a #ThunarVfsThumbFactory. - * @info : the #ThunarVfsInfo of a file. - * - * Checks whether we know that @factory won't be able to generate - * a thumbnail for the file referred to by @info. - * - * The usage of this method is thread-safe. - * - * Return value: %TRUE if @factory knows that it cannot generate - * a thumbnail for @info, else %TRUE. - **/ -gboolean -thunar_vfs_thumb_factory_has_failed_thumbnail (ThunarVfsThumbFactory *factory, - const ThunarVfsInfo *info) -{ - gchar uri[THUNAR_VFS_PATH_MAXURILEN]; - gchar path[4096]; - gchar *md5; - - g_return_val_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory), FALSE); - g_return_val_if_fail (info != NULL, FALSE); - - /* determine the URI of the info */ - if (thunar_vfs_path_to_uri (info->path, uri, sizeof (uri), NULL) < 0) - return FALSE; - - /* determine the path to the thumbnail */ - md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1); - g_snprintf (path, sizeof (path), "%s%s.png", factory->fail_path, md5); - g_free (md5); - - return thunar_vfs_thumbnail_is_valid (path, uri, info->mtime); -} - - - -static gchar* -thumbnailer_script_expand (const gchar *script, - const gchar *ipath, - const gchar *opath, - gint size) -{ - const gchar *p; - GString *s; - gchar *quoted; - gchar *uri; - - s = g_string_new (NULL); - for (p = script; *p != '\0'; ++p) - { - if (G_LIKELY (*p != '%')) - { - g_string_append_c (s, *p); - continue; - } - - switch (*++p) - { - case 'u': - uri = g_filename_to_uri (ipath, NULL, NULL); - if (G_LIKELY (uri != NULL)) - { - quoted = g_shell_quote (uri); - g_string_append (s, quoted); - g_free (quoted); - g_free (uri); - } - break; - - case 'i': - quoted = g_shell_quote (ipath); - g_string_append (s, quoted); - g_free (quoted); - break; - - case 'o': - quoted = g_shell_quote (opath); - g_string_append (s, quoted); - g_free (quoted); - break; - - case 's': - g_string_append_printf (s, "%d", size); - break; - - case '%': - g_string_append_c (s, '%'); - break; - - case '\0': - --p; - break; - - default: - break; - } - } - - return g_string_free (s, FALSE); -} - - - -/** - * thunar_vfs_thumb_factory_generate_thumbnail: - * @factory : a #ThunarVfsThumbFactory. - * @info : the #ThunarVfsInfo of the file for which a thumbnail - * should be generated. - * - * Tries to generate a thumbnail for the file referred to by @info in - * @factory. - * - * The caller is responsible to free the returned #GdkPixbuf using - * g_object_unref() when no longer needed. - * - * The usage of this method is thread-safe. - * - * Return value: the thumbnail for the @uri or %NULL. - **/ -GdkPixbuf* -thunar_vfs_thumb_factory_generate_thumbnail (ThunarVfsThumbFactory *factory, - const ThunarVfsInfo *info) -{ - const gchar *name; - GdkPixbuf *pixbuf = NULL; - GdkPixbuf *scaled; - gchar *tmp_path; - gchar *command; - gchar *script; - gchar *path; - gint name_len; - gint status; - gint size; - gint fd; - - g_return_val_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory), NULL); - g_return_val_if_fail (info != NULL, NULL); - - /* determine the pixel size of the thumbnail */ - size = G_LIKELY (factory->size == THUNAR_VFS_THUMB_SIZE_NORMAL) ? 128 : 256; - - /* determine the absolute local path to the file */ - path = _thunar_vfs_path_translate_dup_string (info->path, THUNAR_VFS_PATH_SCHEME_FILE, NULL); - if (G_UNLIKELY (path == NULL)) - return NULL; - - /* determine the length of the mime type */ - name = thunar_vfs_mime_info_get_name (info->mime_info); - name_len = strlen (name); - - /* try the fast JPEG thumbnailer */ - if (G_LIKELY (name_len == 10 && memcmp (name, "image/jpeg", 10) == 0)) - { - /* try loading the JPEG using our builtin thumbnailer */ - pixbuf = thunar_vfs_thumb_jpeg_load (path, size); - if (G_LIKELY (pixbuf != NULL) - && gdk_pixbuf_get_width (pixbuf) <= 160 - && gdk_pixbuf_get_height (pixbuf) <= 120) - { - /* since most embedded thumbnails are at size 160x120, - * we avoid scaling down the thumbnail again here and - * simply accept that even for "normal" thumbnails - */ - goto done; - } - } - - /* otherwise check if we have a thumbnailer script in the cache */ - if (pixbuf == NULL && thunar_vfs_thumb_factory_cache_lookup (factory, name, name_len, &script)) - { - /* create a temporary file for the thumbnailer */ - fd = g_file_open_tmp (".thunar-vfs-thumbnail.XXXXXX", &tmp_path, NULL); - if (G_LIKELY (fd >= 0)) - { - /* determine the command for the script */ - command = thumbnailer_script_expand (script, path, tmp_path, size); - - /* run the thumbnailer script and load the generated file */ - if (g_spawn_command_line_sync (command, NULL, NULL, &status, NULL) && WIFEXITED (status) && WEXITSTATUS (status) == 0) - { - pixbuf = gdk_pixbuf_new_from_file (tmp_path, NULL); - } - - /* unlink the temporary file */ - g_unlink (tmp_path); - - /* cleanup */ - g_free (tmp_path); - g_free (command); - close (fd); - } - - /* cleanup */ - g_free (script); - } - - /* check if we need to scale the image */ - if (pixbuf != NULL && (gdk_pixbuf_get_width (pixbuf) > size || gdk_pixbuf_get_height (pixbuf) > size)) - { - scaled = exo_gdk_pixbuf_scale_ratio (pixbuf, size); - g_object_unref (G_OBJECT (pixbuf)); - pixbuf = scaled; - } - -done: - /* cleanup */ - g_free (path); - - return pixbuf; -} - - - -/** - * thunar_vfs_thumb_factory_store_thumbnail: - * @factory : a #ThunarVfsThumbFactory. - * @pixbuf : the thumbnail #GdkPixbuf to store or %NULL - * to remember the thumbnail for @uri as failed. - * @info : the #ThunarVfsInfo of the original file. - * @error : return location for errors or %NULL. - * - * Stores @pixbuf as thumbnail for @info in the right place, according - * to the size set for @factory. - * - * If you specify %NULL for @pixbuf, the @factory will remember that - * the thumbnail generation for @info failed. - * - * The usage of this method is thread-safe. - * - * Return value: %TRUE if the thumbnail was stored successfully, - * else %FALSE. - **/ -gboolean -thunar_vfs_thumb_factory_store_thumbnail (ThunarVfsThumbFactory *factory, - const GdkPixbuf *pixbuf, - const ThunarVfsInfo *info, - GError **error) -{ - const gchar *base_path; - GdkPixbuf *thumbnail; - gboolean succeed; - gchar *dst_path; - gchar *tmp_path; - gchar *mtime; - gchar *size; - gchar *md5; - gchar *uri; - gint tmp_fd; - - g_return_val_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory), FALSE); - g_return_val_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf), FALSE); - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - - /* check whether we should save a thumbnail or remember failed generation */ - base_path = G_LIKELY (pixbuf != NULL) ? factory->base_path : factory->fail_path; - - /* verify that the target directory exists */ - if (!xfce_mkdirhier (base_path, 0700, error)) - return FALSE; - - /* determine the URI of the file */ - uri = thunar_vfs_path_dup_uri (info->path); - - /* determine the MD5 sum for the URI */ - md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1); - - /* try to open a temporary file to write the thumbnail to */ - tmp_path = g_strconcat (base_path, md5, ".png.XXXXXX", NULL); - tmp_fd = g_mkstemp (tmp_path); - if (G_UNLIKELY (tmp_fd < 0)) - { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), "%s", g_strerror (errno)); - g_free (md5); - g_free (uri); - return FALSE; - } - - /* close the temporary file as it exists now, and hence - * we successfully avoided a race condition there. - */ - close (tmp_fd); - - /* generate a 1x1 image if we're storing a failure */ - thumbnail = (pixbuf != NULL) ? GDK_PIXBUF (pixbuf) : gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 1, 1); - - /* determine string representations for the modification time and size */ - mtime = g_strdup_printf ("%lu", (gulong) info->mtime); - size = g_strdup_printf ("%" G_GUINT64_FORMAT, (guint64) info->size); - - /* write the thumbnail to the temporary location */ - succeed = gdk_pixbuf_save (thumbnail, tmp_path, "png", error, - "tEXt::Thumb::URI", uri, - "tEXt::Thumb::Size", size, - "tEXt::Thumb::MTime", mtime, - "tEXt::Thumb::Mimetype", thunar_vfs_mime_info_get_name (info->mime_info), - "tEXt::Software", "Thunar-VFS Thumbnail Factory", - NULL); - - /* drop the failed thumbnail pixbuf (if any) */ - if (G_UNLIKELY (pixbuf == NULL)) - g_object_unref (G_OBJECT (thumbnail)); - - /* rename the file to the final location */ - if (G_LIKELY (succeed)) - { - dst_path = g_strconcat (base_path, md5, ".png", NULL); - if (G_UNLIKELY (g_rename (tmp_path, dst_path) < 0)) - { - g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), "%s", g_strerror (errno)); - succeed = FALSE; - } - g_free (dst_path); - } - - /* cleanup */ - g_free (tmp_path); - g_free (mtime); - g_free (size); - g_free (md5); - g_free (uri); - - return succeed; -} - - - -/** - * thunar_vfs_thumbnail_for_path: - * @path : the #ThunarVfsPath to the original file. - * @size : the desired #ThunarVfsThumbSize. - * - * Returns the absolute path to the thumbnail location - * for the file described by @path, at the given @size. - * - * The caller is responsible to free the returned - * string using g_free() when no longer needed. - * - * The usage of this method is thread-safe. - * - * Return value: the absolute path to the thumbnail - * location for @path at @size. - **/ -gchar* -thunar_vfs_thumbnail_for_path (const ThunarVfsPath *path, - ThunarVfsThumbSize size) -{ - gchar *thumbnail; - gchar *md5; - gchar *uri; - - uri = thunar_vfs_path_dup_uri (path); - md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1); - thumbnail = g_strconcat (xfce_get_homedir (), - G_DIR_SEPARATOR_S ".thumbnails" G_DIR_SEPARATOR_S, - (size == THUNAR_VFS_THUMB_SIZE_NORMAL) ? "normal" : "large", - G_DIR_SEPARATOR_S, md5, ".png", NULL); - g_free (md5); - g_free (uri); - - return thumbnail; -} - - - -/** - * thunar_vfs_thumbnail_is_valid: - * @thumbnail : the absolute path to a thumbnail file. - * @uri : the URI of the original file. - * @mtime : the modification time of the original file. - * - * Checks whether the file located at @thumbnail contains a - * valid thumbnail for the file described by @uri and @mtime. - * - * The usage of this method is thread-safe. - * - * Return value: %TRUE if @thumbnail is a valid thumbnail for - * the file referred to by @uri, else %FALSE. - **/ -gboolean -thunar_vfs_thumbnail_is_valid (const gchar *thumbnail, - const gchar *uri, - ThunarVfsFileTime mtime) -{ - png_structp png_ptr; - png_infop info_ptr; - png_textp text_ptr; - gboolean is_valid = FALSE; - gchar signature[4]; - FILE *fp; - gint n_checked; - gint n_text; - gint n; - - g_return_val_if_fail (g_path_is_absolute (thumbnail), FALSE); - g_return_val_if_fail (uri != NULL && *uri != '\0', FALSE); - - /* try to open the thumbnail file */ - fp = fopen (thumbnail, "r"); - if (G_UNLIKELY (fp == NULL)) - return FALSE; - - /* read the png signature */ - if (G_UNLIKELY (fread (signature, 1, sizeof (signature), fp) != sizeof (signature))) - goto done0; - - /* verify the png signature */ - if (G_LIKELY (png_check_sig ((png_bytep) signature, sizeof (signature)))) - rewind (fp); - else - goto done0; - - /* allocate the png read structure */ - png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (G_UNLIKELY (png_ptr == NULL)) - goto done0; - - /* allocate the png info structure */ - info_ptr = png_create_info_struct (png_ptr); - if (G_UNLIKELY (info_ptr == NULL)) - { - png_destroy_read_struct (&png_ptr, NULL, NULL); - goto done0; - } - - /* read the png info from the file */ - png_init_io (png_ptr, fp); - png_read_info (png_ptr, info_ptr); - - /* verify the tEXt attributes defined by the thumbnail spec */ - n_text = png_get_text (png_ptr, info_ptr, &text_ptr, &n_text); - for (n = 0, n_checked = 0; n_checked < 2 && n < n_text; ++n) - { - if (strcmp (text_ptr[n].key, "Thumb::MTime") == 0) - { - /* verify the modification time */ - if (G_UNLIKELY (strtol (text_ptr[n].text, NULL, 10) != mtime)) - goto done1; - ++n_checked; - } - else if (strcmp (text_ptr[n].key, "Thumb::URI") == 0) - { - /* check if the URIs are equal */ - if (strcmp (text_ptr[n].text, uri) != 0) - goto done1; - ++n_checked; - } - } - - /* check if all required attributes were checked successfully */ - is_valid = (n_checked == 2); - -done1: - png_destroy_read_struct (&png_ptr, &info_ptr, NULL); -done0: - fclose (fp); - return is_valid; -} - - - -/** - * _thunar_vfs_thumbnail_remove_for_path: - * @path : the #ThunarVfsPath to the file whose thumbnails should be removed. - * - * Removes any existing thumbnails for the file at the specified @path. - **/ -void -_thunar_vfs_thumbnail_remove_for_path (const ThunarVfsPath *path) -{ - ThunarVfsThumbSize size; - gchar *thumbnail_path; - - /* drop the normal and large thumbnails for the path */ - for (size = THUNAR_VFS_THUMB_SIZE_NORMAL; size < THUNAR_VFS_THUMB_SIZE_LARGE; ++size) - { - /* the thumbnail may not exist, so simply ignore errors here */ - thumbnail_path = thunar_vfs_thumbnail_for_path (path, size); - g_unlink (thumbnail_path); - g_free (thumbnail_path); - } -} - - - -#define __THUNAR_VFS_THUMB_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-thumb.h b/thunar-vfs/thunar-vfs-thumb.h deleted file mode 100644 index a5c7b02e9..000000000 --- a/thunar-vfs/thunar-vfs-thumb.h +++ /dev/null @@ -1,86 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2004-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#if !defined (THUNAR_VFS_INSIDE_THUNAR_VFS_H) && !defined (THUNAR_VFS_COMPILATION) -#error "Only <thunar-vfs/thunar-vfs.h> can be included directly, this file may disappear or change contents." -#endif - -#ifndef __THUNAR_VFS_THUMB_H__ -#define __THUNAR_VFS_THUMB_H__ - -#include <thunar-vfs/thunar-vfs-info.h> -#include <thunar-vfs/thunar-vfs-job.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsThumbFactoryClass ThunarVfsThumbFactoryClass; -typedef struct _ThunarVfsThumbFactory ThunarVfsThumbFactory; - -#define THUNAR_VFS_TYPE_THUMB_FACTORY (thunar_vfs_thumb_factory_get_type ()) -#define THUNAR_VFS_THUMB_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_THUMB_FACTORY, ThunarVfsThumbFactory)) -#define THUNAR_VFS_THUMB_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_THUMB_FACTORY, ThunarVfsThumbFactoryClass)) -#define THUNAR_VFS_IS_THUMB_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_THUMB_FACTORY)) -#define THUNAR_VFS_IS_THUMB_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_THUMB_FACTORY)) -#define THUNAR_VFS_THUMB_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_THUMB_FACTORY, ThunarVfsThumbFactoryClass)) - -/** - * ThunarVfsThumbSize: - * @THUNAR_VFS_THUMB_SIZE_NORMAL : thumbnails at size 128x128. - * @THUNAR_VFS_THUMB_SIZE_LARGE : thumbnails at size 256x256. - * - * The desired size of thumbnails loaded by a #ThunarVfsThumbFactory. - **/ -typedef enum -{ - THUNAR_VFS_THUMB_SIZE_NORMAL, - THUNAR_VFS_THUMB_SIZE_LARGE, -} ThunarVfsThumbSize; - -GType thunar_vfs_thumb_factory_get_type (void) G_GNUC_CONST; - -ThunarVfsThumbFactory *thunar_vfs_thumb_factory_new (ThunarVfsThumbSize size) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -gchar *thunar_vfs_thumb_factory_lookup_thumbnail (ThunarVfsThumbFactory *factory, - const ThunarVfsInfo *info) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -gboolean thunar_vfs_thumb_factory_can_thumbnail (ThunarVfsThumbFactory *factory, - const ThunarVfsInfo *info); - -gboolean thunar_vfs_thumb_factory_has_failed_thumbnail (ThunarVfsThumbFactory *factory, - const ThunarVfsInfo *info); - -GdkPixbuf *thunar_vfs_thumb_factory_generate_thumbnail (ThunarVfsThumbFactory *factory, - const ThunarVfsInfo *info) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -gboolean thunar_vfs_thumb_factory_store_thumbnail (ThunarVfsThumbFactory *factory, - const GdkPixbuf *pixbuf, - const ThunarVfsInfo *info, - GError **error); - - -gchar *thunar_vfs_thumbnail_for_path (const ThunarVfsPath *path, - ThunarVfsThumbSize size) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gboolean thunar_vfs_thumbnail_is_valid (const gchar *thumbnail, - const gchar *uri, - ThunarVfsFileTime mtime); - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_THUMB_H__ */ diff --git a/thunar-vfs/thunar-vfs-transfer-job.c b/thunar-vfs/thunar-vfs-transfer-job.c deleted file mode 100644 index 43d9b3c08..000000000 --- a/thunar-vfs/thunar-vfs-transfer-job.c +++ /dev/null @@ -1,630 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif - -#include <thunar-vfs/thunar-vfs-io-ops.h> -#include <thunar-vfs/thunar-vfs-io-scandir.h> -#include <thunar-vfs/thunar-vfs-job-private.h> -#include <thunar-vfs/thunar-vfs-monitor-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-transfer-job.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -typedef struct _ThunarVfsTransferNode ThunarVfsTransferNode; - - - -static void thunar_vfs_transfer_job_class_init (ThunarVfsTransferJobClass *klass); -static void thunar_vfs_transfer_job_finalize (GObject *object); -static void thunar_vfs_transfer_job_execute (ThunarVfsJob *job); -static gboolean thunar_vfs_transfer_job_progress (ThunarVfsFileSize chunk_size, - gpointer callback_data); -static gboolean thunar_vfs_transfer_job_copy_file (ThunarVfsTransferJob *transfer_job, - ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error); -static void thunar_vfs_transfer_job_node_copy (ThunarVfsTransferJob *transfer_job, - ThunarVfsTransferNode *transfer_node, - ThunarVfsPath *target_path, - ThunarVfsPath *target_parent_path, - GList **target_path_list_return, - GError **error); -static void thunar_vfs_transfer_node_free (ThunarVfsTransferNode *transfer_node); -static gboolean thunar_vfs_transfer_node_collect (ThunarVfsTransferNode *transfer_node, - ThunarVfsFileSize *total_size_return, - volatile gboolean *cancelled, - GError **error); - - - -struct _ThunarVfsTransferJobClass -{ - ThunarVfsInteractiveJobClass __parent__; -}; - -struct _ThunarVfsTransferJob -{ - ThunarVfsInteractiveJob __parent__; - - /* whether to move files instead of copying them */ - gboolean move; - - /* the source nodes and the matching target paths */ - GList *source_node_list; - GList *target_path_list; - - /* the amount of completeness */ - ThunarVfsFileSize total_size; - ThunarVfsFileSize completed_size; -}; - -struct _ThunarVfsTransferNode -{ - ThunarVfsPath *source_path; - ThunarVfsTransferNode *next; - ThunarVfsTransferNode *children; -}; - - - -static GObjectClass *thunar_vfs_transfer_job_parent_class; - - - -GType -thunar_vfs_transfer_job_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_INTERACTIVE_JOB, - "ThunarVfsTransferJob", - sizeof (ThunarVfsTransferJobClass), - thunar_vfs_transfer_job_class_init, - sizeof (ThunarVfsTransferJob), - NULL, - 0); - } - - return type; -} - - - -static void -thunar_vfs_transfer_job_class_init (ThunarVfsTransferJobClass *klass) -{ - ThunarVfsJobClass *thunarvfs_job_class; - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_transfer_job_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_transfer_job_finalize; - - thunarvfs_job_class = THUNAR_VFS_JOB_CLASS (klass); - thunarvfs_job_class->execute = thunar_vfs_transfer_job_execute; -} - - - -static void -thunar_vfs_transfer_job_finalize (GObject *object) -{ - ThunarVfsTransferJob *transfer_job = THUNAR_VFS_TRANSFER_JOB (object); - - /* release the source node list */ - g_list_foreach (transfer_job->source_node_list, (GFunc) thunar_vfs_transfer_node_free, NULL); - g_list_free (transfer_job->source_node_list); - - /* release the target path list */ - thunar_vfs_path_list_free (transfer_job->target_path_list); - - /* call the parents finalize method */ - (*G_OBJECT_CLASS (thunar_vfs_transfer_job_parent_class)->finalize) (object); -} - - - -static void -thunar_vfs_transfer_job_execute (ThunarVfsJob *job) -{ - ThunarVfsTransferNode *transfer_node; - ThunarVfsTransferJob *transfer_job = THUNAR_VFS_TRANSFER_JOB (job); - ThunarVfsPath *target_path; - GError *err = NULL; - GList *new_files_list = NULL; - GList *snext; - GList *tnext; - GList *sp; - GList *tp; - - _thunar_vfs_return_if_fail (g_list_length (transfer_job->source_node_list) == g_list_length (transfer_job->target_path_list)); - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_TRANSFER_JOB (transfer_job)); - - /* update the progress information */ - _thunar_vfs_job_info_message (job, _("Collecting files...")); - - /* collect all source transfer nodes (try to move the stuff first) */ - for (sp = transfer_job->source_node_list, tp = transfer_job->target_path_list; sp != NULL; sp = snext, tp = tnext) - { - /* determine the next list items */ - snext = sp->next; - tnext = tp->next; - - /* determine the current source node */ - transfer_node = sp->data; - - /* try to move the file/folder directly, otherwise fallback to copy logic */ - if (transfer_job->move && _thunar_vfs_io_ops_move_file (transfer_node->source_path, tp->data, &target_path, NULL)) - { - /* add the target file to the new files list */ - new_files_list = g_list_prepend (new_files_list, target_path); - - /* move worked, don't need to keep this node */ - thunar_vfs_transfer_node_free (transfer_node); - thunar_vfs_path_unref (tp->data); - - /* drop the matching list items */ - transfer_job->source_node_list = g_list_delete_link (transfer_job->source_node_list, sp); - transfer_job->target_path_list = g_list_delete_link (transfer_job->target_path_list, tp); - } - else if (!thunar_vfs_transfer_node_collect (transfer_node, &transfer_job->total_size, &job->cancelled, &err)) - { - /* failed to collect, cannot continue */ - break; - } - } - - /* check if we succeed so far */ - if (G_LIKELY (err == NULL)) - { - /* perform the copy recursively for all source transfer nodes, that have not been skipped */ - for (sp = transfer_job->source_node_list, tp = transfer_job->target_path_list; sp != NULL; sp = sp->next, tp = tp->next) - { - /* check if the process was cancelled */ - if (thunar_vfs_job_cancelled (job)) - break; - - /* copy the file for this node */ - thunar_vfs_transfer_job_node_copy (transfer_job, sp->data, tp->data, NULL, &new_files_list, &err); - } - } - - /* check if we failed */ - if (G_UNLIKELY (err != NULL)) - { - /* EINTR should be ignored, as it indicates user cancellation */ - if (G_LIKELY (err->domain != G_FILE_ERROR || err->code != G_FILE_ERROR_INTR)) - _thunar_vfs_job_error (job, err); - - /* we're done */ - g_error_free (err); - } - - /* emit the "new-files" signal if we have any new files */ - if (!thunar_vfs_job_cancelled (job)) - _thunar_vfs_job_new_files (job, new_files_list); - thunar_vfs_path_list_free (new_files_list); -} - - - -static gboolean -thunar_vfs_transfer_job_progress (ThunarVfsFileSize chunk_size, - gpointer callback_data) -{ - ThunarVfsTransferJob *transfer_job = THUNAR_VFS_TRANSFER_JOB (callback_data); - gdouble percent; - - /* update the current completed size */ - transfer_job->completed_size += chunk_size; - - /* check if we can calculate the percentage */ - if (G_LIKELY (transfer_job->total_size > 0)) - { - /* calculate the new percentage */ - percent = (transfer_job->completed_size * 100.0) / transfer_job->total_size; - _thunar_vfs_job_percent (THUNAR_VFS_JOB (transfer_job), percent); - } - - return !thunar_vfs_job_cancelled (THUNAR_VFS_JOB (transfer_job)); -} - - - -static gboolean -thunar_vfs_transfer_job_copy_file (ThunarVfsTransferJob *transfer_job, - ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - ThunarVfsPath **target_path_return, - GError **error) -{ - ThunarVfsJobResponse response; - GError *err = NULL; - - _thunar_vfs_return_val_if_fail (THUNAR_VFS_IS_TRANSFER_JOB (transfer_job), FALSE); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (target_path_return != NULL, FALSE); - - /* various attemps to copy the file */ - while (err == NULL && !thunar_vfs_job_cancelled (THUNAR_VFS_JOB (transfer_job))) - { - /* try to copy the file from source_path to the target_path */ - if (_thunar_vfs_io_ops_copy_file (source_path, target_path, &target_path, thunar_vfs_transfer_job_progress, transfer_job, &err)) - { - /* return the real target path */ - *target_path_return = target_path; - return TRUE; - } - - /* check if we can recover from this error */ - if (err->domain == G_FILE_ERROR && err->code == G_FILE_ERROR_EXIST) - { - /* reset the error */ - g_clear_error (&err); - - /* ask the user whether to replace the target file */ - response = _thunar_vfs_job_ask_replace (THUNAR_VFS_JOB (transfer_job), source_path, target_path); - - /* check if we should retry the copy operation */ - if (response == THUNAR_VFS_JOB_RESPONSE_RETRY) - continue; - - /* try to remove the target file if we should overwrite */ - if (response == THUNAR_VFS_JOB_RESPONSE_YES && !_thunar_vfs_io_ops_remove (target_path, THUNAR_VFS_IO_OPS_IGNORE_ENOENT, &err)) - break; - - /* check if we should skip this file */ - if (response == THUNAR_VFS_JOB_RESPONSE_NO) - { - /* tell the caller that we skipped this one */ - *target_path_return = NULL; - return TRUE; - } - } - } - - /* check if we were cancelled */ - if (G_LIKELY (err == NULL)) - { - /* user cancellation is represented by EINTR */ - _thunar_vfs_set_g_error_from_errno (error, EINTR); - } - else - { - /* propagate the error */ - g_propagate_error (error, err); - } - - return FALSE; -} - - - -static void -thunar_vfs_transfer_job_node_copy (ThunarVfsTransferJob *transfer_job, - ThunarVfsTransferNode *transfer_node, - ThunarVfsPath *target_path, - ThunarVfsPath *target_parent_path, - GList **target_path_list_return, - GError **error) -{ - ThunarVfsPath *target_path_return; - gchar *display_name; - GError *err = NULL; - gboolean retry; - - _thunar_vfs_return_if_fail ((target_path == NULL && target_parent_path != NULL) || (target_path != NULL && target_parent_path == NULL)); - _thunar_vfs_return_if_fail (target_path == NULL || transfer_node->next == NULL); - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_TRANSFER_JOB (transfer_job)); - _thunar_vfs_return_if_fail (error == NULL || *error == NULL); - _thunar_vfs_return_if_fail (transfer_node != NULL); - - /* The caller can either provide a target_path or a target_parent_path, but not both. The toplevel - * transfer_nodes (for which next is NULL) should be called with target_path, to get proper behavior - * wrt restoring files from the trash. Other transfer_nodes will be called with target_parent_path. - */ - - /* process all transfer nodes in the row */ - for (; err == NULL && !thunar_vfs_job_cancelled (THUNAR_VFS_JOB (transfer_job)) && transfer_node != NULL; transfer_node = transfer_node->next) - { - /* guess the target_path for this file item (if not provided) */ - if (G_LIKELY (target_path == NULL)) - target_path = _thunar_vfs_path_child (target_parent_path, thunar_vfs_path_get_name (transfer_node->source_path)); - else - target_path = thunar_vfs_path_ref (target_path); - - /* update the progress information */ - display_name = _thunar_vfs_path_dup_display_name (_thunar_vfs_path_is_local (target_path) ? target_path : transfer_node->source_path); - _thunar_vfs_job_info_message (THUNAR_VFS_JOB (transfer_job), display_name); - g_free (display_name); - -retry_copy: - /* copy the item specified by this node (not recursive!) */ - if (thunar_vfs_transfer_job_copy_file (transfer_job, transfer_node->source_path, target_path, &target_path_return, &err)) - { - /* target_path_return == NULL: skip this file */ - if (G_LIKELY (target_path_return != NULL)) - { - /* check if we have children to copy */ - if (transfer_node->children != NULL) - { - /* copy all children for this node */ - thunar_vfs_transfer_job_node_copy (transfer_job, transfer_node->children, NULL, target_path_return, NULL, &err); - - /* free the resources allocated to the children */ - thunar_vfs_transfer_node_free (transfer_node->children); - transfer_node->children = NULL; - } - - /* check if the child copy failed */ - if (G_UNLIKELY (err != NULL)) - { - /* outa here, freeing the target paths */ - thunar_vfs_path_unref (target_path_return); - thunar_vfs_path_unref (target_path); - break; - } - - /* add the real target path to the return list */ - if (G_LIKELY (target_path_list_return != NULL)) - *target_path_list_return = g_list_prepend (*target_path_list_return, target_path_return); - else - thunar_vfs_path_unref (target_path_return); - -retry_remove: - /* try to remove the source directory if we should move instead of just copy */ - if (transfer_job->move && !_thunar_vfs_io_ops_remove (transfer_node->source_path, THUNAR_VFS_IO_OPS_IGNORE_ENOENT, &err)) - { - /* we can ignore ENOTEMPTY (which is mapped to G_FILE_ERROR_FAILED) */ - if (err->domain == G_FILE_ERROR && err->code == G_FILE_ERROR_FAILED) - { - /* no error then... */ - g_clear_error (&err); - } - else - { - /* ask the user whether to skip/retry the removal */ - retry = (_thunar_vfs_job_ask_skip (THUNAR_VFS_JOB (transfer_job), "%s", err->message) == THUNAR_VFS_JOB_RESPONSE_RETRY); - - /* reset the error */ - g_clear_error (&err); - - /* check whether to retry */ - if (G_UNLIKELY (retry)) - goto retry_remove; - } - } - } - } - else if (err != NULL && (err->domain != G_FILE_ERROR || err->code != G_FILE_ERROR_NOSPC)) /* ENOSPC cannot be skipped! */ - { - /* ask the user whether to skip this node and all subnodes (-> cancellation) */ - retry = (_thunar_vfs_job_ask_skip (THUNAR_VFS_JOB (transfer_job), "%s", err->message) == THUNAR_VFS_JOB_RESPONSE_RETRY); - - /* reset the error */ - g_clear_error (&err); - - /* check whether to retry */ - if (G_UNLIKELY (retry)) - goto retry_copy; - } - - /* release the guessed target_path */ - thunar_vfs_path_unref (target_path); - target_path = NULL; - } - - /* check if we failed */ - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - } -} - - - - - - -static gboolean -thunar_vfs_transfer_node_collect (ThunarVfsTransferNode *transfer_node, - ThunarVfsFileSize *total_size_return, - volatile gboolean *cancelled, - GError **error) -{ - ThunarVfsTransferNode *child_node; - ThunarVfsFileSize size; - ThunarVfsFileType type; - GError *err = NULL; - GList *path_list; - GList *lp; - - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, FALSE); - _thunar_vfs_return_val_if_fail (total_size_return != NULL, FALSE); - _thunar_vfs_return_val_if_fail (transfer_node != NULL, FALSE); - _thunar_vfs_return_val_if_fail (cancelled != NULL, FALSE); - - /* determine the file size and mode */ - if (!_thunar_vfs_io_ops_get_file_size_and_type (transfer_node->source_path, &size, &type, error)) - return FALSE; - - /* add the file size to the total size */ - *total_size_return += size; - - /* check if we have a directory here */ - if (type == THUNAR_VFS_FILE_TYPE_DIRECTORY) - { - /* scan the directory and add appropriate children for this transfer node */ - path_list = _thunar_vfs_io_scandir (transfer_node->source_path, cancelled, 0, &err); - for (lp = path_list; err == NULL && lp != NULL; lp = lp->next) - { - /* check if the user cancelled the process */ - if (G_UNLIKELY (*cancelled)) - { - /* user cancellation is represented as EINTR */ - _thunar_vfs_set_g_error_from_errno (&err, EINTR); - } - else - { - /* allocate a new transfer node for the child */ - child_node = _thunar_vfs_slice_new0 (ThunarVfsTransferNode); - child_node->source_path = lp->data; - - /* hook the child node into the child list */ - child_node->next = transfer_node->children; - transfer_node->children = child_node; - - /* collect the child node */ - thunar_vfs_transfer_node_collect (child_node, total_size_return, cancelled, &err); - } - } - - /* release the remaining items on the path_list */ - g_list_foreach (lp, (GFunc) thunar_vfs_path_unref, NULL); - g_list_free (path_list); - } - - /* check if we failed */ - if (G_UNLIKELY (err != NULL)) - { - /* propagate the error */ - g_propagate_error (error, err); - return FALSE; - } - - return TRUE; -} - - - -static void -thunar_vfs_transfer_node_free (ThunarVfsTransferNode *transfer_node) -{ - ThunarVfsTransferNode *transfer_next; - - /* free all nodes in a row */ - while (transfer_node != NULL) - { - /* free all children of this node */ - thunar_vfs_transfer_node_free (transfer_node->children); - - /* determine the next node */ - transfer_next = transfer_node->next; - - /* drop the source path for this node */ - thunar_vfs_path_unref (transfer_node->source_path); - - /* release the resources for this node */ - _thunar_vfs_slice_free (ThunarVfsTransferNode, transfer_node); - - /* continue with the next node */ - transfer_node = transfer_next; - } -} - - - -/** - * thunar_vfs_transfer_job_new: - * @source_path_list : a list of #ThunarVfsPath<!---->s that should be transferred. - * @target_path_list : a list of #ThunarVfsPath<!---->s referring to the targets of the transfer. - * @move : whether to copy or move the files. - * @error : return location for errors or %NULL. - * - * Transfers the files from the @source_path_list to the files in the @target_path_list. - * @source_path_list and @target_path_list must be of the same length. - * - * If @move is %FALSE, then all source/target path tuple, which refer to the same - * file cause a duplicate action, which means a new unique target path will be - * generated based on the source path. - * - * The caller is responsible to free the returned object using g_object_unref() - * when no longer needed. - * - * Return value: the newly allocated #ThunarVfsTransferJob or %NULL on error. - **/ -ThunarVfsJob* -thunar_vfs_transfer_job_new (GList *source_path_list, - GList *target_path_list, - gboolean move, - GError **error) -{ - ThunarVfsTransferNode *transfer_node; - ThunarVfsTransferJob *transfer_job; - GList *sp, *tp; - - _thunar_vfs_return_val_if_fail (g_list_length (target_path_list) == g_list_length (source_path_list), NULL); - _thunar_vfs_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* allocate the job object */ - transfer_job = g_object_new (THUNAR_VFS_TYPE_TRANSFER_JOB, NULL); - transfer_job->move = move; - - /* add a transfer node for each source path, and a matching target parent path */ - for (sp = source_path_list, tp = target_path_list; sp != NULL; sp = sp->next, tp = tp->next) - { - /* verify that we don't transfer the root directory */ - if (G_UNLIKELY (thunar_vfs_path_is_root (sp->data) || thunar_vfs_path_is_root (tp->data))) - { - /* we don't support this, the file manager will prevent this anyway */ - _thunar_vfs_set_g_error_not_supported (error); - g_object_unref (G_OBJECT (transfer_job)); - return NULL; - } - - /* strip off all pairs with source=target when not copying */ - if (G_LIKELY (!move || !thunar_vfs_path_equal (sp->data, tp->data))) - { - /* allocate a node for the source and add it to the source list */ - transfer_node = _thunar_vfs_slice_new0 (ThunarVfsTransferNode); - transfer_node->source_path = thunar_vfs_path_ref (sp->data); - transfer_job->source_node_list = g_list_append (transfer_job->source_node_list, transfer_node); - - /* append the target path to the target list */ - transfer_job->target_path_list = thunar_vfs_path_list_append (transfer_job->target_path_list, tp->data); - } - } - - /* make sure that we did not mess up anything */ - _thunar_vfs_assert (g_list_length (transfer_job->source_node_list) == g_list_length (transfer_job->target_path_list)); - - /* the job is ready */ - return THUNAR_VFS_JOB (transfer_job); -} - - - -#define __THUNAR_VFS_TRANSFER_JOB_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-transfer-job.h b/thunar-vfs/thunar-vfs-transfer-job.h deleted file mode 100644 index b297a985a..000000000 --- a/thunar-vfs/thunar-vfs-transfer-job.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_TRANSFER_JOB_H__ -#define __THUNAR_VFS_TRANSFER_JOB_H__ - -#include <thunar-vfs/thunar-vfs-interactive-job.h> -#include <thunar-vfs/thunar-vfs-path.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsTransferJobClass ThunarVfsTransferJobClass; -typedef struct _ThunarVfsTransferJob ThunarVfsTransferJob; - -#define THUNAR_VFS_TYPE_TRANSFER_JOB (thunar_vfs_transfer_job_get_type ()) -#define THUNAR_VFS_TRANSFER_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_TRANSFER_JOB, ThunarVfsTransferJob)) -#define THUNAR_VFS_TRANSFER_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_TRANSFER_JOB, ThunarVfsTransferJobClass)) -#define THUNAR_VFS_IS_TRANSFER_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_TRANSFER_JOB)) -#define THUNAR_VFS_IS_TRANSFER_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_TRANSFER_JOB)) -#define THUNAR_VFS_TRANSFER_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_TRANSFER_JOB, ThunarVfsTransferJobClass)) - -GType thunar_vfs_transfer_job_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - -ThunarVfsJob *thunar_vfs_transfer_job_new (GList *source_path_list, - GList *target_path_list, - gboolean move, - GError **error) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_TRANSFER_JOB_H__ */ diff --git a/thunar-vfs/thunar-vfs-types.h b/thunar-vfs/thunar-vfs-types.h deleted file mode 100644 index 3d9de697d..000000000 --- a/thunar-vfs/thunar-vfs-types.h +++ /dev/null @@ -1,158 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_TYPES_H__ -#define __THUNAR_VFS_TYPES_H__ - -#include <sys/types.h> -#include <unistd.h> - -#include <glib.h> - -G_BEGIN_DECLS; - -/** - * ThunarVfsDeepCountFlags: - * @THUNAR_VFS_DEEP_COUNT_FLAGS_NONE : no special behavior. - * @THUNAR_VFS_DEEP_COUNT_FLAGS_FOLLOW_SYMLINKS : follow symlinks to folders. If this flag is set, the - * job will also count symlinked folders recursively. - * - * Additional flags to pass to thunar_vfs_deep_count(), which - * control the exact behavior of the job. - **/ -typedef enum /*< flags >*/ -{ - THUNAR_VFS_DEEP_COUNT_FLAGS_NONE = 0L, - THUNAR_VFS_DEEP_COUNT_FLAGS_FOLLOW_SYMLINKS = 1L << 0, -} ThunarVfsDeepCountFlags; - -/** - * ThunarVfsFileType: - * @THUNAR_VFS_FILE_TYPE_FIFO : A named FIFO. - * @THUNAR_VFS_FILE_TYPE_CHARDEV : A character device node. - * @THUNAR_VFS_FILE_TYPE_DIRECTORY: A directory node. - * @THUNAR_VFS_FILE_TYPE_BLOCKDEV : A block device node. - * @THUNAR_VFS_FILE_TYPE_REGULAR : A regular file. - * @THUNAR_VFS_FILE_TYPE_SYMLINK : A broken symlink, for which the target does - * not exist (if the target would exist, the - * #ThunarVfsInfo object would have the type - * of the target). - * @THUNAR_VFS_FILE_TYPE_SOCKET : A unix domain socket. - * @THUNAR_VFS_FILE_TYPE_DOOR : A door (Solaris IPC mechanism). - * @THUNAR_VFS_FILE_TYPE_PORT : An event port (Solaris event framework). - * @THUNAR_VFS_FILE_TYPE_UNKNOWN : The exact type of the file could not be - * determined. - * - * Describes the type of a file. - **/ -typedef enum -{ - THUNAR_VFS_FILE_TYPE_PORT = 0160000 >> 12, - THUNAR_VFS_FILE_TYPE_DOOR = 0150000 >> 12, - THUNAR_VFS_FILE_TYPE_SOCKET = 0140000 >> 12, - THUNAR_VFS_FILE_TYPE_SYMLINK = 0120000 >> 12, - THUNAR_VFS_FILE_TYPE_REGULAR = 0100000 >> 12, - THUNAR_VFS_FILE_TYPE_BLOCKDEV = 0060000 >> 12, - THUNAR_VFS_FILE_TYPE_DIRECTORY = 0040000 >> 12, - THUNAR_VFS_FILE_TYPE_CHARDEV = 0020000 >> 12, - THUNAR_VFS_FILE_TYPE_FIFO = 0010000 >> 12, - THUNAR_VFS_FILE_TYPE_UNKNOWN = 0000000 >> 12, -} ThunarVfsFileType; - -/** - * ThunarVfsFileMode: - * @THUNAR_VFS_FILE_MODE_SUID : SUID bit. - * @THUNAR_VFS_FILE_MODE_SGID : SGID bit. - * @THUNAR_VFS_FILE_MODE_STICKY : Sticky bit. - * @THUNAR_VFS_FILE_MODE_USR_ALL : Owner can do everything. - * @THUNAR_VFS_FILE_MODE_USR_READ : Owner can read the file. - * @THUNAR_VFS_FILE_MODE_USR_WRITE: Owner can write the file. - * @THUNAR_VFS_FILE_MODE_USR_EXEC : Owner can execute the file. - * @THUNAR_VFS_FILE_MODE_GRP_ALL : Owner group can do everything. - * @THUNAR_VFS_FILE_MODE_GRP_READ : Owner group can read the file. - * @THUNAR_VFS_FILE_MODE_GRP_WRITE: Owner group can write the file. - * @THUNAR_VFS_FILE_MODE_GRP_EXEC : Owner group can execute the file. - * @THUNAR_VFS_FILE_MODE_OTH_ALL : Others can do everything. - * @THUNAR_VFS_FILE_MODE_OTH_READ : Others can read the file. - * @THUNAR_VFS_FILE_MODE_OTH_WRITE: Others can write the file. - * @THUNAR_VFS_FILE_MODE_OTH_EXEC : Others can execute the file. - * - * Special flags and permissions of a filesystem entity. - **/ -typedef enum /*< flags >*/ -{ - THUNAR_VFS_FILE_MODE_SUID = 04000, - THUNAR_VFS_FILE_MODE_SGID = 02000, - THUNAR_VFS_FILE_MODE_STICKY = 01000, - THUNAR_VFS_FILE_MODE_USR_ALL = 00700, - THUNAR_VFS_FILE_MODE_USR_READ = 00400, - THUNAR_VFS_FILE_MODE_USR_WRITE = 00200, - THUNAR_VFS_FILE_MODE_USR_EXEC = 00100, - THUNAR_VFS_FILE_MODE_GRP_ALL = 00070, - THUNAR_VFS_FILE_MODE_GRP_READ = 00040, - THUNAR_VFS_FILE_MODE_GRP_WRITE = 00020, - THUNAR_VFS_FILE_MODE_GRP_EXEC = 00010, - THUNAR_VFS_FILE_MODE_OTH_ALL = 00007, - THUNAR_VFS_FILE_MODE_OTH_READ = 00004, - THUNAR_VFS_FILE_MODE_OTH_WRITE = 00002, - THUNAR_VFS_FILE_MODE_OTH_EXEC = 00001, -} ThunarVfsFileMode; - -/** - * ThunarVfsFileFlags: - * @THUNAR_VFS_FILE_FLAGS_NONE : No additional information available. - * @THUNAR_VFS_FILE_FLAGS_SYMLINK : The file is a symlink. Whether or not - * the info fields refer to the symlink - * itself or the linked file, depends on - * whether the symlink is broken or not. - * @THUNAR_VFS_FILE_FLAGS_EXECUTABLE : The file can most probably be executed - * by thunar_vfs_info_execute(). - * @THUNAR_VFS_FILE_FLAGS_HIDDEN : The file should not be displayed normally, - * but only if the user requests to display - * hidden files. Hidden files start with a - * dot character ('.') or end with a tilde - * character ('~'). - * @THUNAR_VFS_FILE_FLAGS_READABLE : The file can most probably be read by the - * current user. - * @THUNAR_VFS_FILE_FLAGS_WRITABLE : The file can most probably be written by - * the current user. - * - * Flags providing additional information about the - * file system entity. - **/ -typedef enum /*< flags >*/ -{ - THUNAR_VFS_FILE_FLAGS_NONE = 0, - THUNAR_VFS_FILE_FLAGS_SYMLINK = 1L << 0, - THUNAR_VFS_FILE_FLAGS_EXECUTABLE = 1L << 1, - THUNAR_VFS_FILE_FLAGS_HIDDEN = 1L << 2, - THUNAR_VFS_FILE_FLAGS_READABLE = 1L << 3, - THUNAR_VFS_FILE_FLAGS_WRITABLE = 1L << 4, -} ThunarVfsFileFlags; - -typedef dev_t ThunarVfsFileDevice; -typedef gint64 ThunarVfsFileSize; -typedef time_t ThunarVfsFileTime; -typedef gid_t ThunarVfsGroupId; -typedef uid_t ThunarVfsUserId; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_TYPES_H__ */ diff --git a/thunar-vfs/thunar-vfs-update-thumbnailers-cache.c b/thunar-vfs/thunar-vfs-update-thumbnailers-cache.c deleted file mode 100644 index b9ddaa6ff..000000000 --- a/thunar-vfs/thunar-vfs-update-thumbnailers-cache.c +++ /dev/null @@ -1,589 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/******************************************************************************** - * WHAT IS THIS? * - * * - * thunar-vfs-update-thumbnailers-cache-1 is a small utility that collects the * - * available thumbnailers on the system and generates a thumbnailers.cache file * - * in the users home directory (in $XDG_CACHE_HOME/Thunar/), which provides a * - * mapping between mime types and the thumbnailers that can handle these mime * - * types. * - * * - * See the file docs/ThumbnailersCacheFormat.txt for a description of the file * - * format and thumbnailing in thunar-vfs. * - ********************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <gdk-pixbuf/gdk-pixbuf.h> - -#include <libxfce4util/libxfce4util.h> - -#ifdef HAVE_GCONF -#include <gconf/gconf-client.h> -#endif - -/* use g_access(), g_open(), g_rename() and g_unlink() on win32 */ -#if defined(G_OS_WIN32) -#include <glib/gstdio.h> -#else -#define g_access(filename, mode) (access ((filename), (mode))) -#define g_open(filename, flags, mode) (open ((filename), (flags), (mode))) -#define g_rename(oldfilename, newfilename) (rename ((oldfilename), (newfilename))) -#define g_unlink(filename) (unlink ((filename))) -#endif - - - -#define CACHE_VERSION_MAJOR (1) -#define CACHE_VERSION_MINOR (0) - - - -static gint -mime_type_compare (gconstpointer a, - gconstpointer b) -{ - gint a_len; - gint b_len; - - a_len = strlen (a); - b_len = strlen (b); - - if (a_len == b_len) - return strcmp (a, b); - else - return a_len - b_len; -} - - - -static void -thumbnailers_serialize_foreach (gpointer key, - gpointer value, - gpointer user_data) -{ - /* insert the key (-> mime type) into the return list */ - *((GSList **) user_data) = g_slist_insert_sorted (*((GSList **) user_data), key, mime_type_compare); -} - - - -static guchar* -thumbnailers_serialize (GHashTable *thumbnailers, - guint *size_return) -{ - GHashTable *thumbnailer_scripts_offsets; - guint thumbnailer_scripts_size; - GSList *mime_types = NULL; - guint mime_type_strings_size; - GSList *lp; - guchar *serialized; - gchar *script; - guint offset_thumbnailers_strings; - guint offset_thumbnailers_table; - guint offset_mime_type_strings; - guint offset_mime_type_table; - guint offset_strings; - guint offset_table; - guint offset; - guint length; - guint n_mime_types; - guint size; - - /* collect all keys (-> mime types) from the hash table */ - g_hash_table_foreach (thumbnailers, thumbnailers_serialize_foreach, &mime_types); - - /* the mime type strings */ - mime_type_strings_size = 0; - for (lp = mime_types, n_mime_types = 0; lp != NULL; lp = lp->next, ++n_mime_types) - { - /* mime type strings are aligned at 4 byte boundaries */ - mime_type_strings_size += ((strlen (lp->data) + 1 + 3) / 4) * 4; - } - - /* the thumbnailer scripts */ - thumbnailer_scripts_size = 0; - thumbnailer_scripts_offsets = g_hash_table_new (g_str_hash, g_str_equal); - for (lp = mime_types; lp != NULL; lp = lp->next) - { - /* do not add thumbnailer scripts twice */ - script = g_hash_table_lookup (thumbnailers, lp->data); - if (!g_hash_table_lookup_extended (thumbnailer_scripts_offsets, script, NULL, NULL)) - { - /* thumbnailer strings are aligned at 4 byte boundaries */ - offset = thumbnailer_scripts_size; - thumbnailer_scripts_size += ((strlen (script) + 1 + 3) / 4) * 4; - g_hash_table_insert (thumbnailer_scripts_offsets, script, GUINT_TO_POINTER (offset)); - } - } - - /* overall size: header + mime type table + mime type strings + thumbnailer table + thumbnailer strings */ - size = (4 + 4 + 4 + 4) + (n_mime_types * 8) + mime_type_strings_size + (n_mime_types * 4) + thumbnailer_scripts_size; - - /* determine the various offsets */ - offset_mime_type_table = 4 + 4 + 4 + 4; - offset_mime_type_strings = offset_mime_type_table + (n_mime_types * 8); - offset_thumbnailers_table = offset_mime_type_strings + mime_type_strings_size; - offset_thumbnailers_strings = offset_thumbnailers_table + (n_mime_types * 4); - - /* allocate memory and setup the header */ - serialized = g_malloc0 (size); - *((guint32 *) (serialized + 0)) = GUINT32_TO_BE ((guint32) CACHE_VERSION_MAJOR); - *((guint32 *) (serialized + 4)) = GUINT32_TO_BE ((guint32) CACHE_VERSION_MINOR); - *((guint32 *) (serialized + 8)) = GUINT32_TO_BE ((guint32) n_mime_types); - *((guint32 *) (serialized + 12)) = GUINT32_TO_BE ((guint32) offset_thumbnailers_table); - - /* write the mime type table */ - for (lp = mime_types, offset_strings = offset_mime_type_strings, offset_table = offset_mime_type_table; lp != NULL; lp = lp->next) - { - /* write the mime type table entry */ - length = strlen (lp->data); - *((guint32 *) (serialized + offset_table + 0)) = GUINT32_TO_BE ((guint32) length); - *((guint32 *) (serialized + offset_table + 4)) = GUINT32_TO_BE ((guint32) offset_strings); - offset_table += 8; - - /* write the mime type string */ - memcpy (serialized + offset_strings, lp->data, length + 1); - offset_strings += ((length + 1 + 3) / 4) * 4; - } - - /* write the thumbnailer table */ - for (lp = mime_types, offset_table = offset_thumbnailers_table; lp != NULL; lp = lp->next) - { - /* determine the script for the mime type */ - script = g_hash_table_lookup (thumbnailers, lp->data); - - /* lookup the offset for the thumbnailer string */ - offset_strings = offset_thumbnailers_strings + GPOINTER_TO_UINT (g_hash_table_lookup (thumbnailer_scripts_offsets, script)); - - /* write the thumbnailer table entry */ - *((guint32 *) (serialized + offset_table)) = GUINT32_TO_BE ((guint32) offset_strings); - offset_table += 4; - - /* write the thumbnailer scripts string */ - memcpy (serialized + offset_strings, script, strlen (script)); - } - - *size_return = size; - return serialized; -} - - - -static void -thumbnailers_load_gnome (GHashTable *thumbnailers) -{ -#ifdef HAVE_GCONF - /* load the available thumbnailers from GConf */ - GConfClient *client; - GSList *formats; - GSList *lp; - gchar *mime_type; - gchar *script; - gchar *format; - gchar key[1024]; - guint n; - - /* grab a reference on the default GConf client */ - client = gconf_client_get_default (); - - /* determine the MIME types supported by the GNOME thumbnailers */ - formats = gconf_client_all_dirs (client, "/desktop/gnome/thumbnailers", NULL); - for (lp = formats; lp != NULL; lp = lp->next) - { - /* check if the given thumbnailer is enabled */ - format = (gchar *) lp->data; - g_snprintf (key, sizeof (key), "%s/enable", format); - if (gconf_client_get_bool (client, key, NULL)) - { - /* determine the command */ - g_snprintf (key, sizeof (key), "%s/command", format); - script = gconf_client_get_string (client, key, NULL); - if (G_LIKELY (script != NULL)) - { - mime_type = strrchr (format, '/'); - if (G_LIKELY (mime_type != NULL)) - { - /* skip past slash */ - ++mime_type; - - /* convert '@' to slash in the mime_type */ - for (n = 0; mime_type[n] != '\0'; ++n) - if (G_UNLIKELY (mime_type[n] == '@')) - mime_type[n] = '/'; - - /* add the script to the thumbnailers list */ - g_hash_table_insert (thumbnailers, mime_type, script); - } - } - } - } -#else - /* load some well known GNOME thumbnailers */ - static const struct - { - const gchar *binary; - const gchar *parameters; - const gchar *mime_types; - } WELL_KNOWN_THUMBNAILERS[] = - { - { /* Evince */ - "evince-thumbnailer", "-s %s %u %o", - "application/pdf;" - "application/x-dvi", - }, - { /* Totem */ - "totem-video-thumbnailer", "-s %s %u %o", - "application/ogg;" - "application/vnd.rn-realmedia;" - "application/x-extension-m4a;" - "application/x-extension-mp4;" - "application/x-matroska;" - "application/x-ogg;" - "application/x-shockwave-flash;" - "application/x-shorten;" - "audio/x-pn-realaudio;" - "image/vnd.rn-realpix;" - "misc/ultravox;" - "video/3gpp;" - "video/dv;" - "video/mp4;" - "video/mpeg;" - "video/msvideo;" - "video/quicktime;" - "video/vnd.rn-realvideo;" - "video/x-anim;" - "video/x-avi;" - "video/x-flc;" - "video/x-fli;" - "video/x-mpeg;" - "video/x-ms-asf;" - "video/x-ms-wmv;" - "video/x-msvideo;" - "video/x-nsv", - }, - { /* Gsf Thumbnailer */ - "gsf-office-thumbnailer", "-i %i -o %o -s %s", - "application/vnd.ms-excel;" - "application/vnd.ms-powerpoint;" - "application/vnd.oasis.opendocument.presentation;" - "application/vnd.oasis.opendocument.presentation-template;" - "application/vnd.oasis.opendocument.spreadsheet;" - "application/vnd.oasis.opendocument.spreadsheet-template;" - "application/vnd.oasis.opendocument.text;" - "application/vnd.oasis.opendocument.text-template", - }, - { /* Font Thumbnailer */ - "gnome-thumbnail-font", "%u %o", - "application/x-font-otf;" - "application/x-font-pcf;" - "application/x-font-ttf;" - "application/x-font-type1", - }, - { /* Theme Thumbnailer */ - "gnome-theme-thumbnailer", "%u %o", - "application/x-gnome-theme;" - "application/x-gnome-theme-installed", - }, - }; - - gchar **mime_types; - gchar *script; - gchar *path; - guint m, n; - - /* test all of the well-known thumbnailers */ - for (n = 0; n < G_N_ELEMENTS (WELL_KNOWN_THUMBNAILERS); ++n) - { - /* check if the thumbnailer is installed */ - path = g_find_program_in_path (WELL_KNOWN_THUMBNAILERS[n].binary); - if (G_UNLIKELY (path == NULL)) - continue; - - /* generate the script command */ - script = g_strconcat (WELL_KNOWN_THUMBNAILERS[n].binary, " ", WELL_KNOWN_THUMBNAILERS[n].parameters, NULL); - - /* add the script for all specified mime types */ - mime_types = g_strsplit (WELL_KNOWN_THUMBNAILERS[n].mime_types, ";", -1); - for (m = 0; mime_types[m] != NULL; ++m) - g_hash_table_insert (thumbnailers, mime_types[m], script); - } -#endif -} - - - -static void -thumbnailers_load_pixbuf (GHashTable *thumbnailers) -{ - GSList *formats; - GSList *lp; - gchar **mime_types; - guint n; - - /* determine the formats supported by gdk-pixbuf */ - formats = gdk_pixbuf_get_formats (); - for (lp = formats; lp != NULL; lp = lp->next) - { - /* determine the mime types for the format */ - mime_types = gdk_pixbuf_format_get_mime_types (lp->data); - for (n = 0; mime_types[n] != NULL; ++n) - { - /* set our thumbnailer for all those mime types */ - g_hash_table_insert (thumbnailers, mime_types[n], LIBEXECDIR G_DIR_SEPARATOR_S "thunar-vfs-pixbuf-thumbnailer-1 %s %i %o"); - } - } -} - - - -static void -thumbnailers_load_custom (GHashTable *thumbnailers) -{ - const gchar *exec; - const gchar *type; - XfceRc *rc; - gchar **mime_types; - gchar **specs; - gchar *path; - guint n, m; - - /* load available custom thumbnailers from $XDG_DATA_DIRS/thumbnailers/ */ - specs = xfce_resource_match (XFCE_RESOURCE_DATA, "thumbnailers/*.desktop", TRUE); - for (n = 0; specs[n] != NULL; ++n) - { - /* try to load the .desktop file */ - rc = xfce_rc_config_open (XFCE_RESOURCE_DATA, specs[n], TRUE); - if (G_UNLIKELY (rc == NULL)) - continue; - - /* we only care for the [Desktop Entry] group */ - xfce_rc_set_group (rc, "Desktop Entry"); - - /* verify that we have an X-Thumbnailer here */ - type = xfce_rc_read_entry_untranslated (rc, "Type", NULL); - if (G_UNLIKELY (type == NULL || strcmp (type, "X-Thumbnailer") != 0)) - continue; - - /* check if the thumbnailer specifies a TryExec field */ - exec = xfce_rc_read_entry_untranslated (rc, "TryExec", NULL); - if (G_UNLIKELY (exec != NULL)) - { - /* check if the binary exists and is executable */ - path = g_path_is_absolute (exec) ? (gchar *) exec : g_find_program_in_path (exec); - if (G_UNLIKELY (path == NULL || g_access (path, X_OK) < 0)) - continue; - } - - /* verify that the thumbnailer specifies an X-Thumbnailer-Exec field */ - exec = xfce_rc_read_entry_untranslated (rc, "X-Thumbnailer-Exec", NULL); - if (G_UNLIKELY (exec == NULL)) - continue; - - /* determine the mime types for this thumbnailer */ - mime_types = xfce_rc_read_list_entry (rc, "MimeType", ";"); - if (G_UNLIKELY (mime_types == NULL)) - continue; - - /* process all specified mime types */ - for (m = 0; mime_types[m] != NULL; ++m) - { - /* check if we have a valid mime type here */ - if (strlen (mime_types[m]) > 0 && strstr (mime_types[m], "/") != NULL) - { - /* set our thumbnailer for all those mime types (don't need to - * duplicate the exec string, because we leave the RC file open). - */ - g_hash_table_insert (thumbnailers, mime_types[m], (gchar *) exec); - } - } - } -} - - - -static gboolean -thumbnailers_needs_update (const gchar *filename, - gconstpointer serialized, - guint serialized_size) -{ - struct stat statb; - gboolean needs_update; - gssize m; - gchar *contents; - gsize n; - gint fd; - - /* try to open the file */ - fd = g_open (filename, O_RDONLY, 0000); - if (G_UNLIKELY (fd < 0)) - return TRUE; - - /* try to stat the file */ - if (fstat (fd, &statb) < 0 || statb.st_size != serialized_size) - { - close (fd); - return TRUE; - } - - /* try to mmap the file */ -#ifdef HAVE_MMAP - contents = mmap (NULL, statb.st_size, PROT_READ, MAP_SHARED, fd, 0); - if (G_LIKELY (contents != MAP_FAILED)) - { - /* check if the contents is the same */ - needs_update = (memcmp (contents, serialized, statb.st_size) != 0); - - /* unmap the file */ - munmap (contents, statb.st_size); - } - else -#endif - { - /* read the file */ - contents = g_malloc (statb.st_size); - for (n = 0; n < statb.st_size; n += m) - { - /* read the next chunk */ - m = read (fd, contents + n, statb.st_size - n); - if (G_UNLIKELY (m <= 0)) - { - close (fd); - return TRUE; - } - } - - /* compare the contents */ - needs_update = (memcmp (contents, serialized, statb.st_size) == 0); - } - - /* close the file */ - close (fd); - - return needs_update; -} - - - -int -main (int argc, char **argv) -{ - GHashTable *thumbnailers; - gchar *filename; - gchar *tmp_name; - guchar *serialized; - gssize m; - guint serialized_size; - gsize n; - gint fd; - - /* be sure to initialize the GType system */ - g_type_init (); - - /* allocate the hash table for the thumbnailers */ - thumbnailers = g_hash_table_new (g_str_hash, g_str_equal); - - /* load the available GNOME thumbnailers */ - thumbnailers_load_gnome (thumbnailers); - - /* load the available gdk-pixbuf thumbnailers */ - thumbnailers_load_pixbuf (thumbnailers); - - /* load the available custom thumbnailers */ - thumbnailers_load_custom (thumbnailers); - - /* serialize the loaded thumbnailers */ - serialized = thumbnailers_serialize (thumbnailers, &serialized_size); - - /* determine the cache file */ - filename = xfce_resource_save_location (XFCE_RESOURCE_CACHE, "Thunar/thumbnailers.cache", TRUE); - if (G_UNLIKELY (filename == NULL)) - return EXIT_FAILURE; - - /* check if we need to update the thumbnailers.cache */ - if (thumbnailers_needs_update (filename, serialized, serialized_size)) - { - tmp_name = g_strconcat (filename, ".XXXXXX", NULL); - fd = g_mkstemp (tmp_name); - if (G_UNLIKELY (fd < 0)) - return EXIT_FAILURE; - - /* write the content */ - for (n = 0; n < serialized_size; n += m) - { - /* write the next chunk */ - m = write (fd, serialized + n, serialized_size - n); - if (G_UNLIKELY (m < 0)) - { -err0: g_unlink (tmp_name); - return EXIT_FAILURE; - } - } - - /* make sure the file isn't writable */ - fchmod (fd, S_IRUSR); - - /* close the temp file */ - close (fd); - - /* try to rename to the cache file */ - if (g_rename (tmp_name, filename) < 0) - goto err0; - - /* we did it, new cache contents -> 33 */ - return 33; - } - - /* not updated -> 0 */ - return EXIT_SUCCESS; -} - - - diff --git a/thunar-vfs/thunar-vfs-user.h b/thunar-vfs/thunar-vfs-user.h deleted file mode 100644 index 42a48f57f..000000000 --- a/thunar-vfs/thunar-vfs-user.h +++ /dev/null @@ -1,87 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_USER_H__ -#define __THUNAR_VFS_USER_H__ - -#include <thunar-vfs/thunar-vfs-info.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsGroupClass ThunarVfsGroupClass; -typedef struct _ThunarVfsGroup ThunarVfsGroup; - -#define THUNAR_VFS_TYPE_GROUP (thunar_vfs_group_get_type ()) -#define THUNAR_VFS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_GROUP, ThunarVfsGroup)) -#define THUNAR_VFS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_GROUP, ThunarVfsGroupClass)) -#define THUNAR_VFS_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_GROUP)) -#define THUNAR_VFS_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_GROUP)) -#define THUNAR_VFS_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_GROUP, ThunarVfsGroupClass)) - -GType thunar_vfs_group_get_type (void) G_GNUC_CONST; - -ThunarVfsGroupId thunar_vfs_group_get_id (ThunarVfsGroup *group); -const gchar *thunar_vfs_group_get_name (ThunarVfsGroup *group); - - -typedef struct _ThunarVfsUserClass ThunarVfsUserClass; -typedef struct _ThunarVfsUser ThunarVfsUser; - -#define THUNAR_VFS_TYPE_USER (thunar_vfs_user_get_type ()) -#define THUNAR_VFS_USER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_USER, ThunarVfsUser)) -#define THUNAR_VFS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_USER, ThunarVfsUserClass)) -#define THUNAR_VFS_IS_USER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_USER)) -#define THUNAR_VFS_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_USER)) -#define THUNAR_VFS_USER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_USER, ThunarVfsUserClass)) - -GType thunar_vfs_user_get_type (void) G_GNUC_CONST; - -GList *thunar_vfs_user_get_groups (ThunarVfsUser *user); -ThunarVfsGroup *thunar_vfs_user_get_primary_group (ThunarVfsUser *user); -ThunarVfsUserId thunar_vfs_user_get_id (ThunarVfsUser *user); -const gchar *thunar_vfs_user_get_name (ThunarVfsUser *user); -const gchar *thunar_vfs_user_get_real_name (ThunarVfsUser *user); -gboolean thunar_vfs_user_is_me (ThunarVfsUser *user); - - -typedef struct _ThunarVfsUserManagerClass ThunarVfsUserManagerClass; -typedef struct _ThunarVfsUserManager ThunarVfsUserManager; - -#define THUNAR_VFS_TYPE_USER_MANAGER (thunar_vfs_user_manager_get_type ()) -#define THUNAR_VFS_USER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_USER_MANAGER, ThunarVfsUserManager)) -#define THUNAR_VFS_USER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_USER_MANAGER, ThunarVfsUserManagerClass)) -#define THUNAR_VFS_IS_USER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_USER_MANAGER)) -#define THUNAR_VFS_IS_USER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_USER_MANAGER)) -#define THUNAR_VFS_USER_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_USER_MANAGER, ThunarVfsUserManagerClass)) - -GType thunar_vfs_user_manager_get_type (void) G_GNUC_CONST; - -ThunarVfsUserManager *thunar_vfs_user_manager_get_default (void) G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsGroup *thunar_vfs_user_manager_get_group_by_id (ThunarVfsUserManager *manager, - ThunarVfsGroupId id) G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsUser *thunar_vfs_user_manager_get_user_by_id (ThunarVfsUserManager *manager, - ThunarVfsUserId id) G_GNUC_WARN_UNUSED_RESULT; - -GList *thunar_vfs_user_manager_get_all_groups (ThunarVfsUserManager *manager) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_USER_H__ */ diff --git a/thunar-vfs/thunar-vfs-util.c b/thunar-vfs/thunar-vfs-util.c deleted file mode 100644 index 83177dd9f..000000000 --- a/thunar-vfs/thunar-vfs-util.c +++ /dev/null @@ -1,341 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - * thunar_vfs_canonicalize_pathname() derived from code by Brian Fox and Chet - * Ramey in GNU Bash, the Bourne Again SHell. Copyright (C) 1987, 1988, 1989, - * 1990, 1991, 1992 Free Software Foundation, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_PWD_H -#include <pwd.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#include <thunar-vfs/thunar-vfs-util.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -static inline gint -find_next_slash (const gchar *path, - gint current_offset) -{ - const gchar *match; - match = strchr (path + current_offset, G_DIR_SEPARATOR); - return (match == NULL) ? -1 : (match - path); -} - - - -static inline gint -find_slash_before_offset (const gchar *path, - gint to) -{ - gint next_offset; - gint result = -1; - - for (next_offset = 0;; ++next_offset) - { - next_offset = find_next_slash (path, next_offset); - if (next_offset < 0 || next_offset >= to) - break; - - result = next_offset; - } - - return result; -} - - - -static inline void -collapse_slash_runs (gchar *path, - gint from_offset) -{ - gint i; - - /* Collapse multiple `/'s in a row. */ - for (i = from_offset; path[i] == G_DIR_SEPARATOR; i++) - ; - - if (from_offset < i) - memmove (path + from_offset, path + i, strlen (path + i) + 1); -} - - - -/** - * thunar_vfs_canonicalize_filename: - * @filename : a local filename. - * - * Canonicalizes @filename and returns a new path. The new path - * differs from @filename in: - * - * <simplelist> - * <member>Multiple `/'s are collapsed to a single `/'.</member> - * <member>Leading `./'s and trailing `/.'s are removed.</member> - * <member>Non-leading `../'s and trailing `..'s are handled by removing portions of the path.</member> - * </simplelist> - * - * The caller is responsible to free the returned string using - * g_free() when no longer needed. - * - * Return value: the canonicalized path for @filename. - **/ -gchar* -thunar_vfs_canonicalize_filename (const gchar *filename) -{ - gchar *path; - gint marker; - gint i; - - g_return_val_if_fail (filename != NULL, NULL); - - /* take a copy of the filename to operate on */ - path = g_strdup (filename); - if (G_UNLIKELY (*path == '\0')) - return path; - - /* Walk along path looking for things to compact. */ - for (i = 0, marker = 0;;) - { - if (G_UNLIKELY (path[i] == '\0')) - break; - - /* Check for `../', `./' or trailing `.' by itself. */ - if (path[i] == '.') - { - /* Handle trailing `.' by itself. */ - if (path[i + 1] == '\0') - { - if (i > 1 && path[i - 1] == G_DIR_SEPARATOR) - { - /* strip the trailing /. */ - path[i - 1] = '\0'; - } - else - { - /* convert path "/." to "/" */ - path[i] = '\0'; - } - break; - } - - /* Handle `./'. */ - if (path[i + 1] == G_DIR_SEPARATOR) - { - memmove (path + i, path + i + 2, strlen (path + i + 2) + 1); - if (i == 0) - { - /* don't leave leading '/' for paths that started - * as relative (.//foo) - */ - collapse_slash_runs (path, i); - marker = 0; - } - continue; - } - - /* Handle `../' or trailing `..' by itself. - * Remove the previous xxx/ part - */ - if (path[i + 1] == '.' && (path[i + 2] == G_DIR_SEPARATOR || path[i + 2] == '\0')) - { - /* ignore ../ at the beginning of a path */ - if (i != 0) - { - marker = find_slash_before_offset (path, i - 1); - - /* Either advance past '/' or point to the first character */ - marker ++; - if (path [i + 2] == '\0' && marker > 1) - { - /* If we are looking at a /.. at the end of the uri and we - * need to eat the last '/' too. - */ - marker--; - } - - /* strip the entire ../ string */ - if (path[i + 2] == G_DIR_SEPARATOR) - ++i; - - memmove (path + marker, path + i + 2, strlen (path + i + 2) + 1); - i = marker; - } - else - { - i = 2; - if (path[i] == G_DIR_SEPARATOR) - i++; - } - - collapse_slash_runs (path, i); - continue; - } - } - - /* advance to the next '/' */ - i = find_next_slash (path, i); - - /* If we didn't find any slashes, then there is nothing left to do. */ - if (i < 0) - break; - - marker = i++; - collapse_slash_runs (path, i); - } - - return path; -} - - - -/** - * thunar_vfs_expand_filename: - * @filename : a local filename. - * @error : return location for errors or %NULL. - * - * Takes a user-typed @filename and expands a tilde at the - * beginning of the @filename. - * - * The caller is responsible to free the returned string using - * g_free() when no longer needed. - * - * Return value: the expanded @filename or %NULL on error. - **/ -gchar* -thunar_vfs_expand_filename (const gchar *filename, - GError **error) -{ - struct passwd *passwd; - const gchar *replacement; - const gchar *remainder; - const gchar *slash; - gchar *username; - - g_return_val_if_fail (filename != NULL, NULL); - - /* check if we have a valid (non-empty!) filename */ - if (G_UNLIKELY (*filename == '\0')) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid path")); - return NULL; - } - - /* check if we start with a '~' */ - if (G_LIKELY (*filename != '~')) - return g_strdup (filename); - - /* examine the remainder of the filename */ - remainder = filename + 1; - - /* if we have only the slash, then we want the home dir */ - if (G_UNLIKELY (*remainder == '\0')) - return g_strdup (xfce_get_homedir ()); - - /* lookup the slash */ - for (slash = remainder; *slash != '\0' && *slash != G_DIR_SEPARATOR; ++slash) - ; - - /* check if a username was given after the '~' */ - if (G_LIKELY (slash == remainder)) - { - /* replace the tilde with the home dir */ - replacement = xfce_get_homedir (); - } - else - { - /* lookup the pwd entry for the username */ - username = g_strndup (remainder, slash - remainder); - passwd = getpwnam (username); - g_free (username); - - /* check if we have a valid entry */ - if (G_UNLIKELY (passwd == NULL)) - { - username = g_strndup (remainder, slash - remainder); - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Unknown user \"%s\""), username); - g_free (username); - return NULL; - } - - /* use the homedir of the specified user */ - replacement = passwd->pw_dir; - } - - /* generate the filename */ - return g_build_filename (replacement, slash, NULL); -} - - - -/** - * thunar_vfs_humanize_size: - * @size : size in bytes. - * @buffer : destination buffer or %NULL to dynamically allocate a buffer. - * @buflen : length of @buffer in bytes. - * - * The caller is responsible to free the returned string using g_free() - * if you pass %NULL for @buffer. Else the returned string will be a - * pointer to @buffer. - * - * Return value: a string containing a human readable description of @size. - **/ -gchar* -thunar_vfs_humanize_size (ThunarVfsFileSize size, - gchar *buffer, - gsize buflen) -{ - /* allocate buffer if necessary */ - if (buffer == NULL) - { - buffer = g_new (gchar, 32); - buflen = 32; - } - - if (G_UNLIKELY (size > 1024ul * 1024ul * 1024ul)) - g_snprintf (buffer, buflen, "%0.1f GB", size / (1024.0 * 1024.0 * 1024.0)); - else if (size > 1024ul * 1024ul) - g_snprintf (buffer, buflen, "%0.1f MB", size / (1024.0 * 1024.0)); - else if (size > 1024ul) - g_snprintf (buffer, buflen, "%0.1f kB", size / 1024.0); - else - g_snprintf (buffer, buflen, "%lu B", (gulong) size); - - return buffer; -} - - - -#define __THUNAR_VFS_UTIL_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-util.h b/thunar-vfs/thunar-vfs-util.h deleted file mode 100644 index d2cd0ced9..000000000 --- a/thunar-vfs/thunar-vfs-util.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_UTIL_H__ -#define __THUNAR_VFS_UTIL_H__ - -#include <thunar-vfs/thunar-vfs-config.h> -#include <thunar-vfs/thunar-vfs-types.h> - -G_BEGIN_DECLS; - -gchar *thunar_vfs_canonicalize_filename (const gchar *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -gchar *thunar_vfs_expand_filename (const gchar *filename, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -gchar *thunar_vfs_humanize_size (ThunarVfsFileSize size, - gchar *buffer, - gsize buflen); - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_UTIL_H__ */ diff --git a/thunar-vfs/thunar-vfs-volume-freebsd.c b/thunar-vfs/thunar-vfs-volume-freebsd.c deleted file mode 100644 index ab949d2a5..000000000 --- a/thunar-vfs/thunar-vfs-volume-freebsd.c +++ /dev/null @@ -1,528 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_CDIO_H -#include <sys/cdio.h> -#endif -#ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -#ifdef HAVE_SYS_MOUNT_H -#include <sys/mount.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_FSTAB_H -#include <fstab.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <thunar-vfs/thunar-vfs-exec.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-volume-freebsd.h> -#include <thunar-vfs/thunar-vfs-volume-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -static void thunar_vfs_volume_freebsd_class_init (ThunarVfsVolumeFreeBSDClass *klass); -static void thunar_vfs_volume_freebsd_finalize (GObject *object); -static ThunarVfsVolumeKind thunar_vfs_volume_freebsd_get_kind (ThunarVfsVolume *volume); -static const gchar *thunar_vfs_volume_freebsd_get_name (ThunarVfsVolume *volume); -static ThunarVfsVolumeStatus thunar_vfs_volume_freebsd_get_status (ThunarVfsVolume *volume); -static ThunarVfsPath *thunar_vfs_volume_freebsd_get_mount_point (ThunarVfsVolume *volume); -static gboolean thunar_vfs_volume_freebsd_is_ejectable (ThunarVfsVolume *volume); -static gboolean thunar_vfs_volume_freebsd_eject (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); -static gboolean thunar_vfs_volume_freebsd_mount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); -static gboolean thunar_vfs_volume_freebsd_unmount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); -static gboolean thunar_vfs_volume_freebsd_update (gpointer user_data); -static ThunarVfsVolumeFreeBSD *thunar_vfs_volume_freebsd_new (const gchar *device_path, - const gchar *mount_path); - - - -struct _ThunarVfsVolumeFreeBSDClass -{ - ThunarVfsVolumeClass __parent__; -}; - -struct _ThunarVfsVolumeFreeBSD -{ - ThunarVfsVolume __parent__; - - gchar *device_path; - const gchar *device_name; - ThunarVfsFileDevice device_id; - - gchar *label; - - struct statfs info; - ThunarVfsPath *mount_point; - - ThunarVfsVolumeKind kind; - ThunarVfsVolumeStatus status; - - gint update_timer_id; -}; - - - -static GObjectClass *thunar_vfs_volume_freebsd_parent_class; - - - -GType -thunar_vfs_volume_freebsd_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_VOLUME, - "ThunarVfsVolumeFreeBSD", - sizeof (ThunarVfsVolumeFreeBSDClass), - thunar_vfs_volume_freebsd_class_init, - sizeof (ThunarVfsVolumeFreeBSD), - NULL, - 0); - } - - return type; -} - - - -static void -thunar_vfs_volume_freebsd_class_init (ThunarVfsVolumeFreeBSDClass *klass) -{ - ThunarVfsVolumeClass *thunarvfs_volume_class; - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_volume_freebsd_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_volume_freebsd_finalize; - - thunarvfs_volume_class = THUNAR_VFS_VOLUME_CLASS (klass); - thunarvfs_volume_class->get_kind = thunar_vfs_volume_freebsd_get_kind; - thunarvfs_volume_class->get_name = thunar_vfs_volume_freebsd_get_name; - thunarvfs_volume_class->get_status = thunar_vfs_volume_freebsd_get_status; - thunarvfs_volume_class->get_mount_point = thunar_vfs_volume_freebsd_get_mount_point; - thunarvfs_volume_class->is_ejectable = thunar_vfs_volume_freebsd_is_ejectable; - thunarvfs_volume_class->eject = thunar_vfs_volume_freebsd_eject; - thunarvfs_volume_class->mount = thunar_vfs_volume_freebsd_mount; - thunarvfs_volume_class->unmount = thunar_vfs_volume_freebsd_unmount; -} - - - -static void -thunar_vfs_volume_freebsd_finalize (GObject *object) -{ - ThunarVfsVolumeFreeBSD *volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (object); - - if (G_LIKELY (volume_freebsd->update_timer_id > 0)) - g_source_remove (volume_freebsd->update_timer_id); - - if (G_LIKELY (volume_freebsd->mount_point != NULL)) - thunar_vfs_path_unref (volume_freebsd->mount_point); - - g_free (volume_freebsd->device_path); - g_free (volume_freebsd->label); - - (*G_OBJECT_CLASS (thunar_vfs_volume_freebsd_parent_class)->finalize) (object); -} - - - -static ThunarVfsVolumeKind -thunar_vfs_volume_freebsd_get_kind (ThunarVfsVolume *volume) -{ - return THUNAR_VFS_VOLUME_FREEBSD (volume)->kind; -} - - - -static const gchar* -thunar_vfs_volume_freebsd_get_name (ThunarVfsVolume *volume) -{ - ThunarVfsVolumeFreeBSD *volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (volume); - return (volume_freebsd->label != NULL) ? volume_freebsd->label : volume_freebsd->device_name; -} - - - -static ThunarVfsVolumeStatus -thunar_vfs_volume_freebsd_get_status (ThunarVfsVolume *volume) -{ - return THUNAR_VFS_VOLUME_FREEBSD (volume)->status; -} - - - -static ThunarVfsPath* -thunar_vfs_volume_freebsd_get_mount_point (ThunarVfsVolume *volume) -{ - return THUNAR_VFS_VOLUME_FREEBSD (volume)->mount_point; -} - - - -static gboolean -thunar_vfs_volume_freebsd_is_ejectable (ThunarVfsVolume *volume) -{ - /* we can only eject removable media, that are present (surprise, surprise) */ - return (thunar_vfs_volume_is_present (volume) && thunar_vfs_volume_is_removable (volume)); -} - - - -static gboolean -thunar_vfs_volume_freebsd_eject (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error) -{ - ThunarVfsVolumeFreeBSD *volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (volume); - gboolean result; - gchar *quoted; - - /* execute the eject command */ - quoted = g_shell_quote (volume_freebsd->device_path); - result = thunar_vfs_exec_sync ("exo-eject -n -d %s", error, quoted); - g_free (quoted); - - /* update volume state if successfull */ - if (G_LIKELY (result)) - thunar_vfs_volume_freebsd_update (volume_freebsd); - - return result; -} - - - -static gboolean -thunar_vfs_volume_freebsd_mount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error) -{ - ThunarVfsVolumeFreeBSD *volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (volume); - gboolean result; - gchar *quoted; - - /* execute the mount command */ - quoted = g_shell_quote (volume_freebsd->device_path); - result = thunar_vfs_exec_sync ("exo-mount -n -d %s", error, quoted); - g_free (quoted); - - /* update volume state if successfull */ - if (G_LIKELY (result)) - thunar_vfs_volume_freebsd_update (volume_freebsd); - - return result; -} - - - -static gboolean -thunar_vfs_volume_freebsd_unmount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error) -{ - ThunarVfsVolumeFreeBSD *volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (volume); - gboolean result; - gchar *quoted; - - /* execute the umount command */ - quoted = g_shell_quote (volume_freebsd->device_path); - result = thunar_vfs_exec_sync ("exo-unmount -n -d %s", error, quoted); - g_free (quoted); - - /* update volume state if successfull */ - if (G_LIKELY (result)) - thunar_vfs_volume_freebsd_update (volume_freebsd); - - return result; -} - - - -static gboolean -thunar_vfs_volume_freebsd_update (gpointer user_data) -{ - ThunarVfsVolumeFreeBSD *volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (user_data); - ThunarVfsVolumeStatus status = 0; - struct ioc_toc_header ith; - struct stat sb; - gchar *label; - gchar buffer[2048]; - int fd; - - if (volume_freebsd->kind == THUNAR_VFS_VOLUME_KIND_CDROM) - { - /* try to read the table of contents from the CD-ROM, - * which will only succeed if a disc is present for - * the drive. - */ - fd = open (volume_freebsd->device_path, O_RDONLY); - if (fd >= 0) - { - if (ioctl (fd, CDIOREADTOCHEADER, &ith) >= 0) - { - status |= THUNAR_VFS_VOLUME_STATUS_PRESENT; - - /* read the label of the disc */ - if (volume_freebsd->label == NULL && (volume_freebsd->status & THUNAR_VFS_VOLUME_STATUS_PRESENT) == 0) - { - /* skip to sector 16 and read it */ - if (lseek (fd, 16 * 2048, SEEK_SET) >= 0 && read (fd, buffer, sizeof (buffer)) >= 0) - { - /* offset 40 contains the volume identifier */ - label = buffer + 40; - label[32] = '\0'; - g_strchomp (label); - if (G_LIKELY (*label != '\0')) - volume_freebsd->label = g_strdup (label); - - /* if we got this far, the CD should be mountable */ - status |= THUNAR_VFS_VOLUME_STATUS_MOUNTABLE; - } - } - } - - close (fd); - } - } - else - { - /* FIXME: not sure how to determine mountability */ - status |= THUNAR_VFS_VOLUME_STATUS_MOUNTABLE; - } - - /* determine the absolute path to the mount point */ - if (thunar_vfs_path_to_string (volume_freebsd->mount_point, buffer, sizeof (buffer), NULL) > 0) - { - /* query the file system information for the mount point */ - if (statfs (buffer, &volume_freebsd->info) >= 0) - { - /* if the device is mounted, it means that a medium is present */ - if (exo_str_is_equal (volume_freebsd->info.f_mntfromname, volume_freebsd->device_path)) - status |= THUNAR_VFS_VOLUME_STATUS_MOUNTED | THUNAR_VFS_VOLUME_STATUS_PRESENT; - } - - /* free the volume label if no disc is present */ - if ((status & THUNAR_VFS_VOLUME_STATUS_PRESENT) == 0) - { - g_free (volume_freebsd->label); - volume_freebsd->label = NULL; - } - - /* determine the device id if mounted */ - if ((status & THUNAR_VFS_VOLUME_STATUS_MOUNTED) != 0) - { - if (stat (buffer, &sb) < 0) - volume_freebsd->device_id = (ThunarVfsFileDevice) -1; - else - volume_freebsd->device_id = sb.st_dev; - } - } - - /* update the status if necessary */ - if (status != volume_freebsd->status) - { - volume_freebsd->status = status; - thunar_vfs_volume_changed (THUNAR_VFS_VOLUME (volume_freebsd)); - } - - return TRUE; -} - - - -static ThunarVfsVolumeFreeBSD* -thunar_vfs_volume_freebsd_new (const gchar *device_path, - const gchar *mount_path) -{ - ThunarVfsVolumeFreeBSD *volume_freebsd; - const gchar *p; - - g_return_val_if_fail (device_path != NULL, NULL); - g_return_val_if_fail (mount_path != NULL, NULL); - - /* allocate the volume object */ - volume_freebsd = g_object_new (THUNAR_VFS_TYPE_VOLUME_FREEBSD, NULL); - volume_freebsd->device_path = g_strdup (device_path); - volume_freebsd->mount_point = thunar_vfs_path_new (mount_path, NULL); - - /* determine the device name */ - for (p = volume_freebsd->device_name = volume_freebsd->device_path; *p != '\0'; ++p) - if (p[0] == '/' && (p[1] != '/' && p[1] != '\0')) - volume_freebsd->device_name = p + 1; - - /* determine the kind of the volume */ - p = volume_freebsd->device_name; - if (p[0] == 'c' && p[1] == 'd' && g_ascii_isdigit (p[2])) - volume_freebsd->kind = THUNAR_VFS_VOLUME_KIND_CDROM; - else if (p[0] == 'f' && p[1] == 'd' && g_ascii_isdigit (p[2])) - volume_freebsd->kind = THUNAR_VFS_VOLUME_KIND_FLOPPY; - else if ((p[0] == 'a' && p[1] == 'd' && g_ascii_isdigit (p[2])) - || (p[0] == 'd' && p[1] == 'a' && g_ascii_isdigit (p[2]))) - volume_freebsd->kind = THUNAR_VFS_VOLUME_KIND_HARDDISK; - else - volume_freebsd->kind = THUNAR_VFS_VOLUME_KIND_UNKNOWN; - - /* determine up-to-date status */ - thunar_vfs_volume_freebsd_update (volume_freebsd); - - /* start the update timer */ - volume_freebsd->update_timer_id = g_timeout_add (1000, thunar_vfs_volume_freebsd_update, volume_freebsd); - - return volume_freebsd; -} - - - - -static void thunar_vfs_volume_manager_freebsd_class_init (ThunarVfsVolumeManagerFreeBSDClass *klass); -static void thunar_vfs_volume_manager_freebsd_init (ThunarVfsVolumeManagerFreeBSD *manager_freebsd); -static ThunarVfsVolume *thunar_vfs_volume_manager_freebsd_get_volume_by_info (ThunarVfsVolumeManager *manager, - const ThunarVfsInfo *info); - - - -struct _ThunarVfsVolumeManagerFreeBSDClass -{ - ThunarVfsVolumeManagerClass __parent__; -}; - -struct _ThunarVfsVolumeManagerFreeBSD -{ - ThunarVfsVolumeManager __parent__; -}; - - - -GType -thunar_vfs_volume_manager_freebsd_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_VOLUME_MANAGER, - "ThunarVfsVolumeManagerFreeBSD", - sizeof (ThunarVfsVolumeManagerFreeBSDClass), - thunar_vfs_volume_manager_freebsd_class_init, - sizeof (ThunarVfsVolumeManagerFreeBSD), - thunar_vfs_volume_manager_freebsd_init, - 0); - } - - return type; -} - - - -static void -thunar_vfs_volume_manager_freebsd_class_init (ThunarVfsVolumeManagerFreeBSDClass *klass) -{ - ThunarVfsVolumeManagerClass *thunarvfs_volume_manager_class; - - thunarvfs_volume_manager_class = THUNAR_VFS_VOLUME_MANAGER_CLASS (klass); - thunarvfs_volume_manager_class->get_volume_by_info = thunar_vfs_volume_manager_freebsd_get_volume_by_info; -} - - - -static void -thunar_vfs_volume_manager_freebsd_init (ThunarVfsVolumeManagerFreeBSD *manager_freebsd) -{ - ThunarVfsVolumeFreeBSD *volume_freebsd; - struct fstab *fs; - - /* load the fstab database */ - setfsent (); - - /* process all fstab entries and generate volume objects */ - for (;;) - { - /* query the next fstab entry */ - fs = getfsent (); - if (G_UNLIKELY (fs == NULL)) - break; - - /* we only care for file systems */ - if (!exo_str_is_equal (fs->fs_type, FSTAB_RW) - && !exo_str_is_equal (fs->fs_type, FSTAB_RQ) - && !exo_str_is_equal (fs->fs_type, FSTAB_RO)) - continue; - - volume_freebsd = thunar_vfs_volume_freebsd_new (fs->fs_spec, fs->fs_file); - if (G_LIKELY (volume_freebsd != NULL)) - { - thunar_vfs_volume_manager_add (THUNAR_VFS_VOLUME_MANAGER (manager_freebsd), THUNAR_VFS_VOLUME (volume_freebsd)); - g_object_unref (G_OBJECT (volume_freebsd)); - } - } - - /* unload the fstab database */ - endfsent (); -} - - - -static ThunarVfsVolume* -thunar_vfs_volume_manager_freebsd_get_volume_by_info (ThunarVfsVolumeManager *manager, - const ThunarVfsInfo *info) -{ - ThunarVfsVolumeFreeBSD *volume_freebsd = NULL; - GList *lp; - - for (lp = manager->volumes; lp != NULL; lp = lp->next) - { - volume_freebsd = THUNAR_VFS_VOLUME_FREEBSD (lp->data); - if ((volume_freebsd->status & THUNAR_VFS_VOLUME_STATUS_MOUNTED) != 0 && volume_freebsd->device_id == info->device) - return THUNAR_VFS_VOLUME (volume_freebsd); - } - - return NULL; -} - - - -#define __THUNAR_VFS_VOLUME_FREEBSD_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-volume-freebsd.h b/thunar-vfs/thunar-vfs-volume-freebsd.h deleted file mode 100644 index fa80e1dc1..000000000 --- a/thunar-vfs/thunar-vfs-volume-freebsd.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_VOLUME_FREEBSD_H__ -#define __THUNAR_VFS_VOLUME_FREEBSD_H__ - -#include <thunar-vfs/thunar-vfs-volume.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsVolumeFreeBSDClass ThunarVfsVolumeFreeBSDClass; -typedef struct _ThunarVfsVolumeFreeBSD ThunarVfsVolumeFreeBSD; - -#define THUNAR_VFS_TYPE_VOLUME_FREEBSD (thunar_vfs_volume_freebsd_get_type ()) -#define THUNAR_VFS_VOLUME_FREEBSD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME_FREEBSD, ThunarVfsVolumeFreeBSD)) -#define THUNAR_VFS_VOLUME_FREEBSD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME_FREEBSD, ThunarVfsVolumeFreeBSDClass)) -#define THUNAR_VFS_IS_VOLUME_FREEBSD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME_FREEBSD)) -#define THUNAR_VFS_IS_VOLUME_FREEBSD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME_FREEBSD)) -#define THUNAR_VFS_VOLUME_FREEBSD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME_FREEBSD, ThunarVfsVolumeFreeBSDClass)) - -GType thunar_vfs_volume_freebsd_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - - -typedef struct _ThunarVfsVolumeManagerFreeBSDClass ThunarVfsVolumeManagerFreeBSDClass; -typedef struct _ThunarVfsVolumeManagerFreeBSD ThunarVfsVolumeManagerFreeBSD; - -#define THUNAR_VFS_TYPE_VOLUME_MANAGER_FREEBSD (thunar_vfs_volume_manager_freebsd_get_type ()) -#define THUNAR_VFS_VOLUME_MANAGER_FREEBSD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER_FREEBSD, ThunarVfsVolumeManagerFreeBSD)) -#define THUNAR_VFS_VOLUME_MANAGER_FREEBSD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER_FREEBSD, ThunarVfsVolumeManagerFreeBSDClass)) -#define THUNAR_VFS_IS_VOLUME_MANAGER_FREEBSD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER_FREEBSD)) -#define THUNAR_VFS_IS_VOLUME_MANAGER_FREEBSD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER_FREEBSD)) -#define THUNAR_VFS_VOLUME_MANAGER_FREEBSD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER_FREEBSD, ThunarVfsVolumeManagerFreeBSDClass)) - -GType thunar_vfs_volume_manager_freebsd_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_VOLUME_FREEBSD_H__ */ diff --git a/thunar-vfs/thunar-vfs-volume-hal.c b/thunar-vfs/thunar-vfs-volume-hal.c deleted file mode 100644 index c17cd5439..000000000 --- a/thunar-vfs/thunar-vfs-volume-hal.c +++ /dev/null @@ -1,1244 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif - -#include <dbus/dbus-glib-lowlevel.h> - -#include <libhal-storage.h> - -#include <exo-hal/exo-hal.h> - -#include <thunar-vfs/thunar-vfs-exec.h> -#include <thunar-vfs/thunar-vfs-marshal.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-volume-hal.h> -#include <thunar-vfs/thunar-vfs-volume-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -static void thunar_vfs_volume_hal_class_init (ThunarVfsVolumeHalClass *klass); -static void thunar_vfs_volume_hal_finalize (GObject *object); -static ThunarVfsVolumeKind thunar_vfs_volume_hal_get_kind (ThunarVfsVolume *volume); -static const gchar *thunar_vfs_volume_hal_get_name (ThunarVfsVolume *volume); -static ThunarVfsVolumeStatus thunar_vfs_volume_hal_get_status (ThunarVfsVolume *volume); -static ThunarVfsPath *thunar_vfs_volume_hal_get_mount_point (ThunarVfsVolume *volume); -static gboolean thunar_vfs_volume_hal_is_ejectable (ThunarVfsVolume *volume); -static const gchar *thunar_vfs_volume_hal_lookup_icon_name (ThunarVfsVolume *volume, - GtkIconTheme *icon_theme); -static gboolean thunar_vfs_volume_hal_eject (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); -static gboolean thunar_vfs_volume_hal_mount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); -static gboolean thunar_vfs_volume_hal_unmount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); -static ThunarVfsPath *thunar_vfs_volume_hal_find_active_mount_point (const ThunarVfsVolumeHal *volume_hal); -static ThunarVfsPath *thunar_vfs_volume_hal_find_fstab_mount_point (const ThunarVfsVolumeHal *volume_hal); -static void thunar_vfs_volume_hal_update (ThunarVfsVolumeHal *volume_hal, - LibHalContext *context, - LibHalVolume *hv, - LibHalDrive *hd); - - - -struct _ThunarVfsVolumeHalClass -{ - ThunarVfsVolumeClass __parent__; -}; - -struct _ThunarVfsVolumeHal -{ - ThunarVfsVolume __parent__; - - gchar *udi; - - gchar *device_file; - gchar *device_label; - - /* list of possible icons */ - GList *icon_list; - - gboolean requires_eject; - ThunarVfsPath *mount_point; - ThunarVfsVolumeKind kind; - ThunarVfsVolumeStatus status; -}; - - - -static GObjectClass *thunar_vfs_volume_hal_parent_class; - - - -GType -thunar_vfs_volume_hal_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_VOLUME, - "ThunarVfsVolumeHal", - sizeof (ThunarVfsVolumeHalClass), - thunar_vfs_volume_hal_class_init, - sizeof (ThunarVfsVolumeHal), - NULL, - 0); - } - - return type; -} - - - -static void -thunar_vfs_volume_hal_class_init (ThunarVfsVolumeHalClass *klass) -{ - ThunarVfsVolumeClass *thunarvfs_volume_class; - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_volume_hal_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_volume_hal_finalize; - - thunarvfs_volume_class = THUNAR_VFS_VOLUME_CLASS (klass); - thunarvfs_volume_class->get_kind = thunar_vfs_volume_hal_get_kind; - thunarvfs_volume_class->get_name = thunar_vfs_volume_hal_get_name; - thunarvfs_volume_class->get_status = thunar_vfs_volume_hal_get_status; - thunarvfs_volume_class->get_mount_point = thunar_vfs_volume_hal_get_mount_point; - thunarvfs_volume_class->is_ejectable = thunar_vfs_volume_hal_is_ejectable; - thunarvfs_volume_class->lookup_icon_name = thunar_vfs_volume_hal_lookup_icon_name; - thunarvfs_volume_class->eject = thunar_vfs_volume_hal_eject; - thunarvfs_volume_class->mount = thunar_vfs_volume_hal_mount; - thunarvfs_volume_class->unmount = thunar_vfs_volume_hal_unmount; -} - - - -static void -thunar_vfs_volume_hal_finalize (GObject *object) -{ - ThunarVfsVolumeHal *volume_hal = THUNAR_VFS_VOLUME_HAL (object); - - g_free (volume_hal->udi); - - g_free (volume_hal->device_file); - g_free (volume_hal->device_label); - - g_list_foreach (volume_hal->icon_list, (GFunc) g_free, NULL); - g_list_free (volume_hal->icon_list); - - /* release the mount point (if any) */ - if (G_LIKELY (volume_hal->mount_point != NULL)) - thunar_vfs_path_unref (volume_hal->mount_point); - - (*G_OBJECT_CLASS (thunar_vfs_volume_hal_parent_class)->finalize) (object); -} - - - -static ThunarVfsVolumeKind -thunar_vfs_volume_hal_get_kind (ThunarVfsVolume *volume) -{ - return THUNAR_VFS_VOLUME_HAL (volume)->kind; -} - - - -static const gchar* -thunar_vfs_volume_hal_get_name (ThunarVfsVolume *volume) -{ - return THUNAR_VFS_VOLUME_HAL (volume)->device_label; -} - - - -static ThunarVfsVolumeStatus -thunar_vfs_volume_hal_get_status (ThunarVfsVolume *volume) -{ - return THUNAR_VFS_VOLUME_HAL (volume)->status; -} - - - -static ThunarVfsPath* -thunar_vfs_volume_hal_get_mount_point (ThunarVfsVolume *volume) -{ - return THUNAR_VFS_VOLUME_HAL (volume)->mount_point; -} - - - -static gboolean -thunar_vfs_volume_hal_is_ejectable (ThunarVfsVolume *volume) -{ - /* check if HAL drive requires eject */ - return THUNAR_VFS_VOLUME_HAL (volume)->requires_eject; -} - - - -static const gchar* -thunar_vfs_volume_hal_lookup_icon_name (ThunarVfsVolume *volume, - GtkIconTheme *icon_theme) -{ - GList *lp; - - /* check if we have atleast one usable icon in our icon_list */ - for (lp = THUNAR_VFS_VOLUME_HAL (volume)->icon_list; lp != NULL; lp = lp->next) - if (gtk_icon_theme_has_icon (icon_theme, lp->data)) - return lp->data; - - /* fallback in thunar_vfs_volume_lookup_icon() */ - return NULL; -} - - - -static gboolean -thunar_vfs_volume_hal_eject (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error) -{ - ThunarVfsVolumeHal *volume_hal = THUNAR_VFS_VOLUME_HAL (volume); - gboolean result = TRUE; - gchar *quoted; - - /* use exo-eject to eject the device */ - quoted = g_shell_quote (volume_hal->udi); - result = thunar_vfs_exec_sync ("exo-eject -n -h %s", error, quoted); - g_free (quoted); - - /* check if we were successfull */ - if (G_LIKELY (result)) - { - /* reset the status */ - volume_hal->status &= ~(THUNAR_VFS_VOLUME_STATUS_MOUNTED | THUNAR_VFS_VOLUME_STATUS_PRESENT); - - /* emit "changed" on the volume */ - thunar_vfs_volume_changed (THUNAR_VFS_VOLUME (volume_hal)); - } - - return result; -} - - - -static gboolean -thunar_vfs_volume_hal_mount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error) -{ - ThunarVfsVolumeHal *volume_hal = THUNAR_VFS_VOLUME_HAL (volume); - ThunarVfsPath *path; - gboolean result; - gchar *quoted; - - /* use exo-mount to mount the device */ - quoted = g_shell_quote (volume_hal->udi); - result = thunar_vfs_exec_sync ("exo-mount -n -h %s", error, quoted); - g_free (quoted); - - /* check if we were successfull */ - if (G_LIKELY (result)) - { - /* try to figure out where the device was mounted */ - path = thunar_vfs_volume_hal_find_active_mount_point (volume_hal); - if (G_LIKELY (path != NULL)) - { - /* we must have been mounted successfully */ - volume_hal->status |= THUNAR_VFS_VOLUME_STATUS_MOUNTED | THUNAR_VFS_VOLUME_STATUS_PRESENT; - - /* replace the existing mount point */ - thunar_vfs_path_unref (volume_hal->mount_point); - volume_hal->mount_point = path; - - /* tell everybody that we have a new state */ - thunar_vfs_volume_changed (THUNAR_VFS_VOLUME (volume_hal)); - } - else - { - /* something went wrong, for sure */ - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Failed to determine the mount point for %s"), volume_hal->device_file); - result = FALSE; - } - } - - return result; -} - - - -static gboolean -thunar_vfs_volume_hal_unmount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error) -{ - ThunarVfsVolumeHal *volume_hal = THUNAR_VFS_VOLUME_HAL (volume); - gboolean result; - gchar *quoted; - - /* unmount using exo-unmount */ - quoted = g_shell_quote (volume_hal->udi); - result = thunar_vfs_exec_sync ("exo-unmount -n -h %s", error, quoted); - g_free (quoted); - - /* check if we were successfull */ - if (G_LIKELY (result)) - { - /* reset the status */ - volume_hal->status &= ~THUNAR_VFS_VOLUME_STATUS_MOUNTED; - - /* emit "changed" on the volume */ - thunar_vfs_volume_changed (THUNAR_VFS_VOLUME (volume_hal)); - } - - return result; -} - - - -static ThunarVfsPath* -thunar_vfs_volume_hal_find_active_mount_point (const ThunarVfsVolumeHal *volume_hal) -{ - ThunarVfsPath *mount_point = NULL; - GSList *mount_points; - - /* check if we have a matching active mount point (using the ExoMountPoint module) */ - mount_points = exo_mount_point_list_matched (EXO_MOUNT_POINT_MATCH_ACTIVE - | EXO_MOUNT_POINT_MATCH_DEVICE, - volume_hal->device_file, NULL, - NULL, NULL); - - /* the function may return several mount points... */ - if (G_LIKELY (mount_points != NULL)) - { - /* ...but we care only for the first of them (to be exact, for the folder of the first one) */ - mount_point = thunar_vfs_path_new (((const ExoMountPoint *) mount_points->data)->folder, NULL); - - /* clean up the mount points */ - g_slist_foreach (mount_points, (GFunc) exo_mount_point_free, NULL); - g_slist_free (mount_points); - } - - return mount_point; -} - - - -static ThunarVfsPath* -thunar_vfs_volume_hal_find_fstab_mount_point (const ThunarVfsVolumeHal *volume_hal) -{ - ThunarVfsPath *mount_point = NULL; - GSList *mount_points; - - /* check if we have a matching configured mount point (using the ExoMountPoint module) */ - mount_points = exo_mount_point_list_matched (EXO_MOUNT_POINT_MATCH_CONFIGURED - | EXO_MOUNT_POINT_MATCH_DEVICE, - volume_hal->device_file, NULL, - NULL, NULL); - - /* the function may return several mount points... */ - if (G_LIKELY (mount_points != NULL)) - { - /* ...but we care only for the first of them (to be exact, for the folder of the first one) */ - mount_point = thunar_vfs_path_new (((const ExoMountPoint *) mount_points->data)->folder, NULL); - - /* clean up the mount points */ - g_slist_foreach (mount_points, (GFunc) exo_mount_point_free, NULL); - g_slist_free (mount_points); - } - - return mount_point; -} - - - -static void -thunar_vfs_volume_hal_update (ThunarVfsVolumeHal *volume_hal, - LibHalContext *context, - LibHalVolume *hv, - LibHalDrive *hd) -{ - gchar *desired_mount_point; - gchar *mount_root; - gchar *basename; - gchar *filename; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_VOLUME_HAL (volume_hal)); - _thunar_vfs_return_if_fail (hd != NULL); - - /* reset the volume status */ - volume_hal->status = 0; - - /* determine the new device file */ - g_free (volume_hal->device_file); - volume_hal->device_file = g_strdup ((hv != NULL) ? libhal_volume_get_device_file (hv) : libhal_drive_get_device_file (hd)); - - /* compute a usable display name for the volume/drive */ - g_free (volume_hal->device_label); - volume_hal->device_label = (hv == NULL) - ? exo_hal_drive_compute_display_name (context, hd) - : exo_hal_volume_compute_display_name (context, hv, hd); - if (G_UNLIKELY (volume_hal->device_label == NULL)) - { - /* use the basename of the device file as label */ - volume_hal->device_label = g_path_get_basename (volume_hal->device_file); - } - - /* compute a usable list of icon names for the volume/drive */ - g_list_foreach (volume_hal->icon_list, (GFunc) g_free, NULL); - g_list_free (volume_hal->icon_list); - volume_hal->icon_list = (hv == NULL) - ? exo_hal_drive_compute_icon_list (context, hd) - : exo_hal_volume_compute_icon_list (context, hv, hd); - - /* release the previous mount point (if any) */ - if (G_LIKELY (volume_hal->mount_point != NULL)) - { - thunar_vfs_path_unref (volume_hal->mount_point); - volume_hal->mount_point = NULL; - } - - /* determine the type of the volume */ - switch (libhal_drive_get_type (hd)) - { - case LIBHAL_DRIVE_TYPE_CDROM: - /* check if we have a pure audio CD without any data track */ - if (libhal_volume_disc_has_audio (hv) && !libhal_volume_disc_has_data (hv)) - { - /* special treatment for pure audio CDs */ - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_AUDIO_CD; - } - else - { - /* check which kind of CD-ROM/DVD we have */ - switch (libhal_volume_get_disc_type (hv)) - { - case LIBHAL_VOLUME_DISC_TYPE_CDROM: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_CDROM; - break; - - case LIBHAL_VOLUME_DISC_TYPE_CDR: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_CDR; - break; - - case LIBHAL_VOLUME_DISC_TYPE_CDRW: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_CDRW; - break; - - case LIBHAL_VOLUME_DISC_TYPE_DVDROM: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_DVDROM; - break; - - case LIBHAL_VOLUME_DISC_TYPE_DVDRAM: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_DVDRAM; - break; - - case LIBHAL_VOLUME_DISC_TYPE_DVDR: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_DVDR; - break; - - case LIBHAL_VOLUME_DISC_TYPE_DVDRW: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_DVDRW; - break; - - case LIBHAL_VOLUME_DISC_TYPE_DVDPLUSR: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_DVDPLUSR; - break; - - case LIBHAL_VOLUME_DISC_TYPE_DVDPLUSRW: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_DVDPLUSRW; - break; - - default: - /* unsupported disc type */ - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_UNKNOWN; - break; - } - } - break; - - case LIBHAL_DRIVE_TYPE_FLOPPY: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_FLOPPY; - break; - - case LIBHAL_DRIVE_TYPE_PORTABLE_AUDIO_PLAYER: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_AUDIO_PLAYER; - break; - - case LIBHAL_DRIVE_TYPE_SMART_MEDIA: - case LIBHAL_DRIVE_TYPE_SD_MMC: - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_MEMORY_CARD; - break; - - default: - /* check if the drive is connected to the USB bus */ - if (libhal_drive_get_bus (hd) == LIBHAL_DRIVE_BUS_USB) - { - /* we consider the drive to be an USB stick */ - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_USBSTICK; - } - else if (libhal_drive_uses_removable_media (hd) - || libhal_drive_is_hotpluggable (hd)) - { - /* fallback to generic removable disk */ - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_REMOVABLE_DISK; - } - else - { - /* fallback to harddisk drive */ - volume_hal->kind = THUNAR_VFS_VOLUME_KIND_HARDDISK; - } - break; - } - - /* either we have a volume, which means we have media, or - * a drive, which means non-pollable then, so it's present - */ - volume_hal->status |= THUNAR_VFS_VOLUME_STATUS_PRESENT; - - /* figure out if the volume is mountable */ - if(hv != NULL && libhal_volume_get_fsusage (hv) == LIBHAL_VOLUME_USAGE_MOUNTABLE_FILESYSTEM) - volume_hal->status |= THUNAR_VFS_VOLUME_STATUS_MOUNTABLE; - - /* check if the drive requires eject */ - volume_hal->requires_eject = libhal_drive_requires_eject (hd); - - /* check if the volume is currently mounted */ - if (hv != NULL && libhal_volume_is_mounted (hv)) - { - /* try to determine the new mount point */ - volume_hal->mount_point = thunar_vfs_path_new (libhal_volume_get_mount_point (hv), NULL); - - /* we only mark the volume as mounted if we have a valid mount point */ - if (G_LIKELY (volume_hal->mount_point != NULL)) - volume_hal->status |= THUNAR_VFS_VOLUME_STATUS_MOUNTED | THUNAR_VFS_VOLUME_STATUS_PRESENT; - } - else - { - /* we don't trust HAL, so let's see what the kernel says about the volume */ - volume_hal->mount_point = thunar_vfs_volume_hal_find_active_mount_point (volume_hal); - - /* we must have been mounted successfully if we have a mount point */ - if (G_LIKELY (volume_hal->mount_point != NULL)) - volume_hal->status |= THUNAR_VFS_VOLUME_STATUS_MOUNTED | THUNAR_VFS_VOLUME_STATUS_PRESENT; - } - - /* check if we have to figure out the mount point ourself */ - if (G_UNLIKELY (volume_hal->mount_point == NULL)) - { - /* ask HAL for the default mount root (falling back to /media otherwise) */ - mount_root = libhal_device_get_property_string (context, "/org/freedesktop/Hal/devices/computer", "storage.policy.default.mount_root", NULL); - if (G_UNLIKELY (mount_root == NULL || !g_path_is_absolute (mount_root))) - { - /* fallback to /media (seems to be sane) */ - g_free (mount_root); - mount_root = g_strdup ("/media"); - } - - /* lets see, maybe /etc/fstab knows where to mount */ - volume_hal->mount_point = thunar_vfs_volume_hal_find_fstab_mount_point (volume_hal); - - /* if we still don't have a mount point, ask HAL */ - if (G_UNLIKELY (volume_hal->mount_point == NULL)) - { - /* determine the desired mount point and prepend the mount root */ - desired_mount_point = libhal_device_get_property_string (context, volume_hal->udi, "volume.policy.desired_mount_point", NULL); - if (G_LIKELY (desired_mount_point != NULL && *desired_mount_point != '\0')) - { - filename = g_build_filename (mount_root, desired_mount_point, NULL); - volume_hal->mount_point = thunar_vfs_path_new (filename, NULL); - g_free (filename); - } - libhal_free_string (desired_mount_point); - } - - /* ok, last fallback, just use <mount-root>/<device> */ - if (G_UNLIKELY (volume_hal->mount_point == NULL)) - { - /* <mount-root>/<device> looks like a good idea */ - basename = g_path_get_basename (volume_hal->device_file); - filename = g_build_filename (mount_root, basename, NULL); - volume_hal->mount_point = thunar_vfs_path_new (filename, NULL); - g_free (filename); - g_free (basename); - } - - /* release the mount root */ - g_free (mount_root); - } - - /* if we get here, we must have a valid mount point */ - g_assert (volume_hal->mount_point != NULL); - - /* emit the "changed" signal */ - thunar_vfs_volume_changed (THUNAR_VFS_VOLUME (volume_hal)); -} - - - - -static void thunar_vfs_volume_manager_hal_class_init (ThunarVfsVolumeManagerHalClass *klass); -static void thunar_vfs_volume_manager_hal_init (ThunarVfsVolumeManagerHal *manager_hal); -static void thunar_vfs_volume_manager_hal_finalize (GObject *object); -static ThunarVfsVolumeHal *thunar_vfs_volume_manager_hal_get_volume_by_udi (ThunarVfsVolumeManagerHal *manager_hal, - const gchar *udi); -static void thunar_vfs_volume_manager_hal_update_volume_by_udi (ThunarVfsVolumeManagerHal *manager_hal, - const gchar *udi); -static void thunar_vfs_volume_manager_hal_device_added (LibHalContext *context, - const gchar *udi); -static void thunar_vfs_volume_manager_hal_device_removed (LibHalContext *context, - const gchar *udi); -static void thunar_vfs_volume_manager_hal_device_new_capability (LibHalContext *context, - const gchar *udi, - const gchar *capability); -static void thunar_vfs_volume_manager_hal_device_lost_capability (LibHalContext *context, - const gchar *udi, - const gchar *capability); -static void thunar_vfs_volume_manager_hal_device_property_modified (LibHalContext *context, - const gchar *udi, - const gchar *key, - dbus_bool_t is_removed, - dbus_bool_t is_added); -static void thunar_vfs_volume_manager_hal_device_condition (LibHalContext *context, - const gchar *udi, - const gchar *name, - const gchar *details); - - - -struct _ThunarVfsVolumeManagerHalClass -{ - ThunarVfsVolumeManagerClass __parent__; -}; - -struct _ThunarVfsVolumeManagerHal -{ - ThunarVfsVolumeManager __parent__; - DBusConnection *dbus_connection; - LibHalContext *context; - GList *volumes; -}; - - - -static GObjectClass *thunar_vfs_volume_manager_hal_parent_class; - - - -GType -thunar_vfs_volume_manager_hal_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (THUNAR_VFS_TYPE_VOLUME_MANAGER, - "ThunarVfsVolumeManagerHal", - sizeof (ThunarVfsVolumeManagerHalClass), - thunar_vfs_volume_manager_hal_class_init, - sizeof (ThunarVfsVolumeManagerHal), - thunar_vfs_volume_manager_hal_init, - 0); - } - - return type; -} - - - -static void -thunar_vfs_volume_manager_hal_class_init (ThunarVfsVolumeManagerHalClass *klass) -{ - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_volume_manager_hal_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_volume_manager_hal_finalize; - - /** - * ThunarVfsVolumeManagerHal::device-added: - * @manager_hal : a #ThunarVfsVolumeManagerHal instance. - * @udi : the HAL device UDI of the newly added device. - * - * This is a special signal of the HAL volume manager backend, - * which is emitted whenever a new device is added. This signal - * is used by Thunar to support thunar-volman. Since it's special - * to the HAL backend, no other application must use this signal, - * especially no application must assume that the signal is - * available on any given #ThunarVfsVolumeManager. - **/ - g_signal_new (I_("device-added"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - /** - * ThunarVfsVolumeManagerHal::device-removed: - * @manager_hal : a #ThunarVfsVolumeManagerHal instance. - * @udi : the HAL device UDI of the removed device. - * - * This is a special signal of the HAL volume manager backend, - * which is emitted whenever one of the current devices disappear. - * This signal is used by Thunar to support thunar-volman. Since - * it's special to the HAL backend, no other application must use - * this signal, especially no application must assume that the - * signal is available on any given #ThunarVfsVolumeManager. - **/ - g_signal_new (I_("device-removed"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - /** - * ThunarVfsVolumeManagerHal::device-eject: - * @manager_hal : a #ThunarVfsVolumeManagerlHal instance. - * @udi : the UDI of the device. - * - * Emitted by @manager_hal to let Thunar know that the "Eject" - * button was pressed on the device with the @udi. - * - * This signal is used by Thunar to support volume management. - * Since it's special to the HAL backend, no other application - * must use this signal, especially no application must assume - * that the signal is available on any given #ThunarVfsVolumeManager. - **/ - g_signal_new (I_("device-eject"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - - /* initialize exo-hal support */ - if (!exo_hal_init ()) - { - /* atleast warn the user here, so he/she can rebuild libexo with HAL support or ask the admin */ - g_warning ("exo was built without HAL support. Volume management may not work as expected."); - } -} - - - -static void -thunar_vfs_volume_manager_hal_init (ThunarVfsVolumeManagerHal *manager_hal) -{ - LibHalDrive *hd; - DBusError error; - gchar **drive_udis; - gchar **udis; - gint n_drive_udis; - gint n_udis; - gint n, m; - - /* initialize the D-BUS error */ - dbus_error_init (&error); - - /* allocate a HAL context */ - manager_hal->context = libhal_ctx_new (); - if (G_UNLIKELY (manager_hal->context == NULL)) - return; - - /* try to connect to the system bus */ - manager_hal->dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); - if (G_UNLIKELY (manager_hal->dbus_connection == NULL)) - goto failed; - - /* setup the D-BUS connection for the HAL context */ - libhal_ctx_set_dbus_connection (manager_hal->context, manager_hal->dbus_connection); - - /* connect our manager object to the HAL context */ - libhal_ctx_set_user_data (manager_hal->context, manager_hal); - - /* setup callbacks */ - libhal_ctx_set_device_added (manager_hal->context, thunar_vfs_volume_manager_hal_device_added); - libhal_ctx_set_device_removed (manager_hal->context, thunar_vfs_volume_manager_hal_device_removed); - libhal_ctx_set_device_new_capability (manager_hal->context, thunar_vfs_volume_manager_hal_device_new_capability); - libhal_ctx_set_device_lost_capability (manager_hal->context, thunar_vfs_volume_manager_hal_device_lost_capability); - libhal_ctx_set_device_property_modified (manager_hal->context, thunar_vfs_volume_manager_hal_device_property_modified); - libhal_ctx_set_device_condition (manager_hal->context, thunar_vfs_volume_manager_hal_device_condition); - - /* try to initialize the HAL context */ - if (!libhal_ctx_init (manager_hal->context, &error)) - goto failed; - - /* setup the D-BUS connection with the GLib main loop */ - dbus_connection_setup_with_g_main (manager_hal->dbus_connection, NULL); - - /* lookup all drives currently known to HAL */ - drive_udis = libhal_find_device_by_capability (manager_hal->context, "storage", &n_drive_udis, &error); - if (G_LIKELY (drive_udis != NULL)) - { - /* process all drives UDIs */ - for (m = 0; m < n_drive_udis; ++m) - { - /* determine the LibHalDrive for the drive UDI */ - hd = libhal_drive_from_udi (manager_hal->context, drive_udis[m]); - if (G_UNLIKELY (hd == NULL)) - continue; - - /* check if we have a floppy disk here */ - if (libhal_drive_get_type (hd) == LIBHAL_DRIVE_TYPE_FLOPPY) - { - /* add the drive based on the UDI */ - thunar_vfs_volume_manager_hal_device_added (manager_hal->context, drive_udis[m]); - } - else - { - /* determine all volumes for the given drive */ - udis = libhal_drive_find_all_volumes (manager_hal->context, hd, &n_udis); - if (G_LIKELY (udis != NULL)) - { - /* add volumes for all given UDIs */ - for (n = 0; n < n_udis; ++n) - { - /* add the volume based on the UDI */ - thunar_vfs_volume_manager_hal_device_added (manager_hal->context, udis[n]); - - /* release the UDI (HAL bug #5279) */ - free (udis[n]); - } - - /* release the UDIs array (HAL bug #5279) */ - free (udis); - } - } - - /* release the hal drive */ - libhal_drive_free (hd); - } - - /* release the drive UDIs */ - libhal_free_string_array (drive_udis); - } - - /* watch all devices for changes */ - if (!libhal_device_property_watch_all (manager_hal->context, &error)) - goto failed; - - return; - -failed: - /* release the HAL context */ - if (G_LIKELY (manager_hal->context != NULL)) - { - libhal_ctx_free (manager_hal->context); - manager_hal->context = NULL; - } - - /* print a warning message */ - if (dbus_error_is_set (&error)) - { - g_warning (_("Failed to connect to the HAL daemon: %s"), error.message); - dbus_error_free (&error); - } -} - - - -static void -thunar_vfs_volume_manager_hal_finalize (GObject *object) -{ - ThunarVfsVolumeManagerHal *manager_hal = THUNAR_VFS_VOLUME_MANAGER_HAL (object); - GList *lp; - - /* release all active volumes */ - for (lp = manager_hal->volumes; lp != NULL; lp = lp->next) - g_object_unref (G_OBJECT (lp->data)); - g_list_free (manager_hal->volumes); - - /* shutdown the HAL context */ - if (G_LIKELY (manager_hal->context != NULL)) - { - libhal_ctx_shutdown (manager_hal->context, NULL); - libhal_ctx_free (manager_hal->context); - } - - /* shutdown the D-BUS connection */ - if (G_LIKELY (manager_hal->dbus_connection != NULL)) - dbus_connection_unref (manager_hal->dbus_connection); - - (*G_OBJECT_CLASS (thunar_vfs_volume_manager_hal_parent_class)->finalize) (object); -} - - - -static ThunarVfsVolumeHal* -thunar_vfs_volume_manager_hal_get_volume_by_udi (ThunarVfsVolumeManagerHal *manager_hal, - const gchar *udi) -{ - GList *lp; - - for (lp = THUNAR_VFS_VOLUME_MANAGER (manager_hal)->volumes; lp != NULL; lp = lp->next) - if (exo_str_is_equal (THUNAR_VFS_VOLUME_HAL (lp->data)->udi, udi)) - return THUNAR_VFS_VOLUME_HAL (lp->data); - - return NULL; -} - - - -static void -thunar_vfs_volume_manager_hal_update_volume_by_udi (ThunarVfsVolumeManagerHal *manager_hal, - const gchar *udi) -{ - ThunarVfsVolumeHal *volume_hal; - LibHalVolume *hv = NULL; - LibHalDrive *hd = NULL; - const gchar *drive_udi; - - /* check if we have a volume for the UDI */ - volume_hal = thunar_vfs_volume_manager_hal_get_volume_by_udi (manager_hal, udi); - if (G_UNLIKELY (volume_hal == NULL)) - return; - - /* check if we have a volume here */ - hv = libhal_volume_from_udi (manager_hal->context, udi); - if (G_UNLIKELY (hv == NULL)) - { - /* check if we have a drive here */ - hd = libhal_drive_from_udi (manager_hal->context, udi); - if (G_UNLIKELY (hd == NULL)) - { - /* the device is no longer a drive or volume, so drop it */ - thunar_vfs_volume_manager_hal_device_removed (manager_hal->context, udi); - return; - } - - /* update the drive with the new HAL drive/volume */ - thunar_vfs_volume_hal_update (volume_hal, manager_hal->context, NULL, hd); - - /* release the drive */ - libhal_drive_free (hd); - } - else - { - /* determine the UDI of the drive to which this volume belongs */ - drive_udi = libhal_volume_get_storage_device_udi (hv); - if (G_LIKELY (drive_udi != NULL)) - { - /* determine the drive for the volume */ - hd = libhal_drive_from_udi (manager_hal->context, drive_udi); - } - - /* check if we have the drive for the volume */ - if (G_LIKELY (hd != NULL)) - { - /* update the volume with the new HAL drive/volume */ - thunar_vfs_volume_hal_update (volume_hal, manager_hal->context, hv, hd); - - /* release the drive */ - libhal_drive_free (hd); - } - else - { - /* unable to determine the drive, volume gone? */ - thunar_vfs_volume_manager_hal_device_removed (manager_hal->context, udi); - } - - /* release the volume */ - libhal_volume_free (hv); - } -} - - - -static void -thunar_vfs_volume_manager_hal_device_added (LibHalContext *context, - const gchar *udi) -{ - ThunarVfsVolumeManagerHal *manager_hal = libhal_ctx_get_user_data (context); - ThunarVfsVolumeHal *volume_hal; - LibHalVolume *hv; - LibHalDrive *hd; - const gchar *drive_udi; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER_HAL (manager_hal)); - _thunar_vfs_return_if_fail (manager_hal->context == context); - - /* check if we have a volume here */ - hv = libhal_volume_from_udi (context, udi); - - /* HAL might want us to ignore this volume for some reason */ - if (G_UNLIKELY (hv != NULL && libhal_volume_should_ignore (hv))) - { - libhal_volume_free (hv); - return; - } - - /* emit the "device-added" signal (to support thunar-volman) */ - g_signal_emit_by_name (G_OBJECT (manager_hal), "device-added", udi); - - if (G_LIKELY (hv != NULL)) - { - /* check if we have a mountable file system here */ - if (libhal_volume_get_fsusage (hv) == LIBHAL_VOLUME_USAGE_MOUNTABLE_FILESYSTEM) - { - /* determine the UDI of the drive to which this volume belongs */ - drive_udi = libhal_volume_get_storage_device_udi (hv); - if (G_LIKELY (drive_udi != NULL)) - { - /* determine the drive for the volume */ - hd = libhal_drive_from_udi (context, drive_udi); - if (G_LIKELY (hd != NULL)) - { - /* check if we already have a volume object for the UDI */ - volume_hal = thunar_vfs_volume_manager_hal_get_volume_by_udi (manager_hal, udi); - if (G_LIKELY (volume_hal == NULL)) - { - /* otherwise, we allocate a new volume object */ - volume_hal = g_object_new (THUNAR_VFS_TYPE_VOLUME_HAL, NULL); - volume_hal->udi = g_strdup (udi); - } - - /* update the volume object with the new data from the HAL volume/drive */ - thunar_vfs_volume_hal_update (volume_hal, context, hv, hd); - - /* add the volume object to our list if we allocated a new one */ - if (g_list_find (THUNAR_VFS_VOLUME_MANAGER (manager_hal)->volumes, volume_hal) == NULL) - { - /* add the volume to the volume manager */ - thunar_vfs_volume_manager_add (THUNAR_VFS_VOLUME_MANAGER (manager_hal), THUNAR_VFS_VOLUME (volume_hal)); - - /* release the reference on the volume */ - g_object_unref (G_OBJECT (volume_hal)); - } - - /* release the HAL drive */ - libhal_drive_free (hd); - } - } - } - - /* release the HAL volume */ - libhal_volume_free (hv); - } - else - { - /* but maybe we have a floppy disk drive here */ - hd = libhal_drive_from_udi (context, udi); - if (G_UNLIKELY (hd == NULL)) - return; - - /* check if we have a floppy disk drive */ - if (G_LIKELY (libhal_drive_get_type (hd) == LIBHAL_DRIVE_TYPE_FLOPPY)) - { - /* check if we already have a volume object for the UDI */ - volume_hal = thunar_vfs_volume_manager_hal_get_volume_by_udi (manager_hal, udi); - if (G_LIKELY (volume_hal == NULL)) - { - /* otherwise, we allocate a new volume object */ - volume_hal = g_object_new (THUNAR_VFS_TYPE_VOLUME_HAL, NULL); - volume_hal->udi = g_strdup (udi); - } - - /* update the volume object with the new data from the HAL volume/drive */ - thunar_vfs_volume_hal_update (volume_hal, context, NULL, hd); - - /* add the volume object to our list if we allocated a new one */ - if (g_list_find (THUNAR_VFS_VOLUME_MANAGER (manager_hal)->volumes, volume_hal) == NULL) - { - /* add the volume to the volume manager */ - thunar_vfs_volume_manager_add (THUNAR_VFS_VOLUME_MANAGER (manager_hal), THUNAR_VFS_VOLUME (volume_hal)); - - /* release the reference on the volume */ - g_object_unref (G_OBJECT (volume_hal)); - } - } - - /* release the HAL drive */ - libhal_drive_free (hd); - } -} - - - -static void -thunar_vfs_volume_manager_hal_device_removed (LibHalContext *context, - const gchar *udi) -{ - ThunarVfsVolumeManagerHal *manager_hal = libhal_ctx_get_user_data (context); - ThunarVfsVolumeHal *volume_hal; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER_HAL (manager_hal)); - _thunar_vfs_return_if_fail (manager_hal->context == context); - - /* emit the "device-removed" signal (to support thunar-volman) */ - g_signal_emit_by_name (G_OBJECT (manager_hal), "device-removed", udi); - - /* check if we already have a volume object for the UDI */ - volume_hal = thunar_vfs_volume_manager_hal_get_volume_by_udi (manager_hal, udi); - if (G_LIKELY (volume_hal != NULL)) - { - /* remove the volume from the volume manager */ - thunar_vfs_volume_manager_remove (THUNAR_VFS_VOLUME_MANAGER (manager_hal), THUNAR_VFS_VOLUME (volume_hal)); - } -} - - - -static void -thunar_vfs_volume_manager_hal_device_new_capability (LibHalContext *context, - const gchar *udi, - const gchar *capability) -{ - ThunarVfsVolumeManagerHal *manager_hal = libhal_ctx_get_user_data (context); - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER_HAL (manager_hal)); - _thunar_vfs_return_if_fail (manager_hal->context == context); - - /* update the volume for the device (if any) */ - thunar_vfs_volume_manager_hal_update_volume_by_udi (manager_hal, udi); -} - - - -static void -thunar_vfs_volume_manager_hal_device_lost_capability (LibHalContext *context, - const gchar *udi, - const gchar *capability) -{ - ThunarVfsVolumeManagerHal *manager_hal = libhal_ctx_get_user_data (context); - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER_HAL (manager_hal)); - _thunar_vfs_return_if_fail (manager_hal->context == context); - - /* update the volume for the device (if any) */ - thunar_vfs_volume_manager_hal_update_volume_by_udi (manager_hal, udi); -} - - - -static void -thunar_vfs_volume_manager_hal_device_property_modified (LibHalContext *context, - const gchar *udi, - const gchar *key, - dbus_bool_t is_removed, - dbus_bool_t is_added) -{ - ThunarVfsVolumeManagerHal *manager_hal = libhal_ctx_get_user_data (context); - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER_HAL (manager_hal)); - _thunar_vfs_return_if_fail (manager_hal->context == context); - - /* update the volume for the device (if any) */ - thunar_vfs_volume_manager_hal_update_volume_by_udi (manager_hal, udi); -} - - - -static void -thunar_vfs_volume_manager_hal_device_condition (LibHalContext *context, - const gchar *udi, - const gchar *name, - const gchar *details) -{ - ThunarVfsVolumeManagerHal *manager_hal = libhal_ctx_get_user_data (context); - ThunarVfsVolumeHal *volume_hal; - DBusError derror; - GList *volumes = NULL; - GList *lp; - gchar **volume_udis; - gint n_volume_udis; - gint n; - - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER_HAL (manager_hal)); - _thunar_vfs_return_if_fail (manager_hal->context == context); - - /* check if the device should be ejected */ - if (G_LIKELY (strcmp (name, "EjectPressed") == 0)) - { - /* check if we have a volume for the device */ - volume_hal = thunar_vfs_volume_manager_hal_get_volume_by_udi (manager_hal, udi); - if (G_LIKELY (volume_hal == NULL)) - { - /* initialize D-Bus error */ - dbus_error_init (&derror); - - /* the UDI most probably identifies the drive of the volume */ - volume_udis = libhal_manager_find_device_string_match (context, "info.parent", udi, &n_volume_udis, &derror); - if (G_LIKELY (volume_udis != NULL)) - { - /* determine the volumes for the UDIs */ - for (n = 0; n < n_volume_udis; ++n) - { - /* check if we have a mounted volume for this UDI */ - volume_hal = thunar_vfs_volume_manager_hal_get_volume_by_udi (manager_hal, volume_udis[n]); - if (volume_hal != NULL && thunar_vfs_volume_is_mounted (THUNAR_VFS_VOLUME (volume_hal))) - volumes = g_list_prepend (volumes, g_object_ref (G_OBJECT (volume_hal))); - } - libhal_free_string_array (volume_udis); - } - - /* free D-Bus error */ - dbus_error_free (&derror); - } - else if (thunar_vfs_volume_is_mounted (THUNAR_VFS_VOLUME (volume_hal))) - { - volumes = g_list_prepend (volumes, g_object_ref (G_OBJECT (volume_hal))); - } - - /* check there are any mounted volumes on the device */ - if (G_LIKELY (volumes != NULL)) - { - /* tell everybody, that we're about to unmount those volumes */ - for (lp = volumes; lp != NULL; lp = lp->next) - { - thunar_vfs_volume_pre_unmount (lp->data); - g_object_unref (G_OBJECT (lp->data)); - } - g_list_free (volumes); - - /* emit the "device-eject" signal and let Thunar eject the device */ - g_signal_emit_by_name (G_OBJECT (manager_hal), "device-eject", udi); - } - } -} - - - -#define __THUNAR_VFS_VOLUME_HAL_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-volume-hal.h b/thunar-vfs/thunar-vfs-volume-hal.h deleted file mode 100644 index 658e7e54b..000000000 --- a/thunar-vfs/thunar-vfs-volume-hal.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_VOLUME_HAL_H__ -#define __THUNAR_VFS_VOLUME_HAL_H__ - -#include <thunar-vfs/thunar-vfs-volume.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsVolumeHalClass ThunarVfsVolumeHalClass; -typedef struct _ThunarVfsVolumeHal ThunarVfsVolumeHal; - -#define THUNAR_VFS_TYPE_VOLUME_HAL (thunar_vfs_volume_hal_get_type ()) -#define THUNAR_VFS_VOLUME_HAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME_HAL, ThunarVfsVolumeHal)) -#define THUNAR_VFS_VOLUME_HAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME_HAL, ThunarVfsVolumeHalClass)) -#define THUNAR_VFS_IS_VOLUME_HAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME_HAL)) -#define THUNAR_VFS_IS_VOLUME_HAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME_HAL)) -#define THUNAR_VFS_VOLUME_HAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME_HAL, ThunarVfsVolumeHalClass)) - -GType thunar_vfs_volume_hal_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - - -typedef struct _ThunarVfsVolumeManagerHalClass ThunarVfsVolumeManagerHalClass; -typedef struct _ThunarVfsVolumeManagerHal ThunarVfsVolumeManagerHal; - -#define THUNAR_VFS_TYPE_VOLUME_MANAGER_HAL (thunar_vfs_volume_manager_hal_get_type ()) -#define THUNAR_VFS_VOLUME_MANAGER_HAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER_HAL, ThunarVfsVolumeManagerHal)) -#define THUNAR_VFS_VOLUME_MANAGER_HAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER_HAL, ThunarVfsVolumeManagerHalClass)) -#define THUNAR_VFS_IS_VOLUME_MANAGER_HAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER_HAL)) -#define THUNAR_VFS_IS_VOLUME_MANAGER_HAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER_HAL)) -#define THUNAR_VFS_VOLUME_MANAGER_HAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER_HAL, ThunarVfsVolumeManagerHalClass)) - -GType thunar_vfs_volume_manager_hal_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_VOLUME_HAL_H__ */ diff --git a/thunar-vfs/thunar-vfs-volume-manager.c b/thunar-vfs/thunar-vfs-volume-manager.c deleted file mode 100644 index 97364fbc0..000000000 --- a/thunar-vfs/thunar-vfs-volume-manager.c +++ /dev/null @@ -1,492 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <thunar-vfs/thunar-vfs-enum-types.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-volume-freebsd.h> -#include <thunar-vfs/thunar-vfs-volume-hal.h> -#include <thunar-vfs/thunar-vfs-volume-none.h> -#include <thunar-vfs/thunar-vfs-volume-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/* determine the default thunar vfs volume manager type */ -#if defined(THUNAR_VFS_VOLUME_IMPL_FREEBSD) -#define THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL THUNAR_VFS_TYPE_VOLUME_MANAGER_FREEBSD -#elif defined(THUNAR_VFS_VOLUME_IMPL_HAL) -#define THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL THUNAR_VFS_TYPE_VOLUME_MANAGER_HAL -#elif defined(THUNAR_VFS_VOLUME_IMPL_NONE) -#define THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL THUNAR_VFS_TYPE_VOLUME_MANAGER_NONE -#else -#error "Add your volume manager implemenation here!" -#endif - - - -/* Signal identifiers */ -enum -{ - VOLUMES_ADDED, - VOLUMES_REMOVED, - VOLUME_MOUNTED, - VOLUME_PRE_UNMOUNT, - VOLUME_UNMOUNTED, - LAST_SIGNAL, -}; - - - -static void thunar_vfs_volume_manager_class_init (ThunarVfsVolumeManagerClass *klass); -static void thunar_vfs_volume_manager_finalize (GObject *object); -static ThunarVfsVolume *thunar_vfs_volume_manager_real_get_volume_by_info (ThunarVfsVolumeManager *manager, - const ThunarVfsInfo *info); -static void thunar_vfs_volume_manager_volume_mounted (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume); -static void thunar_vfs_volume_manager_volume_pre_unmount (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume); -static void thunar_vfs_volume_manager_volume_unmounted (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume); - - - -static GObjectClass *thunar_vfs_volume_manager_parent_class; -static guint manager_signals[LAST_SIGNAL]; - - - -GType -thunar_vfs_volume_manager_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsVolumeManager", - sizeof (ThunarVfsVolumeManagerClass), - thunar_vfs_volume_manager_class_init, - sizeof (ThunarVfsVolumeManager), - NULL, - G_TYPE_FLAG_ABSTRACT); - } - - return type; -} - - - -static void -thunar_vfs_volume_manager_class_init (ThunarVfsVolumeManagerClass *klass) -{ - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_vfs_volume_manager_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_volume_manager_finalize; - - /* we provide a fallback implementation */ - klass->get_volume_by_info = thunar_vfs_volume_manager_real_get_volume_by_info; - - /** - * ThunarVfsVolumeManager::volumes-added: - * @manager : a #ThunarVfsVolumeManager instance. - * @volumes : a list of #ThunarVfsVolume<!---->s. - * - * Invoked by the @manager whenever new volumes have been - * attached to the system or the administrator changes the - * /etc/fstab file, or some other condition, depending - * on the manager implementation. - * - * Note that the implementation should not invoke this - * method when a volume is mounted, as that's a completely - * different condition! - **/ - manager_signals[VOLUMES_ADDED] = - g_signal_new (I_("volumes-added"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volumes_added), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - /** - * ThunarVfsVolumeManager::volumes-removed: - * @manager : a #ThunarVfsVolumeManager instance. - * @volumes : a list of #ThunarVfsVolume<!---->s. - * - * Invoked whenever the @manager notices that @volumes have - * been detached from the system. - **/ - manager_signals[VOLUMES_REMOVED] = - g_signal_new (I_("volumes-removed"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volumes_removed), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - /** - * ThunarVfsVolumeManager::volume-mounted: - * @manager : a #ThunarVfsVolumeManager instance. - * @volume : a #ThunarVfsVolume instance. - * - * Emitted by @manager right after the @volume was - * successfully mounted. - **/ - manager_signals[VOLUME_MOUNTED] = - g_signal_new (I_("volume-mounted"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volume_mounted), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, THUNAR_VFS_TYPE_VOLUME); - - /** - * ThunarVfsVolumeManager::volume-pre-unmount: - * @manager : a #ThunarVfsVolumeManager instance. - * @volume : a #ThunarVfsVolume instance. - * - * Emitted by @manager right before an attempt is - * made to unmount @volume. Applications can connect - * to this signal to perform cleanups, like changing - * to a different folder if a folder on the @volume - * is currently displayed. - **/ - manager_signals[VOLUME_PRE_UNMOUNT] = - g_signal_new (I_("volume-pre-unmount"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volume_pre_unmount), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, THUNAR_VFS_TYPE_VOLUME); - - /** - * ThunarVfsVolumeManager::volume-unmounted: - * @manager : a #ThunarVfsVolumeManager instance. - * @volume : a #ThunarVfsVolume instance. - * - * Emitted by @manager right after the @volume was - * successfully unmounted. - **/ - manager_signals[VOLUME_UNMOUNTED] = - g_signal_new (I_("volume-unmounted"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsVolumeManagerClass, volume_unmounted), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, THUNAR_VFS_TYPE_VOLUME); -} - - - -static void -thunar_vfs_volume_manager_finalize (GObject *object) -{ - ThunarVfsVolumeManager *manager = THUNAR_VFS_VOLUME_MANAGER (object); - ThunarVfsVolume *volume; - - /* drop all managed volumes */ - while (manager->volumes != NULL) - { - /* grab the first volume */ - volume = THUNAR_VFS_VOLUME (manager->volumes->data); - - /* verify that we're the only one keeping a reference on it */ - if (G_UNLIKELY (G_OBJECT (volume)->ref_count > 1)) - { - g_warning ("Attempt detected to finalize the ThunarVfsVolumeManager, while " - "there are still ThunarVfsVolume instances with a reference count " - "of 2 or more. This usually presents a bug in the application."); - } - - /* disconnect from the volume */ - thunar_vfs_volume_manager_remove (manager, volume); - } - - (*G_OBJECT_CLASS (thunar_vfs_volume_manager_parent_class)->finalize) (object); -} - - - -static ThunarVfsVolume* -thunar_vfs_volume_manager_real_get_volume_by_info (ThunarVfsVolumeManager *manager, - const ThunarVfsInfo *info) -{ - ThunarVfsVolume *best_volume = NULL; - ThunarVfsPath *best_path = NULL; - ThunarVfsPath *info_path; - ThunarVfsPath *path; - GList *lp; - - /* translate the info's path to a local path */ - info_path = _thunar_vfs_path_translate (info->path, THUNAR_VFS_PATH_SCHEME_FILE, NULL); - if (G_LIKELY (info_path != NULL)) - { - /* otherwise try to find it the hard way */ - for (lp = manager->volumes; lp != NULL; lp = lp->next) - { - /* check if the volume is mounted */ - if (!thunar_vfs_volume_is_mounted (lp->data)) - continue; - - /* check if the mount point is an ancestor of the info path */ - path = thunar_vfs_volume_get_mount_point (lp->data); - if (path == NULL || (!thunar_vfs_path_equal (info_path, path) && !thunar_vfs_path_is_ancestor (info_path, path))) - continue; - - /* possible match, check if better than previous match */ - if (best_volume == NULL || thunar_vfs_path_equal (path, best_path) || thunar_vfs_path_is_ancestor (path, best_path)) - { - best_volume = lp->data; - best_path = path; - } - } - - /* cleanup */ - thunar_vfs_path_unref (info_path); - } - - return best_volume; -} - - - -static void -thunar_vfs_volume_manager_volume_mounted (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume) -{ - g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); - g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager)); - g_return_if_fail (g_list_find (manager->volumes, volume) != NULL); - g_signal_emit (G_OBJECT (manager), manager_signals[VOLUME_MOUNTED], 0, volume); -} - - - -static void -thunar_vfs_volume_manager_volume_pre_unmount (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume) -{ - g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); - g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager)); - g_return_if_fail (g_list_find (manager->volumes, volume) != NULL); - g_signal_emit (G_OBJECT (manager), manager_signals[VOLUME_PRE_UNMOUNT], 0, volume); -} - - - -static void -thunar_vfs_volume_manager_volume_unmounted (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume) -{ - g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); - g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager)); - g_return_if_fail (g_list_find (manager->volumes, volume) != NULL); - g_signal_emit (G_OBJECT (manager), manager_signals[VOLUME_UNMOUNTED], 0, volume); -} - - - -/** - * thunar_vfs_volume_manager_get_default: - * - * Returns the default, shared #ThunarVfsVolumeManager instance - * for this system. This function automatically determines, which - * implementation of #ThunarVfsVolumeManager should be used for - * the target system and returns an instance of that class, which - * is shared among all modules using the volume manager facility. - * - * Call g_object_unref() on the returned object when you are - * done with it. - * - * Return value: the shared #ThunarVfsVolumeManager instance. - **/ -ThunarVfsVolumeManager* -thunar_vfs_volume_manager_get_default (void) -{ - static ThunarVfsVolumeManager *manager = NULL; - - if (G_UNLIKELY (manager == NULL)) - { - manager = g_object_new (THUNAR_VFS_TYPE_VOLUME_MANAGER_IMPL, NULL); - g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager); - } - else - { - g_object_ref (G_OBJECT (manager)); - } - - return manager; -} - - - -/** - * thunar_vfs_volume_manager_get_volume_by_info: - * @manager : a #ThunarVfsVolumeManager instance. - * @info : a #ThunarVfsInfo. - * - * Tries to lookup the #ThunarVfsVolume on which @info is - * located. If @manager doesn't know a #ThunarVfsVolume - * for @info, %NULL will be returned. - * - * The returned #ThunarVfsVolume (if any) is owned by - * @manager and must not be freed by the caller. - * - * Return value: the #ThunarVfsVolume, on which @info is - * located or %NULL. - **/ -ThunarVfsVolume* -thunar_vfs_volume_manager_get_volume_by_info (ThunarVfsVolumeManager *manager, - const ThunarVfsInfo *info) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager), NULL); - g_return_val_if_fail (info != NULL, NULL); - return (*THUNAR_VFS_VOLUME_MANAGER_GET_CLASS (manager)->get_volume_by_info) (manager, info); -} - - - -/** - * thunar_vfs_volume_manager_get_volumes: - * @manager : a #ThunarVfsVolumeManager instance. - * - * Returns all #ThunarVfsVolume<!---->s currently known for - * @manager. The returned list is owned by @manager and should - * therefore considered constant in the caller. - * - * Return value: the list of volumes known for @manager. - **/ -GList* -thunar_vfs_volume_manager_get_volumes (ThunarVfsVolumeManager *manager) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager), NULL); - return manager->volumes; -} - - - -/** - * thunar_vfs_volume_manager_add: - * @manager : a #ThunarVfsVolumeManager instance. - * @volume : a #ThunarVfsVolume. - * - * Adds @volume to the list of #ThunarVfsVolume<!---->s managed - * by the @manager, and emits the "volumes-added" signal on - * @manager using the given @volume. - * - * It is an error to call this method with a @volume that is - * already managed by @manager. - * - * This method should only be used by #ThunarVfsVolumeManager - * implementations. - **/ -void -thunar_vfs_volume_manager_add (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume) -{ - GList list; - - g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); - g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager)); - g_return_if_fail (g_list_find (manager->volumes, volume) == NULL); - - /* add the volume to the list of managed volumes */ - manager->volumes = g_list_prepend (manager->volumes, volume); - g_object_ref (G_OBJECT (volume)); - - /* connect the required signals */ - g_signal_connect_swapped (G_OBJECT (volume), "mounted", G_CALLBACK (thunar_vfs_volume_manager_volume_mounted), manager); - g_signal_connect_swapped (G_OBJECT (volume), "pre-unmount", G_CALLBACK (thunar_vfs_volume_manager_volume_pre_unmount), manager); - g_signal_connect_swapped (G_OBJECT (volume), "unmounted", G_CALLBACK (thunar_vfs_volume_manager_volume_unmounted), manager); - - /* fake a volume list */ - list.data = volume; - list.next = NULL; - list.prev = NULL; - - /* emit "volumes-added" with the faked list */ - g_signal_emit (G_OBJECT (manager), manager_signals[VOLUMES_ADDED], 0, &list); -} - - - -/** - * thunar_vfs_volume_manager_remove: - * @manager : a #ThunarVfsVolumeManager instance. - * @volume : a #ThunarVfsVolume. - * - * Removes @volume from the list of #ThunarVfsVolume<!---->s managed - * by the @manager, and emits the "volumes-removed" signal on - * @manager using the given @volume. - * - * It is an error to call this method with @volume that is not - * currently managed by @manager. - * - * This method should only be used by #ThunarVfsVolumeManager - * implementations. - **/ -void -thunar_vfs_volume_manager_remove (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume) -{ - GList list; - - g_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); - g_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (manager)); - g_return_if_fail (g_list_find (manager->volumes, volume) != NULL); - - /* remove the volume from our list */ - manager->volumes = g_list_remove (manager->volumes, volume); - - /* disconnect our signal handlers */ - g_signal_handlers_disconnect_by_func (G_OBJECT (volume), thunar_vfs_volume_manager_volume_mounted, manager); - g_signal_handlers_disconnect_by_func (G_OBJECT (volume), thunar_vfs_volume_manager_volume_pre_unmount, manager); - g_signal_handlers_disconnect_by_func (G_OBJECT (volume), thunar_vfs_volume_manager_volume_unmounted, manager); - - /* fake a volume list */ - list.data = volume; - list.next = NULL; - list.prev = NULL; - - /* emit "volumes-removed" with the faked list */ - g_signal_emit (G_OBJECT (manager), manager_signals[VOLUMES_REMOVED], 0, &list); - - /* drop our reference on the volume */ - g_object_unref (G_OBJECT (volume)); -} - - - -#define __THUNAR_VFS_VOLUME_MANAGER_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-volume-none.c b/thunar-vfs/thunar-vfs-volume-none.c deleted file mode 100644 index fdc314d24..000000000 --- a/thunar-vfs/thunar-vfs-volume-none.c +++ /dev/null @@ -1,73 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <thunar-vfs/thunar-vfs-volume-none.h> -#include <thunar-vfs/thunar-vfs-volume-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -struct _ThunarVfsVolumeManagerNoneClass -{ - ThunarVfsVolumeManagerClass __parent__; -}; - -struct _ThunarVfsVolumeManagerNone -{ - ThunarVfsVolumeClass __parent__; -}; - - - -GType -thunar_vfs_volume_manager_none_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - static const GTypeInfo info = - { - sizeof (ThunarVfsVolumeManagerNoneClass), - NULL, - NULL, - NULL, - NULL, - NULL, - sizeof (ThunarVfsVolumeManagerNone), - 0, - NULL, - NULL, - }; - - type = g_type_register_static (THUNAR_VFS_TYPE_VOLUME_MANAGER, I_("ThunarVfsVolumeManagerNone"), &info, 0); - } - - return type; -} - - - -#define __THUNAR_VFS_VOLUME_NONE_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-volume-none.h b/thunar-vfs/thunar-vfs-volume-none.h deleted file mode 100644 index 4a335965f..000000000 --- a/thunar-vfs/thunar-vfs-volume-none.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_VOLUME_NONE_H__ -#define __THUNAR_VFS_VOLUME_NONE_H__ - -#include <thunar-vfs/thunar-vfs-volume.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsVolumeNoneClass ThunarVfsVolumeNoneClass; -typedef struct _ThunarVfsVolumeNone ThunarVfsVolumeNone; - -#define THUNAR_VFS_TYPE_VOLUME_NONE (thunar_vfs_volume_none_get_type ()) -#define THUNAR_VFS_VOLUME_NONE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME_NONE, ThunarVfsVolumeNONE)) -#define THUNAR_VFS_VOLUME_NONE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME_NONE, ThunarVfsVolumeNONEClass)) -#define THUNAR_VFS_IS_VOLUME_NONE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME_NONE)) -#define THUNAR_VFS_IS_VOLUME_NONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME_NONE)) -#define THUNAR_VFS_VOLUME_NONE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME_NONE, ThunarVfsVolumeNONEClass)) - -GType thunar_vfs_volume_none_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - - -typedef struct _ThunarVfsVolumeManagerNoneClass ThunarVfsVolumeManagerNoneClass; -typedef struct _ThunarVfsVolumeManagerNone ThunarVfsVolumeManagerNone; - -#define THUNAR_VFS_TYPE_VOLUME_MANAGER_NONE (thunar_vfs_volume_manager_none_get_type ()) -#define THUNAR_VFS_VOLUME_MANAGER_NONE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER_NONE, ThunarVfsVolumeManagerNONE)) -#define THUNAR_VFS_VOLUME_MANAGER_NONE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER_NONE, ThunarVfsVolumeManagerNONEClass)) -#define THUNAR_VFS_IS_VOLUME_MANAGER_NONE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER_NONE)) -#define THUNAR_VFS_IS_VOLUME_MANAGER_NONE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER_NONE)) -#define THUNAR_VFS_VOLUME_MANAGER_NONE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER_NONE, ThunarVfsVolumeManagerNONEClass)) - -GType thunar_vfs_volume_manager_none_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_VOLUME_NONE_H__ */ diff --git a/thunar-vfs/thunar-vfs-volume-private.h b/thunar-vfs/thunar-vfs-volume-private.h deleted file mode 100644 index 74ebb0c6b..000000000 --- a/thunar-vfs/thunar-vfs-volume-private.h +++ /dev/null @@ -1,113 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_VOLUME_PRIVATE_H__ -#define __THUNAR_VFS_VOLUME_PRIVATE_H__ - -#include <thunar-vfs/thunar-vfs-volume.h> - -G_BEGIN_DECLS; - -struct _ThunarVfsVolumeClass -{ - /*< private >*/ - GObjectClass __parent__; - - /*< public >*/ - - /* methods */ - ThunarVfsVolumeKind (*get_kind) (ThunarVfsVolume *volume); - const gchar *(*get_name) (ThunarVfsVolume *volume); - ThunarVfsVolumeStatus (*get_status) (ThunarVfsVolume *volume); - ThunarVfsPath *(*get_mount_point) (ThunarVfsVolume *volume); - gboolean (*is_ejectable) (ThunarVfsVolume *volume); - const gchar *(*lookup_icon_name) (ThunarVfsVolume *volume, - GtkIconTheme *icon_theme); - - gboolean (*eject) (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); - gboolean (*mount) (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); - gboolean (*unmount) (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); - - /* signals */ - void (*changed) (ThunarVfsVolume *volume); - void (*mounted) (ThunarVfsVolume *volume); - void (*pre_unmount) (ThunarVfsVolume *volume); - void (*unmounted) (ThunarVfsVolume *volume); -}; - -struct _ThunarVfsVolume -{ - /*< private >*/ - GObject __parent__; -}; - -void thunar_vfs_volume_changed (ThunarVfsVolume *volume) G_GNUC_INTERNAL; -void thunar_vfs_volume_pre_unmount (ThunarVfsVolume *volume) G_GNUC_INTERNAL; - - -struct _ThunarVfsVolumeManagerClass -{ - /*< private >*/ - GObjectClass __parent__; - - /*< public >*/ - - /* methods */ - ThunarVfsVolume *(*get_volume_by_info) (ThunarVfsVolumeManager *manager, - const ThunarVfsInfo *info); - - /* signals */ - void (*volumes_added) (ThunarVfsVolumeManager *manager, - GList *volumes); - void (*volumes_removed) (ThunarVfsVolumeManager *manager, - GList *volumes); - void (*volume_mounted) (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume); - void (*volume_pre_unmount) (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume); - void (*volume_unmounted) (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume); -}; - -struct _ThunarVfsVolumeManager -{ - /*< private >*/ - GObject __parent__; - - /*< public >*/ - - /* the list of available volumes */ - GList *volumes; -}; - -void thunar_vfs_volume_manager_add (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume) G_GNUC_INTERNAL; -void thunar_vfs_volume_manager_remove (ThunarVfsVolumeManager *manager, - ThunarVfsVolume *volume) G_GNUC_INTERNAL; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_VOLUME_PRIVATE_H__ */ diff --git a/thunar-vfs/thunar-vfs-volume.c b/thunar-vfs/thunar-vfs-volume.c deleted file mode 100644 index 95bdc99f8..000000000 --- a/thunar-vfs/thunar-vfs-volume.c +++ /dev/null @@ -1,722 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <thunar-vfs/thunar-vfs-enum-types.h> -#include <thunar-vfs/thunar-vfs-io-trash.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-volume-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -/* Signal identifiers */ -enum -{ - CHANGED, - MOUNTED, - PRE_UNMOUNT, - UNMOUNTED, - LAST_SIGNAL, -}; - - - -static void thunar_vfs_volume_class_init (ThunarVfsVolumeClass *klass); - - - -static guint volume_signals[LAST_SIGNAL]; - - - -GType -thunar_vfs_volume_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsVolume", - sizeof (ThunarVfsVolumeClass), - thunar_vfs_volume_class_init, - sizeof (ThunarVfsVolume), - NULL, - G_TYPE_FLAG_ABSTRACT); - } - - return type; -} - - - -static void -thunar_vfs_volume_class_init (ThunarVfsVolumeClass *klass) -{ - /** - * ThunarVfsVolume::changed: - * @volume : the #ThunarVfsVolume instance. - * - * Emitted whenever the state of @volume changed. - **/ - volume_signals[CHANGED] = - g_signal_new (I_("changed"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsVolumeClass, changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * ThunarVfsVolume::mounted: - * @volume : the #ThunarVfsVolume instance. - * - * Emitted by @volume after a successfull mount - * operation. - **/ - volume_signals[MOUNTED] = - g_signal_new (I_("mounted"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsVolumeClass, mounted), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * ThunarVfsVolume::pre-unmount: - * @volume : the #ThunarVfsVolume instance. - * - * Emitted by @volume right before an attempt - * is made to unmount the @volume. - **/ - volume_signals[PRE_UNMOUNT] = - g_signal_new (I_("pre-unmount"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsVolumeClass, pre_unmount), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - /** - * ThunarVfsVolume::unmounted: - * @volume : the #ThunarVfsVolume instance. - * - * Emitted by @volume right after the @volume - * was successfully unmounted. - **/ - volume_signals[UNMOUNTED] = - g_signal_new (I_("unmounted"), - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ThunarVfsVolumeClass, unmounted), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - - - -/** - * thunar_vfs_volume_get_kind: - * @volume : a #ThunarVfsVolume instance. - * - * Returns the kind of drive/device representd by @volume. - * - * Return value: the kind of @volume. - **/ -ThunarVfsVolumeKind -thunar_vfs_volume_get_kind (ThunarVfsVolume *volume) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), THUNAR_VFS_VOLUME_KIND_UNKNOWN); - return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_kind) (volume); -} - - - -/** - * thunar_vfs_volume_get_name; - * @volume : a #ThunarVfsVolume instance. - * - * Returns the name of the @volume. This is usually the - * name of the device or the label of the medium, if a - * medium is present. - * - * Return value: the name of @volume. - **/ -const gchar* -thunar_vfs_volume_get_name (ThunarVfsVolume *volume) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), NULL); - return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_name) (volume); -} - - - -/** - * thunar_vfs_volume_get_status: - * @volume : a #ThunarVfsVolume instance. - * - * Determines the current status of the @volume, e.g. whether - * or not the @volume is currently mounted, or whether a - * medium is present. - * - * Return value: the status for @volume. - **/ -ThunarVfsVolumeStatus -thunar_vfs_volume_get_status (ThunarVfsVolume *volume) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), 0); - return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_status) (volume); -} - - - -/** - * thunar_vfs_volume_get_mount_point: - * @volume : a #ThunarVfsVolume instance. - * - * Determines the current mount point for @volume. If @volume - * is mounted this will be the location at which it is currently - * mounted. Else it will be the location where @volume is most - * probably being mounted. Note that this location may change - * during a call to thunar_vfs_volume_mount(), so be sure to - * check the mount point after the call to thunar_vfs_volume_mount(). - * - * Return value: the path which identifies the path where - * the volume will be mounted (or is already - * mounted). - **/ -ThunarVfsPath* -thunar_vfs_volume_get_mount_point (ThunarVfsVolume *volume) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), NULL); - return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_mount_point) (volume); -} - - - -/** - * thunar_vfs_volume_is_disc: - * @volume : a #ThunarVfsVolume instance. - * - * Determines whether @volume is a disc, which can be ejected. - * Applications should use this method to determine whether to - * thunar_vfs_volume_eject() or thunar_vfs_volume_unmount(). - * - * Return value: %TRUE if @volume is a disc. - **/ -gboolean -thunar_vfs_volume_is_disc (ThunarVfsVolume *volume) -{ - ThunarVfsVolumeKind kind; - - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE); - - kind = thunar_vfs_volume_get_kind (volume); - - return (kind >= THUNAR_VFS_VOLUME_KIND_CDROM && kind <= THUNAR_VFS_VOLUME_KIND_DVDPLUSRW) - || (kind == THUNAR_VFS_VOLUME_KIND_AUDIO_CD); -} - - - -/** - * thunar_vfs_volume_is_mountable: - * @volume : a #ThunarVfsVolume instance. - * - * Determines whether @volume has a valid filesystem and - * if it can be mounted. - * - * Return value: %TRUE if @volume is mountable, else %FALSE. - **/ -gboolean -thunar_vfs_volume_is_mountable (ThunarVfsVolume *volume) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE); - return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_status) (volume) & THUNAR_VFS_VOLUME_STATUS_MOUNTABLE; -} - - - -/** - * thunar_vfs_volume_is_mounted: - * @volume : a #ThunarVfsVolume instance. - * - * Determines whether @volume is currently mounted into the - * filesystem hierarchy. - * - * Return value: %TRUE if @volume is mounted, else %FALSE. - **/ -gboolean -thunar_vfs_volume_is_mounted (ThunarVfsVolume *volume) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE); - return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_status) (volume) & THUNAR_VFS_VOLUME_STATUS_MOUNTED; -} - - - -/** - * thunar_vfs_volume_is_present: - * @volume : a #ThunarVfsVolume instance. - * - * Determines whether a medium is currently inserted for - * @volume, e.g. for a CD-ROM drive, this will be %TRUE - * only if a disc is present in the slot. - * - * Return value: %TRUE if @volume is present, else %FALSE. - **/ -gboolean -thunar_vfs_volume_is_present (ThunarVfsVolume *volume) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE); - return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->get_status) (volume) & THUNAR_VFS_VOLUME_STATUS_PRESENT; -} - - - -/** - * thunar_vfs_volume_is_ejectable: - * @volume : a #ThunarVfsVolume instance. - * - * Determines whether the current user is allowed to eject the medium - * for @volume. This method should return %TRUE only if a medium is - * present and the @volume is removable. Still, there's no warranty - * that a call to thunar_vfs_volume_eject() will succeed. - * - * Return value: whether the medium for @volume can be ejected. - **/ -gboolean -thunar_vfs_volume_is_ejectable (ThunarVfsVolume *volume) -{ - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE); - return (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->is_ejectable) (volume); -} - - - -/** - * thunar_vfs_volume_is_removable: - * @volume : a #ThunarVfsVolume instance. - * - * Determines whether @volume is a removable device, for example - * a CD-ROM, an USB stick or a floppy drive. - * - * Return value: %TRUE if @volume is a removable device, else %FALSE. - **/ -gboolean -thunar_vfs_volume_is_removable (ThunarVfsVolume *volume) -{ - ThunarVfsVolumeKind kind; - - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE); - - kind = thunar_vfs_volume_get_kind (volume); - - switch (kind) - { - case THUNAR_VFS_VOLUME_KIND_CDROM: - case THUNAR_VFS_VOLUME_KIND_CDR: - case THUNAR_VFS_VOLUME_KIND_CDRW: - case THUNAR_VFS_VOLUME_KIND_DVDROM: - case THUNAR_VFS_VOLUME_KIND_DVDRAM: - case THUNAR_VFS_VOLUME_KIND_DVDR: - case THUNAR_VFS_VOLUME_KIND_DVDRW: - case THUNAR_VFS_VOLUME_KIND_DVDPLUSR: - case THUNAR_VFS_VOLUME_KIND_DVDPLUSRW: - case THUNAR_VFS_VOLUME_KIND_FLOPPY: - case THUNAR_VFS_VOLUME_KIND_USBSTICK: - case THUNAR_VFS_VOLUME_KIND_AUDIO_PLAYER: - case THUNAR_VFS_VOLUME_KIND_AUDIO_CD: - case THUNAR_VFS_VOLUME_KIND_MEMORY_CARD: - case THUNAR_VFS_VOLUME_KIND_REMOVABLE_DISK: - return TRUE; - - default: - return FALSE; - } -} - - - -/** - * thunar_vfs_volume_lookup_icon_name: - * @volume : a #ThunarVfsVolume instance. - * @icon_theme : a #GtkIconTheme instance. - * - * Tries to find a suitable icon for @volume in the given @icon_theme and - * returns its name. If no suitable icon is found in @icon_theme, then - * a fallback icon name will be returned. This way you can always count - * on this method to return a valid string. - * - * Return value: the icon name. - **/ -const gchar* -thunar_vfs_volume_lookup_icon_name (ThunarVfsVolume *volume, - GtkIconTheme *icon_theme) -{ - ThunarVfsVolumeClass *klass; - ThunarVfsVolumeKind kind; - const gchar *icon_name; - - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), NULL); - g_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL); - - /* allow the implementing class to provide a custom icon */ - klass = THUNAR_VFS_VOLUME_GET_CLASS (volume); - if (klass->lookup_icon_name != NULL) - { - icon_name = (*klass->lookup_icon_name) (volume, icon_theme); - if (G_LIKELY (icon_name != NULL)) - return icon_name; - } - - kind = thunar_vfs_volume_get_kind (volume); - switch (kind) - { -cdrom: - case THUNAR_VFS_VOLUME_KIND_CDROM: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-cdrom")) - return "gnome-dev-cdrom"; - break; - - case THUNAR_VFS_VOLUME_KIND_CDR: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-disc-cdr")) - return "gnome-dev-disc-cdr"; - goto cdrom; - - case THUNAR_VFS_VOLUME_KIND_CDRW: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-disc-cdrw")) - return "gnome-dev-disc-cdrw"; - goto cdrom; - -dvdrom: - case THUNAR_VFS_VOLUME_KIND_DVDROM: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-disc-dvdrom")) - return "gnome-dev-disc-dvdrom"; - else if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-dvd")) - return "gnome-dev-dvd"; - goto cdrom; - - case THUNAR_VFS_VOLUME_KIND_DVDRAM: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-disc-dvdram")) - return "gnome-dev-disc-dvdram"; - goto dvdrom; - -dvdr: - case THUNAR_VFS_VOLUME_KIND_DVDR: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-disc-dvdr")) - return "gnome-dev-disc-dvdr"; - goto dvdrom; - - case THUNAR_VFS_VOLUME_KIND_DVDRW: - case THUNAR_VFS_VOLUME_KIND_DVDPLUSRW: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-disc-dvdrw")) - return "gnome-dev-disc-dvdrw"; - goto dvdrom; - - case THUNAR_VFS_VOLUME_KIND_DVDPLUSR: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-disc-dvdr-plus")) - return "gnome-dev-disc-dvdr-plus"; - goto dvdr; - - case THUNAR_VFS_VOLUME_KIND_FLOPPY: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-floppy")) - return "gnome-dev-floppy"; - break; - - case THUNAR_VFS_VOLUME_KIND_HARDDISK: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-harddisk")) - return "gnome-dev-harddisk"; - break; - - case THUNAR_VFS_VOLUME_KIND_USBSTICK: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-removable-usb")) - return "gnome-dev-removable-usb"; - else if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-harddisk-usb")) - return "gnome-dev-harddisk-usb"; - break; - - case THUNAR_VFS_VOLUME_KIND_AUDIO_PLAYER: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-ipod")) - return "gnome-dev-ipod"; - break; - - case THUNAR_VFS_VOLUME_KIND_AUDIO_CD: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-cdrom-audio")) - return "gnome-dev-cdrom-audio"; - goto cdrom; - - case THUNAR_VFS_VOLUME_KIND_MEMORY_CARD: - case THUNAR_VFS_VOLUME_KIND_REMOVABLE_DISK: - if (gtk_icon_theme_has_icon (icon_theme, "gnome-dev-removable")) - return "gnome-dev-removable"; - break; - - default: - break; - } - - return "gnome-fs-blockdev"; -} - - - -/** - * thunar_vfs_volume_eject: - * @volume : a #ThunarVfsVolume instance. - * @window : a #GtkWindow or %NULL. - * @error : return location for errors or %NULL. - * - * Tries to eject the medium present for @volume (or atleast to - * unmount the @volume). - * - * If ejecting @volume requires some complex user interaction - * (basicly everything else than displaying an error dialog), it - * should popup a modal dialog on @window (or on the default - * #GdkScreen if @window is %NULL). But be aware, that if an - * implementation of #ThunarVfsVolume performs user interaction - * during a call to this method, it must implement this method - * in a reentrant fashion! - * - * Return value: %TRUE if the medium for @volume was successfully - * ejected (or atleast the @volume was unmounted - * successfully), else %FALSE. - **/ -gboolean -thunar_vfs_volume_eject (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error) -{ - GdkCursor *cursor; - gboolean result; - - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (window == NULL || GTK_IS_WINDOW (window), FALSE); - - /* we're about to unmount (and eject) the volume */ - thunar_vfs_volume_pre_unmount (volume); - - /* setup a watch cursor on the window */ - if (window != NULL && GTK_WIDGET_REALIZED (window)) - { - /* setup the watch cursor */ - cursor = gdk_cursor_new (GDK_WATCH); - gdk_window_set_cursor (window->window, cursor); - gdk_cursor_unref (cursor); - - /* flush the changes */ - gdk_flush (); - } - - /* try to mount the volume */ - result = (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->eject) (volume, window, error); - - /* reset the cursor */ - if (window != NULL && GTK_WIDGET_REALIZED (window)) - gdk_window_set_cursor (window->window, NULL); - - /* check if we unmounted successfully */ - if (G_LIKELY (result)) - g_signal_emit (G_OBJECT (volume), volume_signals[UNMOUNTED], 0); - - return result; -} - - - -/** - * thunar_vfs_volume_mount: - * @volume : a #ThunarVfsVolume instance. - * @window : a #GtkWindow or %NULL. - * @error : return location for errors or %NULL. - * - * Tries to mount @volume. Will return %TRUE if either @volume - * was already mounted previously to this method invokation or - * @volume was successfully mounted now. - * - * If mounting @volume requires some complex user interaction - * (basicly everything else than displaying an error dialog), it - * should popup a modal dialog on @window (or on the default - * #GdkScreen if @window is %NULL). But be aware, that if an - * implementation of #ThunarVfsVolume performs user interaction - * during a call to this method, it must implement this method - * in a reentrant fashion! - * - * Return value: %TRUE if the medium for @volume was successfully - * mounted or was already mounted previously, else - * %FALSE. - **/ -gboolean -thunar_vfs_volume_mount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error) -{ - GdkCursor *cursor; - gboolean result; - - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (window == NULL || GTK_IS_WINDOW (window), FALSE); - - /* setup a watch cursor on the window */ - if (window != NULL && GTK_WIDGET_REALIZED (window)) - { - /* setup the watch cursor */ - cursor = gdk_cursor_new (GDK_WATCH); - gdk_window_set_cursor (window->window, cursor); - gdk_cursor_unref (cursor); - - /* flush the changes */ - gdk_flush (); - } - - /* try to mount the volume */ - result = (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->mount) (volume, window, error); - - /* reset the cursor */ - if (window != NULL && GTK_WIDGET_REALIZED (window)) - gdk_window_set_cursor (window->window, NULL); - - /* check if we successfully mounted the volume */ - if (G_LIKELY (result)) - g_signal_emit (G_OBJECT (volume), volume_signals[MOUNTED], 0); - - return result; -} - - - -/** - * thunar_vfs_volume_unmount: - * @volume : a #ThunarVfsVolume instance. - * @window : a #GtkWindow or %NULL. - * @error : return location for errors or %NULL. - * - * Tries to unmount @volume. Will return %TRUE if either @volume - * was already unmounted previously to this method invokation or - * @volume was successfully unmounted now. - * - * If unmounting @volume requires some complex user interaction - * (basicly everything else than displaying an error dialog), it - * should popup a modal dialog on @window (or on the default - * #GdkScreen if @window is %NULL). But be aware, that if an - * implementation of #ThunarVfsVolume performs user interaction - * during a call to this method, it must implement this method - * in a reentrant fashion! - * - * Return value: %TRUE if the medium for @volume was successfully - * unmounted or wasn't mounted previously, else - * %FALSE. - **/ -gboolean -thunar_vfs_volume_unmount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error) -{ - GdkCursor *cursor; - gboolean result; - - g_return_val_if_fail (THUNAR_VFS_IS_VOLUME (volume), FALSE); - g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - g_return_val_if_fail (window == NULL || GTK_IS_WINDOW (window), FALSE); - - /* we're about to unmount the volume */ - thunar_vfs_volume_pre_unmount (volume); - - /* setup a watch cursor on the window */ - if (window != NULL && GTK_WIDGET_REALIZED (window)) - { - /* setup the watch cursor */ - cursor = gdk_cursor_new (GDK_WATCH); - gdk_window_set_cursor (window->window, cursor); - gdk_cursor_unref (cursor); - - /* flush the changes */ - gdk_flush (); - } - - /* try to mount the volume */ - result = (*THUNAR_VFS_VOLUME_GET_CLASS (volume)->unmount) (volume, window, error); - - /* reset the cursor */ - if (window != NULL && GTK_WIDGET_REALIZED (window)) - gdk_window_set_cursor (window->window, NULL); - - /* check if we unmounted successfully */ - if (G_LIKELY (result)) - g_signal_emit (G_OBJECT (volume), volume_signals[UNMOUNTED], 0); - - return result; -} - - - -/** - * thunar_vfs_volume_changed: - * @volume : a #ThunarVfsVolume instance. - * - * Emits the "changed" signal on @volume. This function should - * only be used by implementations of the #ThunarVfsVolume - * interface. - **/ -void -thunar_vfs_volume_changed (ThunarVfsVolume *volume) -{ - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); - - /* emit the "changed" signal */ - g_signal_emit (G_OBJECT (volume), volume_signals[CHANGED], 0); - - /* rescan the mount points for the trash subsystem, - * as we may have a volume with a new trash dir now. - */ - _thunar_vfs_io_trash_rescan_mounts (); -} - - - -/** - * thunar_vfs_volume_pre_unmount: - * @volume :a #ThunarVfsVolume instance. - * - * Emits the "pre-unmount" signal on the @volume. This function - * should only be used by implementations of the #ThunarVfsVolume - * interface. - **/ -void -thunar_vfs_volume_pre_unmount (ThunarVfsVolume *volume) -{ - _thunar_vfs_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); - g_signal_emit (G_OBJECT (volume), volume_signals[PRE_UNMOUNT], 0); -} - - - -#define __THUNAR_VFS_VOLUME_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs-volume.h b/thunar-vfs/thunar-vfs-volume.h deleted file mode 100644 index 1a06d4fb9..000000000 --- a/thunar-vfs/thunar-vfs-volume.h +++ /dev/null @@ -1,146 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_VOLUME_H__ -#define __THUNAR_VFS_VOLUME_H__ - -#include <gtk/gtk.h> - -#include <thunar-vfs/thunar-vfs-info.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarVfsVolumeClass ThunarVfsVolumeClass; -typedef struct _ThunarVfsVolume ThunarVfsVolume; - -#define THUNAR_VFS_TYPE_VOLUME (thunar_vfs_volume_get_type ()) -#define THUNAR_VFS_VOLUME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME, ThunarVfsVolume)) -#define THUNAR_VFS_VOLUME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME, ThunarVfsVolumeClass)) -#define THUNAR_VFS_IS_VOLUME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME)) -#define THUNAR_VFS_IS_VOLUME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME)) -#define THUNAR_VFS_VOLUME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME, ThunarVfsVolumeClass)) - -/** - * ThunarVfsVolumeKind: - * @THUNAR_VFS_VOLUME_KIND_UNKNOWN : Unknown volume. - * @THUNAR_VFS_VOLUME_KIND_CDROM : CD-ROMs. - * @THUNAR_VFS_VOLUME_KIND_CDR : CD-Rs. - * @THUNAR_VFS_VOLUME_KIND_CDRW : CD-RWs. - * @THUNAR_VFS_VOLUME_KIND_DVDROM : DVD-ROMs. - * @THUNAR_VFS_VOLUME_KIND_DVDRAM : DVD-RAMs. - * @THUNAR_VFS_VOLUME_KIND_DVDR : DVD-Rs. - * @THUNAR_VFS_VOLUME_KIND_DVDRW : DVD-RWs. - * @THUNAR_VFS_VOLUME_KIND_DVDPLUSR : DVD+Rs. - * @THUNAR_VFS_VOLUME_KIND_DVDPLUSRW : DVD+RWs. - * @THUNAR_VFS_VOLUME_KIND_FLOPPY : Floppy drives. - * @THUNAR_VFS_VOLUME_KIND_HARDDISK : Hard disk drives. - * @THUNAR_VFS_VOLUME_KIND_USBSTICK : USB sticks. - * @THUNAR_VFS_VOLUME_KIND_AUDIO_PLAYER : Portable audio players (i.e. iPod). - * @THUNAR_VFS_VOLUME_KIND_AUDIO_CD : Audio CDs. - * @THUNAR_VFS_VOLUME_KIND_MEMORY_CARD : Memory cards. - * @THUNAR_VFS_VOLUME_KIND_REMOVABLE_DISK : Other removable disks. - * - * Describes the type of a VFS volume. - **/ -typedef enum -{ - THUNAR_VFS_VOLUME_KIND_UNKNOWN, - THUNAR_VFS_VOLUME_KIND_CDROM, - THUNAR_VFS_VOLUME_KIND_CDR, - THUNAR_VFS_VOLUME_KIND_CDRW, - THUNAR_VFS_VOLUME_KIND_DVDROM, - THUNAR_VFS_VOLUME_KIND_DVDRAM, - THUNAR_VFS_VOLUME_KIND_DVDR, - THUNAR_VFS_VOLUME_KIND_DVDRW, - THUNAR_VFS_VOLUME_KIND_DVDPLUSR, - THUNAR_VFS_VOLUME_KIND_DVDPLUSRW, - THUNAR_VFS_VOLUME_KIND_FLOPPY, - THUNAR_VFS_VOLUME_KIND_HARDDISK, - THUNAR_VFS_VOLUME_KIND_USBSTICK, - THUNAR_VFS_VOLUME_KIND_AUDIO_PLAYER, - THUNAR_VFS_VOLUME_KIND_AUDIO_CD, - THUNAR_VFS_VOLUME_KIND_MEMORY_CARD, - THUNAR_VFS_VOLUME_KIND_REMOVABLE_DISK, -} ThunarVfsVolumeKind; - -/** - * ThunarVfsVolumeStatus: - * @THUNAR_VFS_VOLUME_STATUS_PRESENT : Whether or not a medium is present. - * @THUNAR_VFS_VOLUME_STATUS_MOUNTED : Whether or not the media is currently mounted. - * @THUNAR_VFS_VOLUME_STATUS_MOUNTABLE : Whether or not the media can be mounted. - * - * Describes the current status of a VFS volume. - **/ -typedef enum /*< flags >*/ -{ - THUNAR_VFS_VOLUME_STATUS_MOUNTED = 1 << 0, - THUNAR_VFS_VOLUME_STATUS_PRESENT = 1 << 1, - THUNAR_VFS_VOLUME_STATUS_MOUNTABLE = 1 << 2, -} ThunarVfsVolumeStatus; - -GType thunar_vfs_volume_get_type (void) G_GNUC_CONST; - -ThunarVfsVolumeKind thunar_vfs_volume_get_kind (ThunarVfsVolume *volume); -const gchar *thunar_vfs_volume_get_name (ThunarVfsVolume *volume); -ThunarVfsVolumeStatus thunar_vfs_volume_get_status (ThunarVfsVolume *volume); -ThunarVfsPath *thunar_vfs_volume_get_mount_point (ThunarVfsVolume *volume); - -gboolean thunar_vfs_volume_is_disc (ThunarVfsVolume *volume); -gboolean thunar_vfs_volume_is_mountable (ThunarVfsVolume *volume); -gboolean thunar_vfs_volume_is_mounted (ThunarVfsVolume *volume); -gboolean thunar_vfs_volume_is_present (ThunarVfsVolume *volume); -gboolean thunar_vfs_volume_is_ejectable (ThunarVfsVolume *volume); -gboolean thunar_vfs_volume_is_removable (ThunarVfsVolume *volume); - -const gchar *thunar_vfs_volume_lookup_icon_name (ThunarVfsVolume *volume, - GtkIconTheme *icon_theme); - -gboolean thunar_vfs_volume_eject (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); -gboolean thunar_vfs_volume_mount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); -gboolean thunar_vfs_volume_unmount (ThunarVfsVolume *volume, - GtkWidget *window, - GError **error); - - -typedef struct _ThunarVfsVolumeManagerClass ThunarVfsVolumeManagerClass; -typedef struct _ThunarVfsVolumeManager ThunarVfsVolumeManager; - -#define THUNAR_VFS_TYPE_VOLUME_MANAGER (thunar_vfs_volume_manager_get_type ()) -#define THUNAR_VFS_VOLUME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER, ThunarVfsVolumeManager)) -#define THUNAR_VFS_VOLUME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER, ThunarVfsVolumeManagerClass)) -#define THUNAR_VFS_IS_VOLUME_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER)) -#define THUNAR_VFS_IS_VOLUME_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_VFS_TYPE_VOLUME_MANAGER)) -#define THUNAR_VFS_VOLUME_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_VFS_TYPE_VOLUME_MANAGER, ThunarVfsVolumeManagerClass)) - -GType thunar_vfs_volume_manager_get_type (void) G_GNUC_CONST; - -ThunarVfsVolumeManager *thunar_vfs_volume_manager_get_default (void); - -ThunarVfsVolume *thunar_vfs_volume_manager_get_volume_by_info (ThunarVfsVolumeManager *manager, - const ThunarVfsInfo *info); -GList *thunar_vfs_volume_manager_get_volumes (ThunarVfsVolumeManager *manager); - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_VOLUME_H__ */ diff --git a/thunar-vfs/thunar-vfs.c b/thunar-vfs/thunar-vfs.c deleted file mode 100644 index 139a260e7..000000000 --- a/thunar-vfs/thunar-vfs.c +++ /dev/null @@ -1,815 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <thunar-vfs/thunar-vfs.h> -#include <thunar-vfs/thunar-vfs-deep-count-job.h> -#include <thunar-vfs/thunar-vfs-io-jobs.h> -#include <thunar-vfs/thunar-vfs-io-trash.h> -#include <thunar-vfs/thunar-vfs-job-private.h> -#include <thunar-vfs/thunar-vfs-mime-database-private.h> -#include <thunar-vfs/thunar-vfs-monitor-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-simple-job.h> -#include <thunar-vfs/thunar-vfs-transfer-job.h> -#include <thunar-vfs/thunar-vfs-alias.h> - - - -static gint thunar_vfs_ref_count = 0; - - - -/** - * thunar_vfs_init: - * - * Initializes the ThunarVFS library. - **/ -void -thunar_vfs_init (void) -{ - if (g_atomic_int_exchange_and_add (&thunar_vfs_ref_count, 1) == 0) - { - /* initialize the GThread system */ - if (!g_thread_supported ()) - g_thread_init (NULL); - - /* ensure any strings get translated properly */ - xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8"); - - /* initialize the path module */ - _thunar_vfs_path_init (); - - /* allocate the shared monitor instance */ - _thunar_vfs_monitor = g_object_new (THUNAR_VFS_TYPE_MONITOR, NULL); - - /* allocate the shared mime database instance */ - _thunar_vfs_mime_database = g_object_new (THUNAR_VFS_TYPE_MIME_DATABASE, NULL); - - /* pre-determine the most important mime types */ - _thunar_vfs_mime_inode_directory = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "inode/directory"); - _thunar_vfs_mime_application_x_desktop = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "application/x-desktop"); - _thunar_vfs_mime_application_x_executable = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "application/x-executable"); - _thunar_vfs_mime_application_x_shellscript = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "application/x-shellscript"); - _thunar_vfs_mime_application_octet_stream = thunar_vfs_mime_database_get_info (_thunar_vfs_mime_database, "application/octet-stream"); - - /* initialize the trash subsystem */ - _thunar_vfs_io_trash_init (); - - /* initialize the jobs framework */ - _thunar_vfs_job_init (); - - /* do not maintain more than 4 unused threads */ - g_thread_pool_set_max_unused_threads (4); - -#if GLIB_CHECK_VERSION(2,10,0) - /* stop unused threads after 10 seconds of idle time */ - g_thread_pool_set_max_idle_time (10 * 1000); -#endif - } -} - - - -/** - * thunar_vfs_shutdown: - * - * Shuts down the ThunarVFS library. - **/ -void -thunar_vfs_shutdown (void) -{ - if (g_atomic_int_dec_and_test (&thunar_vfs_ref_count)) - { - /* shutdown the jobs framework */ - _thunar_vfs_job_shutdown (); - - /* shutdown the trash subsystem */ - _thunar_vfs_io_trash_shutdown (); - - /* release the mime type references */ - thunar_vfs_mime_info_unref (_thunar_vfs_mime_application_octet_stream); - thunar_vfs_mime_info_unref (_thunar_vfs_mime_application_x_shellscript); - thunar_vfs_mime_info_unref (_thunar_vfs_mime_application_x_executable); - thunar_vfs_mime_info_unref (_thunar_vfs_mime_application_x_desktop); - thunar_vfs_mime_info_unref (_thunar_vfs_mime_inode_directory); - - /* release the reference on the mime database */ - g_object_unref (G_OBJECT (_thunar_vfs_mime_database)); - _thunar_vfs_mime_database = NULL; - - /* release the reference on the monitor */ - g_object_unref (G_OBJECT (_thunar_vfs_monitor)); - _thunar_vfs_monitor = NULL; - - /* shutdown the path module */ - _thunar_vfs_path_shutdown (); - } -} - - - -/** - * thunar_vfs_listdir: - * @path : the #ThunarVfsPath for the folder that should be listed. - * @error : return location for errors or %NULL. - * - * Generates a #ThunarVfsJob, which lists the contents of the folder - * at the specified @path. If the job could not be launched for - * some reason, %NULL will be returned and @error will be set to - * point to a #GError describing the cause. Otherwise the newly - * allocated #ThunarVfsJob will be returned and the caller is - * responsible to call g_object_unref(). - * - * Note, that the returned job is launched right away, so you - * don't need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_listdir (ThunarVfsPath *path, - GError **error) -{ - /* allocate and launch the listdir job */ - return thunar_vfs_simple_job_launch (_thunar_vfs_io_jobs_listdir, 1, - THUNAR_VFS_TYPE_PATH, path); -} - - - -/** - * thunar_vfs_create_file: - * @path : the #ThunarVfsPath of the file to create. - * @error : return location for errors or %NULL. - * - * Allocates a new #ThunarVfsJob, which creates a new empty - * file at @path. - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note that the returned job is launched right away, so you - * don't need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_create_file (ThunarVfsPath *path, - GError **error) -{ - GList path_list; - - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* fake a path list */ - path_list.data = path; - path_list.next = NULL; - path_list.prev = NULL; - - /* allocate the job */ - return thunar_vfs_create_files (&path_list, error); -} - - - -/** - * thunar_vfs_create_files: - * @path_list : a list of #ThunarVfsPath<!---->s for files to create. - * @error : return location for errors or %NULL. - * - * Allocates a new #ThunarVfsJob which creates new empty files for all - * #ThunarVfsPath<!---->s in @path_list. - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note that the returned job is launched right away, so you - * don't need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_create_files (GList *path_list, - GError **error) -{ - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* verify that we have only local paths here */ - if (!_thunar_vfs_check_only_local (path_list, error)) - return NULL; - - /* allocate and launch the create job */ - return thunar_vfs_simple_job_launch (_thunar_vfs_io_jobs_create, 1, - THUNAR_VFS_TYPE_PATH_LIST, path_list); -} - - - -/** - * thunar_vfs_copy_file: - * @source_path : the source #ThunarVfsPath. - * @target_path : the target #ThunarVfsPath. - * @error : return location for errors or %NULL. - * - * Allocates a new #ThunarVfsTransferJob, which copies the file - * from @source_path to @target_path. That said, the file or directory - * located at @source_path will be placed at @target_path, NOT INTO - * @target_path. - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsTransferJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_copy_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError **error) -{ - GList source_path_list; - GList target_path_list; - - g_return_val_if_fail (source_path != NULL, NULL); - g_return_val_if_fail (target_path != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* fake a source path list */ - source_path_list.data = source_path; - source_path_list.next = NULL; - source_path_list.prev = NULL; - - /* fake a target path list */ - target_path_list.data = target_path; - target_path_list.next = NULL; - target_path_list.prev = NULL; - - /* allocate the job */ - return thunar_vfs_copy_files (&source_path_list, &target_path_list, error); -} - - - -/** - * thunar_vfs_copy_files: - * @source_path_list : the list of #ThunarVfsPath<!---->s that should be copied. - * @target_path_list : the list of #ThunarVfsPath<!---->s for the targets. - * @error : return location for errors or %NULL. - * - * Similar to thunar_vfs_copy_file(), but takes a bunch of files. The - * @source_path_list and @target_path_list must be of the same size. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. The caller is responsible - * to free the returned object using g_object_unref() when no longer - * needed. - * - * Return value: the newly allocated #ThunarVfsTransferJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_copy_files (GList *source_path_list, - GList *target_path_list, - GError **error) -{ - ThunarVfsJob *job; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* allocate/launch the job */ - job = thunar_vfs_transfer_job_new (source_path_list, target_path_list, FALSE, error); - if (G_LIKELY (job != NULL)) - thunar_vfs_job_launch (job); - - return job; -} - - - -/** - * thunar_vfs_link_file: - * @source_path : the source #ThunarVfsPath. - * @target_path : the target #ThunarVfsPath. - * @error : return location for errors or %NULL. - * - * Allocates a new #ThunarVfsJob, which creates a symbolic - * link from @source_path to @target_path. - * - * If @source_path and @target_path refer to the same file, - * a new unique target filename will be choosen automatically. - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_link_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError **error) -{ - GList source_path_list; - GList target_path_list; - - g_return_val_if_fail (!thunar_vfs_path_is_root (source_path), NULL); - g_return_val_if_fail (!thunar_vfs_path_is_root (target_path), NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* fake a source path list */ - source_path_list.data = source_path; - source_path_list.next = NULL; - source_path_list.prev = NULL; - - /* fake a target path list */ - target_path_list.data = target_path; - target_path_list.next = NULL; - target_path_list.prev = NULL; - - return thunar_vfs_link_files (&source_path_list, &target_path_list, error); -} - - - -/** - * thunar_vfs_link_files: - * @source_path_list : list of #ThunarVfsPath<!---->s to the source files. - * @target_path_list : list of #ThunarVfsPath<!---->s to the target files. - * @error : return location for errors or %NULL. - * - * Like thunar_vfs_link_file(), but works on path lists, rather than a single - * path. The length of the @source_path_list and @target_path_list must match, - * otherwise the behaviour is undefined, but its likely to crash the application. - * - * Right now links can only be created from local files to local files (with - * path scheme %THUNAR_VFS_PATH_SCHEME_FILE). - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_link_files (GList *source_path_list, - GList *target_path_list, - GError **error) -{ - g_return_val_if_fail (g_list_length (source_path_list) == g_list_length (target_path_list), NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* allocate and launch the job */ - return thunar_vfs_simple_job_launch (_thunar_vfs_io_jobs_link, 2, - THUNAR_VFS_TYPE_PATH_LIST, source_path_list, - THUNAR_VFS_TYPE_PATH_LIST, target_path_list); -} - - - -/** - * thunar_vfs_move_file: - * @source_path : the source #ThunarVfsPath. - * @target_path : the target #ThunarVfsPath. - * @error : return location for errors or %NULL. - * - * Allocates a new #ThunarVfsTransferJob, which moves the file - * from @source_path to @target_path. That said, the file or directory - * located at @source_path will be placed at @target_path, NOT INTO - * @target_path. - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsTransferJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_move_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError **error) -{ - GList source_path_list; - GList target_path_list; - - g_return_val_if_fail (source_path != NULL, NULL); - g_return_val_if_fail (target_path != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* fake a source path list */ - source_path_list.data = source_path; - source_path_list.next = NULL; - source_path_list.prev = NULL; - - /* fake a target path list */ - target_path_list.data = target_path; - target_path_list.next = NULL; - target_path_list.prev = NULL; - - /* allocate and launch the job */ - return thunar_vfs_move_files (&source_path_list, &target_path_list, error); -} - - - -/** - * thunar_vfs_move_files: - * @source_path_list : the list of #ThunarVfsPath<!---->s that should be moved. - * @target_path_list : the list of #ThunarVfsPath<!---->s to the targets. - * @error : return location for errors or %NULL. - * - * Similar to thunar_vfs_move_file(), but takes a bunch of files. The - * @source_path_list and @target_path_list must be of the same size. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. The caller is responsible - * to free the returned object using g_object_unref() when no longer - * needed. - * - * Return value: the newly allocated #ThunarVfsTransferJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_move_files (GList *source_path_list, - GList *target_path_list, - GError **error) -{ - ThunarVfsJob *job; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* allocate/launch the job */ - job = thunar_vfs_transfer_job_new (source_path_list, target_path_list, TRUE, error); - if (G_LIKELY (job != NULL)) - thunar_vfs_job_launch (job); - - return job; -} - - - -/** - * thunar_vfs_unlink_file: - * @path : a #ThunarVfsPath, that should be unlinked. - * @error : return location for errors or %NULL. - * - * Simple wrapper to thunar_vfs_unlink_files(), which takes - * only a single path. - * - * Note, that the returned job is launched right away, so you - * don't need to call thunar_vfs_job_launch() on it. The caller - * is responsible to free the returned object using g_object_unref() - * when no longer needed. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_unlink_file (ThunarVfsPath *path, - GError **error) -{ - GList path_list; - - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* fake a path list */ - path_list.data = path; - path_list.next = NULL; - path_list.prev = NULL; - - /* allocate and launch the job */ - return thunar_vfs_unlink_files (&path_list, error); -} - - - -/** - * thunar_vfs_unlink_files: - * @path_list : a list of #ThunarVfsPath<!---->s, that should be unlinked. - * @error : return location for errors or %NULL. - * - * Allocates a new #ThunarVfsJob which recursively unlinks all files - * referenced by the @path_list. If the job cannot be launched for - * some reason, %NULL will be returned and @error will be set to point to - * a #GError describing the cause. Else, the newly allocated #ThunarVfsJob - * will be returned, and the caller is responsible to free it using - * g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you - * don't need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_unlink_files (GList *path_list, - GError **error) -{ - return thunar_vfs_simple_job_launch (_thunar_vfs_io_jobs_unlink, 1, - THUNAR_VFS_TYPE_PATH_LIST, path_list); -} - - - -/** - * thunar_vfs_make_directory: - * @path : the #ThunarVfsPath to the directory to create. - * @error : return location for errors or %NULL. - * - * Simple wrapper for thunar_vfs_make_directories(). - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_make_directory (ThunarVfsPath *path, - GError **error) -{ - GList path_list; - - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* fake a path list */ - path_list.data = path; - path_list.next = NULL; - path_list.prev = NULL; - - /* allocate and launch the job */ - return thunar_vfs_make_directories (&path_list, error); -} - - - -/** - * thunar_vfs_make_directories: - * @path_list : a list of #ThunarVfsPath<!---->s that contain the paths - * to the directories which should be created. - * @error : return location for errors or %NULL. - * - * Allocates a new #ThunarVfsJob to create new directories at all - * #ThunarVfsPath<!---->s specified in @path_list. Returns %NULL if - * the job could not be launched for some reason, and @error will be - * set to point to a #GError describing the cause. Otherwise the - * job will be returned and the caller is responsible to free the - * returned object using g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_make_directories (GList *path_list, - GError **error) -{ - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* verify that we have only local paths here */ - if (!_thunar_vfs_check_only_local (path_list, error)) - return NULL; - - /* allocate and launch the mkdir job */ - return thunar_vfs_simple_job_launch (_thunar_vfs_io_jobs_mkdir, 1, - THUNAR_VFS_TYPE_PATH_LIST, path_list); -} - - - -/** - * thunar_vfs_change_mode: - * @path : the base #ThunarVfsPath. - * @dir_mask : the mask for the @dir_mode. - * @dir_mode : the new mode for directories. - * @file_mask : the mask for the @file_mode. - * @file_mode : the new mode for files. - * @recursive : whether to change permissions recursively. - * @error : return location for errors or %NULL. - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_change_mode (ThunarVfsPath *path, - ThunarVfsFileMode dir_mask, - ThunarVfsFileMode dir_mode, - ThunarVfsFileMode file_mask, - ThunarVfsFileMode file_mode, - gboolean recursive, - GError **error) -{ - GList path_list; - - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* verify that we have only local paths here */ - if (G_UNLIKELY (!_thunar_vfs_path_is_local (path))) - { - _thunar_vfs_set_g_error_not_supported (error); - return NULL; - } - - /* fake a path list */ - path_list.data = path; - path_list.next = NULL; - path_list.prev = NULL; - - /* allocate and launch the new job */ - return thunar_vfs_simple_job_launch (_thunar_vfs_io_jobs_chmod, 6, - THUNAR_VFS_TYPE_PATH_LIST, &path_list, - THUNAR_VFS_TYPE_VFS_FILE_MODE, dir_mask, - THUNAR_VFS_TYPE_VFS_FILE_MODE, dir_mode, - THUNAR_VFS_TYPE_VFS_FILE_MODE, file_mask, - THUNAR_VFS_TYPE_VFS_FILE_MODE, file_mode, - G_TYPE_BOOLEAN, recursive); -} - - - -/** - * thunar_vfs_change_group: - * @path : the base #ThunarVfsPath. - * @gid : the new group id. - * @recursive : whether to change groups recursively. - * @error : return location for errors or %NULL. - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_change_group (ThunarVfsPath *path, - ThunarVfsGroupId gid, - gboolean recursive, - GError **error) -{ - GList path_list; - - g_return_val_if_fail (gid >= 0, NULL); - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* verify that we have only local paths here */ - if (G_UNLIKELY (!_thunar_vfs_path_is_local (path))) - { - _thunar_vfs_set_g_error_not_supported (error); - return NULL; - } - - /* fake a path list */ - path_list.data = path; - path_list.next = NULL; - path_list.prev = NULL; - - /* allocate and launch the new job */ - return thunar_vfs_simple_job_launch (_thunar_vfs_io_jobs_chown, 4, - THUNAR_VFS_TYPE_PATH_LIST, &path_list, - G_TYPE_INT, (gint) -1, - G_TYPE_INT, (gint) gid, - G_TYPE_BOOLEAN, recursive); -} - - - -/** - * thunar_vfs_change_owner: - * @path : the base #ThunarVfsPath. - * @uid : the new user id. - * @recursive : whether to change groups recursively. - * @error : return location for errors or %NULL. - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsChownJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_change_owner (ThunarVfsPath *path, - ThunarVfsUserId uid, - gboolean recursive, - GError **error) -{ - GList path_list; - - g_return_val_if_fail (uid >= 0, NULL); - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* verify that we have only local paths here */ - if (G_UNLIKELY (!_thunar_vfs_path_is_local (path))) - { - _thunar_vfs_set_g_error_not_supported (error); - return NULL; - } - - /* fake a path list */ - path_list.data = path; - path_list.next = NULL; - path_list.prev = NULL; - - /* allocate and launch the new job */ - return thunar_vfs_simple_job_launch (_thunar_vfs_io_jobs_chown, 4, - THUNAR_VFS_TYPE_PATH_LIST, &path_list, - G_TYPE_INT, (gint) uid, - G_TYPE_INT, (gint) -1, - G_TYPE_BOOLEAN, recursive); -} - - - -/** - * thunar_vfs_deep_count: - * @path : the base #ThunarVfsPath. - * @flags : the #ThunarVfsDeepCountFlags which control the behaviour - * of the returned job. - * @error : return location for errors or %NULL. - * - * Starts a #ThunarVfsJob, which will count the number of items - * in the directory specified by @path and also determine the - * total size. If @path is not a directory, then the size of the - * item at @path will be determined. - * - * The caller is responsible to free the returned job using - * g_object_unref() when no longer needed. - * - * Note, that the returned job is launched right away, so you don't - * need to call thunar_vfs_job_launch() on it. - * - * Return value: the newly allocated #ThunarVfsDeepCountJob or %NULL - * if an error occurs while creating the job. - **/ -ThunarVfsJob* -thunar_vfs_deep_count (ThunarVfsPath *path, - ThunarVfsDeepCountFlags flags, - GError **error) -{ - ThunarVfsJob *job; - - g_return_val_if_fail (path != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - /* allocate and launch the new job */ - job = thunar_vfs_deep_count_job_new (path, flags); - if (G_LIKELY (job != NULL)) - thunar_vfs_job_launch (job); - - return job; -} - - - -#define __THUNAR_VFS_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar-vfs/thunar-vfs.h b/thunar-vfs/thunar-vfs.h deleted file mode 100644 index cfa0827ad..000000000 --- a/thunar-vfs/thunar-vfs.h +++ /dev/null @@ -1,112 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __THUNAR_VFS_H__ -#define __THUNAR_VFS_H__ - -#define THUNAR_VFS_INSIDE_THUNAR_VFS_H - -#include <thunar-vfs/thunar-vfs-enum-types.h> -#include <thunar-vfs/thunar-vfs-info.h> -#include <thunar-vfs/thunar-vfs-interactive-job.h> -#include <thunar-vfs/thunar-vfs-job.h> -#include <thunar-vfs/thunar-vfs-mime-action.h> -#include <thunar-vfs/thunar-vfs-mime-application.h> -#include <thunar-vfs/thunar-vfs-mime-database.h> -#include <thunar-vfs/thunar-vfs-mime-handler.h> -#include <thunar-vfs/thunar-vfs-mime-info.h> -#include <thunar-vfs/thunar-vfs-monitor.h> -#include <thunar-vfs/thunar-vfs-path.h> -#include <thunar-vfs/thunar-vfs-thumb.h> -#include <thunar-vfs/thunar-vfs-user.h> -#include <thunar-vfs/thunar-vfs-util.h> -#include <thunar-vfs/thunar-vfs-volume.h> - -#undef THUNAR_VFS_INSIDE_THUNAR_VFS_H - -G_BEGIN_DECLS; - -void thunar_vfs_init (void); -void thunar_vfs_shutdown (void); - -ThunarVfsJob *thunar_vfs_listdir (ThunarVfsPath *path, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_create_file (ThunarVfsPath *path, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsJob *thunar_vfs_create_files (GList *path_list, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_copy_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsJob *thunar_vfs_copy_files (GList *source_path_list, - GList *target_path_list, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_link_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsJob *thunar_vfs_link_files (GList *source_path_list, - GList *target_path_list, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_move_file (ThunarVfsPath *source_path, - ThunarVfsPath *target_path, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsJob *thunar_vfs_move_files (GList *source_path_list, - GList *target_path_list, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_unlink_file (ThunarVfsPath *path, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsJob *thunar_vfs_unlink_files (GList *path_list, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_make_directory (ThunarVfsPath *path, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsJob *thunar_vfs_make_directories (GList *path_list, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_change_mode (ThunarVfsPath *path, - ThunarVfsFileMode dir_mask, - ThunarVfsFileMode dir_mode, - ThunarVfsFileMode file_mask, - ThunarVfsFileMode file_mode, - gboolean recursive, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_change_group (ThunarVfsPath *path, - ThunarVfsGroupId gid, - gboolean recursive, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_change_owner (ThunarVfsPath *path, - ThunarVfsUserId uid, - gboolean recursive, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -ThunarVfsJob *thunar_vfs_deep_count (ThunarVfsPath *path, - ThunarVfsDeepCountFlags flags, - GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; - -G_END_DECLS; - -#endif /* !__THUNAR_VFS_H__ */ diff --git a/thunar-vfs/thunar-vfs.symbols b/thunar-vfs/thunar-vfs.symbols deleted file mode 100644 index 641a444a7..000000000 --- a/thunar-vfs/thunar-vfs.symbols +++ /dev/null @@ -1,339 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org>. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* This file lists all exported symbols. It is used to generate - * the gobject.def file used to control exports on Windows and the - * thunar-vfs-alias.h/thunar-vfs-aliasdef.c files used to avoid PLT - * entries for * internal uses of exported functions (see - * make-thunar-vfs-alias.pl). - * - * Every symbol must be included in the right - * #ifdef IN_HEADER(sym) #endif and - * #ifdef IN_SOURCE(sym) #endif sections. - */ - -#ifdef ALL_FILES -#define IN_SOURCE(x) 1 -#define IN_HEADER(x) 1 -#endif - -/* thunar-vfs functions */ -#if IN_HEADER(__THUNAR_VFS_H__) -#if IN_SOURCE(__THUNAR_VFS_C__) -thunar_vfs_init -thunar_vfs_shutdown -thunar_vfs_listdir G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_create_file G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_create_files G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_copy_file G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_copy_files G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_link_file G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_link_files G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_move_file G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_move_files G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_unlink_file G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_unlink_files G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_make_directory G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_make_directories G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_change_mode G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_change_group G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_change_owner G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_deep_count G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -#endif -#endif - -/* thunar-vfs-config symbols */ -#if IN_HEADER(__THUNAR_VFS_CONFIG_H__) -#if IN_SOURCE(__THUNAR_VFS_CONFIG_C__) -thunar_vfs_major_version -thunar_vfs_minor_version -thunar_vfs_micro_version -thunar_vfs_check_version G_GNUC_WARN_UNUSED_RESULT -#endif -#endif - -/* ThunarVfsInfo methods */ -#if IN_HEADER(__THUNAR_VFS_INFO_H__) -#if IN_SOURCE(__THUNAR_VFS_INFO_C__) -thunar_vfs_info_get_type G_GNUC_CONST -thunar_vfs_info_new_for_path G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -#ifdef INCLUDE_INTERNAL_SYMBOLS -thunar_vfs_info_ref -#endif -thunar_vfs_info_unref -thunar_vfs_info_copy G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -#ifdef INCLUDE_INTERNAL_SYMBOLS -thunar_vfs_info_get_custom_icon G_GNUC_WARN_UNUSED_RESULT -#endif -thunar_vfs_info_set_custom_icon G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_info_get_free_space -thunar_vfs_info_get_metadata G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -#ifdef INCLUDE_INTERNAL_SYMBOLS -thunar_vfs_info_read_link G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -#endif -thunar_vfs_info_execute -thunar_vfs_info_rename -thunar_vfs_info_matches -thunar_vfs_info_list_free -#endif -#endif - -/* thunar-vfs-enum-types functions */ -#if IN_HEADER(__THUNAR_VFS_ENUM_TYPES_H__) -#if IN_SOURCE(__THUNAR_VFS_ENUM_TYPES_C__) -thunar_vfs_deep_count_flags_get_type G_GNUC_CONST -thunar_vfs_file_flags_get_type G_GNUC_CONST -thunar_vfs_file_mode_get_type G_GNUC_CONST -thunar_vfs_file_type_get_type G_GNUC_CONST -thunar_vfs_job_response_get_type G_GNUC_CONST -thunar_vfs_mime_handler_flags_get_type G_GNUC_CONST -thunar_vfs_monitor_event_get_type G_GNUC_CONST -thunar_vfs_thumb_size_get_type G_GNUC_CONST -thunar_vfs_volume_kind_get_type G_GNUC_CONST -thunar_vfs_volume_status_get_type G_GNUC_CONST -#endif -#endif - -/* ThunarVfsInteractiveJob methods */ -#if IN_HEADER(__THUNAR_VFS_INTERACTIVE_JOB_H__) -#if IN_SOURCE(__THUNAR_VFS_INTERACTIVE_JOB_C__) -thunar_vfs_interactive_job_response_get_type G_GNUC_CONST -thunar_vfs_interactive_job_get_type G_GNUC_CONST -#endif -#endif - -/* ThunarVfsJob methods */ -#if IN_HEADER(__THUNAR_VFS_JOB_H__) -#if IN_SOURCE(__THUNAR_VFS_JOB_C__) -thunar_vfs_job_get_type G_GNUC_CONST -thunar_vfs_job_launch -thunar_vfs_job_cancel -#ifdef INCLUDE_INTERNAL_SYMBOLS -thunar_vfs_job_cancelled -#endif -#endif -#endif - -/* ThunarVfsMimeAction methods */ -#if IN_HEADER(__THUNAR_VFS_MIME_ACTION_H__) -#if IN_SOURCE(__THUNAR_VFS_MIME_ACTION_C__) -thunar_vfs_mime_action_get_type G_GNUC_CONST -#endif -#endif - -/* ThunarVfsMimeApplication methods */ -#if IN_HEADER(__THUNAR_VFS_MIME_APPLICATION_H__) -#if IN_SOURCE(__THUNAR_VFS_MIME_APPLICATION_C__) -thunar_vfs_mime_application_get_type G_GNUC_CONST -thunar_vfs_mime_application_new_from_desktop_id G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_application_new_from_file G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_application_is_usercreated G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_application_get_actions G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_application_get_desktop_id G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_application_get_mime_types G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_application_hash G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_application_equal G_GNUC_WARN_UNUSED_RESULT -#endif -#endif - -/* ThunarVfsMimeDatabase methods */ -#if IN_HEADER(__THUNAR_VFS_MIME_DATABASE_H__) -#if IN_SOURCE(__THUNAR_VFS_MIME_DATABASE_C__) -thunar_vfs_mime_database_get_type G_GNUC_CONST -thunar_vfs_mime_database_get_default G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_get_info G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_get_info_for_data G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_get_info_for_name G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_get_info_for_file G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_get_infos_for_info G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_get_applications G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_get_default_application G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_set_default_application G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_add_application G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_database_remove_application G_GNUC_WARN_UNUSED_RESULT -#endif -#endif - -/* ThunarVfsMimeHandler methods */ -#if IN_HEADER(__THUNAR_VFS_MIME_HANDLER_H__) -#if IN_SOURCE(__THUNAR_VFS_MIME_HANDLER_C__) -thunar_vfs_mime_handler_get_type G_GNUC_CONST -thunar_vfs_mime_handler_get_command -thunar_vfs_mime_handler_get_flags -thunar_vfs_mime_handler_get_name -thunar_vfs_mime_handler_exec -thunar_vfs_mime_handler_exec_with_env -thunar_vfs_mime_handler_lookup_icon_name -#endif -#endif - -/* ThunarVfsMimeInfo methods */ -#if IN_HEADER(__THUNAR_VFS_MIME_INFO_H__) -#if IN_SOURCE(__THUNAR_VFS_MIME_INFO_C__) -thunar_vfs_mime_info_get_type G_GNUC_CONST -thunar_vfs_mime_info_new G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -#ifdef INCLUDE_INTERNAL_SYMBOLS -thunar_vfs_mime_info_ref -#endif -thunar_vfs_mime_info_unref -thunar_vfs_mime_info_get_comment -#ifdef INCLUDE_INTERNAL_SYMBOLS -thunar_vfs_mime_info_get_name -#endif -thunar_vfs_mime_info_get_media G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_info_get_subtype G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_mime_info_hash -thunar_vfs_mime_info_equal -thunar_vfs_mime_info_lookup_icon_name -thunar_vfs_mime_info_list_free -#endif -#endif - -/* ThunarVfsMonitor methods */ -#if IN_HEADER(__THUNAR_VFS_MONITOR_H__) -#if IN_SOURCE(__THUNAR_VFS_MONITOR_C__) -thunar_vfs_monitor_get_type G_GNUC_CONST -thunar_vfs_monitor_get_default G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_monitor_add_directory -thunar_vfs_monitor_add_file -thunar_vfs_monitor_remove -thunar_vfs_monitor_feed -thunar_vfs_monitor_wait -#endif -#endif - -/* ThunarVfsPath methods */ -#if IN_HEADER(__THUNAR_VFS_PATH_H__) -#if IN_SOURCE(__THUNAR_VFS_PATH_C__) -thunar_vfs_path_get_type G_GNUC_CONST -thunar_vfs_path_list_get_type G_GNUC_CONST -thunar_vfs_path_new G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_path_get_for_home G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_path_get_for_root G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_path_get_for_trash G_GNUC_WARN_UNUSED_RESULT -#ifdef INCLUDE_INTERNAL_SYMBOLS -thunar_vfs_path_ref -#endif -thunar_vfs_path_unref -thunar_vfs_path_hash -thunar_vfs_path_equal -thunar_vfs_path_relative G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_path_is_ancestor -thunar_vfs_path_is_home -#ifdef INCLUDE_INTERNAL_SYMBOLS -thunar_vfs_path_is_root -thunar_vfs_path_get_name -thunar_vfs_path_get_parent -thunar_vfs_path_get_scheme -#endif -thunar_vfs_path_dup_string G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_path_to_string -thunar_vfs_path_dup_uri G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_path_to_uri -thunar_vfs_path_list_from_string G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_path_list_to_string G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -#ifdef INCLUDE_INTERNAL_SYMBOLS -thunar_vfs_path_list_append G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_path_list_prepend G_GNUC_WARN_UNUSED_RESULT -#endif -thunar_vfs_path_list_copy G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_path_list_free -#endif -#endif - -/* ThunarVfsThumbFactory methods */ -#if IN_HEADER(__THUNAR_VFS_THUMB_H__) -#if IN_SOURCE(__THUNAR_VFS_THUMB_C__) -thunar_vfs_thumb_factory_get_type G_GNUC_CONST -thunar_vfs_thumb_factory_new G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_thumb_factory_lookup_thumbnail G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_thumb_factory_can_thumbnail -thunar_vfs_thumb_factory_has_failed_thumbnail -thunar_vfs_thumb_factory_generate_thumbnail G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_thumb_factory_store_thumbnail -#endif -#endif - -/* thunar-vfs-thumbnail functions */ -#if IN_HEADER(__THUNAR_VFS_THUMB_H__) -#if IN_SOURCE(__THUNAR_VFS_THUMB_C__) -thunar_vfs_thumbnail_for_path G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_thumbnail_is_valid -#endif -#endif - -/* ThunarVfsGroup/ThunarVfsUser/ThunarVfsUserManager methods */ -#if IN_HEADER(__THUNAR_VFS_USER_H__) -#if IN_SOURCE(__THUNAR_VFS_USER_C__) -thunar_vfs_group_get_type G_GNUC_CONST -thunar_vfs_group_get_id -thunar_vfs_group_get_name -thunar_vfs_user_get_type G_GNUC_CONST -thunar_vfs_user_get_groups -thunar_vfs_user_get_primary_group -thunar_vfs_user_get_id -thunar_vfs_user_get_name -thunar_vfs_user_get_real_name -thunar_vfs_user_is_me -thunar_vfs_user_manager_get_type G_GNUC_CONST -thunar_vfs_user_manager_get_default G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_user_manager_get_group_by_id G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_user_manager_get_user_by_id G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_user_manager_get_all_groups G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -#endif -#endif - -/* thunar-vfs-util functions */ -#if IN_HEADER(__THUNAR_VFS_UTIL_H__) -#if IN_SOURCE(__THUNAR_VFS_UTIL_C__) -thunar_vfs_canonicalize_filename G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_expand_filename G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT -thunar_vfs_humanize_size -#endif -#endif - -/* ThunarVfsVolume/ThunarVfsVolumeManager methods */ -#if IN_HEADER(__THUNAR_VFS_VOLUME_H__) -#if IN_SOURCE(__THUNAR_VFS_VOLUME_C__) -thunar_vfs_volume_get_type G_GNUC_CONST -thunar_vfs_volume_get_kind -thunar_vfs_volume_get_name -thunar_vfs_volume_get_status -thunar_vfs_volume_get_mount_point -thunar_vfs_volume_is_disc -thunar_vfs_volume_is_mountable -thunar_vfs_volume_is_mounted -thunar_vfs_volume_is_present -thunar_vfs_volume_is_ejectable -thunar_vfs_volume_is_removable -thunar_vfs_volume_lookup_icon_name -thunar_vfs_volume_eject -thunar_vfs_volume_mount -thunar_vfs_volume_unmount -#endif -#if IN_SOURCE(__THUNAR_VFS_VOLUME_MANAGER_C__) -thunar_vfs_volume_manager_get_type G_GNUC_CONST -thunar_vfs_volume_manager_get_default -thunar_vfs_volume_manager_get_volume_by_info -thunar_vfs_volume_manager_get_volumes -#endif -#endif - - diff --git a/thunar/Makefile.am b/thunar/Makefile.am index 644d7fb4c..e6c34a393 100644 --- a/thunar/Makefile.am +++ b/thunar/Makefile.am @@ -11,6 +11,7 @@ INCLUDES = \ -DLIBEXECDIR=\"$(libexecdir)\" \ -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \ -DTHUNAR_VERSION_API=\"$(THUNAR_VERSION_API)\" \ + -DSN_API_NOT_YET_FROZEN \ $(PLATFORM_CPPFLAGS) bin_SCRIPTS = \ @@ -37,6 +38,8 @@ Thunar_SOURCES = \ thunar-abstract-icon-view.h \ thunar-application.c \ thunar-application.h \ + thunar-browser.c \ + thunar-browser.h \ thunar-chooser-button.c \ thunar-chooser-button.h \ thunar-chooser-dialog.c \ @@ -57,6 +60,8 @@ Thunar_SOURCES = \ thunar-create-dialog.h \ thunar-debug.h \ thunar-debug.c \ + thunar-deep-count-job.h \ + thunar-deep-count-job.c \ thunar-details-view-ui.h \ thunar-details-view.c \ thunar-details-view.h \ @@ -68,6 +73,8 @@ Thunar_SOURCES = \ thunar-emblem-chooser.h \ thunar-enum-types.c \ thunar-enum-types.h \ + thunar-exec.c \ + thunar-exec.h \ thunar-file.c \ thunar-file.h \ thunar-file-monitor.c \ @@ -76,6 +83,8 @@ Thunar_SOURCES = \ thunar-folder.h \ thunar-gdk-extensions.c \ thunar-gdk-extensions.h \ + thunar-gio-extensions.c \ + thunar-gio-extensions.h \ thunar-gobject-extensions.c \ thunar-gobject-extensions.h \ thunar-gtk-extensions.c \ @@ -92,6 +101,16 @@ Thunar_SOURCES = \ thunar-icon-renderer.h \ thunar-icon-view.c \ thunar-icon-view.h \ + thunar-image.c \ + thunar-image.h \ + thunar-io-jobs.c \ + thunar-io-jobs.h \ + thunar-io-jobs-util.c \ + thunar-io-jobs-util.h \ + thunar-io-scan-directory.c \ + thunar-io-scan-directory.h \ + thunar-job.c \ + thunar-job.h \ thunar-launcher.c \ thunar-launcher.h \ thunar-launcher-ui.h \ @@ -110,6 +129,8 @@ Thunar_SOURCES = \ thunar-location-entry.h \ thunar-metafile.c \ thunar-metafile.h \ + thunar-misc-jobs.c \ + thunar-misc-jobs.h \ thunar-navigator.c \ thunar-navigator.h \ thunar-pango-extensions.c \ @@ -151,6 +172,8 @@ Thunar_SOURCES = \ thunar-shortcuts-view.h \ thunar-side-pane.c \ thunar-side-pane.h \ + thunar-simple-job.c \ + thunar-simple-job.h \ thunar-size-label.c \ thunar-size-label.h \ thunar-standard-view.c \ @@ -168,10 +191,12 @@ Thunar_SOURCES = \ thunar-throbber.h \ thunar-throbber-fallback.c \ thunar-throbber-fallback.h \ + thunar-thumbnailer.c \ + thunar-thumbnailer.h \ thunar-thumbnail-frame.c \ thunar-thumbnail-frame.h \ - thunar-thumbnail-generator.c \ - thunar-thumbnail-generator.h \ + thunar-transfer-job.c \ + thunar-transfer-job.h \ thunar-trash-action.c \ thunar-trash-action.h \ thunar-tree-model.c \ @@ -180,6 +205,8 @@ Thunar_SOURCES = \ thunar-tree-pane.h \ thunar-tree-view.c \ thunar-tree-view.h \ + thunar-user.c \ + thunar-user.h \ thunar-util.c \ thunar-util.h \ thunar-view.c \ @@ -195,7 +222,9 @@ Thunar_SOURCES = \ Thunar_CFLAGS = \ $(EXO_CFLAGS) \ $(GTHREAD_CFLAGS) \ + $(GIO_CFLAGS) \ $(LIBSM_CFLAGS) \ + $(LIBSTARTUP_NOTIFICATION_CFLAGS) \ $(PLATFORM_CFLAGS) Thunar_LDFLAGS = \ @@ -205,26 +234,30 @@ Thunar_LDFLAGS = \ Thunar_LDADD = \ $(top_builddir)/tdb/libtdb.la \ - $(top_builddir)/thunar-vfs/libthunar-vfs-$(THUNAR_VERSION_API).la \ - $(top_builddir)/thunarx/libthunarx-$(THUNAR_VERSION_API).la \ + $(top_builddir)/thunarx/libthunarx-$(THUNARX_VERSION_API).la \ $(EXO_LIBS) \ $(GTHREAD_LIBS) \ + $(GIO_LIBS) \ + $(LIBSTARTUP_NOTIFICATION_LIBS) \ $(LIBSM_LIBS) Thunar_DEPENDENCIES = \ $(top_builddir)/tdb/libtdb.la \ - $(top_builddir)/thunar-vfs/libthunar-vfs-$(THUNAR_VERSION_API).la \ - $(top_builddir)/thunarx/libthunarx-$(THUNAR_VERSION_API).la + $(top_builddir)/thunarx/libthunarx-$(THUNARX_VERSION_API).la if HAVE_DBUS thunar_built_sources += \ - thunar-dbus-service-infos.h + thunar-dbus-service-infos.h \ + thunar-thumbnailer-proxy.h \ + thunar-thumbnailer-manager-proxy.h thunar_dbus_sources = \ thunar-dbus-client.c \ thunar-dbus-client.h \ thunar-dbus-service.c \ - thunar-dbus-service.h + thunar-dbus-service.h \ + thunar-thumbnailer-proxy.h \ + thunar-thumbnailer-manager-proxy.h Thunar_CFLAGS += \ -DDBUS_API_SUBJECT_TO_CHANGE \ @@ -234,6 +267,14 @@ Thunar_LDADD += \ $(DBUS_LIBS) endif +if HAVE_GIO_UNIX +Thunar_CFLAGS += \ + $(GIO_UNIX_CFLAGS) + +Thunar_LDADD += \ + $(GIO_UNIX_LIBS) +endif + desktopdir = $(datadir)/applications desktop_in_files = thunar-settings.desktop.in desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) @@ -247,7 +288,7 @@ install-data-local: clean-local: rm -f *.core core core.* -DISTCLEANFILES = \ +DISTCLEANFILES = \ thunar-settings.desktop if MAINTAINER_MODE @@ -285,6 +326,18 @@ BUILT_SOURCES = \ if HAVE_DBUS thunar-dbus-service-infos.h: $(srcdir)/thunar-dbus-service-infos.xml Makefile dbus-binding-tool --prefix=thunar_dbus_service --mode=glib-server $(srcdir)/thunar-dbus-service-infos.xml > thunar-dbus-service-infos.h + +thunar-thumbnailer-proxy.h: $(srcdir)/thunar-thumbnailer-dbus.xml Makefile + dbus-binding-tool --mode=glib-client \ + $(srcdir)/thunar-thumbnailer-dbus.xml > thunar-thumbnailer-proxy.h \ + && sed -i -e 's/org_freedesktop_thumbnails_Thumbnailer/thunar_thumbnailer_proxy/g' \ + thunar-thumbnailer-proxy.h + +thunar-thumbnailer-manager-proxy.h: $(srcdir)/thunar-thumbnailer-manager-dbus.xml Makefile + dbus-binding-tool --mode=glib-client \ + $(srcdir)/thunar-thumbnailer-manager-dbus.xml > thunar-thumbnailer-manager-proxy.h \ + && sed -i -e 's/org_freedesktop_thumbnails_Manager/thunar_thumbnailer_manager_proxy/g' \ + thunar-thumbnailer-manager-proxy.h endif thunar-throbber-fallback.c: $(srcdir)/thunar-throbber-fallback.png Makefile @@ -335,18 +388,18 @@ thunar-marshal.c: thunar-marshal.list Makefile && rm -f xgen-tmc endif -EXTRA_DIST = \ - thunar-abstract-icon-view-ui.xml \ - thunar-dbus-service-infos.xml \ +EXTRA_DIST = \ + thunar-abstract-icon-view-ui.xml \ + thunar-dbus-service-infos.xml \ thunar-details-view-ui.xml \ thunar-launcher-ui.xml \ - thunar-location-buttons-ui.xml \ - thunar-marshal.list \ - thunar-renamer-dialog-ui.xml \ + thunar-location-buttons-ui.xml \ + thunar-marshal.list \ + thunar-renamer-dialog-ui.xml \ thunar-standard-view-ui.xml \ thunar-thumbnail-frame.png \ thunar-window-ui.xml \ - thunar-settings \ + thunar-settings \ $(desktop_in_files) # vi:set ts=8 sw=8 noet ai nocindent syntax=automake: diff --git a/thunar/main.c b/thunar/main.c index e960c09ce..6bec9bf36 100644 --- a/thunar/main.c +++ b/thunar/main.c @@ -29,11 +29,15 @@ #endif #include <glib/gstdio.h> +#ifdef HAVE_GIO_UNIX +#include <gio/gdesktopappinfo.h> +#endif #include <thunar/thunar-application.h> #include <thunar/thunar-dbus-client.h> #include <thunar/thunar-dbus-service.h> #include <thunar/thunar-gobject-extensions.h> +#include <thunar/thunar-private.h> #include <thunar/thunar-session-client.h> #include <thunar/thunar-stock.h> @@ -69,17 +73,49 @@ static GOptionEntry option_entries[] = +static gboolean +thunar_delayed_exit_check (gpointer user_data) +{ + ThunarApplication *application = user_data; + + _thunar_return_val_if_fail (THUNAR_IS_APPLICATION (application), FALSE); + + /* call this function again later if the application is still processing the + * command line arguments */ + if (thunar_application_is_processing (application)) + return TRUE; + + /* the application has processed all command line arguments. don't call + * this function again if it could load at least one of them */ + if (thunar_application_has_windows (application)) + { + return FALSE; + } + else + { + /* no command line arguments opened in Thunar, exit now */ + gtk_main_quit (); + + /* don't call this function again */ + return FALSE; + } + +} + + + int main (int argc, char **argv) { ThunarSessionClient *session_client; #ifdef HAVE_DBUS - ThunarDBusService *dbus_service; + ThunarDBusService *dbus_service = NULL; #endif ThunarApplication *application; GError *error = NULL; gchar *working_directory; gchar **filenames = NULL; + const gchar *startup_id; /* setup translation domain */ xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8"); @@ -97,6 +133,9 @@ main (int argc, char **argv) /* initialize the GThread system */ if (!g_thread_supported ()) g_thread_init (NULL); + + /* get the startup notification id */ + startup_id = g_getenv ("DESKTOP_STARTUP_ID"); /* initialize Gtk+ */ if (!gtk_init_with_args (&argc, &argv, _("[FILES...]"), option_entries, GETTEXT_PACKAGE, &error)) @@ -129,6 +168,11 @@ main (int argc, char **argv) return EXIT_SUCCESS; } +#ifdef HAVE_GIO_UNIX + /* set desktop environment for app infos */ + g_desktop_app_info_set_desktop_env ("XFCE"); +#endif + /* register additional transformation functions */ thunar_g_initialize_transformations (); @@ -176,12 +220,9 @@ main (int argc, char **argv) #ifdef HAVE_DBUS /* check if we can reuse an existing instance */ - if ((!opt_bulk_rename && filenames != NULL && thunar_dbus_client_launch_files (working_directory, filenames, NULL, NULL)) - || (opt_bulk_rename && thunar_dbus_client_bulk_rename (working_directory, filenames, TRUE, NULL, NULL))) + if ((!opt_bulk_rename && filenames != NULL && thunar_dbus_client_launch_files (working_directory, filenames, NULL, startup_id, NULL)) + || (opt_bulk_rename && thunar_dbus_client_bulk_rename (working_directory, filenames, TRUE, NULL, startup_id, NULL))) { - /* stop any running startup notification */ - gdk_notify_startup_complete (); - /* that worked, let's get outa here */ g_free (working_directory); g_strfreev (filenames); @@ -189,9 +230,6 @@ main (int argc, char **argv) } #endif - /* initialize the ThunarVFS library */ - thunar_vfs_init (); - /* initialize the thunar stock items/icons */ thunar_stock_init (); @@ -210,16 +248,15 @@ main (int argc, char **argv) if (G_UNLIKELY (opt_bulk_rename)) { /* try to open the bulk rename dialog */ - if (!thunar_application_bulk_rename (application, working_directory, filenames, TRUE, NULL, &error)) + if (!thunar_application_bulk_rename (application, working_directory, filenames, TRUE, NULL, startup_id, &error)) goto error0; } - else if (filenames != NULL && !thunar_application_process_filenames (application, working_directory, filenames, NULL, &error)) + else if (filenames != NULL && !thunar_application_process_filenames (application, working_directory, filenames, NULL, startup_id, &error)) { /* we failed to process the filenames or the bulk rename failed */ error0: g_fprintf (stderr, "Thunar: %s\n", error->message); g_object_unref (G_OBJECT (application)); - thunar_vfs_shutdown (); g_error_free (error); return EXIT_FAILURE; } @@ -231,22 +268,31 @@ error0: /* connect to the session manager */ session_client = thunar_session_client_new (opt_sm_client_id); - /* do not enter the main loop, unless we have atleast one window or we are in daemon mode */ - if (thunar_application_has_windows (application) || thunar_application_get_daemon (application)) + /* check if the application should run as a daemon */ + if (thunar_application_get_daemon (application)) { - /* attach the D-BUS service */ #ifdef HAVE_DBUS + /* attach the D-Bus service */ dbus_service = g_object_new (THUNAR_TYPE_DBUS_SERVICE, NULL); #endif + } + else + { + /* processing the command line arguments is done asynchronously. Thus, we + * schedule an idle source which repeatedly checks whether we are done + * processing. Once we're done, it'll make the application quit if there + * are no open windows */ + g_idle_add_full (G_PRIORITY_LOW, thunar_delayed_exit_check, + g_object_ref (application), g_object_unref); + } - /* enter the main loop */ - gtk_main (); + /* enter the main loop */ + gtk_main (); - /* detach the D-BUS service */ #ifdef HAVE_DBUS - g_object_unref (G_OBJECT (dbus_service)); + if (dbus_service != NULL) + g_object_unref (G_OBJECT (dbus_service)); #endif - } /* disconnect from the session manager */ g_object_unref (G_OBJECT (session_client)); @@ -254,8 +300,5 @@ error0: /* release the application reference */ g_object_unref (G_OBJECT (application)); - /* shutdown the VFS library */ - thunar_vfs_shutdown (); - return EXIT_SUCCESS; } diff --git a/thunar/thunar-abstract-icon-view.c b/thunar/thunar-abstract-icon-view.c index 62e96ab01..7c4237591 100644 --- a/thunar/thunar-abstract-icon-view.c +++ b/thunar/thunar-abstract-icon-view.c @@ -642,10 +642,8 @@ thunar_abstract_icon_view_expose_event (ExoIconView *view, GtkAction *action = NULL; GdkPixbuf *stock_icon = NULL; gchar *stock_id; -#if GTK_CHECK_VERSION(2,7,1) GdkColor bg; cairo_t *cr; -#endif _thunar_return_val_if_fail (EXO_IS_ICON_VIEW (view), FALSE); _thunar_return_val_if_fail (THUNAR_IS_ABSTRACT_ICON_VIEW (abstract_icon_view), FALSE); @@ -654,7 +652,6 @@ thunar_abstract_icon_view_expose_event (ExoIconView *view, _thunar_return_val_if_fail (abstract_icon_view->priv->gesture_release_id > 0, FALSE); /* shade the abstract_icon view content while performing mouse gestures */ -#if GTK_CHECK_VERSION(2,7,1) cr = gdk_cairo_create (event->window); bg = GTK_WIDGET (view)->style->base[GTK_STATE_NORMAL]; cairo_set_source_rgba (cr, bg.red / 65535.0, bg.green / 65535.0, bg.blue / 65535.0, 0.7); @@ -662,7 +659,6 @@ thunar_abstract_icon_view_expose_event (ExoIconView *view, cairo_clip (cr); cairo_paint (cr); cairo_destroy (cr); -#endif /* determine the gesture action */ action = thunar_abstract_icon_view_gesture_action (abstract_icon_view); diff --git a/thunar/thunar-application.c b/thunar/thunar-application.c index c30d43ad5..0d64a1dca 100644 --- a/thunar/thunar-application.c +++ b/thunar/thunar-application.c @@ -2,6 +2,7 @@ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> * Copyright (c) 2005 Jeff Franks <jcfranks@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -39,6 +40,7 @@ #include <thunar/thunar-dialogs.h> #include <thunar/thunar-gdk-extensions.h> #include <thunar/thunar-gobject-extensions.h> +#include <thunar/thunar-io-jobs.h> #include <thunar/thunar-preferences.h> #include <thunar/thunar-private.h> #include <thunar/thunar-progress-dialog.h> @@ -47,10 +49,9 @@ -/* Prototype for the Thunar-VFS job launchers */ -typedef ThunarVfsJob *(*Launcher) (GList *source_path_list, - GList *target_path_list, - GError **error); +/* Prototype for the Thunar job launchers */ +typedef ThunarJob *(*Launcher) (GList *source_path_list, + GList *target_path_list); @@ -63,56 +64,53 @@ enum -static void thunar_application_class_init (ThunarApplicationClass *klass); -static void thunar_application_init (ThunarApplication *application); -static void thunar_application_finalize (GObject *object); -static void thunar_application_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void thunar_application_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void thunar_application_collect_and_launch (ThunarApplication *application, - gpointer parent, - const gchar *icon_name, - const gchar *title, - Launcher launcher, - GList *source_path_list, - ThunarVfsPath *target_path, - GClosure *new_files_closure); -static void thunar_application_launch (ThunarApplication *application, - gpointer parent, - const gchar *icon_name, - const gchar *title, - Launcher launcher, - GList *source_path_list, - GList *target_path_list, - GClosure *new_files_closure); -static GtkWidget *thunar_application_open_window_with_role (ThunarApplication *application, - const gchar *role, - ThunarFile *directory, - GdkScreen *screen); -static void thunar_application_window_destroyed (GtkWidget *window, - ThunarApplication *application); -static void thunar_application_volman_device_added (ThunarVfsVolumeManager *volume_manager, - const gchar *udi, - ThunarApplication *application); -static void thunar_application_volman_device_removed (ThunarVfsVolumeManager *volume_manager, - const gchar *udi, - ThunarApplication *application); -static void thunar_application_volman_device_eject (ThunarVfsVolumeManager *volume_manager, - const gchar *udi, - ThunarApplication *application); -static gboolean thunar_application_volman_idle (gpointer user_data); -static void thunar_application_volman_idle_destroy (gpointer user_data); -static void thunar_application_volman_watch (GPid pid, - gint status, - gpointer user_data); -static void thunar_application_volman_watch_destroy (gpointer user_data); -static gboolean thunar_application_show_dialogs (gpointer user_data); -static void thunar_application_show_dialogs_destroy (gpointer user_data); +static void thunar_application_class_init (ThunarApplicationClass *klass); +static void thunar_application_init (ThunarApplication *application); +static void thunar_application_finalize (GObject *object); +static void thunar_application_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void thunar_application_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void thunar_application_collect_and_launch (ThunarApplication *application, + gpointer parent, + const gchar *icon_name, + const gchar *title, + Launcher launcher, + GList *source_file_list, + GFile *target_file, + GClosure *new_files_closure); +static void thunar_application_launch (ThunarApplication *application, + gpointer parent, + const gchar *icon_name, + const gchar *title, + Launcher launcher, + GList *source_path_list, + GList *target_path_list, + GClosure *new_files_closure); +static void thunar_application_window_destroyed (GtkWidget *window, + ThunarApplication *application); +static void thunar_application_drive_connected (GVolumeMonitor *volume_monitor, + GDrive *drive, + ThunarApplication *application); +static void thunar_application_drive_disconnected (GVolumeMonitor *volume_monitor, + GDrive *drive, + ThunarApplication *application); +static void thunar_application_drive_eject (GVolumeMonitor *volume_monitor, + GDrive *drive, + ThunarApplication *application); +static gboolean thunar_application_volman_idle (gpointer user_data); +static void thunar_application_volman_idle_destroy (gpointer user_data); +static void thunar_application_volman_watch (GPid pid, + gint status, + gpointer user_data); +static void thunar_application_volman_watch_destroy (gpointer user_data); +static gboolean thunar_application_show_dialogs (gpointer user_data); +static void thunar_application_show_dialogs_destroy (gpointer user_data); +static void thunar_application_process_files (ThunarApplication *application); @@ -132,16 +130,20 @@ struct _ThunarApplication guint show_dialogs_timer_id; - /* the volume manager support */ - ThunarVfsVolumeManager *volman; - GSList *volman_udis; - guint volman_idle_id; - guint volman_watch_id; + GVolumeMonitor *volume_monitor; + + GSList *volman_udis; + guint volman_idle_id; + guint volman_watch_id; + + GList *files_to_launch; }; static GObjectClass *thunar_application_parent_class; +static GQuark thunar_application_screen_quark; +static GQuark thunar_application_startup_id_quark; @@ -179,6 +181,12 @@ thunar_application_class_init (ThunarApplicationClass *klass) { GObjectClass *gobject_class; + /* pre-allocate the required quarks */ + thunar_application_screen_quark = + g_quark_from_static_string ("thunar-application-screen"); + thunar_application_startup_id_quark = + g_quark_from_static_string ("thunar-application-startup-id"); + /* determine the parent type class */ thunar_application_parent_class = g_type_class_peek_parent (klass); @@ -214,6 +222,8 @@ thunar_application_init (ThunarApplication *application) /* initialize the application */ application->preferences = thunar_preferences_get (); + application->files_to_launch = NULL; + /* check if we have a saved accel map */ path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, "Thunar/accels.scm"); if (G_LIKELY (path != NULL)) @@ -224,16 +234,12 @@ thunar_application_init (ThunarApplication *application) } /* connect to the volume manager */ - application->volman = thunar_vfs_volume_manager_get_default (); + application->volume_monitor = g_volume_monitor_get (); - /* check if the volume manager supports HAL */ - if (g_signal_lookup ("device-added", G_OBJECT_TYPE (application->volman)) != 0) - { - /* connect the volume manager support callbacks (used to spawn thunar-volman appropriately) */ - g_signal_connect (G_OBJECT (application->volman), "device-added", G_CALLBACK (thunar_application_volman_device_added), application); - g_signal_connect (G_OBJECT (application->volman), "device-removed", G_CALLBACK (thunar_application_volman_device_removed), application); - g_signal_connect (G_OBJECT (application->volman), "device-eject", G_CALLBACK (thunar_application_volman_device_eject), application); - } + /* connect the volume manager support callbacks (used to spawn thunar-volman appropriately) */ + g_signal_connect (application->volume_monitor, "drive-connected", G_CALLBACK (thunar_application_drive_connected), application); + g_signal_connect (application->volume_monitor, "drive-disconnected", G_CALLBACK (thunar_application_drive_disconnected), application); + g_signal_connect (application->volume_monitor, "drive-eject-button", G_CALLBACK (thunar_application_drive_eject), application); } @@ -245,6 +251,9 @@ thunar_application_finalize (GObject *object) gchar *path; GList *lp; + /* unqueue all files waiting to be processed */ + thunar_file_list_free (application->files_to_launch); + /* save the current accel map */ path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "Thunar/accels.scm", TRUE); if (G_LIKELY (path != NULL)) @@ -266,8 +275,8 @@ thunar_application_finalize (GObject *object) g_slist_foreach (application->volman_udis, (GFunc) g_free, NULL); g_slist_free (application->volman_udis); - /* disconnect from the volume manager */ - g_object_unref (G_OBJECT (application->volman)); + /* disconnect from the volume monitor */ + g_object_unref (application->volume_monitor); /* drop any running "show dialogs" timer */ if (G_UNLIKELY (application->show_dialogs_timer_id != 0)) @@ -339,66 +348,38 @@ thunar_application_collect_and_launch (ThunarApplication *application, const gchar *icon_name, const gchar *title, Launcher launcher, - GList *source_path_list, - ThunarVfsPath *target_path, + GList *source_file_list, + GFile *target_file, GClosure *new_files_closure) { - ThunarVfsInfo *info; - ThunarVfsPath *path; - GError *err = NULL; - GList *target_path_list = NULL; - GList *lp; - gchar *original_path; - gchar *original_name; + GFile *file; + GError *err = NULL; + GList *target_file_list = NULL; + GList *lp; + gchar *basename; /* check if we have anything to operate on */ - if (G_UNLIKELY (source_path_list == NULL)) + if (G_UNLIKELY (source_file_list == NULL)) return; /* generate the target path list */ - for (lp = g_list_last (source_path_list); err == NULL && lp != NULL; lp = lp->prev) + for (lp = g_list_last (source_file_list); err == NULL && lp != NULL; lp = lp->prev) { - /* reset the path */ - path = NULL; - /* verify that we're not trying to collect a root node */ - if (G_UNLIKELY (thunar_vfs_path_is_root (lp->data))) + if (G_UNLIKELY (thunar_g_file_is_root (lp->data))) { /* tell the user that we cannot perform the requested operation */ g_set_error (&err, G_FILE_ERROR, G_FILE_ERROR_INVAL, "%s", g_strerror (EINVAL)); } else { - /* check if we're copying from a location in the trash */ - if (G_UNLIKELY (thunar_vfs_path_get_scheme (lp->data) == THUNAR_VFS_PATH_SCHEME_TRASH)) - { - /* determine the info for the trashed resource */ - info = thunar_vfs_info_new_for_path (lp->data, NULL); - if (G_LIKELY (info != NULL)) - { - /* try to use the basename of the original path */ - original_path = thunar_vfs_info_get_metadata (info, THUNAR_VFS_INFO_METADATA_TRASH_ORIGINAL_PATH, NULL); - if (G_LIKELY (original_path != NULL)) - { - /* g_path_get_basename() may return '.' or '/' */ - original_name = g_path_get_basename (original_path); - if (strcmp (original_name, ".") != 0 && strchr (original_name, G_DIR_SEPARATOR) == NULL) - path = thunar_vfs_path_relative (target_path, original_name); - g_free (original_name); - g_free (original_path); - } - - /* release the info */ - thunar_vfs_info_unref (info); - } - } + basename = g_file_get_basename (lp->data); + file = g_file_resolve_relative_path (target_file, basename); + g_free (basename); - /* fallback to the path's basename */ - if (G_LIKELY (path == NULL)) - path = thunar_vfs_path_relative (target_path, thunar_vfs_path_get_name (lp->data)); - - /* add to the target path list */ - target_path_list = g_list_prepend (target_path_list, path); + /* add to the target file list */ + target_file_list = thunar_g_file_list_prepend (target_file_list, file); + g_object_unref (file); } } @@ -415,11 +396,11 @@ thunar_application_collect_and_launch (ThunarApplication *application, { /* launch the operation */ thunar_application_launch (application, parent, icon_name, title, launcher, - source_path_list, target_path_list, new_files_closure); + source_file_list, target_file_list, new_files_closure); } /* release the target path list */ - thunar_vfs_path_list_free (target_path_list); + thunar_g_file_list_free (target_file_list); } @@ -430,15 +411,14 @@ thunar_application_launch (ThunarApplication *application, const gchar *icon_name, const gchar *title, Launcher launcher, - GList *source_path_list, - GList *target_path_list, + GList *source_file_list, + GList *target_file_list, GClosure *new_files_closure) { - ThunarVfsJob *job; - GtkWindow *window; - GtkWidget *dialog; - GdkScreen *screen; - GError *error = NULL; + GtkWindow *window; + GtkWidget *dialog; + GdkScreen *screen; + ThunarJob *job; _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent)); @@ -446,82 +426,41 @@ thunar_application_launch (ThunarApplication *application, screen = thunar_util_parse_parent (parent, &window); /* try to allocate a new job for the operation */ - job = (*launcher) (source_path_list, target_path_list, &error); - if (G_UNLIKELY (job == NULL)) - { - /* display an error message to the user */ - thunar_dialogs_show_error (parent, error, _("Failed to launch operation")); - - /* release the error */ - g_error_free (error); - } - else - { - /* connect the "new-files" closure (if any) */ - if (G_LIKELY (new_files_closure != NULL)) - g_signal_connect_closure (G_OBJECT (job), "new-files", new_files_closure, FALSE); - - /* allocate a progress dialog for the job */ - dialog = g_object_new (THUNAR_TYPE_PROGRESS_DIALOG, - "icon-name", icon_name, - "title", title, - "job", job, - "screen", screen, - NULL); - - /* connect to the parent (if any) */ - if (G_LIKELY (window != NULL)) - gtk_window_set_transient_for (GTK_WINDOW (dialog), window); - - /* be sure to destroy the dialog when the job is done */ - g_signal_connect_after (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), dialog); - - /* hook up the dialog window */ - thunar_application_take_window (application, GTK_WINDOW (dialog)); - - /* Set up a timer to show the dialog, to make sure we don't - * just popup and destroy a dialog for a very short job. - */ - if (G_LIKELY (application->show_dialogs_timer_id == 0)) - { - application->show_dialogs_timer_id = g_timeout_add_full (G_PRIORITY_DEFAULT, 750, thunar_application_show_dialogs, - application, thunar_application_show_dialogs_destroy); - } - - /* drop our reference on the job */ - g_object_unref (G_OBJECT (job)); - } -} - - - -static GtkWidget* -thunar_application_open_window_with_role (ThunarApplication *application, - const gchar *role, - ThunarFile *directory, - GdkScreen *screen) -{ - GtkWidget *window; - - if (G_UNLIKELY (screen == NULL)) - screen = gdk_screen_get_default (); - - /* allocate the window */ - window = g_object_new (THUNAR_TYPE_WINDOW, - "role", role, + job = (*launcher) (source_file_list, target_file_list); + + /* connect the "new-files" closure (if any) */ + if (G_LIKELY (new_files_closure != NULL)) + g_signal_connect_closure (job, "new-files", new_files_closure, FALSE); + + /* allocate a progress dialog for the job */ + dialog = g_object_new (THUNAR_TYPE_PROGRESS_DIALOG, + "icon-name", icon_name, + "title", title, + "job", job, "screen", screen, NULL); - /* hook up the window */ - thunar_application_take_window (application, GTK_WINDOW (window)); + /* connect to the parent (if any) */ + if (G_LIKELY (window != NULL)) + gtk_window_set_transient_for (GTK_WINDOW (dialog), window); - /* show the new window */ - gtk_widget_show (window); + /* be sure to destroy the dialog when the job is done */ + g_signal_connect_after (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), dialog); - /* change the directory */ - thunar_window_set_current_directory (THUNAR_WINDOW (window), directory); + /* hook up the dialog window */ + thunar_application_take_window (application, GTK_WINDOW (dialog)); - return window; + /* Set up a timer to show the dialog, to make sure we don't + * just popup and destroy a dialog for a very short job. + */ + if (G_LIKELY (application->show_dialogs_timer_id == 0)) + { + application->show_dialogs_timer_id = g_timeout_add_full (G_PRIORITY_DEFAULT, 750, thunar_application_show_dialogs, + application, thunar_application_show_dialogs_destroy); + } + + /* drop our reference on the job */ + g_object_unref (job); } @@ -546,16 +485,29 @@ thunar_application_window_destroyed (GtkWidget *window, static void -thunar_application_volman_device_added (ThunarVfsVolumeManager *volume_manager, - const gchar *udi, - ThunarApplication *application) +thunar_application_drive_connected (GVolumeMonitor *volume_monitor, + GDrive *drive, + ThunarApplication *application) { - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager)); - _thunar_return_if_fail (application->volman == volume_manager); + gchar *udi = NULL; + + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (application->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_DRIVE (drive)); _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); - /* schedule the UDI for processing (last come, first served) */ - application->volman_udis = g_slist_prepend (application->volman_udis, g_strdup (udi)); + /* determine the HAL UDI for this drive */ + udi = g_drive_get_identifier (drive, G_VOLUME_IDENTIFIER_KIND_HAL_UDI); + + /* check if we have a UDI */ + if (G_LIKELY (udi != NULL)) + { + /* only insert the UDI if we don't have it already. free it otherwise */ + if (g_slist_find_custom (application->volman_udis, udi, (GCompareFunc) g_utf8_collate) == NULL) + application->volman_udis = g_slist_prepend (application->volman_udis, udi); + else + g_free (udi); + } /* check if there's currently no active or scheduled handler */ if (G_LIKELY (application->volman_idle_id == 0 && application->volman_watch_id == 0)) @@ -569,64 +521,86 @@ thunar_application_volman_device_added (ThunarVfsVolumeManager *volume_manager, static void -thunar_application_volman_device_removed (ThunarVfsVolumeManager *volume_manager, - const gchar *udi, - ThunarApplication *application) +thunar_application_drive_disconnected (GVolumeMonitor *volume_monitor, + GDrive *drive, + ThunarApplication *application) { GSList *lp; + gchar *udi; - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager)); - _thunar_return_if_fail (application->volman == volume_manager); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (application->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_DRIVE (drive)); _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); - /* check if this is one of the pending UDIs */ - for (lp = application->volman_udis; lp != NULL; lp = lp->next) - if (G_UNLIKELY (strcmp (lp->data, udi) == 0)) - { - /* release the UDI */ - g_free (lp->data); + /* determine the HAL UDI for this drive */ + udi = g_drive_get_identifier (drive, G_VOLUME_IDENTIFIER_KIND_HAL_UDI); - /* drop the UDI from the list of pending device UDIs */ - application->volman_udis = g_slist_delete_link (application->volman_udis, lp); - break; - } + /* check if we have a UDI */ + if (G_LIKELY (udi != NULL)) + { + /* look for the UDI in the list of pending UDIs */ + lp = g_slist_find_custom (application->volman_udis, udi, (GCompareFunc) g_utf8_collate); + + if (G_LIKELY (lp != NULL)) + { + /* free the UDI string */ + g_free (lp->data); + + /* drop the UDI from the list of pending device UDIs */ + application->volman_udis = g_slist_delete_link (application->volman_udis, lp); + } + + g_free (udi); + } } static void -thunar_application_volman_device_eject (ThunarVfsVolumeManager *volume_manager, - const gchar *udi, - ThunarApplication *application) +thunar_application_drive_eject (GVolumeMonitor *volume_monitor, + GDrive *drive, + ThunarApplication *application) { GdkScreen *screen; GError *err = NULL; gchar *argv[4]; + gchar *udi; - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager)); - _thunar_return_if_fail (application->volman == volume_manager); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (application->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_DRIVE (drive)); _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); - /* generate the argument list for exo-eject */ - argv[0] = (gchar *) "exo-eject"; - argv[1] = (gchar *) "-h"; - argv[2] = (gchar *) udi; - argv[3] = NULL; + /* determine the HAL UDI for this device */ + udi = g_drive_get_identifier (drive, G_VOLUME_IDENTIFIER_KIND_HAL_UDI); - /* locate the currently active screen (the one with the pointer) */ - screen = thunar_gdk_screen_get_active (); - - /* try to spawn the volman on the active screen */ - if (!gdk_spawn_on_screen (screen, NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &err)) + /* check if we have a UDI */ + if (G_LIKELY (udi != NULL)) { - /* failed to launch exo-eject, inform the user about this */ - thunar_dialogs_show_error (screen, err, _("Failed to execute \"%s\""), "exo-eject"); - g_error_free (err); - } - else - { - /* we most probably removed the device */ - thunar_application_volman_device_removed (volume_manager, udi, application); + /* generate the argument list for exo-eject */ + argv[0] = (gchar *) "exo-eject"; + argv[1] = (gchar *) "-h"; + argv[2] = (gchar *) udi; + argv[3] = NULL; + + /* locate the currently active screen (the one with the pointer) */ + screen = thunar_gdk_screen_get_active (); + + /* try to spawn the volume_monitor on the active screen */ + if (!gdk_spawn_on_screen (screen, NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &err)) + { + /* failed to launch exo-eject, inform the user about this */ + thunar_dialogs_show_error (screen, err, _("Failed to execute \"%s\""), "exo-eject"); + g_error_free (err); + } + else + { + /* we most probably removed the device */ + thunar_application_drive_disconnected (volume_monitor, drive, application); + } + + g_free (udi); } } @@ -929,6 +903,8 @@ thunar_application_take_window (ThunarApplication *application, * @directory : the directory to open. * @screen : the #GdkScreen on which to open the window or %NULL * to open on the default screen. + * @startup_id : startup id from startup notification passed along + * with dbus to make focus stealing work properly. * * Opens a new #ThunarWindow for @application, displaying the * given @directory. @@ -938,7 +914,8 @@ thunar_application_take_window (ThunarApplication *application, GtkWidget* thunar_application_open_window (ThunarApplication *application, ThunarFile *directory, - GdkScreen *screen) + GdkScreen *screen, + const gchar *startup_id) { GtkWidget *window; gchar *role; @@ -947,11 +924,34 @@ thunar_application_open_window (ThunarApplication *application, _thunar_return_val_if_fail (THUNAR_IS_FILE (directory), NULL); _thunar_return_val_if_fail (screen == NULL || GDK_IS_SCREEN (screen), NULL); + if (G_UNLIKELY (screen == NULL)) + screen = gdk_screen_get_default (); + /* generate a unique role for the new window (for session management) */ role = g_strdup_printf ("Thunar-%u-%u", (guint) time (NULL), (guint) g_random_int ()); - window = thunar_application_open_window_with_role (application, role, directory, screen); + + /* allocate the window */ + window = g_object_new (THUNAR_TYPE_WINDOW, + "role", role, + "screen", screen, + NULL); + + /* cleanup */ g_free (role); + /* set the startup id */ + if (startup_id != NULL) + gtk_window_set_startup_id (GTK_WINDOW (window), startup_id); + + /* hook up the window */ + thunar_application_take_window (application, GTK_WINDOW (window)); + + /* show the new window */ + gtk_widget_show (window); + + /* change the directory */ + thunar_window_set_current_directory (THUNAR_WINDOW (window), directory); + return window; } @@ -969,6 +969,8 @@ thunar_application_open_window (ThunarApplication *application, * application. * @screen : the #GdkScreen on which to rename the @filenames or %NULL * to use the default #GdkScreen. + * @startup_id : startup notification id to properly finish startup notification + * and focus the window when focus stealing is enabled or %NULL. * @error : return location for errors or %NULL. * * Tries to popup the bulk rename dialog. @@ -981,6 +983,7 @@ thunar_application_bulk_rename (ThunarApplication *application, gchar **filenames, gboolean standalone, GdkScreen *screen, + const gchar *startup_id, GError **error) { ThunarFile *current_directory = NULL; @@ -1032,7 +1035,7 @@ thunar_application_bulk_rename (ThunarApplication *application, if (G_LIKELY (filenames[n] == NULL)) { /* popup the bulk rename dialog */ - thunar_show_renamer_dialog (screen, current_directory, file_list, standalone); + thunar_show_renamer_dialog (screen, current_directory, file_list, standalone, startup_id); /* we succeed */ result = TRUE; @@ -1047,6 +1050,116 @@ thunar_application_bulk_rename (ThunarApplication *application, +static void +thunar_application_process_files_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + ThunarApplication *application = THUNAR_APPLICATION (user_data); + ThunarFile *file; + GdkScreen *screen; + GError *error = NULL; + const gchar *startup_id; + + _thunar_return_if_fail (G_IS_FILE (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); + _thunar_return_if_fail (application->files_to_launch != NULL); + _thunar_return_if_fail (THUNAR_IS_FILE (application->files_to_launch->data)); + + /* finish mounting the volume */ + if (!g_file_mount_enclosing_volume_finish (G_FILE (object), result, &error)) + { + /* ignore already mounted and not supported errors */ + if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_ALREADY_MOUNTED) + g_clear_error (&error); + else if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_SUPPORTED) + g_clear_error (&error); + } + + /* get the current file */ + file = THUNAR_FILE (application->files_to_launch->data); + + /* determine and reset the screen of the file */ + screen = g_object_get_qdata (G_OBJECT (file), thunar_application_screen_quark); + g_object_set_qdata (G_OBJECT (file), thunar_application_screen_quark, NULL); + + /* determine and the startup id of the file */ + startup_id = g_object_get_qdata (G_OBJECT (file), thunar_application_startup_id_quark); + + /* check if mounting succeeded */ + if (error == NULL) + { + /* try to open the file or directory */ + thunar_file_launch (file, screen, startup_id, &error); + } + + /* unset the startup id */ + if (startup_id != NULL) + g_object_set_qdata (G_OBJECT (file), thunar_application_startup_id_quark, NULL); + + if (error != NULL) + { + /* tell the user that we were unable to launch the file specified */ + thunar_dialogs_show_error (screen, error, _("Failed to open \"%s\""), + thunar_file_get_display_name (file)); + + /* stop processing files */ + thunar_file_list_free (application->files_to_launch); + application->files_to_launch = NULL; + } + else + { + /* release the file */ + g_object_unref (file); + + /* remove the file item from the list */ + application->files_to_launch = g_list_delete_link (application->files_to_launch, + application->files_to_launch); + + /* continue processing the next file */ + thunar_application_process_files (application); + } +} + + + +static void +thunar_application_process_files (ThunarApplication *application) +{ + GMountOperation *mount_operation; + ThunarFile *file; + GdkScreen *screen; + GFile *location; + + _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); + + /* don't do anything if no files are to be processed */ + if (application->files_to_launch == NULL) + return; + + /* get the next file */ + file = THUNAR_FILE (application->files_to_launch->data); + + /* create a GTK+ mount operation */ + mount_operation = gtk_mount_operation_new (NULL); + screen = g_object_get_qdata (G_OBJECT (file), thunar_application_screen_quark); + if (screen != NULL) + gtk_mount_operation_set_screen (GTK_MOUNT_OPERATION (mount_operation), screen); + + /* determine the location of the file */ + location = thunar_file_get_file (file); + + /* try to mount the enclosing volume asynchronously. Thunar will launch files + * that are accessible in the mount callback */ + g_file_mount_enclosing_volume (location, G_MOUNT_MOUNT_NONE, + mount_operation, NULL, + thunar_application_process_files_finish, + application); +} + + + /** * thunar_application_process_filenames: * @application : a #ThunarApplication. @@ -1057,6 +1170,8 @@ thunar_application_bulk_rename (ThunarApplication *application, * @working_directory. * @screen : the #GdkScreen on which to process the @filenames, or %NULL to * use the default screen. + * @startup_id : startup id to finish startup notification and properly focus the + * window when focus stealing is enabled or %NULL. * @error : return location for errors or %NULL. * * Tells @application to process the given @filenames and launch them appropriately. @@ -1068,6 +1183,7 @@ thunar_application_process_filenames (ThunarApplication *application, const gchar *working_directory, gchar **filenames, GdkScreen *screen, + const gchar *startup_id, GError **error) { ThunarFile *file; @@ -1103,37 +1219,58 @@ thunar_application_process_filenames (ThunarApplication *application, /* verify that we have a valid file */ if (G_LIKELY (file != NULL)) - file_list = g_list_append (file_list, file); + { + file_list = g_list_append (file_list, file); + } else - goto failure; + { + /* tell the user that we were unable to launch the file specified */ + thunar_dialogs_show_error (screen, derror, _("Failed to open \"%s\""), + filenames[n]); + + g_set_error (error, derror->domain, derror->code, + _("Failed to open \"%s\": %s"), filenames[n], derror->message); + g_error_free (derror); + + thunar_file_list_free (file_list); + + return FALSE; + } } - /* ok, let's try to launch the given files then */ + /* loop over all files */ for (lp = file_list; lp != NULL; lp = lp->next) { - /* try to launch this file, display an error dialog if that fails */ - if (!thunar_file_launch (lp->data, screen, &derror)) - { - /* tell the user that we were unable to launch the file specified on the cmdline */ - thunar_dialogs_show_error (screen, derror, _("Failed to open \"%s\""), thunar_file_get_display_name (lp->data)); - g_error_free (derror); - break; - } + /* remember the screen to launch the file on */ + g_object_set_qdata (G_OBJECT (lp->data), thunar_application_screen_quark, screen); + + /* remember the startup id to set on the window */ + if (G_LIKELY (startup_id != NULL && *startup_id != '\0')) + g_object_set_qdata_full (G_OBJECT (lp->data), thunar_application_startup_id_quark, + g_strdup (startup_id), (GDestroyNotify) g_free); + + /* append the file to the list of files we need to launch */ + application->files_to_launch = g_list_append (application->files_to_launch, + lp->data); } - /* release all files */ - thunar_file_list_free (file_list); + /* start processing files if we have any to launch */ + if (application->files_to_launch != NULL) + thunar_application_process_files (application); + + /* free the file list */ + g_list_free (file_list); return TRUE; +} -failure: - /* tell the user that we were unable to launch the file specified on the cmdline */ - thunar_dialogs_show_error (screen, derror, _("Failed to open \"%s\""), filenames[n]); - g_set_error (error, derror->domain, derror->code, _("Failed to open \"%s\": %s"), filenames[n], derror->message); - thunar_file_list_free (file_list); - g_error_free (derror); - return FALSE; + +gboolean +thunar_application_is_processing (ThunarApplication *application) +{ + _thunar_return_val_if_fail (THUNAR_IS_APPLICATION (application), FALSE); + return application->files_to_launch != NULL; } @@ -1142,33 +1279,33 @@ failure: * thunar_application_copy_to: * @application : a #ThunarApplication. * @parent : a #GdkScreen, a #GtkWidget or %NULL. - * @source_path_list : the list of #ThunarVfsPath<!---->s that should be copied. - * @target_path_list : the list of #ThunarVfsPath<!---->s where files should be copied to. + * @source_file_list : the list of #GFile<!---->s that should be copied. + * @target_file_list : the list of #GFile<!---->s where files should be copied to. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the - * list of #ThunarVfsPath<!---->s created by the job, or + * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * - * Copies all files from @source_path_list to their locations specified in - * @target_path_list. + * Copies all files from @source_file_list to their locations specified in + * @target_file_list. * - * @source_path_list and @target_path_list must be of the same length. + * @source_file_list and @target_file_list must be of the same length. **/ void thunar_application_copy_to (ThunarApplication *application, gpointer parent, - GList *source_path_list, - GList *target_path_list, + GList *source_file_list, + GList *target_file_list, GClosure *new_files_closure) { - _thunar_return_if_fail (g_list_length (source_path_list) == g_list_length (target_path_list)); + _thunar_return_if_fail (g_list_length (source_file_list) == g_list_length (target_file_list)); _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent)); _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); /* launch the operation */ thunar_application_launch (application, parent, "stock_folder-copy", - _("Copying files..."), thunar_vfs_copy_files, - source_path_list, target_path_list, new_files_closure); + _("Copying files..."), thunar_io_jobs_copy_files, + source_file_list, target_file_list, new_files_closure); } @@ -1177,31 +1314,31 @@ thunar_application_copy_to (ThunarApplication *application, * thunar_application_copy_into: * @application : a #ThunarApplication. * @parent : a #GdkScreen, a #GtkWidget or %NULL. - * @source_path_list : the list of #ThunarVfsPath<!---->s that should be copied. - * @target_path : the #ThunarVfsPath to the target directory. + * @source_file_list : the list of #GFile<!---->s that should be copied. + * @target_file : the #GFile to the target directory. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the - * list of #ThunarVfsPath<!---->s created by the job, or + * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * - * Copies all files referenced by the @source_path_list to the directory - * referenced by @target_path. This method takes care of all user interaction. + * Copies all files referenced by the @source_file_list to the directory + * referenced by @target_file. This method takes care of all user interaction. **/ void thunar_application_copy_into (ThunarApplication *application, gpointer parent, - GList *source_path_list, - ThunarVfsPath *target_path, + GList *source_file_list, + GFile *target_file, GClosure *new_files_closure) { _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent)); _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); - _thunar_return_if_fail (target_path != NULL); + _thunar_return_if_fail (G_IS_FILE (target_file)); - /* collect the target paths and launch the job */ + /* collect the target files and launch the job */ thunar_application_collect_and_launch (application, parent, "stock_folder-copy", - _("Copying files..."), thunar_vfs_copy_files, - source_path_list, target_path, new_files_closure); + _("Copying files..."), thunar_io_jobs_copy_files, + source_file_list, target_file, new_files_closure); } @@ -1210,33 +1347,33 @@ thunar_application_copy_into (ThunarApplication *application, * thunar_application_link_into: * @application : a #ThunarApplication. * @parent : a #GdkScreen, a #GtkWidget or %NULL. - * @source_path_list : the list of #ThunarVfsPath<!---->s that should be symlinked. - * @target_path : the target directory. + * @source_file_list : the list of #GFile<!---->s that should be symlinked. + * @target_file : the target directory. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the - * list of #ThunarVfsPath<!---->s created by the job, or + * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * - * Symlinks all files referenced by the @source_path_list to the directory - * referenced by @target_path. This method takes care of all user + * Symlinks all files referenced by the @source_file_list to the directory + * referenced by @target_file. This method takes care of all user * interaction. **/ void thunar_application_link_into (ThunarApplication *application, gpointer parent, - GList *source_path_list, - ThunarVfsPath *target_path, + GList *source_file_list, + GFile *target_file, GClosure *new_files_closure) { _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent)); _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); - _thunar_return_if_fail (target_path != NULL); + _thunar_return_if_fail (G_IS_FILE (target_file)); - /* collect the target paths and launch the job */ + /* collect the target files and launch the job */ thunar_application_collect_and_launch (application, parent, "stock_link", _("Creating symbolic links..."), - thunar_vfs_link_files, source_path_list, - target_path, new_files_closure); + thunar_io_jobs_link_files, source_file_list, + target_file, new_files_closure); } @@ -1245,57 +1382,50 @@ thunar_application_link_into (ThunarApplication *application, * thunar_application_move_into: * @application : a #ThunarApplication. * @parent : a #GdkScreen, a #GtkWidget or %NULL. - * @source_path_list : the list of #ThunarVfsPath<!---->s that should be moved. - * @target_path : the target directory. + * @source_file_list : the list of #GFile<!---->s that should be moved. + * @target_file : the target directory. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the - * list of #ThunarVfsPath<!---->s created by the job, or + * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * - * Moves all files referenced by the @source_path_list to the directory - * referenced by @target_path. This method takes care of all user + * Moves all files referenced by the @source_file_list to the directory + * referenced by @target_file. This method takes care of all user * interaction. **/ void thunar_application_move_into (ThunarApplication *application, gpointer parent, - GList *source_path_list, - ThunarVfsPath *target_path, + GList *source_file_list, + GFile *target_file, GClosure *new_files_closure) { - const gchar *icon; - const gchar *text; - _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent)); _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); - _thunar_return_if_fail (target_path != NULL); - - /* determine the appropriate message text and the icon based on the target_path */ - if (thunar_vfs_path_get_scheme (target_path) == THUNAR_VFS_PATH_SCHEME_TRASH) + _thunar_return_if_fail (target_file != NULL); + + /* launch the appropriate operation depending on the target file */ + if (thunar_g_file_is_trashed (target_file)) { - icon = "gnome-fs-trash-full"; - text = _("Moving files into the trash..."); + thunar_application_trash (application, parent, source_file_list); } else { - icon = "stock_folder-move"; - text = _("Moving files..."); + thunar_application_collect_and_launch (application, parent, + "stock_folder-move", _("Moving files..."), + thunar_io_jobs_move_files, + source_file_list, target_file, + new_files_closure); } - - /* launch the operation */ - thunar_application_collect_and_launch (application, parent, icon, text, - thunar_vfs_move_files, source_path_list, - target_path, new_files_closure); } -static ThunarVfsJob* -unlink_stub (GList *source_path_list, - GList *target_path_list, - GError **error) +static ThunarJob * +unlink_stub (GList *source_path_list, + GList *target_path_list) { - return thunar_vfs_unlink_files (source_path_list, error); + return thunar_io_jobs_unlink_files (source_path_list); } @@ -1318,7 +1448,6 @@ thunar_application_unlink_files (ThunarApplication *application, GList *file_list) { GdkModifierType state; - ThunarVfsPath *path; GtkWidget *dialog; GtkWindow *window; GdkScreen *screen; @@ -1339,11 +1468,7 @@ thunar_application_unlink_files (ThunarApplication *application, for (lp = g_list_last (file_list); lp != NULL; lp = lp->prev, ++n_path_list) { /* prepend the path to the path list */ - path_list = thunar_vfs_path_list_prepend (path_list, thunar_file_get_path (lp->data)); - - /* check if the file is not a local file */ - if (!thunar_file_is_local (lp->data)) - permanently = TRUE; + path_list = thunar_g_file_list_prepend (path_list, thunar_file_get_file (lp->data)); } /* nothing to do if we don't have any paths */ @@ -1372,8 +1497,7 @@ thunar_application_unlink_files (ThunarApplication *application, /* ask the user to confirm the delete operation */ dialog = gtk_message_dialog_new (window, - GTK_DIALOG_MODAL - | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", message); @@ -1384,7 +1508,8 @@ thunar_application_unlink_files (ThunarApplication *application, GTK_STOCK_DELETE, GTK_RESPONSE_YES, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("If you delete a file, it is permanently lost.")); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + _("If you delete a file, it is permanently lost.")); response = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); g_free (message); @@ -1394,30 +1519,52 @@ thunar_application_unlink_files (ThunarApplication *application, { /* launch the "Delete" operation */ thunar_application_launch (application, parent, "stock_delete", - _("Deleting files..."), unlink_stub, - path_list, path_list, NULL); + _("Deleting files..."), unlink_stub, + path_list, path_list, NULL); } } else { /* launch the "Move to Trash" operation */ - path = thunar_vfs_path_get_for_trash (); - thunar_application_move_into (application, parent, path_list, path, NULL); - thunar_vfs_path_unref (path); + thunar_application_trash (application, parent, path_list); } /* release the path list */ - thunar_vfs_path_list_free (path_list); + thunar_g_file_list_free (path_list); } -static ThunarVfsJob* -creat_stub (GList *source_path_list, - GList *target_path_list, - GError **error) +static ThunarJob * +trash_stub (GList *source_file_list, + GList *target_file_list) { - return thunar_vfs_create_files (source_path_list, error); + return thunar_io_jobs_trash_files (source_file_list); +} + + + +void +thunar_application_trash (ThunarApplication *application, + gpointer parent, + GList *file_list) +{ + _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent)); + _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); + _thunar_return_if_fail (file_list != NULL); + + thunar_application_launch (application, parent, "gnome-fs-trash-full", + _("Moving files into the trash..."), trash_stub, + file_list, NULL, NULL); +} + + + +static ThunarJob * +creat_stub (GList *source_path_list, + GList *target_path_list) +{ + return thunar_io_jobs_create_files (source_path_list); } @@ -1426,38 +1573,37 @@ creat_stub (GList *source_path_list, * thunar_application_creat: * @application : a #ThunarApplication. * @parent : a #GdkScreen, a #GtkWidget or %NULL. - * @path_list : the list of files to create. + * @file_list : the list of files to create. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the - * list of #ThunarVfsPath<!---->s created by the job, or + * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * - * Creates empty files for all #ThunarVfsPath<!---->s listed in @path_list. This + * Creates empty files for all #GFile<!---->s listed in @file_list. This * method takes care of all user interaction. **/ void thunar_application_creat (ThunarApplication *application, gpointer parent, - GList *path_list, + GList *file_list, GClosure *new_files_closure) { _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent)); _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); - + /* launch the operation */ thunar_application_launch (application, parent, "stock_new", _("Creating files..."), creat_stub, - path_list, path_list, new_files_closure); + file_list, file_list, new_files_closure); } -static ThunarVfsJob* -mkdir_stub (GList *source_path_list, - GList *target_path_list, - GError **error) +static ThunarJob * +mkdir_stub (GList *source_path_list, + GList *target_path_list) { - return thunar_vfs_make_directories (source_path_list, error); + return thunar_io_jobs_make_directories (source_path_list); } @@ -1466,19 +1612,19 @@ mkdir_stub (GList *source_path_list, * thunar_application_mkdir: * @application : a #ThunarApplication. * @parent : a #GdkScreen, a #GtkWidget or %NULL. - * @path_list : the list of directories to create. + * @file_list : the list of directories to create. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the - * list of #ThunarVfsPath<!---->s created by the job, or + * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * - * Creates all directories referenced by the @path_list. This method takes care of all user + * Creates all directories referenced by the @file_list. This method takes care of all user * interaction. **/ void thunar_application_mkdir (ThunarApplication *application, gpointer parent, - GList *path_list, + GList *file_list, GClosure *new_files_closure) { _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent)); @@ -1487,7 +1633,7 @@ thunar_application_mkdir (ThunarApplication *application, /* launch the operation */ thunar_application_launch (application, parent, "stock_folder", _("Creating directories..."), mkdir_stub, - path_list, path_list, new_files_closure); + file_list, file_list, new_files_closure); } @@ -1509,7 +1655,7 @@ thunar_application_empty_trash (ThunarApplication *application, GtkWidget *dialog; GtkWindow *window; GdkScreen *screen; - GList path_list; + GList file_list; gint response; _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); @@ -1544,17 +1690,17 @@ thunar_application_empty_trash (ThunarApplication *application, /* fake a path list with only the trash root (the root * folder itself will never be unlinked, so this is safe) */ - path_list.data = thunar_vfs_path_get_for_trash (); - path_list.next = NULL; - path_list.prev = NULL; + file_list.data = thunar_g_file_new_for_trash (); + file_list.next = NULL; + file_list.prev = NULL; /* launch the operation */ thunar_application_launch (application, parent, "gnome-fs-trash-empty", - _("Emptying the Trash..."), - unlink_stub, &path_list, NULL, NULL); + _("Emptying the Trash..."), + unlink_stub, &file_list, NULL, NULL); /* cleanup */ - thunar_vfs_path_unref (path_list.data); + g_object_unref (file_list.data); } } @@ -1567,7 +1713,7 @@ thunar_application_empty_trash (ThunarApplication *application, * @trash_file_list : a #GList of #ThunarFile<!---->s in the trash. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the - * list of #ThunarVfsPath<!---->s created by the job, or + * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * * Restores all #ThunarFile<!---->s in the @trash_file_list to their original @@ -1579,28 +1725,20 @@ thunar_application_restore_files (ThunarApplication *application, GList *trash_file_list, GClosure *new_files_closure) { - ThunarVfsPath *target_path; - GtkWidget *dialog; - GtkWindow *window; - GdkScreen *screen; - GError *err = NULL; - GList *source_path_list = NULL; - GList *target_path_list = NULL; - GList *lp; - gchar *original_path; - gchar *original_dir; - gchar *display_name; - gint response = GTK_RESPONSE_YES; + const gchar *original_uri; + GError *err = NULL; + GFile *target_path; + GList *source_path_list = NULL; + GList *target_path_list = NULL; + GList *lp; _thunar_return_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent)); _thunar_return_if_fail (THUNAR_IS_APPLICATION (application)); - /* determine the target paths for all files */ - for (lp = trash_file_list; err == NULL && lp != NULL && response == GTK_RESPONSE_YES; lp = lp->next) + for (lp = trash_file_list; lp != NULL; lp = lp->next) { - /* determine the original path for the file */ - original_path = thunar_file_get_original_path (lp->data); - if (G_UNLIKELY (original_path == NULL)) + original_uri = thunar_file_get_original_path (lp->data); + if (G_UNLIKELY (original_uri == NULL)) { /* no OriginalPath, impossible to continue */ g_set_error (&err, G_FILE_ERROR, G_FILE_ERROR_INVAL, @@ -1609,90 +1747,33 @@ thunar_application_restore_files (ThunarApplication *application, break; } - /* determine the target path for the OriginalPath */ - target_path = thunar_vfs_path_new (original_path, &err); - if (G_UNLIKELY (target_path == NULL)) - { - /* invalid OriginalPath, cannot continue */ - g_free (original_path); - break; - } + /* TODO we might have to distinguish between URIs and paths here */ + target_path = g_file_new_for_commandline_arg (original_uri); - /* determine the directory of the original path */ - original_dir = g_path_get_dirname (original_path); - if (!g_file_test (original_dir, G_FILE_TEST_IS_DIR)) - { - /* parse the parent pointer */ - screen = thunar_util_parse_parent (parent, &window); - - /* ask the user whether to recreate the original dir */ - display_name = g_filename_display_name (original_dir); - dialog = gtk_message_dialog_new (window, - GTK_DIALOG_MODAL - | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - _("Create the folder \"%s\"?"), - display_name); - gtk_dialog_add_buttons (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - _("C_reate Folder"), GTK_RESPONSE_YES, - NULL); - if (G_UNLIKELY (window == NULL && screen != NULL)) - gtk_window_set_screen (GTK_WINDOW (dialog), screen); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), - _("The folder \"%s\" does not exist anymore, but it is required to restore " - "the file \"%s\" from the trash. Do you want to create the folder again?"), - display_name, thunar_file_get_display_name (lp->data)); - response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - g_free (display_name); - - /* check if the user wants to recreate the folder */ - if (G_LIKELY (response == GTK_RESPONSE_YES)) - { - /* try to recreate the folder */ - xfce_mkdirhier (original_dir, 0755, &err); - } - } - - /* check if we succeed and aren't cancelled */ - if (G_LIKELY (err == NULL && response == GTK_RESPONSE_YES)) - { - /* add the source/target pair to our lists */ - source_path_list = thunar_vfs_path_list_append (source_path_list, thunar_file_get_path (lp->data)); - target_path_list = g_list_append (target_path_list, target_path); - } - else - { - /* release the target path */ - thunar_vfs_path_unref (target_path); - } + source_path_list = thunar_g_file_list_append (source_path_list, thunar_file_get_file (lp->data)); + target_path_list = thunar_g_file_list_append (target_path_list, target_path); - /* cleanup */ - g_free (original_path); - g_free (original_dir); + g_object_unref (target_path); } - /* check if an error occurred or the user cancelled */ if (G_UNLIKELY (err != NULL)) { /* display an error dialog */ - thunar_dialogs_show_error (parent, err, _("Failed to restore \"%s\""), thunar_file_get_display_name (lp->data)); + thunar_dialogs_show_error (parent, err, _("Could not restore \"%s\""), + thunar_file_get_display_name (lp->data)); g_error_free (err); } - else if (G_LIKELY (response == GTK_RESPONSE_YES)) + else { /* launch the operation */ thunar_application_launch (application, parent, "stock_folder-move", - _("Restoring files..."), thunar_vfs_move_files, + _("Restoring files..."), thunar_io_jobs_restore_files, source_path_list, target_path_list, new_files_closure); } - /* cleanup */ - thunar_vfs_path_list_free (target_path_list); - thunar_vfs_path_list_free (source_path_list); + /* free path lists */ + thunar_g_file_list_free (source_path_list); + thunar_g_file_list_free (target_path_list); } diff --git a/thunar/thunar-application.h b/thunar/thunar-application.h index 9e052bf9a..d90dd28ca 100644 --- a/thunar/thunar-application.h +++ b/thunar/thunar-application.h @@ -2,6 +2,7 @@ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> * Copyright (c) 2005 Jeff Franks <jcfranks@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -52,57 +53,66 @@ void thunar_application_take_window (ThunarApplication *appl GtkWidget *thunar_application_open_window (ThunarApplication *application, ThunarFile *directory, - GdkScreen *screen); + GdkScreen *screen, + const gchar *startup_id); gboolean thunar_application_bulk_rename (ThunarApplication *application, const gchar *working_directory, gchar **filenames, gboolean standalone, GdkScreen *screen, + const gchar *startup_id, GError **error); gboolean thunar_application_process_filenames (ThunarApplication *application, const gchar *working_directory, gchar **filenames, GdkScreen *screen, + const gchar *startup_id, GError **error); +gboolean thunar_application_is_processing (ThunarApplication *application); + void thunar_application_copy_to (ThunarApplication *application, gpointer parent, - GList *source_path_list, - GList *target_path_list, + GList *source_file_list, + GList *target_file_list, GClosure *new_files_closure); void thunar_application_copy_into (ThunarApplication *application, gpointer parent, - GList *source_path_list, - ThunarVfsPath *target_path, + GList *source_file_list, + GFile *target_file, GClosure *new_files_closure); void thunar_application_link_into (ThunarApplication *application, gpointer parent, - GList *source_path_list, - ThunarVfsPath *target_path, + GList *source_file_list, + GFile *target_file, GClosure *new_files_closure); void thunar_application_move_into (ThunarApplication *application, gpointer parent, - GList *source_path_list, - ThunarVfsPath *target_path, + GList *source_file_list, + GFile *target_file, GClosure *new_files_closure); void thunar_application_unlink_files (ThunarApplication *application, gpointer parent, GList *file_list); +void thunar_application_trash (ThunarApplication *application, + gpointer parent, + GList *file_list); + void thunar_application_creat (ThunarApplication *application, gpointer parent, - GList *path_list, + GList *file_list, GClosure *new_files_closure); void thunar_application_mkdir (ThunarApplication *application, gpointer parent, - GList *path_list, + GList *file_list, GClosure *new_files_closure); void thunar_application_empty_trash (ThunarApplication *application, diff --git a/thunar/thunar-browser.c b/thunar/thunar-browser.c new file mode 100644 index 000000000..75ea0b717 --- /dev/null +++ b/thunar/thunar-browser.c @@ -0,0 +1,549 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 + +#include <glib-object.h> + +#include <thunar/thunar-browser.h> +#include <thunar/thunar-file.h> +#include <thunar/thunar-private.h> +#include <thunar/thunar-util.h> + + + +typedef struct _PokeFileData PokeFileData; +typedef struct _PokeVolumeData PokeVolumeData; + +struct _PokeFileData +{ + ThunarBrowser *browser; + ThunarFile *source; + ThunarFile *file; + ThunarBrowserPokeFileFunc func; + gpointer user_data; +}; + +struct _PokeVolumeData +{ + ThunarBrowser *browser; + GVolume *volume; + ThunarFile *mount_point; + ThunarBrowserPokeVolumeFunc func; + gpointer user_data; +}; + + + +GType +thunar_browser_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + type = g_type_register_static_simple (G_TYPE_INTERFACE, + "ThunarBrowser", + sizeof (ThunarBrowserIface), + NULL, + 0, + NULL, + 0); + + g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); + } + + return type; +} + + + +static PokeFileData * +thunar_browser_poke_file_data_new (ThunarBrowser *browser, + ThunarFile *source, + ThunarFile *file, + ThunarBrowserPokeFileFunc func, + gpointer user_data) +{ + PokeFileData *poke_data; + + _thunar_return_val_if_fail (THUNAR_IS_BROWSER (browser), NULL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (source), NULL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + + poke_data = _thunar_slice_new0 (PokeFileData); + poke_data->browser = g_object_ref (browser); + poke_data->source = g_object_ref (source); + poke_data->file = g_object_ref (file); + poke_data->func = func; + poke_data->user_data = user_data; + + return poke_data; +} + + + +static void +thunar_browser_poke_file_data_free (PokeFileData *poke_data) +{ + _thunar_return_if_fail (poke_data != NULL); + _thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (poke_data->source)); + _thunar_return_if_fail (THUNAR_IS_FILE (poke_data->file)); + + g_object_unref (poke_data->browser); + g_object_unref (poke_data->source); + g_object_unref (poke_data->file); + + _thunar_slice_free (PokeFileData, poke_data); +} + + + +static PokeVolumeData * +thunar_browser_poke_volume_data_new (ThunarBrowser *browser, + GVolume *volume, + ThunarBrowserPokeVolumeFunc func, + gpointer user_data) +{ + PokeVolumeData *poke_data; + + _thunar_return_val_if_fail (THUNAR_IS_BROWSER (browser), NULL); + _thunar_return_val_if_fail (G_IS_VOLUME (volume), NULL); + + poke_data = _thunar_slice_new0 (PokeVolumeData); + poke_data->browser = g_object_ref (browser); + poke_data->volume = g_object_ref (volume); + poke_data->func = func; + poke_data->user_data = user_data; + + return poke_data; +} + + + +static void +thunar_browser_poke_volume_data_free (PokeVolumeData *poke_data) +{ + _thunar_return_if_fail (poke_data != NULL); + _thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser)); + _thunar_return_if_fail (G_IS_VOLUME (poke_data->volume)); + + g_object_unref (poke_data->browser); + g_object_unref (poke_data->volume); + + _thunar_slice_free (PokeVolumeData, poke_data); +} + + + +static GMountOperation * +thunar_browser_mount_operation_new (gpointer parent) +{ + GMountOperation *mount_operation; + GtkWindow *window = NULL; + GdkScreen *screen = NULL; + + mount_operation = gtk_mount_operation_new (NULL); + + screen = thunar_util_parse_parent (parent, &window); + gtk_mount_operation_set_screen (GTK_MOUNT_OPERATION (mount_operation), screen); + gtk_mount_operation_set_parent (GTK_MOUNT_OPERATION (mount_operation), window); + + return mount_operation; +} + + + +static void +thunar_browser_poke_mountable_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + PokeFileData *poke_data = user_data; + ThunarFile *target = NULL; + GError *error = NULL; + GFile *location; + + _thunar_return_if_fail (G_IS_FILE (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (user_data != NULL); + _thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (poke_data->file)); + + g_debug (" poke mountable finish"); + + if (!g_file_mount_mountable_finish (G_FILE (object), result, &error)) + { + if (error->domain == G_IO_ERROR) + { + if (error->code == G_IO_ERROR_ALREADY_MOUNTED) + g_clear_error (&error); + } + } + + if (error == NULL) + { + thunar_file_reload (poke_data->file); + + location = thunar_file_get_target_location (poke_data->file); + target = thunar_file_get (location, &error); + g_object_unref (location); + } + + if (poke_data->func != NULL) + { + (poke_data->func) (poke_data->browser, poke_data->source, target, error, + poke_data->user_data); + } + + g_clear_error (&error); + + if (target != NULL) + g_object_unref (target); + + thunar_browser_poke_file_data_free (poke_data); +} + + + +static void +thunar_browser_poke_file_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + PokeFileData *poke_data = user_data; + GError *error = NULL; + + _thunar_return_if_fail (G_IS_FILE (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (user_data != NULL); + _thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (poke_data->file)); + + g_debug (" poke file finish"); + + if (!g_file_mount_enclosing_volume_finish (G_FILE (object), result, &error)) + { + if (error->domain == G_IO_ERROR) + { + if (error->code == G_IO_ERROR_ALREADY_MOUNTED) + g_clear_error (&error); + } + } + + if (error == NULL) + thunar_file_reload (poke_data->file); + + g_debug (" %s type %d", thunar_file_dup_uri (poke_data->file), + thunar_file_get_kind (poke_data->file)); + + if (poke_data->func != NULL) + { + if (error == NULL) + { + (poke_data->func) (poke_data->browser, poke_data->source, poke_data->file, + NULL, poke_data->user_data); + } + else + { + (poke_data->func) (poke_data->browser, poke_data->source, NULL, error, + poke_data->user_data); + } + } + + g_clear_error (&error); + + thunar_browser_poke_file_data_free (poke_data); +} + + + +static void +thunar_browser_poke_file_internal (ThunarBrowser *browser, + ThunarFile *source, + ThunarFile *file, + gpointer widget, + ThunarBrowserPokeFileFunc func, + gpointer user_data) +{ + GMountOperation *mount_operation; + ThunarFile *target; + PokeFileData *poke_data; + GError *error = NULL; + GFile *location; + + _thunar_return_if_fail (THUNAR_IS_BROWSER (browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (source)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + g_debug ("poke %s", thunar_file_dup_uri (file)); + + if (thunar_file_get_kind (file) == G_FILE_TYPE_SHORTCUT) + { + location = thunar_file_get_target_location (file); + target = thunar_file_get (location, &error); + g_debug (" shortcut, target %s (%p)", g_file_get_uri (location), target); + g_object_unref (location); + + if (target != NULL) + { + /* TODO in very rare occasions (shortcut X -> other shortcut -> shortcut X), + * this can lead to endless recursion */ + thunar_browser_poke_file_internal (browser, source, target, widget, + func, user_data); + } + else + { + if (func != NULL) + func (browser, source, NULL, error, user_data); + } + + g_clear_error (&error); + + if (target != NULL) + g_object_unref (target); + } + else if (thunar_file_get_kind (file) == G_FILE_TYPE_MOUNTABLE) + { + if (thunar_file_is_mounted (file)) + { + g_debug (" mountable, already mounted"); + + location = thunar_file_get_target_location (file); + target = thunar_file_get (location, &error); + g_object_unref (location); + + if (func != NULL) + func (browser, source, target, error, user_data); + + g_clear_error (&error); + + if (target != NULL) + g_object_unref (target); + } + else + { + g_debug (" mountable, needs mounting"); + + poke_data = thunar_browser_poke_file_data_new (browser, source, file, + func, user_data); + + mount_operation = thunar_browser_mount_operation_new (widget); + + g_file_mount_mountable (thunar_file_get_file (file), + G_MOUNT_MOUNT_NONE, mount_operation, NULL, + thunar_browser_poke_mountable_finish, + poke_data); + + g_object_unref (mount_operation); + } + } + else if (!thunar_file_is_mounted (file)) + { + g_debug (" file, enclosing volume needs mounting"); + + poke_data = thunar_browser_poke_file_data_new (browser, source, file, + func, user_data); + + mount_operation = thunar_browser_mount_operation_new (widget); + + g_file_mount_enclosing_volume (thunar_file_get_file (file), + G_MOUNT_MOUNT_NONE, mount_operation, NULL, + thunar_browser_poke_file_finish, + poke_data); + + g_object_unref (mount_operation); + } + else + { + g_debug (" file, enclosing volume already mounted"); + + if (func != NULL) + func (browser, source, file, NULL, user_data); + } +} + + + +/** + * thunar_browser_poke_file: + * @browser : a #ThunarBrowser. + * @file : a #ThunarFile. + * @widget : a #GtkWidget, a #GdkScreen or %NULL. + * @func : a #ThunarBrowserPokeFileFunc callback or %NULL. + * @user_data : pointer to arbitrary user data or %NULL. + * + * Pokes a #ThunarFile to see what's behind it. + * + * If @file has the type %G_FILE_TYPE_SHORTCUT, it tries to load and mount + * the file that is referred to by the %G_FILE_ATTRIBUTE_STANDARD_TARGET_URI + * of the @file. + * + * If @file has the type %G_FILE_TYPE_MOUNTABLE, it tries to mount the @file. + * + * In the other cases, if the enclosing volume of the @file is not mounted + * yet, it tries to mount it. + * + * When finished or if an error occured, it calls @func with the provided + * @user data. The #GError parameter to @func is set if, and only if there + * was an error. + **/ +void +thunar_browser_poke_file (ThunarBrowser *browser, + ThunarFile *file, + gpointer widget, + ThunarBrowserPokeFileFunc func, + gpointer user_data) +{ + _thunar_return_if_fail (THUNAR_IS_BROWSER (browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + thunar_browser_poke_file_internal (browser, file, file, widget, func, user_data); +} + + + +static void +thunar_browser_poke_volume_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + PokeVolumeData *poke_data = user_data; + ThunarFile *file; + GError *error = NULL; + GMount *mount; + GFile *mount_point; + + _thunar_return_if_fail (G_IS_VOLUME (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (user_data != NULL); + _thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser)); + _thunar_return_if_fail (G_IS_VOLUME (poke_data->volume)); + _thunar_return_if_fail (G_VOLUME (object) == poke_data->volume); + + if (!g_volume_mount_finish (G_VOLUME (object), result, &error)) + { + if (error->domain == G_IO_ERROR) + { + if (error->code == G_IO_ERROR_ALREADY_MOUNTED) + g_clear_error (&error); + } + } + + if (error == NULL) + { + mount = g_volume_get_mount (poke_data->volume); + mount_point = g_mount_get_root (mount); + + file = thunar_file_get (mount_point, &error); + + g_object_unref (mount_point); + g_object_unref (mount); + + if (poke_data->func != NULL) + { + (poke_data->func) (poke_data->browser, poke_data->volume, file, error, + poke_data->user_data); + } + + if (file != NULL) + g_object_unref (file); + } + else + { + if (poke_data->func != NULL) + { + (poke_data->func) (poke_data->browser, poke_data->volume, NULL, error, + poke_data->user_data); + } + } + + thunar_browser_poke_volume_data_free (poke_data); +} + + + +/** + * thunar_browser_poke_volume: + * @browser : a #ThunarBrowser. + * @volume : a #GVolume. + * @widget : a #GtkWidget, a #GdkScreen or %NULL. + * @func : a #ThunarBrowserPokeVolumeFunc callback or %NULL. + * @user_data : pointer to arbitrary user data or %NULL. + * + * This function checks if @volume is mounted or not. If it is, it loads + * a #ThunarFile for the mount root and calls @func. If it is not mounted, + * it first mounts the volume asynchronously and calls @func with the + * #ThunarFile corresponding to the mount root when the mounting is finished. + * + * The #ThunarFile passed to @func will be %NULL if, and only if mounting + * the @volume failed. The #GError passed to @func will be set if, and only if + * mounting failed. + **/ +void +thunar_browser_poke_volume (ThunarBrowser *browser, + GVolume *volume, + gpointer widget, + ThunarBrowserPokeVolumeFunc func, + gpointer user_data) +{ + GMountOperation *mount_operation; + PokeVolumeData *poke_data; + ThunarFile *file; + GError *error = NULL; + GMount *mount; + GFile *mount_point; + + _thunar_return_if_fail (THUNAR_IS_BROWSER (browser)); + _thunar_return_if_fail (G_IS_VOLUME (volume)); + + if (thunar_g_volume_is_mounted (volume)) + { + mount = g_volume_get_mount (volume); + mount_point = g_mount_get_root (mount); + + file = thunar_file_get (mount_point, &error); + + g_object_unref (mount_point); + g_object_unref (mount); + + if (func != NULL) + func (browser, volume, file, error, user_data); + + g_clear_error (&error); + + if (file != NULL) + g_object_unref (file); + } + else + { + poke_data = thunar_browser_poke_volume_data_new (browser, volume, func, user_data); + + mount_operation = thunar_browser_mount_operation_new (widget); + + g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_operation, NULL, + thunar_browser_poke_volume_finish, poke_data); + + g_object_unref (mount_operation); + } +} diff --git a/thunar/thunar-browser.h b/thunar/thunar-browser.h new file mode 100644 index 000000000..d9bb79594 --- /dev/null +++ b/thunar/thunar-browser.h @@ -0,0 +1,72 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_BROWSER_H__ +#define __THUNAR_BROWSER_H__ + +#include <thunar/thunar-file.h> + +G_BEGIN_DECLS + +#define THUNAR_TYPE_BROWSER (thunar_browser_get_type ()) +#define THUNAR_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_BROWSER, ThunarBrowser)) +#define THUNAR_IS_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_BROWSER)) +#define THUNAR_BROWSER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), THUNAR_TYPE_BROWSER, ThunarBrowserIface)) + +typedef struct _ThunarBrowser ThunarBrowser; +typedef struct _ThunarBrowserIface ThunarBrowserIface; + +typedef void (*ThunarBrowserPokeFileFunc) (ThunarBrowser *browser, + ThunarFile *file, + ThunarFile *target_file, + GError *error, + gpointer user_data); + +typedef void (*ThunarBrowserPokeVolumeFunc) (ThunarBrowser *browser, + GVolume *volume, + ThunarFile *mount_point, + GError *error, + gpointer user_data); + +struct _ThunarBrowserIface +{ + GTypeInterface __parent__; + + /* signals */ + + /* virtual methods */ +}; + +GType thunar_browser_get_type (void) G_GNUC_CONST; + +void thunar_browser_poke_file (ThunarBrowser *browser, + ThunarFile *file, + gpointer widget, + ThunarBrowserPokeFileFunc func, + gpointer user_data); +void thunar_browser_poke_volume (ThunarBrowser *browser, + GVolume *volume, + gpointer widget, + ThunarBrowserPokeVolumeFunc func, + gpointer user_data); + +G_END_DECLS + +#endif /* !__THUNAR_BROWSER_H__ */ diff --git a/thunar/thunar-chooser-button.c b/thunar/thunar-chooser-button.c index 607cca866..92e76610e 100644 --- a/thunar/thunar-chooser-button.c +++ b/thunar/thunar-chooser-button.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>. + * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -76,8 +77,6 @@ struct _ThunarChooserButton GtkWidget *button; ThunarFile *file; - - ThunarVfsMimeDatabase *database; }; @@ -150,9 +149,6 @@ thunar_chooser_button_init (ThunarChooserButton *chooser_button) GtkWidget *arrow; GtkWidget *hbox; - /* grab a reference on the mime database */ - chooser_button->database = thunar_vfs_mime_database_get_default (); - gtk_widget_push_composite_child (); chooser_button->button = gtk_button_new (); @@ -193,9 +189,6 @@ thunar_chooser_button_finalize (GObject *object) /* reset the "file" property */ thunar_chooser_button_set_file (chooser_button, NULL); - /* disconnect from the mime database */ - g_object_unref (G_OBJECT (chooser_button->database)); - (*G_OBJECT_CLASS (thunar_chooser_button_parent_class)->finalize) (object); } @@ -249,9 +242,9 @@ static void thunar_chooser_button_activate (ThunarChooserButton *chooser_button, GtkWidget *item) { - ThunarVfsMimeApplication *application; - ThunarVfsMimeInfo *info; - GError *error = NULL; + const gchar *content_type; + GAppInfo *app_info; + GError *error = NULL; _thunar_return_if_fail (THUNAR_IS_CHOOSER_BUTTON (chooser_button)); _thunar_return_if_fail (GTK_IS_MENU_ITEM (item)); @@ -261,15 +254,15 @@ thunar_chooser_button_activate (ThunarChooserButton *chooser_button, return; /* determine the application that was set for the item */ - application = g_object_get_data (G_OBJECT (item), "thunar-vfs-mime-application"); - if (G_UNLIKELY (application == NULL)) + app_info = g_object_get_data (G_OBJECT (item), "app-info"); + if (G_UNLIKELY (app_info == NULL)) return; /* determine the mime info for the file */ - info = thunar_file_get_mime_info (chooser_button->file); + content_type = thunar_file_get_content_type (chooser_button->file); /* try to set application as default for these kind of file */ - if (!thunar_vfs_mime_database_set_default_application (chooser_button->database, info, application, &error)) + if (!g_app_info_set_as_default_for_type (app_info, content_type, &error)) { /* tell the user that it didn't work */ thunar_dialogs_show_error (GTK_WIDGET (chooser_button), error, _("Failed to set default application for \"%s\""), @@ -313,45 +306,32 @@ static void thunar_chooser_button_file_changed (ThunarChooserButton *chooser_button, ThunarFile *file) { - ThunarVfsMimeApplication *application; - ThunarVfsMimeInfo *info; - ThunarIconFactory *icon_factory; - GtkIconTheme *icon_theme; - const gchar *icon_name; - GdkPixbuf *icon = NULL; - gint icon_size; + const gchar *content_type; + GAppInfo *app_info; + gchar *description; _thunar_return_if_fail (THUNAR_IS_CHOOSER_BUTTON (chooser_button)); _thunar_return_if_fail (chooser_button->file == file); _thunar_return_if_fail (THUNAR_IS_FILE (file)); - /* determine the mime info for the file */ - info = thunar_file_get_mime_info (file); + /* determine the content type of the file */ + content_type = thunar_file_get_content_type (file); - /* determine the default application for that mime info */ - application = thunar_vfs_mime_database_get_default_application (chooser_button->database, info); - if (G_LIKELY (application != NULL)) + /* determine the default application for that content type */ + app_info = g_app_info_get_default_for_type (content_type, FALSE); + if (G_LIKELY (app_info != NULL)) { - /* determine the icon size for menus */ - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_size, &icon_size); - /* setup the image for the application */ - icon_factory = thunar_icon_factory_get_default (); - icon_theme = thunar_icon_factory_get_icon_theme (icon_factory); - icon_name = thunar_vfs_mime_handler_lookup_icon_name (THUNAR_VFS_MIME_HANDLER (application), icon_theme); - if (G_LIKELY (icon_name != NULL)) - icon = thunar_icon_factory_load_icon (icon_factory, icon_name, icon_size, NULL, FALSE); - gtk_image_set_from_pixbuf (GTK_IMAGE (chooser_button->image), icon); - g_object_unref (G_OBJECT (icon_factory)); - if (G_LIKELY (icon != NULL)) - g_object_unref (G_OBJECT (icon)); + gtk_image_set_from_gicon (GTK_IMAGE (chooser_button->image), + g_app_info_get_icon (app_info), + GTK_ICON_SIZE_MENU); /* setup the label for the application */ gtk_label_set_attributes (GTK_LABEL (chooser_button->label), NULL); - gtk_label_set_text (GTK_LABEL (chooser_button->label), thunar_vfs_mime_handler_get_name (THUNAR_VFS_MIME_HANDLER (application))); + gtk_label_set_text (GTK_LABEL (chooser_button->label), g_app_info_get_name (app_info)); /* cleanup */ - g_object_unref (G_OBJECT (application)); + g_object_unref (app_info); } else { @@ -362,10 +342,12 @@ thunar_chooser_button_file_changed (ThunarChooserButton *chooser_button, } /* setup a useful tooltip for the button */ + description = g_content_type_get_description (content_type); thunar_gtk_widget_set_tooltip (chooser_button->button, _("The selected application is used to open " "this and other files of type \"%s\"."), - thunar_vfs_mime_info_get_comment (info)); + description); + g_free (description); } @@ -415,18 +397,13 @@ static void thunar_chooser_button_pressed (ThunarChooserButton *chooser_button, GtkWidget *button) { - ThunarVfsMimeApplication *default_application; - ThunarVfsMimeInfo *info; - ThunarIconFactory *icon_factory; - GtkIconTheme *icon_theme; - const gchar *icon_name; - GdkPixbuf *icon; - GtkWidget *image; - GtkWidget *item; - GtkWidget *menu; - GList *applications; - GList *lp; - gint icon_size; + const gchar *content_type; + GtkWidget *image; + GtkWidget *item; + GtkWidget *menu; + GAppInfo *default_app_info; + GList *app_infos; + GList *lp; _thunar_return_if_fail (THUNAR_IS_CHOOSER_BUTTON (chooser_button)); _thunar_return_if_fail (chooser_button->button == button); @@ -436,69 +413,47 @@ thunar_chooser_button_pressed (ThunarChooserButton *chooser_button, if (G_UNLIKELY (chooser_button->file == NULL)) return; - /* determine the mime info for the file */ - info = thunar_file_get_mime_info (chooser_button->file); + /* determine the content type for the file */ + content_type = thunar_file_get_content_type (chooser_button->file); /* determine the default application */ - default_application = thunar_vfs_mime_database_get_default_application (chooser_button->database, info); - if (G_UNLIKELY (default_application == NULL)) + default_app_info = g_app_info_get_default_for_type (content_type, FALSE); + if (G_UNLIKELY (default_app_info == NULL)) { /* no default application, just popup the application chooser */ thunar_chooser_button_activate_other (chooser_button); + g_object_unref (default_app_info); return; } /* determine all applications that claim to be able to handle the file */ - applications = thunar_vfs_mime_database_get_applications (chooser_button->database, info); - - /* make sure the default application comes first */ - lp = g_list_find (applications, default_application); - if (G_LIKELY (lp != NULL)) - { - applications = g_list_delete_link (applications, lp); - g_object_unref (G_OBJECT (default_application)); - } - applications = g_list_prepend (applications, default_application); + app_infos = g_app_info_get_all_for_type (content_type); /* allocate a new popup menu */ menu = gtk_menu_new (); - /* determine the icon size for menus */ - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_size, &icon_size); - - /* determine the icon factory for our screen */ - icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (button)); - icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); - /* add the other possible applications */ - for (lp = applications; lp != NULL; lp = lp->next) + for (lp = app_infos; lp != NULL; lp = lp->next) { - item = gtk_image_menu_item_new_with_label (thunar_vfs_mime_handler_get_name (lp->data)); - g_object_set_data_full (G_OBJECT (item), I_("thunar-vfs-mime-application"), lp->data, g_object_unref); + item = gtk_image_menu_item_new_with_label (g_app_info_get_name (lp->data)); + g_object_set_data_full (G_OBJECT (item), I_("app-info"), lp->data, g_object_unref); g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_chooser_button_activate), chooser_button); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* setup the icon for the application */ - icon_name = thunar_vfs_mime_handler_lookup_icon_name (lp->data, icon_theme); - icon = thunar_icon_factory_load_icon (icon_factory, icon_name, icon_size, NULL, FALSE); - image = gtk_image_new_from_pixbuf (icon); + image = gtk_image_new_from_gicon (g_app_info_get_icon (lp->data), GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); gtk_widget_show (image); - if (G_LIKELY (icon != NULL)) - g_object_unref (icon); } - /* cleanup */ - g_object_unref (G_OBJECT (icon_factory)); - /* append a separator */ item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* release the applications list */ - g_list_free (applications); + g_list_free (app_infos); /* add the "Other Application..." choice */ item = gtk_image_menu_item_new_with_mnemonic (_("_Other Application...")); diff --git a/thunar/thunar-chooser-dialog.c b/thunar/thunar-chooser-dialog.c index 05b3b7ab6..081bf1f15 100644 --- a/thunar/thunar-chooser-dialog.c +++ b/thunar/thunar-chooser-dialog.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>. + * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -83,9 +84,7 @@ static gboolean thunar_chooser_dialog_button_press_event (GtkWidget static void thunar_chooser_dialog_notify_expanded (GtkExpander *expander, GParamSpec *pspec, ThunarChooserDialog *dialog); -static void thunar_chooser_dialog_notify_loading (ThunarChooserModel *model, - GParamSpec *pspec, - ThunarChooserDialog *dialog); +static void thunar_chooser_dialog_expand (ThunarChooserDialog *dialog); static gboolean thunar_chooser_dialog_popup_menu (GtkWidget *tree_view, ThunarChooserDialog *dialog); static void thunar_chooser_dialog_row_activated (GtkTreeView *treeview, @@ -268,7 +267,7 @@ thunar_chooser_dialog_init (ThunarChooserDialog *dialog) renderer = g_object_new (EXO_TYPE_CELL_RENDERER_ICON, "follow-state", FALSE, "size", 24, NULL); gtk_tree_view_column_pack_start (column, renderer, FALSE); gtk_tree_view_column_set_attributes (column, renderer, - "icon", THUNAR_CHOOSER_MODEL_COLUMN_ICON, + "gicon", THUNAR_CHOOSER_MODEL_COLUMN_ICON, NULL); renderer = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, renderer, TRUE); @@ -282,13 +281,11 @@ thunar_chooser_dialog_init (ThunarChooserDialog *dialog) gtk_tree_view_column_set_sort_column_id (column, THUNAR_CHOOSER_MODEL_COLUMN_NAME); gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->tree_view), column); -#if GTK_CHECK_VERSION(2,9,0) - /* don't show the expanders with GTK+ 2.9 and above */ + /* don't show the expanders */ g_object_set (G_OBJECT (dialog->tree_view), "level-indentation", 24, "show-expanders", FALSE, NULL); -#endif /* create the "Custom command" expand */ dialog->custom_expander = gtk_expander_new_with_mnemonic (_("Use a _custom command:")); @@ -408,23 +405,12 @@ static void thunar_chooser_dialog_realize (GtkWidget *widget) { ThunarChooserDialog *dialog = THUNAR_CHOOSER_DIALOG (widget); - GtkTreeModel *model; - GdkCursor *cursor; /* let the GtkWindow class realize the dialog */ (*GTK_WIDGET_CLASS (thunar_chooser_dialog_parent_class)->realize) (widget); /* update the dialog header */ thunar_chooser_dialog_update_header (dialog); - - /* setup a watch cursor if we're currently loading the model */ - model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view)); - if (thunar_chooser_model_get_loading (THUNAR_CHOOSER_MODEL (model))) - { - cursor = gdk_cursor_new (GDK_WATCH); - gdk_window_set_cursor (widget->window, cursor); - gdk_cursor_unref (cursor); - } } @@ -433,37 +419,34 @@ static void thunar_chooser_dialog_response (GtkDialog *widget, gint response) { - ThunarVfsMimeApplication *application = NULL; - ThunarVfsMimeDatabase *mime_database; - ThunarChooserDialog *dialog = THUNAR_CHOOSER_DIALOG (widget); - ThunarVfsMimeInfo *mime_info; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - const gchar *exec; - gboolean succeed = TRUE; - GError *error = NULL; - gchar *path; - gchar *name; - gchar *s; - GList list; + GdkAppLaunchContext *context; + ThunarChooserDialog *dialog = THUNAR_CHOOSER_DIALOG (widget); + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + const gchar *content_type; + const gchar *exec; + GAppInfo *app_info; + gboolean succeed = TRUE; + GError *error = NULL; + gchar *path; + gchar *name; + gchar *s; + GList list; /* no special processing for non-accept responses */ if (G_UNLIKELY (response != GTK_RESPONSE_ACCEPT)) return; - /* grab a reference on the mime database */ - mime_database = thunar_vfs_mime_database_get_default (); - - /* determine the mime info for the file */ - mime_info = thunar_file_get_mime_info (dialog->file); + /* determine the content type for the file */ + content_type = thunar_file_get_content_type (dialog->file); /* determine the application that was chosen by the user */ if (!gtk_expander_get_expanded (GTK_EXPANDER (dialog->custom_expander))) { selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tree_view)); if (gtk_tree_selection_get_selected (selection, &model, &iter)) - gtk_tree_model_get (model, &iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &application, -1); + gtk_tree_model_get (model, &iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &app_info, -1); } else { @@ -480,10 +463,10 @@ thunar_chooser_dialog_response (GtkDialog *widget, name = g_path_get_basename (path); /* try to add an application for the custom command */ - application = thunar_vfs_mime_database_add_application (mime_database, mime_info, name, exec, &error); + app_info = g_app_info_create_from_commandline (exec, name, G_APP_INFO_CREATE_NONE, &error); /* verify the application */ - if (G_UNLIKELY (application == NULL)) + if (G_UNLIKELY (app_info == NULL)) { /* display an error to the user */ thunar_dialogs_show_error (GTK_WIDGET (dialog), error, _("Failed to add new application \"%s\""), name); @@ -498,20 +481,22 @@ thunar_chooser_dialog_response (GtkDialog *widget, } /* verify that we have a valid application */ - if (G_UNLIKELY (application == NULL)) - goto cleanup; + if (G_UNLIKELY (app_info == NULL)) + return; /* check if we should also set the application as default */ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->default_button))) { /* remember the application as default for these kind of file */ - succeed = thunar_vfs_mime_database_set_default_application (mime_database, mime_info, application, &error); + succeed = g_app_info_set_as_default_for_type (app_info, content_type, &error); /* verify that we were successfull */ if (G_UNLIKELY (!succeed)) { /* display an error to the user */ - thunar_dialogs_show_error (GTK_WIDGET (dialog), error, _("Failed to set default application for \"%s\""), + thunar_dialogs_show_error (GTK_WIDGET (dialog), + error, + _("Failed to set default application for \"%s\""), thunar_file_get_display_name (dialog->file)); /* release the error */ @@ -526,23 +511,31 @@ thunar_chooser_dialog_response (GtkDialog *widget, /* check if we should also execute the application */ if (G_LIKELY (succeed && dialog->open)) { - /* open the file using the specified application */ - list.data = thunar_file_get_path (dialog->file); list.next = list.prev = NULL; - if (!thunar_vfs_mime_handler_exec (THUNAR_VFS_MIME_HANDLER (application), gtk_widget_get_screen (GTK_WIDGET (dialog)), &list, &error)) + /* create launch context */ + context = gdk_app_launch_context_new (); + gdk_app_launch_context_set_screen (context, gtk_widget_get_screen (GTK_WIDGET (dialog))); + + /* create fake file list */ + list.data = thunar_file_get_file (dialog->file); list.next = list.prev = NULL; + + if (!g_app_info_launch (app_info, &list, G_APP_LAUNCH_CONTEXT (context), &error)) { /* display an error to the user */ - thunar_dialogs_show_error (GTK_WIDGET (dialog), error, _("Failed to execute \"%s\""), - thunar_vfs_mime_handler_get_name (THUNAR_VFS_MIME_HANDLER (application))); + thunar_dialogs_show_error (GTK_WIDGET (dialog), + error, + _("Failed to execute application \"%s\""), + g_app_info_get_name (app_info)); /* release the error */ g_error_free (error); } + + /* destroy the launch context */ + g_object_unref (context); } /* cleanup */ - g_object_unref (G_OBJECT (application)); -cleanup: - g_object_unref (G_OBJECT (mime_database)); + g_object_unref (app_info); } @@ -578,13 +571,13 @@ thunar_chooser_dialog_context_menu (ThunarChooserDialog *dialog, guint button, guint32 time) { - ThunarVfsMimeApplication *mime_application; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - GtkWidget *image; - GtkWidget *item; - GtkWidget *menu; + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + GtkWidget *image; + GtkWidget *item; + GtkWidget *menu; + GAppInfo *app_info; _thunar_return_val_if_fail (THUNAR_IS_CHOOSER_DIALOG (dialog), FALSE); @@ -593,9 +586,9 @@ thunar_chooser_dialog_context_menu (ThunarChooserDialog *dialog, if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return FALSE; - /* determine the mime application for the row */ - gtk_tree_model_get (model, &iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &mime_application, -1); - if (G_UNLIKELY (mime_application == NULL)) + /* determine the app info for the row */ + gtk_tree_model_get (model, &iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &app_info, -1); + if (G_UNLIKELY (app_info == NULL)) return FALSE; /* prepare the popup menu */ @@ -603,7 +596,8 @@ thunar_chooser_dialog_context_menu (ThunarChooserDialog *dialog, /* append the "Remove Launcher" item */ item = gtk_image_menu_item_new_with_mnemonic (_("_Remove Launcher")); - gtk_widget_set_sensitive (item, thunar_vfs_mime_application_is_usercreated (mime_application)); + /* FIXME Need a way to find out whether the appinfo was created by the user: */ + gtk_widget_set_sensitive (item, FALSE); g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_chooser_dialog_action_remove), dialog); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); @@ -616,7 +610,7 @@ thunar_chooser_dialog_context_menu (ThunarChooserDialog *dialog, thunar_gtk_menu_run (GTK_MENU (menu), GTK_WIDGET (dialog), NULL, NULL, button, time); /* clean up */ - g_object_unref (G_OBJECT (mime_application)); + g_object_unref (app_info); return TRUE; } @@ -662,12 +656,10 @@ thunar_chooser_dialog_update_accept (ThunarChooserDialog *dialog) static void thunar_chooser_dialog_update_header (ThunarChooserDialog *dialog) { - ThunarVfsMimeInfo *mime_info; - ThunarIconFactory *icon_factory; - GtkIconTheme *icon_theme; - const gchar *icon_name; - GdkPixbuf *icon; - gchar *text; + const gchar *content_type; + GIcon *icon; + gchar *description; + gchar *text; _thunar_return_if_fail (THUNAR_IS_CHOOSER_DIALOG (dialog)); _thunar_return_if_fail (GTK_WIDGET_REALIZED (dialog)); @@ -675,32 +667,22 @@ thunar_chooser_dialog_update_header (ThunarChooserDialog *dialog) /* check if we have a valid file set */ if (G_UNLIKELY (dialog->file == NULL)) { -#if GTK_CHECK_VERSION(2,8,0) gtk_image_clear (GTK_IMAGE (dialog->header_image)); -#endif gtk_label_set_text (GTK_LABEL (dialog->header_label), NULL); } else { - /* determine the mime info for the file */ - mime_info = thunar_file_get_mime_info (dialog->file); + content_type = thunar_file_get_content_type (dialog->file); + description = g_content_type_get_description (content_type); - /* determine the icon theme/factory for the widget */ - icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (dialog))); - icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); - - /* update the header image with the icon for the mime type */ - icon_name = thunar_vfs_mime_info_lookup_icon_name (mime_info, icon_theme); - icon = thunar_icon_factory_load_icon (icon_factory, icon_name, 48, NULL, FALSE); - gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->header_image), icon); - gtk_window_set_icon (GTK_WINDOW (dialog), icon); - if (G_LIKELY (icon != NULL)) - g_object_unref (G_OBJECT (icon)); + icon = g_content_type_get_icon (content_type); + gtk_image_set_from_gicon (GTK_IMAGE (dialog->header_image), icon, GTK_ICON_SIZE_DIALOG); + g_object_unref (icon); /* update the header label */ text = g_strdup_printf (_("Open <i>%s</i> and other files of type \"%s\" with:"), thunar_file_get_display_name (dialog->file), - thunar_vfs_mime_info_get_comment (mime_info)); + description); gtk_label_set_markup (GTK_LABEL (dialog->header_label), text); g_free (text); @@ -708,16 +690,16 @@ thunar_chooser_dialog_update_header (ThunarChooserDialog *dialog) thunar_gtk_widget_set_tooltip (dialog->custom_button, _("Browse the file system to select an " "application to open files of type \"%s\"."), - thunar_vfs_mime_info_get_comment (mime_info)); + description); /* update the "Use as default for this kind of file" tooltip */ thunar_gtk_widget_set_tooltip (dialog->default_button, _("Change the default application for files " "of type \"%s\" to the selected application."), - thunar_vfs_mime_info_get_comment (mime_info)); + description); /* cleanup */ - g_object_unref (G_OBJECT (icon_factory)); + g_free (description); } } @@ -726,14 +708,14 @@ thunar_chooser_dialog_update_header (ThunarChooserDialog *dialog) static void thunar_chooser_dialog_action_remove (ThunarChooserDialog *dialog) { - ThunarVfsMimeApplication *mime_application; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - const gchar *name; - GtkWidget *message; - GError *error = NULL; - gint response; + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + const gchar *name; + GtkWidget *message; + GAppInfo *app_info; + GError *error = NULL; + gint response; _thunar_return_if_fail (THUNAR_IS_CHOOSER_DIALOG (dialog)); @@ -742,16 +724,16 @@ thunar_chooser_dialog_action_remove (ThunarChooserDialog *dialog) if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; - /* determine the mime application for the row */ - gtk_tree_model_get (model, &iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &mime_application, -1); - if (G_UNLIKELY (mime_application == NULL)) + /* determine the app info for the row */ + gtk_tree_model_get (model, &iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &app_info, -1); + if (G_UNLIKELY (app_info == NULL)) return; - /* verify that the application is usercreated */ - if (thunar_vfs_mime_application_is_usercreated (mime_application)) + /* FIXME need a way to verify that the application is usercreated */ + if (FALSE) { - /* determine the name of the mime application */ - name = thunar_vfs_mime_handler_get_name (THUNAR_VFS_MIME_HANDLER (mime_application)); + /* determine the name of the app info */ + name = g_app_info_get_name (app_info); /* ask the user whether to remove the application launcher */ message = gtk_message_dialog_new (GTK_WINDOW (dialog), @@ -792,7 +774,7 @@ thunar_chooser_dialog_action_remove (ThunarChooserDialog *dialog) } /* cleanup */ - g_object_unref (G_OBJECT (mime_application)); + g_object_unref (app_info); } @@ -970,16 +952,16 @@ thunar_chooser_dialog_notify_expanded (GtkExpander *expander, static void -thunar_chooser_dialog_notify_loading (ThunarChooserModel *model, - GParamSpec *pspec, - ThunarChooserDialog *dialog) +thunar_chooser_dialog_expand (ThunarChooserDialog *dialog) { - GtkTreePath *path; - GtkTreeIter iter; + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; - _thunar_return_if_fail (THUNAR_IS_CHOOSER_MODEL (model)); _thunar_return_if_fail (THUNAR_IS_CHOOSER_DIALOG (dialog)); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view)); + /* expand the first tree view row (the recommended applications) */ if (G_LIKELY (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))) { @@ -988,7 +970,6 @@ thunar_chooser_dialog_notify_loading (ThunarChooserModel *model, gtk_tree_path_free (path); } -#if GTK_CHECK_VERSION(2,9,0) /* expand the second tree view row (the other applications) */ if (G_LIKELY (gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter))) { @@ -996,7 +977,6 @@ thunar_chooser_dialog_notify_loading (ThunarChooserModel *model, gtk_tree_view_expand_to_path (GTK_TREE_VIEW (dialog->tree_view), path); gtk_tree_path_free (path); } -#endif /* reset the cursor */ if (G_LIKELY (GTK_WIDGET_REALIZED (dialog))) @@ -1072,19 +1052,19 @@ static void thunar_chooser_dialog_selection_changed (GtkTreeSelection *selection, ThunarChooserDialog *dialog) { - ThunarVfsMimeApplication *mime_application; - GtkTreeModel *model; - const gchar *exec; - GtkTreeIter iter; + GAppInfo *app_info; + GtkTreeModel *model; + const gchar *exec; + GtkTreeIter iter; /* determine the iterator for the selected row */ if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - /* determine the mime application for the selected row */ - gtk_tree_model_get (model, &iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &mime_application, -1); + /* determine the app info for the selected row */ + gtk_tree_model_get (model, &iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &app_info, -1); - /* determine the command for the mime application */ - exec = thunar_vfs_mime_handler_get_command (THUNAR_VFS_MIME_HANDLER (mime_application)); + /* determine the command for the app info */ + exec = g_app_info_get_executable (app_info); if (G_LIKELY (exec != NULL && g_utf8_validate (exec, -1, NULL))) { /* setup the command as default for the custom command box */ @@ -1092,7 +1072,7 @@ thunar_chooser_dialog_selection_changed (GtkTreeSelection *selection, } /* cleanup */ - g_object_unref (G_OBJECT (mime_application)); + g_object_unref (app_info); } /* update the sensitivity of the "Ok"/"Open" button */ @@ -1146,7 +1126,6 @@ thunar_chooser_dialog_set_file (ThunarChooserDialog *dialog, ThunarFile *file) { ThunarChooserModel *model; - ThunarVfsMimeInfo *mime_info; _thunar_return_if_fail (THUNAR_IS_CHOOSER_DIALOG (dialog)); _thunar_return_if_fail (file == NULL || THUNAR_IS_FILE (file)); @@ -1179,10 +1158,9 @@ thunar_chooser_dialog_set_file (ThunarChooserDialog *dialog, g_signal_connect_swapped (G_OBJECT (file), "destroy", G_CALLBACK (gtk_widget_destroy), dialog); /* allocate the new chooser model */ - mime_info = thunar_file_get_mime_info (file); - model = thunar_chooser_model_new (mime_info); + model = thunar_chooser_model_new (thunar_file_get_content_type (file)); gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->tree_view), GTK_TREE_MODEL (model)); - g_signal_connect (G_OBJECT (model), "notify::loading", G_CALLBACK (thunar_chooser_dialog_notify_loading), dialog); + thunar_chooser_dialog_expand (dialog); g_object_unref (G_OBJECT (model)); } diff --git a/thunar/thunar-chooser-model.c b/thunar/thunar-chooser-model.c index 8de97bda4..14f789f0d 100644 --- a/thunar/thunar-chooser-model.c +++ b/thunar/thunar-chooser-model.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>. + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -39,14 +40,14 @@ enum { PROP_0, - PROP_LOADING, - PROP_MIME_INFO, + PROP_CONTENT_TYPE, }; static void thunar_chooser_model_class_init (ThunarChooserModelClass *klass); static void thunar_chooser_model_init (ThunarChooserModel *model); +static void thunar_chooser_model_constructed (GObject *object); static void thunar_chooser_model_finalize (GObject *object); static void thunar_chooser_model_get_property (GObject *object, guint prop_id, @@ -56,19 +57,7 @@ static void thunar_chooser_model_set_property (GObject *o guint prop_id, const GValue *value, GParamSpec *pspec); -static void thunar_chooser_model_append (ThunarChooserModel *model, - const gchar *title, - const gchar *icon_name, - GList *applications); -static void thunar_chooser_model_import (ThunarChooserModel *model, - GList *applications); -static GList *thunar_chooser_model_readdir (ThunarChooserModel *model, - const gchar *absdir, - const gchar *reldir); -static gpointer thunar_chooser_model_thread (gpointer user_data); -static gboolean thunar_chooser_model_timer (gpointer user_data); -static void thunar_chooser_model_timer_destroy (gpointer user_data); - +static void thunar_chooser_model_reload (ThunarChooserModel *model); @@ -81,13 +70,7 @@ struct _ThunarChooserModel { GtkTreeStore __parent__; - ThunarVfsMimeInfo *mime_info; - - /* thread interaction */ - gint timer_id; - GThread *thread; - volatile gboolean finished; - volatile gboolean cancelled; + gchar *content_type; }; @@ -135,31 +118,23 @@ thunar_chooser_model_class_init (ThunarChooserModelClass *klass) gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = thunar_chooser_model_finalize; + gobject_class->constructed = thunar_chooser_model_constructed; gobject_class->get_property = thunar_chooser_model_get_property; gobject_class->set_property = thunar_chooser_model_set_property; /** - * ThunarChooserModel::loading: + * ThunarChooserModel::content-type: * - * Whether the contents of the #ThunarChooserModel are - * currently being loaded from disk. + * The content type for the model. **/ g_object_class_install_property (gobject_class, - PROP_LOADING, - g_param_spec_boolean ("loading", "loading", "loading", - FALSE, - EXO_PARAM_READABLE)); - - /** - * ThunarChooserModel::mime-info: - * - * The #ThunarVfsMimeInfo info for the model. - **/ - g_object_class_install_property (gobject_class, - PROP_MIME_INFO, - g_param_spec_boxed ("mime-info", "mime-info", "mime-info", - THUNAR_VFS_TYPE_MIME_INFO, - G_PARAM_CONSTRUCT_ONLY | EXO_PARAM_READWRITE)); + PROP_CONTENT_TYPE, + g_param_spec_string ("content-type", + "content-type", + "content-type", + NULL, + G_PARAM_CONSTRUCT_ONLY | + EXO_PARAM_READWRITE)); } @@ -171,8 +146,8 @@ thunar_chooser_model_init (ThunarChooserModel *model) GType column_types[THUNAR_CHOOSER_MODEL_N_COLUMNS] = { G_TYPE_STRING, - G_TYPE_STRING, - THUNAR_VFS_TYPE_MIME_APPLICATION, + G_TYPE_ICON, + G_TYPE_APP_INFO, PANGO_TYPE_STYLE, G_TYPE_BOOLEAN, PANGO_TYPE_WEIGHT, @@ -180,45 +155,31 @@ thunar_chooser_model_init (ThunarChooserModel *model) }; /* register the column types */ - gtk_tree_store_set_column_types (GTK_TREE_STORE (model), G_N_ELEMENTS (column_types), column_types); - - /* start to load the applications installed on the system */ - model->thread = g_thread_create (thunar_chooser_model_thread, model, TRUE, NULL); - - /* start the timer to monitor the thread */ - model->timer_id = g_timeout_add_full (G_PRIORITY_LOW, 200, thunar_chooser_model_timer, - model, thunar_chooser_model_timer_destroy); + gtk_tree_store_set_column_types (GTK_TREE_STORE (model), + G_N_ELEMENTS (column_types), + column_types); } static void -thunar_chooser_model_finalize (GObject *object) +thunar_chooser_model_constructed (GObject *object) { ThunarChooserModel *model = THUNAR_CHOOSER_MODEL (object); - GList *applications; - /* drop any pending timer */ - if (G_UNLIKELY (model->timer_id >= 0)) - g_source_remove (model->timer_id); + /* start to load the applications installed on the system */ + thunar_chooser_model_reload (model); +} - /* cancel the thread (if running) */ - if (G_UNLIKELY (model->thread != NULL)) - { - /* set the cancellation flag */ - model->cancelled = TRUE; - /* join the thread */ - applications = g_thread_join (model->thread); - /* ditch the returned application list */ - g_list_foreach (applications, (GFunc) g_object_unref, NULL); - g_list_free (applications); - } +static void +thunar_chooser_model_finalize (GObject *object) +{ + ThunarChooserModel *model = THUNAR_CHOOSER_MODEL (object); - /* drop the mime info (if any) */ - if (G_LIKELY (model->mime_info != NULL)) - thunar_vfs_mime_info_unref (model->mime_info); + /* free the content type */ + g_free (model->content_type); (*G_OBJECT_CLASS (thunar_chooser_model_parent_class)->finalize) (object); } @@ -235,12 +196,8 @@ thunar_chooser_model_get_property (GObject *object, switch (prop_id) { - case PROP_LOADING: - g_value_set_boolean (value, thunar_chooser_model_get_loading (model)); - break; - - case PROP_MIME_INFO: - g_value_set_boxed (value, thunar_chooser_model_get_mime_info (model)); + case PROP_CONTENT_TYPE: + g_value_set_string (value, thunar_chooser_model_get_content_type (model)); break; default: @@ -261,9 +218,8 @@ thunar_chooser_model_set_property (GObject *object, switch (prop_id) { - case PROP_MIME_INFO: - if (G_LIKELY (model->mime_info == NULL)) - model->mime_info = g_value_dup_boxed (value); + case PROP_CONTENT_TYPE: + model->content_type = g_value_dup_string (value); break; default: @@ -278,40 +234,39 @@ static void thunar_chooser_model_append (ThunarChooserModel *model, const gchar *title, const gchar *icon_name, - GList *applications) + GList *app_infos) { - GtkIconTheme *icon_theme; - GtkTreeIter parent_iter; - GtkTreeIter child_iter; - GList *lp; + GtkTreeIter child_iter; + GtkTreeIter parent_iter; + GIcon *icon; + GList *lp; _thunar_return_if_fail (THUNAR_IS_CHOOSER_MODEL (model)); _thunar_return_if_fail (title != NULL); _thunar_return_if_fail (icon_name != NULL); - /* query the default icon theme */ - icon_theme = gtk_icon_theme_get_default (); + icon = g_themed_icon_new (icon_name); - /* insert the section title */ gtk_tree_store_append (GTK_TREE_STORE (model), &parent_iter, NULL); gtk_tree_store_set (GTK_TREE_STORE (model), &parent_iter, THUNAR_CHOOSER_MODEL_COLUMN_NAME, title, - THUNAR_CHOOSER_MODEL_COLUMN_ICON, icon_name, + THUNAR_CHOOSER_MODEL_COLUMN_ICON, icon, THUNAR_CHOOSER_MODEL_COLUMN_WEIGHT, PANGO_WEIGHT_SEMIBOLD, THUNAR_CHOOSER_MODEL_COLUMN_WEIGHT_SET, TRUE, -1); - /* check if we have any program items */ - if (G_LIKELY (applications != NULL)) + g_object_unref (icon); + + if (G_LIKELY (app_infos != NULL)) { /* insert the program items */ - for (lp = applications; lp != NULL; lp = lp->next) + for (lp = app_infos; lp != NULL; lp = lp->next) { /* append the tree row with the program data */ gtk_tree_store_append (GTK_TREE_STORE (model), &child_iter, &parent_iter); gtk_tree_store_set (GTK_TREE_STORE (model), &child_iter, - THUNAR_CHOOSER_MODEL_COLUMN_NAME, thunar_vfs_mime_handler_get_name (lp->data), - THUNAR_CHOOSER_MODEL_COLUMN_ICON, thunar_vfs_mime_handler_lookup_icon_name (lp->data, icon_theme), + THUNAR_CHOOSER_MODEL_COLUMN_NAME, g_app_info_get_name (lp->data), + THUNAR_CHOOSER_MODEL_COLUMN_ICON, g_app_info_get_icon (lp->data), THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, lp->data, -1); } @@ -330,286 +285,96 @@ thunar_chooser_model_append (ThunarChooserModel *model, -static void -thunar_chooser_model_import (ThunarChooserModel *model, - GList *applications) +static gint +compare_app_infos (gconstpointer a, + gconstpointer b) { - ThunarVfsMimeDatabase *mime_database; - GList *recommended; - GList *other = NULL; - GList *lp; - GList *p; - - _thunar_return_if_fail (THUNAR_IS_CHOOSER_MODEL (model)); - _thunar_return_if_fail (model->mime_info != NULL); - - /* determine the recommended applications for the mime info */ - mime_database = thunar_vfs_mime_database_get_default (); - recommended = thunar_vfs_mime_database_get_applications (mime_database, model->mime_info); - g_object_unref (G_OBJECT (mime_database)); - - /* add all applications to other that are not already on recommended */ - for (lp = applications; lp != NULL; lp = lp->next) - { - /* check if this application is already on the recommended list */ - for (p = recommended; p != NULL; p = p->next) - if (thunar_vfs_mime_application_equal (p->data, lp->data)) - break; - - /* add to the list of other applications if it's not on recommended */ - if (G_LIKELY (p == NULL)) - other = g_list_append (other, lp->data); - } - - /* append the "Recommended Applications:" category */ - thunar_chooser_model_append (model, _("Recommended Applications"), "preferences-desktop-default-applications", recommended); - - /* append the "Other Applications:" category */ - thunar_chooser_model_append (model, _("Other Applications"), "gnome-applications", other); - - /* cleanup */ - g_list_foreach (recommended, (GFunc) g_object_unref, NULL); - g_list_free (recommended); - g_list_free (other); + return g_app_info_equal (G_APP_INFO (a), G_APP_INFO (b)) ? 0 : 1; } -static GList* -thunar_chooser_model_readdir (ThunarChooserModel *model, - const gchar *absdir, - const gchar *reldir) +static void +thunar_chooser_model_reload (ThunarChooserModel *model) { - ThunarVfsMimeApplication *application; - const gchar *name; - GList *applications = NULL; - gchar *abspath; - gchar *relpath; - gchar *p; - GDir *dp; - - _thunar_return_val_if_fail (THUNAR_IS_CHOOSER_MODEL (model), NULL); - _thunar_return_val_if_fail (reldir == NULL || !g_path_is_absolute (reldir), NULL); - _thunar_return_val_if_fail (g_path_is_absolute (absdir), NULL); - - /* try to open the directory */ - dp = g_dir_open (absdir, 0, NULL); - if (G_LIKELY (dp != NULL)) - { - /* process the files within the directory */ - while (!model->cancelled) - { - /* read the next file entry */ - name = g_dir_read_name (dp); - if (G_UNLIKELY (name == NULL)) - break; - - /* generate the absolute path to the file entry */ - abspath = g_build_filename (absdir, name, NULL); - - /* generate the relative path to the file entry */ - relpath = (reldir != NULL) ? g_build_filename (reldir, name, NULL) : g_strdup (name); - - /* check if we have a directory or a regular file here */ - if (g_file_test (abspath, G_FILE_TEST_IS_DIR)) - { - /* recurse for directories */ - applications = g_list_concat (applications, thunar_chooser_model_readdir (model, abspath, relpath)); - } - else if (g_file_test (abspath, G_FILE_TEST_IS_REGULAR) && g_str_has_suffix (name, ".desktop")) - { - /* generate the desktop-id from the relative path */ - for (p = relpath; *p != '\0'; ++p) - if (*p == G_DIR_SEPARATOR) - *p = '-'; - - /* try to load the application for the given desktop-id */ - application = thunar_vfs_mime_application_new_from_file (abspath, relpath); - - /* check if we have successfully loaded the application */ - if (G_LIKELY (application != NULL)) - { - /* check if the application supports atleast one mime-type */ - if (thunar_vfs_mime_application_get_mime_types (application) != NULL) - applications = g_list_append (applications, application); - else - g_object_unref (G_OBJECT (application)); - } - } - - /* cleanup */ - g_free (abspath); - g_free (relpath); - } + GList *all; + GList *lp; + GList *other = NULL; + GList *recommended; - /* close the directory handle */ - g_dir_close (dp); - } + _thunar_return_if_fail (THUNAR_IS_CHOOSER_MODEL (model)); + _thunar_return_if_fail (model->content_type != NULL); - return applications; -} + gtk_tree_store_clear (GTK_TREE_STORE (model)); + /* check if we have any applications for this type */ + recommended = g_app_info_get_all_for_type (model->content_type); + /* append them as recommended */ + thunar_chooser_model_append (model, + _("Recommended Applications"), + "preferences-desktop-default-applications", + recommended); -static gint -compare_application_by_name (gconstpointer a, - gconstpointer b) -{ - return strcmp (thunar_vfs_mime_handler_get_name (a), - thunar_vfs_mime_handler_get_name (b)); -} - - - -static gpointer -thunar_chooser_model_thread (gpointer user_data) -{ - ThunarChooserModel *model = THUNAR_CHOOSER_MODEL (user_data); - GList *applications = NULL; - GList *list; - GList *lp; - GList *p; - gchar **paths; - guint n; - - /* determine the available applications/ directories */ - paths = xfce_resource_lookup_all (XFCE_RESOURCE_DATA, "applications/"); - for (n = 0; !model->cancelled && paths[n] != NULL; ++n) + all = g_app_info_get_all (); + for (lp = g_list_last (all); lp != NULL; lp = lp->prev) { - /* lookup the applications in this directory */ - list = thunar_chooser_model_readdir (model, paths[n], NULL); - - /* merge the applications with what we already have */ - for (lp = list; lp != NULL; lp = lp->next) + if (g_list_find_custom (recommended, + lp->data, + (GCompareFunc) compare_app_infos) == NULL) { - /* ignore hidden applications to be compatible with the Nautilus mess */ - if ((thunar_vfs_mime_handler_get_flags (lp->data) & THUNAR_VFS_MIME_HANDLER_HIDDEN) != 0) - { - g_object_unref (G_OBJECT (lp->data)); - continue; - } - - /* check if we have that application already */ - for (p = applications; p != NULL; p = p->next) - { - /* compare the desktop-ids */ - if (thunar_vfs_mime_application_equal (p->data, lp->data)) - break; - } - - /* no need to add if we have it already */ - if (G_UNLIKELY (p != NULL)) - { - g_object_unref (G_OBJECT (lp->data)); - continue; - } - - /* insert the application into the list */ - applications = g_list_insert_sorted (applications, lp->data, compare_application_by_name); + other = g_list_prepend (other, lp->data); } - - /* free the temporary list */ - g_list_free (list); - } - g_strfreev (paths); - - /* tell the model that we're done */ - model->finished = TRUE; - - return applications; -} - - - -static gboolean -thunar_chooser_model_timer (gpointer user_data) -{ - ThunarChooserModel *model = THUNAR_CHOOSER_MODEL (user_data); - gboolean finished; - GList *applications; - - /* check if the applications are loaded */ - GDK_THREADS_ENTER (); - finished = model->finished; - if (G_LIKELY (finished)) - { - /* grab the application list from the thread */ - applications = g_thread_join (model->thread); - model->thread = NULL; - - /* process the applications list */ - thunar_chooser_model_import (model, applications); - - /* tell everybody that the model is loaded */ - g_object_notify (G_OBJECT (model), "loading"); - - /* free the application list */ - g_list_foreach (applications, (GFunc) g_object_unref, NULL); - g_list_free (applications); } - GDK_THREADS_LEAVE (); - return !finished; -} + /* append the other applications */ + thunar_chooser_model_append (model, + _("Other Applications"), + "gnome-applications", + other); + g_list_foreach (recommended, (GFunc) g_object_unref, NULL); + g_list_free (recommended); + g_list_foreach (all, (GFunc) g_object_unref, NULL); + g_list_free (all); -static void -thunar_chooser_model_timer_destroy (gpointer user_data) -{ - THUNAR_CHOOSER_MODEL (user_data)->timer_id = -1; + g_list_free (other); } /** * thunar_chooser_model_new: - * @mime_info : a #ThunarVfsMimeInfo. + * @content_type : the content type for this model. * - * Allocates a new #ThunarChooserModel for @mime_info. + * Allocates a new #ThunarChooserModel for @content_type. * * Return value: the newly allocated #ThunarChooserModel. **/ -ThunarChooserModel* -thunar_chooser_model_new (ThunarVfsMimeInfo *mime_info) +ThunarChooserModel * +thunar_chooser_model_new (const gchar *content_type) { return g_object_new (THUNAR_TYPE_CHOOSER_MODEL, - "mime-info", mime_info, + "content-type", content_type, NULL); } /** - * thunar_chooser_model_get_loading: - * @model : a #ThunarChooserModel. - * - * Returns %TRUE if @model is currently being loaded. - * - * Return value: %TRUE if @model is currently being loaded. - **/ -gboolean -thunar_chooser_model_get_loading (ThunarChooserModel *model) -{ - _thunar_return_val_if_fail (THUNAR_IS_CHOOSER_MODEL (model), FALSE); - return (model->thread != NULL); -} - - - -/** - * thunar_chooser_model_get_mime_info: + * thunar_chooser_model_get_content_type: * @model : a #ThunarChooserModel. * - * Returns the #ThunarVfsMimeInfo for @model. + * Returns the content type for @model. * - * Return value: the #ThunarVfsMimeInfo for @model. + * Return value: the content type for @model. **/ -ThunarVfsMimeInfo* -thunar_chooser_model_get_mime_info (ThunarChooserModel *model) +const gchar * +thunar_chooser_model_get_content_type (ThunarChooserModel *model) { _thunar_return_val_if_fail (THUNAR_IS_CHOOSER_MODEL (model), NULL); - return model->mime_info; + return model->content_type; } @@ -631,24 +396,29 @@ thunar_chooser_model_remove (ThunarChooserModel *model, GtkTreeIter *iter, GError **error) { - ThunarVfsMimeApplication *mime_application; - ThunarVfsMimeDatabase *mime_database; - gboolean succeed; + GAppInfo *app_info; + gboolean succeed; _thunar_return_val_if_fail (THUNAR_IS_CHOOSER_MODEL (model), FALSE); _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); _thunar_return_val_if_fail (gtk_tree_store_iter_is_valid (GTK_TREE_STORE (model), iter), FALSE); - /* determine the mime application for the iter */ - gtk_tree_model_get (GTK_TREE_MODEL (model), iter, THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &mime_application, -1); - if (G_UNLIKELY (mime_application == NULL)) + /* determine the app info for the iter */ + gtk_tree_model_get (GTK_TREE_MODEL (model), + iter, + THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION, &app_info, + -1); + + if (G_UNLIKELY (app_info == NULL)) return TRUE; - /* try to remove the application from the database */ - mime_database = thunar_vfs_mime_database_get_default (); - succeed = thunar_vfs_mime_database_remove_application (mime_database, mime_application, error); - g_object_unref (G_OBJECT (mime_application)); - g_object_unref (G_OBJECT (mime_database)); + /* try to remove support for this content type */ + succeed = g_app_info_remove_supports_type (app_info, + model->content_type, + error); + + /* clean up */ + g_object_unref (app_info); /* if the removal was successfull, delete the row from the model */ if (G_LIKELY (succeed)) diff --git a/thunar/thunar-chooser-model.h b/thunar/thunar-chooser-model.h index f6403a260..ab5021688 100644 --- a/thunar/thunar-chooser-model.h +++ b/thunar/thunar-chooser-model.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>. + * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -20,7 +21,7 @@ #ifndef __THUNAR_CHOOSER_MODEL_H__ #define __THUNAR_CHOOSER_MODEL_H__ -#include <thunar-vfs/thunar-vfs.h> +#include <gtk/gtk.h> G_BEGIN_DECLS; @@ -38,7 +39,7 @@ typedef struct _ThunarChooserModel ThunarChooserModel; * ThunarChooserModelColumn: * @THUNAR_CHOOSER_MODEL_COLUMN_NAME : the name of the application. * @THUNAR_CHOOSER_MODEL_COLUMN_ICON : the name or absolute path of the application's icon. - * @THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION : the #ThunarVfsMimeApplication object. + * @THUNAR_CHOOSER_MODEL_COLUMN_APPLICATION : the #GAppInfo object. * @THUNAR_CHOOSER_MODEL_COLUMN_STYLE : custom font style. * @THUNAR_CHOOSER_MODEL_COLUMN_STYLE_SET : whether to actually use the custom font style. * @THUNAR_CHOOSER_MODEL_N_COLUMNS : the number of columns in #ThunarChooserModel. @@ -57,17 +58,13 @@ typedef enum THUNAR_CHOOSER_MODEL_N_COLUMNS, } ThunarChooserModelColumn; -GType thunar_chooser_model_get_type (void) G_GNUC_CONST; +GType thunar_chooser_model_get_type (void) G_GNUC_CONST; -ThunarChooserModel *thunar_chooser_model_new (ThunarVfsMimeInfo *mime_info) G_GNUC_MALLOC; - -gboolean thunar_chooser_model_get_loading (ThunarChooserModel *model); - -ThunarVfsMimeInfo *thunar_chooser_model_get_mime_info (ThunarChooserModel *model); - -gboolean thunar_chooser_model_remove (ThunarChooserModel *model, - GtkTreeIter *iter, - GError **error); +ThunarChooserModel *thunar_chooser_model_new (const gchar *content_type) G_GNUC_MALLOC; +const gchar *thunar_chooser_model_get_content_type (ThunarChooserModel *model); +gboolean thunar_chooser_model_remove (ThunarChooserModel *model, + GtkTreeIter *iter, + GError **error); G_END_DECLS; diff --git a/thunar/thunar-clipboard-manager.c b/thunar/thunar-clipboard-manager.c index 2e02ad86a..adc9dc671 100644 --- a/thunar/thunar-clipboard-manager.c +++ b/thunar/thunar-clipboard-manager.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -108,7 +109,7 @@ struct _ThunarClipboardManager typedef struct { ThunarClipboardManager *manager; - ThunarVfsPath *target_path; + GFile *target_file; GtkWidget *widget; GClosure *new_files_closure; } ThunarClipboardPasteRequest; @@ -301,7 +302,7 @@ thunar_clipboard_manager_contents_received (GtkClipboard *clipboard, ThunarClipboardManager *manager = THUNAR_CLIPBOARD_MANAGER (request->manager); ThunarApplication *application; gboolean path_copy = TRUE; - GList *path_list = NULL; + GList *file_list = NULL; gchar *data; /* check whether the retrieval worked */ @@ -324,19 +325,19 @@ thunar_clipboard_manager_contents_received (GtkClipboard *clipboard, } /* determine the path list stored with the selection */ - path_list = thunar_vfs_path_list_from_string (data, NULL); + file_list = thunar_g_file_list_new_from_string (data); } /* perform the action if possible */ - if (G_LIKELY (path_list != NULL)) + if (G_LIKELY (file_list != NULL)) { application = thunar_application_get (); if (G_LIKELY (path_copy)) - thunar_application_copy_into (application, request->widget, path_list, request->target_path, request->new_files_closure); + thunar_application_copy_into (application, request->widget, file_list, request->target_file, request->new_files_closure); else - thunar_application_move_into (application, request->widget, path_list, request->target_path, request->new_files_closure); + thunar_application_move_into (application, request->widget, file_list, request->target_file, request->new_files_closure); g_object_unref (G_OBJECT (application)); - thunar_vfs_path_list_free (path_list); + thunar_g_file_list_free (file_list); /* clear the clipboard if it contained "cutted data" * (gtk_clipboard_clear takes care of not clearing @@ -345,13 +346,9 @@ thunar_clipboard_manager_contents_received (GtkClipboard *clipboard, if (G_UNLIKELY (!path_copy)) gtk_clipboard_clear (manager->clipboard); - /* check the contents of the clipboard again - * if either the Xserver or our GTK+ version - * doesn't support the XFixes extension. - */ -#if GTK_CHECK_VERSION(2,6,0) + /* check the contents of the clipboard again if either the Xserver or + * our GTK+ version doesn't support the XFixes extension */ if (!gdk_display_supports_selection_notification (gtk_clipboard_get_display (manager->clipboard))) -#endif { thunar_clipboard_manager_owner_changed (manager->clipboard, NULL, manager); } @@ -368,7 +365,7 @@ thunar_clipboard_manager_contents_received (GtkClipboard *clipboard, if (G_LIKELY (request->new_files_closure != NULL)) g_closure_unref (request->new_files_closure); g_object_unref (G_OBJECT (request->manager)); - thunar_vfs_path_unref (request->target_path); + g_object_unref (request->target_file); _thunar_slice_free (ThunarClipboardPasteRequest, request); } @@ -405,11 +402,11 @@ thunar_clipboard_manager_targets_received (GtkClipboard *clipboard, } /* notify listeners that we have a new clipboard state */ - g_signal_emit (G_OBJECT (manager), manager_signals[CHANGED], 0); + g_signal_emit (manager, manager_signals[CHANGED], 0); g_object_notify (G_OBJECT (manager), "can-paste"); /* drop the reference taken for the callback */ - g_object_unref (G_OBJECT (manager)); + g_object_unref (manager); } @@ -421,7 +418,7 @@ thunar_clipboard_manager_get_callback (GtkClipboard *clipboard, gpointer user_data) { ThunarClipboardManager *manager = THUNAR_CLIPBOARD_MANAGER (user_data); - GList *path_list = NULL; + GList *file_list = NULL; gchar *string_list; gchar *data; @@ -430,10 +427,10 @@ thunar_clipboard_manager_get_callback (GtkClipboard *clipboard, _thunar_return_if_fail (manager->clipboard == clipboard); /* determine the path list from the file list */ - path_list = thunar_file_list_to_path_list (manager->files); + file_list = thunar_file_list_to_thunar_g_file_list (manager->files); /* determine the string representation of the path list */ - string_list = thunar_vfs_path_list_to_string (path_list); + string_list = thunar_g_file_list_to_string (file_list); switch (target_info) { @@ -452,7 +449,7 @@ thunar_clipboard_manager_get_callback (GtkClipboard *clipboard, } /* cleanup */ - thunar_vfs_path_list_free (path_list); + thunar_g_file_list_free (file_list); g_free (string_list); } @@ -516,12 +513,8 @@ thunar_clipboard_manager_transfer_files (ThunarClipboardManager *manager, G_OBJECT (manager)); /* Need to fake a "owner-change" event here if the Xserver doesn't support clipboard notification */ -#if GTK_CHECK_VERSION(2,6,0) if (!gdk_display_supports_selection_notification (gtk_clipboard_get_display (manager->clipboard))) -#endif - { - thunar_clipboard_manager_owner_changed (manager->clipboard, NULL, manager); - } + thunar_clipboard_manager_owner_changed (manager->clipboard, NULL, manager); } @@ -657,21 +650,21 @@ thunar_clipboard_manager_cut_files (ThunarClipboardManager *manager, /** * thunar_clipboard_manager_paste_files: * @manager : a #ThunarClipboardManager. - * @target_path : the #ThunarVfsPath of the folder to which the contents on the clipboard + * @target_file : the #GFile of the folder to which the contents on the clipboard * should be pasted. * @widget : a #GtkWidget, on which to perform the paste or %NULL if no widget is * known. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the - * list of #ThunarVfsPath<!---->s created by the job, or + * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * * Pastes the contents from the clipboard associated with @manager to the directory - * referenced by @target_path. + * referenced by @target_file. **/ void thunar_clipboard_manager_paste_files (ThunarClipboardManager *manager, - ThunarVfsPath *target_path, + GFile *target_file, GtkWidget *widget, GClosure *new_files_closure) { @@ -683,7 +676,7 @@ thunar_clipboard_manager_paste_files (ThunarClipboardManager *manager, /* prepare the paste request */ request = _thunar_slice_new0 (ThunarClipboardPasteRequest); request->manager = g_object_ref (G_OBJECT (manager)); - request->target_path = thunar_vfs_path_ref (target_path); + request->target_file = g_object_ref (target_file); request->widget = widget; /* take a reference on the closure (if any) */ diff --git a/thunar/thunar-clipboard-manager.h b/thunar/thunar-clipboard-manager.h index 88867c56c..c0c2c90f2 100644 --- a/thunar/thunar-clipboard-manager.h +++ b/thunar/thunar-clipboard-manager.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -48,7 +49,7 @@ void thunar_clipboard_manager_copy_files (ThunarClipboar void thunar_clipboard_manager_cut_files (ThunarClipboardManager *manager, GList *files); void thunar_clipboard_manager_paste_files (ThunarClipboardManager *manager, - ThunarVfsPath *target_path, + GFile *target_file, GtkWidget *widget, GClosure *new_files_closure); diff --git a/thunar/thunar-create-dialog.c b/thunar/thunar-create-dialog.c index 94d3d4baa..591f79280 100644 --- a/thunar/thunar-create-dialog.c +++ b/thunar/thunar-create-dialog.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -36,7 +37,7 @@ enum { PROP_0, PROP_FILENAME, - PROP_MIME_INFO, + PROP_CONTENT_TYPE, }; @@ -68,10 +69,10 @@ struct _ThunarCreateDialog { ThunarAbstractDialog __parent__; - GtkWidget *image; - GtkWidget *entry; + GtkWidget *image; + GtkWidget *entry; - ThunarVfsMimeInfo *mime_info; + gchar *content_type; }; @@ -87,21 +88,13 @@ thunar_create_dialog_get_type (void) if (G_UNLIKELY (type == G_TYPE_INVALID)) { - static const GTypeInfo info = - { - sizeof (ThunarCreateDialogClass), - NULL, - NULL, - (GClassInitFunc) thunar_create_dialog_class_init, - NULL, - NULL, - sizeof (ThunarCreateDialog), - 0, - (GInstanceInitFunc) thunar_create_dialog_init, - NULL, - }; - - type = g_type_register_static (THUNAR_TYPE_ABSTRACT_DIALOG, I_("ThunarCreateDialog"), &info, 0); + type = g_type_register_static_simple (THUNAR_TYPE_ABSTRACT_DIALOG, + I_("ThunarCreateDialog"), + sizeof (ThunarCreateDialogClass), + (GClassInitFunc) thunar_create_dialog_class_init, + sizeof (ThunarCreateDialog), + (GInstanceInitFunc) thunar_create_dialog_init, + 0); } return type; @@ -133,19 +126,23 @@ thunar_create_dialog_class_init (ThunarCreateDialogClass *klass) **/ g_object_class_install_property (gobject_class, PROP_FILENAME, - g_param_spec_string ("filename", "filename", "filename", + g_param_spec_string ("filename", + "filename", + "filename", NULL, EXO_PARAM_READWRITE)); /** - * ThunarCreateDialog::mime-info: + * ThunarCreateDialog::content-type: * - * The #ThunarVfsMimeInfo of the file to create. + * The content type of the file to create. **/ g_object_class_install_property (gobject_class, - PROP_MIME_INFO, - g_param_spec_boxed ("mime-info", "mime-info", "mime-info", - THUNAR_VFS_TYPE_MIME_INFO, + PROP_CONTENT_TYPE, + g_param_spec_string ("content-type", + "content-type", + "content-type", + NULL, EXO_PARAM_READWRITE)); } @@ -157,6 +154,8 @@ thunar_create_dialog_init (ThunarCreateDialog *dialog) GtkWidget *label; GtkWidget *table; + dialog->content_type = NULL; + /* configure the dialog itself */ gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, @@ -193,8 +192,8 @@ thunar_create_dialog_dispose (GObject *object) { ThunarCreateDialog *dialog = THUNAR_CREATE_DIALOG (object); - /* release the mime info (if any) */ - thunar_create_dialog_set_mime_info (dialog, NULL); + /* release the content type */ + thunar_create_dialog_set_content_type (dialog, NULL); (*G_OBJECT_CLASS (thunar_create_dialog_parent_class)->dispose) (object); } @@ -215,8 +214,8 @@ thunar_create_dialog_get_property (GObject *object, g_value_set_string (value, thunar_create_dialog_get_filename (dialog)); break; - case PROP_MIME_INFO: - g_value_set_boxed (value, thunar_create_dialog_get_mime_info (dialog)); + case PROP_CONTENT_TYPE: + g_value_set_string (value, thunar_create_dialog_get_content_type (dialog)); break; default: @@ -241,8 +240,8 @@ thunar_create_dialog_set_property (GObject *object, thunar_create_dialog_set_filename (dialog, g_value_get_string (value)); break; - case PROP_MIME_INFO: - thunar_create_dialog_set_mime_info (dialog, g_value_get_boxed (value)); + case PROP_CONTENT_TYPE: + thunar_create_dialog_set_content_type (dialog, g_value_get_string (value)); break; default: @@ -270,39 +269,21 @@ thunar_create_dialog_realize (GtkWidget *widget) static void thunar_create_dialog_update_image (ThunarCreateDialog *dialog) { - ThunarIconFactory *icon_factory; - GtkIconTheme *icon_theme; - const gchar *icon_name; - GdkPixbuf *icon = NULL; - - /* check if we have a mime info */ - if (G_LIKELY (dialog->mime_info != NULL)) - { - /* determine the icon theme and factory for the current screen */ - icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (dialog))); - icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); + GIcon *icon = NULL; - /* determine the icon name for the mime info */ - icon_name = thunar_vfs_mime_info_lookup_icon_name (dialog->mime_info, icon_theme); - - /* try to load the icon for the given name */ - icon = thunar_icon_factory_load_icon (icon_factory, icon_name, 48, NULL, FALSE); - - /* release the icon factory */ - g_object_unref (G_OBJECT (icon_factory)); - } + /* try to load the icon */ + if (G_LIKELY (dialog->content_type != NULL)) + icon = g_content_type_get_icon (dialog->content_type); /* setup the image */ if (G_LIKELY (icon != NULL)) { - gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->image), icon); - g_object_unref (G_OBJECT (icon)); + gtk_image_set_from_gicon (GTK_IMAGE (dialog->image), icon, GTK_ICON_SIZE_DIALOG); + g_object_unref (icon); gtk_widget_show (dialog->image); } else - { - gtk_widget_hide (dialog->image); - } + gtk_widget_hide (dialog->image); } @@ -398,12 +379,12 @@ thunar_create_dialog_set_filename (ThunarCreateDialog *dialog, /* select the text prior to the dot */ if (G_LIKELY (offset > 0)) - gtk_entry_select_region (GTK_ENTRY (dialog->entry), 0, offset); + gtk_editable_select_region (GTK_EDITABLE (dialog->entry), 0, offset); } else { /* select the whole file name */ - gtk_entry_select_region (GTK_ENTRY (dialog->entry), 0, -1); + gtk_editable_select_region (GTK_EDITABLE (dialog->entry), 0, -1); } /* notify listeners */ @@ -413,63 +394,57 @@ thunar_create_dialog_set_filename (ThunarCreateDialog *dialog, /** - * thunar_create_dialog_get_mime_info: + * thunar_create_dialog_get_content_type: * @dialog : a #ThunarCreateDialog. * - * Returns the current mime info for @dialog - * or %NULL. + * Returns the current content type for @dialog or %NULL. * - * Return value: the mime info for @dialog. + * Return value: the content type for @dialog. **/ -ThunarVfsMimeInfo* -thunar_create_dialog_get_mime_info (const ThunarCreateDialog *dialog) +const gchar * +thunar_create_dialog_get_content_type (const ThunarCreateDialog *dialog) { _thunar_return_val_if_fail (THUNAR_IS_CREATE_DIALOG (dialog), NULL); - return dialog->mime_info; + return dialog->content_type; } /** - * thunar_create_dialog_set_mime_info: - * @dialog : a #ThunarCreateDialog. - * @mime_info : the new #ThunarVfsMimeInfo or %NULL. + * thunar_create_dialog_set_content_type: + * @dialog : a #ThunarCreateDialog. + * @content_type : the new content type. * - * Set the mime info for @dialog to @mime_info. + * Set the content type for @dialog to @content_type. **/ void -thunar_create_dialog_set_mime_info (ThunarCreateDialog *dialog, - ThunarVfsMimeInfo *mime_info) +thunar_create_dialog_set_content_type (ThunarCreateDialog *dialog, + const gchar *content_type) { _thunar_return_if_fail (THUNAR_IS_CREATE_DIALOG (dialog)); - /* release the previous mime info */ - if (G_UNLIKELY (dialog->mime_info != NULL)) - thunar_vfs_mime_info_unref (dialog->mime_info); - - /* activate the new mime info */ - dialog->mime_info = mime_info; + /* release the previous content type */ + g_free (dialog->content_type); - /* take a reference on the mime info */ - if (G_LIKELY (mime_info != NULL)) - thunar_vfs_mime_info_ref (mime_info); + /* set the new content type */ + dialog->content_type = g_strdup (content_type); /* update the image if we're already realized */ if (GTK_WIDGET_REALIZED (dialog)) thunar_create_dialog_update_image (dialog); /* notify listeners */ - g_object_notify (G_OBJECT (dialog), "mime-info"); + g_object_notify (G_OBJECT (dialog), "content-type"); } /** * thunar_show_create_dialog: - * @parent : the parent widget or %NULL. - * @mime_info : the #ThunarVfsMimeInfo of the file or folder to create. - * @filename : the suggested filename or %NULL. - * @title : the dialog title. + * @parent : the parent widget or %NULL. + * @content_type : the content type of the file or folder to create. + * @filename : the suggested filename or %NULL. + * @title : the dialog title. * * Constructs and display a #ThunarCreateDialog with the specified * parameters that asks the user to enter a name for a new file or @@ -482,10 +457,10 @@ thunar_create_dialog_set_mime_info (ThunarCreateDialog *dialog, * cancelled the dialog. **/ gchar* -thunar_show_create_dialog (GtkWidget *parent, - ThunarVfsMimeInfo *mime_info, - const gchar *filename, - const gchar *title) +thunar_show_create_dialog (GtkWidget *parent, + const gchar *content_type, + const gchar *filename, + const gchar *title) { GtkWidget *dialog; GtkWidget *window; @@ -501,7 +476,7 @@ thunar_show_create_dialog (GtkWidget *parent, dialog = g_object_new (THUNAR_TYPE_CREATE_DIALOG, "destroy-with-parent", TRUE, "filename", filename, - "mime-info", mime_info, + "content-type", content_type, "modal", TRUE, "title", title, NULL); diff --git a/thunar/thunar-create-dialog.h b/thunar/thunar-create-dialog.h index e8aca253f..2d3d30b5b 100644 --- a/thunar/thunar-create-dialog.h +++ b/thunar/thunar-create-dialog.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -20,7 +21,7 @@ #ifndef __THUNAR_CREATE_DIALOG_H__ #define __THUNAR_CREATE_DIALOG_H__ -#include <thunar-vfs/thunar-vfs.h> +#include <gtk/gtk.h> G_BEGIN_DECLS; @@ -34,22 +35,22 @@ typedef struct _ThunarCreateDialog ThunarCreateDialog; #define THUNAR_IS_CREATE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_CREATE_DIALOG)) #define THUNAR_CREATE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_CREATE_DIALOG, ThunarCreateDialogClass)) -GType thunar_create_dialog_get_type (void) G_GNUC_CONST; +GType thunar_create_dialog_get_type (void) G_GNUC_CONST; -GtkWidget *thunar_create_dialog_new (void) G_GNUC_MALLOC; +GtkWidget *thunar_create_dialog_new (void) G_GNUC_MALLOC; -const gchar *thunar_create_dialog_get_filename (const ThunarCreateDialog *dialog); -void thunar_create_dialog_set_filename (ThunarCreateDialog *dialog, - const gchar *filename); +const gchar *thunar_create_dialog_get_filename (const ThunarCreateDialog *dialog); +void thunar_create_dialog_set_filename (ThunarCreateDialog *dialog, + const gchar *filename); -ThunarVfsMimeInfo *thunar_create_dialog_get_mime_info (const ThunarCreateDialog *dialog); -void thunar_create_dialog_set_mime_info (ThunarCreateDialog *dialog, - ThunarVfsMimeInfo *mime_info); +const gchar *thunar_create_dialog_get_content_type (const ThunarCreateDialog *dialog); +void thunar_create_dialog_set_content_type (ThunarCreateDialog *dialog, + const gchar *content_type); -gchar *thunar_show_create_dialog (GtkWidget *parent, - ThunarVfsMimeInfo *mime_info, - const gchar *filename, - const gchar *title) G_GNUC_MALLOC; +gchar *thunar_show_create_dialog (GtkWidget *parent, + const gchar *content_type, + const gchar *filename, + const gchar *title) G_GNUC_MALLOC; G_END_DECLS; diff --git a/thunar/thunar-dbus-client.c b/thunar/thunar-dbus-client.c index e5bc460aa..83d817492 100644 --- a/thunar/thunar-dbus-client.c +++ b/thunar/thunar-dbus-client.c @@ -37,6 +37,8 @@ * @standalone : whether to run the bulk renamer in standalone mode. * @screen : the #GdkScreen on which to display the dialog or %NULL to * use the default #GdkScreen. + * @startup_id : startup id to properly finish startup notification and set + * the window timestamp or %NULL. * @error : return location for errors or %NULL. * * Tries to invoke the BulkRename() method on a running Thunar instance, that is @@ -53,6 +55,7 @@ thunar_dbus_client_bulk_rename (const gchar *working_directory, gchar **filenames, gboolean standalone, GdkScreen *screen, + const gchar *startup_id, GError **error) { DBusConnection *connection; @@ -85,6 +88,10 @@ thunar_dbus_client_bulk_rename (const gchar *working_directory, /* determine the display name for the screen */ display_name = gdk_screen_make_display_name (screen); + /* dbus does not like null values */ + if (startup_id == NULL) + startup_id = ""; + /* generate the BulkRename() method (disable activation!) */ message = dbus_message_new_method_call ("org.xfce.Thunar", "/org/xfce/FileManager", "org.xfce.Thunar", "BulkRename"); dbus_message_set_auto_start (message, FALSE); @@ -93,6 +100,7 @@ thunar_dbus_client_bulk_rename (const gchar *working_directory, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &filenames, g_strv_length (filenames), DBUS_TYPE_BOOLEAN, &standalone, DBUS_TYPE_STRING, &display_name, + DBUS_TYPE_STRING, &startup_id, DBUS_TYPE_INVALID); /* release the display name */ @@ -133,6 +141,8 @@ thunar_dbus_client_bulk_rename (const gchar *working_directory, * @filenames : the list of @filenames to launch. * @screen : the #GdkScreen on which to launch the @filenames or %NULL * to use the default #GdkScreen. + * @startup_id : startup id to properly finish startup notification and set + * the window timestamp or %NULL. * @error : return location for errors or %NULL. * * Tries to invoke the LaunchFiles() method on a running Thunar instance, that is @@ -149,6 +159,7 @@ gboolean thunar_dbus_client_launch_files (const gchar *working_directory, gchar **filenames, GdkScreen *screen, + const gchar *startup_id, GError **error) { DBusConnection *connection; @@ -181,6 +192,10 @@ thunar_dbus_client_launch_files (const gchar *working_directory, /* determine the display name for the screen */ display_name = gdk_screen_make_display_name (screen); + /* dbus does not like null values */ + if (startup_id == NULL) + startup_id = ""; + /* generate the LaunchFiles() method (disable activation!) */ message = dbus_message_new_method_call ("org.xfce.Thunar", "/org/xfce/FileManager", "org.xfce.Thunar", "LaunchFiles"); dbus_message_set_auto_start (message, FALSE); @@ -188,6 +203,7 @@ thunar_dbus_client_launch_files (const gchar *working_directory, DBUS_TYPE_STRING, &working_directory, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &filenames, g_strv_length (filenames), DBUS_TYPE_STRING, &display_name, + DBUS_TYPE_STRING, &startup_id, DBUS_TYPE_INVALID); /* release the display name */ diff --git a/thunar/thunar-dbus-client.h b/thunar/thunar-dbus-client.h index acc9add4c..6542c8841 100644 --- a/thunar/thunar-dbus-client.h +++ b/thunar/thunar-dbus-client.h @@ -28,11 +28,13 @@ gboolean thunar_dbus_client_bulk_rename (const gchar *working_directory, gchar **filenames, gboolean standalone, GdkScreen *screen, + const gchar *startup_id, GError **error); gboolean thunar_dbus_client_launch_files (const gchar *working_directory, gchar **filenames, GdkScreen *screen, + const gchar *startup_id, GError **error); gboolean thunar_dbus_client_terminate (GError **error); diff --git a/thunar/thunar-dbus-service-infos.xml b/thunar/thunar-dbus-service-infos.xml index a45211d46..c2c01c745 100644 --- a/thunar/thunar-dbus-service-infos.xml +++ b/thunar/thunar-dbus-service-infos.xml @@ -105,9 +105,9 @@ <!-- Launch (uri : STRING, display : STRING) : VOID - uri : either a file:-URI or an absolute path. - display : the screen on which to launch the file or "" - to use the default screen of the file manager. + uri : either a file:-URI or an absolute path. + display : the screen on which to launch the file or "" + to use the default screen of the file manager. --> <method name="Launch"> <arg direction="in" name="uri" type="s" /> @@ -219,7 +219,7 @@ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="thunar_dbus_service" /> <!-- - BulkRename (working-directory : STRING, filenames : ARRAY OF STRING, standalone : BOOLEAN, display : STRING) : VOID + BulkRename (working-directory : STRING, filenames : ARRAY OF STRING, standalone : BOOLEAN, display : STRING, startup-id : STRING) : VOID working-directory : the default directory for the "Add Files" dialog of the bulk rename window. May also be the empty string, in @@ -239,16 +239,19 @@ bunch of selected files will be renamed. display : the screen on which to launch the filenames or "" to use the default screen of the file manager. + startup-id : the DESKTOP_STARTUP_ID environment variable for properly + handling startup notification and focus stealing. --> <method name="BulkRename"> <arg direction="in" name="working-directory" type="s" /> <arg direction="in" name="filenames" type="as" /> <arg direction="in" name="standalone" type="b" /> <arg direction="in" name="display" type="s" /> + <arg direction="in" name="startup-id" type="s" /> </method> <!-- - LaunchFiles (working-directory : STRING, filenames : ARRAY OF STRING, display : STRING) : VOID + LaunchFiles (working-directory : STRING, filenames : ARRAY OF STRING, display : STRING, startup-id : STRING) : VOID working-directory : the directory, relative to which filenames should be interpreted. @@ -257,11 +260,14 @@ to the working-directory. display : the screen on which to launch the filenames or "" to use the default screen of the file manager. + startup-id : the DESKTOP_STARTUP_ID environment variable for properly + handling startup notification and focus stealing. --> <method name="LaunchFiles"> <arg direction="in" name="working-directory" type="s" /> <arg direction="in" name="filenames" type="as" /> <arg direction="in" name="display" type="s" /> + <arg direction="in" name="startup-id" type="s" /> </method> <!-- diff --git a/thunar/thunar-dbus-service.c b/thunar/thunar-dbus-service.c index db4c4b5f5..a1dfc5f2e 100644 --- a/thunar/thunar-dbus-service.c +++ b/thunar/thunar-dbus-service.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -101,11 +102,13 @@ static gboolean thunar_dbus_service_bulk_rename (ThunarDBusServi gchar **filenames, gboolean standalone, const gchar *display, + const gchar *startup_id, GError **error); static gboolean thunar_dbus_service_launch_files (ThunarDBusService *dbus_service, const gchar *working_directory, gchar **filenames, const gchar *display, + const gchar *startup_id, GError **error); static gboolean thunar_dbus_service_terminate (ThunarDBusService *dbus_service, GError **error); @@ -252,14 +255,14 @@ static gboolean thunar_dbus_service_connect_trash_bin (ThunarDBusService *dbus_service, GError **error) { - ThunarVfsPath *trash_bin_path; + GFile *trash_bin_path; /* check if we're not already connected to the trash bin */ if (G_UNLIKELY (dbus_service->trash_bin == NULL)) { /* try to connect to the trash bin */ - trash_bin_path = thunar_vfs_path_get_for_trash (); - dbus_service->trash_bin = thunar_file_get_for_path (trash_bin_path, error); + trash_bin_path = thunar_g_file_new_for_trash (); + dbus_service->trash_bin = thunar_file_get (trash_bin_path, error); if (G_LIKELY (dbus_service->trash_bin != NULL)) { /* watch the trash bin for changes */ @@ -270,7 +273,7 @@ thunar_dbus_service_connect_trash_bin (ThunarDBusService *dbus_service, G_CALLBACK (thunar_dbus_service_trash_bin_changed), dbus_service); } - thunar_vfs_path_unref (trash_bin_path); + g_object_unref (trash_bin_path); } return (dbus_service->trash_bin != NULL); @@ -360,7 +363,7 @@ thunar_dbus_service_display_folder (ThunarDBusService *dbus_service, /* popup a new window for the folder */ application = thunar_application_get (); - thunar_application_open_window (application, file, screen); + thunar_application_open_window (application, file, screen, NULL); g_object_unref (G_OBJECT (application)); /* cleanup */ @@ -380,11 +383,11 @@ thunar_dbus_service_display_folder_and_select (ThunarDBusService *dbus_service, GError **error) { ThunarApplication *application; - ThunarVfsPath *path; ThunarFile *file; ThunarFile *folder; GdkScreen *screen; GtkWidget *window; + GFile *path; /* verify that filename is valid */ if (G_UNLIKELY (filename == NULL || *filename == '\0' || strchr (filename, '/') != NULL)) @@ -399,31 +402,31 @@ thunar_dbus_service_display_folder_and_select (ThunarDBusService *dbus_service, /* popup a new window for the folder */ application = thunar_application_get (); - window = thunar_application_open_window (application, folder, screen); - g_object_unref (G_OBJECT (application)); + window = thunar_application_open_window (application, folder, screen, NULL); + g_object_unref (application); /* determine the path for the filename relative to the folder */ - path = thunar_vfs_path_relative (thunar_file_get_path (folder), filename); + path = g_file_resolve_relative_path (thunar_file_get_file (folder), filename); if (G_LIKELY (path != NULL)) { /* try to determine the file for the path */ - file = thunar_file_get_for_path (path, NULL); + file = thunar_file_get (path, NULL); if (G_LIKELY (file != NULL)) { /* tell the window to scroll to the given file and select it */ thunar_window_scroll_to_file (THUNAR_WINDOW (window), file, TRUE, TRUE, 0.5f, 0.5f); /* release the file reference */ - g_object_unref (G_OBJECT (file)); + g_object_unref (file); } /* release the path */ - thunar_vfs_path_unref (path); + g_object_unref (path); } /* cleanup */ - g_object_unref (G_OBJECT (screen)); - g_object_unref (G_OBJECT (folder)); + g_object_unref (screen); + g_object_unref (folder); return TRUE; } @@ -479,7 +482,7 @@ thunar_dbus_service_launch (ThunarDBusService *dbus_service, if (thunar_dbus_service_parse_uri_and_display (dbus_service, uri, display, &file, &screen, error)) { /* try to launch the file on the given screen */ - result = thunar_file_launch (file, screen, error); + result = thunar_file_launch (file, screen, NULL, error); /* cleanup */ g_object_unref (G_OBJECT (screen)); @@ -508,7 +511,7 @@ thunar_dbus_service_display_preferences_dialog (ThunarDBusService *dbus_service, /* popup the preferences dialog... */ dialog = thunar_preferences_dialog_new (NULL); gtk_window_set_screen (GTK_WINDOW (dialog), screen); - gtk_widget_show (dialog); + gtk_window_present (GTK_WINDOW (dialog)); /* ...and let the application take care of it */ application = thunar_application_get (); @@ -541,7 +544,7 @@ thunar_dbus_service_display_trash (ThunarDBusService *dbus_service, { /* tell the application to display the trash bin */ application = thunar_application_get (); - thunar_application_open_window (application, dbus_service->trash_bin, screen); + thunar_application_open_window (application, dbus_service->trash_bin, screen, NULL); g_object_unref (G_OBJECT (application)); /* release the screen */ @@ -588,11 +591,10 @@ thunar_dbus_service_move_to_trash (ThunarDBusService *dbus_service, GError **error) { ThunarApplication *application; - ThunarVfsPath *target_path; - ThunarVfsPath *path; + GFile *file; GdkScreen *screen; GError *err = NULL; - GList *path_list = NULL; + GList *file_list = NULL; gchar *filename; guint n; @@ -608,9 +610,10 @@ thunar_dbus_service_move_to_trash (ThunarDBusService *dbus_service, if (G_LIKELY (err == NULL)) { /* determine the path for the filename */ - path = thunar_vfs_path_new (filename, &err); - if (G_LIKELY (path != NULL)) - path_list = g_list_append (path_list, path); + /* TODO Not sure this will work as expected */ + file = g_file_new_for_commandline_arg (filename); + file_list = thunar_g_file_list_append (file_list, file); + g_object_unref (file); } /* cleanup */ @@ -622,15 +625,13 @@ thunar_dbus_service_move_to_trash (ThunarDBusService *dbus_service, { /* tell the application to move the specified files to the trash */ application = thunar_application_get (); - target_path = thunar_vfs_path_get_for_trash (); - thunar_application_move_into (application, screen, path_list, target_path, NULL); - g_object_unref (G_OBJECT (application)); - thunar_vfs_path_unref (target_path); + thunar_application_trash (application, screen, file_list); + g_object_unref (application); } /* cleanup */ - thunar_vfs_path_list_free (path_list); - g_object_unref (G_OBJECT (screen)); + thunar_g_file_list_free (file_list); + g_object_unref (screen); } /* check if we failed */ @@ -670,6 +671,7 @@ thunar_dbus_service_bulk_rename (ThunarDBusService *dbus_service, gchar **filenames, gboolean standalone, const gchar *display, + const gchar *startup_id, GError **error) { ThunarApplication *application; @@ -688,7 +690,7 @@ thunar_dbus_service_bulk_rename (ThunarDBusService *dbus_service, { /* tell the application to display the bulk rename dialog */ application = thunar_application_get (); - result = thunar_application_bulk_rename (application, cwd, filenames, standalone, screen, error); + result = thunar_application_bulk_rename (application, cwd, filenames, standalone, screen, startup_id, error); g_object_unref (G_OBJECT (application)); /* release the screen */ @@ -708,6 +710,7 @@ thunar_dbus_service_launch_files (ThunarDBusService *dbus_service, const gchar *working_directory, gchar **filenames, const gchar *display, + const gchar *startup_id, GError **error) { ThunarApplication *application; @@ -736,7 +739,7 @@ thunar_dbus_service_launch_files (ThunarDBusService *dbus_service, { /* let the application process the filenames */ application = thunar_application_get (); - result = thunar_application_process_filenames (application, working_directory, filenames, screen, error); + result = thunar_application_process_filenames (application, working_directory, filenames, screen, startup_id, error); g_object_unref (G_OBJECT (application)); /* release the screen */ diff --git a/thunar/thunar-debug.c b/thunar/thunar-debug.c index c7bd22e33..38d30874b 100644 --- a/thunar/thunar-debug.c +++ b/thunar/thunar-debug.c @@ -30,11 +30,7 @@ #include <thunar/thunar-debug.h> -#if GLIB_CHECK_VERSION(2,8,0) #include <glib/gstdio.h> -#else -#define g_access(filename, mode) access((filename),(mode)) -#endif diff --git a/thunar/thunar-deep-count-job.c b/thunar/thunar-deep-count-job.c new file mode 100644 index 000000000..8d519de9d --- /dev/null +++ b/thunar/thunar-deep-count-job.c @@ -0,0 +1,373 @@ +/* vi:set sw=2 sts=2 ts=2 et ai: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <glib-object.h> +#include <gio/gio.h> + +#include <thunar/thunar-deep-count-job.h> +#include <thunar/thunar-job.h> +#include <thunar/thunar-marshal.h> +#include <thunar/thunar-private.h> + + + +/* Signal identifiers */ +enum +{ + STATUS_UPDATE, + LAST_SIGNAL, +}; + + + +static void thunar_deep_count_job_class_init (ThunarDeepCountJobClass *klass); +static void thunar_deep_count_job_init (ThunarDeepCountJob *job); +static void thunar_deep_count_job_finalize (GObject *object); +static gboolean thunar_deep_count_job_execute (ExoJob *job, + GError **error); + + + +struct _ThunarDeepCountJobClass +{ + ThunarJobClass __parent__; + + /* signals */ + void (*status_update) (ThunarJob *job, + guint64 total_size, + guint file_count, + guint directory_count, + guint unreadable_directory_count); +}; + +struct _ThunarDeepCountJob +{ + ThunarJob __parent__; + + GFile *file; + GFileQueryInfoFlags query_flags; + + /* the time of the last "status-update" emission */ + GTimeVal last_time; + + /* status information */ + guint64 total_size; + guint file_count; + guint directory_count; + guint unreadable_directory_count; +}; + + + +static GObjectClass *thunar_deep_count_job_parent_class = NULL; +static guint deep_count_signals[LAST_SIGNAL]; + + + +GType +thunar_deep_count_job_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + type = g_type_register_static_simple (THUNAR_TYPE_JOB, + "ThunarDeepCountJob", + sizeof (ThunarDeepCountJobClass), + (GClassInitFunc) thunar_deep_count_job_class_init, + sizeof (ThunarDeepCountJob), + (GInstanceInitFunc) thunar_deep_count_job_init, + 0); + } + + return type; +} + + + +static void +thunar_deep_count_job_class_init (ThunarDeepCountJobClass *klass) +{ + ExoJobClass *job_class; + GObjectClass *gobject_class; + + /* Determine the parent type class */ + thunar_deep_count_job_parent_class = g_type_class_peek_parent (klass); + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = thunar_deep_count_job_finalize; + + job_class = EXO_JOB_CLASS (klass); + job_class->execute = thunar_deep_count_job_execute; + + /** + * ThunarDeepCountJob::status-update: + * @job : a #ThunarJob. + * @total_size : the total size in bytes. + * @file_count : the number of files. + * @directory_count : the number of directories. + * @unreadable_directory_count : the number of unreadable directories. + * + * Emitted by the @job to inform listeners about the number of files, + * directories and bytes counted so far. + **/ + deep_count_signals[STATUS_UPDATE] = + g_signal_new ("status-update", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (ThunarDeepCountJobClass, status_update), + NULL, NULL, + _thunar_marshal_VOID__UINT64_UINT_UINT_UINT, + G_TYPE_NONE, 4, + G_TYPE_UINT64, + G_TYPE_UINT, + G_TYPE_UINT, + G_TYPE_UINT); +} + + + +static void +thunar_deep_count_job_init (ThunarDeepCountJob *job) +{ + job->file = NULL; + job->query_flags = G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS; + job->total_size = 0; + job->file_count = 0; + job->directory_count = 0; + job->unreadable_directory_count = 0; +} + + + +static void +thunar_deep_count_job_finalize (GObject *object) +{ + ThunarDeepCountJob *job = THUNAR_DEEP_COUNT_JOB (object); + + if (G_LIKELY (job->file != NULL)) + g_object_unref (job->file); + + (*G_OBJECT_CLASS (thunar_deep_count_job_parent_class)->finalize) (object); +} + + + +static void +thunar_deep_count_job_status_update (ThunarDeepCountJob *job) +{ + _thunar_return_if_fail (THUNAR_IS_DEEP_COUNT_JOB (job)); + + exo_job_emit (EXO_JOB (job), + deep_count_signals[STATUS_UPDATE], + 0, + job->total_size, + job->file_count, + job->directory_count, + job->unreadable_directory_count); +} + + + +static gboolean +thunar_deep_count_job_process (ExoJob *job, + GFile *file, + GError **error) +{ + ThunarDeepCountJob *count_job = THUNAR_DEEP_COUNT_JOB (job); + GFileEnumerator *enumerator; + GFileInfo *child_info; + GFileInfo *info; + gboolean success = TRUE; + GFile *child; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (G_IS_FILE (file), FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* abort if job was already cancelled */ + if (exo_job_is_cancelled (job)) + return FALSE; + + /* query size and type of the current file */ + info = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_SIZE, + count_job->query_flags, + exo_job_get_cancellable (job), + error); + + /* abort on invalid info or cancellation */ + if (info == NULL || exo_job_is_cancelled (job)) + return FALSE; + + /* add size of the file to the total size */ + count_job->total_size += g_file_info_get_size (info); + + /* recurse if we have a directory */ + if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + { + /* try to read from the directory */ + enumerator = g_file_enumerate_children (file, + G_FILE_ATTRIBUTE_STANDARD_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_SIZE "," + G_FILE_ATTRIBUTE_STANDARD_NAME, + count_job->query_flags, + exo_job_get_cancellable (job), + error); + + if (!exo_job_is_cancelled (job)) + { + if (enumerator == NULL) + { + /* directory was unreadable */ + count_job->unreadable_directory_count += 1; + + if (file == count_job->file) + { + /* we only bail out if the job file is unreadable */ + success = FALSE; + } + else + { + /* ignore errors from files other than the job file */ + g_error_free (*error); + *error = NULL; + } + } + else + { + /* directory was readable */ + count_job->directory_count += 1; + + while (!exo_job_is_cancelled (job)) + { + /* query next child info */ + child_info = g_file_enumerator_next_file (enumerator, + exo_job_get_cancellable (job), + error); + + /* abort on invalid child info (iteration ends) or cancellation */ + if (child_info == NULL || exo_job_is_cancelled (job)) + break; + + /* generate a GFile for the child */ + child = g_file_resolve_relative_path (file, g_file_info_get_name (child_info)); + + /* recurse unless the job was cancelled before */ + if (!exo_job_is_cancelled (job)) + thunar_deep_count_job_process (job, child, error); + + /* free resources */ + g_object_unref (child); + g_object_unref (child_info); + } + + /* destroy the enumerator */ + g_object_unref (enumerator); + } + } + + /* emit status update whenever we've finished a directory */ + thunar_deep_count_job_status_update (count_job); + } + else + { + /* we have a regular file or at least not a directory */ + count_job->file_count += 1; + } + + /* destroy the file info */ + g_object_unref (info); + + /* emit final status update at the very end of the computation */ + if (file == count_job->file) + thunar_deep_count_job_status_update (count_job); + + /* we've succeeded if there was no error when loading information + * about the job file itself and the job was not cancelled */ + return !exo_job_is_cancelled (job) && success; +} + + + +static gboolean +thunar_deep_count_job_execute (ExoJob *job, + GError **error) +{ + gboolean success; + GError *err = NULL; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* don't start the job if it was already cancelled */ + if (exo_job_set_error_if_cancelled (job, error)) + return FALSE; + + /* count files, directories and compute size of the job file */ + success = thunar_deep_count_job_process (job, + THUNAR_DEEP_COUNT_JOB (job)->file, + &err); + + if (!success) + { + g_assert (err != NULL || exo_job_is_cancelled (job)); + + /* set error if the job was cancelled. otherwise just propagate + * the results of the processing function */ + if (exo_job_set_error_if_cancelled (job, error)) + { + if (err != NULL) + g_error_free (err); + } + else + { + if (err != NULL) + g_propagate_error (error, err); + } + + return FALSE; + } + else + return TRUE; +} + + + +ThunarDeepCountJob * +thunar_deep_count_job_new (GFile *file, + GFileQueryInfoFlags flags) +{ + ThunarDeepCountJob *job; + + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); + + job = g_object_new (THUNAR_TYPE_DEEP_COUNT_JOB, NULL); + job->file = g_object_ref (file); + job->query_flags = flags; + + return job; +} diff --git a/thunar/thunar-deep-count-job.h b/thunar/thunar-deep-count-job.h new file mode 100644 index 000000000..4dcefe0c4 --- /dev/null +++ b/thunar/thunar-deep-count-job.h @@ -0,0 +1,48 @@ +/* vi:set sw=2 sts=2 ts=2 et ai: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __THUNAR_DEEP_COUNT_JOB_H__ +#define __THUNAR_DEEP_COUNT_JOB_H__ + +#include <gio/gio.h> + +#include <thunar/thunar-job.h> + +G_BEGIN_DECLS; + +typedef struct _ThunarDeepCountJobPrivate ThunarDeepCountJobPrivate; +typedef struct _ThunarDeepCountJobClass ThunarDeepCountJobClass; +typedef struct _ThunarDeepCountJob ThunarDeepCountJob; + +#define THUNAR_TYPE_DEEP_COUNT_JOB (thunar_deep_count_job_get_type ()) +#define THUNAR_DEEP_COUNT_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_DEEP_COUNT_JOB, ThunarDeepCountJob)) +#define THUNAR_DEEP_COUNT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_DEEP_COUNT_JOB, ThunarDeepCountJobClass)) +#define THUNAR_IS_DEEP_COUNT_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_DEEP_COUNT_JOB)) +#define THUNAR_IS_DEEP_COUNT_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_DEEP_COUNT_JOB) +#define THUNAR_DEEP_COUNT_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_DEEP_COUNT_JOB, ThunarDeepCountJobClass)) + +GType thunar_deep_count_job_get_type (void) G_GNUC_CONST; + +ThunarDeepCountJob *thunar_deep_count_job_new (GFile *file, + GFileQueryInfoFlags flags) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +G_END_DECLS; + +#endif /* !__THUNAR_DEEP_COUNT_JOB_H__ */ diff --git a/thunar/thunar-details-view.c b/thunar/thunar-details-view.c index b626f42cb..7a3087106 100644 --- a/thunar/thunar-details-view.c +++ b/thunar/thunar-details-view.c @@ -250,9 +250,7 @@ thunar_details_view_init (ThunarDetailsView *details_view) gtk_tree_view_set_enable_search (GTK_TREE_VIEW (tree_view), TRUE); /* enable rubberbanding (if supported) */ -#if GTK_CHECK_VERSION(2,9,0) gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (tree_view), TRUE); -#endif /* connect to the default column model */ details_view->column_model = thunar_column_model_get_default (); @@ -575,11 +573,7 @@ thunar_details_view_get_visible_range (ThunarStandardView *standard_view, { _thunar_return_val_if_fail (THUNAR_IS_DETAILS_VIEW (standard_view), FALSE); -#if GTK_CHECK_VERSION(2,8,0) return gtk_tree_view_get_visible_range (GTK_TREE_VIEW (GTK_BIN (standard_view)->child), start_path, end_path); -#else - return FALSE; -#endif } @@ -809,22 +803,8 @@ thunar_details_view_zoom_level_changed (ThunarDetailsView *details_view) /* determine the list of tree view columns */ for (column = 0; column < THUNAR_N_VISIBLE_COLUMNS; ++column) { -#if GTK_CHECK_VERSION(2,8,0) /* just queue a resize on this column */ gtk_tree_view_column_queue_resize (details_view->columns[column]); -#else - /* determine the renderers for this column */ - GList *renderers = gtk_tree_view_column_get_cell_renderers (details_view->columns[column]); - if (G_LIKELY (renderers != NULL)) - { - /* this is really an awfull hack, but it works! It forces GtkTreeView to recalculate - * the dimensions of this column, and that's all that matters. We don't use it with - * newer Gtk+ versions either, so what the f*ck... - */ - gtk_tree_view_column_set_cell_data_func (details_view->columns[column], renderers->data, NULL, NULL, NULL); - g_list_free (renderers); - } -#endif } } diff --git a/thunar/thunar-dialogs.c b/thunar/thunar-dialogs.c index 0e36ee3c8..221505a57 100644 --- a/thunar/thunar-dialogs.c +++ b/thunar/thunar-dialogs.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -33,6 +34,8 @@ #include <thunar/thunar-dialogs.h> #include <thunar/thunar-icon-factory.h> +#include <thunar/thunar-io-jobs.h> +#include <thunar/thunar-job.h> #include <thunar/thunar-pango-extensions.h> #include <thunar/thunar-preferences.h> #include <thunar/thunar-private.h> @@ -47,11 +50,10 @@ * * Displays the Thunar rename dialog for a single file rename. * - * Return value: returns %TRUE if the file has been successfully renamed. - * Note that it also returns %FALSE if no rename was required - * and thus there is no need for visible updates. + * Return value: The #ThunarJob responsible for renaming the file or + * %NULL if there was no renaming required. **/ -gboolean +ThunarJob * thunar_dialogs_show_rename_file (GtkWindow *parent, ThunarFile *file) { @@ -59,24 +61,20 @@ thunar_dialogs_show_rename_file (GtkWindow *parent, GtkIconTheme *icon_theme; const gchar *filename; const gchar *text; + ThunarJob *job = NULL; GtkWidget *dialog; GtkWidget *entry; GtkWidget *label; GtkWidget *image; GtkWidget *table; GdkPixbuf *icon; - GError *error = NULL; glong offset; gchar *title; gint response; - gboolean succeed = FALSE; _thunar_return_val_if_fail (GTK_IS_WINDOW (parent), FALSE); _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); - /* take an extra reference on the file */ - g_object_ref (G_OBJECT (file)); - /* get the filename of the file */ filename = thunar_file_get_display_name (file); @@ -137,7 +135,7 @@ thunar_dialogs_show_rename_file (GtkWindow *parent, /* select the text prior to the dot */ if (G_LIKELY (offset > 0)) - gtk_entry_select_region (GTK_ENTRY (entry), 0, offset); + gtk_editable_select_region (GTK_EDITABLE (entry), 0, offset); } } @@ -155,27 +153,14 @@ thunar_dialogs_show_rename_file (GtkWindow *parent, if (G_LIKELY (!exo_str_is_equal (filename, text))) { /* try to rename the file */ - if (!thunar_file_rename (file, text, &error)) - { - /* display an error message */ - thunar_dialogs_show_error (GTK_WIDGET (parent), error, _("Failed to rename \"%s\""), filename); - - /* release the error */ - g_error_free (error); - } - else - { - /* we've succeeded */ - succeed = TRUE; - } + job = thunar_io_jobs_rename_file (file, text); } } /* cleanup */ - g_object_unref (G_OBJECT (file)); gtk_widget_destroy (dialog); - return succeed; + return job; } @@ -240,11 +225,7 @@ thunar_dialogs_show_about (GtkWindow *parent, "documenters", documenters, "license", XFCE_LICENSE_GPL, "logo", logo, -#if GTK_CHECK_VERSION(2,11,0) "program-name", title, -#else - "name", title, -#endif "translator-credits", _("translator-credits"), "version", PACKAGE_VERSION, "website", "http://thunar.xfce.org/", @@ -388,15 +369,15 @@ thunar_dialogs_show_help (gpointer parent, * @question : the question text. * @choices : possible responses. * - * Utility function to display a question dialog for the ThunarVfsJob::ask + * Utility function to display a question dialog for the ThunarJob::ask * signal. * - * Return value: the #ThunarVfsJobResponse. + * Return value: the #ThunarJobResponse. **/ -ThunarVfsJobResponse -thunar_dialogs_show_job_ask (GtkWindow *parent, - const gchar *question, - ThunarVfsJobResponse choices) +ThunarJobResponse +thunar_dialogs_show_job_ask (GtkWindow *parent, + const gchar *question, + ThunarJobResponse choices) { const gchar *separator; const gchar *mnemonic; @@ -407,8 +388,8 @@ thunar_dialogs_show_job_ask (GtkWindow *parent, gint response; gint n, m; - _thunar_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (g_utf8_validate (question, -1, NULL), THUNAR_VFS_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (g_utf8_validate (question, -1, NULL), THUNAR_JOB_RESPONSE_CANCEL); /* try to separate the question into primary and secondary parts */ separator = strstr (question, ": "); @@ -468,27 +449,27 @@ thunar_dialogs_show_job_ask (GtkWindow *parent, switch (response) { - case THUNAR_VFS_JOB_RESPONSE_YES: + case THUNAR_JOB_RESPONSE_YES: mnemonic = _("_Yes"); break; - case THUNAR_VFS_JOB_RESPONSE_YES_ALL: + case THUNAR_JOB_RESPONSE_YES_ALL: mnemonic = _("Yes to _all"); break; - case THUNAR_VFS_JOB_RESPONSE_NO: + case THUNAR_JOB_RESPONSE_NO: mnemonic = _("_No"); break; - case THUNAR_VFS_JOB_RESPONSE_NO_ALL: + case THUNAR_JOB_RESPONSE_NO_ALL: mnemonic = _("N_o to all"); break; - case THUNAR_VFS_JOB_RESPONSE_RETRY: + case THUNAR_JOB_RESPONSE_RETRY: mnemonic = _("_Retry"); break; - case THUNAR_VFS_JOB_RESPONSE_CANCEL: + case THUNAR_JOB_RESPONSE_CANCEL: response = GTK_RESPONSE_CANCEL; mnemonic = _("_Cancel"); break; @@ -512,7 +493,7 @@ thunar_dialogs_show_job_ask (GtkWindow *parent, /* transform the result as required */ if (G_UNLIKELY (response <= 0)) - response = THUNAR_VFS_JOB_RESPONSE_CANCEL; + response = THUNAR_JOB_RESPONSE_CANCEL; /* cleanup */ g_string_free (secondary, TRUE); @@ -526,26 +507,24 @@ thunar_dialogs_show_job_ask (GtkWindow *parent, /** * thunar_dialogs_show_job_ask_replace: * @parent : the parent #GtkWindow or %NULL. - * @src_info : the #ThunarVfsInfo of the source file. - * @dst_info : the #ThunarVfsInfo of the destination file that + * @src_file : the #ThunarFile of the source file. + * @dst_file : the #ThunarFile of the destination file that * may be replaced with the source file. * * Asks the user whether to replace the destination file with the - * source file identified by @src_info. + * source file identified by @src_file. * - * Return value: the selected #ThunarVfsJobResponse. + * Return value: the selected #ThunarJobResponse. **/ -ThunarVfsJobResponse -thunar_dialogs_show_job_ask_replace (GtkWindow *parent, - ThunarVfsInfo *src_info, - ThunarVfsInfo *dst_info) +ThunarJobResponse +thunar_dialogs_show_job_ask_replace (GtkWindow *parent, + ThunarFile *src_file, + ThunarFile *dst_file) { ThunarIconFactory *icon_factory; ThunarPreferences *preferences; ThunarDateStyle date_style; GtkIconTheme *icon_theme; - ThunarFile *src_file; - ThunarFile *dst_file; GtkWidget *dialog; GtkWidget *table; GtkWidget *image; @@ -556,19 +535,15 @@ thunar_dialogs_show_job_ask_replace (GtkWindow *parent, gchar *text; gint response; - _thunar_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (src_info != NULL, THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (dst_info != NULL, THUNAR_VFS_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (src_file), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (dst_file), THUNAR_JOB_RESPONSE_CANCEL); /* determine the style used to format dates */ preferences = thunar_preferences_get (); g_object_get (G_OBJECT (preferences), "misc-date-style", &date_style, NULL); g_object_unref (G_OBJECT (preferences)); - /* determine the files for the infos */ - src_file = thunar_file_get_for_info (src_info); - dst_file = thunar_file_get_for_info (dst_info); - /* setup the confirmation dialog */ dialog = gtk_dialog_new_with_buttons (_("Confirm to replace files"), parent, @@ -576,17 +551,17 @@ thunar_dialogs_show_job_ask_replace (GtkWindow *parent, | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - _("_Skip"), THUNAR_VFS_JOB_RESPONSE_NO, - _("Replace _All"), THUNAR_VFS_JOB_RESPONSE_YES_ALL, - _("_Replace"), THUNAR_VFS_JOB_RESPONSE_YES, + _("_Skip"), THUNAR_JOB_RESPONSE_NO, + _("Replace _All"), THUNAR_JOB_RESPONSE_YES_ALL, + _("_Replace"), THUNAR_JOB_RESPONSE_YES, NULL); gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), - THUNAR_VFS_JOB_RESPONSE_YES, - THUNAR_VFS_JOB_RESPONSE_YES_ALL, - THUNAR_VFS_JOB_RESPONSE_NO, + THUNAR_JOB_RESPONSE_YES, + THUNAR_JOB_RESPONSE_YES_ALL, + THUNAR_JOB_RESPONSE_NO, GTK_RESPONSE_CANCEL, -1); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), THUNAR_VFS_JOB_RESPONSE_YES); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), THUNAR_JOB_RESPONSE_YES); /* determine the icon factory to use */ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (dialog)); @@ -608,7 +583,22 @@ thunar_dialogs_show_job_ask_replace (GtkWindow *parent, gtk_table_attach (GTK_TABLE (table), image, 0, 1, 0, 1, GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show (image); - text = g_strdup_printf (_("This folder already contains a file \"%s\"."), thunar_file_get_display_name (dst_file)); + if (thunar_file_is_symlink (dst_file)) + { + text = g_strdup_printf (_("This folder already contains a symbolic link \"%s\"."), + thunar_file_get_display_name (dst_file)); + } + else if (thunar_file_is_directory (dst_file)) + { + text = g_strdup_printf (_("This folder already contains a folder \"%s\"."), + thunar_file_get_display_name (dst_file)); + } + else + { + text = g_strdup_printf (_("This folder already contains a file \"%s\"."), + thunar_file_get_display_name (dst_file)); + } + label = gtk_label_new (text); gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_big ()); @@ -616,7 +606,13 @@ thunar_dialogs_show_job_ask_replace (GtkWindow *parent, gtk_widget_show (label); g_free (text); - text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the existing file")); + if (thunar_file_is_symlink (dst_file)) + text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the link")); + else if (thunar_file_is_directory (dst_file)) + text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the existing folder")); + else + text = g_strdup_printf (Q_("ReplaceDialogPart1|Do you want to replace the existing file")); + label = gtk_label_new (text); gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); gtk_table_attach (GTK_TABLE (table), label, 1, 3, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); @@ -641,7 +637,13 @@ thunar_dialogs_show_job_ask_replace (GtkWindow *parent, g_free (date_string); g_free (text); - text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following file?")); + if (thunar_file_is_symlink (src_file)) + text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following link?")); + else if (thunar_file_is_directory (src_file)) + text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following folder?")); + else + text = g_strdup_printf (Q_("ReplaceDialogPart2|with the following file?")); + label = gtk_label_new (text); gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); gtk_table_attach (GTK_TABLE (table), label, 1, 3, 3, 4, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); @@ -672,12 +674,10 @@ thunar_dialogs_show_job_ask_replace (GtkWindow *parent, /* cleanup */ g_object_unref (G_OBJECT (icon_factory)); - g_object_unref (G_OBJECT (dst_file)); - g_object_unref (G_OBJECT (src_file)); /* translate GTK responses */ if (G_UNLIKELY (response < 0)) - response = THUNAR_VFS_JOB_RESPONSE_CANCEL; + response = THUNAR_JOB_RESPONSE_CANCEL; return response; } @@ -687,10 +687,10 @@ thunar_dialogs_show_job_ask_replace (GtkWindow *parent, /** * thunar_dialogs_show_job_error: * @parent : the parent #GtkWindow or %NULL. - * @error : the #GError provided by the #ThunarVfsJob. + * @error : the #GError provided by the #ThunarJob. * * Utility function to display a message dialog for the - * ThunarVfsJob::error signal. + * ThunarJob::error signal. **/ void thunar_dialogs_show_job_error (GtkWindow *parent, diff --git a/thunar/thunar-dialogs.h b/thunar/thunar-dialogs.h index d89aac81c..1422b40d6 100644 --- a/thunar/thunar-dialogs.h +++ b/thunar/thunar-dialogs.h @@ -20,38 +20,39 @@ #ifndef __THUNAR_DIALOGS_H__ #define __THUNAR_DIALOGS_H__ -#include <thunar-vfs/thunar-vfs.h> +#include <thunar/thunar-enum-types.h> #include <thunar/thunar-file.h> +#include <thunar/thunar-job.h> G_BEGIN_DECLS; -gboolean thunar_dialogs_show_rename_file (GtkWindow *parent, - ThunarFile *file) G_GNUC_INTERNAL; +ThunarJob *thunar_dialogs_show_rename_file (GtkWindow *parent, + ThunarFile *file) G_GNUC_INTERNAL; -void thunar_dialogs_show_about (GtkWindow *parent, - const gchar *title, - const gchar *format, - ...) G_GNUC_INTERNAL G_GNUC_PRINTF (3, 4); +void thunar_dialogs_show_about (GtkWindow *parent, + const gchar *title, + const gchar *format, + ...) G_GNUC_INTERNAL G_GNUC_PRINTF (3, 4); -void thunar_dialogs_show_error (gpointer parent, - const GError *error, - const gchar *format, - ...) G_GNUC_INTERNAL G_GNUC_PRINTF (3, 4); +void thunar_dialogs_show_error (gpointer parent, + const GError *error, + const gchar *format, + ...) G_GNUC_INTERNAL G_GNUC_PRINTF (3, 4); -void thunar_dialogs_show_help (gpointer parent, - const gchar *page, - const gchar *offset) G_GNUC_INTERNAL; +void thunar_dialogs_show_help (gpointer parent, + const gchar *page, + const gchar *offset) G_GNUC_INTERNAL; -ThunarVfsJobResponse thunar_dialogs_show_job_ask (GtkWindow *parent, - const gchar *question, - ThunarVfsJobResponse choices) G_GNUC_INTERNAL; +ThunarJobResponse thunar_dialogs_show_job_ask (GtkWindow *parent, + const gchar *question, + ThunarJobResponse choices) G_GNUC_INTERNAL; -ThunarVfsJobResponse thunar_dialogs_show_job_ask_replace (GtkWindow *parent, - ThunarVfsInfo *src_info, - ThunarVfsInfo *dst_info) G_GNUC_INTERNAL; +ThunarJobResponse thunar_dialogs_show_job_ask_replace (GtkWindow *parent, + ThunarFile *src_file, + ThunarFile *dst_file) G_GNUC_INTERNAL; -void thunar_dialogs_show_job_error (GtkWindow *parent, - GError *error) G_GNUC_INTERNAL; +void thunar_dialogs_show_job_error (GtkWindow *parent, + GError *error) G_GNUC_INTERNAL; G_END_DECLS; diff --git a/thunar/thunar-dnd.c b/thunar/thunar-dnd.c index 4fb278c62..a64cf5d1d 100644 --- a/thunar/thunar-dnd.c +++ b/thunar/thunar-dnd.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -44,7 +45,7 @@ dnd_action_selected (GtkWidget *item, * thunar_dnd_ask: * @widget : the widget on which the drop was performed. * @folder : the #ThunarFile to which the @path_list is being dropped. - * @path_list : the #ThunarVfsPath<!---->s of the files being dropped to @file. + * @path_list : the #GFile<!---->s of the files being dropped to @file. * @time : the time of the drop event. * @actions : the list of actions supported for the drop. * @@ -188,15 +189,15 @@ thunar_dnd_ask (GtkWidget *widget, /** * thunar_dnd_perform: * @widget : the #GtkWidget on which the drop was done. - * @file : the #ThunarFile on which the @path_list was dropped. - * @path_list : the list of #ThunarVfsPath<!---->s that was dropped. + * @file : the #ThunarFile on which the @file_list was dropped. + * @file_list : the list of #GFile<!---->s that was dropped. * @action : the #GdkDragAction that was performed. * @new_files_closure : a #GClosure to connect to the job's "new-files" signal, * which will be emitted when the job finishes with the - * list of #ThunarVfsPath<!---->s created by the job, or + * list of #GFile<!---->s created by the job, or * %NULL if you're not interested in the signal. * - * Performs the drop of @path_list on @file in @widget, as given in + * Performs the drop of @file_list on @file in @widget, as given in * @action and returns %TRUE if the drop was started successfully * (or even completed successfully), else %FALSE. * @@ -206,7 +207,7 @@ thunar_dnd_ask (GtkWidget *widget, gboolean thunar_dnd_perform (GtkWidget *widget, ThunarFile *file, - GList *path_list, + GList *file_list, GdkDragAction action, GClosure *new_files_closure) { @@ -228,15 +229,15 @@ thunar_dnd_perform (GtkWidget *widget, switch (action) { case GDK_ACTION_COPY: - thunar_application_copy_into (application, widget, path_list, thunar_file_get_path (file), new_files_closure); + thunar_application_copy_into (application, widget, file_list, thunar_file_get_file (file), new_files_closure); break; case GDK_ACTION_MOVE: - thunar_application_move_into (application, widget, path_list, thunar_file_get_path (file), new_files_closure); + thunar_application_move_into (application, widget, file_list, thunar_file_get_file (file), new_files_closure); break; case GDK_ACTION_LINK: - thunar_application_link_into (application, widget, path_list, thunar_file_get_path (file), new_files_closure); + thunar_application_link_into (application, widget, file_list, thunar_file_get_file (file), new_files_closure); break; default: @@ -245,7 +246,7 @@ thunar_dnd_perform (GtkWidget *widget, } else if (thunar_file_is_executable (file)) { - succeed = thunar_file_execute (file, gtk_widget_get_screen (widget), path_list, &error); + succeed = thunar_file_execute (file, gtk_widget_get_screen (widget), file_list, &error); if (G_UNLIKELY (!succeed)) { /* display an error to the user */ diff --git a/thunar/thunar-enum-types.c b/thunar/thunar-enum-types.c index bfcf373cf..b9303b6ce 100644 --- a/thunar/thunar-enum-types.c +++ b/thunar/thunar-enum-types.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -271,4 +272,60 @@ thunar_icon_size_from_zoom_level (const GValue *src_value, +GType +thunar_job_response_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + static const GFlagsValue values[] = + { + { THUNAR_JOB_RESPONSE_YES, "THUNAR_JOB_RESPONSE_YES", "yes" }, + { THUNAR_JOB_RESPONSE_YES_ALL, "THUNAR_JOB_RESPONSE_YES_ALL", "yes-all" }, + { THUNAR_JOB_RESPONSE_NO, "THUNAR_JOB_RESPONSE_NO", "no" }, + { THUNAR_JOB_RESPONSE_CANCEL, "THUNAR_JOB_RESPONSE_CANCEL", "cancel" }, + { THUNAR_JOB_RESPONSE_NO_ALL, "THUNAR_JOB_RESPONSE_NO_ALL", "no-all" }, + { THUNAR_JOB_RESPONSE_RETRY, "THUNAR_JOB_RESPONSE_RETRY", "retry" }, + { 0, NULL, NULL } + }; + + type = g_flags_register_static (I_("ThunarJobResponse"), values); + } + + return type; +} + + +GType +thunar_file_mode_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (type == G_TYPE_INVALID) + { + static const GFlagsValue values[] = + { + { THUNAR_FILE_MODE_SUID, "THUNAR_FILE_MODE_SUID", "suid" }, + { THUNAR_FILE_MODE_SGID, "THUNAR_FILE_MODE_SGID", "sgid" }, + { THUNAR_FILE_MODE_STICKY, "THUNAR_FILE_MODE_STICKY", "sticky" }, + { THUNAR_FILE_MODE_USR_ALL, "THUNAR_FILE_MODE_USR_ALL", "usr-all" }, + { THUNAR_FILE_MODE_USR_READ, "THUNAR_FILE_MODE_USR_READ", "usr-read" }, + { THUNAR_FILE_MODE_USR_WRITE, "THUNAR_FILE_MODE_USR_WRITE", "usr-write" }, + { THUNAR_FILE_MODE_USR_EXEC, "THUNAR_FILE_MODE_USR_EXEC", "usr-exec" }, + { THUNAR_FILE_MODE_GRP_ALL, "THUNAR_FILE_MODE_GRP_ALL", "grp-all" }, + { THUNAR_FILE_MODE_GRP_READ, "THUNAR_FILE_MODE_GRP_READ", "grp-read" }, + { THUNAR_FILE_MODE_GRP_WRITE, "THUNAR_FILE_MODE_GRP_WRITE", "grp-write" }, + { THUNAR_FILE_MODE_GRP_EXEC, "THUNAR_FILE_MODE_GRP_EXEC", "grp-exec" }, + { THUNAR_FILE_MODE_OTH_ALL, "THUNAR_FILE_MODE_OTH_ALL", "oth-all" }, + { THUNAR_FILE_MODE_OTH_READ, "THUNAR_FILE_MODE_OTH_READ", "oth-read" }, + { THUNAR_FILE_MODE_OTH_WRITE, "THUNAR_FILE_MODE_OTH_WRITE", "oth-write" }, + { THUNAR_FILE_MODE_OTH_EXEC, "THUNAR_FILE_MODE_OTH_EXEC", "oth-exec" }, + { 0, NULL, NULL } + }; + + type = g_flags_register_static ("ThunarFileMode", values); + } + return type; +} diff --git a/thunar/thunar-enum-types.h b/thunar/thunar-enum-types.h index 9be31bdca..a6c49f2bf 100644 --- a/thunar/thunar-enum-types.h +++ b/thunar/thunar-enum-types.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -234,6 +235,61 @@ typedef enum GType thunar_zoom_level_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; ThunarIconSize thunar_zoom_level_to_icon_size (ThunarZoomLevel zoom_level) G_GNUC_CONST G_GNUC_INTERNAL; + +#define THUNAR_TYPE_JOB_RESPONSE (thunar_job_response_get_type ()) + +/** + * ThunarJobResponse: + * @THUNAR_JOB_RESPONSE_YES : + * @THUNAR_JOB_RESPONSE_YES_ALL : + * @THUNAR_JOB_RESPONSE_NO : + * @THUNAR_JOB_RESPONSE_NO_ALL : + * @THUNAR_JOB_RESPONSE_CANCEL : + * @THUNAR_JOB_RESPONSE_RETRY : + * + * Possible responses for the ThunarJob::ask signal. + **/ +typedef enum /*< flags >*/ +{ + THUNAR_JOB_RESPONSE_YES = 1 << 0, + THUNAR_JOB_RESPONSE_YES_ALL = 1 << 1, + THUNAR_JOB_RESPONSE_NO = 1 << 2, + THUNAR_JOB_RESPONSE_CANCEL = 1 << 3, + THUNAR_JOB_RESPONSE_NO_ALL = 1 << 4, + THUNAR_JOB_RESPONSE_RETRY = 1 << 5, +} ThunarJobResponse; + +GType thunar_job_response_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; + + +#define THUNAR_TYPE_FILE_MODE (thunar_file_mode_get_type ()) + +/** + * ThunarFileMode: + * + * Special flags and permissions of a filesystem entity. + **/ +typedef enum /*< flags >*/ +{ + THUNAR_FILE_MODE_SUID = 04000, + THUNAR_FILE_MODE_SGID = 02000, + THUNAR_FILE_MODE_STICKY = 01000, + THUNAR_FILE_MODE_USR_ALL = 00700, + THUNAR_FILE_MODE_USR_READ = 00400, + THUNAR_FILE_MODE_USR_WRITE = 00200, + THUNAR_FILE_MODE_USR_EXEC = 00100, + THUNAR_FILE_MODE_GRP_ALL = 00070, + THUNAR_FILE_MODE_GRP_READ = 00040, + THUNAR_FILE_MODE_GRP_WRITE = 00020, + THUNAR_FILE_MODE_GRP_EXEC = 00010, + THUNAR_FILE_MODE_OTH_ALL = 00007, + THUNAR_FILE_MODE_OTH_READ = 00004, + THUNAR_FILE_MODE_OTH_WRITE = 00002, + THUNAR_FILE_MODE_OTH_EXEC = 00001, +} ThunarFileMode; + +GType thunar_file_mode_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL; + G_END_DECLS; #endif /* !__THUNAR_ENUM_TYPES_H__ */ diff --git a/thunar-vfs/thunar-vfs-exec.c b/thunar/thunar-exec.c similarity index 67% rename from thunar-vfs/thunar-vfs-exec.c rename to thunar/thunar-exec.c index 05ca804a9..900c136f1 100644 --- a/thunar-vfs/thunar-vfs-exec.c +++ b/thunar/thunar-exec.c @@ -1,23 +1,25 @@ -/* $Id$ */ +/* vi:set et ai sw=2 sts=2 ts=2: */ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 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 library is distributed in the hope that it will be useful, + * 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 - * Library General Public License for more details. + * 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 Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * 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 @@ -39,10 +41,16 @@ #include <string.h> #endif -#include <thunar-vfs/thunar-vfs-exec.h> -#include <thunar-vfs/thunar-vfs-path-private.h> -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-alias.h> +#include <glib.h> +#include <gio/gio.h> + +#include <gdk/gdk.h> +#include <gtk/gtk.h> + +#include <libxfce4util/libxfce4util.h> + +#include <thunar/thunar-exec.h> +#include <thunar/thunar-private.h> #ifdef GDK_WINDOWING_X11 #include <X11/Xatom.h> @@ -51,19 +59,19 @@ -static void tve_string_append_quoted (GString *string, - const gchar *unquoted); -static gboolean tve_string_append_quoted_path (GString *string, - ThunarVfsPath *path, - GError **error); -static void tve_string_append_quoted_uri (GString *string, - const ThunarVfsPath *path); +static void te_string_append_quoted (GString *string, + const gchar *unquoted); +static gboolean te_string_append_quoted_file (GString *string, + GFile *file, + GError **error); +static void te_string_append_quoted_uri (GString *string, + GFile *file); static void -tve_string_append_quoted (GString *string, - const gchar *unquoted) +te_string_append_quoted (GString *string, + const gchar *unquoted) { gchar *quoted; @@ -75,43 +83,45 @@ tve_string_append_quoted (GString *string, static gboolean -tve_string_append_quoted_path (GString *string, - ThunarVfsPath *path, - GError **error) +te_string_append_quoted_file (GString *string, + GFile *file, + GError **error) { - gchar *absolute_path; + gboolean success = FALSE; + gchar *path; /* append the absolute, local, quoted path to the string */ - absolute_path = _thunar_vfs_path_translate_dup_string (path, THUNAR_VFS_PATH_SCHEME_FILE, error); - if (G_LIKELY (absolute_path != NULL)) + path = g_file_get_path (file); + if (G_LIKELY (path != NULL)) { - tve_string_append_quoted (string, absolute_path); - g_free (absolute_path); + te_string_append_quoted (string, path); + success = TRUE; + g_free (path); } - return (absolute_path != NULL); + return success; } static void -tve_string_append_quoted_uri (GString *string, - const ThunarVfsPath *path) +te_string_append_quoted_uri (GString *string, + GFile *file) { gchar *uri; /* append the quoted URI for the path */ - uri = thunar_vfs_path_dup_uri (path); - tve_string_append_quoted (string, uri); + uri = g_file_get_uri (file); + te_string_append_quoted (string, uri); g_free (uri); } /** - * thunar_vfs_exec_parse: + * thunar_exec_parse: * @exec : the value of the <literal>Exec</literal> field. - * @path_list : the list of #ThunarVfsPath<!---->s. + * @file_list : the list of #GFile<!---->s. * @icon : value of the <literal>Icon</literal> field or %NULL. * @name : translated value for the <literal>Name</literal> field or %NULL. * @path : full path to the desktop file or %NULL. @@ -137,21 +147,20 @@ tve_string_append_quoted_uri (GString *string, * Return value: %TRUE on success, else %FALSE. **/ gboolean -thunar_vfs_exec_parse (const gchar *exec, - GList *path_list, - const gchar *icon, - const gchar *name, - const gchar *path, - gboolean terminal, - gint *argc, - gchar ***argv, - GError **error) +thunar_exec_parse (const gchar *exec, + GList *file_list, + const gchar *icon, + const gchar *name, + const gchar *uri, + gboolean terminal, + gint *argc, + gchar ***argv, + GError **error) { - ThunarVfsPath *parent; - const gchar *p; - gboolean result = FALSE; - GString *command_line = g_string_new (NULL); - GList *lp; + const gchar *p; + gboolean result = FALSE; + GString *command_line = g_string_new (NULL); + GList *lp; /* prepend terminal command if required */ if (G_UNLIKELY (terminal)) @@ -165,68 +174,31 @@ thunar_vfs_exec_parse (const gchar *exec, { case 'f': /* append the absolute local path of the first path object */ - if (path_list != NULL && !tve_string_append_quoted_path (command_line, path_list->data, error)) + if (file_list != NULL && !te_string_append_quoted_file (command_line, file_list->data, error)) goto done; break; case 'F': - for (lp = path_list; lp != NULL; lp = lp->next) + for (lp = file_list; lp != NULL; lp = lp->next) { - if (G_LIKELY (lp != path_list)) + if (G_LIKELY (lp != file_list)) g_string_append_c (command_line, ' '); - if (!tve_string_append_quoted_path (command_line, lp->data, error)) + if (!te_string_append_quoted_file (command_line, lp->data, error)) goto done; } break; case 'u': - if (G_LIKELY (path_list != NULL)) - tve_string_append_quoted_uri (command_line, path_list->data); + if (G_LIKELY (file_list != NULL)) + te_string_append_quoted_uri (command_line, file_list->data); break; case 'U': - for (lp = path_list; lp != NULL; lp = lp->next) + for (lp = file_list; lp != NULL; lp = lp->next) { - if (G_LIKELY (lp != path_list)) + if (G_LIKELY (lp != file_list)) g_string_append_c (command_line, ' '); - tve_string_append_quoted_uri (command_line, lp->data); - } - break; - - case 'd': - if (G_LIKELY (path_list != NULL)) - { - parent = thunar_vfs_path_get_parent (path_list->data); - if (parent != NULL && !tve_string_append_quoted_path (command_line, parent, error)) - goto done; - } - break; - - case 'D': - for (lp = path_list; lp != NULL; lp = lp->next) - { - parent = thunar_vfs_path_get_parent (lp->data); - if (G_LIKELY (parent != NULL)) - { - if (G_LIKELY (lp != path_list)) - g_string_append_c (command_line, ' '); - if (!tve_string_append_quoted_path (command_line, parent, error)) - goto done; - } - } - break; - - case 'n': - if (G_LIKELY (path_list != NULL)) - tve_string_append_quoted (command_line, thunar_vfs_path_get_name (path_list->data)); - break; - - case 'N': - for (lp = path_list; lp != NULL; lp = lp->next) - { - if (G_LIKELY (lp != path_list)) - g_string_append_c (command_line, ' '); - tve_string_append_quoted (command_line, thunar_vfs_path_get_name (lp->data)); + te_string_append_quoted_uri (command_line, lp->data); } break; @@ -234,18 +206,18 @@ thunar_vfs_exec_parse (const gchar *exec, if (G_LIKELY (icon != NULL)) { g_string_append (command_line, "--icon "); - tve_string_append_quoted (command_line, icon); + te_string_append_quoted (command_line, icon); } break; case 'c': if (G_LIKELY (name != NULL)) - tve_string_append_quoted (command_line, name); + te_string_append_quoted (command_line, name); break; case 'k': - if (G_LIKELY (path != NULL)) - tve_string_append_quoted (command_line, path); + if (G_LIKELY (uri != NULL)) + te_string_append_quoted (command_line, uri); break; case '%': @@ -272,7 +244,7 @@ done: #include <libsn/sn.h> /* the max. timeout for an application to startup */ -#define TVSN_STARTUP_TIMEOUT (30 * 1000) +#define TSN_STARTUP_TIMEOUT (30 * 1000) typedef struct { @@ -280,16 +252,16 @@ typedef struct guint timeout_id; guint watch_id; GPid pid; -} TvsnStartupData; +} TsnStartupData; static gboolean tvsn_startup_timeout (gpointer data) { - TvsnStartupData *startup_data = data; - GTimeVal now; - gdouble elapsed; - glong tv_sec; - glong tv_usec; + TsnStartupData *startup_data = data; + GTimeVal now; + gdouble elapsed; + glong tv_sec; + glong tv_usec; GDK_THREADS_ENTER (); @@ -299,7 +271,7 @@ tvsn_startup_timeout (gpointer data) elapsed = (((gdouble) now.tv_sec - tv_sec) * G_USEC_PER_SEC + (now.tv_usec - tv_usec)) / 1000.0; /* check if the timeout was reached */ - if (elapsed >= TVSN_STARTUP_TIMEOUT) + if (elapsed >= TSN_STARTUP_TIMEOUT) { /* abort the startup notification */ sn_launcher_context_complete (startup_data->sn_launcher); @@ -310,15 +282,15 @@ tvsn_startup_timeout (gpointer data) GDK_THREADS_LEAVE (); /* keep the startup timeout if not elapsed */ - return (elapsed < TVSN_STARTUP_TIMEOUT); + return (elapsed < TSN_STARTUP_TIMEOUT); } static void tvsn_startup_timeout_destroy (gpointer data) { - TvsnStartupData *startup_data = data; + TsnStartupData *startup_data = data; - _thunar_vfs_return_if_fail (startup_data->sn_launcher == NULL); + _thunar_return_if_fail (startup_data->sn_launcher == NULL); /* cancel the watch (if any) */ if (startup_data->watch_id != 0) @@ -330,7 +302,7 @@ tvsn_startup_timeout_destroy (gpointer data) NULL, NULL); /* release the startup data */ - _thunar_vfs_slice_free (TvsnStartupData, startup_data); + _thunar_slice_free (TsnStartupData, startup_data); } static void @@ -338,11 +310,11 @@ tvsn_startup_watch (GPid pid, gint status, gpointer data) { - TvsnStartupData *startup_data = data; + TsnStartupData *startup_data = data; - _thunar_vfs_return_if_fail (startup_data->sn_launcher != NULL); - _thunar_vfs_return_if_fail (startup_data->watch_id != 0); - _thunar_vfs_return_if_fail (startup_data->pid == pid); + _thunar_return_if_fail (startup_data->sn_launcher != NULL); + _thunar_return_if_fail (startup_data->watch_id != 0); + _thunar_return_if_fail (startup_data->pid == pid); /* abort the startup notification (application exited) */ sn_launcher_context_complete (startup_data->sn_launcher); @@ -408,7 +380,7 @@ tvsn_get_active_workspace_number (GdkScreen *screen) /** - * thunar_vfs_exec_on_screen: + * thunar_exec_on_screen: * @screen : a #GdkScreen. * @working_directory : child's current working directory or %NULL to inherit parent's. * @argv : child's argument vector. @@ -419,23 +391,23 @@ tvsn_get_active_workspace_number (GdkScreen *screen) * @error : return location for errors or %NULL. * * Like gdk_spawn_on_screen(), but also supports startup notification - * (if Thunar-VFS was built with startup notification support). + * (if Thunar was built with startup notification support). * * Return value: %TRUE on success, %FALSE if @error is set. **/ gboolean -thunar_vfs_exec_on_screen (GdkScreen *screen, - const gchar *working_directory, - gchar **argv, - gchar **envp, - GSpawnFlags flags, - gboolean startup_notify, - const gchar *icon_name, - GError **error) +thunar_exec_on_screen (GdkScreen *screen, + const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + gboolean startup_notify, + const gchar *icon_name, + GError **error) { #ifdef HAVE_LIBSTARTUP_NOTIFICATION SnLauncherContext *sn_launcher = NULL; - TvsnStartupData *startup_data; + TsnStartupData *startup_data; SnDisplay *sn_display = NULL; gint sn_workspace; #endif @@ -507,9 +479,9 @@ thunar_vfs_exec_on_screen (GdkScreen *screen, else { /* schedule a startup notification timeout */ - startup_data = _thunar_vfs_slice_new (TvsnStartupData); + startup_data = _thunar_slice_new (TsnStartupData); startup_data->sn_launcher = sn_launcher; - startup_data->timeout_id = g_timeout_add_full (G_PRIORITY_LOW, TVSN_STARTUP_TIMEOUT, tvsn_startup_timeout, + startup_data->timeout_id = g_timeout_add_full (G_PRIORITY_LOW, TSN_STARTUP_TIMEOUT, tvsn_startup_timeout, startup_data, tvsn_startup_timeout_destroy); startup_data->watch_id = g_child_watch_add_full (G_PRIORITY_LOW, pid, tvsn_startup_watch, startup_data, NULL); startup_data->pid = pid; @@ -536,7 +508,7 @@ thunar_vfs_exec_on_screen (GdkScreen *screen, /** - * thunar_vfs_exec_sync: + * thunar_exec_sync: * @command_fmt : the command to execute (can be a printf * format string). * @error : return location for errors or %NULL. @@ -551,9 +523,9 @@ thunar_vfs_exec_on_screen (GdkScreen *screen, * successfully, %FALSE if @error is set. **/ gboolean -thunar_vfs_exec_sync (const gchar *command_fmt, - GError **error, - ...) +thunar_exec_sync (const gchar *command_fmt, + GError **error, + ...) { gboolean result; va_list args; @@ -602,8 +574,3 @@ thunar_vfs_exec_sync (const gchar *command_fmt, return result; } - - - -#define __THUNAR_VFS_EXEC_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar/thunar-exec.h b/thunar/thunar-exec.h new file mode 100644 index 000000000..99eda8c90 --- /dev/null +++ b/thunar/thunar-exec.h @@ -0,0 +1,54 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_EXEC_H__ +#define __THUNAR_EXEC_H__ + +#include <gdk/gdk.h> + +G_BEGIN_DECLS; + +gboolean thunar_exec_parse (const gchar *exec, + GList *path_list, + const gchar *icon, + const gchar *name, + const gchar *path, + gboolean terminal, + gint *argc, + gchar ***argv, + GError **error) G_GNUC_INTERNAL; + +gboolean thunar_exec_on_screen (GdkScreen *screen, + const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + gboolean startup_notify, + const gchar *icon_name, + GError **error) G_GNUC_INTERNAL; + +gboolean thunar_exec_sync (const gchar *command_line, + GError **error, + ...) G_GNUC_INTERNAL; + +G_END_DECLS; + +#endif /* !__THUNAR_EXEC_H__ */ diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c index c04921351..bc3722ecb 100644 --- a/thunar/thunar-file.c +++ b/thunar/thunar-file.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -25,6 +26,10 @@ #include <sys/types.h> #endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + #ifdef HAVE_ERRNO_H #include <errno.h> #endif @@ -44,12 +49,19 @@ #include <unistd.h> #endif +#include <gio/gio.h> + +#include <thunarx/thunarx.h> + #include <thunar/thunar-application.h> #include <thunar/thunar-chooser-dialog.h> +#include <thunar/thunar-exec.h> #include <thunar/thunar-file.h> #include <thunar/thunar-file-monitor.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-private.h> +#include <thunar/thunar-user.h> #include <thunar/thunar-util.h> @@ -90,34 +102,36 @@ static gchar *thunar_file_info_get_mime_type (ThunarxFileInfo static gboolean thunar_file_info_has_mime_type (ThunarxFileInfo *file_info, const gchar *mime_type); static gboolean thunar_file_info_is_directory (ThunarxFileInfo *file_info); -static ThunarVfsInfo *thunar_file_info_get_vfs_info (ThunarxFileInfo *file_info); +static GFileInfo *thunar_file_info_get_file_info (ThunarxFileInfo *file_info); +static GFileInfo *thunar_file_info_get_filesystem_info (ThunarxFileInfo *file_info); +static GFile *thunar_file_info_get_location (ThunarxFileInfo *file_info); static void thunar_file_info_changed (ThunarxFileInfo *file_info); static gboolean thunar_file_denies_access_permission (const ThunarFile *file, - ThunarVfsFileMode usr_permissions, - ThunarVfsFileMode grp_permissions, - ThunarVfsFileMode oth_permissions); + ThunarFileMode usr_permissions, + ThunarFileMode grp_permissions, + ThunarFileMode oth_permissions); static ThunarMetafile *thunar_file_get_metafile (ThunarFile *file); -static void thunar_file_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, +static void thunar_file_monitor (GFileMonitor *monitor, + GFile *path, + GFile *other_path, + GFileMonitorEvent event_type, gpointer user_data); -static void thunar_file_watch_free (gpointer data); -static ThunarVfsUserManager *user_manager; -static ThunarVfsMonitor *monitor; -static ThunarVfsUserId effective_user_id; -static ThunarMetafile *metafile; -static GObjectClass *thunar_file_parent_class; -static GHashTable *file_cache; -static GQuark thunar_file_thumb_path_quark; -static GQuark thunar_file_watch_count_quark; -static GQuark thunar_file_watch_handle_quark; -static GQuark thunar_file_emblem_names_quark; -static guint file_signals[LAST_SIGNAL]; +G_LOCK_DEFINE_STATIC (file_cache_mutex); + + + +static ThunarUserManager *user_manager; +static ThunarMetafile *metafile; +static GObjectClass *thunar_file_parent_class; +static GHashTable *file_cache; +static guint32 effective_user_id; +static GQuark thunar_file_thumb_path_quark; +static GQuark thunar_file_watch_count_quark; +static GQuark thunar_file_emblem_names_quark; +static guint file_signals[LAST_SIGNAL]; @@ -166,18 +180,23 @@ thunar_file_atexit_foreach (gpointer key, gpointer value, gpointer user_data) { - gchar *s; + gchar *uri; - s = thunar_vfs_path_dup_string (key); - g_print ("--> %s (%u)\n", s, G_OBJECT (value)->ref_count); - g_free (s); + uri = g_file_get_uri (key); + g_print ("--> %s (%u)\n", uri, G_OBJECT (value)->ref_count); + g_free (uri); } static void thunar_file_atexit (void) { + G_LOCK (file_cache_mutex); + if (file_cache == NULL || g_hash_table_size (file_cache) == 0) - return; + { + G_UNLOCK (file_cache_mutex); + return; + } g_print ("--- Leaked a total of %u ThunarFile objects:\n", g_hash_table_size (file_cache)); @@ -185,6 +204,8 @@ thunar_file_atexit (void) g_hash_table_foreach (file_cache, thunar_file_atexit_foreach, NULL); g_print ("\n"); + + G_UNLOCK (file_cache_mutex); } #endif @@ -206,14 +227,13 @@ thunar_file_class_init (ThunarFileClass *klass) /* pre-allocate the required quarks */ thunar_file_thumb_path_quark = g_quark_from_static_string ("thunar-file-thumb-path"); thunar_file_watch_count_quark = g_quark_from_static_string ("thunar-file-watch-count"); - thunar_file_watch_handle_quark = g_quark_from_static_string ("thunar-file-watch-handle"); thunar_file_emblem_names_quark = g_quark_from_static_string ("thunar-file-emblem-names"); /* determine the parent class */ thunar_file_parent_class = g_type_class_peek_parent (klass); /* grab a reference on the user manager */ - user_manager = thunar_vfs_user_manager_get_default (); + user_manager = thunar_user_manager_get_default (); /* determine the effective user id of the process */ effective_user_id = geteuid (); @@ -251,7 +271,9 @@ thunar_file_info_init (ThunarxFileInfoIface *iface) iface->get_mime_type = thunar_file_info_get_mime_type; iface->has_mime_type = thunar_file_info_has_mime_type; iface->is_directory = thunar_file_info_is_directory; - iface->get_vfs_info = thunar_file_info_get_vfs_info; + iface->get_file_info = thunar_file_info_get_file_info; + iface->get_filesystem_info = thunar_file_info_get_filesystem_info; + iface->get_location = thunar_file_info_get_location; iface->changed = thunar_file_info_changed; } @@ -291,24 +313,44 @@ thunar_file_finalize (GObject *object) #endif /* drop the entry from the cache */ - g_hash_table_remove (file_cache, file->info->path); + G_LOCK (file_cache_mutex); + g_hash_table_remove (file_cache, file->gfile); + G_UNLOCK (file_cache_mutex); /* drop a reference on the metadata if we own one */ if ((file->flags & THUNAR_FILE_OWNS_METAFILE_REFERENCE) != 0) g_object_unref (G_OBJECT (metafile)); - /* release the file info */ - thunar_vfs_info_unref (file->info); + /* release file info */ + if (file->info != NULL) + g_object_unref (file->info); + + /* release filesystem info */ + if (file->filesystem_info != NULL) + g_object_unref (file->filesystem_info); + + /* free the custom icon name */ + g_free (file->custom_icon_name); + + /* free display name and basename */ + g_free (file->display_name); + g_free (file->basename); + + /* free the thumbnail path */ + g_free (file->thumbnail_path); + + /* release file */ + g_object_unref (file->gfile); (*G_OBJECT_CLASS (thunar_file_parent_class)->finalize) (object); } -static gchar* +static gchar * thunar_file_info_get_name (ThunarxFileInfo *file_info) { - return g_strdup (thunar_vfs_path_get_name (THUNAR_FILE (file_info)->info->path)); + return g_strdup (thunar_file_get_basename (THUNAR_FILE (file_info))); } @@ -316,7 +358,7 @@ thunar_file_info_get_name (ThunarxFileInfo *file_info) static gchar* thunar_file_info_get_uri (ThunarxFileInfo *file_info) { - return thunar_vfs_path_dup_uri (THUNAR_FILE (file_info)->info->path); + return g_file_get_uri (THUNAR_FILE (file_info)->gfile); } @@ -324,13 +366,17 @@ thunar_file_info_get_uri (ThunarxFileInfo *file_info) static gchar* thunar_file_info_get_parent_uri (ThunarxFileInfo *file_info) { - ThunarVfsPath *parent; + GFile *parent; + gchar *uri = NULL; - parent = thunar_vfs_path_get_parent (THUNAR_FILE (file_info)->info->path); + parent = g_file_get_parent (THUNAR_FILE (file_info)->gfile); if (G_LIKELY (parent != NULL)) - return thunar_vfs_path_dup_uri (parent); + { + uri = g_file_get_uri (parent); + g_object_unref (parent); + } - return NULL; + return uri; } @@ -338,18 +384,7 @@ thunar_file_info_get_parent_uri (ThunarxFileInfo *file_info) static gchar* thunar_file_info_get_uri_scheme (ThunarxFileInfo *file_info) { - gchar *colon; - gchar *uri; - - /* determine the URI for the file... */ - uri = thunar_file_info_get_uri (file_info); - - /* ...and strip off everything after the colon */ - colon = strchr (uri, ':'); - if (G_LIKELY (colon != NULL)) - *colon = '\0'; - - return uri; + return g_file_get_uri_scheme (THUNAR_FILE (file_info)->gfile); } @@ -357,15 +392,10 @@ thunar_file_info_get_uri_scheme (ThunarxFileInfo *file_info) static gchar* thunar_file_info_get_mime_type (ThunarxFileInfo *file_info) { - ThunarVfsMimeInfo *mime_info; - gchar *mime_type = NULL; - - /* determine the mime info for the file */ - mime_info = thunar_file_get_mime_info (THUNAR_FILE (file_info)); - if (G_LIKELY (mime_info != NULL)) - mime_type = g_strdup (thunar_vfs_mime_info_get_name (mime_info)); + if (THUNAR_FILE (file_info)->info == NULL) + return NULL; - return mime_type; + return g_strdup (g_file_info_get_content_type (THUNAR_FILE (file_info)->info)); } @@ -374,26 +404,10 @@ static gboolean thunar_file_info_has_mime_type (ThunarxFileInfo *file_info, const gchar *mime_type) { - ThunarVfsMimeDatabase *mime_database; - ThunarVfsMimeInfo *mime_info; - gboolean valid = FALSE; - GList *mime_infos; - GList *lp; - - /* determine the mime info for the file */ - mime_info = thunar_file_get_mime_info (THUNAR_FILE (file_info)); - if (G_UNLIKELY (mime_info == NULL)) + if (THUNAR_FILE (file_info)->info == NULL) return FALSE; - /* check the related mime types for the file's mime info */ - mime_database = thunar_vfs_mime_database_get_default (); - mime_infos = thunar_vfs_mime_database_get_infos_for_info (mime_database, mime_info); - for (lp = mime_infos; lp != NULL && !valid; lp = lp->next) - valid = (strcmp (thunar_vfs_mime_info_get_name (lp->data), mime_type) == 0); - g_object_unref (G_OBJECT (mime_database)); - thunar_vfs_mime_info_list_free (mime_infos); - - return valid; + return g_content_type_is_a (g_file_info_get_content_type (THUNAR_FILE (file_info)->info), mime_type); } @@ -406,10 +420,37 @@ thunar_file_info_is_directory (ThunarxFileInfo *file_info) -static ThunarVfsInfo* -thunar_file_info_get_vfs_info (ThunarxFileInfo *file_info) +static GFileInfo * +thunar_file_info_get_file_info (ThunarxFileInfo *file_info) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file_info), NULL); + + if (THUNAR_FILE (file_info)->info != NULL) + return g_object_ref (THUNAR_FILE (file_info)->info); + else + return NULL; +} + + + +static GFileInfo * +thunar_file_info_get_filesystem_info (ThunarxFileInfo *file_info) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file_info), NULL); + + if (THUNAR_FILE (file_info)->filesystem_info != NULL) + return g_object_ref (THUNAR_FILE (file_info)->filesystem_info); + else + return NULL; +} + + + +static GFile * +thunar_file_info_get_location (ThunarxFileInfo *file_info) { - return thunar_vfs_info_ref (THUNAR_FILE (file_info)->info); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file_info), NULL); + return g_object_ref (THUNAR_FILE (file_info)->gfile); } @@ -417,9 +458,6 @@ thunar_file_info_get_vfs_info (ThunarxFileInfo *file_info) static void thunar_file_info_changed (ThunarxFileInfo *file_info) { - /* reset the thumbnail state, so the next thunar_icon_factory_load_file_icon() - * invokation will recheck the thumbnail. - */ thunar_file_set_thumb_state (THUNAR_FILE (file_info), THUNAR_FILE_THUMB_STATE_UNKNOWN); /* tell the file monitor that this file changed */ @@ -430,16 +468,16 @@ thunar_file_info_changed (ThunarxFileInfo *file_info) static gboolean thunar_file_denies_access_permission (const ThunarFile *file, - ThunarVfsFileMode usr_permissions, - ThunarVfsFileMode grp_permissions, - ThunarVfsFileMode oth_permissions) + ThunarFileMode usr_permissions, + ThunarFileMode grp_permissions, + ThunarFileMode oth_permissions) { - ThunarVfsFileMode mode; - ThunarVfsGroup *group; - ThunarVfsUser *user; - gboolean result; - GList *groups; - GList *lp; + ThunarFileMode mode; + ThunarGroup *group; + ThunarUser *user; + gboolean result; + GList *groups; + GList *lp; /* query the file mode */ mode = thunar_file_get_mode (file); @@ -456,7 +494,7 @@ thunar_file_denies_access_permission (const ThunarFile *file, if (G_UNLIKELY (effective_user_id == 0)) return FALSE; - if (thunar_vfs_user_is_me (user)) + if (thunar_user_is_me (user)) { /* we're the owner, so the usr permissions must be granted */ result = ((mode & usr_permissions) == 0); @@ -473,13 +511,13 @@ thunar_file_denies_access_permission (const ThunarFile *file, g_object_unref (G_OBJECT (user)); /* determine the effective user */ - user = thunar_vfs_user_manager_get_user_by_id (user_manager, effective_user_id); + user = thunar_user_manager_get_user_by_id (user_manager, effective_user_id); if (G_LIKELY (user != NULL)) { /* check the group permissions */ - groups = thunar_vfs_user_get_groups (user); + groups = thunar_user_get_groups (user); for (lp = groups; lp != NULL; lp = lp->next) - if (THUNAR_VFS_GROUP (lp->data) == group) + if (THUNAR_GROUP (lp->data) == group) { g_object_unref (G_OBJECT (user)); g_object_unref (G_OBJECT (group)); @@ -529,94 +567,116 @@ thunar_file_get_metafile (ThunarFile *file) static void -thunar_file_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data) +thunar_file_monitor_update (GFile *path, + GFileMonitorEvent event_type) { - ThunarFile *file = THUNAR_FILE (user_data); - - _thunar_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); - _thunar_return_if_fail (THUNAR_IS_FILE (file)); - _thunar_return_if_fail (thunar_vfs_path_equal (file->info->path, event_path)); - - /* just to be sure... */ - if (G_UNLIKELY (!thunar_vfs_path_equal (handle_path, event_path))) - return; + ThunarFile *file; - switch (event) + _thunar_return_if_fail (G_IS_FILE (path)); + + file = thunar_file_cache_lookup (path); + if (G_LIKELY (file != NULL)) { - case THUNAR_VFS_MONITOR_EVENT_CHANGED: - case THUNAR_VFS_MONITOR_EVENT_CREATED: - thunar_file_reload (file); - break; - - case THUNAR_VFS_MONITOR_EVENT_DELETED: - thunar_file_destroy (file); - break; + switch (event_type) + { + case G_FILE_MONITOR_EVENT_CREATED: + case G_FILE_MONITOR_EVENT_CHANGED: + case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: + thunar_file_reload (file); + break; + + case G_FILE_MONITOR_EVENT_PRE_UNMOUNT: + case G_FILE_MONITOR_EVENT_DELETED: + thunar_file_reload (file); + break; + + default: + break; + } } } static void -thunar_file_watch_free (gpointer data) +thunar_file_monitor (GFileMonitor *monitor, + GFile *path, + GFile *other_path, + GFileMonitorEvent event_type, + gpointer user_data) { - /* remove the watch from the VFS monitor */ - thunar_vfs_monitor_remove (monitor, data); + ThunarFile *file = THUNAR_FILE (user_data); - /* release our reference on the VFS monitor */ - g_object_unref (G_OBJECT (monitor)); + _thunar_return_if_fail (G_IS_FILE_MONITOR (monitor)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + if (G_UNLIKELY (!G_IS_FILE (path) || !g_file_equal (path, file->gfile))) + return; + + if (G_LIKELY (G_IS_FILE (path))) + thunar_file_monitor_update (path, event_type); + + if (G_UNLIKELY (G_IS_FILE (other_path))) + thunar_file_monitor_update (other_path, event_type); } /** - * thunar_file_get_for_info: - * @info : a #ThunarVfsInfo. + * thunar_file_get: + * @file : a #GFile. + * @error : return location for errors. * - * Looks up the #ThunarFile corresponding to @info. Use - * this function if want to specify the #ThunarVfsInfo - * to use for a #ThunarFile instead of thunar_file_get_for_path(), - * which would determine the #ThunarVfsInfo once again. + * Looks up the #ThunarFile referred to by @file. This function may return a + * ThunarFile even though the file doesn't actually exist. This is the case + * with remote URIs (like SFTP) for instance, if they are not mounted. * * The caller is responsible to call g_object_unref() * when done with the returned object. * - * Return value: the #ThunarFile for @info. + * Return value: the #ThunarFile for @file or %NULL on errors. **/ ThunarFile* -thunar_file_get_for_info (ThunarVfsInfo *info) +thunar_file_get (GFile *gfile, + GError **error) { ThunarFile *file; - _thunar_return_val_if_fail (info != NULL, NULL); + _thunar_return_val_if_fail (G_IS_FILE (gfile), NULL); /* check if we already have a cached version of that file */ - file = thunar_file_cache_lookup (info->path); + file = thunar_file_cache_lookup (gfile); if (G_UNLIKELY (file != NULL)) { /* take a reference for the caller */ - g_object_ref (G_OBJECT (file)); - - /* apply the new info */ - if (!thunar_vfs_info_matches (file->info, info)) - { - thunar_vfs_info_unref (file->info); - file->info = thunar_vfs_info_ref (info); - thunar_file_changed (file); - } + g_object_ref (file); } else { /* allocate a new object */ file = g_object_new (THUNAR_TYPE_FILE, NULL); - file->info = thunar_vfs_info_ref (info); + file->gfile = g_object_ref (gfile); + file->info = NULL; + file->filesystem_info = NULL; + file->custom_icon_name = NULL; + file->display_name = NULL; + file->basename = NULL; + + if (thunar_file_load (file, NULL, error)) + { + /* insert the file into the cache */ + G_LOCK (file_cache_mutex); + g_hash_table_insert (file_cache, g_object_ref (file->gfile), file); + G_UNLOCK (file_cache_mutex); + } + else + { + /* failed loading, destroy the file */ + g_object_unref (file); - /* insert the file into the cache */ - g_hash_table_insert (file_cache, thunar_vfs_path_ref (info->path), file); + /* make sure we return NULL */ + file = NULL; + } } return file; @@ -625,50 +685,32 @@ thunar_file_get_for_info (ThunarVfsInfo *info) /** - * thunar_file_get_for_path: - * @path : a #ThunarVfsPath. - * @error : error return location. - * - * Tries to query the file referred to by @path. Returns %NULL - * if the file could not be queried and @error will point - * to an error describing the problem, else the #ThunarFile - * instance will be returned, which needs to freed using - * g_object_unref() when no longer needed. + * thunar_file_get_for_uri: + * @uri : an URI or an absolute filename. + * @error : return location for errors or %NULL. * - * Note that this function is not thread-safe and may only - * be called from the main thread. + * Convenience wrapper function for thunar_file_get_for_path(), as its + * often required to determine a #ThunarFile for a given @uri. + * + * The caller is responsible to free the returned object using + * g_object_unref() when no longer needed. * - * Return value: the #ThunarFile instance or %NULL on error. + * Return value: the #ThunarFile for the given @uri or %NULL if + * unable to determine. **/ ThunarFile* -thunar_file_get_for_path (ThunarVfsPath *path, - GError **error) +thunar_file_get_for_uri (const gchar *uri, + GError **error) { - ThunarVfsInfo *info; - ThunarFile *file; + ThunarFile *file; + GFile *path; + _thunar_return_val_if_fail (uri != NULL, NULL); _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL); - /* see if we have the corresponding file cached already */ - file = thunar_file_cache_lookup (path); - if (file == NULL) - { - /* determine the file info */ - info = thunar_vfs_info_new_for_path (path, error); - if (G_UNLIKELY (info == NULL)) - return NULL; - - /* allocate the new file object */ - file = thunar_file_get_for_info (info); - - /* release our reference to the info */ - thunar_vfs_info_unref (info); - } - else - { - /* take another reference on the cached file */ - g_object_ref (G_OBJECT (file)); - } + path = g_file_new_for_commandline_arg (uri); + file = thunar_file_get (path, error); + g_object_unref (path); return file; } @@ -676,44 +718,206 @@ thunar_file_get_for_path (ThunarVfsPath *path, /** - * thunar_file_get_for_uri: - * @uri : an URI or an absolute filename. - * @error : return location for errors or %NULL. + * thunar_file_load: + * @file : a #ThunarFile. + * @cancellable : a #GCancellable. + * @error : return location for errors or %NULL. * - * Convenience wrapper function for thunar_file_get_for_path(), as its - * often required to determine a #ThunarFile for a given @uri. + * Loads all information about the file. As this is a possibly + * blocking call, it can be cancelled using @cancellable. * - * The caller is responsible to free the returned object using - * g_object_unref() when no longer needed. + * If loading the file fails or the operation is cancelled, + * @error will be set. * - * Return value: the #ThunarFile for the given @uri or %NULL if - * unable to determine. + * Return value: %TRUE on success, %FALSE on error or interruption. **/ -ThunarFile* -thunar_file_get_for_uri (const gchar *uri, - GError **error) +gboolean +thunar_file_load (ThunarFile *file, + GCancellable *cancellable, + GError **error) { - ThunarVfsPath *path; - ThunarFile *file; + GKeyFile *key_file; + GError *err = NULL; + GFile *thumbnail_dir; + gchar *basename; + gchar *md5_hash; + gchar *thumbnail_dir_path; + gchar *uri = NULL; - _thunar_return_val_if_fail (uri != NULL, NULL); - _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + _thunar_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); - /* determine the path for the URI */ - path = thunar_vfs_path_new (uri, error); - if (G_UNLIKELY (path == NULL)) - return NULL; + /* release the current file info */ + if (file->info != NULL) + { + g_object_unref (file->info); + file->info = NULL; + } - /* determine the file for the path */ - file = thunar_file_get_for_path (path, error); + /* release the current filesystem info */ + if (file->filesystem_info != NULL) + { + g_object_unref (file->filesystem_info); + file->filesystem_info = NULL; + } - /* release the path */ - thunar_vfs_path_unref (path); + /* free the custom icon name */ + g_free (file->custom_icon_name); - return file; -} + /* free display name and basename */ + g_free (file->display_name); + g_free (file->basename); + + /* free thumbnail path */ + g_free (file->thumbnail_path); + + /* assume the file is mounted by default */ + file->is_mounted = TRUE; + + /* query a new file info */ + file->info = g_file_query_info (file->gfile, + THUNARX_FILE_INFO_NAMESPACE, + G_FILE_QUERY_INFO_NONE, + cancellable, &err); + + if (err == NULL) + { + if (g_file_info_get_file_type (file->info) == G_FILE_TYPE_MOUNTABLE) + { + file->is_mounted = + !g_file_info_get_attribute_boolean (file->info, + G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT); + } + } + else + { + if (err->domain == G_IO_ERROR && err->code == G_IO_ERROR_NOT_MOUNTED) + { + file->is_mounted = FALSE; + g_clear_error (&err); + } + } + + /* query a new filesystem info */ + file->filesystem_info = g_file_query_filesystem_info (file->gfile, + THUNARX_FILESYSTEM_INFO_NAMESPACE, + cancellable, + NULL); + + /* determine the basename */ + file->basename = g_file_get_basename (file->gfile); + _thunar_assert (file->basename != NULL); + + /* assume all files are not thumbnails themselves */ + file->is_thumbnail = FALSE; + + /* create a GFile for the $HOME/.thumbnails/ directory */ + thumbnail_dir_path = g_build_filename (xfce_get_homedir (), ".thumbnails", NULL); + thumbnail_dir = g_file_new_for_path (thumbnail_dir_path); + + /* check if this file is a thumbnail */ + if (g_file_has_prefix (file->gfile, thumbnail_dir)) + { + /* remember that this file is a thumbnail */ + file->is_thumbnail = TRUE; + + /* use the filename as custom icon name for thumbnails */ + file->custom_icon_name = g_file_get_path (file->gfile); + } + else if (thunar_file_is_desktop_file (file)) + { + /* determine the custom icon name for .desktop files */ + + /* query a key file for the .desktop file */ + key_file = thunar_g_file_query_key_file (file->gfile, cancellable, NULL); + if (key_file != NULL) + { + /* read the icon name from the .desktop file */ + file->custom_icon_name = g_key_file_get_string (key_file, + G_KEY_FILE_DESKTOP_GROUP, + G_KEY_FILE_DESKTOP_KEY_ICON, + NULL); + + if (file->custom_icon_name != NULL && *file->custom_icon_name != '\0') + { + /* drop any suffix (e.g. '.png') from themed icons */ + if (!g_path_is_absolute (file->custom_icon_name)) + { + gchar *p; + p = strrchr (file->custom_icon_name, '.'); + if (p != NULL) + *p = '\0'; + } + } + + /* free the key file */ + g_key_file_free (key_file); + } + else + { + /* cannot parse the key file, no custom icon */ + file->custom_icon_name = NULL; + } + } + else + { + /* not a .desktop file, no custom icon */ + file->custom_icon_name = NULL; + } + + /* free $HOME/.thumbnails/ GFile and path */ + g_object_unref (thumbnail_dir); + g_free (thumbnail_dir_path); + + /* determine the display name */ + if (file->info != NULL) + { + file->display_name = g_strdup (g_file_info_get_display_name (file->info)); + } + else + { + if (g_file_is_native (file->gfile)) + { + uri = g_file_get_path (file->gfile); + if (uri == NULL) + uri = g_file_get_uri (file->gfile); + } + else + { + uri = g_file_get_uri (file->gfile); + } + + file->display_name = g_filename_display_name (uri); + g_free (uri); + } + /* set thumb state to unknown */ + file->flags = + (file->flags & ~THUNAR_FILE_THUMB_STATE_MASK) | THUNAR_FILE_THUMB_STATE_UNKNOWN; + /* determine thumbnail path */ + uri = g_file_get_uri (file->gfile); + md5_hash = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1); + basename = g_strdup_printf ("%s.png", md5_hash); + file->thumbnail_path = g_build_filename (xfce_get_homedir (), ".thumbnails", + "normal", basename, NULL); + g_free (basename); + g_free (md5_hash); + g_free (uri); + + /* TODO monitor the thumbnail file for changes */ + + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + else + { + return TRUE; + } +} /** * thunar_file_get_parent: @@ -735,16 +939,24 @@ ThunarFile* thunar_file_get_parent (const ThunarFile *file, GError **error) { + ThunarFile *parent = NULL; + GFile *parent_file; + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL); - if (!thunar_file_has_parent (file)) + parent_file = g_file_get_parent (file->gfile); + + if (parent_file == NULL) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT, _("The root folder has no parent")); return NULL; } - return thunar_file_get_for_path (thunar_vfs_path_get_parent (file->info->path), error); + parent = thunar_file_get (parent_file, error); + g_object_unref (parent_file); + + return parent; } @@ -753,8 +965,7 @@ thunar_file_get_parent (const ThunarFile *file, * thunar_file_execute: * @file : a #ThunarFile instance. * @screen : a #GdkScreen. - * @path_list : the list of #ThunarVfsPath<!---->s to supply to @file on - * execution. + * @file_list : the list of #GFile<!---->s to supply to @file on execution. * @error : return location for errors or %NULL. * * Tries to execute @file on the specified @screen. If @file is executable @@ -766,24 +977,163 @@ thunar_file_get_parent (const ThunarFile *file, gboolean thunar_file_execute (ThunarFile *file, GdkScreen *screen, - GList *path_list, + GList *file_list, GError **error) { + gboolean snotify = FALSE; + gboolean terminal; + gboolean result = FALSE; + GKeyFile *key_file; + GError *err = NULL; + GFile *parent; + gchar *icon = NULL; + gchar *name; + gchar *type; + gchar *url; + gchar *location; + gchar *escaped_location; + gchar **argv = NULL; + gchar *exec; + gchar *directory; + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); _thunar_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); - return thunar_vfs_info_execute (file->info, screen, path_list, NULL, error); + + location = thunar_g_file_get_location (file->gfile); + + if (thunar_file_is_desktop_file (file)) + { + key_file = thunar_g_file_query_key_file (file->gfile, NULL, &err); + + if (key_file == NULL) + { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, + _("Failed to parse the desktop file: %s"), err->message); + g_error_free (err); + return FALSE; + } + + type = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, + G_KEY_FILE_DESKTOP_KEY_TYPE, NULL); + + if (G_LIKELY (exo_str_is_equal (type, "Application"))) + { + exec = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, + G_KEY_FILE_DESKTOP_KEY_EXEC, NULL); + if (G_LIKELY (exec != NULL)) + { + /* parse other fields */ + name = g_key_file_get_locale_string (key_file, G_KEY_FILE_DESKTOP_GROUP, + G_KEY_FILE_DESKTOP_KEY_NAME, NULL, + NULL); + icon = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, + G_KEY_FILE_DESKTOP_KEY_ICON, NULL); + terminal = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, + G_KEY_FILE_DESKTOP_KEY_TERMINAL, NULL); + snotify = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, + G_KEY_FILE_DESKTOP_KEY_STARTUP_NOTIFY, + NULL); + + result = thunar_exec_parse (exec, file_list, icon, name, location, + terminal, NULL, &argv, error); + + g_free (name); + g_free (icon); + g_free (exec); + } + else + { + /* TRANSLATORS: `Exec' is a field name in a .desktop file. + * Don't translate it. */ + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, + _("No Exec field specified")); + } + } + else if (exo_str_is_equal (type, "Link")) + { + url = g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, + G_KEY_FILE_DESKTOP_KEY_URL, NULL); + if (G_LIKELY (url != NULL)) + { + /* pass the URL to exo-open which will fire up the appropriate viewer */ + argv = g_new (gchar *, 3); + argv[0] = g_strdup ("exo-open"); + argv[1] = url; + argv[2] = NULL; + result = TRUE; + } + else + { + /* TRANSLATORS: `URL' is a field name in a .desktop file. + * Don't translate it. */ + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, + _("No URL field specified")); + } + } + else + { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, + _("Invalid desktop file")); + } + + g_free (type); + g_key_file_free (key_file); + } + else + { + /* fake the Exec line */ + escaped_location = g_shell_quote (location); + exec = g_strconcat (escaped_location, " %F", NULL); + result = thunar_exec_parse (exec, file_list, NULL, NULL, NULL, FALSE, NULL, &argv, + error); + g_free (escaped_location); + g_free (exec); + } + + if (G_LIKELY (result)) + { + /* determine the working directory */ + if (G_LIKELY (file_list != NULL)) + { + /* use the directory of the first list item */ + parent = g_file_get_parent (file_list->data); + directory = (parent != NULL) ? thunar_g_file_get_location (parent) : NULL; + g_object_unref (parent); + } + else + { + /* use the directory of the executable file */ + parent = g_file_get_parent (file->gfile); + directory = (parent != NULL) ? thunar_g_file_get_location (parent) : NULL; + g_object_unref (parent); + } + + /* execute the command */ + result = thunar_exec_on_screen (screen, directory, argv, NULL, G_SPAWN_SEARCH_PATH, + snotify, icon, error); + + /* release the working directory */ + g_free (directory); + } + + /* clean up */ + g_strfreev (argv); + g_free (location); + + return result; } /** * thunar_file_launch: - * @file : a #ThunarFile instance. - * @parent : a #GtkWidget or a #GdkScreen on which to launch the @file. - * May also be %NULL in which case the default #GdkScreen will - * be used. - * @error : return location for errors or %NULL. + * @file : a #ThunarFile instance. + * @parent : a #GtkWidget or a #GdkScreen on which to launch the @file. + * May also be %NULL in which case the default #GdkScreen will + * be used. + * @startup_id : startup id for the new window (send over for dbus) or %NULL. + * @error : return location for errors or %NULL. * * If @file is an executable file, tries to execute it. Else if @file is * a directory, opens a new #ThunarWindow to display the directory. Else, @@ -798,21 +1148,22 @@ thunar_file_execute (ThunarFile *file, * Return value: %TRUE on success, else %FALSE. **/ gboolean -thunar_file_launch (ThunarFile *file, - gpointer parent, - GError **error) +thunar_file_launch (ThunarFile *file, + gpointer parent, + const gchar *startup_id, + GError **error) { - ThunarVfsMimeApplication *handler; - ThunarVfsMimeDatabase *database; - ThunarApplication *application; - GdkScreen *screen; - gboolean succeed; - GList path_list; + GdkAppLaunchContext *context; + ThunarApplication *application; + GdkScreen *screen; + GAppInfo *app_info; + gboolean succeed; + GList path_list; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); _thunar_return_val_if_fail (parent == NULL || GDK_IS_SCREEN (parent) || GTK_IS_WIDGET (parent), FALSE); - + /* determine the screen for the parent */ if (G_UNLIKELY (parent == NULL)) screen = gdk_screen_get_default (); @@ -821,40 +1172,47 @@ thunar_file_launch (ThunarFile *file, else screen = GDK_SCREEN (parent); - /* check if we should execute the file */ - if (thunar_file_is_executable (file)) - return thunar_file_execute (file, screen, NULL, error); - /* check if we have a folder here */ if (thunar_file_is_directory (file)) { application = thunar_application_get (); - thunar_application_open_window (application, file, screen); + thunar_application_open_window (application, file, screen, startup_id); g_object_unref (G_OBJECT (application)); return TRUE; } - /* determine the default handler for the file */ - database = thunar_vfs_mime_database_get_default (); - handler = thunar_vfs_mime_database_get_default_application (database, thunar_file_get_mime_info (file)); - g_object_unref (G_OBJECT (database)); + /* check if we should execute the file */ + if (thunar_file_is_executable (file)) + return thunar_file_execute (file, screen, NULL, error); + + /* determine the default application to open the file */ + /* TODO We should probably add a cancellable argument to thunar_file_launch() */ + app_info = thunar_file_get_default_handler (file); - /* if we don't have any default handler, just popup the application chooser */ - if (G_UNLIKELY (handler == NULL)) + /* display the application chooser if no application is defined for this file + * type yet */ + if (G_UNLIKELY (app_info == NULL)) { thunar_show_chooser_dialog (parent, file, TRUE); return TRUE; } /* fake a path list */ - path_list.data = thunar_file_get_path (file); + path_list.data = file->gfile; path_list.next = path_list.prev = NULL; + /* create a launch context */ + context = gdk_app_launch_context_new (); + gdk_app_launch_context_set_screen (context, screen); + /* otherwise try to execute the application */ - succeed = thunar_vfs_mime_handler_exec (THUNAR_VFS_MIME_HANDLER (handler), screen, &path_list, error); + succeed = g_app_info_launch (app_info, &path_list, G_APP_LAUNCH_CONTEXT (context), error); + + /* destroy the launch context */ + g_object_unref (context); /* release the handler reference */ - g_object_unref (G_OBJECT (handler)); + g_object_unref (G_OBJECT (app_info)); return succeed; } @@ -868,7 +1226,7 @@ thunar_file_launch (ThunarFile *file, * @error : return location for errors or %NULL. * * Tries to rename @file to the new @name. If @file cannot be renamed, - * %FALSE will be returned and @error will be accordingly. Else, if + * %FALSE will be returned and @error will be set accordingly. Else, if * the operation succeeds, %TRUE will be returned, and @file will have * a new URI and a new display name. * @@ -879,25 +1237,36 @@ thunar_file_launch (ThunarFile *file, * Return value: %TRUE on success, else %FALSE. **/ gboolean -thunar_file_rename (ThunarFile *file, - const gchar *name, - GError **error) +thunar_file_rename (ThunarFile *file, + const gchar *name, + GCancellable *cancellable, + gboolean called_from_job, + GError **error) { - ThunarVfsPath *previous_path; - gboolean succeed; - gint watch_count;; + GFile *previous_file; + GFile *renamed_file; + gint watch_count; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); _thunar_return_val_if_fail (g_utf8_validate (name, -1, NULL), FALSE); + _thunar_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); - /* remember the previous path */ - previous_path = thunar_vfs_path_ref (file->info->path); + /* remember the previous file */ + previous_file = g_object_ref (file->gfile); /* try to rename the file */ - succeed = thunar_vfs_info_rename (file->info, name, error); - if (G_LIKELY (succeed)) + renamed_file = g_file_set_display_name (file->gfile, name, cancellable, error); + + /* check if we succeeded */ + if (renamed_file != NULL) { + /* set the new file */ + file->gfile = renamed_file; + + /* reload file information */ + thunar_file_load (file, NULL, NULL); + /* need to re-register the monitor handle for the new uri */ watch_count = THUNAR_FILE_GET_WATCH_COUNT (file); if (G_LIKELY (watch_count > 0)) @@ -915,23 +1284,36 @@ thunar_file_rename (ThunarFile *file, THUNAR_FILE_SET_WATCH_COUNT (file, watch_count); } + G_LOCK (file_cache_mutex); + /* drop the previous entry from the cache */ - g_hash_table_remove (file_cache, previous_path); + g_hash_table_remove (file_cache, previous_file); + + /* drop the reference on the previous file */ + g_object_unref (previous_file); /* insert the new entry */ - g_hash_table_insert (file_cache, thunar_vfs_path_ref (file->info->path), file); + g_hash_table_insert (file_cache, g_object_ref (file->gfile), file); - /* tell the associated folder that the file was renamed */ - thunarx_file_info_renamed (THUNARX_FILE_INFO (file)); + G_UNLOCK (file_cache_mutex); - /* emit the file changed signal */ - thunar_file_changed (file); - } + if (!called_from_job) + { + /* tell the associated folder that the file was renamed */ + thunarx_file_info_renamed (THUNARX_FILE_INFO (file)); - /* drop the reference on the previous path */ - thunar_vfs_path_unref (previous_path); + /* emit the file changed signal */ + thunar_file_changed (file); + } - return succeed; + return TRUE; + } + else + { + g_object_unref (previous_file); + + return FALSE; + } } @@ -939,7 +1321,7 @@ thunar_file_rename (ThunarFile *file, /** * thunar_file_accepts_drop: * @file : a #ThunarFile instance. - * @path_list : the list of #ThunarVfsPath<!---->s that will be droppped. + * @file_list : the list of #GFile<!---->s that will be droppped. * @context : the current #GdkDragContext, which is used for the drop. * @suggested_action_return : return location for the suggested #GdkDragAction or %NULL. * @@ -956,23 +1338,22 @@ thunar_file_rename (ThunarFile *file, **/ GdkDragAction thunar_file_accepts_drop (ThunarFile *file, - GList *path_list, + GList *file_list, GdkDragContext *context, GdkDragAction *suggested_action_return) { - ThunarVfsPath *parent_path; - ThunarVfsPath *path; - GdkDragAction suggested_action; - GdkDragAction actions; - ThunarFile *ofile; - GList *lp; - guint n; + GdkDragAction suggested_action; + GdkDragAction actions; + ThunarFile *ofile; + GFile *parent_file; + GList *lp; + guint n; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0); _thunar_return_val_if_fail (GDK_IS_DRAG_CONTEXT (context), 0); /* we can never drop an empty list */ - if (G_UNLIKELY (path_list == NULL)) + if (G_UNLIKELY (file_list == NULL)) return 0; /* default to whatever GTK+ thinks for the suggested action */ @@ -984,52 +1365,51 @@ thunar_file_accepts_drop (ThunarFile *file, /* determine the possible actions */ actions = context->actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK); - /* determine the path of the file */ - path = thunar_file_get_path (file); - /* cannot create symbolic links in the trash or copy to the trash */ - if (thunar_vfs_path_get_scheme (path) == THUNAR_VFS_PATH_SCHEME_TRASH) + if (thunar_file_is_trashed (file)) actions &= ~(GDK_ACTION_COPY | GDK_ACTION_LINK); /* check up to 100 of the paths (just in case somebody tries to * drag around his music collection with 5000 files). */ - for (lp = path_list, n = 0; lp != NULL && n < 100; lp = lp->next, ++n) + for (lp = file_list, n = 0; lp != NULL && n < 100; lp = lp->next, ++n) { /* we cannot drop a file on itself */ - if (G_UNLIKELY (thunar_vfs_path_equal (path, lp->data))) + if (G_UNLIKELY (g_file_equal (file->gfile, lp->data))) return 0; /* check whether source and destination are the same */ - parent_path = thunar_vfs_path_get_parent (lp->data); - if (G_LIKELY (parent_path != NULL)) + parent_file = g_file_get_parent (lp->data); + if (G_LIKELY (parent_file != NULL)) { - if (thunar_vfs_path_equal (path, parent_path)) - return 0; + if (g_file_equal (file->gfile, parent_file)) + { + g_object_unref (parent_file); + return 0; + } + else + g_object_unref (parent_file); } - /* check if both source and target is in the trash */ - if (G_UNLIKELY (thunar_vfs_path_get_scheme (lp->data) == THUNAR_VFS_PATH_SCHEME_TRASH - && thunar_vfs_path_get_scheme (path) == THUNAR_VFS_PATH_SCHEME_TRASH)) - { - /* copy/move/link within the trash not possible */ - return 0; - } + /* copy/move/link within the trash not possible */ + if (G_UNLIKELY (thunar_g_file_is_trashed (lp->data) && thunar_file_is_trashed (file))) + return 0; } /* if the source offers both copy and move and the GTK+ suggested action is copy, try to be smart telling whether * we should copy or move by default by checking whether the source and target are on the same disk. */ - if ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE)) != 0 && (suggested_action == GDK_ACTION_COPY)) + if ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE)) != 0 + && (suggested_action == GDK_ACTION_COPY)) { /* default to move as suggested action */ suggested_action = GDK_ACTION_MOVE; /* check for up to 100 files, for the reason state above */ - for (lp = path_list, n = 0; lp != NULL && n < 100; lp = lp->next, ++n) + for (lp = file_list, n = 0; lp != NULL && n < 100; lp = lp->next, ++n) { /* dropping from the trash always suggests move */ - if (G_UNLIKELY (thunar_vfs_path_get_scheme (lp->data) == THUNAR_VFS_PATH_SCHEME_TRASH)) + if (G_UNLIKELY (thunar_g_file_is_trashed (lp->data))) break; /* determine the cached version of the source file */ @@ -1038,7 +1418,11 @@ thunar_file_accepts_drop (ThunarFile *file, /* we have only move if we know the source and both the source and the target * are on the same disk, and the source file is owned by the current user. */ - if (ofile == NULL || (ofile->info->device != file->info->device) || (ofile->info->uid != effective_user_id)) + if (ofile == NULL + || !thunar_file_same_filesystem (file, ofile) + || (ofile->info != NULL + && g_file_info_get_attribute_uint32 (ofile->info, + G_FILE_ATTRIBUTE_UNIX_UID) != effective_user_id)) { /* default to copy and get outa here */ suggested_action = GDK_ACTION_COPY; @@ -1088,21 +1472,33 @@ thunar_file_accepts_drop (ThunarFile *file, * * Return value: the time for @file of the given @date_type. **/ -ThunarVfsFileTime +guint64 thunar_file_get_date (const ThunarFile *file, ThunarFileDateType date_type) { - _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + const gchar *attribute; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0); + + if (file->info == NULL) + return 0; switch (date_type) { - case THUNAR_FILE_DATE_ACCESSED: return file->info->atime; - case THUNAR_FILE_DATE_CHANGED: return file->info->ctime; - case THUNAR_FILE_DATE_MODIFIED: return file->info->mtime; - default: _thunar_assert_not_reached (); + case THUNAR_FILE_DATE_ACCESSED: + attribute = G_FILE_ATTRIBUTE_TIME_ACCESS; + break; + case THUNAR_FILE_DATE_CHANGED: + attribute = G_FILE_ATTRIBUTE_TIME_CHANGED; + break; + case THUNAR_FILE_DATE_MODIFIED: + attribute = G_FILE_ATTRIBUTE_TIME_MODIFIED; + break; + default: + _thunar_assert_not_reached (); } - return (ThunarVfsFileTime) -1; + return g_file_info_get_attribute_uint64 (file->info, attribute); } @@ -1120,169 +1516,732 @@ thunar_file_get_date (const ThunarFile *file, * * Return value: the @date_type of @file formatted as string. **/ -gchar* -thunar_file_get_date_string (const ThunarFile *file, - ThunarFileDateType date_type, - ThunarDateStyle date_style) +gchar* +thunar_file_get_date_string (const ThunarFile *file, + ThunarFileDateType date_type, + ThunarDateStyle date_style) +{ + return thunar_util_humanize_file_time (thunar_file_get_date (file, date_type), date_style); +} + + + +/** + * thunar_file_get_mode_string: + * @file : a #ThunarFile instance. + * + * Returns the mode of @file as text. You'll need to free + * the result using g_free() when you're done with it. + * + * Return value: the mode of @file as string. + **/ +gchar* +thunar_file_get_mode_string (const ThunarFile *file) +{ + ThunarFileMode mode; + GFileType kind; + gchar *text; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + + kind = thunar_file_get_kind (file); + mode = thunar_file_get_mode (file); + text = g_new (gchar, 11); + + /* file type */ + /* TODO earlier versions of Thunar had 'P' for ports and + * 'D' for doors. Do we still need those? */ + switch (kind) + { + case G_FILE_TYPE_SYMBOLIC_LINK: text[0] = 'l'; break; + case G_FILE_TYPE_REGULAR: text[0] = '-'; break; + case G_FILE_TYPE_DIRECTORY: text[0] = 'd'; break; + case G_FILE_TYPE_SPECIAL: + case G_FILE_TYPE_UNKNOWN: + default: + if (S_ISCHR (mode)) + text[0] = 'c'; + else if (S_ISSOCK (mode)) + text[0] = 's'; + else if (S_ISFIFO (mode)) + text[0] = 'f'; + else if (S_ISBLK (mode)) + text[0] = 'b'; + else + text[0] = ' '; + } + + /* permission flags */ + text[1] = (mode & THUNAR_FILE_MODE_USR_READ) ? 'r' : '-'; + text[2] = (mode & THUNAR_FILE_MODE_USR_WRITE) ? 'w' : '-'; + text[3] = (mode & THUNAR_FILE_MODE_USR_EXEC) ? 'x' : '-'; + text[4] = (mode & THUNAR_FILE_MODE_GRP_READ) ? 'r' : '-'; + text[5] = (mode & THUNAR_FILE_MODE_GRP_WRITE) ? 'w' : '-'; + text[6] = (mode & THUNAR_FILE_MODE_GRP_EXEC) ? 'x' : '-'; + text[7] = (mode & THUNAR_FILE_MODE_OTH_READ) ? 'r' : '-'; + text[8] = (mode & THUNAR_FILE_MODE_OTH_WRITE) ? 'w' : '-'; + text[9] = (mode & THUNAR_FILE_MODE_OTH_EXEC) ? 'x' : '-'; + + /* special flags */ + if (G_UNLIKELY (mode & THUNAR_FILE_MODE_SUID)) + text[3] = 's'; + if (G_UNLIKELY (mode & THUNAR_FILE_MODE_SGID)) + text[6] = 's'; + if (G_UNLIKELY (mode & THUNAR_FILE_MODE_STICKY)) + text[9] = 't'; + + text[10] = '\0'; + + return text; +} + + + +/** + * thunar_file_get_size_string: + * @file : a #ThunarFile instance. + * + * Returns the size of the file as text in a human readable + * format. You'll need to free the result using g_free() + * if you're done with it. + * + * Return value: the size of @file in a human readable + * format. + **/ +gchar * +thunar_file_get_size_string (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + return g_format_size_for_display (thunar_file_get_size (file)); +} + + + +/** + * thunar_file_get_volume: + * @file : a #ThunarFile instance. + * + * Attempts to determine the #GVolume on which @file is located. If @file cannot + * determine it's volume, then %NULL will be returned. Else a #GVolume instance + * is returned which has to be released by the caller using g_object_unref(). + * + * Return value: the #GVolume for @file or %NULL. + **/ +GVolume* +thunar_file_get_volume (const ThunarFile *file) +{ + GVolume *volume = NULL; + GMount *mount; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + + /* TODO make this function call asynchronous */ + mount = g_file_find_enclosing_mount (file->gfile, NULL, NULL); + if (mount != NULL) + { + volume = g_mount_get_volume (mount); + g_object_unref (mount); + } + + return volume; +} + + + +/** + * thunar_file_get_group: + * @file : a #ThunarFile instance. + * + * Determines the #ThunarGroup for @file. If there's no + * group associated with @file or if the system is unable to + * determine the group, %NULL will be returned. + * + * The caller is responsible for freeing the returned object + * using g_object_unref(). + * + * Return value: the #ThunarGroup for @file or %NULL. + **/ +ThunarGroup * +thunar_file_get_group (const ThunarFile *file) +{ + guint32 gid; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + + /* TODO what are we going to do on non-UNIX systems? */ + gid = g_file_info_get_attribute_uint32 (file->info, + G_FILE_ATTRIBUTE_UNIX_GID); + + return thunar_user_manager_get_group_by_id (user_manager, gid); +} + + + +/** + * thunar_file_get_user: + * @file : a #ThunarFile instance. + * + * Determines the #ThunarUser for @file. If there's no + * user associated with @file or if the system is unable + * to determine the user, %NULL will be returned. + * + * The caller is responsible for freeing the returned object + * using g_object_unref(). + * + * Return value: the #ThunarUser for @file or %NULL. + **/ +ThunarUser* +thunar_file_get_user (const ThunarFile *file) +{ + guint32 uid; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + + /* TODO what are we going to do on non-UNIX systems? */ + uid = g_file_info_get_attribute_uint32 (file->info, + G_FILE_ATTRIBUTE_UNIX_UID); + + return thunar_user_manager_get_user_by_id (user_manager, uid); +} + + + +/** + * thunar_file_get_content_type: + * @file : a #ThunarFile. + * + * Returns the content type of @file. + * + * Return value: content type of @file. + **/ +const gchar * +thunar_file_get_content_type (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + + if (file->info == NULL) + return NULL; + + return g_file_info_get_content_type (file->info); +} + + + +/** + * thunar_file_get_symlink_target: + * @file : a #ThunarFile. + * + * Returns the path of the symlink target or %NULL if the @file + * is not a symlink. + * + * Return value: path of the symlink target or %NULL. + **/ +const gchar * +thunar_file_get_symlink_target (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + + if (file->info == NULL) + return NULL; + + return g_file_info_get_symlink_target (file->info); +} + + + +/** + * thunar_file_get_basename: + * @file : a #ThunarFile. + * + * Returns the basename of the @file in UTF-8 encoding. + * + * Return value: UTF-8 encoded basename of the @file. + **/ +const gchar * +thunar_file_get_basename (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + return file->basename; +} + + + +/** + * thunar_file_is_symlink: + * @file : a #ThunarFile. + * + * Returns %TRUE if @file is a symbolic link. + * + * Return value: %TRUE if @file is a symbolic link. + **/ +gboolean +thunar_file_is_symlink (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (file->info == NULL) + return FALSE; + + return g_file_info_get_is_symlink (file->info); +} + + + +/** + * thunar_file_get_size: + * @file : a #ThunarFile instance. + * + * Tries to determine the size of @file in bytes and + * returns the size. + * + * Return value: the size of @file in bytes. + **/ +guint64 +thunar_file_get_size (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0); + + if (file->info == NULL) + return 0; + + return g_file_info_get_size (file->info); +} + + + +/** + * thunar_file_get_default_handler: + * @file : a #ThunarFile instance. + * + * Returns the default #GAppInfo for @file or %NULL if there is none. + * + * The caller is responsible to free the returned #GAppInfo using + * g_object_unref(). + * + * Return value: Default #GAppInfo for @file or %NULL if there is none. + **/ +GAppInfo * +thunar_file_get_default_handler (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + return g_file_query_default_handler (THUNAR_FILE ((file))->gfile, NULL, NULL); +} + + + +/** + * thunar_file_get_kind: + * @file : a #ThunarFile instance. + * + * Returns the kind of @file. + * + * Return value: the kind of @file. + **/ +GFileType +thunar_file_get_kind (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), G_FILE_TYPE_UNKNOWN); + + if (file->info == NULL) + return G_FILE_TYPE_UNKNOWN; + + return g_file_info_get_file_type (file->info); +} + + + +GFile * +thunar_file_get_target_location (const ThunarFile *file) +{ + const gchar *uri; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + + if (file->info == NULL) + return g_object_ref (file->gfile); + + uri = g_file_info_get_attribute_string (file->info, + G_FILE_ATTRIBUTE_STANDARD_TARGET_URI); + + return (uri != NULL) ? g_file_new_for_uri (uri) : NULL; +} + + + +/** + * thunar_file_get_mode: + * @file : a #ThunarFile instance. + * + * Returns the permission bits of @file. + * + * Return value: the permission bits of @file. + **/ +ThunarFileMode +thunar_file_get_mode (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), 0); + + if (file->info == NULL) + return 0; + + return g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_MODE); +} + + + +/** + * thunar_file_get_free_space: + * @file : a #ThunarFile instance. + * @free_space_return : return location for the amount of + * free space or %NULL. + * + * Determines the amount of free space of the volume on + * which @file resides. Returns %TRUE if the amount of + * free space was determined successfully and placed into + * @free_space_return, else %FALSE will be returned. + * + * Return value: %TRUE if successfull, else %FALSE. + **/ +gboolean +thunar_file_get_free_space (const ThunarFile *file, + guint64 *free_space_return) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (file->filesystem_info == NULL) + return FALSE; + + *free_space_return = g_file_info_get_attribute_uint64 (file->filesystem_info, + G_FILE_ATTRIBUTE_FILESYSTEM_FREE); + + return g_file_info_has_attribute (file->filesystem_info, + G_FILE_ATTRIBUTE_FILESYSTEM_FREE); +} + + + +gboolean +thunar_file_is_mounted (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + return file->is_mounted; +} + + + +gboolean +thunar_file_exists (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + return g_file_query_exists (file->gfile, NULL); +} + + + +/** + * thunar_file_is_directory: + * @file : a #ThunarFile instance. + * + * Checks whether @file refers to a directory. + * + * Return value: %TRUE if @file is a directory. + **/ +gboolean +thunar_file_is_directory (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (file->info == NULL) + return FALSE; + + return thunar_file_get_kind (file) == G_FILE_TYPE_DIRECTORY; +} + + + +/** + * thunar_file_is_local: + * @file : a #ThunarFile instance. + * + * Returns %TRUE if @file is a local file with the + * file:// URI scheme. + * + * Return value: %TRUE if @file is local. + **/ +gboolean +thunar_file_is_local (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + return g_file_has_uri_scheme (file->gfile, "file"); +} + + + +/** + * thunar_file_is_ancestor: + * @file : a #ThunarFile instance. + * @ancestor : another #ThunarFile instance. + * + * Determines whether @file is somewhere inside @ancestor, + * possibly with intermediate folders. + * + * Return value: %TRUE if @ancestor contains @file as a + * child, grandchild, great grandchild, etc. + **/ +gboolean +thunar_file_is_ancestor (const ThunarFile *file, + const ThunarFile *ancestor) +{ + gboolean is_ancestor = FALSE; + GFile *current = NULL; + GFile *tmp; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + _thunar_return_val_if_fail (THUNAR_IS_FILE (ancestor), FALSE); + + for (current = g_object_ref (file->gfile); + is_ancestor == FALSE && current != NULL; + tmp = g_file_get_parent (current), g_object_unref (current), current = tmp) + { + if (G_UNLIKELY (g_file_equal (current, ancestor->gfile))) + is_ancestor = TRUE; + } + + if (current != NULL) + g_object_unref (current); + + return is_ancestor; +} + + + +/** + * thunar_file_is_executable: + * @file : a #ThunarFile instance. + * + * Determines whether the owner of the current process is allowed + * to execute the @file (or enter the directory refered to by + * @file). On UNIX it also returns %TRUE if @file refers to a + * desktop entry. + * + * Return value: %TRUE if @file can be executed. + **/ +gboolean +thunar_file_is_executable (const ThunarFile *file) +{ + gboolean can_execute = FALSE; + const gchar *content_type; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (file->info == NULL) + return FALSE; + + if (g_file_info_get_attribute_boolean (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) + { + /* get the content type of the file */ + content_type = g_file_info_get_content_type (file->info); + if (G_LIKELY (content_type != NULL)) + { +#ifdef G_OS_WIN32 + /* check for .exe, .bar or .com */ + can_execute = g_content_type_can_be_executable (content_type); +#else + /* check if the content type is save to execute, we don't use + * g_content_type_can_be_executable() for unix because it also returns + * true for "text/plain" and we don't want that */ + if (g_content_type_is_a (content_type, "application/x-executable") + || g_content_type_is_a (content_type, "application/x-shellscript")) + { + can_execute = TRUE; + } +#endif + } + } + + return can_execute || thunar_file_is_desktop_file (file); +} + + + +/** + * thunar_file_is_readable: + * @file : a #ThunarFile instance. + * + * Determines whether the owner of the current process is allowed + * to read the @file. + * + * Return value: %TRUE if @file can be read. + **/ +gboolean +thunar_file_is_readable (const ThunarFile *file) { - return thunar_util_humanize_file_time (thunar_file_get_date (file, date_type), date_style); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (file->info == NULL) + return FALSE; + + if (!g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) + return TRUE; + + return g_file_info_get_attribute_boolean (file->info, + G_FILE_ATTRIBUTE_ACCESS_CAN_READ); } /** - * thunar_file_get_mode_string: + * thunar_file_is_writable: * @file : a #ThunarFile instance. * - * Returns the mode of @file as text. You'll need to free - * the result using g_free() when you're done with it. + * Determines whether the owner of the current process is allowed + * to write the @file. * - * Return value: the mode of @file as string. + * Return value: %TRUE if @file can be read. **/ -gchar* -thunar_file_get_mode_string (const ThunarFile *file) +gboolean +thunar_file_is_writable (const ThunarFile *file) { - ThunarVfsFileType kind; - ThunarVfsFileMode mode; - gchar *text; - - _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (file->info == NULL) + return FALSE; - kind = thunar_file_get_kind (file); - mode = thunar_file_get_mode (file); - text = g_new (gchar, 11); + if (!g_file_info_has_attribute (file->info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) + return TRUE; - /* file type */ - switch (kind) - { - case THUNAR_VFS_FILE_TYPE_PORT: text[0] = 'P'; break; - case THUNAR_VFS_FILE_TYPE_DOOR: text[0] = 'D'; break; - case THUNAR_VFS_FILE_TYPE_SOCKET: text[0] = 's'; break; - case THUNAR_VFS_FILE_TYPE_SYMLINK: text[0] = 'l'; break; - case THUNAR_VFS_FILE_TYPE_REGULAR: text[0] = '-'; break; - case THUNAR_VFS_FILE_TYPE_BLOCKDEV: text[0] = 'b'; break; - case THUNAR_VFS_FILE_TYPE_DIRECTORY: text[0] = 'd'; break; - case THUNAR_VFS_FILE_TYPE_CHARDEV: text[0] = 'c'; break; - case THUNAR_VFS_FILE_TYPE_FIFO: text[0] = 'f'; break; - case THUNAR_VFS_FILE_TYPE_UNKNOWN: text[0] = ' '; break; - default: _thunar_assert_not_reached (); - } + return g_file_info_get_attribute_boolean (file->info, + G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE); +} - /* permission flags */ - text[1] = (mode & THUNAR_VFS_FILE_MODE_USR_READ) ? 'r' : '-'; - text[2] = (mode & THUNAR_VFS_FILE_MODE_USR_WRITE) ? 'w' : '-'; - text[3] = (mode & THUNAR_VFS_FILE_MODE_USR_EXEC) ? 'x' : '-'; - text[4] = (mode & THUNAR_VFS_FILE_MODE_GRP_READ) ? 'r' : '-'; - text[5] = (mode & THUNAR_VFS_FILE_MODE_GRP_WRITE) ? 'w' : '-'; - text[6] = (mode & THUNAR_VFS_FILE_MODE_GRP_EXEC) ? 'x' : '-'; - text[7] = (mode & THUNAR_VFS_FILE_MODE_OTH_READ) ? 'r' : '-'; - text[8] = (mode & THUNAR_VFS_FILE_MODE_OTH_WRITE) ? 'w' : '-'; - text[9] = (mode & THUNAR_VFS_FILE_MODE_OTH_EXEC) ? 'x' : '-'; - /* special flags */ - if (G_UNLIKELY (mode & THUNAR_VFS_FILE_MODE_SUID)) - text[3] = 's'; - if (G_UNLIKELY (mode & THUNAR_VFS_FILE_MODE_SGID)) - text[6] = 's'; - if (G_UNLIKELY (mode & THUNAR_VFS_FILE_MODE_STICKY)) - text[9] = 't'; - text[10] = '\0'; +/** + * thunar_file_is_hidden: + * @file : a #ThunarFile instance. + * + * Checks whether @file can be considered a hidden file. + * + * Return value: %TRUE if @file is a hidden file, else %FALSE. + **/ +gboolean +thunar_file_is_hidden (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (file->info == NULL) + return FALSE; - return text; + return g_file_info_get_is_hidden (file->info); } /** - * thunar_file_get_size_string: - * @file : a #ThunarFile instance. + * thunar_file_is_home: + * @file : a #ThunarFile. * - * Returns the size of the file as text in a human readable - * format. You'll need to free the result using g_free() - * if you're done with it. + * Checks whether @file refers to the users home directory. * - * Return value: the size of @file in a human readable - * format. + * Return value: %TRUE if @file is the users home directory. **/ -gchar* -thunar_file_get_size_string (const ThunarFile *file) +gboolean +thunar_file_is_home (const ThunarFile *file) { - ThunarVfsFileSize size; + gboolean is_home = FALSE; + GFile *home; - _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); - size = thunar_file_get_size (file); + home = thunar_g_file_new_for_home (); + is_home = g_file_equal (file->gfile, home); + g_object_unref (home); - return thunar_vfs_humanize_size (size, NULL, 0); + return is_home; } /** - * thunar_file_get_volume: - * @file : a #ThunarFile instance. - * @volume_manager : the #ThunarVfsVolumeManager to use for the volume lookup. + * thunar_file_is_regular: + * @file : a #ThunarFile. * - * Attempts to determine the #ThunarVfsVolume on which @file is located - * using the given @volume_manager. If @file cannot determine it's volume, - * then %NULL will be returned. Else a #ThunarVfsVolume instance is returned, - * which is owned by @volume_manager and thereby the caller must not free - * the returned object. + * Checks whether @file refers to a regular file. * - * Return value: the #ThunarVfsVolume for @file in @volume_manager or %NULL. + * Return value: %TRUE if @file is a regular file. **/ -ThunarVfsVolume* -thunar_file_get_volume (const ThunarFile *file, - ThunarVfsVolumeManager *volume_manager) +gboolean +thunar_file_is_regular (const ThunarFile *file) { - _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); - _thunar_return_val_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager), NULL); - return thunar_vfs_volume_manager_get_volume_by_info (volume_manager, file->info); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + return thunar_file_get_kind (file) == G_FILE_TYPE_REGULAR; } /** - * thunar_file_get_group: + * thunar_file_is_trashed: * @file : a #ThunarFile instance. * - * Determines the #ThunarVfsGroup for @file. If there's no - * group associated with @file or if the system is unable to - * determine the group, %NULL will be returned. + * Returns %TRUE if @file is a local file that resides in + * the trash bin. * - * The caller is responsible for freeing the returned object - * using g_object_unref(). + * Return value: %TRUE if @file is in the trash, or + * the trash folder itself. + **/ +gboolean +thunar_file_is_trashed (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + return thunar_g_file_is_trashed (file->gfile); +} + + + +/** + * thunar_file_is_desktop_file: + * @file : a #ThunarFile. * - * Return value: the #ThunarVfsGroup for @file or %NULL. + * Returns %TRUE if @file is a .desktop file, but not a .directory file. + * + * Return value: %TRUE if @file is a .desktop file. **/ -ThunarVfsGroup* -thunar_file_get_group (const ThunarFile *file) +gboolean +thunar_file_is_desktop_file (const ThunarFile *file) { - _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); - return thunar_vfs_user_manager_get_group_by_id (user_manager, file->info->gid); + const gchar *content_type; + gboolean is_desktop_file = FALSE; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (file->info == NULL) + return FALSE; + + content_type = g_file_info_get_content_type (file->info); + + if (content_type != NULL) + is_desktop_file = g_content_type_equals (content_type, "application/x-desktop"); + + return is_desktop_file + && !g_str_has_suffix (thunar_file_get_basename (file), ".directory"); } /** - * thunar_file_get_user: + * thunar_file_get_display_name: * @file : a #ThunarFile instance. * - * Determines the #ThunarVfsUser for @file. If there's no - * user associated with @file or if the system is unable - * to determine the user, %NULL will be returned. - * - * The caller is responsible for freeing the returned object - * using g_object_unref(). + * Returns the @file name in the UTF-8 encoding, which is + * suitable for displaying the file name in the GUI. * - * Return value: the #ThunarVfsUser for @file or %NULL. + * Return value: the @file name suitable for display. **/ -ThunarVfsUser* -thunar_file_get_user (const ThunarFile *file) +const gchar * +thunar_file_get_display_name (const ThunarFile *file) { - _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); - return thunar_vfs_user_manager_get_user_by_id (user_manager, file->info->uid); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + return file->display_name; } @@ -1306,22 +2265,19 @@ gchar* thunar_file_get_deletion_date (const ThunarFile *file, ThunarDateStyle date_style) { - time_t time; - gchar *date; + const gchar *date; + time_t time; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + _thunar_return_val_if_fail (G_IS_FILE_INFO (file->info), NULL); - /* query the DeletionDate from the trash backend */ - date = thunar_vfs_info_get_metadata (file->info, THUNAR_VFS_INFO_METADATA_TRASH_DELETION_DATE, NULL); + date = g_file_info_get_attribute_string (file->info, "trash::deletion-date"); if (G_UNLIKELY (date == NULL)) return NULL; /* try to parse the DeletionDate (RFC 3339 string) */ time = thunar_util_time_from_rfc3339 (date); - /* release the DeletionDate */ - g_free (date); - /* humanize the time value */ return thunar_util_humanize_file_time (time, date_style); } @@ -1336,19 +2292,21 @@ thunar_file_get_deletion_date (const ThunarFile *file, * is located in the trash. Otherwise %NULL will be * returned. * - * The caller is responsible to free the returned string - * using g_free() when no longer needed. - * * Return value: the original path of @file if @file is * in the trash, %NULL otherwise. **/ -gchar* +const gchar * thunar_file_get_original_path (const ThunarFile *file) { _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); - /* query the OriginalPath from the trash backend */ - return thunar_vfs_info_get_metadata (file->info, THUNAR_VFS_INFO_METADATA_TRASH_ORIGINAL_PATH, NULL); + if (file->info == NULL) + return NULL; + + if (g_file_info_has_attribute (file->info, "trash::orig-file")) + return g_file_info_get_attribute_string (file->info, "trash::orig-file"); + else + return NULL; } @@ -1373,7 +2331,17 @@ thunar_file_is_chmodable (const ThunarFile *file) * b) the super-user id * and the file is not in the trash. */ - return ((effective_user_id == 0 || effective_user_id == file->info->uid) && !thunar_file_is_trashed (file)); + if (file->info == NULL) + { + return (effective_user_id == 0 && !thunar_file_is_trashed (file)); + } + else + { + return ((effective_user_id == 0 + || effective_user_id == g_file_info_get_attribute_uint32 (file->info, + G_FILE_ATTRIBUTE_UNIX_UID)) + && !thunar_file_is_trashed (file)); + } } @@ -1392,23 +2360,27 @@ thunar_file_is_chmodable (const ThunarFile *file) gboolean thunar_file_is_renameable (const ThunarFile *file) { - gboolean renameable = FALSE; + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + if (file->info == NULL) + return FALSE; + + return g_file_info_get_attribute_boolean (file->info, + G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME); +} + + +gboolean +thunar_file_can_be_trashed (const ThunarFile *file) +{ _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); - /* we cannot the node node or trashed files */ - if (!thunar_file_is_root (file) && !thunar_file_is_trashed (file)) - { - /* we just do a guess here, by checking whether the folder is writable */ - file = thunar_file_get_parent (file, NULL); - if (G_LIKELY (file != NULL)) - { - renameable = thunar_file_is_writable (file); - g_object_unref (G_OBJECT (file)); - } - } + if (file->info == NULL) + return FALSE; - return renameable; + return g_file_info_get_attribute_boolean (file->info, + G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH); } @@ -1432,10 +2404,10 @@ thunar_file_is_renameable (const ThunarFile *file) GList* thunar_file_get_emblem_names (ThunarFile *file) { - const ThunarVfsInfo *info = file->info; - const gchar *emblem_string; - gchar **emblem_names; - GList *emblems = NULL; + const gchar *emblem_string; + guint32 uid; + gchar **emblem_names; + GList *emblems = NULL; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); @@ -1460,21 +2432,27 @@ thunar_file_get_emblem_names (ThunarFile *file) emblems = g_list_append (emblems, *emblem_names); } - if ((info->flags & THUNAR_VFS_FILE_FLAGS_SYMLINK) != 0) + if (thunar_file_is_symlink (file)) emblems = g_list_prepend (emblems, THUNAR_FILE_EMBLEM_NAME_SYMBOLIC_LINK); + /* determine the user ID of the file owner */ + /* TODO what are we going to do here on non-UNIX systems? */ + uid = file->info != NULL + ? g_file_info_get_attribute_uint32 (file->info, G_FILE_ATTRIBUTE_UNIX_UID) + : 0; + /* we add "cant-read" if either (a) the file is not readable or (b) a directory, that lacks the * x-bit, see http://bugzilla.xfce.org/show_bug.cgi?id=1408 for the details about this change. */ if (!thunar_file_is_readable (file) || (thunar_file_is_directory (file) - && thunar_file_denies_access_permission (file, THUNAR_VFS_FILE_MODE_USR_EXEC, - THUNAR_VFS_FILE_MODE_GRP_EXEC, - THUNAR_VFS_FILE_MODE_OTH_EXEC))) + && thunar_file_denies_access_permission (file, THUNAR_FILE_MODE_USR_EXEC, + THUNAR_FILE_MODE_GRP_EXEC, + THUNAR_FILE_MODE_OTH_EXEC))) { emblems = g_list_prepend (emblems, THUNAR_FILE_EMBLEM_NAME_CANT_READ); } - else if (G_UNLIKELY (file->info->uid == effective_user_id && !thunar_file_is_writable (file))) + else if (G_UNLIKELY (uid == effective_user_id && !thunar_file_is_writable (file))) { /* we own the file, but we cannot write to it, that's why we mark it as "cant-write", so * users won't be surprised when opening the file in a text editor, but are unable to save. @@ -1545,7 +2523,9 @@ thunar_file_set_emblem_names (ThunarFile *file, * @custom_icon : the new custom icon for the @file. * @error : return location for errors or %NULL. * - * Wrapper for _thunar_vfs_info_set_custom_icon(). + * Tries to change the custom icon of the .desktop file referred + * to by @file. If that fails, %FALSE is returned and the + * @error is set accordingly. * * Return value: %TRUE if the icon of @file was changed, %FALSE otherwise. **/ @@ -1554,17 +2534,33 @@ thunar_file_set_custom_icon (ThunarFile *file, const gchar *custom_icon, GError **error) { + GKeyFile *key_file; + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); _thunar_return_val_if_fail (custom_icon != NULL, FALSE); - /* try to set the new custom_icon for the file */ - if (!thunar_vfs_info_set_custom_icon (file->info, custom_icon, error)) + key_file = thunar_g_file_query_key_file (file->gfile, NULL, error); + + if (key_file == NULL) return FALSE; - /* tell everybody that we have changed */ - thunar_file_changed (file); - return TRUE; + g_key_file_set_string (key_file, G_KEY_FILE_DESKTOP_GROUP, + G_KEY_FILE_DESKTOP_KEY_ICON, custom_icon); + + if (thunar_g_file_write_key_file (file->gfile, key_file, NULL, error)) + { + /* tell everybody that we have changed */ + thunar_file_changed (file); + + g_key_file_free (key_file); + return TRUE; + } + else + { + g_key_file_free (key_file); + return FALSE; + } } @@ -1579,23 +2575,91 @@ thunar_file_set_custom_icon (ThunarFile *file, gboolean thunar_file_is_desktop (const ThunarFile *file) { -#if GLIB_CHECK_VERSION(2,14,0) - gchar file_path[THUNAR_VFS_PATH_MAXSTRLEN]; + GFile *desktop; + gboolean is_desktop = FALSE; + + desktop = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)); + is_desktop = g_file_equal (file->gfile, desktop); + g_object_unref (desktop); + + return is_desktop; +} + + + +const gchar * +thunar_file_get_thumbnail_path (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + return file->thumbnail_path; +} + + + +gboolean +thunar_file_is_thumbnail (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + return file->is_thumbnail; +} + + + +/** + * thunar_file_set_thumb_state: + * @file : a #ThunarFile. + * @thumb_state : the new #ThunarFileThumbState. + * + * Sets the #ThunarFileThumbState for @file to @thumb_state. + * This will cause a "file-changed" signal to be emitted from + * #ThunarFileMonitor. + **/ +void +thunar_file_set_thumb_state (ThunarFile *file, + ThunarFileThumbState state) +{ + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + /* set the new thumbnail state */ + file->flags = (file->flags & ~THUNAR_FILE_THUMB_STATE_MASK) | (state); + + /* notify others of this change, so that all components can update + * their file information */ + thunar_file_monitor_file_changed (file); +} + + + +/** + * thunar_file_get_custom_icon: + * @file : a #ThunarFile instance. + * + * Queries the custom icon from @file if any, else %NULL is returned. + * The custom icon can be either a themed icon name or an absolute path + * to an icon file in the local file system. + * + * Return value: the custom icon for @file or %NULL. + **/ +gchar * +thunar_file_get_custom_icon (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + return g_strdup (file->custom_icon_name); +} + - file_path[0] = '\0'; - thunar_vfs_path_to_string (thunar_file_get_path (file), file_path, - sizeof (file_path), NULL); - /* g_get_user_special_dir () always returns something for the desktop */ - return exo_str_is_equal (file_path, g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)); -#else /* GLIB_CHECK_VERSION(2,14,0) */ -return (!thunar_vfs_path_is_root (thunar_file_get_path (file)) - && thunar_vfs_path_is_home (thunar_vfs_path_get_parent (thunar_file_get_path (file))) - && exo_str_is_equal (thunar_file_get_display_name (file), "Desktop")); -#endif /* GLIB_CHECK_VERSION(2,14,0) */ +GIcon * +thunar_file_get_preview_icon (const ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + _thunar_return_val_if_fail (file->info != NULL, NULL); + + return G_ICON (g_file_info_get_attribute_object (file->info, "preview::icon")); } + /** * thunar_file_get_icon_name: * @file : a #ThunarFile instance. @@ -1603,55 +2667,91 @@ return (!thunar_vfs_path_is_root (thunar_file_get_path (file)) * @icon_theme : the #GtkIconTheme on which to lookup up the icon name. * * Returns the name of the icon that can be used to present @file, based - * on the given @icon_state and @icon_theme. + * on the given @icon_state and @icon_theme. The returned string has to + * be freed using g_free(). * * Return value: the icon name for @file in @icon_theme. **/ -const gchar* +gchar * thunar_file_get_icon_name (const ThunarFile *file, ThunarFileIconState icon_state, GtkIconTheme *icon_theme) { - const gchar *icon_name; + GFile *icon_file; + GIcon *icon; + gchar **themed_icon_names; + gchar *icon_name = NULL; + gint i; _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); _thunar_return_val_if_fail (GTK_IS_ICON_THEME (icon_theme), NULL); - /* special icon for the home node */ - if (G_UNLIKELY (thunar_file_is_home (file)) - && gtk_icon_theme_has_icon (icon_theme, "gnome-fs-home")) + /* the system root folder has a special icon */ + if (thunar_file_is_root (file) + && thunar_file_is_local (file) + && thunar_file_is_directory (file)) { - return "gnome-fs-home"; + return g_strdup ("drive-harddisk"); } - /* special icon for the desktop node */ - if (G_UNLIKELY (thunar_file_is_desktop (file)) - && gtk_icon_theme_has_icon (icon_theme, "gnome-fs-desktop")) - { - return "gnome-fs-desktop"; - } - - /* try to be smart when determining icons for executable files - * in that we use the name of the file as icon name (which will - * work for quite a lot of binaries, e.g. 'Terminal', 'mousepad', - * 'Thunar', 'xfmedia', etc.). - */ - if (G_UNLIKELY (thunar_file_is_executable (file))) + if (file->info == NULL) + return NULL; + + icon = g_file_info_get_icon (file->info); + + if (icon != NULL) { - icon_name = thunar_vfs_path_get_name (file->info->path); - if (G_UNLIKELY (gtk_icon_theme_has_icon (icon_theme, icon_name))) - return icon_name; - } + if (G_IS_THEMED_ICON (icon)) + { + g_object_get (icon, "names", &themed_icon_names, NULL); + + for (i = 0; icon_name == NULL && themed_icon_names[i] != NULL; ++i) + if (gtk_icon_theme_has_icon (icon_theme, themed_icon_names[i])) + icon_name = g_strdup (themed_icon_names[i]); - /* default is the mime type icon */ - icon_name = thunar_vfs_mime_info_lookup_icon_name (file->info->mime_info, icon_theme); + g_strfreev (themed_icon_names); + } + else if (G_IS_FILE_ICON (icon)) + { + icon_file = g_file_icon_get_file (G_FILE_ICON (icon)); + icon_name = g_file_get_path (icon_file); + g_object_unref (icon_file); + } + } + + if (icon_name == NULL) + { + /* try to be smart when determining icons for executable files + * in that we use the name of the file as icon name (which will + * work for quite a lot of binaries, e.g. 'Terminal', 'mousepad', + * 'Thunar', 'xfmedia', etc.). + */ + if (G_UNLIKELY (thunar_file_is_executable (file))) + { + icon_name = g_file_get_basename (file->gfile); + if (G_LIKELY (!gtk_icon_theme_has_icon (icon_theme, icon_name))) + { + g_free (icon_name); + icon_name = NULL; + } + } + } /* check if we have an accept icon for the icon we found */ - if ((icon_state == THUNAR_FILE_ICON_STATE_DROP || icon_state == THUNAR_FILE_ICON_STATE_OPEN) - && strcmp (icon_name, "gnome-fs-directory") == 0 - && gtk_icon_theme_has_icon (icon_theme, "gnome-fs-directory-accept")) + if (icon_name != NULL + && (g_str_equal (icon_name, "inode-directory") + || g_str_equal (icon_name, "folder"))) { - return "gnome-fs-directory-accept"; + if (icon_state == THUNAR_FILE_ICON_STATE_DROP) + { + g_free (icon_name); + icon_name = g_strdup ("folder-drag-accept"); + } + else if (icon_state == THUNAR_FILE_ICON_STATE_OPEN) + { + g_free (icon_name); + icon_name = g_strdup ("folder-open"); + } } return icon_name; @@ -1687,7 +2787,7 @@ thunar_file_get_metadata (ThunarFile *file, _thunar_return_val_if_fail (key < THUNAR_METAFILE_N_KEYS, NULL); return thunar_metafile_fetch (thunar_file_get_metafile (file), - file->info->path, key, + file->gfile, key, default_value); } @@ -1715,7 +2815,7 @@ thunar_file_set_metadata (ThunarFile *file, _thunar_return_if_fail (value != NULL); thunar_metafile_store (thunar_file_get_metafile (file), - file->info->path, key, value, + file->gfile, key, value, default_value); } @@ -1740,8 +2840,7 @@ thunar_file_set_metadata (ThunarFile *file, void thunar_file_watch (ThunarFile *file) { - ThunarVfsMonitorHandle *handle; - gint watch_count; + gint watch_count; _thunar_return_if_fail (THUNAR_IS_FILE (file)); _thunar_return_if_fail (THUNAR_FILE_GET_WATCH_COUNT (file) >= 0); @@ -1750,20 +2849,16 @@ thunar_file_watch (ThunarFile *file) if (++watch_count == 1) { - /* take a reference on the VFS monitor for this instance */ - if (G_LIKELY (monitor == NULL)) - { - monitor = thunar_vfs_monitor_get_default (); - g_object_add_weak_pointer (G_OBJECT (monitor), (gpointer) &monitor); - } - else + /* create a file or directory monitor */ + file->monitor = g_file_monitor (file->gfile, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL); + if (G_LIKELY (file->monitor != NULL)) { - g_object_ref (G_OBJECT (monitor)); - } + /* make sure the pointer is set to NULL once the monitor is destroyed */ + g_object_add_weak_pointer (G_OBJECT (file->monitor), (gpointer) &(file->monitor)); - /* add us to the file monitor */ - handle = thunar_vfs_monitor_add_file (monitor, file->info->path, thunar_file_monitor, file); - g_object_set_qdata_full (G_OBJECT (file), thunar_file_watch_handle_quark, handle, thunar_file_watch_free); + /* watch monitor for file changes */ + g_signal_connect (file->monitor, "changed", G_CALLBACK (thunar_file_monitor), file); + } } THUNAR_FILE_SET_WATCH_COUNT (file, watch_count); @@ -1790,8 +2885,14 @@ thunar_file_unwatch (ThunarFile *file) if (--watch_count == 0) { - /* just unset the watch handle */ - g_object_set_qdata (G_OBJECT (file), thunar_file_watch_handle_quark, NULL); + if (G_LIKELY (file->monitor != NULL)) + { + /* cancel monitoring */ + g_file_monitor_cancel (file->monitor); + + /* destroy the monitor */ + g_object_unref (file->monitor); + } } THUNAR_FILE_SET_WATCH_COUNT (file, watch_count); @@ -1812,26 +2913,18 @@ thunar_file_unwatch (ThunarFile *file) void thunar_file_reload (ThunarFile *file) { - ThunarVfsInfo *info; - _thunar_return_if_fail (THUNAR_IS_FILE (file)); - /* re-query the file info */ - info = thunar_vfs_info_new_for_path (file->info->path, NULL); - if (G_UNLIKELY (info == NULL)) + if (!thunar_file_load (file, NULL, NULL)) { - /* the file is no longer present */ + /* destroy the file if we cannot query any file information */ thunar_file_destroy (file); + return; } - else - { - /* apply the new info... */ - thunar_vfs_info_unref (file->info); - file->info = info; - /* ... and tell others */ - thunar_file_changed (file); - } + /* ... and tell others */ + thunar_file_changed (file); + } @@ -1928,8 +3021,8 @@ thunar_file_compare_by_name (const ThunarFile *file_a, #endif /* we compare only the display names (UTF-8!) */ - ap = file_a->info->display_name; - bp = file_b->info->display_name; + ap = thunar_file_get_display_name (file_a); + bp = thunar_file_get_display_name (file_b); /* check if we should ignore case */ if (G_LIKELY (case_sensitive)) @@ -1999,7 +3092,8 @@ thunar_file_compare_by_name (const ThunarFile *file_a, /* a second case is '20 file' and '2file', where comparison by number * makes sense, if the previous char for both strings is a digit. */ - if (ap > file_a->info->display_name && bp > file_b->info->display_name + if (ap > thunar_file_get_display_name (file_a) + && bp > thunar_file_get_display_name (file_b) && g_ascii_isdigit (*(ap - 1)) && g_ascii_isdigit (*(bp - 1))) { return compare_by_name_using_number (ap - 1, bp - 1); @@ -2052,30 +3146,72 @@ thunar_file_compare_by_name (const ThunarFile *file_a, +gboolean +thunar_file_same_filesystem (const ThunarFile *file_a, + const ThunarFile *file_b) +{ + const gchar *filesystem_id_a; + const gchar *filesystem_id_b; + + _thunar_return_val_if_fail (THUNAR_IS_FILE (file_a), FALSE); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file_b), FALSE); + + /* return false if we have no information about one of the files */ + if (file_a->info == NULL || file_b->info == NULL) + return FALSE; + + /* determine the filesystem IDs */ + filesystem_id_a = g_file_info_get_attribute_string (file_a->info, + G_FILE_ATTRIBUTE_ID_FILESYSTEM); + + filesystem_id_b = g_file_info_get_attribute_string (file_b->info, + G_FILE_ATTRIBUTE_ID_FILESYSTEM); + + /* compare the filesystem IDs */ + return exo_str_is_equal (filesystem_id_a, filesystem_id_b); +} + + + /** * thunar_file_cache_lookup: - * @path : a #ThunarVfsPath. + * @file : a #GFile. * - * Looks up the #ThunarFile for @path in the internal file - * cache and returns the file present for @path in the - * cache or %NULL if no #ThunarFile is cached for @path. + * Looks up the #ThunarFile for @file in the internal file + * cache and returns the file present for @file in the + * cache or %NULL if no #ThunarFile is cached for @file. * * Note that no reference is taken for the caller. * * This method should not be used but in very rare cases. - * Consider using thunar_file_get_for_path() instead. + * Consider using thunar_file_get() instead. * - * Return value: the #ThunarFile for @path in the internal + * Return value: the #ThunarFile for @file in the internal * cache, or %NULL. **/ -ThunarFile* -thunar_file_cache_lookup (const ThunarVfsPath *path) +ThunarFile * +thunar_file_cache_lookup (const GFile *file) { + ThunarFile *cached_file; + + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); + + G_LOCK (file_cache_mutex); + /* allocate the ThunarFile cache on-demand */ if (G_UNLIKELY (file_cache == NULL)) - file_cache = g_hash_table_new_full (thunar_vfs_path_hash, thunar_vfs_path_equal, (GDestroyNotify) thunar_vfs_path_unref, NULL); + { + file_cache = g_hash_table_new_full (g_file_hash, + (GEqualFunc) g_file_equal, + (GDestroyNotify) g_object_unref, + NULL); + } - return g_hash_table_lookup (file_cache, path); + cached_file = g_hash_table_lookup (file_cache, file); + + G_UNLOCK (file_cache_mutex); + + return cached_file; } @@ -2084,42 +3220,44 @@ thunar_file_cache_lookup (const ThunarVfsPath *path) * thunar_file_list_get_applications: * @file_list : a #GList of #ThunarFile<!---->s. * - * Returns the #GList of #ThunarVfsMimeApplication<!---->s - * that can be used to open all #ThunarFile<!---->s in the - * given @file_list. + * Returns the #GList of #GAppInfo<!---->s that can be used to open + * all #ThunarFile<!---->s in the given @file_list. * - * The caller is responsible to free the returned list using - * something like: + * The caller is responsible to free the returned list using something like: * <informalexample><programlisting> - * g_list_foreach (list, (GFunc) thunar_vfs_mime_application_unref, NULL); + * g_list_foreach (list, (GFunc) g_object_unref, NULL); * g_list_free (list); * </programlisting></informalexample> * - * Return value: the list of #ThunarVfsMimeApplication<!---->s that - * can be used to open all items in the @file_list. + * Return value: the list of #GAppInfo<!---->s that can be used to open all + * items in the @file_list. **/ GList* thunar_file_list_get_applications (GList *file_list) { - ThunarVfsMimeDatabase *database; - GList *applications = NULL; - GList *list; - GList *next; - GList *ap; - GList *lp; - - /* grab a reference on the mime database */ - database = thunar_vfs_mime_database_get_default (); + GList *applications = NULL; + GList *list; + GList *next; + GList *ap; + GList *lp; + const gchar *previous_type; + const gchar *current_type; /* determine the set of applications that can open all files */ for (lp = file_list; lp != NULL; lp = lp->next) { + current_type = thunar_file_get_content_type (lp->data); + /* no need to check anything if this file has the same mime type as the previous file */ - if (lp->prev != NULL && thunar_file_get_mime_info (lp->prev->data) == thunar_file_get_mime_info (lp->data)) - continue; + if (current_type != NULL && lp->prev != NULL) + { + previous_type = thunar_file_get_content_type (lp->prev->data); + if (G_LIKELY (g_content_type_equals (previous_type, current_type))) + continue; + } /* determine the list of applications that can open this file */ - list = thunar_vfs_mime_database_get_applications (database, thunar_file_get_mime_info (lp->data)); + list = current_type == NULL ? NULL : g_app_info_get_all_for_type (current_type); if (G_UNLIKELY (applications == NULL)) { /* first file, so just use the applications list */ @@ -2154,37 +3292,31 @@ thunar_file_list_get_applications (GList *file_list) break; } - /* release the mime database */ - g_object_unref (G_OBJECT (database)); - return applications; } /** - * thunar_file_list_to_path_list: + * thunar_file_list_to_thunar_g_file_list: * @file_list : a #GList of #ThunarFile<!---->s. * - * Transforms the @file_list to a #GList of #ThunarVfsPath<!---->s for + * Transforms the @file_list to a #GList of #GFile<!---->s for * the #ThunarFile<!---->s contained within @file_list. * * The caller is responsible to free the returned list using - * thunar_vfs_path_list_free() when no longer needed. + * thunar_g_file_list_free() when no longer needed. * - * Return value: the list of #ThunarVfsPath<!---->s for @file_list. + * Return value: the list of #GFile<!---->s for @file_list. **/ GList* -thunar_file_list_to_path_list (GList *file_list) +thunar_file_list_to_thunar_g_file_list (GList *file_list) { - GList *path_list = NULL; + GList *list = NULL; GList *lp; for (lp = g_list_last (file_list); lp != NULL; lp = lp->prev) - path_list = g_list_prepend (path_list, thunar_vfs_path_ref (THUNAR_FILE (lp->data)->info->path)); + list = g_list_prepend (list, g_object_ref (THUNAR_FILE (lp->data)->gfile)); - return path_list; + return list; } - - - diff --git a/thunar/thunar-file.h b/thunar/thunar-file.h index 14b86c57c..683b88877 100644 --- a/thunar/thunar-file.h +++ b/thunar/thunar-file.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -20,11 +21,14 @@ #ifndef __THUNAR_FILE_H__ #define __THUNAR_FILE_H__ -#include <thunar/thunar-enum-types.h> -#include <thunar/thunar-metafile.h> +#include <glib.h> + #include <thunarx/thunarx.h> -#include <glib.h> +#include <thunar/thunar-enum-types.h> +#include <thunar/thunar-gio-extensions.h> +#include <thunar/thunar-metafile.h> +#include <thunar/thunar-user.h> G_BEGIN_DECLS; @@ -105,21 +109,33 @@ struct _ThunarFileClass struct _ThunarFile { - GObject __parent__; + GObject __parent__; /*< private >*/ - ThunarVfsInfo *info; - guint flags; + GFileMonitor *monitor; + GFileInfo *info; + GFileInfo *filesystem_info; + GFile *gfile; + gchar *custom_icon_name; + gchar *display_name; + gchar *basename; + gchar *thumbnail_path; + guint flags; + guint is_thumbnail : 1; + guint is_mounted : 1; }; GType thunar_file_get_type (void) G_GNUC_CONST; -ThunarFile *thunar_file_get_for_info (ThunarVfsInfo *info); -ThunarFile *thunar_file_get_for_path (ThunarVfsPath *path, +ThunarFile *thunar_file_get (GFile *file, GError **error); ThunarFile *thunar_file_get_for_uri (const gchar *uri, GError **error); +gboolean thunar_file_load (ThunarFile *file, + GCancellable *cancellable, + GError **error); + ThunarFile *thunar_file_get_parent (const ThunarFile *file, GError **error); @@ -130,10 +146,13 @@ gboolean thunar_file_execute (ThunarFile *file gboolean thunar_file_launch (ThunarFile *file, gpointer parent, + const gchar *startup_id, GError **error); gboolean thunar_file_rename (ThunarFile *file, const gchar *name, + GCancellable *cancellable, + gboolean called_from_job, GError **error); GdkDragAction thunar_file_accepts_drop (ThunarFile *file, @@ -143,7 +162,7 @@ GdkDragAction thunar_file_accepts_drop (ThunarFile *file const gchar *thunar_file_get_display_name (const ThunarFile *file); -ThunarVfsFileTime thunar_file_get_date (const ThunarFile *file, +guint64 thunar_file_get_date (const ThunarFile *file, ThunarFileDateType date_type); gchar *thunar_file_get_date_string (const ThunarFile *file, @@ -152,28 +171,61 @@ gchar *thunar_file_get_date_string (const ThunarFile *file gchar *thunar_file_get_mode_string (const ThunarFile *file) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; gchar *thunar_file_get_size_string (const ThunarFile *file) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -ThunarVfsVolume *thunar_file_get_volume (const ThunarFile *file, - ThunarVfsVolumeManager *volume_manager); - -ThunarVfsGroup *thunar_file_get_group (const ThunarFile *file); -ThunarVfsUser *thunar_file_get_user (const ThunarFile *file); +GVolume *thunar_file_get_volume (const ThunarFile *file); + +ThunarGroup *thunar_file_get_group (const ThunarFile *file); +ThunarUser *thunar_file_get_user (const ThunarFile *file); + +const gchar *thunar_file_get_content_type (const ThunarFile *file); +const gchar *thunar_file_get_symlink_target (const ThunarFile *file); +const gchar *thunar_file_get_basename (const ThunarFile *file); +gboolean thunar_file_is_symlink (const ThunarFile *file); +guint64 thunar_file_get_size (const ThunarFile *file); +GAppInfo *thunar_file_get_default_handler (const ThunarFile *file); +GFileType thunar_file_get_kind (const ThunarFile *file); +GFile *thunar_file_get_target_location (const ThunarFile *file); +ThunarFileMode thunar_file_get_mode (const ThunarFile *file); +gboolean thunar_file_get_free_space (const ThunarFile *file, + guint64 *free_space_return); +gboolean thunar_file_is_mounted (const ThunarFile *file); +gboolean thunar_file_exists (const ThunarFile *file); +gboolean thunar_file_is_directory (const ThunarFile *file); +gboolean thunar_file_is_local (const ThunarFile *file); +gboolean thunar_file_is_ancestor (const ThunarFile *file, + const ThunarFile *ancestor); +gboolean thunar_file_is_executable (const ThunarFile *file); +gboolean thunar_file_is_readable (const ThunarFile *file); +gboolean thunar_file_is_writable (const ThunarFile *file); +gboolean thunar_file_is_hidden (const ThunarFile *file); +gboolean thunar_file_is_home (const ThunarFile *file); +gboolean thunar_file_is_regular (const ThunarFile *file); +gboolean thunar_file_is_trashed (const ThunarFile *file); +gboolean thunar_file_is_desktop_file (const ThunarFile *file); +const gchar *thunar_file_get_display_name (const ThunarFile *file); gchar *thunar_file_get_deletion_date (const ThunarFile *file, ThunarDateStyle date_style) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -gchar *thunar_file_get_original_path (const ThunarFile *file) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +const gchar *thunar_file_get_original_path (const ThunarFile *file); gboolean thunar_file_is_chmodable (const ThunarFile *file); gboolean thunar_file_is_renameable (const ThunarFile *file); +gboolean thunar_file_can_be_trashed (const ThunarFile *file); GList *thunar_file_get_emblem_names (ThunarFile *file); void thunar_file_set_emblem_names (ThunarFile *file, GList *emblem_names); +gchar *thunar_file_get_custom_icon (const ThunarFile *file); gboolean thunar_file_set_custom_icon (ThunarFile *file, const gchar *custom_icon, - GError **error) G_GNUC_WARN_UNUSED_RESULT; - -const gchar *thunar_file_get_icon_name (const ThunarFile *file, + GError **error); + +const gchar *thunar_file_get_thumbnail_path (const ThunarFile *file); +gboolean thunar_file_is_thumbnail (const ThunarFile *file); +void thunar_file_set_thumb_state (ThunarFile *file, + ThunarFileThumbState state); +GIcon *thunar_file_get_preview_icon (const ThunarFile *file); +gchar *thunar_file_get_icon_name (const ThunarFile *file, ThunarFileIconState icon_state, GtkIconTheme *icon_theme); @@ -197,15 +249,27 @@ gint thunar_file_compare_by_name (const ThunarFile *file const ThunarFile *file_b, gboolean case_sensitive); +gboolean thunar_file_same_filesystem (const ThunarFile *file_a, + const ThunarFile *file_b); -ThunarFile *thunar_file_cache_lookup (const ThunarVfsPath *path); +ThunarFile *thunar_file_cache_lookup (const GFile *file); GList *thunar_file_list_get_applications (GList *file_list); -GList *thunar_file_list_to_path_list (GList *file_list); +GList *thunar_file_list_to_thunar_g_file_list (GList *file_list); gboolean thunar_file_is_desktop (const ThunarFile *file); +/** + * thunar_file_is_root: + * @file : a #ThunarFile. + * + * Checks whether @file refers to the root directory. + * + * Return value: %TRUE if @file is the root directory. + **/ +#define thunar_file_is_root(file) (thunar_g_file_is_root (THUNAR_FILE ((file))->gfile)) + /** * thunar_file_has_parent: * @file : a #ThunarFile instance. @@ -215,99 +279,35 @@ gboolean thunar_file_is_desktop (const ThunarFile *file); * * Return value: whether @file has a parent. **/ -#define thunar_file_has_parent(file) (!thunar_vfs_path_is_root (THUNAR_FILE ((file))->info->path)) +#define thunar_file_has_parent(file) (!thunar_file_is_root (THUNAR_FILE ((file)))) /** * thunar_file_get_info: * @file : a #ThunarFile instance. * - * Returns the #ThunarVfsInfo for @file. + * Returns the #GFileInfo for @file. * * Note, that there's no reference taken for the caller on the - * returned #ThunarVfsInfo, so if you need the object for a longer + * returned #GFileInfo, so if you need the object for a longer * perioud, you'll need to take a reference yourself using the - * thunar_vfs_info_ref() method. + * g_object_ref() method. * - * Return value: the #ThunarVfsInfo for @file. + * Return value: the #GFileInfo for @file. **/ #define thunar_file_get_info(file) (THUNAR_FILE ((file))->info) /** - * thunar_file_get_path: - * @file : a #ThunarFile instance. - * - * Returns the #ThunarVfsPath, that refers to the location of the @file. - * - * Note, that there's no reference taken for the caller on the - * returned #ThunarVfsPath, so if you need the object for a longer - * period, you'll need to take a reference yourself using the - * thunar_vfs_path_ref() function. - * - * Return value: the path to the @file. - **/ -#define thunar_file_get_path(file) (THUNAR_FILE ((file))->info->path) - -/** - * thunar_file_get_mime_info: - * @file : a #ThunarFile instance. - * - * Returns the MIME type information for the given @file object. This - * function is garantied to always return a valid #ThunarVfsMimeInfo. - * - * Note, that there's no reference taken for the caller on the - * returned #ThunarVfsMimeInfo, so if you need the object for a - * longer period, you'll need to take a reference yourself using - * the thunar_vfs_mime_info_ref() function. - * - * Return value: the MIME type. - **/ -#define thunar_file_get_mime_info(file) (THUNAR_FILE ((file))->info->mime_info) - -/** - * thunar_file_get_kind: - * @file : a #ThunarFile instance. - * - * Returns the kind of @file. - * - * Return value: the kind of @file. - **/ -#define thunar_file_get_kind(file) (THUNAR_FILE ((file))->info->type) - -/** - * thunar_file_get_mode: + * thunar_file_get_file: * @file : a #ThunarFile instance. * - * Returns the permission bits of @file. + * Returns the #GFile that refers to the location of @file. * - * Return value: the permission bits of @file. + * The returned #GFile is owned by @file and must not be released + * with g_object_unref(). + * + * Return value: the #GFile corresponding to @file. **/ -#define thunar_file_get_mode(file) (THUNAR_FILE ((file))->info->mode) - -/** - * thunar_file_get_size: - * @file : a #ThunarFile instance. - * - * Tries to determine the size of @file in bytes and - * returns the size. - * - * Return value: the size of @file in bytes. - **/ -#define thunar_file_get_size(file) (THUNAR_FILE ((file))->info->size) - -/** - * thunar_file_get_free_space: - * @file : a #ThunarFile instance. - * @free_space_return : return location for the amount of - * free space or %NULL. - * - * Determines the amount of free space of the volume on - * which @file resides. Returns %TRUE if the amount of - * free space was determined successfully and placed into - * @free_space_return, else %FALSE will be returned. - * - * Return value: %TRUE if successfull, else %FALSE. - **/ -#define thunar_file_get_free_space(file, free_space_return) (thunar_vfs_info_get_free_space (THUNAR_FILE ((file))->info, (free_space_return))) +#define thunar_file_get_file(file) (THUNAR_FILE ((file))->gfile) /** * thunar_file_dup_uri: @@ -318,25 +318,7 @@ gboolean thunar_file_is_desktop (const ThunarFile *file); * * Return value: the URI for @file. **/ -#define thunar_file_dup_uri(file) (thunar_vfs_path_dup_uri (thunar_file_get_path ((file)))) - - -/** - * thunar_file_get_custom_icon: - * @file : a #ThunarFile instance. - * - * Queries the custom icon from @file if any, - * else %NULL is returned. The custom icon - * can be either a themed icon name or an - * absolute path to an icon file in the local - * file system. - * - * Return value: the custom icon for @file - * or %NULL. - **/ -#define thunar_file_get_custom_icon(file) (thunar_vfs_info_get_custom_icon (THUNAR_FILE ((file))->info)) - - +#define thunar_file_dup_uri(file) (g_file_get_uri (THUNAR_FILE ((file))->gfile)) /** * thunar_file_changed: @@ -350,174 +332,6 @@ G_STMT_START{ \ thunarx_file_info_changed (THUNARX_FILE_INFO ((file))); \ }G_STMT_END - - -/** - * thunar_file_is_local: - * @file : a #ThunarFile instance. - * - * Returns %TRUE if @file is a local file with the - * %THUNAR_VFS_PATH_SCHEME_FILE scheme. - * - * Return value: %TRUE if @file is local. - **/ -#define thunar_file_is_local(file) (thunar_vfs_path_get_scheme (thunar_file_get_path ((file))) == THUNAR_VFS_PATH_SCHEME_FILE) - -/** - * thunar_file_is_trashed: - * @file : a #ThunarFile instance. - * - * Returns %TRUE if @file is a local file with the - * %THUNAR_VFS_PATH_SCHEME_TRASH scheme. - * - * Return value: %TRUE if @file is in the trash, or - * the trash folder itself. - **/ -#define thunar_file_is_trashed(file) (thunar_vfs_path_get_scheme (thunar_file_get_path ((file))) == THUNAR_VFS_PATH_SCHEME_TRASH) - -/** - * thunar_file_is_ancestor: - * @file : a #ThunarFile instance. - * @ancestor : another #ThunarFile instance. - * - * Determines whether @file is somewhere inside @ancestor, - * possibly with intermediate folders. - * - * Return value: %TRUE if @ancestor contains @file as a - * child, grandchild, great grandchild, etc. - **/ -#define thunar_file_is_ancestor(file, ancestor) (thunar_vfs_path_is_ancestor (thunar_file_get_path ((file)), thunar_file_get_path ((ancestor)))) - -/** - * thunar_file_is_directory: - * @file : a #ThunarFile instance. - * - * Checks whether @file refers to a directory. - * - * Return value: %TRUE if @file is a directory. - **/ -#define thunar_file_is_directory(file) (THUNAR_FILE ((file))->info->type == THUNAR_VFS_FILE_TYPE_DIRECTORY) - -/** - * thunar_file_is_executable: - * @file : a #ThunarFile instance. - * - * Determines whether the owner of the current process is allowed - * to execute the @file (or enter the directory refered to by - * @file). - * - * Return value: %TRUE if @file can be executed. - **/ -#define thunar_file_is_executable(file) (THUNAR_FILE ((file))->info->flags & THUNAR_VFS_FILE_FLAGS_EXECUTABLE) - -/** - * thunar_file_is_readable: - * @file : a #ThunarFile instance. - * - * Determines whether the owner of the current process is allowed - * to read the @file. - * - * Return value: %TRUE if @file can be read. - **/ -#define thunar_file_is_readable(file) (THUNAR_FILE ((file))->info->flags & THUNAR_VFS_FILE_FLAGS_READABLE) - -/** - * thunar_file_is_writable: - * @file : a #ThunarFile instance. - * - * Determines whether the owner of the current process is allowed - * to write the @file. - * - * Return value: %TRUE if @file can be read. - **/ -#define thunar_file_is_writable(file) (THUNAR_FILE ((file))->info->flags & THUNAR_VFS_FILE_FLAGS_WRITABLE) - -/** - * thunar_file_is_hidden: - * @file : a #ThunarFile instance. - * - * Checks whether @file can be considered a hidden file. - * - * Return value: %TRUE if @file is a hidden file, else %FALSE. - **/ -#define thunar_file_is_hidden(file) ((THUNAR_FILE ((file))->info->flags & THUNAR_VFS_FILE_FLAGS_HIDDEN) != 0) - -/** - * thunar_file_is_home: - * @file : a #ThunarFile. - * - * Checks whether @file refers to the users home directory. - * - * Return value: %TRUE if @file is the users home directory. - **/ -#define thunar_file_is_home(file) (thunar_vfs_path_is_home (THUNAR_FILE ((file))->info->path)) - -/** - * thunar_file_is_regular: - * @file : a #ThunarFile. - * - * Checks whether @file refers to a regular file. - * - * Return value: %TRUE if @file is a regular file. - **/ -#define thunar_file_is_regular(file) (THUNAR_FILE ((file))->info->type == THUNAR_VFS_FILE_TYPE_REGULAR) - -/** - * thunar_file_is_root: - * @file : a #ThunarFile. - * - * Checks whether @file refers to the root directory. - * - * Return value: %TRUE if @file is the root directory. - **/ -#define thunar_file_is_root(file) (thunar_vfs_path_is_root (THUNAR_FILE ((file))->info->path)) - -/** - * thunar_file_is_symlink: - * @file : a #ThunarFile. - * - * Returns %TRUE if @file is a symbolic link. - * - * Return value: %TRUE if @file is a symbolic link. - **/ -#define thunar_file_is_symlink(file) ((THUNAR_FILE ((file))->info->flags & THUNAR_VFS_FILE_FLAGS_SYMLINK) != 0) - -/** - * thunar_file_is_desktop_file: - * @file : a #ThunarFile. - * - * Returns %TRUE if @file is a .desktop file, but not a .directory file. - * - * Return value: %TRUE if @file is a .desktop file. - **/ -#define thunar_file_is_desktop_file(file) (exo_str_is_equal (thunar_vfs_mime_info_get_name (thunar_file_get_mime_info ((file))), "application/x-desktop") \ - && !exo_str_is_equal (thunar_vfs_path_get_name (thunar_file_get_path ((file))), ".directory")) - -/** - * thunar_file_get_display_name: - * @file : a #ThunarFile instance. - * - * Returns the @file name in the UTF-8 encoding, which is - * suitable for displaying the file name in the GUI. - * - * Return value: the @file name suitable for display. - **/ -#define thunar_file_get_display_name(file) (THUNAR_FILE ((file))->info->display_name) - -/** - * thunar_file_read_link: - * @file : a #ThunarFile instance. - * @error : return location for errors or %NULL. - * - * Simple wrapper to thunar_vfs_info_read_link(). - * - * Return value: the link target of @file or %NULL - * if an error occurred. - **/ -#define thunar_file_read_link(file, error) (thunar_vfs_info_read_link (THUNAR_FILE ((file))->info, (error))) - - - /** * thunar_file_get_thumb_state: * @file : a #ThunarFile. @@ -529,23 +343,6 @@ G_STMT_START{ \ **/ #define thunar_file_get_thumb_state(file) (THUNAR_FILE ((file))->flags & THUNAR_FILE_THUMB_STATE_MASK) -/** - * thunar_file_set_thumb_state: - * @file : a #ThunarFile. - * @thumb_state : the new #ThunarFileThumbState. - * - * Sets the #ThunarFileThumbState for @file - * to @thumb_state. This method is intended - * to be used by #ThunarIconFactory only. - **/ -#define thunar_file_set_thumb_state(file, thumb_state) \ -G_STMT_START{ \ - ThunarFile *f = THUNAR_FILE ((file)); \ - f->flags = (f->flags & ~THUNAR_FILE_THUMB_STATE_MASK) | (thumb_state); \ -}G_STMT_END - - - /** * thunar_file_list_copy: * @file_list : a list of #ThunarFile<!---->s. diff --git a/thunar/thunar-folder.c b/thunar/thunar-folder.c index 4b6b956bc..fef3b2397 100644 --- a/thunar/thunar-folder.c +++ b/thunar/thunar-folder.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -24,6 +25,8 @@ #include <thunar/thunar-file-monitor.h> #include <thunar/thunar-folder.h> #include <thunar/thunar-gobject-extensions.h> +#include <thunar/thunar-io-jobs.h> +#include <thunar/thunar-job.h> #include <thunar/thunar-private.h> @@ -32,6 +35,7 @@ enum { PROP_0, + PROP_CORRESPONDING_FILE, PROP_LOADING, }; @@ -53,13 +57,17 @@ static void thunar_folder_get_property (GObject guint prop_id, GValue *value, GParamSpec *pspec); -static void thunar_folder_error (ThunarVfsJob *job, +static void thunar_folder_set_property (GObject *object, + guint prop_uid, + const GValue *value, + GParamSpec *pspec); +static void thunar_folder_error (ExoJob *job, GError *error, ThunarFolder *folder); -static gboolean thunar_folder_infos_ready (ThunarVfsJob *job, - GList *infos, +static gboolean thunar_folder_files_ready (ThunarJob *job, + GList *files, ThunarFolder *folder); -static void thunar_folder_finished (ThunarVfsJob *job, +static void thunar_folder_finished (ExoJob *job, ThunarFolder *folder); static void thunar_folder_file_changed (ThunarFileMonitor *file_monitor, ThunarFile *file, @@ -67,11 +75,10 @@ static void thunar_folder_file_changed (ThunarFileMonitor static void thunar_folder_file_destroyed (ThunarFileMonitor *file_monitor, ThunarFile *file, ThunarFolder *folder); -static void thunar_folder_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, +static void thunar_folder_monitor (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, gpointer user_data); @@ -93,16 +100,15 @@ struct _ThunarFolder { GtkObject __parent__; - ThunarVfsJob *job; + ThunarJob *job; - ThunarFile *corresponding_file; - GList *new_files; - GList *files; + ThunarFile *corresponding_file; + GList *new_files; + GList *files; - ThunarFileMonitor *file_monitor; + ThunarFileMonitor *file_monitor; - ThunarVfsMonitor *monitor; - ThunarVfsMonitorHandle *handle; + GFileMonitor *monitor; }; @@ -153,6 +159,22 @@ thunar_folder_class_init (ThunarFolderClass *klass) gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = thunar_folder_finalize; gobject_class->get_property = thunar_folder_get_property; + gobject_class->set_property = thunar_folder_set_property; + + /** + * ThunarFolder::corresponding-file: + * + * The #ThunarFile referring to the #ThunarFolder. + **/ + g_object_class_install_property (gobject_class, + PROP_CORRESPONDING_FILE, + g_param_spec_object ("corresponding-file", + "corresponding-file", + "corresponding-file", + THUNAR_TYPE_FILE, + G_PARAM_READABLE + | G_PARAM_WRITABLE + | G_PARAM_CONSTRUCT_ONLY)); /** * ThunarFolder::loading: @@ -228,8 +250,7 @@ thunar_folder_init (ThunarFolder *folder) g_signal_connect (G_OBJECT (folder->file_monitor), "file-changed", G_CALLBACK (thunar_folder_file_changed), folder); g_signal_connect (G_OBJECT (folder->file_monitor), "file-destroyed", G_CALLBACK (thunar_folder_file_destroyed), folder); - /* connect to the file alteration monitor */ - folder->monitor = thunar_vfs_monitor_get_default (); + folder->monitor = NULL; } @@ -240,20 +261,22 @@ thunar_folder_finalize (GObject *object) ThunarFolder *folder = THUNAR_FOLDER (object); /* disconnect from the ThunarFileMonitor instance */ - g_signal_handlers_disconnect_matched (G_OBJECT (folder->file_monitor), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, folder); - g_object_unref (G_OBJECT (folder->file_monitor)); + g_signal_handlers_disconnect_matched (folder->file_monitor, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, folder); + g_object_unref (folder->file_monitor); /* disconnect from the file alteration monitor */ - if (G_LIKELY (folder->handle != NULL)) - thunar_vfs_monitor_remove (folder->monitor, folder->handle); - g_object_unref (G_OBJECT (folder->monitor)); + if (G_LIKELY (folder->monitor != NULL)) + { + g_file_monitor_cancel (folder->monitor); + g_object_unref (folder->monitor); + } /* cancel the pending job (if any) */ if (G_UNLIKELY (folder->job != NULL)) { g_signal_handlers_disconnect_matched (folder->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, folder); - thunar_vfs_job_cancel (folder->job); - g_object_unref (G_OBJECT (folder->job)); + g_object_unref (folder->job); + folder->job = NULL; } /* disconnect from the corresponding file */ @@ -285,6 +308,10 @@ thunar_folder_get_property (GObject *object, switch (prop_id) { + case PROP_CORRESPONDING_FILE: + g_value_set_object (value, folder->corresponding_file); + break; + case PROP_LOADING: g_value_set_boolean (value, thunar_folder_get_loading (folder)); break; @@ -298,13 +325,38 @@ thunar_folder_get_property (GObject *object, static void -thunar_folder_error (ThunarVfsJob *job, +thunar_folder_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ThunarFolder *folder = THUNAR_FOLDER (object); + + switch (prop_id) + { + case PROP_CORRESPONDING_FILE: + folder->corresponding_file = g_value_dup_object (value); + break; + + case PROP_LOADING: + _thunar_assert_not_reached (); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + + +static void +thunar_folder_error (ExoJob *job, GError *error, ThunarFolder *folder) { _thunar_return_if_fail (THUNAR_IS_FOLDER (folder)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_return_if_fail (folder->job == job); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); /* tell the consumer about the problem */ g_signal_emit (G_OBJECT (folder), folder_signals[ERROR], 0, error); @@ -313,42 +365,25 @@ thunar_folder_error (ThunarVfsJob *job, static gboolean -thunar_folder_infos_ready (ThunarVfsJob *job, - GList *infos, +thunar_folder_files_ready (ThunarJob *job, + GList *files, ThunarFolder *folder) { - ThunarFile *file; - GList *lp; - _thunar_return_val_if_fail (THUNAR_IS_FOLDER (folder), FALSE); - _thunar_return_val_if_fail (THUNAR_VFS_IS_JOB (job), FALSE); - _thunar_return_val_if_fail (folder->handle == NULL, FALSE); - _thunar_return_val_if_fail (folder->job == job, FALSE); - - /* turn the info list into a file list */ - for (lp = infos; lp != NULL; lp = lp->next) - { - /* get the file corresponding to the info... */ - file = thunar_file_get_for_info (lp->data); - - /* ...release the info at the list position... */ - thunar_vfs_info_unref (lp->data); - - /* ...and replace it with the file */ - lp->data = file; - } + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (folder->monitor == NULL, FALSE); /* merge the list with the existing list of new files */ - folder->new_files = g_list_concat (folder->new_files, infos); + folder->new_files = g_list_concat (folder->new_files, files); - /* TRUE to indicate that we took over ownership of the infos list */ + /* indicate that we took over ownership of the file list */ return TRUE; } static void -thunar_folder_finished (ThunarVfsJob *job, +thunar_folder_finished (ExoJob *job, ThunarFolder *folder) { ThunarFile *file; @@ -356,10 +391,9 @@ thunar_folder_finished (ThunarVfsJob *job, GList *lp; _thunar_return_if_fail (THUNAR_IS_FOLDER (folder)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); _thunar_return_if_fail (THUNAR_IS_FILE (folder->corresponding_file)); - _thunar_return_if_fail (folder->handle == NULL); - _thunar_return_if_fail (folder->job == job); + _thunar_return_if_fail (folder->monitor == NULL); /* check if we need to merge new files with existing files */ if (G_UNLIKELY (folder->files != NULL)) @@ -426,18 +460,23 @@ thunar_folder_finished (ThunarVfsJob *job, folder->files = folder->new_files; folder->new_files = NULL; - /* emit a "files-added" signal for the new files */ - g_signal_emit (G_OBJECT (folder), folder_signals[FILES_ADDED], 0, folder->files); + if (folder->files != NULL) + { + /* emit a "files-added" signal for the new files */ + g_signal_emit (G_OBJECT (folder), folder_signals[FILES_ADDED], 0, folder->files); + } } /* we did it, the folder is loaded */ g_signal_handlers_disconnect_matched (folder->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, folder); - g_object_unref (G_OBJECT (folder->job)); + g_object_unref (folder->job); folder->job = NULL; /* add us to the file alteration monitor */ - folder->handle = thunar_vfs_monitor_add_directory (folder->monitor, thunar_file_get_path (folder->corresponding_file), - thunar_folder_monitor, folder); + folder->monitor = g_file_monitor_directory (thunar_file_get_file (folder->corresponding_file), + G_FILE_MONITOR_NONE, NULL, NULL); + if (G_LIKELY (folder->monitor != NULL)) + g_signal_connect (folder->monitor, "changed", G_CALLBACK (thunar_folder_monitor), folder); /* tell the consumers that we have loaded the directory */ g_object_notify (G_OBJECT (folder), "loading"); @@ -504,37 +543,35 @@ thunar_folder_file_destroyed (ThunarFileMonitor *file_monitor, static void -thunar_folder_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data) +thunar_folder_monitor (GFileMonitor *monitor, + GFile *event_file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) { ThunarFolder *folder = THUNAR_FOLDER (user_data); ThunarFile *file; GList *lp; GList list; - _thunar_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); + _thunar_return_if_fail (G_IS_FILE_MONITOR (monitor)); _thunar_return_if_fail (THUNAR_IS_FOLDER (folder)); _thunar_return_if_fail (folder->monitor == monitor); - _thunar_return_if_fail (folder->handle == handle); _thunar_return_if_fail (folder->job == NULL); /* check on which file the event occurred */ - if (!thunar_vfs_path_equal (event_path, thunar_file_get_path (folder->corresponding_file))) + if (!g_file_equal (event_file, thunar_file_get_file (folder->corresponding_file))) { /* check if we already ship the file */ for (lp = folder->files; lp != NULL; lp = lp->next) - if (thunar_vfs_path_equal (event_path, thunar_file_get_path (lp->data))) + if (g_file_equal (event_file, thunar_file_get_file (lp->data))) break; /* if we don't have it, add it if the event is not an "deleted" event */ - if (G_UNLIKELY (lp == NULL && event != THUNAR_VFS_MONITOR_EVENT_DELETED)) + if (G_UNLIKELY (lp == NULL && event_type != G_FILE_MONITOR_EVENT_DELETED)) { /* allocate a file for the path */ - file = thunar_file_get_for_path (event_path, NULL); + file = thunar_file_get (event_file, NULL); if (G_UNLIKELY (file == NULL)) return; @@ -548,7 +585,7 @@ thunar_folder_monitor (ThunarVfsMonitor *monitor, else if (lp != NULL) { /* update/destroy the file */ - if (event == THUNAR_VFS_MONITOR_EVENT_DELETED) + if (event_type == G_FILE_MONITOR_EVENT_DELETED) thunar_file_destroy (lp->data); else thunar_file_reload (lp->data); @@ -557,7 +594,7 @@ thunar_folder_monitor (ThunarVfsMonitor *monitor, else { /* update/destroy the corresponding file */ - if (event == THUNAR_VFS_MONITOR_EVENT_DELETED) + if (event_type == G_FILE_MONITOR_EVENT_DELETED) thunar_file_destroy (folder->corresponding_file); else thunar_file_reload (folder->corresponding_file); @@ -601,9 +638,7 @@ thunar_folder_get_for_file (ThunarFile *file) else { /* allocate the new instance */ - folder = g_object_new (THUNAR_TYPE_FOLDER, NULL); - folder->corresponding_file = file; - g_object_ref (G_OBJECT (file)); + folder = g_object_new (THUNAR_TYPE_FOLDER, "corresponding-file", file, NULL); /* drop the floating reference */ g_object_ref_sink (G_OBJECT (folder)); @@ -694,15 +729,16 @@ thunar_folder_reload (ThunarFolder *folder) { /* disconnect from the job */ g_signal_handlers_disconnect_matched (folder->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, folder); - thunar_vfs_job_cancel (THUNAR_VFS_JOB (folder->job)); - g_object_unref (G_OBJECT (folder->job)); + g_object_unref (folder->job); + folder->job = NULL; } /* disconnect from the file alteration monitor */ - if (G_UNLIKELY (folder->handle != NULL)) + if (G_UNLIKELY (folder->monitor != NULL)) { - thunar_vfs_monitor_remove (folder->monitor, folder->handle); - folder->handle = NULL; + g_file_monitor_cancel (folder->monitor); + g_object_unref (folder->monitor); + folder->monitor = NULL; } /* reset the new_files list */ @@ -710,10 +746,10 @@ thunar_folder_reload (ThunarFolder *folder) folder->new_files = NULL; /* start a new job */ - folder->job = thunar_vfs_listdir (thunar_file_get_path (folder->corresponding_file), NULL); + folder->job = thunar_io_jobs_list_directory (thunar_file_get_file (folder->corresponding_file)); g_signal_connect (folder->job, "error", G_CALLBACK (thunar_folder_error), folder); g_signal_connect (folder->job, "finished", G_CALLBACK (thunar_folder_finished), folder); - g_signal_connect (folder->job, "infos-ready", G_CALLBACK (thunar_folder_infos_ready), folder); + g_signal_connect (folder->job, "files-ready", G_CALLBACK (thunar_folder_files_ready), folder); /* tell all consumers that we're loading */ g_object_notify (G_OBJECT (folder), "loading"); diff --git a/thunar/thunar-gio-extensions.c b/thunar/thunar-gio-extensions.c new file mode 100644 index 000000000..7b8714a37 --- /dev/null +++ b/thunar/thunar-gio-extensions.c @@ -0,0 +1,446 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 + +#include <gio/gio.h> + +#include <exo/exo.h> +#include <libxfce4util/libxfce4util.h> + +#include <thunar/thunar-gio-extensions.h> +#include <thunar/thunar-private.h> + + + +GFile * +thunar_g_file_new_for_home (void) +{ + return g_file_new_for_path (xfce_get_homedir ()); +} + + + +GFile * +thunar_g_file_new_for_root (void) +{ + return g_file_new_for_uri ("file:///"); +} + + + +GFile * +thunar_g_file_new_for_trash (void) +{ + return g_file_new_for_uri ("trash:///"); +} + + + +GFile * +thunar_g_file_new_for_desktop (void) +{ + return g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)); +} + + + +GFile * +thunar_g_file_new_for_user_special_dir (GUserDirectory dir) +{ + const gchar *path; + + _thunar_return_val_if_fail (dir >= 0 && dir < G_USER_N_DIRECTORIES, NULL); + + path = g_get_user_special_dir (dir); + if (path == NULL) + path = xfce_get_homedir (); + + return g_file_new_for_path (path); +} + + + +gboolean +thunar_g_file_is_root (GFile *file) +{ + GFile *parent; + gboolean is_root = TRUE; + + parent = g_file_get_parent (file); + if (G_UNLIKELY (parent != NULL)) + { + is_root = FALSE; + g_object_unref (parent); + } + + return is_root; +} + + + +gboolean +thunar_g_file_is_trashed (GFile *file) +{ + _thunar_return_val_if_fail (G_IS_FILE (file), FALSE); + return g_file_has_uri_scheme (file, "trash"); +} + + + +gboolean +thunar_g_file_is_desktop (GFile *file) +{ + GFile *desktop; + gboolean is_desktop; + + _thunar_return_val_if_fail (G_IS_FILE (file), FALSE); + + desktop = thunar_g_file_new_for_desktop (); + is_desktop = g_file_equal (desktop, file); + g_object_unref (desktop); + + return is_desktop; +} + + + +GKeyFile * +thunar_g_file_query_key_file (GFile *file, + GCancellable *cancellable, + GError **error) +{ + GKeyFile *key_file; + gchar *contents = NULL; + gsize length; + + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); + _thunar_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); + _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* try to load the entire file into memory */ + if (!g_file_load_contents (file, cancellable, &contents, &length, NULL, error)) + return NULL; + + /* allocate a new key file */ + key_file = g_key_file_new (); + + /* try to parse the key file from the contents of the file */ + if (!g_key_file_load_from_data (key_file, contents, length, + G_KEY_FILE_KEEP_COMMENTS + | G_KEY_FILE_KEEP_TRANSLATIONS, + error)) + { + g_free (contents); + g_key_file_free (key_file); + return NULL; + } + else + { + g_free (contents); + return key_file; + } +} + + + +gboolean +thunar_g_file_write_key_file (GFile *file, + GKeyFile *key_file, + GCancellable *cancellable, + GError **error) +{ + gchar *contents; + gsize length; + + _thunar_return_val_if_fail (G_IS_FILE (file), FALSE); + _thunar_return_val_if_fail (key_file != NULL, FALSE); + _thunar_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* write the key file into the contents buffer */ + contents = g_key_file_to_data (key_file, &length, NULL); + + /* try to replace the file contents with the key file data */ + if (!g_file_replace_contents (file, contents, length, NULL, FALSE, +#if GLIB_CHECK_VERSION(2,20,0) + G_FILE_CREATE_REPLACE_DESTINATION, +#else + G_FILE_CREATE_NONE, +#endif + NULL, cancellable, error)) + { + g_free (contents); + return FALSE; + } + else + { + g_free (contents); + return TRUE; + } +} + + + +gchar * +thunar_g_file_get_location (GFile *file) +{ + gchar *location; + + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); + + location = g_file_get_path (file); + if (location == NULL) + location = g_file_get_uri (file); + + return location; +} + + + +GType +thunar_g_file_list_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + type = g_boxed_type_register_static (I_("ThunarGFileList"), + (GBoxedCopyFunc) thunar_g_file_list_copy, + (GBoxedFreeFunc) thunar_g_file_list_free); + } + + return type; +} + + + +/** + * thunar_g_file_list_new_from_string: + * @string : a string representation of an URI list. + * + * Splits an URI list conforming to the text/uri-list + * mime type defined in RFC 2483 into individual URIs, + * discarding any comments and whitespace. The resulting + * list will hold one #GFile for each URI. + * + * If @string contains no URIs, this function + * will return %NULL. + * + * Return value: the list of #GFile<!---->s or %NULL. + **/ +GList * +thunar_g_file_list_new_from_string (const gchar *string) +{ + GList *list = NULL; + gchar **uris; + gsize n; + + uris = g_uri_list_extract_uris (string); + + for (n = 0; uris != NULL && uris[n] != NULL; ++n) + list = g_list_append (list, g_file_new_for_uri (uris[n])); + + g_strfreev (uris); + + return list; +} + + + +/** + * thunar_g_file_list_to_string: + * @list : a list of #GFile<!---->s. + * + * Free the returned value using g_free() when you + * are done with it. + * + * Return value: the string representation of @list conforming to the + * text/uri-list mime type defined in RFC 2483. + **/ +gchar * +thunar_g_file_list_to_string (GList *list) +{ + GString *string; + gchar *uri; + GList *lp; + + /* allocate initial string */ + string = g_string_new (NULL); + + for (lp = list; lp != NULL; lp = lp->next) + { + uri = g_file_get_uri (lp->data); + string = g_string_append (string, uri); + g_free (uri); + + string = g_string_append (string, "\r\n"); + } + + return g_string_free (string, FALSE); +} + + + +GList * +thunar_g_file_list_append (GList *list, + GFile *file) +{ + return g_list_append (list, g_object_ref (file)); +} + + + +GList * +thunar_g_file_list_prepend (GList *list, + GFile *file) +{ + return g_list_prepend (list, g_object_ref (file)); +} + + + +/** + * thunar_g_file_list_copy: + * @list : a list of #GFile<!---->s. + * + * Takes a deep copy of @list and returns the + * result. The caller is responsible to free the + * returned list using thunar_g_file_list_free(). + * + * Return value: a deep copy of @list. + **/ +GList* +thunar_g_file_list_copy (GList *list) +{ + GList *copy = NULL; + GList *lp; + + for (lp = g_list_last (list); lp != NULL; lp = lp->prev) + copy = g_list_prepend (copy, g_object_ref (lp->data)); + + return copy; +} + + + +/** + * thunar_g_file_list_free: + * @list : a list of #GFile<!---->s. + * + * Frees the #GFile<!---->s in @list and + * the @list itself. + **/ +void +thunar_g_file_list_free (GList *list) +{ + GList *lp; + for (lp = list; lp != NULL; lp = lp->next) + g_object_unref (lp->data); + g_list_free (list); +} + + + +gboolean +thunar_g_volume_is_removable (GVolume *volume) +{ + gboolean can_eject = FALSE; + gboolean can_mount = FALSE; + gboolean can_unmount = FALSE; + gboolean is_removable = FALSE; + GDrive *drive; + GMount *mount; + + _thunar_return_val_if_fail (G_IS_VOLUME (volume), FALSE); + + /* check if the volume can be ejected */ + can_eject = g_volume_can_eject (volume); + + /* determine the drive for the volume */ + drive = g_volume_get_drive (volume); + if (drive != NULL) + { + /*check if the drive media can be removed */ + is_removable = g_drive_is_media_removable (drive); + + /* release the drive */ + g_object_unref (drive); + } + + /* determine the mount for the volume (if it is mounted at all) */ + mount = g_volume_get_mount (volume); + if (mount != NULL) + { + /* check if the volume can be unmounted */ + can_unmount = g_mount_can_unmount (mount); + + /* release the mount */ + g_object_unref (mount); + } + + /* determine whether the device can be mounted */ + can_mount = g_volume_can_mount (volume); + + return can_eject || can_unmount || is_removable || can_mount; +} + + + +gboolean +thunar_g_volume_is_mounted (GVolume *volume) +{ + gboolean is_mounted = FALSE; + GMount *mount; + + _thunar_return_val_if_fail (G_IS_VOLUME (volume), FALSE); + + /* determine the mount for this volume (if it is mounted at all) */ + mount = g_volume_get_mount (volume); + if (mount != NULL) + { + is_mounted = TRUE; + g_object_unref (mount); + } + + return is_mounted; +} + + + +gboolean +thunar_g_volume_is_present (GVolume *volume) +{ + gboolean has_media = FALSE; + GDrive *drive; + + _thunar_return_val_if_fail (G_IS_VOLUME (volume), FALSE); + + drive = g_volume_get_drive (volume); + if (drive != NULL) + { + has_media = g_drive_has_media (drive); + g_object_unref (drive); + } + + return has_media; +} diff --git a/thunar/thunar-gio-extensions.h b/thunar/thunar-gio-extensions.h new file mode 100644 index 000000000..0b09fa2c9 --- /dev/null +++ b/thunar/thunar-gio-extensions.h @@ -0,0 +1,73 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_GIO_EXTENSIONS_H__ +#define __THUNAR_GIO_EXTENSIONS_H__ + +#include <gio/gio.h> + +G_BEGIN_DECLS + +GFile *thunar_g_file_new_for_home (void); +GFile *thunar_g_file_new_for_root (void); +GFile *thunar_g_file_new_for_trash (void); +GFile *thunar_g_file_new_for_desktop (void); +GFile *thunar_g_file_new_for_user_special_dir (GUserDirectory dir); + +gboolean thunar_g_file_is_root (GFile *file); +gboolean thunar_g_file_is_trashed (GFile *file); +gboolean thunar_g_file_is_desktop (GFile *file); + +GKeyFile *thunar_g_file_query_key_file (GFile *file, + GCancellable *cancellable, + GError **error); +gboolean thunar_g_file_write_key_file (GFile *file, + GKeyFile *key_file, + GCancellable *cancellable, + GError **error); + +gchar *thunar_g_file_get_location (GFile *file); + +/** + * THUNAR_TYPE_G_FILE_LIST: + * + * Returns the type ID for #GList<!---->s of #GFile<!---->s which is a + * boxed type. + **/ +#define THUNAR_TYPE_G_FILE_LIST (thunar_g_file_list_get_type ()) + +GType thunar_g_file_list_get_type (void); + +GList *thunar_g_file_list_new_from_string (const gchar *string); +gchar *thunar_g_file_list_to_string (GList *list); +GList *thunar_g_file_list_append (GList *list, + GFile *file); +GList *thunar_g_file_list_prepend (GList *list, + GFile *file); +GList *thunar_g_file_list_copy (GList *list); +void thunar_g_file_list_free (GList *list); + +gboolean thunar_g_volume_is_removable (GVolume *volume); +gboolean thunar_g_volume_is_mounted (GVolume *volume); +gboolean thunar_g_volume_is_present (GVolume *volume); + +G_END_DECLS + +#endif /* !__THUNAR_GIO_EXTENSIONS_H__ */ diff --git a/thunar/thunar-gtk-extensions.c b/thunar/thunar-gtk-extensions.c index 852d8370f..952f93a60 100644 --- a/thunar/thunar-gtk-extensions.c +++ b/thunar/thunar-gtk-extensions.c @@ -88,11 +88,7 @@ thunar_gtk_action_group_set_action_sensitive (GtkActionGroup *action_group, action = gtk_action_group_get_action (action_group, action_name); /* apply the sensitivity to the action */ -#if GTK_CHECK_VERSION(2,6,0) gtk_action_set_sensitive (action, sensitive); -#else - g_object_set (G_OBJECT (action), "sensitive", sensitive, NULL); -#endif } diff --git a/thunar/thunar-icon-factory.c b/thunar/thunar-icon-factory.c index 0cdbe0365..12f60b197 100644 --- a/thunar/thunar-icon-factory.c +++ b/thunar/thunar-icon-factory.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -37,7 +38,7 @@ #include <thunar/thunar-preferences.h> #include <thunar/thunar-private.h> #include <thunar/thunar-thumbnail-frame.h> -#include <thunar/thunar-thumbnail-generator.h> +#include <thunar/thunar-thumbnailer.h> @@ -63,37 +64,37 @@ typedef struct _ThunarIconKey ThunarIconKey; -static void thunar_icon_factory_class_init (ThunarIconFactoryClass *klass); -static void thunar_icon_factory_init (ThunarIconFactory *factory); -static void thunar_icon_factory_dispose (GObject *object); -static void thunar_icon_factory_finalize (GObject *object); -static void thunar_icon_factory_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void thunar_icon_factory_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static gboolean thunar_icon_factory_changed (GSignalInvocationHint *ihint, - guint n_param_values, - const GValue *param_values, - gpointer user_data); -static gboolean thunar_icon_factory_sweep_timer (gpointer user_data); -static void thunar_icon_factory_sweep_timer_destroy (gpointer user_data); -static GdkPixbuf *thunar_icon_factory_load_from_file (ThunarIconFactory *factory, - const gchar *path, - gint size); -static GdkPixbuf *thunar_icon_factory_lookup_icon (ThunarIconFactory *factory, - const gchar *name, - gint size, - gboolean wants_default); -static void thunar_icon_factory_mark_recently_used (ThunarIconFactory *factory, - GdkPixbuf *pixbuf); -static guint thunar_icon_key_hash (gconstpointer data); -static gboolean thunar_icon_key_equal (gconstpointer a, - gconstpointer b); -static GdkPixbuf *thunar_icon_factory_load_fallback (gint size); +static void thunar_icon_factory_class_init (ThunarIconFactoryClass *klass); +static void thunar_icon_factory_init (ThunarIconFactory *factory); +static void thunar_icon_factory_dispose (GObject *object); +static void thunar_icon_factory_finalize (GObject *object); +static void thunar_icon_factory_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void thunar_icon_factory_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static gboolean thunar_icon_factory_changed (GSignalInvocationHint *ihint, + guint n_param_values, + const GValue *param_values, + gpointer user_data); +static gboolean thunar_icon_factory_sweep_timer (gpointer user_data); +static void thunar_icon_factory_sweep_timer_destroy (gpointer user_data); +static GdkPixbuf *thunar_icon_factory_load_from_file (ThunarIconFactory *factory, + const gchar *path, + gint size); +static GdkPixbuf *thunar_icon_factory_lookup_icon (ThunarIconFactory *factory, + const gchar *name, + gint size, + gboolean wants_default); +static void thunar_icon_factory_mark_recently_used (ThunarIconFactory *factory, + GdkPixbuf *pixbuf); +static guint thunar_icon_key_hash (gconstpointer data); +static gboolean thunar_icon_key_equal (gconstpointer a, + gconstpointer b); +static GdkPixbuf *thunar_icon_factory_load_fallback (gint size); @@ -106,24 +107,23 @@ struct _ThunarIconFactory { GObject __parent__; - ThunarThumbnailGenerator *thumbnail_generator; - ThunarVfsThumbFactory *thumbnail_factory; + ThunarThumbnailer *thumbnailer; - ThunarPreferences *preferences; + ThunarPreferences *preferences; - GdkPixbuf *recently[MAX_RECENTLY]; /* ring buffer */ - guint recently_pos; /* insert position */ + GdkPixbuf *recently[MAX_RECENTLY]; /* ring buffer */ + guint recently_pos; /* insert position */ - GHashTable *icon_cache; + GHashTable *icon_cache; - GtkIconTheme *icon_theme; + GtkIconTheme *icon_theme; - gboolean show_thumbnails; + gboolean show_thumbnails; - gint changed_idle_id; - gint sweep_timer_id; + gint changed_idle_id; + gint sweep_timer_id; - gulong changed_hook_id; + gulong changed_hook_id; }; struct _ThunarIconKey @@ -136,9 +136,9 @@ struct _ThunarIconKey static GObjectClass *thunar_icon_factory_parent_class = NULL; static GQuark thunar_icon_factory_quark = 0; -static GQuark thunar_icon_thumb_path_quark = 0; +static GQuark thunar_icon_thumb_uri_quark = 0; static GQuark thunar_icon_thumb_time_quark = 0; -static GQuark thunar_file_thumb_path_quark = 0; +static GQuark thunar_file_thumb_uri_quark = 0; @@ -180,11 +180,11 @@ thunar_icon_factory_class_init (ThunarIconFactoryClass *klass) thunar_icon_factory_parent_class = g_type_class_peek_parent (klass); /* setup the thunar-icon-thumb-{path,time} quarks */ - thunar_icon_thumb_path_quark = g_quark_from_static_string ("thunar-icon-thumb-path"); + thunar_icon_thumb_uri_quark = g_quark_from_static_string ("thunar-icon-thumb-path"); thunar_icon_thumb_time_quark = g_quark_from_static_string ("thunar-icon-thumb-time"); /* setup the thunar-file-thumb-path quark */ - thunar_file_thumb_path_quark = g_quark_from_static_string ("thunar-file-thumb-path"); + thunar_file_thumb_uri_quark = g_quark_from_static_string ("thunar-file-thumb-path"); gobject_class = G_OBJECT_CLASS (klass); gobject_class->dispose = thunar_icon_factory_dispose; @@ -240,13 +240,8 @@ thunar_icon_factory_init (ThunarIconFactory *factory) /* allocate the hash table for the icon cache */ factory->icon_cache = g_hash_table_new_full (thunar_icon_key_hash, thunar_icon_key_equal, g_free, g_object_unref); - /* allocate the thumbnail factory */ - factory->thumbnail_factory = thunar_vfs_thumb_factory_new ((THUNAR_THUMBNAIL_SIZE > 128) - ? THUNAR_VFS_THUMB_SIZE_LARGE - : THUNAR_VFS_THUMB_SIZE_NORMAL); - - /* setup the thumbnail generator */ - factory->thumbnail_generator = thunar_thumbnail_generator_new (factory->thumbnail_factory); + /* create a new thumbnailer */ + factory->thumbnailer = thunar_thumbnailer_new (); } @@ -285,11 +280,8 @@ thunar_icon_factory_finalize (GObject *object) /* clear the icon cache hash table */ g_hash_table_destroy (factory->icon_cache); - /* disconnect from the thumbnail factory */ - g_object_unref (G_OBJECT (factory->thumbnail_factory)); - - /* disconnect from the thumbnail generator */ - g_object_unref (G_OBJECT (factory->thumbnail_generator)); + /* release the thumbnailer */ + g_object_unref (G_OBJECT (factory->thumbnailer)); /* remove the "changed" emission hook from the GtkIconTheme class */ g_signal_remove_emission_hook (g_signal_lookup ("changed", GTK_TYPE_ICON_THEME), factory->changed_hook_id); @@ -539,14 +531,8 @@ thunar_icon_factory_lookup_icon (ThunarIconFactory *factory, { ThunarIconKey lookup_key; ThunarIconKey *key; - ThunarVfsPath *path; - ThunarVfsInfo *info; - const gchar *filename; GtkIconInfo *icon_info; GdkPixbuf *pixbuf = NULL; - GdkPixbuf *scaled; - GError *err = NULL; - gchar *thumbnail; _thunar_return_val_if_fail (THUNAR_IS_ICON_FACTORY (factory), NULL); _thunar_return_val_if_fail (name != NULL && *name != '\0', NULL); @@ -571,67 +557,8 @@ thunar_icon_factory_lookup_icon (ThunarIconFactory *factory, icon_info = gtk_icon_theme_lookup_icon (factory->icon_theme, name, size, 0); if (G_LIKELY (icon_info != NULL)) { - /* check if we have an SVG icon here */ - filename = gtk_icon_info_get_filename (icon_info); - if (filename != NULL && g_str_has_suffix (filename, ".svg")) - { - /* We try to load SVG icons via the thumbnail database, because otherwise it's quite - * slow to load the SVG icon each time, and also requires somewhat more memory than - * simply loading and scaling PNG icons from the thumbnail database. - * - * Therefore first determine the path for the SVG icon. - */ - path = thunar_vfs_path_new (filename, NULL); - if (G_LIKELY (path != NULL)) - { - /* determine the info for the SVG icon, required for the thumbnail lookup */ - info = thunar_vfs_info_new_for_path (path, NULL); - if (G_LIKELY (info != NULL)) - { - /* check if we have a valid thumbnail for the SVG icon */ - thumbnail = thunar_vfs_thumb_factory_lookup_thumbnail (factory->thumbnail_factory, info); - if (thumbnail == NULL) - { - /* try to generate a thumbnail for the SVG icon */ - pixbuf = thunar_vfs_thumb_factory_generate_thumbnail (factory->thumbnail_factory, info); - if (G_LIKELY (pixbuf != NULL)) - { - /* try to store the generated thumbnail in the database */ - if (!thunar_vfs_thumb_factory_store_thumbnail (factory->thumbnail_factory, pixbuf, info, &err)) - { - /* not critical, but atleast let the user know whats going on */ - g_warning ("Failed to store thumbnail for \"%s\" (%s), disabling thumbnailing", filename, err->message); - g_object_set (G_OBJECT (factory->preferences), "misc-show-thumbnails", FALSE, NULL); - g_error_free (err); - } - - /* scale down the generated thumbnail */ - scaled = exo_gdk_pixbuf_scale_down (pixbuf, TRUE, size, size); - g_object_unref (G_OBJECT (pixbuf)); - pixbuf = scaled; - } - } - else - { - /* load icon from the thumbnail */ - pixbuf = exo_gdk_pixbuf_new_from_file_at_max_size (thumbnail, size, size, TRUE, NULL); - - /* cleanup */ - g_free (thumbnail); - } - - /* cleanup */ - thunar_vfs_info_unref (info); - } - - /* cleanup */ - thunar_vfs_path_unref (path); - } - } - - /* fallback to loading via the GtkIconTheme methods */ - if (G_LIKELY (pixbuf == NULL)) - pixbuf = gtk_icon_info_load_icon (icon_info, NULL); + /* try to load the pixbuf from the icon info */ + pixbuf = gtk_icon_info_load_icon (icon_info, NULL); /* cleanup */ gtk_icon_info_free (icon_info); @@ -921,24 +848,24 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory *factory, gint icon_size) { ThunarFileThumbState thumb_state; - ThunarVfsFileTime time; - ThunarVfsInfo *info; - ThunarVfsPath *path; - ThunarIconKey key; - const gchar *icon_name; - GdkPixbuf *icon; - gchar *thumb_path; + GInputStream *stream; + GtkIconInfo *icon_info; + const gchar *thumbnail_path; + GdkPixbuf *icon = NULL; + GIcon *gicon; + gchar *icon_name; _thunar_return_val_if_fail (THUNAR_IS_ICON_FACTORY (factory), NULL); _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); _thunar_return_val_if_fail (icon_size > 0, NULL); - /* check if there's a custom icon for the file */ + /* check if we have a custom icon for this file */ icon_name = thunar_file_get_custom_icon (file); - if (G_UNLIKELY (icon_name != NULL)) + if (icon_name != NULL) { /* try to load the icon */ icon = thunar_icon_factory_lookup_icon (factory, icon_name, icon_size, FALSE); + g_free (icon_name); if (G_LIKELY (icon != NULL)) return icon; } @@ -946,107 +873,91 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory *factory, /* check if thumbnails are enabled and we can display a thumbnail for the item */ if (G_LIKELY (factory->show_thumbnails && thunar_file_is_regular (file))) { - /* determine the thumbnail state */ + /* this is how thumbnails for files are loaded: first, we check the thumbnail + * state. If that is unknown, we request a thumbnail to be generated in the + * background. At the same time we already try to load the thumbnail, in case + * it's already there. when the thumbnail is ready, we just load it */ + + /* determine the thumbnail state of the file */ thumb_state = thunar_file_get_thumb_state (file); - /* check if we haven't yet determine the thumbnail state */ if (thumb_state == THUNAR_FILE_THUMB_STATE_UNKNOWN) { -again: - /* determine the ThunarVfsInfo for the file */ - info = thunar_file_get_info (file); - - /* try to load an existing thumbnail for the file */ - thumb_path = thunar_vfs_thumb_factory_lookup_thumbnail (factory->thumbnail_factory, info); - - /* check if we can generate a thumbnail in case there's none yet */ - if (G_UNLIKELY (thumb_path == NULL && thunar_vfs_thumb_factory_can_thumbnail (factory->thumbnail_factory, info))) - { - /* schedule the thumbnail loading for the file */ - thunar_thumbnail_generator_enqueue (factory->thumbnail_generator, file); + /* we don't know the state yet so request a new thumbnail in the background */ + thunar_thumbnailer_queue_file (factory->thumbnailer, file); + } - /* set the thumbnail state to "loading" */ - thumb_state = THUNAR_FILE_THUMB_STATE_LOADING; - } + /* determine the preview icon first */ + gicon = thunar_file_get_preview_icon (file); - if (G_LIKELY (thumb_path != NULL)) + /* check if we have a preview icon */ + if (gicon != NULL) + { + if (G_IS_THEMED_ICON (gicon)) { - thumb_state = THUNAR_FILE_THUMB_STATE_READY; - g_object_set_qdata_full (G_OBJECT (file), thunar_file_thumb_path_quark, thumb_path, g_free); + /* we have a themed preview icon, look it up using the icon theme */ + icon_info = + gtk_icon_theme_lookup_by_gicon (factory->icon_theme, + gicon, icon_size, + GTK_ICON_LOOKUP_USE_BUILTIN); + + /* check if the lookup succeeded */ + if (icon_info != NULL) + { + /* try to load the pixbuf from the icon info */ + icon = gtk_icon_info_load_icon (icon_info, NULL); + gtk_icon_info_free (icon_info); + } } - else if (thumb_state != THUNAR_FILE_THUMB_STATE_LOADING) + else if (G_IS_LOADABLE_ICON (gicon)) { - thumb_state = THUNAR_FILE_THUMB_STATE_NONE; - } + /* we have a loadable icon, try to open it for reading */ + stream = g_loadable_icon_load (G_LOADABLE_ICON (icon), icon_size, + NULL, NULL, NULL); - /* apply the new state */ - thunar_file_set_thumb_state (file, thumb_state); - } - - /* check if we have a thumbnail path loaded */ - if (thumb_state == THUNAR_FILE_THUMB_STATE_READY) - { - thumb_path = g_object_get_qdata (G_OBJECT (file), thunar_file_thumb_path_quark); - if (G_LIKELY (thumb_path != NULL)) - { - /* try to load the thumbnail for the given path */ - icon = thunar_icon_factory_lookup_icon (factory, thumb_path, icon_size, FALSE); - if (G_LIKELY (icon != NULL)) + /* check if we have a valid input stream */ + if (stream != NULL) { - /* determine the VFS info for the file */ - info = thunar_file_get_info (file); - - /* determine mtime and path for the thumbnail */ - path = g_object_get_qdata (G_OBJECT (icon), thunar_icon_thumb_path_quark); - time = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (icon), thunar_icon_thumb_time_quark)); - - /* check if mtime and path was already associated with the thumbnail */ - if (G_UNLIKELY (path == NULL)) - { - /* just save mtime and path for the thumbnail */ - g_object_set_qdata_full (G_OBJECT (icon), thunar_icon_thumb_path_quark, - thunar_vfs_path_ref (info->path), - (GDestroyNotify) thunar_vfs_path_unref); - g_object_set_qdata (G_OBJECT (icon), thunar_icon_thumb_time_quark, - GUINT_TO_POINTER (info->mtime)); - } - else if (G_UNLIKELY (time != info->mtime || !thunar_vfs_path_equal (path, info->path))) - { - /* the thumbnail is no longer valid, remove it from our internal cache */ - key.name = thumb_path; - key.size = icon_size; - - /* try to remove based on the key */ - if (g_hash_table_remove (factory->icon_cache, &key)) - { - /* we only restart the operation if we were successfull, else we could recurse infinitely */ - thumb_state = THUNAR_FILE_THUMB_STATE_UNKNOWN; - g_object_unref (G_OBJECT (icon)); - goto again; - } - } - - /* ok, we have a valid thumbnail */ - return icon; + /* load the pixbuf from the stream */ + icon = gdk_pixbuf_new_from_stream (stream, NULL, NULL); + + /* destroy the stream */ + g_object_unref (stream); } } - } - /* check if we are currently loading a thumbnail */ - if (G_UNLIKELY (thumb_state == THUNAR_FILE_THUMB_STATE_LOADING)) - { - /* check if the icon theme supports the loading icon */ - icon = thunar_icon_factory_lookup_icon (factory, "gnome-fs-loading-icon", icon_size, FALSE); - if (G_LIKELY (icon != NULL)) + /* release the preview icon */ + g_object_unref (gicon); + + /* return the icon if we have one */ + if (icon != NULL) return icon; } + else + { + /* we have no preview icon but the thumbnail should be ready. determine + * the filename of the thumbnail */ + thumbnail_path = thunar_file_get_thumbnail_path (file); + + /* check if we have a valid path */ + if (thumbnail_path != NULL) + { + /* try to load the thumbnail */ + icon = thunar_icon_factory_load_from_file (factory, thumbnail_path, + icon_size); + + /* return the thumbnail if it could be loaded */ + if (icon != NULL) + return icon; + } + } } - /* lookup the icon name for the icon in the given state */ + /* lookup the icon name for the icon in the given state and load the icon */ icon_name = thunar_file_get_icon_name (file, icon_state, factory->icon_theme); - - /* load the icon of the given name */ - return thunar_icon_factory_load_icon (factory, icon_name, icon_size, NULL, TRUE); + icon = thunar_icon_factory_load_icon (factory, icon_name, icon_size, NULL, TRUE); + g_free (icon_name); + return icon; } diff --git a/thunar/thunar-icon-factory.h b/thunar/thunar-icon-factory.h index bb7834992..39d91ed80 100644 --- a/thunar/thunar-icon-factory.h +++ b/thunar/thunar-icon-factory.h @@ -65,10 +65,6 @@ ThunarIconFactory *thunar_icon_factory_get_for_icon_theme (GtkIconTheme GtkIconTheme *thunar_icon_factory_get_icon_theme (const ThunarIconFactory *factory); -#if 0 -ThunarVfsThumbFactory *thunar_icon_factory_get_thumb_factory (const ThunarIconFactory *factory); -#endif - GdkPixbuf *thunar_icon_factory_load_icon (ThunarIconFactory *factory, const gchar *name, gint size, diff --git a/thunar/thunar-image.c b/thunar/thunar-image.c new file mode 100644 index 000000000..650da202b --- /dev/null +++ b/thunar/thunar-image.c @@ -0,0 +1,253 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 + +#include <glib.h> +#include <glib-object.h> + +#include <thunar/thunar-application.h> +#include <thunar/thunar-file-monitor.h> +#include <thunar/thunar-image.h> +#include <thunar/thunar-icon-factory.h> +#include <thunar/thunar-private.h> + + + +#define THUNAR_IMAGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), THUNAR_TYPE_IMAGE, ThunarImagePrivate)) + + + +/* Property identifiers */ +enum +{ + PROP_0, + PROP_FILE, +}; + + + +static void thunar_image_finalize (GObject *object); +static void thunar_image_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void thunar_image_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void thunar_image_file_changed (ThunarFileMonitor *monitor, + ThunarFile *file, + ThunarImage *image); + + + +struct _ThunarImageClass +{ + GtkImageClass __parent__; +}; + +struct _ThunarImage +{ + GtkImage __parent__; + + ThunarImagePrivate *priv; +}; + +struct _ThunarImagePrivate +{ + ThunarFileMonitor *monitor; + ThunarFile *file; +}; + + + +G_DEFINE_TYPE (ThunarImage, thunar_image, GTK_TYPE_IMAGE); + + + +static void +thunar_image_class_init (ThunarImageClass *klass) +{ + GObjectClass *gobject_class; + + g_type_class_add_private (klass, sizeof (ThunarImagePrivate)); + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = thunar_image_finalize; + gobject_class->get_property = thunar_image_get_property; + gobject_class->set_property = thunar_image_set_property; + + g_object_class_install_property (gobject_class, PROP_FILE, + g_param_spec_object ("file", + "file", + "file", + THUNAR_TYPE_FILE, + G_PARAM_READWRITE)); +} + + + +static void +thunar_image_init (ThunarImage *image) +{ + image->priv = THUNAR_IMAGE_GET_PRIVATE (image); + image->priv->file = NULL; + + image->priv->monitor = thunar_file_monitor_get_default (); + g_signal_connect (image->priv->monitor, "file-changed", + G_CALLBACK (thunar_image_file_changed), image); +} + + + +static void +thunar_image_finalize (GObject *object) +{ + ThunarImage *image = THUNAR_IMAGE (object); + + g_signal_handlers_disconnect_by_func (image->priv->monitor, + thunar_image_file_changed, image); + g_object_unref (image->priv->monitor); + + thunar_image_set_file (image, NULL); + + (*G_OBJECT_CLASS (thunar_image_parent_class)->finalize) (object); +} + + + +static void +thunar_image_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ThunarImage *image = THUNAR_IMAGE (object); + + switch (prop_id) + { + case PROP_FILE: + g_value_set_object (value, image->priv->file); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + + +static void +thunar_image_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ThunarImage *image = THUNAR_IMAGE (object); + + switch (prop_id) + { + case PROP_FILE: + thunar_image_set_file (image, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + + +static void +thunar_image_update (ThunarImage *image) +{ + ThunarIconFactory *icon_factory; + GtkIconTheme *icon_theme; + GdkPixbuf *icon; + GdkScreen *screen; + + _thunar_return_if_fail (THUNAR_IS_IMAGE (image)); + + if (THUNAR_IS_FILE (image->priv->file)) + { + screen = gtk_widget_get_screen (GTK_WIDGET (image)); + icon_theme = gtk_icon_theme_get_for_screen (screen); + icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); + + icon = thunar_icon_factory_load_file_icon (icon_factory, image->priv->file, + THUNAR_FILE_ICON_STATE_DEFAULT, 48); + + gtk_image_set_from_pixbuf (GTK_IMAGE (image), icon); + + g_object_unref (icon_factory); + } +} + + + +static void +thunar_image_file_changed (ThunarFileMonitor *monitor, + ThunarFile *file, + ThunarImage *image) +{ + _thunar_return_if_fail (THUNAR_IS_FILE_MONITOR (monitor)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + _thunar_return_if_fail (THUNAR_IS_IMAGE (image)); + + if (file == image->priv->file) + thunar_image_update (image); +} + + + +GtkWidget * +thunar_image_new (void) +{ + return g_object_new (THUNAR_TYPE_IMAGE, NULL); +} + + + +void +thunar_image_set_file (ThunarImage *image, + ThunarFile *file) +{ + _thunar_return_if_fail (THUNAR_IS_IMAGE (image)); + + if (image->priv->file != NULL) + { + if (image->priv->file == file) + return; + + g_object_unref (image->priv->file); + } + + if (file != NULL) + image->priv->file = g_object_ref (file); + else + image->priv->file = NULL; + + thunar_image_update (image); + + g_object_notify (G_OBJECT (image), "file"); +} diff --git a/thunar/thunar-image.h b/thunar/thunar-image.h new file mode 100644 index 000000000..8714475b2 --- /dev/null +++ b/thunar/thunar-image.h @@ -0,0 +1,47 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_IMAGE_H__ +#define __THUNAR_IMAGE_H__ + +#include <thunar/thunar-file.h> + +G_BEGIN_DECLS; + +#define THUNAR_TYPE_IMAGE (thunar_image_get_type ()) +#define THUNAR_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_IMAGE, ThunarImage)) +#define THUNAR_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_IMAGE, ThunarImageClass)) +#define THUNAR_IS_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_IMAGE)) +#define THUNAR_IS_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_IMAGE) +#define THUNAR_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_IMAGE, ThunarImageClass)) + +typedef struct _ThunarImagePrivate ThunarImagePrivate; +typedef struct _ThunarImageClass ThunarImageClass; +typedef struct _ThunarImage ThunarImage; + +GType thunar_image_get_type (void) G_GNUC_CONST; + +GtkWidget *thunar_image_new (void) G_GNUC_MALLOC; +void thunar_image_set_file (ThunarImage *image, + ThunarFile *file); + +G_END_DECLS; + +#endif /* !__THUNAR_IMAGE_H__ */ diff --git a/thunar/thunar-io-jobs-util.c b/thunar/thunar-io-jobs-util.c new file mode 100644 index 000000000..8367df8b2 --- /dev/null +++ b/thunar/thunar-io-jobs-util.c @@ -0,0 +1,139 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 + +#include <gio/gio.h> + +#include <thunar/thunar-gio-extensions.h> +#include <thunar/thunar-job.h> +#include <thunar/thunar-private.h> + + + +static const gchar *duplicate_names[4][2] = +{ + /* Copy/link name for n <= 3 */ + { N_("copy of %s"), N_("link to %s"), }, + { N_("another copy of %s"), N_("another link to %s"), }, + { N_("third copy of %s"), N_("third link to %s"), }, + + /* Fallback copy/link name for n >= 4 */ + { N_("%uth copy of %s"), N_("%uth link to %s"), }, +}; + + + +/** + * thunar_io_jobs_util_next_duplicate_file: + * @job : a #ThunarJob. + * @file : the source #GFile. + * @type : the operation type (copy or link). + * @n : the @n<!---->th copy/link to create the #GFile for. + * @error : return location for errors or %NULL. + * + * Determines the #GFile for the next copy/link of/to @file. + * + * Copies of a file called X are named: + * n = 1: "copy of X" + * n = 2: "another copy of X" + * n = 3: "third copy of X" + * n >= 4: "@n<!---->th copy of X" + * + * Links follow the same naming scheme, except that they use + * "link to X" instead of "copy of X". + * + * If there are errors or the job was cancelled, the return value + * will be %NULL and @error will be set. + * + * Return value: the #GFile referencing the @n<!---->th copy or link + * of @file or %NULL on error/cancellation. + **/ +GFile * +thunar_io_jobs_util_next_duplicate_file (ThunarJob *job, + GFile *file, + gboolean copy, + gint n, + GError **error) +{ + GFileInfo *info; + GError *err = NULL; + GFile *duplicate_file = NULL; + GFile *parent_file = NULL; + gchar *display_name; + gint type_index; + gint name_index; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), NULL); + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); + _thunar_return_val_if_fail (0 < n, NULL); + _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL); + _thunar_return_val_if_fail (!thunar_g_file_is_root (file), NULL); + + /* abort on cancellation */ + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return NULL; + + /* query the source file info / display name */ + info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job)), &err); + + /* abort on error */ + if (info == NULL) + { + g_propagate_error (error, err); + return NULL; + } + + /* determine the type index (copy = 0, link = 1) */ + type_index = (copy ? 0 : 1); + + /* make sure the name index is not out of bounds */ + name_index = MIN (n-1, G_N_ELEMENTS (duplicate_names)-1); + + /* generate the display name for the nth copy/link of the source file */ + if (name_index < G_N_ELEMENTS (duplicate_names)-1) + { + display_name = g_strdup_printf (gettext (duplicate_names[name_index][type_index]), + g_file_info_get_display_name (info)); + } + else + { + display_name = g_strdup_printf (gettext (duplicate_names[name_index][type_index]), + n, g_file_info_get_display_name (info)); + } + + /* create the GFile for the copy/link */ + parent_file = g_file_get_parent (file); + duplicate_file = g_file_get_child (parent_file, display_name); + g_object_unref (parent_file); + + /* free resources */ + g_object_unref (info); + g_free (display_name); + + return duplicate_file; +} + + + diff --git a/thunar/thunar-io-jobs-util.h b/thunar/thunar-io-jobs-util.h new file mode 100644 index 000000000..d5eb11d44 --- /dev/null +++ b/thunar/thunar-io-jobs-util.h @@ -0,0 +1,36 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_IO_JOBS_UTIL_H__ +#define __THUNAR_IO_JOBS_UTIL_H__ + +#include <thunar/thunar-job.h> + +G_BEGIN_DECLS + +GFile *thunar_io_jobs_util_next_duplicate_file (ThunarJob *job, + GFile *file, + gboolean copy, + gint n, + GError **error) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +G_END_DECLS + +#endif /* !__THUNAR_IO_JOBS_UITL_H__ */ diff --git a/thunar/thunar-io-jobs.c b/thunar/thunar-io-jobs.c new file mode 100644 index 000000000..27b772534 --- /dev/null +++ b/thunar/thunar-io-jobs.c @@ -0,0 +1,1162 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 + +#include <gio/gio.h> + +#include <thunar/thunar-enum-types.h> +#include <thunar/thunar-gio-extensions.h> +#include <thunar/thunar-io-scan-directory.h> +#include <thunar/thunar-job.h> +#include <thunar/thunar-private.h> +#include <thunar/thunar-simple-job.h> +#include <thunar/thunar-transfer-job.h> + + + +static GList * +_tij_collect_nofollow (ThunarJob *job, + GList *base_file_list, + GError **error) +{ + GError *err = NULL; + GList *child_file_list = NULL; + GList *file_list = NULL; + GList *lp; + + /* recursively collect the files */ + for (lp = base_file_list; + err == NULL && lp != NULL && !exo_job_is_cancelled (EXO_JOB (job)); + lp = lp->next) + { + /* try to scan the directory */ + child_file_list = thunar_io_scan_directory (job, lp->data, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + TRUE, &err); + + /* prepend the new files to the existing list */ + file_list = thunar_g_file_list_prepend (file_list, lp->data); + file_list = g_list_concat (child_file_list, file_list); + } + + /* check if we failed */ + if (err != NULL || exo_job_is_cancelled (EXO_JOB (job))) + { + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + g_error_free (err); + else + g_propagate_error (error, err); + + /* release the collected files */ + thunar_g_file_list_free (file_list); + + return NULL; + } + + return file_list; +} + + + +static gboolean +_thunar_io_jobs_create (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + GFileOutputStream *stream; + ThunarJobResponse response = THUNAR_JOB_RESPONSE_CANCEL; + GFileInfo *info; + GError *err = NULL; + GList *file_list; + GList *lp; + gchar *basename; + gchar *display_name; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (param_values != NULL, FALSE); + _thunar_return_val_if_fail (param_values->n_values == 1, FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* get the file list */ + file_list = g_value_get_boxed (g_value_array_get_nth (param_values, 0)); + + /* we know the total amount of files to be processed */ + thunar_job_set_total_files (THUNAR_JOB (job), file_list); + + /* iterate over all files in the list */ + for (lp = file_list; + err == NULL && lp != NULL && !exo_job_is_cancelled (EXO_JOB (job)); + lp = lp->next) + { + g_assert (G_IS_FILE (lp->data)); + + /* update progress information */ + thunar_job_processing_file (THUNAR_JOB (job), lp); + +again: + /* try to create the file */ + stream = g_file_create (lp->data, + G_FILE_CREATE_NONE, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + + /* abort if the job was cancelled */ + if (exo_job_is_cancelled (EXO_JOB (job))) + break; + + /* check if creating failed */ + if (stream == NULL) + { + if (err->code == G_IO_ERROR_EXISTS) + { + g_clear_error (&err); + + /* the file already exists, query its display name */ + info = g_file_query_info (lp->data, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + G_FILE_QUERY_INFO_NONE, + exo_job_get_cancellable (EXO_JOB (job)), + NULL); + + /* abort if the job was cancelled */ + if (exo_job_is_cancelled (EXO_JOB (job))) + break; + + /* determine the display name, using the basename as a fallback */ + if (info != NULL) + { + display_name = g_strdup (g_file_info_get_display_name (info)); + g_object_unref (info); + } + else + { + basename = g_file_get_basename (lp->data); + display_name = g_filename_display_name (basename); + g_free (basename); + } + + /* ask the user whether he wants to overwrite the existing file */ + response = thunar_job_ask_overwrite (THUNAR_JOB (job), + _("The file \"%s\" already exists"), + display_name); + + /* check if we should overwrite */ + if (response == THUNAR_JOB_RESPONSE_YES) + { + /* try to remove the file. fail if not possible */ + if (g_file_delete (lp->data, exo_job_get_cancellable (EXO_JOB (job)), &err)) + goto again; + } + + /* clean up */ + g_free (display_name); + } + else + { + /* determine display name of the file */ + basename = g_file_get_basename (lp->data); + display_name = g_filename_display_basename (basename); + g_free (basename); + + /* ask the user whether to skip/retry this path (cancels the job if not) */ + response = thunar_job_ask_skip (THUNAR_JOB (job), + _("Failed to create empty file \"%s\": %s"), + display_name, err->message); + g_free (display_name); + + g_clear_error (&err); + + /* go back to the beginning if the user wants to retry */ + if (response == THUNAR_JOB_RESPONSE_RETRY) + goto again; + } + } + else + g_object_unref (stream); + } + + /* check if we have failed */ + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + + /* check if the job was cancelled */ + if (exo_job_is_cancelled (EXO_JOB (job))) + return FALSE; + + /* emit the "new-files" signal with the given file list */ + thunar_job_new_files (THUNAR_JOB (job), file_list); + + return TRUE; +} + + + +ThunarJob * +thunar_io_jobs_create_files (GList *file_list) +{ + return thunar_simple_job_launch (_thunar_io_jobs_create, 1, + THUNAR_TYPE_G_FILE_LIST, file_list); +} + + + +static gboolean +_thunar_io_jobs_mkdir (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + ThunarJobResponse response; + GFileInfo *info; + GError *err = NULL; + GList *file_list; + GList *lp; + gchar *basename; + gchar *display_name; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (param_values != NULL, FALSE); + _thunar_return_val_if_fail (param_values->n_values == 1, FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + file_list = g_value_get_boxed (g_value_array_get_nth (param_values, 0)); + + /* we know the total list of files to process */ + thunar_job_set_total_files (THUNAR_JOB (job), file_list); + + for (lp = file_list; + err == NULL && lp != NULL && !exo_job_is_cancelled (EXO_JOB (job)); + lp = lp->next) + { + g_assert (G_IS_FILE (lp->data)); + + /* update progress information */ + thunar_job_processing_file (THUNAR_JOB (job), lp); + +again: + /* try to create the directory */ + if (!g_file_make_directory (lp->data, exo_job_get_cancellable (EXO_JOB (job)), &err)) + { + if (err->code == G_IO_ERROR_EXISTS) + { + g_error_free (err); + err = NULL; + + /* abort if the job was cancelled */ + if (exo_job_is_cancelled (EXO_JOB (job))) + break; + + /* the file already exists, query its display name */ + info = g_file_query_info (lp->data, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + G_FILE_QUERY_INFO_NONE, + exo_job_get_cancellable (EXO_JOB (job)), + NULL); + + /* abort if the job was cancelled */ + if (exo_job_is_cancelled (EXO_JOB (job))) + break; + + /* determine the display name, using the basename as a fallback */ + if (info != NULL) + { + display_name = g_strdup (g_file_info_get_display_name (info)); + g_object_unref (info); + } + else + { + basename = g_file_get_basename (lp->data); + display_name = g_filename_display_name (basename); + g_free (basename); + } + + /* ask the user whether he wants to overwrite the existing file */ + response = thunar_job_ask_overwrite (THUNAR_JOB (job), + _("The file \"%s\" already exists"), + display_name); + + /* check if we should overwrite it */ + if (response == THUNAR_JOB_RESPONSE_YES) + { + /* try to remove the file, fail if not possible */ + if (g_file_delete (lp->data, exo_job_get_cancellable (EXO_JOB (job)), &err)) + goto again; + } + + /* clean up */ + g_free (display_name); + } + else + { + /* determine the display name of the file */ + basename = g_file_get_basename (lp->data); + display_name = g_filename_display_basename (basename); + g_free (basename); + + /* ask the user whether to skip/retry this path (cancels the job if not) */ + response = thunar_job_ask_skip (THUNAR_JOB (job), + _("Failed to create directory \"%s\": %s"), + display_name, err->message); + g_free (display_name); + + g_error_free (err); + err = NULL; + + /* go back to the beginning if the user wants to retry */ + if (response == THUNAR_JOB_RESPONSE_RETRY) + goto again; + } + } + } + + /* check if we have failed */ + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + + /* check if the job was cancelled */ + if (exo_job_is_cancelled (EXO_JOB (job))) + return FALSE; + + /* emit the "new-files" signal with the given file list */ + thunar_job_new_files (THUNAR_JOB (job), file_list); + + return TRUE; +} + + + +ThunarJob * +thunar_io_jobs_make_directories (GList *file_list) +{ + return thunar_simple_job_launch (_thunar_io_jobs_mkdir, 1, + THUNAR_TYPE_G_FILE_LIST, file_list); +} + + + +static gboolean +_thunar_io_jobs_unlink (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + ThunarJobResponse response; + GFileInfo *info; + GError *err = NULL; + GList *file_list; + GList *lp; + gchar *basename; + gchar *display_name; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (param_values != NULL, FALSE); + _thunar_return_val_if_fail (param_values->n_values == 1, FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* get the file list */ + file_list = g_value_get_boxed (g_value_array_get_nth (param_values, 0)); + + /* tell the user that we're preparing to unlink the files */ + exo_job_info_message (EXO_JOB (job), _("Preparing...")); + + /* recursively collect files for removal, not following any symlinks */ + file_list = _tij_collect_nofollow (job, file_list, &err); + + /* free the file list and fail if there was an error or the job was cancelled */ + if (err != NULL || exo_job_is_cancelled (EXO_JOB (job))) + { + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + g_error_free (err); + else + g_propagate_error (error, err); + + thunar_g_file_list_free (file_list); + return FALSE; + } + + /* we know the total list of files to process */ + thunar_job_set_total_files (THUNAR_JOB (job), file_list); + + /* remove all the files */ + for (lp = file_list; lp != NULL && !exo_job_is_cancelled (EXO_JOB (job)); lp = lp->next) + { + g_assert (G_IS_FILE (lp->data)); + + /* skip root folders which cannot be deleted anyway */ + if (thunar_g_file_is_root (lp->data)) + continue; + +again: + /* try to delete the file */ + if (!g_file_delete (lp->data, exo_job_get_cancellable (EXO_JOB (job)), &err)) + { + /* query the file info for the display name */ + info = g_file_query_info (lp->data, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + G_FILE_QUERY_INFO_NONE, + exo_job_get_cancellable (EXO_JOB (job)), + NULL); + + /* abort if the job was cancelled */ + if (exo_job_is_cancelled (EXO_JOB (job))) + { + g_clear_error (&err); + break; + } + + /* determine the display name, using the basename as a fallback */ + if (info != NULL) + { + display_name = g_strdup (g_file_info_get_display_name (info)); + g_object_unref (info); + } + else + { + basename = g_file_get_basename (lp->data); + display_name = g_filename_display_name (basename); + g_free (basename); + } + + /* ask the user whether he wants to skip this file */ + response = thunar_job_ask_skip (THUNAR_JOB (job), + _("Could not delete file \"%s\": %s"), + display_name, err->message); + g_free (display_name); + + /* clear the error */ + g_clear_error (&err); + + /* check whether to retry */ + if (response == THUNAR_JOB_RESPONSE_RETRY) + goto again; + } + } + + /* release the file list */ + thunar_g_file_list_free (file_list); + + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return FALSE; + else + return TRUE; +} + + + +ThunarJob * +thunar_io_jobs_unlink_files (GList *file_list) +{ + return thunar_simple_job_launch (_thunar_io_jobs_unlink, 1, + THUNAR_TYPE_G_FILE_LIST, file_list); +} + + + +ThunarJob * +thunar_io_jobs_move_files (GList *source_file_list, + GList *target_file_list) +{ + ThunarJob *job; + + _thunar_return_val_if_fail (source_file_list != NULL, NULL); + _thunar_return_val_if_fail (target_file_list != NULL, NULL); + _thunar_return_val_if_fail (g_list_length (source_file_list) == g_list_length (target_file_list), NULL); + + job = thunar_transfer_job_new (source_file_list, target_file_list, + THUNAR_TRANSFER_JOB_MOVE); + + return THUNAR_JOB (exo_job_launch (EXO_JOB (job))); +} + + + +ThunarJob * +thunar_io_jobs_copy_files (GList *source_file_list, + GList *target_file_list) +{ + ThunarJob *job; + + _thunar_return_val_if_fail (source_file_list != NULL, NULL); + _thunar_return_val_if_fail (target_file_list != NULL, NULL); + _thunar_return_val_if_fail (g_list_length (source_file_list) == g_list_length (target_file_list), NULL); + + job = thunar_transfer_job_new (source_file_list, target_file_list, + THUNAR_TRANSFER_JOB_COPY); + + return THUNAR_JOB (exo_job_launch (EXO_JOB (job))); +} + + + +static gboolean +_thunar_io_jobs_link (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + ThunarJobResponse response; + GError *err = NULL; + GList *new_files_list = NULL; + GList *source_file_list; + GList *sp; + GList *target_file_list; + GList *tp; + gchar *basename; + gchar *display_name; + gchar *source_path; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (param_values != NULL, FALSE); + _thunar_return_val_if_fail (param_values->n_values == 2, FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + source_file_list = g_value_get_boxed (g_value_array_get_nth (param_values, 0)); + target_file_list = g_value_get_boxed (g_value_array_get_nth (param_values, 1)); + + /* we know the total list of paths to process */ + thunar_job_set_total_files (THUNAR_JOB (job), source_file_list); + + /* process all files */ + for (sp = source_file_list, tp = target_file_list; + err == NULL && sp != NULL && tp != NULL; + sp = sp->next, tp = tp->next) + { + _thunar_assert (G_IS_FILE (sp->data)); + _thunar_assert (G_IS_FILE (tp->data)); + + /* update progress information */ + thunar_job_processing_file (THUNAR_JOB (job), sp); + +again: + source_path = g_file_get_path (sp->data); + + if (G_LIKELY (source_path != NULL)) + { + /* try to create the symlink */ + g_file_make_symbolic_link (tp->data, source_path, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + + g_free (source_path); + + if (err == NULL) + new_files_list = thunar_g_file_list_prepend (new_files_list, sp->data); + else + { + /* check if we have an error from which we can recover */ + if (err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS) + { + /* ask the user whether he wants to overwrite the existing file */ + response = thunar_job_ask_overwrite (THUNAR_JOB (job), "%s", + err->message); + + /* release the error */ + g_clear_error (&err); + + /* try to delete the file */ + if (G_LIKELY (response == THUNAR_JOB_RESPONSE_YES)) + { + /* try to remove the target file (fail if not possible) */ + if (g_file_delete (tp->data, exo_job_get_cancellable (EXO_JOB (job)), &err)) + goto again; + } + } + } + } + else + { + basename = g_file_get_basename (sp->data); + display_name = g_filename_display_name (basename); + g_set_error (&err, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Could not create symbolic link to \"%s\" " + "because it is not a local file"), display_name); + g_free (display_name); + g_free (basename); + } + } + + if (err != NULL) + { + thunar_g_file_list_free (new_files_list); + g_propagate_error (error, err); + return FALSE; + } + else + { + thunar_job_new_files (THUNAR_JOB (job), new_files_list); + thunar_g_file_list_free (new_files_list); + return TRUE; + } +} + + + +ThunarJob * +thunar_io_jobs_link_files (GList *source_file_list, + GList *target_file_list) +{ + _thunar_return_val_if_fail (source_file_list != NULL, NULL); + _thunar_return_val_if_fail (target_file_list != NULL, NULL); + _thunar_return_val_if_fail (g_list_length (source_file_list) == g_list_length (target_file_list), NULL); + + return thunar_simple_job_launch (_thunar_io_jobs_link, 2, + THUNAR_TYPE_G_FILE_LIST, source_file_list, + THUNAR_TYPE_G_FILE_LIST, target_file_list); +} + + + +static gboolean +_thunar_io_jobs_trash (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + GError *err = NULL; + GList *file_list; + GList *lp; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (param_values != NULL, FALSE); + _thunar_return_val_if_fail (param_values->n_values == 1, FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + file_list = g_value_get_boxed (g_value_array_get_nth (param_values, 0)); + + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return FALSE; + + for (lp = file_list; err == NULL && lp != NULL; lp = lp->next) + { + _thunar_assert (G_IS_FILE (lp->data)); + g_file_trash (lp->data, exo_job_get_cancellable (EXO_JOB (job)), &err); + } + + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + else + { + return TRUE; + } +} + + + +ThunarJob * +thunar_io_jobs_trash_files (GList *file_list) +{ + _thunar_return_val_if_fail (file_list != NULL, NULL); + + return thunar_simple_job_launch (_thunar_io_jobs_trash, 1, + THUNAR_TYPE_G_FILE_LIST, file_list); +} + + + +ThunarJob * +thunar_io_jobs_restore_files (GList *source_file_list, + GList *target_file_list) +{ + ThunarJob *job; + + _thunar_return_val_if_fail (source_file_list != NULL, NULL); + _thunar_return_val_if_fail (target_file_list != NULL, NULL); + _thunar_return_val_if_fail (g_list_length (source_file_list) == g_list_length (target_file_list), NULL); + + job = thunar_transfer_job_new (source_file_list, target_file_list, + THUNAR_TRANSFER_JOB_MOVE); + + return THUNAR_JOB (exo_job_launch (EXO_JOB (job))); +} + + + +static gboolean +_thunar_io_jobs_chown (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + ThunarJobResponse response; + const gchar *message; + GFileInfo *info; + gboolean recursive; + GError *err = NULL; + GList *file_list; + GList *lp; + gint uid; + gint gid; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (param_values != NULL, FALSE); + _thunar_return_val_if_fail (param_values->n_values == 4, FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + file_list = g_value_get_boxed (g_value_array_get_nth (param_values, 0)); + uid = g_value_get_int (g_value_array_get_nth (param_values, 1)); + gid = g_value_get_int (g_value_array_get_nth (param_values, 2)); + recursive = g_value_get_boolean (g_value_array_get_nth (param_values, 3)); + + _thunar_assert ((uid >= 0 || gid >= 0) && !(uid >= 0 && gid >= 0)); + + /* collect the files for the chown operation */ + if (recursive) + file_list = _tij_collect_nofollow (job, file_list, &err); + else + file_list = thunar_g_file_list_copy (file_list); + + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + + /* we know the total list of files to process */ + thunar_job_set_total_files (THUNAR_JOB (job), file_list); + + /* change the ownership of all files */ + for (lp = file_list; lp != NULL && err == NULL; lp = lp->next) + { + /* update progress information */ + thunar_job_processing_file (THUNAR_JOB (job), lp); + + /* try to query information about the file */ + info = g_file_query_info (lp->data, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + + if (err != NULL) + break; + +retry_chown: + if (uid >= 0) + { + /* try to change the owner UID */ + g_file_set_attribute_uint32 (lp->data, + G_FILE_ATTRIBUTE_UNIX_UID, uid, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + } + else if (gid >= 0) + { + /* try to change the owner GID */ + g_file_set_attribute_uint32 (lp->data, + G_FILE_ATTRIBUTE_UNIX_GID, gid, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + } + + /* check if there was a recoverable error */ + if (err != NULL && !exo_job_is_cancelled (EXO_JOB (job))) + { + /* generate a useful error message */ + message = G_LIKELY (uid >= 0) ? _("Failed to change the owner of \"%s\": %s") + : _("Failed to change the group of \"%s\": %s"); + + /* ask the user whether to skip/retry this file */ + response = thunar_job_ask_skip (THUNAR_JOB (job), message, + g_file_info_get_display_name (info), + err->message); + + /* clear the error */ + g_clear_error (&err); + + /* check whether to retry */ + if (response == THUNAR_JOB_RESPONSE_RETRY) + goto retry_chown; + } + + /* release file information */ + g_object_unref (info); + } + + /* release the file list */ + thunar_g_file_list_free (file_list); + + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + else + { + return TRUE; + } +} + + + +ThunarJob * +thunar_io_jobs_change_group (GFile *file, + guint32 gid, + gboolean recursive) +{ + GList file_list; + + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); + + file_list.data = g_object_ref (file); + file_list.next = NULL; + file_list.prev = NULL; + + return thunar_simple_job_launch (_thunar_io_jobs_chown, 4, + THUNAR_TYPE_G_FILE_LIST, &file_list, + G_TYPE_INT, -1, + G_TYPE_INT, (gint) gid, + G_TYPE_BOOLEAN, recursive); + + g_object_unref (file_list.data); +} + + + +static gboolean +_thunar_io_jobs_chmod (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + ThunarJobResponse response; + GFileInfo *info; + gboolean recursive; + GError *err = NULL; + GList *file_list; + GList *lp; + ThunarFileMode dir_mask; + ThunarFileMode dir_mode; + ThunarFileMode file_mask; + ThunarFileMode file_mode; + ThunarFileMode mask; + ThunarFileMode mode; + ThunarFileMode old_mode; + ThunarFileMode new_mode; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (param_values != NULL, FALSE); + _thunar_return_val_if_fail (param_values->n_values == 6, FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + file_list = g_value_get_boxed (g_value_array_get_nth (param_values, 0)); + dir_mask = g_value_get_flags (g_value_array_get_nth (param_values, 1)); + dir_mode = g_value_get_flags (g_value_array_get_nth (param_values, 2)); + file_mask = g_value_get_flags (g_value_array_get_nth (param_values, 3)); + file_mode = g_value_get_flags (g_value_array_get_nth (param_values, 4)); + recursive = g_value_get_boolean (g_value_array_get_nth (param_values, 5)); + + /* collect the files for the chown operation */ + if (recursive) + file_list = _tij_collect_nofollow (job, file_list, &err); + else + file_list = thunar_g_file_list_copy (file_list); + + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + + /* we know the total list of files to process */ + thunar_job_set_total_files (THUNAR_JOB (job), file_list); + + /* change the ownership of all files */ + for (lp = file_list; lp != NULL && err == NULL; lp = lp->next) + { + /* update progress information */ + thunar_job_processing_file (THUNAR_JOB (job), lp); + + /* try to query information about the file */ + info = g_file_query_info (lp->data, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," + G_FILE_ATTRIBUTE_STANDARD_TYPE "," + G_FILE_ATTRIBUTE_UNIX_MODE, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + + if (err != NULL) + break; + +retry_chown: + /* different actions depending on the type of the file */ + if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + { + mask = dir_mask; + mode = dir_mode; + } + else + { + mask = file_mask; + mode = file_mode; + } + + /* determine the current mode */ + old_mode = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE); + + /* generate the new mode, taking the old mode (which contains file type + * information) into account */ + new_mode = ((old_mode & ~mask) | mode) & 07777; + + /* try to change the file mode */ + g_file_set_attribute_uint32 (lp->data, + G_FILE_ATTRIBUTE_UNIX_MODE, new_mode, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + + /* check if there was a recoverable error */ + if (err != NULL && !exo_job_is_cancelled (EXO_JOB (job))) + { + /* ask the user whether to skip/retry this file */ + response = thunar_job_ask_skip (job, + _("Failed to change the permissions of \"%s\": %s"), + g_file_info_get_display_name (info), + err->message); + + /* clear the error */ + g_clear_error (&err); + + /* check whether to retry */ + if (response == THUNAR_JOB_RESPONSE_RETRY) + goto retry_chown; + } + + /* release file information */ + g_object_unref (info); + } + + /* release the file list */ + thunar_g_file_list_free (file_list); + + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + else + { + return TRUE; + } + return TRUE; +} + + + +ThunarJob * +thunar_io_jobs_change_mode (GFile *file, + ThunarFileMode dir_mask, + ThunarFileMode dir_mode, + ThunarFileMode file_mask, + ThunarFileMode file_mode, + gboolean recursive) +{ + GList file_list; + + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); + + file_list.data = g_object_ref (file); + file_list.next = NULL; + file_list.prev = NULL; + + return thunar_simple_job_launch (_thunar_io_jobs_chmod, 6, + THUNAR_TYPE_G_FILE_LIST, &file_list, + THUNAR_TYPE_FILE_MODE, dir_mask, + THUNAR_TYPE_FILE_MODE, dir_mode, + THUNAR_TYPE_FILE_MODE, file_mask, + THUNAR_TYPE_FILE_MODE, file_mode, + G_TYPE_BOOLEAN, recursive); + + g_object_unref (file_list.data); +} + + + +static gboolean +_thunar_io_jobs_ls (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + ThunarFile *file; + GError *err = NULL; + GFile *directory; + GList *file_list = NULL; + GList *lp; + GList *path_list; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (param_values != NULL, FALSE); + _thunar_return_val_if_fail (param_values->n_values == 1, FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return FALSE; + + /* determine the directory to list */ + directory = g_value_get_object (g_value_array_get_nth (param_values, 0)); + + /* make sure the object is valid */ + _thunar_assert (G_IS_FILE (directory)); + + /* collect directory contents (non-recursively) */ + path_list = thunar_io_scan_directory (job, directory, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + FALSE, &err); + + /* turn the GFile list into a ThunarFile list */ + for (lp = g_list_last (path_list); + err == NULL && !exo_job_is_cancelled (EXO_JOB (job)) && lp != NULL; + lp = lp->prev) + { + file = thunar_file_get (lp->data, &err); + if (G_LIKELY (file != NULL)) + file_list = g_list_prepend (file_list, file); + } + + /* free the GFile list */ + thunar_g_file_list_free (path_list); + + /* abort on errors or cancellation */ + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + else if (exo_job_set_error_if_cancelled (EXO_JOB (job), &err)) + { + g_propagate_error (error, err); + return FALSE; + } + + /* check if we have any files to report */ + if (G_LIKELY (file_list != NULL)) + { + /* emit the "files-ready" signal */ + if (!thunar_job_files_ready (THUNAR_JOB (job), file_list)) + { + /* none of the handlers took over the file list, so it's up to us + * to destroy it */ + thunar_file_list_free (file_list); + } + } + + /* there should be no errors here */ + _thunar_assert (err == NULL); + + /* propagate cancellation error */ + if (exo_job_set_error_if_cancelled (EXO_JOB (job), &err)) + { + g_propagate_error (error, err); + return FALSE; + } + + return TRUE; +} + + + +ThunarJob * +thunar_io_jobs_list_directory (GFile *directory) +{ + _thunar_return_val_if_fail (G_IS_FILE (directory), NULL); + + return thunar_simple_job_launch (_thunar_io_jobs_ls, 1, G_TYPE_FILE, directory); +} + + + +gboolean +_thunar_io_jobs_rename_notify (ThunarFile *file) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + /* tell the associated folder that the file was renamed */ + thunarx_file_info_renamed (THUNARX_FILE_INFO (file)); + + /* emit the file changed signal */ + thunar_file_changed (file); + + return FALSE; +} + + + +gboolean +_thunar_io_jobs_rename (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + const gchar *display_name; + ThunarFile *file; + GError *err = NULL; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (param_values != NULL, FALSE); + _thunar_return_val_if_fail (param_values->n_values == 2, FALSE); + _thunar_return_val_if_fail (G_VALUE_HOLDS (¶m_values->values[0], THUNAR_TYPE_FILE), FALSE); + _thunar_return_val_if_fail (G_VALUE_HOLDS_STRING (¶m_values->values[1]), FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return FALSE; + + /* determine the file and display name */ + file = g_value_get_object (g_value_array_get_nth (param_values, 0)); + display_name = g_value_get_string (g_value_array_get_nth (param_values, 1)); + + /* try to rename the file */ + if (thunar_file_rename (file, display_name, exo_job_get_cancellable (EXO_JOB (job)), TRUE, &err)) + { + exo_job_send_to_mainloop (EXO_JOB (job), + (GSourceFunc) _thunar_io_jobs_rename_notify, + g_object_ref (file), g_object_unref); + } + + /* abort on errors or cancellation */ + if (err != NULL) + { + g_propagate_error (error, err); + return FALSE; + } + + return TRUE; +} + + + +ThunarJob * +thunar_io_jobs_rename_file (ThunarFile *file, + const gchar *display_name) +{ + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL); + _thunar_return_val_if_fail (g_utf8_validate (display_name, -1, NULL), NULL); + + return thunar_simple_job_launch (_thunar_io_jobs_rename, 2, + THUNAR_TYPE_FILE, file, + G_TYPE_STRING, display_name); +} diff --git a/thunar/thunar-io-jobs.h b/thunar/thunar-io-jobs.h new file mode 100644 index 000000000..5821c44ef --- /dev/null +++ b/thunar/thunar-io-jobs.h @@ -0,0 +1,56 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_IO_JOBS_H__ +#define __THUNAR_IO_JOBS_H__ + +#include <thunar/thunar-job.h> +#include <thunar/thunar-enum-types.h> + +G_BEGIN_DECLS + +ThunarJob *thunar_io_jobs_create_files (GList *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_make_directories (GList *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_unlink_files (GList *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_move_files (GList *source_file_list, + GList *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_copy_files (GList *source_file_list, + GList *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_link_files (GList *source_file_list, + GList *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_trash_files (GList *file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_restore_files (GList *source_file_list, + GList *target_file_list) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_change_group (GFile *file, + guint32 gid, + gboolean recursive) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_change_mode (GFile *file, + ThunarFileMode dir_mask, + ThunarFileMode dir_mode, + ThunarFileMode file_mask, + ThunarFileMode file_mode, + gboolean recursive) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_list_directory (GFile *directory) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +ThunarJob *thunar_io_jobs_rename_file (ThunarFile *file, + const gchar *display_name) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +G_END_DECLS + +#endif /* !__THUNAR_IO_JOBS_H__ */ diff --git a/thunar/thunar-io-scan-directory.c b/thunar/thunar-io-scan-directory.c new file mode 100644 index 000000000..cacc381cf --- /dev/null +++ b/thunar/thunar-io-scan-directory.c @@ -0,0 +1,130 @@ +//* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 + +#include <gio/gio.h> + +#include <exo/exo.h> + +#include <thunar/thunar-gio-extensions.h> +#include <thunar/thunar-job.h> +#include <thunar/thunar-private.h> + + + +GList * +thunar_io_scan_directory (ThunarJob *job, + GFile *file, + GFileQueryInfoFlags flags, + gboolean recursively, + GError **error) +{ + GFileEnumerator *enumerator; + GFileInfo *info; + GFileType type; + GError *err = NULL; + GFile *child_file; + GList *child_files = NULL; + GList *files = NULL; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), NULL); + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); + _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* abort if the job was cancelled */ + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return NULL; + + /* query the file type */ + type = g_file_query_file_type (file, flags, exo_job_get_cancellable (EXO_JOB (job))); + + /* abort if the job was cancelled */ + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return NULL; + + /* ignore non-directory nodes */ + if (type != G_FILE_TYPE_DIRECTORY) + return NULL; + + /* try to read from the direectory */ + enumerator = g_file_enumerate_children (file, + G_FILE_ATTRIBUTE_STANDARD_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_NAME, + flags, exo_job_get_cancellable (EXO_JOB (job)), + &err); + + /* abort if there was an error or the job was cancelled */ + if (err != NULL) + { + g_propagate_error (error, err); + return NULL; + } + + /* query info of the first child */ + info = g_file_enumerator_next_file (enumerator, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + + /* iterate over children one by one as long as there's no error */ + while (info != NULL && err == NULL && !exo_job_is_cancelled (EXO_JOB (job))) + { + /* create GFile for the child and prepend it to the file list */ + child_file = g_file_get_child (file, g_file_info_get_name (info)); + files = thunar_g_file_list_prepend (files, child_file); + + /* if the child is a directory and we need to recurse ... just do so */ + if (recursively && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + { + child_files = thunar_io_scan_directory (job, child_file, flags, recursively, &err); + + /* prepend children to the file list to make sure they're + * processed first (required for unlinking) */ + files = g_list_concat (child_files, files); + } + + g_object_unref (child_file); + g_object_unref (info); + + info = g_file_enumerator_next_file (enumerator, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + } + + /* release the enumerator */ + g_object_unref (enumerator); + + if (G_UNLIKELY (err != NULL)) + { + g_propagate_error (error, err); + thunar_g_file_list_free (files); + return NULL; + } + else if (exo_job_set_error_if_cancelled (EXO_JOB (job), &err)) + { + g_propagate_error (error, err); + thunar_g_file_list_free (files); + return NULL; + } + + return files; +} diff --git a/thunar/thunar-io-scan-directory.h b/thunar/thunar-io-scan-directory.h new file mode 100644 index 000000000..f654e6820 --- /dev/null +++ b/thunar/thunar-io-scan-directory.h @@ -0,0 +1,39 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_IO_SCAN_DIRECTORY_H__ +#define __THUNAR_IO_SCAN_DIRECTORY_H__ + +#include <exo/exo.h> + +#include <thunar/thunar-job.h> +#include <thunar/thunar-private.h> + +G_BEGIN_DECLS + +GList *thunar_io_scan_directory (ThunarJob *job, + GFile *file, + GFileQueryInfoFlags flags, + gboolean recursively, + GError **error); + +G_END_DECLS + +#endif /* !__THUNAR_IO_SCAN_DIRECTORY_H__ */ diff --git a/thunar/thunar-job.c b/thunar/thunar-job.c new file mode 100644 index 000000000..893f637e5 --- /dev/null +++ b/thunar/thunar-job.c @@ -0,0 +1,624 @@ +/* $Id$ */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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_MEMORY_H +#include <memory.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include <exo/exo.h> + +#include <thunar/thunar-enum-types.h> +#include <thunar/thunar-job.h> +#include <thunar/thunar-marshal.h> +#include <thunar/thunar-private.h> + + + +#define THUNAR_JOB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), THUNAR_TYPE_JOB, ThunarJobPrivate)) + + + +/* Signal identifiers */ +enum +{ + ASK, + ASK_REPLACE, + FILES_READY, + NEW_FILES, + LAST_SIGNAL, +}; + + + +static void thunar_job_class_init (ThunarJobClass *klass); +static void thunar_job_init (ThunarJob *job); +static void thunar_job_finalize (GObject *object); +static ThunarJobResponse thunar_job_real_ask (ThunarJob *job, + const gchar *message, + ThunarJobResponse choices); +static ThunarJobResponse thunar_job_real_ask_replace (ThunarJob *job, + ThunarFile *source_file, + ThunarFile *target_file); + + + +struct _ThunarJobPrivate +{ + ThunarJobResponse earlier_ask_create_response; + ThunarJobResponse earlier_ask_overwrite_response; + ThunarJobResponse earlier_ask_skip_response; + GList *total_files; +}; + + + +static ExoJobClass *thunar_job_parent_class; +static guint job_signals[LAST_SIGNAL]; + + + +GType +thunar_job_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + type = g_type_register_static_simple (EXO_TYPE_JOB, + "ThunarJob", + sizeof (ThunarJobClass), + (GClassInitFunc) thunar_job_class_init, + sizeof (ThunarJob), + (GInstanceInitFunc) thunar_job_init, + G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + + + +static gboolean +_thunar_job_ask_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer data) +{ + g_value_copy (handler_return, return_accu); + return FALSE; +} + + + +static void +thunar_job_class_init (ThunarJobClass *klass) +{ + GObjectClass *gobject_class; + + /* add our private data for this class */ + g_type_class_add_private (klass, sizeof (ThunarJobPrivate)); + + /* determine the parent class */ + thunar_job_parent_class = g_type_class_peek_parent (klass); + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = thunar_job_finalize; + + klass->ask = thunar_job_real_ask; + klass->ask_replace = thunar_job_real_ask_replace; + + /** + * ThunarJob::ask: + * @job : a #ThunarJob. + * @message : question to display to the user. + * @choices : a combination of #ThunarJobResponse<!---->s. + * + * The @message is garantied to contain valid UTF-8. + * + * Return value: the selected choice. + **/ + job_signals[ASK] = + g_signal_new (I_("ask"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_NO_HOOKS | G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ThunarJobClass, ask), + _thunar_job_ask_accumulator, NULL, + _thunar_marshal_FLAGS__STRING_FLAGS, + THUNAR_TYPE_JOB_RESPONSE, + 2, G_TYPE_STRING, + THUNAR_TYPE_JOB_RESPONSE); + + /** + * ThunarJob::ask-replace: + * @job : a #ThunarJob. + * @src_file : the #ThunarFile of the source file. + * @dst_file : the #ThunarFile of the destination file, that + * may be replaced with the source file. + * + * Emitted to ask the user whether the destination file should + * be replaced by the source file. + * + * Return value: the selected choice. + **/ + job_signals[ASK_REPLACE] = + g_signal_new (I_("ask-replace"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_NO_HOOKS | G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ThunarJobClass, ask_replace), + _thunar_job_ask_accumulator, NULL, + _thunar_marshal_FLAGS__OBJECT_OBJECT, + THUNAR_TYPE_JOB_RESPONSE, + 2, THUNAR_TYPE_FILE, THUNAR_TYPE_FILE); + + /** + * ThunarJob::files-ready: + * @job : a #ThunarJob. + * @file_list : a list of #ThunarFile<!---->s. + * + * This signal is used by #ThunarJob<!---->s returned by + * the thunar_io_jobs_list_directory() function whenever + * there's a bunch of #ThunarFile<!---->s ready. This signal + * is garantied to be never emitted with an @file_list + * parameter of %NULL. + * + * To allow some further optimizations on the handler-side, + * the handler is allowed to take over ownership of the + * @file_list, i.e. it can reuse the @infos list and just replace + * the data elements with it's own objects based on the + * #ThunarFile<!---->s contained within the @file_list (and + * of course properly unreffing the previously contained infos). + * If a handler takes over ownership of @file_list it must return + * %TRUE here, and no further handlers will be run. Else, if + * the handler doesn't want to take over ownership of @infos, + * it must return %FALSE, and other handlers will be run. Use + * this feature with care, and only if you can be sure that + * you are the only handler connected to this signal for a + * given job! + * + * Return value: %TRUE if the handler took over ownership of + * @file_list, else %FALSE. + **/ + job_signals[FILES_READY] = + g_signal_new (I_("files-ready"), + G_TYPE_FROM_CLASS (klass), G_SIGNAL_NO_HOOKS, + 0, g_signal_accumulator_true_handled, NULL, + _thunar_marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, 1, G_TYPE_POINTER); + + /** + * ThunarJob::new-files: + * @job : a #ThunarJob. + * @file_list : a list of #GFile<!---->s that were created by @job. + * + * This signal is emitted by the @job right before the @job is terminated + * and informs the application about the list of created files in @file_list. + * @file_list contains only the toplevel file items, that were specified by + * the application on creation of the @job. + **/ + job_signals[NEW_FILES] = + g_signal_new (I_("new-files"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_NO_HOOKS, 0, NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); +} + + + +static void +thunar_job_init (ThunarJob *job) +{ + job->priv = THUNAR_JOB_GET_PRIVATE (job); + job->priv->earlier_ask_create_response = 0; + job->priv->earlier_ask_overwrite_response = 0; + job->priv->earlier_ask_skip_response = 0; +} + + + +static void +thunar_job_finalize (GObject *object) +{ + (*G_OBJECT_CLASS (thunar_job_parent_class)->finalize) (object); +} + + + +static ThunarJobResponse +thunar_job_real_ask (ThunarJob *job, + const gchar *message, + ThunarJobResponse choices) +{ + ThunarJobResponse response; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + g_signal_emit (job, job_signals[ASK], 0, message, choices, &response); + return response; +} + + + +static ThunarJobResponse +thunar_job_real_ask_replace (ThunarJob *job, + ThunarFile *source_file, + ThunarFile *target_file) +{ + ThunarJobResponse response; + gchar *message; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (source_file), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (target_file), THUNAR_JOB_RESPONSE_CANCEL); + + message = g_strdup_printf (_("The file \"%s\" already exists. Would you like to replace it?\n\n" + "If you replace an existing file, its contents will be overwritten."), + thunar_file_get_display_name (source_file)); + + g_signal_emit (job, job_signals[ASK], 0, message, + THUNAR_JOB_RESPONSE_YES + | THUNAR_JOB_RESPONSE_YES_ALL + | THUNAR_JOB_RESPONSE_NO + | THUNAR_JOB_RESPONSE_NO_ALL + | THUNAR_JOB_RESPONSE_CANCEL, + &response); + + /* clean up */ + g_free (message); + + return response; +} + + + +static ThunarJobResponse +_thunar_job_ask_valist (ThunarJob *job, + const gchar *format, + va_list var_args, + const gchar *question, + ThunarJobResponse choices) +{ + ThunarJobResponse response; + gchar *text; + gchar *message; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (g_utf8_validate (format, -1, NULL), THUNAR_JOB_RESPONSE_CANCEL); + + /* generate the dialog message */ + text = g_strdup_vprintf (format, var_args); + message = (question != NULL) + ? g_strconcat (text, ".\n\n", question, NULL) + : g_strconcat (text, ".", NULL); + g_free (text); + + /* send the question and wait for the answer */ + exo_job_emit (EXO_JOB (job), job_signals[ASK], 0, message, choices, &response); + g_free (message); + + /* cancel the job as per users request */ + if (G_UNLIKELY (response == THUNAR_JOB_RESPONSE_CANCEL)) + exo_job_cancel (EXO_JOB (job)); + + return response; +} + + + +ThunarJobResponse +thunar_job_ask_overwrite (ThunarJob *job, + const gchar *format, + ...) +{ + ThunarJobResponse response; + va_list var_args; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (format != NULL, THUNAR_JOB_RESPONSE_CANCEL); + + /* check if the user already cancelled the job */ + if (G_UNLIKELY (exo_job_is_cancelled (EXO_JOB (job)))) + return THUNAR_JOB_RESPONSE_CANCEL; + + /* check if the user said "Overwrite All" earlier */ + if (G_UNLIKELY (job->priv->earlier_ask_overwrite_response == THUNAR_JOB_RESPONSE_YES_ALL)) + return THUNAR_JOB_RESPONSE_YES; + + /* check if the user said "Overwrite None" earlier */ + if (G_UNLIKELY (job->priv->earlier_ask_overwrite_response == THUNAR_JOB_RESPONSE_NO_ALL)) + return THUNAR_JOB_RESPONSE_NO; + + /* ask the user what he wants to do */ + va_start (var_args, format); + response = _thunar_job_ask_valist (job, format, var_args, + _("Do you want to overwrite it?"), + THUNAR_JOB_RESPONSE_YES + | THUNAR_JOB_RESPONSE_YES_ALL + | THUNAR_JOB_RESPONSE_NO + | THUNAR_JOB_RESPONSE_NO_ALL + | THUNAR_JOB_RESPONSE_CANCEL); + va_end (var_args); + + /* remember response for later */ + job->priv->earlier_ask_overwrite_response = response; + + /* translate response */ + switch (response) + { + case THUNAR_JOB_RESPONSE_YES_ALL: + response = THUNAR_JOB_RESPONSE_YES; + break; + + case THUNAR_JOB_RESPONSE_NO_ALL: + response = THUNAR_JOB_RESPONSE_NO; + break; + + default: + break; + } + + return response; +} + + + +ThunarJobResponse +thunar_job_ask_create (ThunarJob *job, + const gchar *format, + ...) +{ + ThunarJobResponse response; + va_list var_args; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + + if (G_UNLIKELY (exo_job_is_cancelled (EXO_JOB (job)))) + return THUNAR_JOB_RESPONSE_CANCEL; + + /* check if the user said "Create All" earlier */ + if (G_UNLIKELY (job->priv->earlier_ask_create_response == THUNAR_JOB_RESPONSE_YES_ALL)) + return THUNAR_JOB_RESPONSE_YES; + + /* check if the user said "Create None" earlier */ + if (G_UNLIKELY (job->priv->earlier_ask_create_response == THUNAR_JOB_RESPONSE_NO_ALL)) + return THUNAR_JOB_RESPONSE_NO; + + va_start (var_args, format); + response = _thunar_job_ask_valist (job, format, var_args, + _("Do you want to create it?"), + THUNAR_JOB_RESPONSE_YES + | THUNAR_JOB_RESPONSE_CANCEL); + va_end (var_args); + + job->priv->earlier_ask_create_response = response; + + /* translate the response */ + if (response == THUNAR_JOB_RESPONSE_YES_ALL) + response = THUNAR_JOB_RESPONSE_YES; + else if (response == THUNAR_JOB_RESPONSE_NO_ALL) + response = THUNAR_JOB_RESPONSE_NO; + else if (response == THUNAR_JOB_RESPONSE_CANCEL) + exo_job_cancel (EXO_JOB (job)); + + return response; +} + + + +ThunarJobResponse +thunar_job_ask_replace (ThunarJob *job, + GFile *source_path, + GFile *target_path, + GError **error) +{ + ThunarJobResponse response; + ThunarFile *source_file; + ThunarFile *target_file; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (G_IS_FILE (source_path), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (G_IS_FILE (target_path), THUNAR_JOB_RESPONSE_CANCEL); + + if (G_UNLIKELY (exo_job_set_error_if_cancelled (EXO_JOB (job), error))) + return THUNAR_JOB_RESPONSE_CANCEL; + + /* check if the user said "Overwrite All" earlier */ + if (G_UNLIKELY (job->priv->earlier_ask_overwrite_response == THUNAR_JOB_RESPONSE_YES_ALL)) + return THUNAR_JOB_RESPONSE_YES; + + /* check if the user said "Overwrite None" earlier */ + if (G_UNLIKELY (job->priv->earlier_ask_overwrite_response == THUNAR_JOB_RESPONSE_NO_ALL)) + return THUNAR_JOB_RESPONSE_NO; + + source_file = thunar_file_get (source_path, error); + + if (G_UNLIKELY (source_file == NULL)) + return THUNAR_JOB_RESPONSE_NO; + + target_file = thunar_file_get (target_path, error); + + if (G_UNLIKELY (target_file == NULL)) + { + g_object_unref (source_file); + return THUNAR_JOB_RESPONSE_NO; + } + + exo_job_emit (EXO_JOB (job), job_signals[ASK_REPLACE], 0, + source_file, target_file, &response); + + g_object_unref (source_file); + g_object_unref (target_file); + + /* remember the response for later */ + job->priv->earlier_ask_overwrite_response = response; + + /* translate the response */ + if (response == THUNAR_JOB_RESPONSE_YES_ALL) + response = THUNAR_JOB_RESPONSE_YES; + else if (response == THUNAR_JOB_RESPONSE_NO_ALL) + response = THUNAR_JOB_RESPONSE_NO; + else if (response == THUNAR_JOB_RESPONSE_CANCEL) + exo_job_cancel (EXO_JOB (job)); + + return response; +} + + + +ThunarJobResponse +thunar_job_ask_skip (ThunarJob *job, + const gchar *format, + ...) +{ + ThunarJobResponse response; + va_list var_args; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (format != NULL, THUNAR_JOB_RESPONSE_CANCEL); + + /* check if the user already cancelled the job */ + if (G_UNLIKELY (exo_job_is_cancelled (EXO_JOB (job)))) + return THUNAR_JOB_RESPONSE_CANCEL; + + /* check if the user said "Skip All" earlier */ + if (G_UNLIKELY (job->priv->earlier_ask_skip_response == THUNAR_JOB_RESPONSE_YES_ALL)) + return THUNAR_JOB_RESPONSE_YES; + + /* ask the user what he wants to do */ + va_start (var_args, format); + response = _thunar_job_ask_valist (job, format, var_args, + _("Do you want to skip it?"), + THUNAR_JOB_RESPONSE_YES + | THUNAR_JOB_RESPONSE_YES_ALL + | THUNAR_JOB_RESPONSE_CANCEL + | THUNAR_JOB_RESPONSE_RETRY); + va_end (var_args); + + /* remember the response */ + job->priv->earlier_ask_skip_response = response; + + /* translate the response */ + switch (response) + { + case THUNAR_JOB_RESPONSE_YES_ALL: + response = THUNAR_JOB_RESPONSE_YES; + break; + + case THUNAR_JOB_RESPONSE_YES: + case THUNAR_JOB_RESPONSE_CANCEL: + case THUNAR_JOB_RESPONSE_RETRY: + break; + + default: + _thunar_assert_not_reached (); + } + + return response; +} + + + +gboolean +thunar_job_files_ready (ThunarJob *job, + GList *file_list) +{ + gboolean handled = FALSE; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + + exo_job_emit (EXO_JOB (job), job_signals[FILES_READY], 0, file_list, &handled); + return handled; +} + + + +void +thunar_job_new_files (ThunarJob *job, + const GList *file_list) +{ + _thunar_return_if_fail (THUNAR_IS_JOB (job)); + + /* check if we have any files */ + if (G_LIKELY (file_list != NULL)) + { + /* emit the "new-files" signal */ + exo_job_emit (EXO_JOB (job), job_signals[NEW_FILES], 0, file_list); + } +} + + + +void +thunar_job_set_total_files (ThunarJob *job, + GList *total_files) +{ + _thunar_return_if_fail (THUNAR_IS_JOB (job)); + _thunar_return_if_fail (job->priv->total_files == NULL); + _thunar_return_if_fail (total_files != NULL); + + job->priv->total_files = total_files; +} + + + +void +thunar_job_processing_file (ThunarJob *job, + GList *current_file) +{ + GList *lp; + gchar *basename; + gchar *display_name; + guint n_processed; + guint n_total; + + _thunar_return_if_fail (THUNAR_IS_JOB (job)); + _thunar_return_if_fail (current_file != NULL); + + basename = g_file_get_basename (current_file->data); + display_name = g_filename_display_name (basename); + g_free (basename); + + exo_job_info_message (EXO_JOB (job), display_name); + g_free (display_name); + + /* verify that we have total files set */ + if (G_LIKELY (job->priv->total_files != NULL)) + { + /* determine the number of files processed so far */ + for (lp = job->priv->total_files, n_processed = 0; + lp != current_file; + lp = lp->next); + + /* emit only if n_processed is a multiple of 8 */ + if ((n_processed % 8) == 0) + { + /* determine the total_number of files */ + n_total = g_list_length (job->priv->total_files); + + exo_job_percent (EXO_JOB (job), (n_processed * 100.0) / n_total); + } + } +} diff --git a/thunar/thunar-job.h b/thunar/thunar-job.h new file mode 100644 index 000000000..8ed8a8b03 --- /dev/null +++ b/thunar/thunar-job.h @@ -0,0 +1,94 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_JOB_H__ +#define __THUNAR_JOB_H__ + +#include <gio/gio.h> + +#include <exo/exo.h> + +#include <thunar/thunar-enum-types.h> +#include <thunar/thunar-file.h> + +G_BEGIN_DECLS + +typedef struct _ThunarJobPrivate ThunarJobPrivate; +typedef struct _ThunarJobClass ThunarJobClass; +typedef struct _ThunarJob ThunarJob; + +#define THUNAR_TYPE_JOB (thunar_job_get_type ()) +#define THUNAR_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_JOB, ThunarJob)) +#define THUNAR_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_JOB, ThunarJobClass)) +#define THUNAR_IS_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_JOB)) +#define THUNAR_IS_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_JOB)) +#define THUNAR_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_JOB, ThunarJobClass)) + +struct _ThunarJobClass +{ + /*< private >*/ + ExoJobClass __parent__; + + /*< public >*/ + + /* signals */ + ThunarJobResponse (*ask) (ThunarJob *job, + const gchar *message, + ThunarJobResponse choices); + ThunarJobResponse (*ask_replace) (ThunarJob *job, + ThunarFile *source_file, + ThunarFile *target_file); +}; + +struct _ThunarJob +{ + /*< private >*/ + ExoJob __parent__; + ThunarJobPrivate *priv; +}; + +GType thunar_job_get_type (void) G_GNUC_CONST; +void thunar_job_set_total_files (ThunarJob *job, + GList *total_files); +void thunar_job_processing_file (ThunarJob *job, + GList *current_file); + +ThunarJobResponse thunar_job_ask_create (ThunarJob *job, + const gchar *format, + ...); +ThunarJobResponse thunar_job_ask_overwrite (ThunarJob *job, + const gchar *format, + ...); +ThunarJobResponse thunar_job_ask_replace (ThunarJob *job, + GFile *source_path, + GFile *target_path, + GError **error); +ThunarJobResponse thunar_job_ask_skip (ThunarJob *job, + const gchar *format, + ...); +gboolean thunar_job_files_ready (ThunarJob *job, + GList *file_list); +void thunar_job_new_files (ThunarJob *job, + const GList *file_list); + +G_END_DECLS + +#endif /* !__THUNAR_JOB_H__ */ diff --git a/thunar/thunar-launcher.c b/thunar/thunar-launcher.c index a4e134817..ac167f97d 100644 --- a/thunar/thunar-launcher.c +++ b/thunar/thunar-launcher.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -29,8 +30,10 @@ #endif #include <thunar/thunar-application.h> +#include <thunar/thunar-browser.h> #include <thunar/thunar-chooser-dialog.h> #include <thunar/thunar-dialogs.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-gtk-extensions.h> #include <thunar/thunar-launcher.h> @@ -41,6 +44,11 @@ +typedef struct _ThunarLauncherMountData ThunarLauncherMountData; +typedef struct _ThunarLauncherPokeData ThunarLauncherPokeData; + + + /* Property identifiers */ enum { @@ -53,53 +61,63 @@ enum -static void thunar_launcher_class_init (ThunarLauncherClass *klass); -static void thunar_launcher_component_init (ThunarComponentIface *iface); -static void thunar_launcher_navigator_init (ThunarNavigatorIface *iface); -static void thunar_launcher_init (ThunarLauncher *launcher); -static void thunar_launcher_dispose (GObject *object); -static void thunar_launcher_finalize (GObject *object); -static void thunar_launcher_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void thunar_launcher_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static ThunarFile *thunar_launcher_get_current_directory (ThunarNavigator *navigator); -static void thunar_launcher_set_current_directory (ThunarNavigator *navigator, - ThunarFile *current_directory); -static GList *thunar_launcher_get_selected_files (ThunarComponent *component); -static void thunar_launcher_set_selected_files (ThunarComponent *component, - GList *selected_files); -static GtkUIManager *thunar_launcher_get_ui_manager (ThunarComponent *component); -static void thunar_launcher_set_ui_manager (ThunarComponent *component, - GtkUIManager *ui_manager); -static void thunar_launcher_execute_files (ThunarLauncher *launcher, - GList *files); -static void thunar_launcher_open_files (ThunarLauncher *launcher, - GList *files); -static void thunar_launcher_open_paths (ThunarVfsMimeHandler *mime_handler, - GList *path_list, - ThunarLauncher *launcher); -static void thunar_launcher_open_windows (ThunarLauncher *launcher, - GList *directories); -static void thunar_launcher_update (ThunarLauncher *launcher); -static void thunar_launcher_action_open (GtkAction *action, - ThunarLauncher *launcher); -static void thunar_launcher_action_open_with_other (GtkAction *action, - ThunarLauncher *launcher); -static void thunar_launcher_action_open_in_new_window (GtkAction *action, - ThunarLauncher *launcher); -static void thunar_launcher_action_sendto_desktop (GtkAction *action, - ThunarLauncher *launcher); -static void thunar_launcher_action_sendto_volume (GtkAction *action, - ThunarLauncher *launcher); -static void thunar_launcher_widget_destroyed (ThunarLauncher *launcher, - GtkWidget *widget); -static gboolean thunar_launcher_sendto_idle (gpointer user_data); -static void thunar_launcher_sendto_idle_destroy (gpointer user_data); +static void thunar_launcher_class_init (ThunarLauncherClass *klass); +static void thunar_launcher_component_init (ThunarComponentIface *iface); +static void thunar_launcher_navigator_init (ThunarNavigatorIface *iface); +static void thunar_launcher_init (ThunarLauncher *launcher); +static void thunar_launcher_dispose (GObject *object); +static void thunar_launcher_finalize (GObject *object); +static void thunar_launcher_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void thunar_launcher_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static ThunarFile *thunar_launcher_get_current_directory (ThunarNavigator *navigator); +static void thunar_launcher_set_current_directory (ThunarNavigator *navigator, + ThunarFile *current_directory); +static GList *thunar_launcher_get_selected_files (ThunarComponent *component); +static void thunar_launcher_set_selected_files (ThunarComponent *component, + GList *selected_files); +static GtkUIManager *thunar_launcher_get_ui_manager (ThunarComponent *component); +static void thunar_launcher_set_ui_manager (ThunarComponent *component, + GtkUIManager *ui_manager); +static void thunar_launcher_execute_files (ThunarLauncher *launcher, + GList *files); +static void thunar_launcher_open_files (ThunarLauncher *launcher, + GList *files); +static void thunar_launcher_open_paths (GAppInfo *app_info, + GList *file_list, + ThunarLauncher *launcher); +static void thunar_launcher_open_windows (ThunarLauncher *launcher, + GList *directories); +static void thunar_launcher_update (ThunarLauncher *launcher); +static void thunar_launcher_action_open (GtkAction *action, + ThunarLauncher *launcher); +static void thunar_launcher_action_open_with_other (GtkAction *action, + ThunarLauncher *launcher); +static void thunar_launcher_action_open_in_new_window (GtkAction *action, + ThunarLauncher *launcher); +static void thunar_launcher_action_sendto_desktop (GtkAction *action, + ThunarLauncher *launcher); +static void thunar_launcher_action_sendto_volume (GtkAction *action, + ThunarLauncher *launcher); +static void thunar_launcher_widget_destroyed (ThunarLauncher *launcher, + GtkWidget *widget); +static gboolean thunar_launcher_sendto_idle (gpointer user_data); +static void thunar_launcher_sendto_idle_destroy (gpointer user_data); +static void thunar_launcher_mount_data_free (ThunarLauncherMountData *data); +static void thunar_launcher_poke_files (ThunarLauncher *launcher, + ThunarLauncherPokeData *poke_data); +static void thunar_launcher_poke_files_finish (ThunarBrowser *browser, + ThunarFile *file, + ThunarFile *target_file, + GError *error, + gpointer user_data); +static ThunarLauncherPokeData *thunar_launcher_poke_data_new (GList *files); +static void thunar_launcher_poke_data_free (ThunarLauncherPokeData *data); @@ -128,11 +146,23 @@ struct _ThunarLauncher GtkWidget *widget; - ThunarVfsVolumeManager *sendto_volman; + GVolumeMonitor *volume_monitor; ThunarSendtoModel *sendto_model; gint sendto_idle_id; }; +struct _ThunarLauncherMountData +{ + ThunarLauncher *launcher; + GList *files; +}; + +struct _ThunarLauncherPokeData +{ + GList *files; + GList *resolved_files; +}; + static const GtkActionEntry action_entries[] = @@ -171,6 +201,13 @@ thunar_launcher_get_type (void) NULL, }; + static const GInterfaceInfo browser_info = + { + NULL, + NULL, + NULL + }; + static const GInterfaceInfo component_info = { (GInterfaceInitFunc) thunar_launcher_component_init, @@ -186,6 +223,7 @@ thunar_launcher_get_type (void) }; type = g_type_register_static (G_TYPE_OBJECT, I_("ThunarLauncher"), &info, 0); + g_type_add_interface_static (type, THUNAR_TYPE_BROWSER, &browser_info); g_type_add_interface_static (type, THUNAR_TYPE_NAVIGATOR, &navigator_info); g_type_add_interface_static (type, THUNAR_TYPE_COMPONENT, &component_info); } @@ -276,10 +314,10 @@ thunar_launcher_init (ThunarLauncher *launcher) /* setup the "Send To" support */ launcher->sendto_model = thunar_sendto_model_get_default (); - /* the "Send To" menu also displays removable devices from the volume manager */ - launcher->sendto_volman = thunar_vfs_volume_manager_get_default (); - g_signal_connect_swapped (G_OBJECT (launcher->sendto_volman), "volumes-added", G_CALLBACK (thunar_launcher_update), launcher); - g_signal_connect_swapped (G_OBJECT (launcher->sendto_volman), "volumes-removed", G_CALLBACK (thunar_launcher_update), launcher); + /* the "Send To" menu also displays removable devices from the volume monitor */ + launcher->volume_monitor = g_volume_monitor_get (); + g_signal_connect_swapped (launcher->volume_monitor, "volume-added", G_CALLBACK (thunar_launcher_update), launcher); + g_signal_connect_swapped (launcher->volume_monitor, "volume-removed", G_CALLBACK (thunar_launcher_update), launcher); } @@ -314,17 +352,17 @@ thunar_launcher_finalize (GObject *object) /* drop our custom icon factory for the application/action icons */ gtk_icon_factory_remove_default (launcher->icon_factory); - g_object_unref (G_OBJECT (launcher->icon_factory)); + g_object_unref (launcher->icon_factory); /* release the reference on the action group */ - g_object_unref (G_OBJECT (launcher->action_group)); + g_object_unref (launcher->action_group); - /* disconnect from the volume manager used for the "Send To" menu */ - g_signal_handlers_disconnect_by_func (G_OBJECT (launcher->sendto_volman), thunar_launcher_update, launcher); - g_object_unref (G_OBJECT (launcher->sendto_volman)); + /* disconnect from the volume monitor used for the "Send To" menu */ + g_signal_handlers_disconnect_by_func (launcher->volume_monitor, thunar_launcher_update, launcher); + g_object_unref (launcher->volume_monitor); /* release the reference on the sendto model */ - g_object_unref (G_OBJECT (launcher->sendto_model)); + g_object_unref (launcher->sendto_model); (*G_OBJECT_CLASS (thunar_launcher_parent_class)->finalize) (object); } @@ -561,44 +599,38 @@ static void thunar_launcher_open_files (ThunarLauncher *launcher, GList *files) { - ThunarVfsMimeApplication *application; - ThunarVfsMimeDatabase *database; - ThunarVfsMimeInfo *info; - GHashTable *applications; - GList *path_list; - GList *lp; + GAppInfo *app_info; + GHashTable *applications; + GList *file_list; + GList *lp; /* allocate a hash table to associate applications to URIs */ - applications = g_hash_table_new_full (thunar_vfs_mime_application_hash, - thunar_vfs_mime_application_equal, + applications = g_hash_table_new_full (g_direct_hash, + (GEqualFunc) g_app_info_equal, (GDestroyNotify) g_object_unref, - (GDestroyNotify) thunar_vfs_path_list_free); - - /* take a reference on the mime database */ - database = thunar_vfs_mime_database_get_default (); + (GDestroyNotify) thunar_g_file_list_free); for (lp = files; lp != NULL; lp = lp->next) { /* determine the default application for the MIME type */ - info = thunar_file_get_mime_info (lp->data); - application = thunar_vfs_mime_database_get_default_application (database, info); + app_info = thunar_file_get_default_handler (lp->data); /* check if we have an application here */ - if (G_LIKELY (application != NULL)) + if (G_LIKELY (app_info != NULL)) { /* check if we have that application already */ - path_list = g_hash_table_lookup (applications, application); - if (G_LIKELY (path_list != NULL)) + file_list = g_hash_table_lookup (applications, app_info); + if (G_LIKELY (file_list != NULL)) { /* take a copy of the list as the old one will be dropped by the insert */ - path_list = thunar_vfs_path_list_copy (path_list); + file_list = thunar_g_file_list_copy (file_list); } /* append our new URI to the list */ - path_list = thunar_vfs_path_list_append (path_list, thunar_file_get_path (lp->data)); + file_list = thunar_g_file_list_append (file_list, thunar_file_get_file (lp->data)); /* (re)insert the URI list for the application */ - g_hash_table_insert (applications, application, path_list); + g_hash_table_insert (applications, app_info, file_list); } else { @@ -611,9 +643,6 @@ thunar_launcher_open_files (ThunarLauncher *launcher, /* run all collected applications */ g_hash_table_foreach (applications, (GHFunc) thunar_launcher_open_paths, launcher); - /* release the reference on the mime database */ - g_object_unref (G_OBJECT (database)); - /* drop the applications hash table */ g_hash_table_destroy (applications); } @@ -621,28 +650,33 @@ thunar_launcher_open_files (ThunarLauncher *launcher, static void -thunar_launcher_open_paths (ThunarVfsMimeHandler *mime_handler, - GList *path_list, - ThunarLauncher *launcher) +thunar_launcher_open_paths (GAppInfo *app_info, + GList *path_list, + ThunarLauncher *launcher) { - GdkScreen *screen; - GError *error = NULL; - gchar *message; - gchar *name; - guint n; + GdkAppLaunchContext *context; + GdkScreen *screen; + GError *error = NULL; + gchar *message; + gchar *name; + guint n; /* determine the screen on which to launch the application */ screen = (launcher->widget != NULL) ? gtk_widget_get_screen (launcher->widget) : NULL; + /* create launch context */ + context = gdk_app_launch_context_new (); + gdk_app_launch_context_set_screen (context, screen); + /* try to execute the application with the given URIs */ - if (!thunar_vfs_mime_handler_exec (mime_handler, screen, path_list, &error)) + if (!g_app_info_launch (app_info, path_list, G_APP_LAUNCH_CONTEXT (context), &error)) { /* figure out the appropriate error message */ n = g_list_length (path_list); if (G_LIKELY (n == 1)) { /* we can give a precise error message here */ - name = g_filename_display_name (thunar_vfs_path_get_name (path_list->data)); + name = g_filename_display_name (g_file_get_basename (path_list->data)); message = g_strdup_printf (_("Failed to open file \"%s\""), name); g_free (name); } @@ -657,6 +691,9 @@ thunar_launcher_open_paths (ThunarVfsMimeHandler *mime_handler, g_error_free (error); g_free (message); } + + /* destroy the launch context */ + g_object_unref (context); } @@ -711,7 +748,7 @@ thunar_launcher_open_windows (ThunarLauncher *launcher, /* open all requested windows */ for (lp = directories; lp != NULL; lp = lp->next) - thunar_application_open_window (application, lp->data, screen); + thunar_application_open_window (application, lp->data, screen, NULL); /* release the application object */ g_object_unref (G_OBJECT (application)); @@ -723,10 +760,10 @@ thunar_launcher_open_windows (ThunarLauncher *launcher, static void thunar_launcher_update (ThunarLauncher *launcher) { - GtkIconTheme *icon_theme; - const gchar *icon_name; const gchar *context_menu_path; const gchar *file_menu_path; + GtkWidget *menu_item; + GtkWidget *image; GtkAction *action; gboolean default_is_open_with_other = FALSE; GList *applications; @@ -735,6 +772,7 @@ thunar_launcher_update (ThunarLauncher *launcher) gchar *tooltip; gchar *label; gchar *name; + gchar *ui_path; gint n_directories = 0; gint n_executables = 0; gint n_regulars = 0; @@ -863,10 +901,10 @@ thunar_launcher_update (ThunarLauncher *launcher) else if (G_LIKELY (applications != NULL)) { /* turn the "Open" action into "Open With DEFAULT" */ - label = g_strdup_printf (_("_Open With \"%s\""), thunar_vfs_mime_application_get_name (applications->data)); + label = g_strdup_printf (_("_Open With \"%s\""), g_app_info_get_name (applications->data)); tooltip = g_strdup_printf (ngettext ("Use \"%s\" to open the selected file", "Use \"%s\" to open the selected files", - n_selected_files), thunar_vfs_mime_application_get_name (applications->data)); + n_selected_files), g_app_info_get_name (applications->data)); g_object_set (G_OBJECT (launcher->action_open), "label", label, "tooltip", tooltip, @@ -877,8 +915,8 @@ thunar_launcher_update (ThunarLauncher *launcher) /* remember the default application for the "Open" action */ g_object_set_qdata_full (G_OBJECT (launcher->action_open), thunar_launcher_handler_quark, applications->data, g_object_unref); - /* add the desktop actions for this application */ - actions = g_list_concat (actions, thunar_vfs_mime_application_get_actions (applications->data)); + /* FIXME Add the desktop actions for this application. + * Unfortunately this is not supported by GIO directly */ /* drop the default application from the list */ applications = g_list_remove (applications, applications->data); @@ -938,32 +976,24 @@ thunar_launcher_update (ThunarLauncher *launcher) gtk_action_set_visible (launcher->action_open_with_other_in_menu, FALSE); } - /* determine a the default icon theme for application/action icon lookups */ - icon_theme = gtk_icon_theme_get_default (); - /* add actions for all remaining applications */ if (G_LIKELY (applications != NULL)) { /* process all applications and determine the desktop actions */ for (lp = applications, n = 0; lp != NULL; lp = lp->next, ++n) { - /* determine the desktop actions for this application */ - actions = g_list_concat (actions, thunar_vfs_mime_application_get_actions (lp->data)); + /* FIXME Determine the desktop actions for this application. + * Unfortunately this is not supported by GIO directly. */ /* generate a unique label, unique id and tooltip for the application's action */ name = g_strdup_printf ("thunar-launcher-addon-application%d-%p", n, launcher); - label = g_strdup_printf (_("Open With \"%s\""), thunar_vfs_mime_application_get_name (lp->data)); + label = g_strdup_printf (_("Open With \"%s\""), g_app_info_get_name (lp->data)); tooltip = g_strdup_printf (ngettext ("Use \"%s\" to open the selected file", "Use \"%s\" to open the selected files", - n_selected_files), thunar_vfs_mime_application_get_name (lp->data)); - - /* check if we have an icon for this application */ - icon_name = thunar_vfs_mime_handler_lookup_icon_name (lp->data, icon_theme); - if (G_LIKELY (icon_name != NULL)) - thunar_gtk_icon_factory_insert_icon (launcher->icon_factory, name, icon_name); + n_selected_files), g_app_info_get_name (lp->data)); /* allocate a new action for the application */ - action = gtk_action_new (name, label, tooltip, (icon_name != NULL) ? name : NULL); + action = gtk_action_new (name, label, tooltip, NULL); gtk_action_group_add_action (launcher->action_group, action); g_object_set_qdata_full (G_OBJECT (action), thunar_launcher_handler_quark, lp->data, g_object_unref); g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (thunar_launcher_action_open), launcher); @@ -975,6 +1005,23 @@ thunar_launcher_update (ThunarLauncher *launcher) GTK_UI_MANAGER_MENUITEM, FALSE); g_object_unref (G_OBJECT (action)); + /* FIXME There's no API for creating GtkActions using GIcon in GTK+ 2.14. A "gicon" property + * has been added to GtkAction in GTK+ 2.16 though. For now, this hack will have to do: */ + + ui_path = g_strconcat (file_menu_path, "/", name, NULL); + menu_item = gtk_ui_manager_get_widget (launcher->ui_manager, ui_path); + image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menu_item)); + gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (lp->data), GTK_ICON_SIZE_MENU); + g_free (ui_path); + + ui_path = g_strconcat (context_menu_path, "/", name, NULL); + menu_item = gtk_ui_manager_get_widget (launcher->ui_manager, ui_path); + image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menu_item)); + gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (lp->data), GTK_ICON_SIZE_MENU); + g_free (ui_path); + + /* FIXME End of the hack */ + /* cleanup */ g_free (tooltip); g_free (label); @@ -985,48 +1032,8 @@ thunar_launcher_update (ThunarLauncher *launcher) g_list_free (applications); } - /* check if we have any desktop actions */ - if (G_UNLIKELY (actions != NULL)) - { - /* add separator before the desktop actions */ - gtk_ui_manager_add_ui (launcher->ui_manager, launcher->ui_addons_merge_id, - "/main-menu/file-menu/placeholder-launcher/placeholder-actions", - "separator", NULL, GTK_UI_MANAGER_SEPARATOR, FALSE); - gtk_ui_manager_add_ui (launcher->ui_manager, launcher->ui_addons_merge_id, - "/file-context-menu/placeholder-launcher/placeholder-actions", - "separator", NULL, GTK_UI_MANAGER_SEPARATOR, FALSE); - - /* process all actions and add them to the UI manager */ - for (lp = actions, n = 0; lp != NULL; lp = lp->next, ++n) - { - /* generate a unique name for the mime action */ - name = g_strdup_printf ("thunar-launcher-addon-action%d-%p", n, launcher); - - /* check if we have an icon for this action */ - icon_name = thunar_vfs_mime_handler_lookup_icon_name (lp->data, icon_theme); - if (G_LIKELY (icon_name != NULL)) - thunar_gtk_icon_factory_insert_icon (launcher->icon_factory, name, icon_name); - - /* allocate a new ui action for the mime action */ - action = gtk_action_new (name, thunar_vfs_mime_handler_get_name (lp->data), NULL, (icon_name != NULL) ? name : NULL); - gtk_action_group_add_action (launcher->action_group, action); - g_object_set_qdata_full (G_OBJECT (action), thunar_launcher_handler_quark, lp->data, g_object_unref); - g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (thunar_launcher_action_open), launcher); - gtk_ui_manager_add_ui (launcher->ui_manager, launcher->ui_addons_merge_id, - "/main-menu/file-menu/placeholder-launcher/placeholder-actions", - name, name, GTK_UI_MANAGER_MENUITEM, FALSE); - gtk_ui_manager_add_ui (launcher->ui_manager, launcher->ui_addons_merge_id, - "/file-context-menu/placeholder-launcher/placeholder-actions", - name, name, GTK_UI_MANAGER_MENUITEM, FALSE); - g_object_unref (G_OBJECT (action)); - - /* cleanup */ - g_free (name); - } - - /* cleanup */ - g_list_free (actions); - } + /* FIXME Add desktop actions here. Unfortunately they are not supported by + * GIO, so we'll have to roll our own thing here */ } /* schedule an update of the "Send To" menu */ @@ -1040,60 +1047,129 @@ thunar_launcher_update (ThunarLauncher *launcher) static void -thunar_launcher_action_open (GtkAction *action, - ThunarLauncher *launcher) +thunar_launcher_open_file (ThunarLauncher *launcher, + ThunarFile *file) { - ThunarVfsMimeHandler *mime_handler; - GdkScreen *screen; - gboolean executable = TRUE; - GList *selected_paths; - GList *directories = NULL; - GList *files = NULL; - GList *lp; + GList files; - _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_LAUNCHER (launcher)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + files.data = file; + files.next = NULL; + files.prev = NULL; - /* determine the screen on which to open the new windows */ - screen = (launcher->widget != NULL) ? gtk_widget_get_screen (launcher->widget) : NULL; - - /* check if we have a mime handler associated with the action */ - mime_handler = g_object_get_qdata (G_OBJECT (action), thunar_launcher_handler_quark); - if (G_LIKELY (mime_handler != NULL)) - { - /* try to open the selected files using the given application */ - selected_paths = thunar_file_list_to_path_list (launcher->selected_files); - thunar_launcher_open_paths (mime_handler, selected_paths, launcher); - thunar_vfs_path_list_free (selected_paths); - } - else if (g_list_length (launcher->selected_files) == 1 && thunar_file_is_directory (launcher->selected_files->data)) + if (thunar_file_is_directory (file)) { /* check if we're in a regular view (i.e. current_directory is set) */ if (G_LIKELY (launcher->current_directory != NULL)) { /* we want to open one directory, so just emit "change-directory" here */ - thunar_navigator_change_directory (THUNAR_NAVIGATOR (launcher), launcher->selected_files->data); + thunar_navigator_change_directory (THUNAR_NAVIGATOR (launcher), file); + } + else + { + /* open the selected directory in a new window */ + thunar_launcher_open_windows (launcher, &files); + } + } + else + { + if (thunar_file_is_executable (file)) + { + /* try to execute the file */ + thunar_launcher_execute_files (launcher, &files); } else { - /* open the selected directories in new windows */ - thunar_launcher_open_windows (launcher, launcher->selected_files); + /* try to open the file using its default application */ + thunar_launcher_open_files (launcher, &files); } } +} + + + +static void +thunar_launcher_poke_file_finish (ThunarBrowser *browser, + ThunarFile *file, + ThunarFile *target_file, + GError *error, + gpointer ignored) +{ + if (error == NULL) + { + thunar_launcher_open_file (THUNAR_LAUNCHER (browser), target_file); + } else + { + thunar_dialogs_show_error (THUNAR_LAUNCHER (browser)->widget, error, + _("Failed to open \"%s\""), + thunar_file_get_display_name (file)); + } +} + + + +static void +thunar_launcher_poke_files (ThunarLauncher *launcher, + ThunarLauncherPokeData *poke_data) +{ + _thunar_return_if_fail (THUNAR_IS_LAUNCHER (launcher)); + _thunar_return_if_fail (poke_data != NULL); + _thunar_return_if_fail (poke_data->files != NULL); + + thunar_browser_poke_file (THUNAR_BROWSER (launcher), poke_data->files->data, + launcher->widget, thunar_launcher_poke_files_finish, + poke_data); +} + + + +static void +thunar_launcher_poke_files_finish (ThunarBrowser *browser, + ThunarFile *file, + ThunarFile *target_file, + GError *error, + gpointer user_data) +{ + ThunarLauncherPokeData *poke_data = user_data; + gboolean executable = TRUE; + GList *directories = NULL; + GList *files = NULL; + GList *lp; + + _thunar_return_if_fail (THUNAR_IS_BROWSER (browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + _thunar_return_if_fail (poke_data != NULL); + _thunar_return_if_fail (poke_data->files != NULL); + + /* check if poking succeeded */ + if (error == NULL) + { + /* add the resolved file to the list of file to be opened/executed later */ + poke_data->resolved_files = g_list_prepend (poke_data->resolved_files, + g_object_ref (target_file)); + } + + /* release and remove the just poked file from the list */ + g_object_unref (poke_data->files->data); + poke_data->files = g_list_delete_link (poke_data->files, poke_data->files); + + if (poke_data->files == NULL) { /* separate files and directories in the selected files list */ - for (lp = launcher->selected_files; lp != NULL; lp = lp->next) + for (lp = poke_data->resolved_files; lp != NULL; lp = lp->next) { if (thunar_file_is_directory (lp->data)) { /* add to our directory list */ - directories = g_list_append (directories, lp->data); + directories = g_list_prepend (directories, lp->data); } else { /* add to our file list */ - files = g_list_append (files, lp->data); + files = g_list_prepend (files, lp->data); /* check if the file is executable */ executable = (executable && thunar_file_is_executable (lp->data)); @@ -1104,7 +1180,7 @@ thunar_launcher_action_open (GtkAction *action, if (G_LIKELY (directories != NULL)) { /* open new windows for all directories */ - thunar_launcher_open_windows (launcher, directories); + thunar_launcher_open_windows (THUNAR_LAUNCHER (browser), directories); g_list_free (directories); } @@ -1115,17 +1191,63 @@ thunar_launcher_action_open (GtkAction *action, if (G_UNLIKELY (executable)) { /* try to execute all given files */ - thunar_launcher_execute_files (launcher, files); + thunar_launcher_execute_files (THUNAR_LAUNCHER (browser), files); } else { /* try to open all files using their default applications */ - thunar_launcher_open_files (launcher, files); + thunar_launcher_open_files (THUNAR_LAUNCHER (browser), files); } /* cleanup */ g_list_free (files); } + + /* free all files allocated for the poke data */ + thunar_launcher_poke_data_free (poke_data); + } + else + { + /* we need to continue this until all files have been resolved */ + thunar_launcher_poke_files (THUNAR_LAUNCHER (browser), poke_data); + } +} + + + +static void +thunar_launcher_action_open (GtkAction *action, + ThunarLauncher *launcher) +{ + ThunarLauncherPokeData *poke_data; + GAppInfo *app_info; + GList *selected_paths; + + _thunar_return_if_fail (GTK_IS_ACTION (action)); + _thunar_return_if_fail (THUNAR_IS_LAUNCHER (launcher)); + + /* check if we have a mime handler associated with the action */ + app_info = g_object_get_qdata (G_OBJECT (action), thunar_launcher_handler_quark); + if (G_LIKELY (app_info != NULL)) + { + /* try to open the selected files using the given application */ + selected_paths = thunar_file_list_to_thunar_g_file_list (launcher->selected_files); + thunar_launcher_open_paths (app_info, selected_paths, launcher); + thunar_g_file_list_free (selected_paths); + } + else if (g_list_length (launcher->selected_files) == 1) + { + thunar_browser_poke_file (THUNAR_BROWSER (launcher), + launcher->selected_files->data, launcher->widget, + thunar_launcher_poke_file_finish, NULL); + } + else + { + /* resolve files one after another until none is left. Open/execute + * the resolved files/directories when all this is done at a later + * stage */ + poke_data = thunar_launcher_poke_data_new (launcher->selected_files); + thunar_launcher_poke_files (launcher, poke_data); } } @@ -1166,44 +1288,152 @@ thunar_launcher_action_sendto_desktop (GtkAction *action, ThunarLauncher *launcher) { ThunarApplication *application; - ThunarVfsPath *desktop_path; - ThunarVfsPath *home_path; - GList *paths; - gchar *str_desktop_path = NULL; + GFile *desktop_file; + GList *files; _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_LAUNCHER (launcher)); - /* determine the source paths */ - paths = thunar_file_list_to_path_list (launcher->selected_files); - if (G_UNLIKELY (paths == NULL)) + /* determine the source files */ + files = thunar_file_list_to_thunar_g_file_list (launcher->selected_files); + if (G_UNLIKELY (files == NULL)) return; - /* determine the path to the ~/Desktop folder */ - home_path = thunar_vfs_path_get_for_home (); -#if GLIB_CHECK_VERSION(2,14,0) - str_desktop_path = g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)); -#else /* GLIB_CHECK_VERSION(2,14,0) */ - str_desktop_path = g_build_filename (G_DIR_SEPARATOR_S, xfce_get_homedir (), - "Desktop", NULL); -#endif /* GLIB_CHECK_VERSION(2,14,0) */ - - desktop_path = thunar_vfs_path_new (str_desktop_path, NULL); - - if (G_UNLIKELY (desktop_path == NULL)) - desktop_path = thunar_vfs_path_relative (home_path, "Desktop"); - - thunar_vfs_path_unref (home_path); - g_free (str_desktop_path); + /* determine the file to the ~/Desktop folder */ + desktop_file = thunar_g_file_new_for_desktop (); /* launch the link job */ application = thunar_application_get (); - thunar_application_link_into (application, launcher->widget, paths, desktop_path, NULL); + thunar_application_link_into (application, launcher->widget, files, desktop_file, NULL); g_object_unref (G_OBJECT (application)); /* cleanup */ - thunar_vfs_path_unref (desktop_path); - thunar_vfs_path_list_free (paths); + g_object_unref (desktop_file); + thunar_g_file_list_free (files); +} + + + +static ThunarLauncherMountData * +thunar_launcher_mount_data_new (ThunarLauncher *launcher, + GList *files) +{ + ThunarLauncherMountData *data; + + _thunar_return_val_if_fail (THUNAR_IS_LAUNCHER (launcher), NULL); + + data = _thunar_slice_new0 (ThunarLauncherMountData); + data->launcher = g_object_ref (launcher); + data->files = thunar_g_file_list_copy (files); + + return data; +} + + + +static void +thunar_launcher_mount_data_free (ThunarLauncherMountData *data) +{ + _thunar_return_if_fail (data != NULL); + _thunar_return_if_fail (THUNAR_IS_LAUNCHER (data->launcher)); + + g_object_unref (data->launcher); + thunar_g_file_list_free (data->files); + _thunar_slice_free (ThunarLauncherMountData, data); +} + + + +static ThunarLauncherPokeData * +thunar_launcher_poke_data_new (GList *files) +{ + ThunarLauncherPokeData *data; + + data = _thunar_slice_new0 (ThunarLauncherPokeData); + data->files = thunar_file_list_copy (files); + data->resolved_files = NULL; + + return data; +} + + + +static void +thunar_launcher_poke_data_free (ThunarLauncherPokeData *data) +{ + _thunar_return_if_fail (data != NULL); + + thunar_file_list_free (data->files); + thunar_file_list_free (data->resolved_files); + _thunar_slice_free (ThunarLauncherPokeData, data); +} + + + +static void +thunar_launcher_sendto_volume (ThunarLauncher *launcher, + GVolume *volume, + GList *files) +{ + ThunarApplication *application; + GMount *mount; + GFile *mount_point; + + _thunar_return_if_fail (THUNAR_IS_LAUNCHER (launcher)); + _thunar_return_if_fail (G_IS_VOLUME (volume)); + + if (!thunar_g_volume_is_mounted (volume)) + return; + + mount = g_volume_get_mount (volume); + if (mount != NULL) + { + mount_point = g_mount_get_root (mount); + + /* copy the files onto the specified volume */ + application = thunar_application_get (); + thunar_application_copy_into (application, launcher->widget, files, mount_point, NULL); + g_object_unref (application); + + g_object_unref (mount_point); + g_object_unref (mount); + } +} + + + +static void +thunar_launcher_sendto_mount_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + ThunarLauncherMountData *data = user_data; + GVolume *volume = G_VOLUME (object); + GError *error = NULL; + gchar *volume_name; + + _thunar_return_if_fail (G_IS_VOLUME (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (user_data != NULL); + _thunar_return_if_fail (THUNAR_IS_LAUNCHER (data->launcher)); + + if (!g_volume_mount_finish (volume, result, &error)) + { + /* tell the user that we were unable to mount the volume, which is + * required to send files to it */ + volume_name = g_volume_get_name (volume); + thunar_dialogs_show_error (data->launcher->widget, error, _("Failed to mount \"%s\""), + volume_name); + g_free (volume_name); + + g_error_free (error); + } + else + { + thunar_launcher_sendto_volume (data->launcher, volume, data->files); + } + + thunar_launcher_mount_data_free (data); } @@ -1212,17 +1442,18 @@ static void thunar_launcher_action_sendto_volume (GtkAction *action, ThunarLauncher *launcher) { - ThunarApplication *application; - ThunarVfsVolume *volume; - GError *err = NULL; - GList *paths; + ThunarLauncherMountData *data; + GMountOperation *mount_operation; + GtkWidget *window; + GVolume *volume; + GList *files; _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_LAUNCHER (launcher)); /* determine the source paths */ - paths = thunar_file_list_to_path_list (launcher->selected_files); - if (G_UNLIKELY (paths == NULL)) + files = thunar_file_list_to_thunar_g_file_list (launcher->selected_files); + if (G_UNLIKELY (files == NULL)) return; /* determine the volume to which to send */ @@ -1231,23 +1462,28 @@ thunar_launcher_action_sendto_volume (GtkAction *action, return; /* make sure to mount the volume first, if it's not already mounted */ - if (!thunar_vfs_volume_is_mounted (volume) && - !thunar_vfs_volume_mount (volume, launcher->widget, &err)) + if (!thunar_g_volume_is_mounted (volume)) { - /* tell the user that we were unable to mount the volume, which is required to send files to it */ - thunar_dialogs_show_error (launcher->widget, err, _("Failed to mount \"%s\""), thunar_vfs_volume_get_name (volume)); - g_error_free (err); + /* determine the toplevel window */ + window = gtk_widget_get_toplevel (launcher->widget); + + /* allocate mount data */ + data = thunar_launcher_mount_data_new (launcher, files); + + /* allocate a GTK+ mount operation */ + mount_operation = gtk_mount_operation_new (GTK_WINDOW (window)); + + /* try to mount the volume and later start sending the files */ + g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_operation, NULL, + thunar_launcher_sendto_mount_finish, data); } else { - /* copy the files onto the specified volume */ - application = thunar_application_get (); - thunar_application_copy_into (application, launcher->widget, paths, thunar_vfs_volume_get_mount_point (volume), NULL); - g_object_unref (G_OBJECT (application)); + thunar_launcher_sendto_volume (launcher, volume, files); } /* cleanup */ - thunar_vfs_path_list_free (paths); + thunar_g_file_list_free (files); } @@ -1270,16 +1506,19 @@ static gboolean thunar_launcher_sendto_idle (gpointer user_data) { ThunarLauncher *launcher = THUNAR_LAUNCHER (user_data); - GtkIconTheme *icon_theme; - const gchar *icon_name; const gchar *label; GtkAction *action; + GtkWidget *image; + GtkWidget *menu_item; gboolean linkable = TRUE; + GIcon *icon; GList *handlers; GList *volumes; GList *lp; gchar *name; gchar *tooltip; + gchar *ui_path; + gchar *volume_name; gint n_selected_files; gint n = 0; @@ -1319,55 +1558,74 @@ thunar_launcher_sendto_idle (gpointer user_data) gtk_action_group_remove_action (launcher->action_group, lp->data); g_list_free (handlers); - /* determine a the default icon theme for handler icon lookups */ - icon_theme = gtk_icon_theme_get_default (); - /* allocate a new merge id from the UI manager (if not already done) */ if (G_UNLIKELY (launcher->ui_addons_merge_id == 0)) launcher->ui_addons_merge_id = gtk_ui_manager_new_merge_id (launcher->ui_manager); /* determine the currently active volumes */ - volumes = thunar_vfs_volume_manager_get_volumes (launcher->sendto_volman); - if (G_LIKELY (volumes != NULL)) + volumes = g_volume_monitor_get_volumes (launcher->volume_monitor); + + /* add removable (and writable) drives and media */ + for (lp = volumes; lp != NULL; lp = lp->next, ++n) { - /* add removable (and writable) drives and media */ - for (lp = volumes; lp != NULL; lp = lp->next, ++n) + /* skip non-removable or disc media (CD-ROMs aren't writable by Thunar) */ + /* TODO skip non-writable volumes like CD-ROMs here */ + if (!thunar_g_volume_is_removable (lp->data)) { - /* skip non-removable or disc media (CD-ROMs aren't writable by Thunar) */ - if (!thunar_vfs_volume_is_removable (lp->data) || thunar_vfs_volume_is_disc (lp->data)) - continue; - - /* generate a unique name and tooltip for the volume */ - label = thunar_vfs_volume_get_name (lp->data); - name = g_strdup_printf ("thunar-launcher-sendto%d-%p", n, launcher); - tooltip = g_strdup_printf (ngettext ("Send the selected file to \"%s\"", - "Send the selected files to \"%s\"", - n_selected_files), label); - - /* check if we have an icon for this volume */ - icon_name = thunar_vfs_volume_lookup_icon_name (lp->data, icon_theme); - if (G_LIKELY (icon_name != NULL)) - thunar_gtk_icon_factory_insert_icon (launcher->icon_factory, name, icon_name); + g_object_unref (lp->data); + continue; + } - /* allocate a new action for the volume */ - action = gtk_action_new (name, label, tooltip, (icon_name != NULL) ? name : NULL); - g_object_set_qdata_full (G_OBJECT (action), thunar_launcher_handler_quark, g_object_ref (G_OBJECT (lp->data)), g_object_unref); - g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (thunar_launcher_action_sendto_volume), launcher); - gtk_action_group_add_action (launcher->action_group, action); - gtk_ui_manager_add_ui (launcher->ui_manager, launcher->ui_addons_merge_id, - "/main-menu/file-menu/sendto-menu/placeholder-sendto-actions", - name, name, GTK_UI_MANAGER_MENUITEM, FALSE); - gtk_ui_manager_add_ui (launcher->ui_manager, launcher->ui_addons_merge_id, - "/file-context-menu/sendto-menu/placeholder-sendto-actions", - name, name, GTK_UI_MANAGER_MENUITEM, FALSE); - g_object_unref (G_OBJECT (action)); + /* generate a unique name and tooltip for the volume */ + volume_name = g_volume_get_name (lp->data); + name = g_strdup_printf ("thunar-launcher-sendto%d-%p", n, launcher); + tooltip = g_strdup_printf (ngettext ("Send the selected file to \"%s\"", + "Send the selected files to \"%s\"", + n_selected_files), volume_name); + + /* allocate a new action for the volume */ + action = gtk_action_new (name, volume_name, tooltip, NULL); + g_object_set_qdata_full (G_OBJECT (action), thunar_launcher_handler_quark, lp->data, g_object_unref); + g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (thunar_launcher_action_sendto_volume), launcher); + gtk_action_group_add_action (launcher->action_group, action); + gtk_ui_manager_add_ui (launcher->ui_manager, launcher->ui_addons_merge_id, + "/main-menu/file-menu/sendto-menu/placeholder-sendto-actions", + name, name, GTK_UI_MANAGER_MENUITEM, FALSE); + gtk_ui_manager_add_ui (launcher->ui_manager, launcher->ui_addons_merge_id, + "/file-context-menu/sendto-menu/placeholder-sendto-actions", + name, name, GTK_UI_MANAGER_MENUITEM, FALSE); + g_object_unref (action); + + /* FIXME There's no API for creating GtkActions using GIcon in GTK+ 2.14. A "gicon" property + * has been added to GtkAction in GTK+ 2.16 though. For now, this hack will have to do: */ + + ui_path = g_strconcat ("/main-menu/file-menu/sendto-menu/placeholder-sendto-actions/", name, NULL); + menu_item = gtk_ui_manager_get_widget (launcher->ui_manager, ui_path); + image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menu_item)); + icon = g_volume_get_icon (lp->data); + gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU); + g_object_unref (icon); + g_free (ui_path); + + ui_path = g_strconcat ("/file-context-menu/sendto-menu/placeholder-sendto-actions/", name, NULL); + menu_item = gtk_ui_manager_get_widget (launcher->ui_manager, ui_path); + image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menu_item)); + icon = g_volume_get_icon (lp->data); + gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU); + g_object_unref (icon); + g_free (ui_path); + + /* FIXME End of the hack */ - /* cleanup */ - g_free (tooltip); - g_free (name); - } + /* cleanup */ + g_free (name); + g_free (tooltip); + g_free (volume_name); } + /* free the volumes list */ + g_list_free (volumes); + /* determine the sendto handlers for the selected files */ handlers = thunar_sendto_model_get_matching (launcher->sendto_model, launcher->selected_files); if (G_LIKELY (handlers != NULL)) @@ -1376,19 +1634,14 @@ thunar_launcher_sendto_idle (gpointer user_data) for (lp = handlers; lp != NULL; lp = lp->next, ++n) { /* generate a unique name and tooltip for the handler */ - label = thunar_vfs_mime_handler_get_name (lp->data); + label = g_app_info_get_name (lp->data); name = g_strdup_printf ("thunar-launcher-sendto%d-%p", n, launcher); tooltip = g_strdup_printf (ngettext ("Send the selected file to \"%s\"", "Send the selected files to \"%s\"", n_selected_files), label); - /* check if we have an icon for this handler */ - icon_name = thunar_vfs_mime_handler_lookup_icon_name (lp->data, icon_theme); - if (G_LIKELY (icon_name != NULL)) - thunar_gtk_icon_factory_insert_icon (launcher->icon_factory, name, icon_name); - /* allocate a new action for the handler */ - action = gtk_action_new (name, label, tooltip, (icon_name != NULL) ? name : NULL); + action = gtk_action_new (name, label, tooltip, NULL); g_object_set_qdata_full (G_OBJECT (action), thunar_launcher_handler_quark, lp->data, g_object_unref); g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (thunar_launcher_action_open), launcher); gtk_action_group_add_action (launcher->action_group, action); @@ -1400,6 +1653,23 @@ thunar_launcher_sendto_idle (gpointer user_data) name, name, GTK_UI_MANAGER_MENUITEM, FALSE); g_object_unref (G_OBJECT (action)); + /* FIXME There's no API for creating GtkActions using GIcon in GTK+ 2.14. A "gicon" property + * has been added to GtkAction in GTK+ 2.16 though. For now, this hack will have to do: */ + + ui_path = g_strconcat ("/main-menu/file-menu/sendto-menu/placeholder-sendto-actions/", name, NULL); + menu_item = gtk_ui_manager_get_widget (launcher->ui_manager, ui_path); + image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menu_item)); + gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (lp->data), GTK_ICON_SIZE_MENU); + g_free (ui_path); + + ui_path = g_strconcat ("/file-context-menu/sendto-menu/placeholder-sendto-actions/", name, NULL); + menu_item = gtk_ui_manager_get_widget (launcher->ui_manager, ui_path); + image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menu_item)); + gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (lp->data), GTK_ICON_SIZE_MENU); + g_free (ui_path); + + /* FIXME End of the hack */ + /* cleanup */ g_free (tooltip); g_free (name); diff --git a/thunar/thunar-list-model.c b/thunar/thunar-list-model.c index d1b1f2bde..c8f02f508 100644 --- a/thunar/thunar-list-model.c +++ b/thunar/thunar-list-model.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2004-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -28,10 +29,12 @@ #include <string.h> #endif +#include <thunar/thunar-application.h> #include <thunar/thunar-file-monitor.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-list-model.h> #include <thunar/thunar-private.h> +#include <thunar/thunar-user.h> @@ -224,8 +227,6 @@ struct _ThunarListModel */ ThunarFileMonitor *file_monitor; - ThunarVfsVolumeManager *volume_manager; - /* ids for the "row-inserted" and "row-deleted" signals * of GtkTreeModel to speed up folder changing. */ @@ -467,8 +468,6 @@ thunar_list_model_init (ThunarListModel *store) store->stamp = g_random_int (); #endif - store->volume_manager = thunar_vfs_volume_manager_get_default (); - store->row_inserted_id = g_signal_lookup ("row-inserted", GTK_TYPE_TREE_MODEL); store->row_deleted_id = g_signal_lookup ("row-deleted", GTK_TYPE_TREE_MODEL); @@ -481,7 +480,8 @@ thunar_list_model_init (ThunarListModel *store) * connect "changed" to every single ThunarFile we own. */ store->file_monitor = thunar_file_monitor_get_default (); - g_signal_connect (G_OBJECT (store->file_monitor), "file-changed", G_CALLBACK (thunar_list_model_file_changed), store); + g_signal_connect (G_OBJECT (store->file_monitor), "file-changed", + G_CALLBACK (thunar_list_model_file_changed), store); } @@ -494,9 +494,6 @@ thunar_list_model_finalize (GObject *object) /* unlink from the folder (if any) */ thunar_list_model_set_folder (store, NULL); - /* disconnect from the volume manager */ - g_object_unref (G_OBJECT (store->volume_manager)); - /* disconnect from the file monitor */ g_signal_handlers_disconnect_by_func (G_OBJECT (store->file_monitor), thunar_list_model_file_changed, store); g_object_unref (G_OBJECT (store->file_monitor)); @@ -697,13 +694,13 @@ thunar_list_model_get_value (GtkTreeModel *model, gint column, GValue *value) { - ThunarVfsMimeInfo *mime_info; - ThunarVfsGroup *group; - ThunarVfsUser *user; - const gchar *name; - const gchar *real_name; - ThunarFile *file; - gchar *str; + ThunarGroup *group; + const gchar *content_type; + const gchar *name; + const gchar *real_name; + ThunarUser *user; + ThunarFile *file; + gchar *str; _thunar_return_if_fail (THUNAR_IS_LIST_MODEL (model)); _thunar_return_if_fail (iter->stamp == (THUNAR_LIST_MODEL (model))->stamp); @@ -729,7 +726,7 @@ thunar_list_model_get_value (GtkTreeModel *model, group = thunar_file_get_group (file); if (G_LIKELY (group != NULL)) { - g_value_set_string (value, thunar_vfs_group_get_name (group)); + g_value_set_string (value, thunar_group_get_name (group)); g_object_unref (G_OBJECT (group)); } else @@ -740,8 +737,7 @@ thunar_list_model_get_value (GtkTreeModel *model, case THUNAR_COLUMN_MIME_TYPE: g_value_init (value, G_TYPE_STRING); - mime_info = thunar_file_get_mime_info (file); - g_value_set_static_string (value, thunar_vfs_mime_info_get_name (mime_info)); + g_value_set_static_string (value, thunar_file_get_content_type (file)); break; case THUNAR_COLUMN_NAME: @@ -755,8 +751,8 @@ thunar_list_model_get_value (GtkTreeModel *model, if (G_LIKELY (user != NULL)) { /* determine sane display name for the owner */ - name = thunar_vfs_user_get_name (user); - real_name = thunar_vfs_user_get_real_name (user); + name = thunar_user_get_name (user); + real_name = thunar_user_get_real_name (user); str = G_LIKELY (real_name != NULL) ? g_strdup_printf ("%s (%s)", real_name, name) : g_strdup (name); g_value_take_string (value, str); g_object_unref (G_OBJECT (user)); @@ -779,13 +775,14 @@ thunar_list_model_get_value (GtkTreeModel *model, case THUNAR_COLUMN_TYPE: g_value_init (value, G_TYPE_STRING); - mime_info = thunar_file_get_mime_info (file); - if (G_UNLIKELY (strcmp (thunar_vfs_mime_info_get_name (mime_info), "inode/symlink") == 0)) - g_value_set_static_string (value, _("broken link")); - else if (G_UNLIKELY (thunar_file_is_symlink (file))) - g_value_take_string (value, g_strdup_printf (_("link to %s"), thunar_vfs_mime_info_get_comment (mime_info))); + if (G_UNLIKELY (thunar_file_is_symlink (file))) + g_value_take_string (value, g_strdup_printf (_("link to %s"), thunar_file_get_symlink_target (file))); else - g_value_set_static_string (value, thunar_vfs_mime_info_get_comment (mime_info)); + { + content_type = thunar_file_get_content_type (file); + if (content_type != NULL) + g_value_take_string (value, g_content_type_get_description (content_type)); + } break; case THUNAR_COLUMN_FILE: @@ -795,7 +792,7 @@ thunar_list_model_get_value (GtkTreeModel *model, case THUNAR_COLUMN_FILE_NAME: g_value_init (value, G_TYPE_STRING); - g_value_take_string (value, g_filename_display_name (thunar_vfs_path_get_name (thunar_file_get_path (file)))); + g_value_set_static_string (value, thunar_file_get_basename (file)); break; default: @@ -1310,7 +1307,7 @@ thunar_list_model_files_added (ThunarFolder *folder, */ path = gtk_tree_path_new_from_indices (0, -1); indices = gtk_tree_path_get_indices (path); - + /* process all added files */ for (; files != NULL; files = files->next) { @@ -1420,8 +1417,8 @@ sort_by_date_accessed (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) { - ThunarVfsFileTime date_a; - ThunarVfsFileTime date_b; + guint64 date_a; + guint64 date_b; date_a = thunar_file_get_date (a, THUNAR_FILE_DATE_ACCESSED); date_b = thunar_file_get_date (b, THUNAR_FILE_DATE_ACCESSED); @@ -1441,8 +1438,8 @@ sort_by_date_modified (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) { - ThunarVfsFileTime date_a; - ThunarVfsFileTime date_b; + guint64 date_a; + guint64 date_b; date_a = thunar_file_get_date (a, THUNAR_FILE_DATE_MODIFIED); date_b = thunar_file_get_date (b, THUNAR_FILE_DATE_MODIFIED); @@ -1462,8 +1459,8 @@ sort_by_file_name (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) { - const gchar *a_name = thunar_vfs_path_get_name (thunar_file_get_path (a)); - const gchar *b_name = thunar_vfs_path_get_name (thunar_file_get_path (b)); + const gchar *a_name = thunar_file_get_display_name (a); + const gchar *b_name = thunar_file_get_display_name (b); if (G_UNLIKELY (!case_sensitive)) return strcasecmp (a_name, b_name); @@ -1478,9 +1475,20 @@ sort_by_group (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) { - if (a->info->gid < b->info->gid) + guint32 gid_a; + guint32 gid_b; + + if (thunar_file_get_info (a) == NULL || thunar_file_get_info (b) == NULL) + return 0; + + gid_a = g_file_info_get_attribute_uint32 (thunar_file_get_info (a), + G_FILE_ATTRIBUTE_UNIX_GID); + gid_b = g_file_info_get_attribute_uint32 (thunar_file_get_info (b), + G_FILE_ATTRIBUTE_UNIX_GID); + + if (gid_a < gid_b) return -1; - else if (a->info->gid > b->info->gid) + else if (gid_a > gid_b) return 1; else return sort_by_name (a, b, case_sensitive); @@ -1493,15 +1501,14 @@ sort_by_mime_type (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) { - const ThunarVfsMimeInfo *info_a; - const ThunarVfsMimeInfo *info_b; - gint result; + const gchar *content_type_a; + const gchar *content_type_b; + gint result; - info_a = thunar_file_get_mime_info (a); - info_b = thunar_file_get_mime_info (b); + content_type_a = thunar_file_get_content_type (a); + content_type_b = thunar_file_get_content_type (b); - result = strcasecmp (thunar_vfs_mime_info_get_name (info_a), - thunar_vfs_mime_info_get_name (info_b)); + result = strcasecmp (content_type_a, content_type_b); if (result == 0) result = sort_by_name (a, b, case_sensitive); @@ -1526,9 +1533,20 @@ sort_by_owner (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) { - if (a->info->uid < b->info->uid) + guint32 uid_a; + guint32 uid_b; + + if (thunar_file_get_info (a) == NULL || thunar_file_get_info (b) == NULL) + return 0; + + uid_a = g_file_info_get_attribute_uint32 (thunar_file_get_info (a), + G_FILE_ATTRIBUTE_UNIX_UID); + uid_b = g_file_info_get_attribute_uint32 (thunar_file_get_info (b), + G_FILE_ATTRIBUTE_UNIX_UID); + + if (uid_a < uid_b) return -1; - else if (a->info->uid > b->info->uid) + else if (uid_a > uid_b) return 1; else return sort_by_name (a, b, case_sensitive); @@ -1541,8 +1559,8 @@ sort_by_permissions (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) { - ThunarVfsFileMode mode_a; - ThunarVfsFileMode mode_b; + ThunarFileMode mode_a; + ThunarFileMode mode_b; mode_a = thunar_file_get_mode (a); mode_b = thunar_file_get_mode (b); @@ -1562,8 +1580,8 @@ sort_by_size (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) { - ThunarVfsFileSize size_a; - ThunarVfsFileSize size_b; + guint64 size_a; + guint64 size_b; size_a = thunar_file_get_size (a); size_b = thunar_file_get_size (b); @@ -1583,15 +1601,19 @@ sort_by_type (const ThunarFile *a, const ThunarFile *b, gboolean case_sensitive) { - ThunarVfsMimeInfo *info_a; - ThunarVfsMimeInfo *info_b; - gint result; + const gchar *content_type_a; + const gchar *content_type_b; + gchar *description_a; + gchar *description_b; + gint result; + + content_type_a = thunar_file_get_content_type (a); + content_type_b = thunar_file_get_content_type (a); - info_a = thunar_file_get_mime_info (a); - info_b = thunar_file_get_mime_info (b); + description_a = g_content_type_get_description (content_type_a); + description_b = g_content_type_get_description (content_type_b); - result = strcasecmp (thunar_vfs_mime_info_get_comment (info_a), - thunar_vfs_mime_info_get_comment (info_b)); + result = strcasecmp (description_a, description_b); if (result == 0) result = sort_by_name (a, b, case_sensitive); @@ -1630,11 +1652,7 @@ ThunarListModel* thunar_list_model_new_with_folder (ThunarFolder *folder) { _thunar_return_val_if_fail (THUNAR_IS_FOLDER (folder), NULL); - - /* allocate the new list model */ - return g_object_new (THUNAR_TYPE_LIST_MODEL, - "folder", folder, - NULL); + return g_object_new (THUNAR_TYPE_LIST_MODEL, "folder", folder, NULL); } @@ -2200,22 +2218,23 @@ gchar* thunar_list_model_get_statusbar_text (ThunarListModel *store, GList *selected_items) { - ThunarVfsMimeInfo *mime_info; - ThunarVfsFileSize size_summary; - ThunarVfsFileSize size; - GtkTreeIter iter; - ThunarFile *file; - GSList *row; - GList *lp; - gchar *absolute_path; - gchar *fspace_string; - gchar *display_name; - gchar *size_string; - gchar *text; - gchar *s; - gint height; - gint width; - gint n; + const gchar *content_type; + const gchar *original_path; + GtkTreeIter iter; + ThunarFile *file; + guint64 size; + guint64 size_summary; + GSList *row; + GList *lp; + gchar *absolute_path; + gchar *fspace_string; + gchar *display_name; + gchar *size_string; + gchar *text; + gchar *s; + gint height; + gint width; + gint n; _thunar_return_val_if_fail (THUNAR_IS_LIST_MODEL (store), NULL); @@ -2228,7 +2247,7 @@ thunar_list_model_get_statusbar_text (ThunarListModel *store, if (G_LIKELY (file != NULL && thunar_file_get_free_space (file, &size))) { /* humanize the free space */ - fspace_string = thunar_vfs_humanize_size (size, NULL, 0); + fspace_string = g_format_size_for_display (size); /* check if we have atleast one file in this folder */ if (G_LIKELY (store->nrows > 0)) @@ -2238,7 +2257,7 @@ thunar_list_model_get_statusbar_text (ThunarListModel *store, size_summary += thunar_file_get_size (row->data); /* humanize the size summary */ - size_string = thunar_vfs_humanize_size (size_summary, NULL, 0); + size_string = g_format_size_for_display (size_summary); /* generate a text which includes the size of all items in the folder */ text = g_strdup_printf (ngettext ("%d item (%s), Free space: %s", "%d items (%s), Free space: %s", store->nrows), @@ -2268,32 +2287,47 @@ thunar_list_model_get_statusbar_text (ThunarListModel *store, /* get the file for the given iter */ file = THUNAR_FILE (G_SLIST (iter.user_data)->data); + + /* determine the content type of the file */ + content_type = thunar_file_get_content_type (file); /* calculate the text to be displayed */ - mime_info = thunar_file_get_mime_info (file); size_string = thunar_file_get_size_string (file); - if (G_UNLIKELY (strcmp (thunar_vfs_mime_info_get_name (mime_info), "inode/symlink") == 0)) + + if (G_UNLIKELY (content_type != NULL && g_str_equal (content_type, "inode/symlink"))) { text = g_strdup_printf (_("\"%s\" broken link"), thunar_file_get_display_name (file)); } else if (G_UNLIKELY (thunar_file_is_symlink (file))) { text = g_strdup_printf (_("\"%s\" (%s) link to %s"), thunar_file_get_display_name (file), - size_string, thunar_vfs_mime_info_get_comment (mime_info)); + size_string, thunar_file_get_symlink_target (file)); + } + else if (G_UNLIKELY (thunar_file_get_kind (file) == G_FILE_TYPE_SHORTCUT)) + { + text = g_strdup_printf (_("\"%s\" shortcut"), thunar_file_get_display_name (file)); + } + else if (G_UNLIKELY (thunar_file_get_kind (file) == G_FILE_TYPE_MOUNTABLE)) + { + text = g_strdup_printf (_("\"%s\" mountable"), thunar_file_get_display_name (file)); } else { + gchar *description; + + description = g_content_type_get_description (thunar_file_get_content_type (file)); text = g_strdup_printf (_("\"%s\" (%s) %s"), thunar_file_get_display_name (file), - size_string, thunar_vfs_mime_info_get_comment (mime_info)); + size_string, description); + g_free (description); } g_free (size_string); /* append the original path (if any) */ - absolute_path = thunar_file_get_original_path (file); - if (G_UNLIKELY (absolute_path != NULL)) + original_path = thunar_file_get_original_path (file); + if (G_UNLIKELY (original_path != NULL)) { /* append the original path to the statusbar text */ - display_name = g_filename_display_name (absolute_path); + display_name = g_filename_display_name (original_path); s = g_strdup_printf ("%s, %s %s", text, _("Original Path:"), display_name); g_free (display_name); g_free (text); @@ -2302,16 +2336,17 @@ thunar_list_model_get_statusbar_text (ThunarListModel *store, else if (thunar_file_is_local (file) && thunar_file_is_regular (file)) { /* check if we can determine the dimension of this file (only for image files) */ - absolute_path = thunar_vfs_path_dup_string (thunar_file_get_path (file)); - if (gdk_pixbuf_get_file_info (absolute_path, &width, &height) != NULL) + absolute_path = g_file_get_path (thunar_file_get_file (file)); + if (absolute_path != NULL + && gdk_pixbuf_get_file_info (absolute_path, &width, &height) != NULL) { /* append the image dimensions to the statusbar text */ s = g_strdup_printf ("%s, %s %dx%d", text, _("Image Size:"), width, height); g_free (text); text = s; } + g_free (absolute_path); } - g_free (absolute_path); } else { @@ -2324,7 +2359,7 @@ thunar_list_model_get_statusbar_text (ThunarListModel *store, if (size_summary > 0) { - size_string = thunar_vfs_humanize_size (size_summary, NULL, 0); + size_string = g_format_size_for_display (size_summary); text = g_strdup_printf (ngettext ("%d item selected (%s)", "%d items selected (%s)", n), n, size_string); g_free (size_string); } diff --git a/thunar/thunar-location-button.c b/thunar/thunar-location-button.c index 8b5c64f17..d34b18dd7 100644 --- a/thunar/thunar-location-button.c +++ b/thunar/thunar-location-button.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -30,6 +31,7 @@ #include <thunar/thunar-application.h> #include <thunar/thunar-dnd.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-icon-factory.h> #include <thunar/thunar-location-button.h> #include <thunar/thunar-pango-extensions.h> @@ -140,7 +142,7 @@ struct _ThunarLocationButton gint enter_timeout_id; /* drop support for the button */ - GList *drop_path_list; + GList *drop_file_list; guint drop_data_ready : 1; guint drop_occurred : 1; @@ -340,7 +342,7 @@ thunar_location_button_finalize (GObject *object) ThunarLocationButton *location_button = THUNAR_LOCATION_BUTTON (object); /* release the drop path list (just in case the drag-leave wasn't fired before) */ - thunar_vfs_path_list_free (location_button->drop_path_list); + thunar_g_file_list_free (location_button->drop_file_list); /* be sure to cancel any pending enter timeout */ if (G_UNLIKELY (location_button->enter_timeout_id != 0)) @@ -434,7 +436,7 @@ thunar_location_button_get_dest_actions (ThunarLocationButton *location_button, if (G_LIKELY (location_button->file != NULL)) { /* determine the possible drop actions for the file (and the suggested action if any) */ - actions = thunar_file_accepts_drop (location_button->file, location_button->drop_path_list, context, &action); + actions = thunar_file_accepts_drop (location_button->file, location_button->drop_file_list, context, &action); } /* tell Gdk whether we can drop here */ @@ -452,9 +454,7 @@ thunar_location_button_file_changed (ThunarLocationButton *location_button, ThunarIconFactory *icon_factory; GtkIconTheme *icon_theme; GtkSettings *settings; -#if GTK_CHECK_VERSION(2,8,0) - const gchar *icon_name; -#endif + gchar *icon_name; GdkPixbuf *icon; gint height; gint width; @@ -467,18 +467,9 @@ thunar_location_button_file_changed (ThunarLocationButton *location_button, /* determine the icon theme for the widget */ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (location_button))); - /* the label is hidden for the file system root */ - if (thunar_file_is_local (file) && thunar_file_is_root (file)) - { - /* hide the label widget */ - gtk_widget_hide (location_button->label); - } - else - { - /* update and show the label widget */ - gtk_label_set_text (GTK_LABEL (location_button->label), thunar_file_get_display_name (file)); - gtk_widget_show (location_button->label); - } + /* update and show the label widget */ + gtk_label_set_text (GTK_LABEL (location_button->label), thunar_file_get_display_name (file)); + gtk_widget_show (location_button->label); /* the image is only visible for certain special paths */ if (thunar_file_is_home (file) || thunar_file_is_desktop (file) || thunar_file_is_root (file)) @@ -506,13 +497,15 @@ thunar_location_button_file_changed (ThunarLocationButton *location_button, gtk_widget_hide (location_button->image); } -#if GTK_CHECK_VERSION(2,8,0) /* setup the DnD icon for the button */ icon_name = thunar_file_get_custom_icon (file); - if (G_LIKELY (icon_name == NULL)) - icon_name = thunar_file_get_icon_name (file, location_button->file_icon_state, icon_theme); + if (icon_name == NULL) + { + icon_name = thunar_file_get_icon_name (file, location_button->file_icon_state, + icon_theme); + } gtk_drag_source_set_icon_name (GTK_BIN (location_button)->child, icon_name); -#endif + g_free (icon_name); } @@ -610,7 +603,7 @@ thunar_location_button_button_release_event (GtkWidget *button, { /* open a new window for the folder */ application = thunar_application_get (); - thunar_application_open_window (application, location_button->file, gtk_widget_get_screen (GTK_WIDGET (location_button))); + thunar_application_open_window (application, location_button->file, gtk_widget_get_screen (GTK_WIDGET (location_button)), NULL); g_object_unref (G_OBJECT (application)); } } @@ -670,8 +663,8 @@ thunar_location_button_drag_data_get (GtkWidget *button, if (G_LIKELY (location_button->file != NULL)) { /* transform the path into an uri list string */ - path_list.data = thunar_file_get_path (location_button->file); path_list.next = path_list.prev = NULL; - uri_string = thunar_vfs_path_list_to_string (&path_list); + path_list.data = thunar_file_get_file (location_button->file); path_list.next = path_list.prev = NULL; + uri_string = thunar_g_file_list_to_string (&path_list); /* set the uri list for the drag selection */ gtk_selection_data_set (selection_data, selection_data->target, 8, (guchar *) uri_string, strlen (uri_string)); @@ -702,7 +695,7 @@ thunar_location_button_drag_data_received (GtkWidget *button, { /* extract the URI list from the selection data (if valid) */ if (selection_data->format == 8 && selection_data->length > 0) - location_button->drop_path_list = thunar_vfs_path_list_from_string ((const gchar *) selection_data->data, NULL); + location_button->drop_file_list = thunar_g_file_list_new_from_string ((const gchar *) selection_data->data); /* reset the state */ location_button->drop_data_ready = TRUE; @@ -720,12 +713,12 @@ thunar_location_button_drag_data_received (GtkWidget *button, { /* as the user what to do with the drop data */ action = (context->action == GDK_ACTION_ASK) - ? thunar_dnd_ask (button, location_button->file, location_button->drop_path_list, time, actions) + ? thunar_dnd_ask (button, location_button->file, location_button->drop_file_list, time, actions) : context->action; /* perform the requested action */ if (G_LIKELY (action != 0)) - succeed = thunar_dnd_perform (button, location_button->file, location_button->drop_path_list, action, NULL); + succeed = thunar_dnd_perform (button, location_button->file, location_button->drop_file_list, action, NULL); } /* tell the peer that we handled the drop */ @@ -761,9 +754,9 @@ thunar_location_button_drag_leave (GtkWidget *button, /* reset the "drop data ready" status and free the path list */ if (G_LIKELY (location_button->drop_data_ready)) { - thunar_vfs_path_list_free (location_button->drop_path_list); + thunar_g_file_list_free (location_button->drop_file_list); location_button->drop_data_ready = FALSE; - location_button->drop_path_list = NULL; + location_button->drop_file_list = NULL; } /* be sure to cancel any running enter timeout */ diff --git a/thunar/thunar-location-buttons.c b/thunar/thunar-location-buttons.c index 218668680..5a62c764b 100644 --- a/thunar/thunar-location-buttons.c +++ b/thunar/thunar-location-buttons.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -27,6 +28,7 @@ #include <thunar/thunar-application.h> #include <thunar/thunar-clipboard-manager.h> #include <thunar/thunar-create-dialog.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-gtk-extensions.h> #include <thunar/thunar-location-button.h> @@ -1317,12 +1319,10 @@ static void thunar_location_buttons_action_create_folder (GtkAction *action, ThunarLocationButtons *buttons) { - ThunarVfsMimeDatabase *mime_database; - ThunarVfsMimeInfo *mime_info; - ThunarApplication *application; - ThunarFile *directory; - GList path_list; - gchar *name; + ThunarApplication *application; + ThunarFile *directory; + GList path_list; + gchar *name; _thunar_return_if_fail (THUNAR_IS_LOCATION_BUTTONS (buttons)); _thunar_return_if_fail (GTK_IS_ACTION (action)); @@ -1332,16 +1332,15 @@ thunar_location_buttons_action_create_folder (GtkAction *action, if (G_UNLIKELY (directory == NULL)) return; - /* lookup "inode/directory" mime info */ - mime_database = thunar_vfs_mime_database_get_default (); - mime_info = thunar_vfs_mime_database_get_info (mime_database, "inode/directory"); - /* ask the user to enter a name for the new folder */ - name = thunar_show_create_dialog (GTK_WIDGET (buttons), mime_info, _("New Folder"), _("Create New Folder")); + name = thunar_show_create_dialog (GTK_WIDGET (buttons), + "inode/directory", + _("New Folder"), + _("Create New Folder")); if (G_LIKELY (name != NULL)) { /* fake the path list */ - path_list.data = thunar_vfs_path_relative (thunar_file_get_path (directory), name); + path_list.data = g_file_resolve_relative_path (thunar_file_get_file (directory), name); path_list.next = path_list.prev = NULL; /* launch the operation */ @@ -1350,15 +1349,11 @@ thunar_location_buttons_action_create_folder (GtkAction *action, g_object_unref (G_OBJECT (application)); /* release the path */ - thunar_vfs_path_unref (path_list.data); + g_object_unref (path_list.data); /* release the file name */ g_free (name); } - - /* cleanup */ - g_object_unref (G_OBJECT (mime_database)); - thunar_vfs_mime_info_unref (mime_info); } @@ -1442,7 +1437,7 @@ thunar_location_buttons_action_open_in_new_window (GtkAction *action { /* open a new window for the directory */ application = thunar_application_get (); - thunar_application_open_window (application, directory, gtk_widget_get_screen (GTK_WIDGET (buttons))); + thunar_application_open_window (application, directory, gtk_widget_get_screen (GTK_WIDGET (buttons)), NULL); g_object_unref (G_OBJECT (application)); } } @@ -1465,7 +1460,7 @@ thunar_location_buttons_action_paste_into_folder (GtkAction *action, { /* paste files from the clipboard to the folder represented by this button */ clipboard = thunar_clipboard_manager_get_for_display (gtk_widget_get_display (GTK_WIDGET (buttons))); - thunar_clipboard_manager_paste_files (clipboard, thunar_file_get_path (directory), GTK_WIDGET (buttons), NULL); + thunar_clipboard_manager_paste_files (clipboard, thunar_file_get_file (directory), GTK_WIDGET (buttons), NULL); g_object_unref (G_OBJECT (clipboard)); } } diff --git a/thunar/thunar-location-dialog.c b/thunar/thunar-location-dialog.c index 240ca9193..6f7ac21dd 100644 --- a/thunar/thunar-location-dialog.c +++ b/thunar/thunar-location-dialog.c @@ -28,7 +28,7 @@ -static void thunar_location_dialog_init (ThunarLocationDialog *location_dialog); +static void thunar_location_dialog_init (ThunarLocationDialog *location_dialog); diff --git a/thunar/thunar-location-entry.c b/thunar/thunar-location-entry.c index 3158babfc..03af3fc32 100644 --- a/thunar/thunar-location-entry.c +++ b/thunar/thunar-location-entry.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -23,6 +24,7 @@ #include <gdk/gdkkeysyms.h> +#include <thunar/thunar-browser.h> #include <thunar/thunar-dialogs.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-gtk-extensions.h> @@ -125,6 +127,13 @@ thunar_location_entry_get_type (void) NULL, }; + static const GInterfaceInfo browser_info = + { + NULL, + NULL, + NULL, + }; + static const GInterfaceInfo component_info = { (GInterfaceInitFunc) thunar_location_entry_component_init, @@ -147,6 +156,7 @@ thunar_location_entry_get_type (void) }; type = g_type_register_static (GTK_TYPE_HBOX, I_("ThunarLocationEntry"), &info, 0); + g_type_add_interface_static (type, THUNAR_TYPE_BROWSER, &browser_info); g_type_add_interface_static (type, THUNAR_TYPE_NAVIGATOR, &navigator_info); g_type_add_interface_static (type, THUNAR_TYPE_COMPONENT, &component_info); g_type_add_interface_static (type, THUNAR_TYPE_LOCATION_BAR, &location_bar_info); @@ -399,18 +409,16 @@ thunar_location_entry_accept_focus (ThunarLocationBar *location_bar, static void -thunar_location_entry_activate (GtkWidget *path_entry, - ThunarLocationEntry *location_entry) +thunar_location_entry_open_or_launch (ThunarLocationEntry *location_entry, + ThunarFile *file) { - ThunarFile *file; - GError *error = NULL; + GError *error = NULL; _thunar_return_if_fail (THUNAR_IS_LOCATION_ENTRY (location_entry)); - _thunar_return_if_fail (location_entry->path_entry == path_entry); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); - /* determine the current file from the path entry */ - file = thunar_path_entry_get_current_file (THUNAR_PATH_ENTRY (path_entry)); - if (G_LIKELY (file != NULL)) + /* check if the file is mounted */ + if (thunar_file_is_mounted (file)) { /* check if we have a new directory or a file to launch */ if (thunar_file_is_directory (file)) @@ -421,17 +429,78 @@ thunar_location_entry_activate (GtkWidget *path_entry, else { /* try to launch the selected file */ - if (!thunar_file_launch (file, path_entry, &error)) - { - thunar_dialogs_show_error (path_entry, error, _("Failed to launch \"%s\""), thunar_file_get_display_name (file)); - g_error_free (error); - } + thunar_file_launch (file, location_entry->path_entry, NULL, &error); /* be sure to reset the current file of the path entry */ if (G_LIKELY (location_entry->current_directory != NULL)) - thunar_path_entry_set_current_file (THUNAR_PATH_ENTRY (path_entry), location_entry->current_directory); + { + thunar_path_entry_set_current_file (THUNAR_PATH_ENTRY (location_entry->path_entry), + location_entry->current_directory); + } } } + else + { + g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("File does not exist")); + } + + /* check if we need to display an error dialog */ + if (error != NULL) + { + thunar_dialogs_show_error (location_entry->path_entry, error, + _("Failed to open \"%s\""), + thunar_file_get_display_name (file)); + g_error_free (error); + } +} + + + +static void +thunar_location_entry_poke_file_finish (ThunarBrowser *browser, + ThunarFile *file, + ThunarFile *target_file, + GError *error, + gpointer ignored) +{ + _thunar_return_if_fail (THUNAR_IS_LOCATION_ENTRY (browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + if (error == NULL) + { + /* try to open or launch the target file */ + thunar_location_entry_open_or_launch (THUNAR_LOCATION_ENTRY (browser), + target_file); + } + else + { + /* display an error explaining why we couldn't open/mount the file */ + thunar_dialogs_show_error (THUNAR_LOCATION_ENTRY (browser)->path_entry, + error, _("Failed to open \"%s\""), + thunar_file_get_display_name (file)); + } +} + + + + + +static void +thunar_location_entry_activate (GtkWidget *path_entry, + ThunarLocationEntry *location_entry) +{ + ThunarFile *file; + + _thunar_return_if_fail (THUNAR_IS_LOCATION_ENTRY (location_entry)); + _thunar_return_if_fail (location_entry->path_entry == path_entry); + + /* determine the current file from the path entry */ + file = thunar_path_entry_get_current_file (THUNAR_PATH_ENTRY (path_entry)); + if (G_LIKELY (file != NULL)) + { + thunar_browser_poke_file (THUNAR_BROWSER (location_entry), file, path_entry, + thunar_location_entry_poke_file_finish, NULL); + } } @@ -497,15 +566,16 @@ thunar_location_entry_button_clicked (GtkWidget *button, { ThunarShortcutsModel *model; ThunarIconFactory *icon_factory; - ThunarVfsVolume *volume; GtkIconTheme *icon_theme; - const gchar *icon_name; GtkTreeIter iter; ThunarFile *file; GtkWidget *image; GtkWidget *item; GtkWidget *menu; GdkPixbuf *icon; + GVolume *volume; + GIcon *volume_icon; + gchar *volume_name; gint icon_size; gint width; @@ -543,19 +613,16 @@ thunar_location_entry_button_clicked (GtkWidget *button, else if (G_UNLIKELY (volume != NULL)) { /* generate an image menu item for the volume */ - item = gtk_image_menu_item_new_with_label (thunar_vfs_volume_get_name (volume)); - - /* load the icon for the volume */ - icon_name = thunar_vfs_volume_lookup_icon_name (volume, icon_theme); - icon = thunar_icon_factory_load_icon (icon_factory, icon_name, icon_size, NULL, FALSE); - if (G_LIKELY (icon != NULL)) - { - /* generate an image for the menu item */ - image = gtk_image_new_from_pixbuf (icon); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - g_object_unref (G_OBJECT (icon)); - gtk_widget_show (image); - } + volume_name = g_volume_get_name (volume); + item = gtk_image_menu_item_new_with_label (volume_name); + g_free (volume_name); + + /* generate an image for the menu item */ + volume_icon = g_volume_get_icon (volume); + image = gtk_image_new_from_gicon (volume_icon, GTK_ICON_SIZE_MENU); + g_object_unref (volume_icon); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); + gtk_widget_show (image); } else { @@ -566,16 +633,16 @@ thunar_location_entry_button_clicked (GtkWidget *button, icon = thunar_icon_factory_load_file_icon (icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, icon_size); image = gtk_image_new_from_pixbuf (icon); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - g_object_unref (G_OBJECT (icon)); + g_object_unref (icon); gtk_widget_show (image); } /* connect the file and volume to the item */ - g_object_set_data_full (G_OBJECT (item), I_("thunar-vfs-volume"), volume, g_object_unref); + g_object_set_data_full (G_OBJECT (item), I_("volume"), volume, g_object_unref); g_object_set_data_full (G_OBJECT (item), I_("thunar-file"), file, g_object_unref); /* append the new item to the menu */ - g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (thunar_location_entry_item_activated), location_entry); + g_signal_connect (item, "activate", G_CALLBACK (thunar_location_entry_item_activated), location_entry); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); } @@ -610,14 +677,77 @@ thunar_location_entry_button_clicked (GtkWidget *button, +static void +thunar_location_entry_mount_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + ThunarLocationEntry *location_entry = THUNAR_LOCATION_ENTRY (user_data); + ThunarFile *file = NULL; + GtkWidget *window; + GVolume *volume = G_VOLUME (object); + GError *error = NULL; + GMount *mount; + GFile *mount_point; + gchar *volume_name; + + _thunar_return_if_fail (G_IS_VOLUME (object)); + _thunar_return_if_fail (THUNAR_IS_LOCATION_ENTRY (user_data)); + + if (!g_volume_mount_finish (volume, result, &error)) + { + /* determine the toplevel window */ + window = gtk_widget_get_toplevel (GTK_WIDGET (location_entry)); + + volume_name = g_volume_get_name (volume); + thunar_dialogs_show_error (window, error, _("Failed to mount \"%s\""), volume_name); + g_free (volume_name); + } + else + { + mount = g_volume_get_mount (volume); + if (mount != NULL) + { + mount_point = g_mount_get_root (mount); + file = thunar_file_get (mount_point, NULL); + g_object_unref (mount_point); + + /* check if we have a file object now */ + if (G_LIKELY (file != NULL)) + { + /* make sure that this is actually a directory */ + if (thunar_file_is_directory (file)) + { + /* open the new directory */ + thunar_navigator_change_directory (THUNAR_NAVIGATOR (location_entry), + file); + } + + /* cleanup */ + g_object_unref (file); + } + + g_object_unref (mount); + } + } + + g_object_unref (location_entry); +} + + + static void thunar_location_entry_item_activated (GtkWidget *item, ThunarLocationEntry *location_entry) { - ThunarVfsVolume *volume; - ThunarFile *file; + GMountOperation *mount_operation; + ThunarFile *file = NULL; GtkWidget *window; + GVolume *volume; GError *error = NULL; + GMount *mount; + GFile *mount_point; + gchar *volume_name; _thunar_return_if_fail (GTK_IS_MENU_ITEM (item)); _thunar_return_if_fail (THUNAR_IS_LOCATION_ENTRY (location_entry)); @@ -626,30 +756,43 @@ thunar_location_entry_item_activated (GtkWidget *item, window = gtk_widget_get_toplevel (GTK_WIDGET (location_entry)); /* check if the item corresponds to a volume */ - volume = g_object_get_data (G_OBJECT (item), "thunar-vfs-volume"); + volume = g_object_get_data (G_OBJECT (item), "volume"); if (G_UNLIKELY (volume != NULL)) { /* check if the volume isn't already mounted */ - if (G_LIKELY (!thunar_vfs_volume_is_mounted (volume))) + if (G_LIKELY (!thunar_g_volume_is_mounted (volume))) { - /* try to mount the volume */ - if (!thunar_vfs_volume_mount (volume, window, &error)) - { - /* display an error dialog to inform the user */ - thunar_dialogs_show_error (window, error, _("Failed to mount \"%s\""), thunar_vfs_volume_get_name (volume)); - g_error_free (error); - return; - } - } + mount_operation = gtk_mount_operation_new (GTK_WINDOW (window)); - /* try to determine the mount point of the volume */ - file = thunar_file_get_for_path (thunar_vfs_volume_get_mount_point (volume), &error); - if (G_UNLIKELY (file == NULL)) + g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_operation, NULL, + thunar_location_entry_mount_finish, + g_object_ref (location_entry)); + + g_object_unref (mount_operation); + } + else { - /* display an error dialog to inform the user */ - thunar_dialogs_show_error (window, error, _("Failed to determine the mount point for %s"), thunar_vfs_volume_get_name (volume)); - g_error_free (error); - return; + mount = g_volume_get_mount (volume); + if (mount != NULL) + { + /* try to determine the mount point of the volume */ + mount_point = g_mount_get_root (mount); + file = thunar_file_get (mount_point, &error); + g_object_unref (mount_point); + + if (G_UNLIKELY (file == NULL)) + { + /* display an error dialog to inform the user */ + volume_name = g_volume_get_name (volume); + thunar_dialogs_show_error (window, error, + _("Failed to determine the mount point of \"%s\""), + volume_name); + g_free (volume_name); + g_error_free (error); + } + + g_object_unref (mount); + } } } else diff --git a/thunar/thunar-marshal.list b/thunar/thunar-marshal.list index 39f204f85..58aaa040a 100644 --- a/thunar/thunar-marshal.list +++ b/thunar/thunar-marshal.list @@ -1,4 +1,9 @@ +BOOLEAN:POINTER BOOLEAN:VOID +FLAGS:OBJECT,OBJECT +FLAGS:STRING,FLAGS VOID:BOXED,OBJECT VOID:BOXED,POINTER VOID:STRING,STRING +VOID:UINT64,UINT,UINT,UINT +VOID:UINT,POINTER,UINT,STRING diff --git a/thunar/thunar-metafile.c b/thunar/thunar-metafile.c index bff93da33..1d49f1e90 100644 --- a/thunar/thunar-metafile.c +++ b/thunar/thunar-metafile.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -37,6 +38,10 @@ #include <string.h> #endif +#include <gio/gio.h> + +#include <exo/exo.h> + #include <tdb/tdb.h> #include <thunar/thunar-metafile.h> @@ -221,7 +226,7 @@ thunar_metafile_get_default (void) /** * thunar_metafile_fetch: * @metafile : a #ThunarMetafile. - * @path : a #ThunarVfsPath. + * @file : a #Gfile. * @key : a #ThunarMetafileKey. * @default_value : the default value for @key, * which may be %NULL. @@ -246,7 +251,7 @@ thunar_metafile_get_default (void) **/ const gchar* thunar_metafile_fetch (ThunarMetafile *metafile, - ThunarVfsPath *path, + GFile *file, ThunarMetafileKey key, const gchar *default_value) { @@ -254,20 +259,20 @@ thunar_metafile_fetch (ThunarMetafile *metafile, const guchar *dp; TDB_DATA key_data; gssize key_size; - gchar key_path[THUNAR_VFS_PATH_MAXSTRLEN]; + gchar *key_path = NULL; _thunar_return_val_if_fail (THUNAR_IS_METAFILE (metafile), NULL); + _thunar_return_val_if_fail (G_IS_FILE (file), NULL); _thunar_return_val_if_fail (key < THUNAR_METAFILE_N_KEYS, NULL); - _thunar_return_val_if_fail (path != NULL, NULL); /* check if the database handle is available */ if (G_UNLIKELY (metafile->context == NULL)) goto use_default_value; /* determine the string representation of the path (using the URI for non-local paths) */ - key_size = (thunar_vfs_path_get_scheme (path) == THUNAR_VFS_PATH_SCHEME_FILE) - ? thunar_vfs_path_to_string (path, key_path, sizeof (key_path), NULL) - : thunar_vfs_path_to_uri (path, key_path, sizeof (key_path), NULL); + key_path = g_file_get_uri (file); + key_size = strlen (key_path); + if (G_UNLIKELY (key_size <= 0)) goto use_default_value; @@ -291,7 +296,10 @@ thunar_metafile_fetch (ThunarMetafile *metafile, { /* check if we have a match */ if (*dp == (guint) key) - return (const gchar *) (dp + 1); + { + g_free (key_path); + return (const gchar *) (dp + 1); + } /* lookup the next entry */ do @@ -306,6 +314,7 @@ thunar_metafile_fetch (ThunarMetafile *metafile, /* use the default value */ use_default_value: + g_free (key_path); return default_value; } @@ -314,7 +323,7 @@ use_default_value: /** * thunar_metafile_store: * @metafile : a #ThunarMetafile. - * @path : a #ThunarVfsPath. + * @file : a #GFile. * @key : a #ThunarMetafileKey. * @value : the new value for @key on @path. * @default_value : the default value for @key on @path. @@ -332,7 +341,7 @@ use_default_value: **/ void thunar_metafile_store (ThunarMetafile *metafile, - ThunarVfsPath *path, + GFile *file, ThunarMetafileKey key, const gchar *value, const gchar *default_value) @@ -343,22 +352,22 @@ thunar_metafile_store (ThunarMetafile *metafile, gssize key_size; gchar *buffer; gchar *bp; - gchar key_path[THUNAR_VFS_PATH_MAXSTRLEN]; + gchar *key_path; _thunar_return_if_fail (THUNAR_IS_METAFILE (metafile)); + _thunar_return_if_fail (G_IS_FILE (file)); _thunar_return_if_fail (key < THUNAR_METAFILE_N_KEYS); - _thunar_return_if_fail (default_value != NULL); _thunar_return_if_fail (value != NULL); - _thunar_return_if_fail (path != NULL); + _thunar_return_if_fail (default_value != NULL); /* check if the database handle is available */ if (G_UNLIKELY (metafile->context == NULL)) return; - /* determine the string representation of the path (using the URI for non-local paths) */ - key_size = (thunar_vfs_path_get_scheme (path) == THUNAR_VFS_PATH_SCHEME_FILE) - ? thunar_vfs_path_to_string (path, key_path, sizeof (key_path), NULL) - : thunar_vfs_path_to_uri (path, key_path, sizeof (key_path), NULL); + /* determine the string representation of the file */ + key_path = g_file_get_uri (file); + key_size = strlen (key_path); + if (G_UNLIKELY (key_size <= 0)) return; @@ -440,6 +449,9 @@ thunar_metafile_store (ThunarMetafile *metafile, tdb_store (metafile->context, key_data, value_data, TDB_REPLACE); } + /* free the file URI */ + g_free (key_path); + /* free the buffer space */ g_free (buffer); } diff --git a/thunar/thunar-metafile.h b/thunar/thunar-metafile.h index edd4c20d1..bd70d1fc8 100644 --- a/thunar/thunar-metafile.h +++ b/thunar/thunar-metafile.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -20,7 +21,7 @@ #ifndef __THUNAR_METAFILE_H__ #define __THUNAR_METAFILE_H__ -#include <thunar-vfs/thunar-vfs.h> +#include <gio/gio.h> G_BEGIN_DECLS; @@ -49,12 +50,12 @@ GType thunar_metafile_get_type (void) G_GNUC_CONST; ThunarMetafile *thunar_metafile_get_default (void); const gchar *thunar_metafile_fetch (ThunarMetafile *metafile, - ThunarVfsPath *path, + GFile *file, ThunarMetafileKey key, const gchar *default_value); void thunar_metafile_store (ThunarMetafile *metafile, - ThunarVfsPath *path, + GFile *file, ThunarMetafileKey key, const gchar *value, const gchar *default_value); diff --git a/thunar/thunar-misc-jobs.c b/thunar/thunar-misc-jobs.c new file mode 100644 index 000000000..9005cefcb --- /dev/null +++ b/thunar/thunar-misc-jobs.c @@ -0,0 +1,104 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 + +#include <gio/gio.h> + +#include <thunar/thunar-io-scan-directory.h> +#include <thunar/thunar-job.h> +#include <thunar/thunar-misc-jobs.h> +#include <thunar/thunar-private.h> +#include <thunar/thunar-simple-job.h> + + + +static gboolean +_thunar_misc_jobs_load_templates (ThunarJob *job, + GValueArray *param_values, + GError **error) +{ + ThunarFile *file; + GtkWidget *menu; + GFile *home_dir; + GFile *templates_dir; + GList *files = NULL; + GList *lp; + GList *paths = NULL; + + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + _thunar_return_val_if_fail (param_values != NULL && param_values->n_values == 1, FALSE); + + menu = g_value_get_object (g_value_array_get_nth (param_values, 0)); + g_object_set_data (G_OBJECT (job), "menu", menu); + + home_dir = thunar_g_file_new_for_home (); + templates_dir = thunar_g_file_new_for_user_special_dir (G_USER_DIRECTORY_TEMPLATES); + + if (G_LIKELY (!g_file_equal (templates_dir, home_dir))) + { + paths = thunar_io_scan_directory (job, templates_dir, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + TRUE, NULL); + + /* turn the GFile list into a ThunarFile list */ + for (lp = g_list_last (paths); + lp != NULL && !exo_job_is_cancelled (EXO_JOB (job)); + lp = lp->prev) + { + file = thunar_file_get (lp->data, NULL); + if (G_LIKELY (file != NULL)) + files = g_list_prepend (files, file); + } + + /* free the GFile list */ + thunar_g_file_list_free (paths); + } + + g_object_unref (templates_dir); + g_object_unref (home_dir); + + if (files == NULL || exo_job_is_cancelled (EXO_JOB (job))) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + _("No templates installed")); + + return FALSE; + } + else + { + if (!thunar_job_files_ready (job, files)) + thunar_file_list_free (files); + + return TRUE; + } +} + + + +ThunarJob * +thunar_misc_jobs_load_template_files (GtkWidget *menu) +{ + return thunar_simple_job_launch (_thunar_misc_jobs_load_templates, 1, + GTK_TYPE_MENU, menu); +} diff --git a/thunar/thunar-misc-jobs.h b/thunar/thunar-misc-jobs.h new file mode 100644 index 000000000..21483af0b --- /dev/null +++ b/thunar/thunar-misc-jobs.h @@ -0,0 +1,32 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_MISC_JOBS_H__ +#define __THUNAR_MISC_JOBS_H__ + +#include <thunar/thunar-job.h> + +G_BEGIN_DECLS + +ThunarJob *thunar_misc_jobs_load_template_files (GtkWidget *menu); + +G_END_DECLS + +#endif /* !__THUNAR_MISC_JOBS_H__ */ diff --git a/thunar/thunar-path-entry.c b/thunar/thunar-path-entry.c index 69ab07787..2946f0218 100644 --- a/thunar/thunar-path-entry.c +++ b/thunar/thunar-path-entry.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -285,9 +286,7 @@ thunar_path_entry_init (ThunarPathEntry *path_entry) /* allocate a new entry completion for the given model */ completion = gtk_entry_completion_new (); -#if GTK_CHECK_VERSION(2,8,0) gtk_entry_completion_set_popup_single_match (completion, FALSE); -#endif gtk_entry_completion_set_match_func (completion, thunar_path_entry_match_func, path_entry, NULL); g_signal_connect (G_OBJECT (completion), "match-selected", G_CALLBACK (thunar_path_entry_match_selected), path_entry); @@ -749,15 +748,15 @@ thunar_path_entry_drag_data_get (GtkWidget *widget, guint time) { ThunarPathEntry *path_entry = THUNAR_PATH_ENTRY (widget); - GList path_list; + GList file_list; gchar *uri_string; /* verify that we actually display a path */ if (G_LIKELY (path_entry->current_file != NULL)) { /* transform the path for the current file into an uri string list */ - path_list.data = thunar_file_get_path (path_entry->current_file); path_list.next = path_list.prev = NULL; - uri_string = thunar_vfs_path_list_to_string (&path_list); + file_list.data = thunar_file_get_file (path_entry->current_file); file_list.next = file_list.prev = NULL; + uri_string = thunar_g_file_list_to_string (&file_list); /* setup the uri list for the drag selection */ gtk_selection_data_set (selection_data, selection_data->target, 8, (guchar *) uri_string, strlen (uri_string)); @@ -791,13 +790,13 @@ thunar_path_entry_changed (GtkEditable *editable) { GtkEntryCompletion *completion; ThunarPathEntry *path_entry = THUNAR_PATH_ENTRY (editable); - ThunarVfsPath *folder_path = NULL; - ThunarVfsPath *file_path = NULL; ThunarFolder *folder; GtkTreeModel *model; const gchar *text; ThunarFile *current_folder; ThunarFile *current_file; + GFile *folder_path = NULL; + GFile *file_path = NULL; gchar *folder_part = NULL; gchar *file_part = NULL; @@ -810,20 +809,24 @@ thunar_path_entry_changed (GtkEditable *editable) if (G_UNLIKELY (thunar_util_looks_like_an_uri (text))) { /* try to parse the URI text */ - file_path = thunar_vfs_path_new (text, NULL); + file_path = g_file_new_for_uri (text); + + /* use the same file if the text assumes we're in a directory */ + if (g_str_has_suffix (text, "/")) + folder_path = g_object_ref (G_OBJECT (file_path)); + else + folder_path = g_file_get_parent (file_path); } else if (thunar_path_entry_parse (path_entry, &folder_part, &file_part, NULL)) { /* determine the folder path */ - folder_path = thunar_vfs_path_new (folder_part, NULL); - if (G_LIKELY (folder_path != NULL)) - { - /* determine the relative file path */ - if (G_LIKELY (*file_part != '\0')) - file_path = thunar_vfs_path_relative (folder_path, file_part); - else - file_path = thunar_vfs_path_ref (folder_path); - } + folder_path = g_file_new_for_path (folder_part); + + /* determine the relative file path */ + if (G_LIKELY (*file_part != '\0')) + file_path = g_file_resolve_relative_path (folder_path, file_part); + else + file_path = g_object_ref (folder_path); /* cleanup the part strings */ g_free (folder_part); @@ -831,8 +834,8 @@ thunar_path_entry_changed (GtkEditable *editable) } /* determine new current file/folder from the paths */ - current_folder = (folder_path != NULL) ? thunar_file_get_for_path (folder_path, NULL) : NULL; - current_file = (file_path != NULL) ? thunar_file_get_for_path (file_path, NULL) : NULL; + current_folder = (folder_path != NULL) ? thunar_file_get (folder_path, NULL) : NULL; + current_file = (file_path != NULL) ? thunar_file_get (file_path, NULL) : NULL; /* determine the entry completion */ completion = gtk_entry_get_completion (GTK_ENTRY (path_entry)); @@ -848,7 +851,10 @@ thunar_path_entry_changed (GtkEditable *editable) g_object_ref (G_OBJECT (current_folder)); /* try to open the current-folder file as folder */ - folder = (current_folder != NULL) ? thunar_folder_get_for_file (current_folder) : NULL; + if (current_folder != NULL && thunar_file_is_directory (current_folder)) + folder = thunar_folder_get_for_file (current_folder); + else + folder = NULL; /* set the new folder for the completion model, but disconnect the model from the * completion first, because GtkEntryCompletion has become very slow recently when @@ -889,9 +895,9 @@ thunar_path_entry_changed (GtkEditable *editable) if (G_LIKELY (current_file != NULL)) g_object_unref (G_OBJECT (current_file)); if (G_LIKELY (folder_path != NULL)) - thunar_vfs_path_unref (folder_path); + g_object_unref (folder_path); if (G_LIKELY (file_path != NULL)) - thunar_vfs_path_unref (file_path); + g_object_unref (file_path); } @@ -1258,7 +1264,7 @@ thunar_path_entry_parse (ThunarPathEntry *path_entry, _thunar_return_val_if_fail (file_part != NULL, FALSE); /* expand the filename */ - filename = thunar_vfs_expand_filename (gtk_entry_get_text (GTK_ENTRY (path_entry)), error); + filename = thunar_util_expand_filename (gtk_entry_get_text (GTK_ENTRY (path_entry)), error); if (G_UNLIKELY (filename == NULL)) return FALSE; @@ -1399,38 +1405,45 @@ void thunar_path_entry_set_current_file (ThunarPathEntry *path_entry, ThunarFile *current_file) { - ThunarVfsPath *path; - gchar *text; + GFile *file; + gchar *text; + gchar *unescaped; _thunar_return_if_fail (THUNAR_IS_PATH_ENTRY (path_entry)); _thunar_return_if_fail (current_file == NULL || THUNAR_IS_FILE (current_file)); - path = (current_file != NULL) ? thunar_file_get_path (current_file) : NULL; - if (G_UNLIKELY (path == NULL)) + file = (current_file != NULL) ? thunar_file_get_file (current_file) : NULL; + if (G_UNLIKELY (file == NULL)) { /* invalid file */ text = g_strdup (""); } - else if (thunar_vfs_path_get_scheme (path) == THUNAR_VFS_PATH_SCHEME_FILE) + else { - /* try absolute path, fallback to URI if not valid UTF-8 */ - text = thunar_vfs_path_dup_string (path); - if (!g_utf8_validate (text, -1, NULL)) + /* check if the file is native to the platform */ + if (g_file_is_native (file)) { - g_free (text); - goto uri; + /* it is, try the local path first */ + text = g_file_get_path (file); + + /* if there is no local path, use the URI (which always works) */ + if (text == NULL) + text = g_file_get_uri (file); + } + else + { + /* not a native file, use the URI */ + text = g_file_get_uri (file); } - } - else - { -uri: /* display the URI for the path */ - text = thunar_vfs_path_dup_uri (path); } - /* setup the entry text */ - gtk_entry_set_text (GTK_ENTRY (path_entry), text); + unescaped = g_uri_unescape_string (text, NULL); g_free (text); + /* setup the entry text */ + gtk_entry_set_text (GTK_ENTRY (path_entry), unescaped); + g_free (unescaped); + gtk_editable_set_position (GTK_EDITABLE (path_entry), -1); gtk_widget_queue_draw (GTK_WIDGET (path_entry)); diff --git a/thunar/thunar-permissions-chooser.c b/thunar/thunar-permissions-chooser.c index f355db142..ffcd2b96c 100644 --- a/thunar/thunar-permissions-chooser.c +++ b/thunar/thunar-permissions-chooser.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -31,14 +32,18 @@ #include <unistd.h> #endif +#include <exo/exo.h> + #include <thunar/thunar-dialogs.h> #include <thunar/thunar-enum-types.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-gtk-extensions.h> +#include <thunar/thunar-io-jobs.h> #include <thunar/thunar-pango-extensions.h> #include <thunar/thunar-permissions-chooser.h> #include <thunar/thunar-preferences.h> #include <thunar/thunar-private.h> +#include <thunar/thunar-user.h> @@ -80,12 +85,12 @@ static void thunar_permissions_chooser_set_property (GObject GParamSpec *pspec); static gint thunar_permissions_chooser_ask_recursive (ThunarPermissionsChooser *chooser); static void thunar_permissions_chooser_change_group (ThunarPermissionsChooser *chooser, - ThunarVfsGroupId gid); + guint32 gid); static void thunar_permissions_chooser_change_mode (ThunarPermissionsChooser *chooser, - ThunarVfsFileMode dir_mask, - ThunarVfsFileMode dir_mode, - ThunarVfsFileMode file_mask, - ThunarVfsFileMode file_mode); + ThunarFileMode dir_mask, + ThunarFileMode dir_mode, + ThunarFileMode file_mask, + ThunarFileMode file_mode); static void thunar_permissions_chooser_access_changed (ThunarPermissionsChooser *chooser, GtkWidget *combo); static void thunar_permissions_chooser_file_changed (ThunarPermissionsChooser *chooser, @@ -96,21 +101,21 @@ static void thunar_permissions_chooser_program_toggled (ThunarP GtkWidget *button); static void thunar_permissions_chooser_fixperm_clicked (ThunarPermissionsChooser *chooser, GtkWidget *button); -static ThunarVfsJobResponse thunar_permissions_chooser_job_ask (ThunarPermissionsChooser *chooser, +static ThunarJobResponse thunar_permissions_chooser_job_ask (ThunarPermissionsChooser *chooser, const gchar *message, - ThunarVfsJobResponse choices, - ThunarVfsJob *job); + ThunarJobResponse choices, + ThunarJob *job); static void thunar_permissions_chooser_job_cancel (ThunarPermissionsChooser *chooser); static void thunar_permissions_chooser_job_error (ThunarPermissionsChooser *chooser, GError *error, - ThunarVfsJob *job); + ThunarJob *job); static void thunar_permissions_chooser_job_finished (ThunarPermissionsChooser *chooser, - ThunarVfsJob *job); + ThunarJob *job); static void thunar_permissions_chooser_job_percent (ThunarPermissionsChooser *chooser, gdouble percent, - ThunarVfsJob *job); + ThunarJob *job); static void thunar_permissions_chooser_job_start (ThunarPermissionsChooser *chooser, - ThunarVfsJob *job, + ThunarJob *job, gboolean recursive); static gboolean thunar_permissions_chooser_row_separator (GtkTreeModel *model, GtkTreeIter *iter, @@ -125,23 +130,23 @@ struct _ThunarPermissionsChooserClass struct _ThunarPermissionsChooser { - GtkVBox __parent__; + GtkVBox __parent__; - ThunarFile *file; + ThunarFile *file; /* the main table widget, which contains everything but the job control stuff */ - GtkWidget *table; + GtkWidget *table; - GtkWidget *user_label; - GtkWidget *group_combo; - GtkWidget *access_combos[3]; - GtkWidget *program_button; - GtkWidget *fixperm_label; - GtkWidget *fixperm_button; + GtkWidget *user_label; + GtkWidget *group_combo; + GtkWidget *access_combos[3]; + GtkWidget *program_button; + GtkWidget *fixperm_label; + GtkWidget *fixperm_button; /* job control stuff */ - ThunarVfsJob *job; - GtkWidget *job_progress; + ThunarJob *job; + GtkWidget *job_progress; }; @@ -456,11 +461,11 @@ thunar_permissions_chooser_finalize (GObject *object) if (G_UNLIKELY (chooser->job != NULL)) { /* cancel the job (if not already done) */ - thunar_vfs_job_cancel (chooser->job); + exo_job_cancel (EXO_JOB (chooser->job)); /* disconnect from the job */ g_signal_handlers_disconnect_matched (chooser->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, chooser); - g_object_unref (G_OBJECT (chooser->job)); + g_object_unref (chooser->job); chooser->job = NULL; } @@ -628,12 +633,11 @@ thunar_permissions_chooser_ask_recursive (ThunarPermissionsChooser *chooser) static void thunar_permissions_chooser_change_group (ThunarPermissionsChooser *chooser, - ThunarVfsGroupId gid) + guint32 gid) { - ThunarVfsJob *job; - gboolean recursive = FALSE; - GError *error = NULL; - gint response; + ThunarJob *job; + gboolean recursive = FALSE; + gint response; _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); _thunar_return_if_fail (THUNAR_IS_FILE (chooser->file)); @@ -659,34 +663,23 @@ thunar_permissions_chooser_change_group (ThunarPermissionsChooser *chooser, } /* try to allocate the new job */ - job = thunar_vfs_change_group (thunar_file_get_path (chooser->file), gid, recursive, &error); - if (G_UNLIKELY (job == NULL)) - { - /* display an error to the user */ - thunar_dialogs_show_error (GTK_WIDGET (chooser), error, _("Failed to change group")); - g_error_free (error); - } - else - { - /* handle the job */ - thunar_permissions_chooser_job_start (chooser, job, recursive); - g_object_unref (G_OBJECT (job)); - } + job = thunar_io_jobs_change_group (thunar_file_get_file (chooser->file), gid, recursive); + thunar_permissions_chooser_job_start (chooser, job, recursive); + g_object_unref (job); } static void thunar_permissions_chooser_change_mode (ThunarPermissionsChooser *chooser, - ThunarVfsFileMode dir_mask, - ThunarVfsFileMode dir_mode, - ThunarVfsFileMode file_mask, - ThunarVfsFileMode file_mode) + ThunarFileMode dir_mask, + ThunarFileMode dir_mode, + ThunarFileMode file_mask, + ThunarFileMode file_mode) { - ThunarVfsJob *job; - gboolean recursive = FALSE; - GError *error = NULL; - gint response; + ThunarJob*job; + gboolean recursive = FALSE; + gint response; _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); _thunar_return_if_fail (THUNAR_IS_FILE (chooser->file)); @@ -712,19 +705,11 @@ thunar_permissions_chooser_change_mode (ThunarPermissionsChooser *chooser, } /* try to allocate the new job */ - job = thunar_vfs_change_mode (thunar_file_get_path (chooser->file), dir_mask, dir_mode, file_mask, file_mode, recursive, &error); - if (G_UNLIKELY (job == NULL)) - { - /* display an error to the user */ - thunar_dialogs_show_error (GTK_WIDGET (chooser), error, _("Failed to apply new permissions")); - g_error_free (error); - } - else - { - /* handle the job */ - thunar_permissions_chooser_job_start (chooser, job, recursive); - g_object_unref (G_OBJECT (job)); - } + job = thunar_io_jobs_change_mode (thunar_file_get_file (chooser->file), + dir_mask, dir_mode, file_mask, file_mode, + recursive); + thunar_permissions_chooser_job_start (chooser, job, recursive); + g_object_unref (job); } @@ -733,11 +718,11 @@ static void thunar_permissions_chooser_access_changed (ThunarPermissionsChooser *chooser, GtkWidget *combo) { - ThunarVfsFileMode file_mask; - ThunarVfsFileMode file_mode; - ThunarVfsFileMode dir_mask; - ThunarVfsFileMode dir_mode; - guint n; + ThunarFileMode file_mask; + ThunarFileMode file_mode; + ThunarFileMode dir_mask; + ThunarFileMode dir_mode; + guint n; _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); _thunar_return_if_fail (GTK_IS_COMBO_BOX (combo)); @@ -747,7 +732,7 @@ thunar_permissions_chooser_access_changed (ThunarPermissionsChooser *chooser, return; /* determine the new mode from the combo box */ - for (n = 0; chooser->access_combos[n] != combo && n < G_N_ELEMENTS (chooser->access_combos); ++n); + for (n = 0; n < G_N_ELEMENTS (chooser->access_combos) && chooser->access_combos[n] != combo ; ++n); dir_mode = file_mode = (gtk_combo_box_get_active (GTK_COMBO_BOX (combo)) << 1) << (n * 3); dir_mask = file_mask = 0006 << (n * 3); @@ -771,9 +756,9 @@ group_compare (gconstpointer group_a, gconstpointer group_b, gpointer group_primary) { - ThunarVfsGroupId group_primary_id = thunar_vfs_group_get_id (THUNAR_VFS_GROUP (group_primary)); - ThunarVfsGroupId group_a_id = thunar_vfs_group_get_id (THUNAR_VFS_GROUP (group_a)); - ThunarVfsGroupId group_b_id = thunar_vfs_group_get_id (THUNAR_VFS_GROUP (group_b)); + guint32 group_primary_id = thunar_group_get_id (THUNAR_GROUP (group_primary)); + guint32 group_a_id = thunar_group_get_id (THUNAR_GROUP (group_a)); + guint32 group_b_id = thunar_group_get_id (THUNAR_GROUP (group_b)); /* check if the groups are equal */ if (group_a_id == group_b_id) @@ -792,7 +777,8 @@ group_compare (gconstpointer group_a, return -1; /* otherwise just sort by name */ - return g_ascii_strcasecmp (thunar_vfs_group_get_name (THUNAR_VFS_GROUP (group_a)), thunar_vfs_group_get_name (THUNAR_VFS_GROUP (group_b))); + return g_ascii_strcasecmp (thunar_group_get_name (THUNAR_GROUP (group_a)), + thunar_group_get_name (THUNAR_GROUP (group_b))); } @@ -801,18 +787,18 @@ static void thunar_permissions_chooser_file_changed (ThunarPermissionsChooser *chooser, ThunarFile *file) { - ThunarVfsUserManager *user_manager; - ThunarVfsFileMode mode; - ThunarVfsGroup *group; - ThunarVfsUser *user; - GtkListStore *store; - GtkTreeIter iter; - const gchar *user_name; - const gchar *real_name; - GList *groups; - GList *lp; - gchar buffer[1024]; - guint n; + ThunarUserManager *user_manager; + ThunarFileMode mode; + ThunarGroup *group; + ThunarUser *user; + GtkListStore *store; + GtkTreeIter iter; + const gchar *user_name; + const gchar *real_name; + GList *groups; + GList *lp; + gchar buffer[1024]; + guint n; _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); _thunar_return_if_fail (THUNAR_IS_FILE (file)); @@ -835,14 +821,14 @@ thunar_permissions_chooser_file_changed (ThunarPermissionsChooser *chooser, if (G_UNLIKELY (geteuid () == 0)) { /* determine all groups in the system */ - user_manager = thunar_vfs_user_manager_get_default (); - groups = thunar_vfs_user_manager_get_all_groups (user_manager); + user_manager = thunar_user_manager_get_default (); + groups = thunar_user_manager_get_all_groups (user_manager); g_object_unref (G_OBJECT (user_manager)); } else { /* determine the groups for the user and take a copy */ - groups = g_list_copy (thunar_vfs_user_get_groups (user)); + groups = g_list_copy (thunar_user_get_groups (user)); g_list_foreach (groups, (GFunc) g_object_ref, NULL); } @@ -857,12 +843,13 @@ thunar_permissions_chooser_file_changed (ThunarPermissionsChooser *chooser, for (lp = groups, n = 0; lp != NULL; lp = lp->next) { /* append a separator after the primary group and after the user-groups (not system groups) */ - if (thunar_vfs_group_get_id (groups->data) == thunar_vfs_group_get_id (group) && lp != groups && n == 0) + if (thunar_group_get_id (groups->data) == thunar_group_get_id (group) + && lp != groups && n == 0) { gtk_list_store_append (store, &iter); n += 1; } - else if (lp != groups && thunar_vfs_group_get_id (lp->data) < 100 && n == 1) + else if (lp != groups && thunar_group_get_id (lp->data) < 100 && n == 1) { gtk_list_store_append (store, &iter); n += 1; @@ -871,8 +858,8 @@ thunar_permissions_chooser_file_changed (ThunarPermissionsChooser *chooser, /* append a new item for the group */ gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, - THUNAR_PERMISSIONS_STORE_COLUMN_NAME, thunar_vfs_group_get_name (lp->data), - THUNAR_PERMISSIONS_STORE_COLUMN_GID, thunar_vfs_group_get_id (lp->data), + THUNAR_PERMISSIONS_STORE_COLUMN_NAME, thunar_group_get_name (lp->data), + THUNAR_PERMISSIONS_STORE_COLUMN_GID, thunar_group_get_id (lp->data), -1); /* set the active iter for the combo box if this group is the primary group */ @@ -887,8 +874,8 @@ thunar_permissions_chooser_file_changed (ThunarPermissionsChooser *chooser, } /* determine sane display name for the owner */ - user_name = thunar_vfs_user_get_name (user); - real_name = thunar_vfs_user_get_real_name (user); + user_name = thunar_user_get_name (user); + real_name = thunar_user_get_real_name (user); if (G_LIKELY (real_name != NULL)) g_snprintf (buffer, sizeof (buffer), "%s (%s)", real_name, user_name); else @@ -948,9 +935,9 @@ static void thunar_permissions_chooser_group_changed (ThunarPermissionsChooser *chooser, GtkWidget *combo) { - ThunarVfsGroupId gid; - GtkTreeModel *model; - GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeIter iter; + guint32 gid; _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); _thunar_return_if_fail (chooser->group_combo == combo); @@ -980,7 +967,7 @@ static void thunar_permissions_chooser_program_toggled (ThunarPermissionsChooser *chooser, GtkWidget *button) { - ThunarVfsFileMode mode; + ThunarFileMode mode; _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); _thunar_return_if_fail (chooser->program_button == button); @@ -1003,12 +990,11 @@ static void thunar_permissions_chooser_fixperm_clicked (ThunarPermissionsChooser *chooser, GtkWidget *button) { - ThunarVfsFileMode mode; - ThunarVfsJob *job; - GtkWidget *dialog; - GtkWidget *window; - GError *error = NULL; - gint response; + ThunarFileMode mode; + GtkWidget *dialog; + GtkWidget *window; + ThunarJob *job; + gint response; _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); _thunar_return_if_fail (chooser->fixperm_button == button); @@ -1046,41 +1032,34 @@ thunar_permissions_chooser_fixperm_clicked (ThunarPermissionsChooser *chooser, mode = thunar_file_get_mode (chooser->file); /* determine the new mode (making sure the owner can read/enter the folder) */ - mode = (THUNAR_VFS_FILE_MODE_USR_READ | THUNAR_VFS_FILE_MODE_USR_EXEC) - | (((mode & THUNAR_VFS_FILE_MODE_GRP_READ) != 0) ? THUNAR_VFS_FILE_MODE_GRP_EXEC : 0) - | (((mode & THUNAR_VFS_FILE_MODE_OTH_READ) != 0) ? THUNAR_VFS_FILE_MODE_OTH_EXEC : 0); + mode = (THUNAR_FILE_MODE_USR_READ | THUNAR_FILE_MODE_USR_EXEC) + | (((mode & THUNAR_FILE_MODE_GRP_READ) != 0) ? THUNAR_FILE_MODE_GRP_EXEC : 0) + | (((mode & THUNAR_FILE_MODE_OTH_READ) != 0) ? THUNAR_FILE_MODE_OTH_EXEC : 0); /* try to allocate the new job */ - job = thunar_vfs_change_mode (thunar_file_get_path (chooser->file), 0511, mode, 0000, 0000, FALSE, &error); - if (G_UNLIKELY (job == NULL)) - { - /* display an error to the user */ - thunar_dialogs_show_error (GTK_WIDGET (chooser), error, _("Failed to apply new permissions")); - g_error_free (error); - } - else - { - /* handle the job */ - thunar_permissions_chooser_job_start (chooser, job, FALSE); - g_object_unref (G_OBJECT (job)); - } + job = thunar_io_jobs_change_mode (thunar_file_get_file (chooser->file), + 0511, mode, 0000, 0000, FALSE); + + /* handle the job */ + thunar_permissions_chooser_job_start (chooser, job, FALSE); + g_object_unref (job); } } -static ThunarVfsJobResponse +static ThunarJobResponse thunar_permissions_chooser_job_ask (ThunarPermissionsChooser *chooser, const gchar *message, - ThunarVfsJobResponse choices, - ThunarVfsJob *job) + ThunarJobResponse choices, + ThunarJob *job) { GtkWidget *toplevel; - _thunar_return_val_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (g_utf8_validate (message, -1, NULL), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (THUNAR_VFS_IS_JOB (job), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (chooser->job == job, THUNAR_VFS_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (g_utf8_validate (message, -1, NULL), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (chooser->job == job, THUNAR_JOB_RESPONSE_CANCEL); /* be sure to display the progress bar prior to opening the question dialog */ gtk_widget_show_now (chooser->job_progress); @@ -1088,7 +1067,7 @@ thunar_permissions_chooser_job_ask (ThunarPermissionsChooser *chooser, /* determine the toplevel window for the chooser */ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (chooser)); if (G_UNLIKELY (toplevel == NULL)) - return THUNAR_VFS_JOB_RESPONSE_CANCEL; + return THUNAR_JOB_RESPONSE_CANCEL; /* display the question dialog */ return thunar_dialogs_show_job_ask (GTK_WINDOW (toplevel), message, choices); @@ -1106,7 +1085,7 @@ thunar_permissions_chooser_job_cancel (ThunarPermissionsChooser *chooser) return; /* cancel the job (if not already done) */ - thunar_vfs_job_cancel (chooser->job); + exo_job_cancel (EXO_JOB (chooser->job)); /* disconnect from the job */ g_signal_handlers_disconnect_matched (chooser->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, chooser); @@ -1125,13 +1104,13 @@ thunar_permissions_chooser_job_cancel (ThunarPermissionsChooser *chooser) static void thunar_permissions_chooser_job_error (ThunarPermissionsChooser *chooser, GError *error, - ThunarVfsJob *job) + ThunarJob *job) { GtkWidget *toplevel; _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); _thunar_return_if_fail (error != NULL && error->message != NULL); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); _thunar_return_if_fail (chooser->job == job); /* be sure to display the progress bar prior to opening the error dialog */ @@ -1150,10 +1129,10 @@ thunar_permissions_chooser_job_error (ThunarPermissionsChooser *chooser, static void thunar_permissions_chooser_job_finished (ThunarPermissionsChooser *chooser, - ThunarVfsJob *job) + ThunarJob *job) { _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); _thunar_return_if_fail (chooser->job == job); /* we can just use job_cancel(), since the job is already done */ @@ -1165,10 +1144,10 @@ thunar_permissions_chooser_job_finished (ThunarPermissionsChooser *chooser, static void thunar_permissions_chooser_job_percent (ThunarPermissionsChooser *chooser, gdouble percent, - ThunarVfsJob *job) + ThunarJob *job) { _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); _thunar_return_if_fail (chooser->job == job); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (chooser->job_progress), percent / 100.0); @@ -1179,22 +1158,22 @@ thunar_permissions_chooser_job_percent (ThunarPermissionsChooser *chooser, static void thunar_permissions_chooser_job_start (ThunarPermissionsChooser *chooser, - ThunarVfsJob *job, + ThunarJob *job, gboolean recursive) { _thunar_return_if_fail (THUNAR_IS_PERMISSIONS_CHOOSER (chooser)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); _thunar_return_if_fail (chooser->job == NULL); /* take a reference to the job and connect signals */ - chooser->job = g_object_ref (G_OBJECT (job)); - g_signal_connect_swapped (G_OBJECT (job), "ask", G_CALLBACK (thunar_permissions_chooser_job_ask), chooser); - g_signal_connect_swapped (G_OBJECT (job), "error", G_CALLBACK (thunar_permissions_chooser_job_error), chooser); - g_signal_connect_swapped (G_OBJECT (job), "finished", G_CALLBACK (thunar_permissions_chooser_job_finished), chooser); + chooser->job = g_object_ref (job); + g_signal_connect_swapped (job, "ask", G_CALLBACK (thunar_permissions_chooser_job_ask), chooser); + g_signal_connect_swapped (job, "error", G_CALLBACK (thunar_permissions_chooser_job_error), chooser); + g_signal_connect_swapped (job, "finished", G_CALLBACK (thunar_permissions_chooser_job_finished), chooser); /* don't connect percent for single file operations */ if (G_UNLIKELY (recursive)) - g_signal_connect_swapped (G_OBJECT (job), "percent", G_CALLBACK (thunar_permissions_chooser_job_percent), chooser); + g_signal_connect_swapped (job, "percent", G_CALLBACK (thunar_permissions_chooser_job_percent), chooser); /* setup the progress bar */ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (chooser->job_progress), 0.0); diff --git a/thunar/thunar-preferences-dialog.c b/thunar/thunar-preferences-dialog.c index fe333618e..4baa69365 100644 --- a/thunar/thunar-preferences-dialog.c +++ b/thunar/thunar-preferences-dialog.c @@ -199,23 +199,21 @@ thunar_preferences_dialog_class_init (ThunarPreferencesDialogClass *klass) static void thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog) { - ThunarVfsVolumeManager *volume_manager; - ThunarDateStyle date_style; - GtkAdjustment *adjustment; - GtkWidget *notebook; - GtkWidget *button; - GtkWidget *align; - GtkWidget *combo; - GtkWidget *frame; - GtkWidget *image; - GtkWidget *label; - GtkWidget *range; - GtkWidget *table; - GtkWidget *hbox; - GtkWidget *ibox; - GtkWidget *vbox; - gchar *path; - gchar *date; + ThunarDateStyle date_style; + GtkAdjustment *adjustment; + GtkWidget *notebook; + GtkWidget *button; + GtkWidget *align; + GtkWidget *combo; + GtkWidget *frame; + GtkWidget *label; + GtkWidget *range; + GtkWidget *table; + GtkWidget *hbox; + GtkWidget *ibox; + GtkWidget *vbox; + gchar *path; + gchar *date; /* grab a reference on the preferences */ dialog->preferences = thunar_preferences_get (); @@ -272,9 +270,6 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog) gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Detailed List View")); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Compact List View")); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Last Active View")); -#if !GTK_CHECK_VERSION(2,9,0) - g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (g_object_notify), "active"); -#endif exo_mutual_binding_new_full (G_OBJECT (dialog->preferences), "default-view", G_OBJECT (combo), "active", transform_view_string_to_index, transform_view_index_to_string, NULL, NULL); gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); @@ -345,9 +340,6 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog) gtk_combo_box_append_text (GTK_COMBO_BOX (combo), date); g_free (date); } -#if !GTK_CHECK_VERSION(2,9,0) - g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (g_object_notify), "active"); -#endif exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-date-style", G_OBJECT (combo), "active"); gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), combo); @@ -392,9 +384,6 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog) gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Large")); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Larger")); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Very Large")); -#if !GTK_CHECK_VERSION(2,9,0) - g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (g_object_notify), "active"); -#endif exo_mutual_binding_new_full (G_OBJECT (dialog->preferences), "shortcuts-icon-size", G_OBJECT (combo), "active", transform_icon_size_to_index, transform_index_to_icon_size, NULL, NULL); gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); @@ -437,9 +426,6 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog) gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Large")); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Larger")); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Very Large")); -#if !GTK_CHECK_VERSION(2,9,0) - g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (g_object_notify), "active"); -#endif exo_mutual_binding_new_full (G_OBJECT (dialog->preferences), "tree-icon-size", G_OBJECT (combo), "active", transform_icon_size_to_index, transform_index_to_icon_size, NULL, NULL); gtk_table_attach (GTK_TABLE (table), combo, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); @@ -591,9 +577,6 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog) gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Ask everytime")); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Apply to Folder Only")); gtk_combo_box_append_text (GTK_COMBO_BOX (combo), _("Apply to Folder and Contents")); -#if !GTK_CHECK_VERSION(2,9,0) - g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (g_object_notify), "active"); -#endif exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-recursive-permissions", G_OBJECT (combo), "active"); gtk_table_attach (GTK_TABLE (table), combo, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); thunar_gtk_label_set_a11y_relation (GTK_LABEL (label), combo); @@ -615,52 +598,26 @@ thunar_preferences_dialog_init (ThunarPreferencesDialog *dialog) gtk_container_add (GTK_CONTAINER (frame), table); gtk_widget_show (table); - /* determine the active volume manager */ - volume_manager = thunar_vfs_volume_manager_get_default (); - /* check if "thunar-volman" is found */ path = g_find_program_in_path ("thunar-volman"); - /* check if we lack volume management support and should warn the user */ - if (g_signal_lookup ("device-added", G_OBJECT_TYPE (volume_manager)) == 0 || path == NULL) - { - /* add a warning telling the user that volume management is not available */ - image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DND); - gtk_misc_set_alignment (GTK_MISC (image), 0.5f, 0.5f); - gtk_table_attach (GTK_TABLE (table), image, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); - gtk_widget_show (image); - - label = gtk_label_new ((path == NULL) - ? _("Install the \"thunar-volman\" package to use\nthe volume management support in Thunar.") - : _("Build thunar-vfs with HAL support to use\nthe volume management support in Thunar.")); - gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); - gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); - gtk_widget_show (label); - - /* make sure to disable "misc-volume-management" then */ - g_object_set (G_OBJECT (dialog->preferences), "misc-volume-management", FALSE, NULL); - } - else - { - /* add check button to enable/disable auto mounting */ - button = gtk_check_button_new_with_mnemonic (_("Enable _Volume Management")); - exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-volume-management", G_OBJECT (button), "active"); - gtk_table_attach (GTK_TABLE (table), button, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); - gtk_widget_show (button); - - label = sexy_url_label_new (); - gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); - exo_binding_new (G_OBJECT (button), "active", G_OBJECT (label), "sensitive"); - g_signal_connect_swapped (G_OBJECT (label), "url-activated", G_CALLBACK (thunar_preferences_dialog_configure), dialog); - /* TRANSLATORS: Make sure you place the <a>...</a>-link on the first line, otherwise the user will be unable to click on it */ - sexy_url_label_set_markup (SEXY_URL_LABEL (label), _("<a href=\"volman-config:\">Configure</a> the management of removable drives\n" - "and media (i.e. how cameras should be handled).")); - gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); - gtk_widget_show (label); - } + /* add check button to enable/disable auto mounting */ + button = gtk_check_button_new_with_mnemonic (_("Enable _Volume Management")); + exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-volume-management", G_OBJECT (button), "active"); + gtk_table_attach (GTK_TABLE (table), button, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (button); + + label = sexy_url_label_new (); + gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f); + exo_binding_new (G_OBJECT (button), "active", G_OBJECT (label), "sensitive"); + g_signal_connect_swapped (G_OBJECT (label), "url-activated", G_CALLBACK (thunar_preferences_dialog_configure), dialog); + /* TRANSLATORS: Make sure you place the <a>...</a>-link on the first line, otherwise the user will be unable to click on it */ + sexy_url_label_set_markup (SEXY_URL_LABEL (label), _("<a href=\"volman-config:\">Configure</a> the management of removable drives\n" + "and media (i.e. how cameras should be handled).")); + gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show (label); /* cleanup */ - g_object_unref (G_OBJECT (volume_manager)); g_free (path); } diff --git a/thunar/thunar-preferences.c b/thunar/thunar-preferences.c index 378fc4b40..daed42f39 100644 --- a/thunar/thunar-preferences.c +++ b/thunar/thunar-preferences.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -37,8 +38,6 @@ #include <string.h> #endif -#include <thunar-vfs/thunar-vfs.h> - #include <thunar/thunar-enum-types.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-preferences.h> @@ -102,11 +101,10 @@ static void thunar_preferences_set_property (GObject *o GParamSpec *pspec); static void thunar_preferences_resume_monitor (ThunarPreferences *preferences); static void thunar_preferences_suspend_monitor (ThunarPreferences *preferences); -static void thunar_preferences_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, +static void thunar_preferences_monitor (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, gpointer user_data); static void thunar_preferences_queue_load (ThunarPreferences *preferences); static void thunar_preferences_queue_store (ThunarPreferences *preferences); @@ -126,15 +124,14 @@ struct _ThunarPreferences { GObject __parent__; - ThunarVfsMonitorHandle *handle; - ThunarVfsMonitor *monitor; + GFileMonitor *monitor; - GValue values[N_PROPERTIES]; + GValue values[N_PROPERTIES]; - gboolean loading_in_progress; + gboolean loading_in_progress; - gint load_idle_id; - gint store_idle_id; + gint load_idle_id; + gint store_idle_id; }; @@ -671,8 +668,7 @@ thunar_preferences_class_init (ThunarPreferencesClass *klass) static void thunar_preferences_init (ThunarPreferences *preferences) { - /* grab a reference on the VFS monitor */ - preferences->monitor = thunar_vfs_monitor_get_default (); + preferences->monitor = NULL; /* load the settings */ thunar_preferences_load_idle (preferences); @@ -763,24 +759,22 @@ thunar_preferences_set_property (GObject *object, static void thunar_preferences_resume_monitor (ThunarPreferences *preferences) { - ThunarVfsPath *path; - gchar *filename; + GFile *file; + gchar *filename; /* verify that the monitor is suspended */ - if (G_LIKELY (preferences->handle == NULL)) + if (G_LIKELY (preferences->monitor == NULL)) { /* determine the save location for thunarrc to monitor */ filename = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "Thunar/thunarrc", TRUE); if (G_LIKELY (filename != NULL)) { - /* determine the VFS path for the filename */ - path = thunar_vfs_path_new (filename, NULL); - if (G_LIKELY (path != NULL)) - { - /* add the monitor handle for the file */ - preferences->handle = thunar_vfs_monitor_add_file (preferences->monitor, path, thunar_preferences_monitor, preferences); - thunar_vfs_path_unref (path); - } + /* monitor this file */ + file = g_file_new_for_path (filename); + preferences->monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL); + if (G_LIKELY (preferences->monitor != NULL)) + g_signal_connect (preferences->monitor, "changed", G_CALLBACK (thunar_preferences_monitor), preferences); + g_object_unref (file); /* release the filename */ g_free (filename); @@ -794,34 +788,35 @@ static void thunar_preferences_suspend_monitor (ThunarPreferences *preferences) { /* verify that the monitor is active */ - if (G_LIKELY (preferences->handle != NULL)) + if (G_LIKELY (preferences->monitor != NULL + && !g_file_monitor_is_cancelled (preferences->monitor))) { /* disconnect the handle from the monitor */ - thunar_vfs_monitor_remove (preferences->monitor, preferences->handle); - preferences->handle = NULL; + g_file_monitor_cancel (preferences->monitor); } } static void -thunar_preferences_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, +thunar_preferences_monitor (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, gpointer user_data) { ThunarPreferences *preferences = THUNAR_PREFERENCES (user_data); _thunar_return_if_fail (THUNAR_IS_PREFERENCES (preferences)); - _thunar_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); + _thunar_return_if_fail (G_IS_FILE_MONITOR (monitor)); _thunar_return_if_fail (preferences->monitor == monitor); - _thunar_return_if_fail (preferences->handle == handle); /* schedule a reload whenever the file is created/changed */ - if (event == THUNAR_VFS_MONITOR_EVENT_CHANGED || event == THUNAR_VFS_MONITOR_EVENT_CREATED) - thunar_preferences_queue_load (preferences); + if (event_type == G_FILE_MONITOR_EVENT_CHANGED + || event_type == G_FILE_MONITOR_EVENT_CREATED) + { + thunar_preferences_queue_load (preferences); + } } diff --git a/thunar/thunar-private.h b/thunar/thunar-private.h index 1e1097d7c..5411eae7a 100644 --- a/thunar/thunar-private.h +++ b/thunar/thunar-private.h @@ -91,8 +91,6 @@ G_STMT_START{ \ }G_STMT_END #endif -#if GLIB_CHECK_VERSION(2,14,0) - #define XDG_USER_DIRS_PACKAGE "xdg-user-dirs" #define LOCALE_FILE_NAME "user-dirs.locale" @@ -107,27 +105,9 @@ typedef GUserDirectory ThunarUserDirectory; #define THUNAR_USER_DIRECTORY_VIDEOS G_USER_DIRECTORY_VIDEOS #define THUNAR_USER_N_DIRECTORIES (8) -#if GLIB_CHECK_VERSION(2, 14, 0) gchar *_thunar_get_xdg_user_dirs_locale (void); -#endif extern const gchar *_thunar_user_directory_names[THUNAR_USER_N_DIRECTORIES+1]; -#else /* GLIB_CHECK_VERSION(2,14,0) */ -typedef enum -{ - THUNAR_USER_DIRECTORY_DESKTOP = 0, - THUNAR_USER_DIRECTORY_DOCUMENTS, - THUNAR_USER_DIRECTORY_DOWNLOAD, - THUNAR_USER_DIRECTORY_MUSIC, - THUNAR_USER_DIRECTORY_PICTURES, - THUNAR_USER_DIRECTORY_PUBLIC_SHARE, - THUNAR_USER_DIRECTORY_TEMPLATES, - THUNAR_USER_DIRECTORY_VIDEOS, - THUNAR_USER_N_DIRECTORIES -} ThunarUserDirectory; - -#endif /*GLIB_CHECK_VERSION(2,14,0) */ - G_END_DECLS; #endif /* !__THUNAR_PRIVATE_H__ */ diff --git a/thunar/thunar-progress-dialog.c b/thunar/thunar-progress-dialog.c index b6cc02205..a9153862d 100644 --- a/thunar/thunar-progress-dialog.c +++ b/thunar/thunar-progress-dialog.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -23,6 +24,7 @@ #include <thunar/thunar-dialogs.h> #include <thunar/thunar-gobject-extensions.h> +#include <thunar/thunar-job.h> #include <thunar/thunar-pango-extensions.h> #include <thunar/thunar-private.h> #include <thunar/thunar-progress-dialog.h> @@ -37,38 +39,38 @@ enum -static void thunar_progress_dialog_class_init (ThunarProgressDialogClass *klass); -static void thunar_progress_dialog_init (ThunarProgressDialog *dialog); -static void thunar_progress_dialog_dispose (GObject *object); -static void thunar_progress_dialog_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void thunar_progress_dialog_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void thunar_progress_dialog_response (GtkDialog *dialog, - gint response); -static ThunarVfsJobResponse thunar_progress_dialog_ask (ThunarProgressDialog *dialog, - const gchar *message, - ThunarVfsJobResponse choices, - ThunarVfsJob *job); -static ThunarVfsJobResponse thunar_progress_dialog_ask_replace (ThunarProgressDialog *dialog, - ThunarVfsInfo *src_info, - ThunarVfsInfo *dst_info, - ThunarVfsJob *job); -static void thunar_progress_dialog_error (ThunarProgressDialog *dialog, - GError *error, - ThunarVfsJob *job); -static void thunar_progress_dialog_finished (ThunarProgressDialog *dialog, - ThunarVfsJob *job); -static void thunar_progress_dialog_info_message (ThunarProgressDialog *dialog, - const gchar *message, - ThunarVfsJob *job); -static void thunar_progress_dialog_percent (ThunarProgressDialog *dialog, - gdouble percent, - ThunarVfsJob *job); +static void thunar_progress_dialog_class_init (ThunarProgressDialogClass *klass); +static void thunar_progress_dialog_init (ThunarProgressDialog *dialog); +static void thunar_progress_dialog_dispose (GObject *object); +static void thunar_progress_dialog_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void thunar_progress_dialog_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void thunar_progress_dialog_response (GtkDialog *dialog, + gint response); +static ThunarJobResponse thunar_progress_dialog_ask (ThunarProgressDialog *dialog, + const gchar *message, + ThunarJobResponse choices, + ThunarJob *job); +static ThunarJobResponse thunar_progress_dialog_ask_replace (ThunarProgressDialog *dialog, + ThunarFile *src_file, + ThunarFile *dst_file, + ThunarJob *job); +static void thunar_progress_dialog_error (ThunarProgressDialog *dialog, + GError *error, + ExoJob *job); +static void thunar_progress_dialog_finished (ThunarProgressDialog *dialog, + ExoJob *job); +static void thunar_progress_dialog_info_message (ThunarProgressDialog *dialog, + const gchar *message, + ExoJob *job); +static void thunar_progress_dialog_percent (ThunarProgressDialog *dialog, + gdouble percent, + ExoJob *job); @@ -79,15 +81,15 @@ struct _ThunarProgressDialogClass struct _ThunarProgressDialog { - GtkDialog __parent__; + GtkDialog __parent__; - ThunarVfsJob *job; + ThunarJob *job; - GTimeVal start_time; - GTimeVal last_update_time; + GTimeVal start_time; + GTimeVal last_update_time; - GtkWidget *progress_bar; - GtkWidget *progress_label; + GtkWidget *progress_bar; + GtkWidget *progress_label; }; @@ -145,13 +147,13 @@ thunar_progress_dialog_class_init (ThunarProgressDialogClass *klass) /** * ThunarProgressDialog:job: * - * The #ThunarVfsJob, whose progress is displayed by - * this dialog, or %NULL if no job is set. + * The #ThunarJob, whose progress is displayed by this dialog, or + * %NULL if no job is set. **/ g_object_class_install_property (gobject_class, PROP_JOB, g_param_spec_object ("job", "job", "job", - THUNAR_VFS_TYPE_JOB, + THUNAR_TYPE_JOB, EXO_PARAM_READWRITE)); } @@ -267,16 +269,16 @@ thunar_progress_dialog_set_property (GObject *object, -static ThunarVfsJobResponse +static ThunarJobResponse thunar_progress_dialog_ask (ThunarProgressDialog *dialog, const gchar *message, - ThunarVfsJobResponse choices, - ThunarVfsJob *job) + ThunarJobResponse choices, + ThunarJob *job) { - _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (g_utf8_validate (message, -1, NULL), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (THUNAR_VFS_IS_JOB (job), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (dialog->job == job, THUNAR_VFS_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (g_utf8_validate (message, -1, NULL), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (dialog->job == job, THUNAR_JOB_RESPONSE_CANCEL); /* be sure to display the progress dialog prior to opening the question dialog */ gtk_widget_show_now (GTK_WIDGET (dialog)); @@ -287,21 +289,23 @@ thunar_progress_dialog_ask (ThunarProgressDialog *dialog, -static ThunarVfsJobResponse +static ThunarJobResponse thunar_progress_dialog_ask_replace (ThunarProgressDialog *dialog, - ThunarVfsInfo *src_info, - ThunarVfsInfo *dst_info, - ThunarVfsJob *job) + ThunarFile *src_file, + ThunarFile *dst_file, + ThunarJob *job) { - _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (THUNAR_VFS_IS_JOB (job), THUNAR_VFS_JOB_RESPONSE_CANCEL); - _thunar_return_val_if_fail (dialog->job == job, THUNAR_VFS_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_JOB (job), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (dialog->job == job, THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (src_file), THUNAR_JOB_RESPONSE_CANCEL); + _thunar_return_val_if_fail (THUNAR_IS_FILE (dst_file), THUNAR_JOB_RESPONSE_CANCEL); /* be sure to display the progress dialog prior to opening the question dialog */ gtk_widget_show_now (GTK_WIDGET (dialog)); /* display the question dialog */ - return thunar_dialogs_show_job_ask_replace (GTK_WINDOW (dialog), src_info, dst_info); + return thunar_dialogs_show_job_ask_replace (GTK_WINDOW (dialog), src_file, dst_file); } @@ -309,12 +313,12 @@ thunar_progress_dialog_ask_replace (ThunarProgressDialog *dialog, static void thunar_progress_dialog_error (ThunarProgressDialog *dialog, GError *error, - ThunarVfsJob *job) + ExoJob *job) { _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog)); _thunar_return_if_fail (error != NULL && error->message != NULL); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_return_if_fail (dialog->job == job); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); + _thunar_return_if_fail (dialog->job == THUNAR_JOB (job)); /* be sure to display the progress dialog prior to opening the error dialog */ gtk_widget_show_now (GTK_WIDGET (dialog)); @@ -327,11 +331,11 @@ thunar_progress_dialog_error (ThunarProgressDialog *dialog, static void thunar_progress_dialog_finished (ThunarProgressDialog *dialog, - ThunarVfsJob *job) + ExoJob *job) { _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_return_if_fail (dialog->job == job); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); + _thunar_return_if_fail (dialog->job == THUNAR_JOB (job)); gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); } @@ -341,12 +345,12 @@ thunar_progress_dialog_finished (ThunarProgressDialog *dialog, static void thunar_progress_dialog_info_message (ThunarProgressDialog *dialog, const gchar *message, - ThunarVfsJob *job) + ExoJob *job) { _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog)); _thunar_return_if_fail (g_utf8_validate (message, -1, NULL)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_return_if_fail (dialog->job == job); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); + _thunar_return_if_fail (dialog->job == THUNAR_JOB (job)); gtk_label_set_text (GTK_LABEL (dialog->progress_label), message); } @@ -366,7 +370,7 @@ time_diff (const GTimeVal *now, static void thunar_progress_dialog_percent (ThunarProgressDialog *dialog, gdouble percent, - ThunarVfsJob *job) + ExoJob *job) { GTimeVal current_time; gulong remaining_time; @@ -375,8 +379,8 @@ thunar_progress_dialog_percent (ThunarProgressDialog *dialog, _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog)); _thunar_return_if_fail (percent >= 0.0 && percent <= 100.0); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_return_if_fail (dialog->job == job); + _thunar_return_if_fail (THUNAR_IS_JOB (job)); + _thunar_return_if_fail (dialog->job == THUNAR_JOB (job)); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (dialog->progress_bar), percent / 100.0); @@ -438,7 +442,7 @@ thunar_progress_dialog_response (GtkDialog *dialog, case GTK_RESPONSE_CLOSE: case GTK_RESPONSE_NO: if (G_LIKELY (THUNAR_PROGRESS_DIALOG (dialog)->job != NULL)) - thunar_vfs_job_cancel (THUNAR_PROGRESS_DIALOG (dialog)->job); + exo_job_cancel (EXO_JOB (THUNAR_PROGRESS_DIALOG (dialog)->job)); break; } @@ -465,17 +469,16 @@ thunar_progress_dialog_new (void) /** * thunar_progress_dialog_new_with_job: - * @job : a #ThunarVfsJob or %NULL. + * @job : a #ThunarJob or %NULL. * - * Allocates a new #ThunarProgressDialog and associates it with - * the @job. + * Allocates a new #ThunarProgressDialog and associates it with the @job. * * Return value: the newly allocated #ThunarProgressDialog. **/ GtkWidget* -thunar_progress_dialog_new_with_job (ThunarVfsJob *job) +thunar_progress_dialog_new_with_job (ThunarJob *job) { - _thunar_return_val_if_fail (job == NULL || THUNAR_VFS_IS_JOB (job), NULL); + _thunar_return_val_if_fail (job == NULL || THUNAR_IS_JOB (job), NULL); return g_object_new (THUNAR_TYPE_PROGRESS_DIALOG, "job", job, NULL); } @@ -485,12 +488,12 @@ thunar_progress_dialog_new_with_job (ThunarVfsJob *job) * thunar_progress_dialog_get_job: * @dialog : a #ThunarProgressDialog. * - * Returns the #ThunarVfsJob associated with @dialog + * Returns the #ThunarJob associated with @dialog * or %NULL if no job is currently associated with @dialog. * * Return value: the job associated with @dialog or %NULL. **/ -ThunarVfsJob* +ThunarJob * thunar_progress_dialog_get_job (ThunarProgressDialog *dialog) { _thunar_return_val_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog), NULL); @@ -502,16 +505,16 @@ thunar_progress_dialog_get_job (ThunarProgressDialog *dialog) /** * thunar_progress_dialog_set_job: * @dialog : a #ThunarProgressDialog. - * @job : a #ThunarVfsJob or %NULL. + * @job : a #ThunarJob or %NULL. * * Associates @job with @dialog. **/ void thunar_progress_dialog_set_job (ThunarProgressDialog *dialog, - ThunarVfsJob *job) + ThunarJob *job) { _thunar_return_if_fail (THUNAR_IS_PROGRESS_DIALOG (dialog)); - _thunar_return_if_fail (job == NULL || THUNAR_VFS_IS_JOB (job)); + _thunar_return_if_fail (job == NULL || THUNAR_IS_JOB (job)); /* check if we're already on that job */ if (G_UNLIKELY (dialog->job == job)) @@ -530,7 +533,7 @@ thunar_progress_dialog_set_job (ThunarProgressDialog *dialog, /* connect to the new job */ if (G_LIKELY (job != NULL)) { - g_object_ref (G_OBJECT (job)); + g_object_ref (job); g_signal_connect_swapped (job, "ask", G_CALLBACK (thunar_progress_dialog_ask), dialog); g_signal_connect_swapped (job, "ask-replace", G_CALLBACK (thunar_progress_dialog_ask_replace), dialog); diff --git a/thunar/thunar-progress-dialog.h b/thunar/thunar-progress-dialog.h index 280ba35b9..cb1dd5147 100644 --- a/thunar/thunar-progress-dialog.h +++ b/thunar/thunar-progress-dialog.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -20,7 +21,9 @@ #ifndef __THUNAR_PROGRESS_DIALOG_H__ #define __THUNAR_PROGRESS_DIALOG_H__ -#include <thunar-vfs/thunar-vfs.h> +#include <gtk/gtk.h> + +#include <thunar/thunar-job.h> G_BEGIN_DECLS; @@ -37,11 +40,11 @@ typedef struct _ThunarProgressDialog ThunarProgressDialog; GType thunar_progress_dialog_get_type (void) G_GNUC_CONST; GtkWidget *thunar_progress_dialog_new (void) G_GNUC_MALLOC; -GtkWidget *thunar_progress_dialog_new_with_job (ThunarVfsJob *job) G_GNUC_MALLOC; +GtkWidget *thunar_progress_dialog_new_with_job (ThunarJob *job) G_GNUC_MALLOC; -ThunarVfsJob *thunar_progress_dialog_get_job (ThunarProgressDialog *dialog); +ThunarJob *thunar_progress_dialog_get_job (ThunarProgressDialog *dialog); void thunar_progress_dialog_set_job (ThunarProgressDialog *dialog, - ThunarVfsJob *job); + ThunarJob *job); G_END_DECLS; diff --git a/thunar/thunar-properties-dialog.c b/thunar/thunar-properties-dialog.c index 9e660bbb3..247e619c9 100644 --- a/thunar/thunar-properties-dialog.c +++ b/thunar/thunar-properties-dialog.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -30,13 +31,20 @@ #include <gdk/gdkkeysyms.h> +#include <exo/exo.h> + #include <thunar/thunar-abstract-dialog.h> +#include <thunar/thunar-application.h> #include <thunar/thunar-chooser-button.h> #include <thunar/thunar-dialogs.h> #include <thunar/thunar-emblem-chooser.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-gtk-extensions.h> #include <thunar/thunar-icon-factory.h> +#include <thunar/thunar-image.h> +#include <thunar/thunar-io-jobs.h> +#include <thunar/thunar-job.h> #include <thunar/thunar-marshal.h> #include <thunar/thunar-pango-extensions.h> #include <thunar/thunar-permissions-chooser.h> @@ -87,8 +95,6 @@ static void thunar_properties_dialog_icon_button_clicked (GtkWidget ThunarPropertiesDialog *dialog); static void thunar_properties_dialog_update (ThunarPropertiesDialog *dialog); static void thunar_properties_dialog_update_providers (ThunarPropertiesDialog *dialog); -static gboolean thunar_properties_dialog_rename_idle (gpointer user_data); -static void thunar_properties_dialog_rename_idle_destroy (gpointer user_data); @@ -109,7 +115,6 @@ struct _ThunarPropertiesDialog ThunarPreferences *preferences; - ThunarVfsVolumeManager *volume_manager; ThunarFile *file; GtkWidget *notebook; @@ -128,8 +133,6 @@ struct _ThunarPropertiesDialog GtkWidget *volume_image; GtkWidget *volume_label; GtkWidget *permissions_chooser; - - guint rename_idle_id; }; @@ -241,7 +244,6 @@ thunar_properties_dialog_init (ThunarPropertiesDialog *dialog) G_CALLBACK (thunar_properties_dialog_reload), dialog); dialog->provider_factory = thunarx_provider_factory_get_default (); - dialog->volume_manager = thunar_vfs_volume_manager_get_default (); gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_HELP, GTK_RESPONSE_HELP, @@ -276,7 +278,7 @@ thunar_properties_dialog_init (ThunarPropertiesDialog *dialog) gtk_box_pack_start (GTK_BOX (box), dialog->icon_button, FALSE, TRUE, 0); gtk_widget_show (dialog->icon_button); - dialog->icon_image = gtk_image_new (); + dialog->icon_image = thunar_image_new (); gtk_box_pack_start (GTK_BOX (box), dialog->icon_image, FALSE, TRUE, 0); gtk_widget_show (dialog->icon_image); @@ -543,22 +545,15 @@ thunar_properties_dialog_finalize (GObject *object) ThunarPropertiesDialog *dialog = THUNAR_PROPERTIES_DIALOG (object); /* disconnect from the preferences */ - g_signal_handlers_disconnect_by_func (G_OBJECT (dialog->preferences), thunar_properties_dialog_reload, dialog); - g_object_unref (G_OBJECT (dialog->preferences)); + g_signal_handlers_disconnect_by_func (dialog->preferences, thunar_properties_dialog_reload, dialog); + g_object_unref (dialog->preferences); /* release the provider property pages */ g_list_foreach (dialog->provider_pages, (GFunc) g_object_unref, NULL); g_list_free (dialog->provider_pages); /* drop the reference on the provider factory */ - g_object_unref (G_OBJECT (dialog->provider_factory)); - - /* drop the reference on the volume manager */ - g_object_unref (G_OBJECT (dialog->volume_manager)); - - /* be sure to cancel any pending rename idle source */ - if (G_UNLIKELY (dialog->rename_idle_id != 0)) - g_source_remove (dialog->rename_idle_id); + g_object_unref (dialog->provider_factory); (*G_OBJECT_CLASS (thunar_properties_dialog_parent_class)->finalize) (object); } @@ -650,14 +645,66 @@ thunar_properties_dialog_reload (ThunarPropertiesDialog *dialog) +static void +thunar_properties_dialog_rename_error (ExoJob *job, + GError *error, + ThunarPropertiesDialog *dialog) +{ + _thunar_return_if_fail (EXO_IS_JOB (job)); + _thunar_return_if_fail (error != NULL); + _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog)); + + /* display an error message */ + thunar_dialogs_show_error (GTK_WIDGET (dialog), error, _("Failed to rename \"%s\""), + thunar_file_get_display_name (dialog->file)); +} + + + +static void +thunar_properties_dialog_rename_finished (ExoJob *job, + ThunarPropertiesDialog *dialog) +{ + const gchar *new_name; + + _thunar_return_if_fail (EXO_IS_JOB (job)); + _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog)); + + /* determine the new display name */ + new_name = thunar_file_get_display_name (dialog->file); + + /* reset the entry widget to the new name */ + gtk_entry_set_text (GTK_ENTRY (dialog->name_entry), new_name); + + g_signal_handlers_disconnect_matched (job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, dialog); + g_object_unref (job); +} + + + static void thunar_properties_dialog_activate (GtkWidget *entry, ThunarPropertiesDialog *dialog) { - if (G_LIKELY (dialog->rename_idle_id == 0)) + const gchar *old_name; + ThunarJob *job; + gchar *new_name; + + /* check if we still have a valid file and if the user is allowed to rename */ + if (G_UNLIKELY (dialog->file == NULL || !GTK_WIDGET_SENSITIVE (dialog->name_entry))) + return; + + /* determine new and old name */ + new_name = gtk_editable_get_chars (GTK_EDITABLE (dialog->name_entry), 0, -1); + old_name = thunar_file_get_display_name (dialog->file); + if (g_utf8_collate (new_name, old_name) != 0) { - dialog->rename_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT, thunar_properties_dialog_rename_idle, - dialog, thunar_properties_dialog_rename_idle_destroy); + job = thunar_io_jobs_rename_file (dialog->file, new_name); + if (job != NULL) + { + g_signal_connect (job, "error", G_CALLBACK (thunar_properties_dialog_rename_error), dialog); + g_signal_connect (job, "finished", G_CALLBACK (thunar_properties_dialog_rename_finished), dialog); + } } } @@ -678,11 +725,11 @@ static void thunar_properties_dialog_icon_button_clicked (GtkWidget *button, ThunarPropertiesDialog *dialog) { - const gchar *custom_icon; - GtkWidget *chooser; - GError *err = NULL; - gchar *title; - gchar *icon; + GtkWidget *chooser; + GError *err = NULL; + gchar *custom_icon; + gchar *title; + gchar *icon; _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog)); _thunar_return_if_fail (GTK_IS_BUTTON (button)); @@ -705,6 +752,7 @@ thunar_properties_dialog_icon_button_clicked (GtkWidget *button, custom_icon = thunar_file_get_custom_icon (dialog->file); if (G_LIKELY (custom_icon != NULL && *custom_icon != '\0')) exo_icon_chooser_dialog_set_icon (EXO_ICON_CHOOSER_DIALOG (chooser), custom_icon); + g_free (custom_icon); /* run the icon chooser dialog and make sure the dialog still has a file */ if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT && dialog->file != NULL) @@ -781,18 +829,20 @@ static void thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) { ThunarIconFactory *icon_factory; - ThunarVfsFileSize size; - ThunarVfsMimeInfo *info; ThunarDateStyle date_style; - ThunarVfsVolume *volume; GtkIconTheme *icon_theme; - const gchar *icon_name; + const gchar *content_type; const gchar *name; - GdkPixbuf *icon; + const gchar *path; + GVolume *volume; + guint64 size; + GIcon *gicon; glong offset; + gchar *date; gchar *display_name; gchar *size_string; gchar *str; + gchar *volume_name; _thunar_return_if_fail (THUNAR_IS_PROPERTIES_DIALOG (dialog)); _thunar_return_if_fail (THUNAR_IS_FILE (dialog->file)); @@ -808,12 +858,8 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) gtk_window_set_title (GTK_WINDOW (dialog), str); g_free (str); - /* update the icon */ - icon = thunar_icon_factory_load_file_icon (icon_factory, dialog->file, THUNAR_FILE_ICON_STATE_DEFAULT, 48); - gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->icon_image), icon); - gtk_window_set_icon (GTK_WINDOW (dialog), icon); - if (G_LIKELY (icon != NULL)) - g_object_unref (G_OBJECT (icon)); + /* update the preview image */ + thunar_image_set_file (THUNAR_IMAGE (dialog->icon_image), dialog->file); /* check if the icon may be changed (only for writable .desktop files) */ g_object_ref (G_OBJECT (dialog->icon_image)); @@ -853,15 +899,15 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) } } - /* update the mime type */ - info = thunar_file_get_mime_info (dialog->file); - if (G_UNLIKELY (strcmp (thunar_vfs_mime_info_get_name (info), "inode/symlink") == 0)) + /* update the content type */ + content_type = thunar_file_get_content_type (dialog->file); + if (G_UNLIKELY (g_content_type_equals (content_type, "inode/symlink"))) str = g_strdup (_("broken link")); else if (G_UNLIKELY (thunar_file_is_symlink (dialog->file))) - str = g_strdup_printf (_("link to %s"), thunar_vfs_mime_info_get_comment (info)); + str = g_strdup_printf (_("link to %s"), thunar_file_get_symlink_target (dialog->file)); else - str = g_strdup (thunar_vfs_mime_info_get_comment (info)); - thunar_gtk_widget_set_tooltip (dialog->kind_ebox, "%s", thunar_vfs_mime_info_get_name (info)); + str = g_content_type_get_description (content_type); + thunar_gtk_widget_set_tooltip (dialog->kind_ebox, "%s", str); gtk_label_set_text (GTK_LABEL (dialog->kind_label), str); g_free (str); @@ -871,14 +917,13 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) NULL); /* update the link target */ - str = thunar_file_is_symlink (dialog->file) ? thunar_file_read_link (dialog->file, NULL) : NULL; - if (G_UNLIKELY (str != NULL)) + path = thunar_file_is_symlink (dialog->file) ? thunar_file_get_symlink_target (dialog->file) : NULL; + if (G_UNLIKELY (path != NULL)) { - display_name = g_filename_display_name (str); + display_name = g_filename_display_name (path); gtk_label_set_text (GTK_LABEL (dialog->link_label), display_name); gtk_widget_show (dialog->link_label); g_free (display_name); - g_free (str); } else { @@ -886,14 +931,13 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) } /* update the original path */ - str = thunar_file_get_original_path (dialog->file); - if (G_UNLIKELY (str != NULL)) + path = thunar_file_get_original_path (dialog->file); + if (G_UNLIKELY (path != NULL)) { - display_name = g_filename_display_name (str); + display_name = g_filename_display_name (path); gtk_label_set_text (GTK_LABEL (dialog->origin_label), display_name); gtk_widget_show (dialog->origin_label); g_free (display_name); - g_free (str); } else { @@ -901,12 +945,12 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) } /* update the deleted time */ - str = thunar_file_get_deletion_date (dialog->file, date_style); - if (G_LIKELY (str != NULL)) + date = thunar_file_get_deletion_date (dialog->file, date_style); + if (G_LIKELY (date != NULL)) { - gtk_label_set_text (GTK_LABEL (dialog->deleted_label), str); + gtk_label_set_text (GTK_LABEL (dialog->deleted_label), date); gtk_widget_show (dialog->deleted_label); - g_free (str); + g_free (date); } else { @@ -914,12 +958,12 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) } /* update the modified time */ - str = thunar_file_get_date_string (dialog->file, THUNAR_FILE_DATE_MODIFIED, date_style); - if (G_LIKELY (str != NULL)) + date = thunar_file_get_date_string (dialog->file, THUNAR_FILE_DATE_MODIFIED, date_style); + if (G_LIKELY (date != NULL)) { - gtk_label_set_text (GTK_LABEL (dialog->modified_label), str); + gtk_label_set_text (GTK_LABEL (dialog->modified_label), date); gtk_widget_show (dialog->modified_label); - g_free (str); + g_free (date); } else { @@ -927,12 +971,12 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) } /* update the accessed time */ - str = thunar_file_get_date_string (dialog->file, THUNAR_FILE_DATE_ACCESSED, date_style); - if (G_LIKELY (str != NULL)) + date = thunar_file_get_date_string (dialog->file, THUNAR_FILE_DATE_ACCESSED, date_style); + if (G_LIKELY (date != NULL)) { - gtk_label_set_text (GTK_LABEL (dialog->accessed_label), str); + gtk_label_set_text (GTK_LABEL (dialog->accessed_label), date); gtk_widget_show (dialog->accessed_label); - g_free (str); + g_free (date); } else { @@ -940,9 +984,10 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) } /* update the free space (only for folders) */ - if (thunar_file_is_directory (dialog->file) && thunar_file_get_free_space (dialog->file, &size)) + if (thunar_file_is_directory (dialog->file) + && thunar_file_get_free_space (dialog->file, &size)) { - size_string = thunar_vfs_humanize_size (size, NULL, 0); + size_string = g_format_size_for_display (size); gtk_label_set_text (GTK_LABEL (dialog->freespace_label), size_string); gtk_widget_show (dialog->freespace_label); g_free (size_string); @@ -953,18 +998,18 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) } /* update the volume */ - volume = thunar_file_is_local (dialog->file) ? thunar_file_get_volume (dialog->file, dialog->volume_manager) : NULL; + volume = thunar_file_get_volume (dialog->file); if (G_LIKELY (volume != NULL)) { - icon_name = thunar_vfs_volume_lookup_icon_name (volume, icon_theme); - icon = thunar_icon_factory_load_icon (icon_factory, icon_name, 16, NULL, FALSE); - gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->volume_image), icon); - if (G_LIKELY (icon != NULL)) - g_object_unref (G_OBJECT (icon)); - - name = thunar_vfs_volume_get_name (volume); - gtk_label_set_text (GTK_LABEL (dialog->volume_label), name); + gicon = g_volume_get_icon (volume); + gtk_image_set_from_gicon (GTK_IMAGE (dialog->volume_image), gicon, GTK_ICON_SIZE_MENU); + if (G_LIKELY (gicon != NULL)) + g_object_unref (gicon); + + volume_name = g_volume_get_name (volume); + gtk_label_set_text (GTK_LABEL (dialog->volume_label), volume_name); gtk_widget_show (dialog->volume_label); + g_free (volume_name); } else { @@ -977,55 +1022,6 @@ thunar_properties_dialog_update (ThunarPropertiesDialog *dialog) -static gboolean -thunar_properties_dialog_rename_idle (gpointer user_data) -{ - ThunarPropertiesDialog *dialog = THUNAR_PROPERTIES_DIALOG (user_data); - const gchar *old_name; - GError *error = NULL; - gchar *new_name; - - /* check if we still have a valid file and if the user is allowed to rename */ - if (G_UNLIKELY (dialog->file == NULL || !GTK_WIDGET_SENSITIVE (dialog->name_entry))) - return FALSE; - - GDK_THREADS_ENTER (); - - /* determine new and old name */ - new_name = gtk_editable_get_chars (GTK_EDITABLE (dialog->name_entry), 0, -1); - old_name = thunar_file_get_display_name (dialog->file); - if (g_utf8_collate (new_name, old_name) != 0) - { - /* try to rename the file to the new name */ - if (!thunar_file_rename (dialog->file, new_name, &error)) - { - /* reset the entry widget to the old name */ - gtk_entry_set_text (GTK_ENTRY (dialog->name_entry), old_name); - - /* display an error message */ - thunar_dialogs_show_error (GTK_WIDGET (dialog), error, _("Failed to rename \"%s\""), old_name); - - /* release the error */ - g_error_free (error); - } - } - g_free (new_name); - - GDK_THREADS_LEAVE (); - - return FALSE; -} - - - -static void -thunar_properties_dialog_rename_idle_destroy (gpointer user_data) -{ - THUNAR_PROPERTIES_DIALOG (user_data)->rename_idle_id = 0; -} - - - /** * thunar_properties_dialog_new: * diff --git a/thunar/thunar-renamer-dialog.c b/thunar/thunar-renamer-dialog.c index 5bb1fd6e4..96ca63a9a 100644 --- a/thunar/thunar-renamer-dialog.c +++ b/thunar/thunar-renamer-dialog.c @@ -627,7 +627,7 @@ thunar_renamer_dialog_init (ThunarRenamerDialog *renamer_dialog) gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); gtk_widget_show (image); - /* TRANSLATORS: You can test this string by temporarily removing thunar-sbr.* from $libdir/thunarx-1/, + /* TRANSLATORS: You can test this string by temporarily removing thunar-sbr.* from $libdir/thunarx-2/, * and opening the multi rename dialog by selecting multiple files and pressing F2. */ label = gtk_label_new (_("No renamer modules were found on your system. Please check your\n" @@ -1329,7 +1329,7 @@ thunar_renamer_dialog_drag_data_received (GtkWidget *tree_view, ThunarRenamerDialog *renamer_dialog) { ThunarFile *file; - GList *path_list; + GList *file_list; GList *lp; GtkTreeModel *model; GtkTreePath *path; @@ -1361,14 +1361,14 @@ thunar_renamer_dialog_drag_data_received (GtkWidget *tree_view, position = -1; } - /* determine the path list from the selection_data */ - path_list = thunar_vfs_path_list_from_string ((const gchar *) selection_data->data, NULL); + /* determine the file list from the selection_data */ + file_list = thunar_g_file_list_new_from_string ((const gchar *) selection_data->data); /* add all paths to the model */ - for (lp = path_list; lp != NULL; lp = lp->next) + for (lp = file_list; lp != NULL; lp = lp->next) { /* determine the file for the path */ - file = thunar_file_get_for_path (lp->data, NULL); + file = thunar_file_get (lp->data, NULL); if (G_LIKELY (file != NULL)) { /* insert the file in the model */ @@ -1379,18 +1379,18 @@ thunar_renamer_dialog_drag_data_received (GtkWidget *tree_view, position++; /* release the file */ - g_object_unref (G_OBJECT (file)); + g_object_unref (file); } - /* release the path */ - thunar_vfs_path_unref (lp->data); + /* release the GFile */ + g_object_unref (lp->data); } /* finish the drag */ - gtk_drag_finish (context, (path_list != NULL), FALSE, time); + gtk_drag_finish (context, (file_list != NULL), FALSE, time); /* release the list */ - g_list_free (path_list); + g_list_free (file_list); } /* stop the emission of the "drag-data-received" signal */ @@ -1861,15 +1861,17 @@ thunar_renamer_dialog_set_standalone (ThunarRenamerDialog *renamer_dialog, * @files : the list of #ThunarFile<!---->s to rename. * @standalone : whether the dialog should appear like a standalone * application instead of an integrated renamer dialog. + * @startup_id : startup id to set on the window or %NULL. * * Convenience function to display a #ThunarRenamerDialog with * the given parameters. **/ void -thunar_show_renamer_dialog (gpointer parent, - ThunarFile *current_directory, - GList *files, - gboolean standalone) +thunar_show_renamer_dialog (gpointer parent, + ThunarFile *current_directory, + GList *files, + gboolean standalone, + const gchar *startup_id) { ThunarApplication *application; GdkScreen *screen; @@ -1904,6 +1906,10 @@ thunar_show_renamer_dialog (gpointer parent, "standalone", standalone, NULL); + /* set the dialogs startup id if available */ + if (startup_id != NULL && *startup_id != '\0') + gtk_window_set_startup_id (GTK_WINDOW (dialog), startup_id); + /* check if we have a toplevel window */ if (G_LIKELY (window != NULL && GTK_WIDGET_TOPLEVEL (window))) { diff --git a/thunar/thunar-renamer-dialog.h b/thunar/thunar-renamer-dialog.h index d7ff846e7..66ab323ad 100644 --- a/thunar/thunar-renamer-dialog.h +++ b/thunar/thunar-renamer-dialog.h @@ -51,7 +51,8 @@ void thunar_renamer_dialog_set_standalone (ThunarRenamerDialog *re void thunar_show_renamer_dialog (gpointer parent, ThunarFile *current_directory, GList *files, - gboolean standalone); + gboolean standalone, + const gchar *startup_id); G_END_DECLS; diff --git a/thunar/thunar-renamer-model.c b/thunar/thunar-renamer-model.c index 593c3834d..2eb612124 100644 --- a/thunar/thunar-renamer-model.c +++ b/thunar/thunar-renamer-model.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -158,12 +159,11 @@ struct _ThunarRenamerModel struct _ThunarRenamerModelItem { - ThunarVfsInfo *info; - ThunarFile *file; - gchar *name; - guint changed : 1; /* if the file changed */ - guint conflict : 1; /* if the item conflicts with another item */ - guint dirty : 1; /* if the item must be updated */ + ThunarFile *file; + gchar *name; + guint changed : 1; /* if the file changed */ + guint conflict : 1; /* if the item conflicts with another item */ + guint dirty : 1; /* if the item must be updated */ }; @@ -645,22 +645,16 @@ thunar_renamer_model_file_changed (ThunarRenamerModel *renamer_model, { /* check if the file changed on disk */ item = THUNAR_RENAMER_MODEL_ITEM (lp->data); - if (!thunar_vfs_info_matches (item->info, thunar_file_get_info (file))) + + /* check if we're frozen */ + if (G_LIKELY (!renamer_model->frozen)) { - /* connect to the new info */ - thunar_vfs_info_unref (item->info); - item->info = thunar_vfs_info_ref (thunar_file_get_info (file)); - - /* check if we're frozen */ - if (G_LIKELY (!renamer_model->frozen)) - { - /* the file changed */ - THUNAR_RENAMER_MODEL_ITEM (lp->data)->changed = TRUE; - - /* invalidate the item */ - thunar_renamer_model_invalidate_item (renamer_model, lp->data); - break; - } + /* the file changed */ + THUNAR_RENAMER_MODEL_ITEM (lp->data)->changed = TRUE; + + /* invalidate the item */ + thunar_renamer_model_invalidate_item (renamer_model, lp->data); + break; } /* determine the iter for the item */ @@ -753,15 +747,15 @@ static gboolean trm_same_directory (ThunarFile *a, ThunarFile *b) { - ThunarVfsPath *parent_a; - ThunarVfsPath *parent_b; + GFile *parent_a; + GFile *parent_b; /* determine the parent paths for both files */ - parent_a = thunar_vfs_path_get_parent (thunar_file_get_path (a)); - parent_b = thunar_vfs_path_get_parent (thunar_file_get_path (b)); + parent_a = g_file_get_parent (thunar_file_get_file (a)); + parent_b = g_file_get_parent (thunar_file_get_file (b)); /* check if both files have the same parent */ - return (parent_a != NULL && parent_b != NULL && thunar_vfs_path_equal (parent_a, parent_b)); + return (parent_a != NULL && parent_b != NULL && g_file_equal (parent_a, parent_b)); } @@ -1004,7 +998,6 @@ thunar_renamer_model_item_new (ThunarFile *file) ThunarRenamerModelItem *item; item = _thunar_slice_new0 (ThunarRenamerModelItem); - item->info = thunar_vfs_info_ref (thunar_file_get_info (file)); item->file = g_object_ref (G_OBJECT (file)); item->dirty = TRUE; @@ -1017,7 +1010,6 @@ static void thunar_renamer_model_item_free (ThunarRenamerModelItem *item) { g_object_unref (G_OBJECT (item->file)); - thunar_vfs_info_unref (item->info); g_free (item->name); _thunar_slice_free (ThunarRenamerModelItem, item); } diff --git a/thunar/thunar-renamer-progress.c b/thunar/thunar-renamer-progress.c index 7631ef91d..a16a8fb73 100644 --- a/thunar/thunar-renamer-progress.c +++ b/thunar/thunar-renamer-progress.c @@ -200,7 +200,7 @@ thunar_renamer_progress_next_idle (gpointer user_data) oldname = g_strdup (thunar_file_get_display_name (pair->file)); /* try to rename the file */ - if (!thunar_file_rename (pair->file, pair->name, &error)) + if (!thunar_file_rename (pair->file, pair->name, NULL, FALSE, &error)) { /* determine the toplevel widget */ toplevel = (GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (renamer_progress)); diff --git a/thunar/thunar-sendto-model.c b/thunar/thunar-sendto-model.c index d3863d524..12b1f9662 100644 --- a/thunar/thunar-sendto-model.c +++ b/thunar/thunar-sendto-model.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -28,20 +29,24 @@ #include <string.h> #endif +#ifdef HAVE_GIO_UNIX +#include <gio/gdesktopappinfo.h> +#endif + #include <thunar/thunar-private.h> #include <thunar/thunar-sendto-model.h> -static void thunar_sendto_model_class_init (ThunarSendtoModelClass *klass); -static void thunar_sendto_model_finalize (GObject *object); -static void thunar_sendto_model_load (ThunarSendtoModel *sendto_model); -static void thunar_sendto_model_event (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data); +static void thunar_sendto_model_class_init (ThunarSendtoModelClass *klass); +static void thunar_sendto_model_init (ThunarSendtoModel *sendto_model); +static void thunar_sendto_model_finalize (GObject *object); +static void thunar_sendto_model_load (ThunarSendtoModel *sendto_model); +static void thunar_sendto_model_event (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data); @@ -52,11 +57,10 @@ struct _ThunarSendtoModelClass struct _ThunarSendtoModel { - GObject __parent__; - ThunarVfsMonitor *monitor; - GList *handles; - GList *handlers; - guint loaded : 1; + GObject __parent__; + GList *monitors; + GList *handlers; + guint loaded : 1; }; @@ -72,21 +76,13 @@ thunar_sendto_model_get_type (void) if (G_UNLIKELY (type == G_TYPE_INVALID)) { - static const GTypeInfo info = - { - sizeof (ThunarSendtoModelClass), - NULL, - NULL, - (GClassInitFunc) thunar_sendto_model_class_init, - NULL, - NULL, - sizeof (ThunarSendtoModel), - 0, - NULL, - NULL, - }; - - type = g_type_register_static (G_TYPE_OBJECT, I_("ThunarSendtoModel"), &info, 0); + type = g_type_register_static_simple (G_TYPE_OBJECT, + I_("ThunarSendtoModel"), + sizeof (ThunarSendtoModelClass), + (GClassInitFunc) thunar_sendto_model_class_init, + sizeof (ThunarSendtoModel), + (GInstanceInitFunc) thunar_sendto_model_init, + 0); } return type; @@ -108,6 +104,14 @@ thunar_sendto_model_class_init (ThunarSendtoModelClass *klass) +static void +thunar_sendto_model_init (ThunarSendtoModel *sendto_model) +{ + sendto_model->monitors = NULL; +} + + + static void thunar_sendto_model_finalize (GObject *object) { @@ -118,15 +122,13 @@ thunar_sendto_model_finalize (GObject *object) g_list_foreach (sendto_model->handlers, (GFunc) g_object_unref, NULL); g_list_free (sendto_model->handlers); - /* disconnect from the monitor (if connected) */ - if (G_LIKELY (sendto_model->monitor != NULL)) + /* disconnect all monitors */ + for (lp = sendto_model->monitors; lp != NULL; lp = lp->next) { - /* disconnect all handles and release monitor reference */ - for (lp = sendto_model->handles; lp != NULL; lp = lp->next) - thunar_vfs_monitor_remove (sendto_model->monitor, lp->data); - g_object_unref (G_OBJECT (sendto_model->monitor)); - g_list_free (sendto_model->handles); + g_file_monitor_cancel (lp->data); + g_object_unref (lp->data); } + g_list_free (sendto_model->monitors); (*G_OBJECT_CLASS (thunar_sendto_model_parent_class)->finalize) (object); } @@ -134,11 +136,11 @@ thunar_sendto_model_finalize (GObject *object) static gint -tvma_compare (gconstpointer a, - gconstpointer b) +g_app_info_compare (gpointer a, + gpointer b) { - return strcmp (thunar_vfs_mime_application_get_desktop_id (b), - thunar_vfs_mime_application_get_desktop_id (a)); + return g_utf8_collate (g_app_info_get_name (b), + g_app_info_get_name (a)); } @@ -146,11 +148,10 @@ tvma_compare (gconstpointer a, static void thunar_sendto_model_load (ThunarSendtoModel *sendto_model) { - ThunarVfsMimeApplication *handler; - const gchar *id; - gchar **specs; - gchar *path; - guint n; + GDesktopAppInfo *app_info = NULL; + gchar **specs; + gchar *path; + guint n; /* lookup all sendto .desktop files */ specs = xfce_resource_match (XFCE_RESOURCE_DATA, "Thunar/sendto/*.desktop", TRUE); @@ -160,15 +161,18 @@ thunar_sendto_model_load (ThunarSendtoModel *sendto_model) path = xfce_resource_lookup (XFCE_RESOURCE_DATA, specs[n]); if (G_LIKELY (path != NULL)) { - /* we use the filename as desktop-id */ - id = specs[n] + (sizeof ("Thunar/sendto/") - 1); - +#ifdef HAVE_GIO_UNIX /* try to load the .desktop file */ - handler = thunar_vfs_mime_application_new_from_file (path, id); - if (G_LIKELY (handler != NULL)) + app_info = g_desktop_app_info_new_from_filename (path); +#else + /* FIXME try to create the app info ourselves in a platform independent way */ +#endif + if (G_LIKELY (app_info != NULL)) { /* add to our handler list, sorted by their desktop-ids (reverse order) */ - sendto_model->handlers = g_list_insert_sorted (sendto_model->handlers, handler, tvma_compare); + sendto_model->handlers = g_list_insert_sorted (sendto_model->handlers, + G_APP_INFO (app_info), + (GCompareFunc) g_app_info_compare); } } @@ -182,12 +186,11 @@ thunar_sendto_model_load (ThunarSendtoModel *sendto_model) static void -thunar_sendto_model_event (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data) +thunar_sendto_model_event (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) { ThunarSendtoModel *sendto_model = THUNAR_SENDTO_MODEL (user_data); @@ -239,8 +242,8 @@ thunar_sendto_model_get_default (void) * @sendto_model : a #ThunarSendtoModel. * @files : a #GList of #ThunarFile<!---->s. * - * Returns the list of #ThunarVfsMimeHandler<!---->s for the "Send To" - * targets that support the specified @files. + * Returns the list of #GAppInfo<!---->s for the "Send To" targets that + * support the specified @files. * * The returned list is owned by the caller and must be freed when no * longer needed, using: @@ -249,23 +252,21 @@ thunar_sendto_model_get_default (void) * g_list_free (list); * </programlisting></informalexample> * - * Return value: a #GList of supported #ThunarVfsMimeHandler<!---->s as + * Return value: a #GList of supported #GAppInfo<!---->s as * "Send To" targets for the specified @files. **/ GList* thunar_sendto_model_get_matching (ThunarSendtoModel *sendto_model, GList *files) { - ThunarVfsMimeHandlerFlags flags; - ThunarVfsMonitorHandle *handle; - const gchar * const *mime_types; - ThunarVfsPath *path; - gchar **datadirs; - gchar *dir; - GList *handlers = NULL; - GList *hp; - GList *fp; - guint n; + GFileMonitor *monitor; + GFile *file; + gchar **datadirs; + gchar *dir; + GList *handlers = NULL; + GList *hp; + GList *fp; + guint n; _thunar_return_val_if_fail (THUNAR_IS_SENDTO_MODEL (sendto_model), NULL); @@ -274,43 +275,37 @@ thunar_sendto_model_get_matching (ThunarSendtoModel *sendto_model, return NULL; /* connect to the monitor on-demand */ - if (G_UNLIKELY (sendto_model->monitor == NULL)) + if (G_UNLIKELY (sendto_model->monitors == NULL)) { - /* connect to the monitor */ - sendto_model->monitor = thunar_vfs_monitor_get_default (); - /* watch all possible sendto directories */ datadirs = xfce_resource_dirs (XFCE_RESOURCE_DATA); for (n = 0; datadirs[n] != NULL; ++n) { /* determine the path to the sendto directory */ dir = g_build_filename (datadirs[n], "Thunar", "sendto", NULL); - path = thunar_vfs_path_new (dir, NULL); - if (G_LIKELY (path != NULL)) + file = g_file_new_for_path (dir); + + /* watch the directory for changes */ + monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); + if (G_LIKELY (monitor != NULL)) { - /* watch the directory for changes */ - handle = thunar_vfs_monitor_add_file (sendto_model->monitor, path, thunar_sendto_model_event, sendto_model); - sendto_model->handles = g_list_prepend (sendto_model->handles, handle); - thunar_vfs_path_unref (path); + g_signal_connect (monitor, "changed", G_CALLBACK (thunar_sendto_model_event), sendto_model); + sendto_model->monitors = g_list_prepend (sendto_model->monitors, monitor); } + + g_object_unref (file); g_free (dir); } g_strfreev (datadirs); - - /* load the model */ - thunar_sendto_model_load (sendto_model); } /* test all handlers */ for (hp = sendto_model->handlers; hp != NULL; hp = hp->next) { - /* ignore the handler if it doesn't support multiple files, but we have more than one file */ - flags = thunar_vfs_mime_handler_get_flags (THUNAR_VFS_MIME_HANDLER (hp->data)); - if ((flags & THUNAR_VFS_MIME_HANDLER_SUPPORTS_MULTI) == 0 && files->next != NULL) - continue; + /* FIXME Ignore GAppInfos which don't support multiple file arguments */ /* ignore the handler if it doesn't support URIs, but we don't have a local file */ - if ((flags & THUNAR_VFS_MIME_HANDLER_SUPPORTS_URIS) == 0) + if (!g_app_info_supports_uris (hp->data)) { /* check if we have any non-local files */ for (fp = files; fp != NULL; fp = fp->next) @@ -322,30 +317,7 @@ thunar_sendto_model_get_matching (ThunarSendtoModel *sendto_model, continue; } - /* check if we need to test mime types for this handler */ - mime_types = thunar_vfs_mime_application_get_mime_types (hp->data); - if (G_LIKELY (mime_types != NULL && *mime_types != NULL)) - { - /* each file must match atleast one of the specified mime types */ - for (fp = files; fp != NULL; fp = fp->next) - { - /* each file must be supported by one of the mime types */ - for (n = 0; mime_types[n] != NULL; ++n) - if (thunarx_file_info_has_mime_type (fp->data, mime_types[n])) - break; - - /* check if all mime types failed */ - if (mime_types[n] == NULL) - break; - } - - /* check if atleast one file failed */ - if (G_UNLIKELY (fp != NULL)) - { - /* skip this handler */ - continue; - } - } + /* FIXME Check if the GAppInfo supports all files */ /* the handler is supported */ handlers = g_list_prepend (handlers, g_object_ref (G_OBJECT (hp->data))); diff --git a/thunar/thunar-shortcuts-icon-renderer.c b/thunar/thunar-shortcuts-icon-renderer.c index d3319fc04..953fb9ed3 100644 --- a/thunar/thunar-shortcuts-icon-renderer.c +++ b/thunar/thunar-shortcuts-icon-renderer.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>. + * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -21,6 +22,9 @@ #include <config.h> #endif +#include <gio/gio.h> + +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-icon-factory.h> #include <thunar/thunar-shortcuts-icon-renderer.h> @@ -66,7 +70,7 @@ struct _ThunarShortcutsIconRenderer { ThunarIconRenderer __parent__; - ThunarVfsVolume *volume; + GVolume *volume; }; @@ -124,13 +128,13 @@ thunar_shortcuts_icon_renderer_class_init (ThunarShortcutsIconRendererClass *kla /** * ThunarShortcutsIconRenderer:volume: * - * The #ThunarVfsVolume for which to render an icon or %NULL to fallback + * The #GVolume for which to render an icon or %NULL to fallback * to the default icon renderering (see #ThunarIconRenderer). **/ g_object_class_install_property (gobject_class, PROP_VOLUME, g_param_spec_object ("volume", "volume", "volume", - THUNAR_VFS_TYPE_VOLUME, + G_TYPE_VOLUME, EXO_PARAM_READWRITE)); } @@ -153,7 +157,7 @@ thunar_shortcuts_icon_renderer_finalize (GObject *object) /* release the volume (if any) */ if (G_UNLIKELY (shortcuts_icon_renderer->volume != NULL)) - g_object_unref (G_OBJECT (shortcuts_icon_renderer->volume)); + g_object_unref (shortcuts_icon_renderer->volume); (*G_OBJECT_CLASS (thunar_shortcuts_icon_renderer_parent_class)->finalize) (object); } @@ -194,8 +198,8 @@ thunar_shortcuts_icon_renderer_set_property (GObject *object, { case PROP_VOLUME: if (G_UNLIKELY (shortcuts_icon_renderer->volume != NULL)) - g_object_unref (G_OBJECT (shortcuts_icon_renderer->volume)); - shortcuts_icon_renderer->volume = (gpointer) g_value_dup_object (value); + g_object_unref (shortcuts_icon_renderer->volume); + shortcuts_icon_renderer->volume = g_value_dup_object (value); break; default: @@ -216,22 +220,32 @@ thunar_shortcuts_icon_renderer_render (GtkCellRenderer *renderer, GtkCellRendererState flags) { ThunarShortcutsIconRenderer *shortcuts_icon_renderer = THUNAR_SHORTCUTS_ICON_RENDERER (renderer); - ThunarIconFactory *icon_factory; GtkIconTheme *icon_theme; GdkRectangle draw_area; GdkRectangle icon_area; - const gchar *icon_name; - GdkPixbuf *icon; + GtkIconInfo *icon_info; + GdkPixbuf *icon = NULL; GdkPixbuf *temp; + GIcon *gicon; /* check if we have a volume set */ if (G_UNLIKELY (shortcuts_icon_renderer->volume != NULL)) { /* load the volume icon */ icon_theme = gtk_icon_theme_get_for_screen (gdk_drawable_get_screen (window)); - icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); - icon_name = thunar_vfs_volume_lookup_icon_name (shortcuts_icon_renderer->volume, icon_theme); - icon = thunar_icon_factory_load_icon (icon_factory, icon_name, THUNAR_ICON_RENDERER (renderer)->size, NULL, FALSE); + + /* look up the volume icon info */ + gicon = g_volume_get_icon (shortcuts_icon_renderer->volume); + icon_info = gtk_icon_theme_lookup_by_gicon (icon_theme, gicon, cell_area->width, + GTK_ICON_LOOKUP_USE_BUILTIN); + g_object_unref (gicon); + + /* try to load the icon */ + if (G_LIKELY (icon_info != NULL)) + { + icon = gtk_icon_info_load_icon (icon_info, NULL); + gtk_icon_info_free (icon_info); + } /* render the icon (if any) */ if (G_LIKELY (icon != NULL)) @@ -253,7 +267,7 @@ thunar_shortcuts_icon_renderer_render (GtkCellRenderer *renderer, icon_area.height = gdk_pixbuf_get_height (icon); } - if (!thunar_vfs_volume_is_mounted (shortcuts_icon_renderer->volume)) + if (!thunar_g_volume_is_mounted (shortcuts_icon_renderer->volume)) { /* 50% translucent for unmounted volumes */ temp = exo_gdk_pixbuf_lucent (icon, 50); @@ -277,9 +291,6 @@ thunar_shortcuts_icon_renderer_render (GtkCellRenderer *renderer, /* cleanup */ g_object_unref (G_OBJECT (icon)); } - - /* cleanup */ - g_object_unref (G_OBJECT (icon_factory)); } else { diff --git a/thunar/thunar-shortcuts-model.c b/thunar/thunar-shortcuts-model.c index 38e0d801f..5ef7eb700 100644 --- a/thunar/thunar-shortcuts-model.c +++ b/thunar/thunar-shortcuts-model.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -34,11 +35,13 @@ #include <locale.h> #endif +#include <glib.h> +#include <glib/gstdio.h> + #include <thunar/thunar-file.h> #include <thunar/thunar-shortcuts-model.h> #include <thunar/thunar-private.h> -#include <glib.h> #define THUNAR_SHORTCUT(obj) ((ThunarShortcut *) (obj)) @@ -112,23 +115,23 @@ static void thunar_shortcuts_model_remove_shortcut (ThunarShort ThunarShortcut *shortcut); static void thunar_shortcuts_model_load (ThunarShortcutsModel *model); static void thunar_shortcuts_model_save (ThunarShortcutsModel *model); -static void thunar_shortcuts_model_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, +static void thunar_shortcuts_model_monitor (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, gpointer user_data); static void thunar_shortcuts_model_file_changed (ThunarFile *file, ThunarShortcutsModel *model); static void thunar_shortcuts_model_file_destroy (ThunarFile *file, ThunarShortcutsModel *model); -static void thunar_shortcuts_model_volume_changed (ThunarVfsVolume *volume, +static void thunar_shortcuts_model_volume_added (GVolumeMonitor *volume_monitor, + GVolume *volume, ThunarShortcutsModel *model); -static void thunar_shortcuts_model_volumes_added (ThunarVfsVolumeManager *volume_manager, - GList *volumes, +static void thunar_shortcuts_model_volume_removed (GVolumeMonitor *volume_monitor, + GVolume *volume, ThunarShortcutsModel *model); -static void thunar_shortcuts_model_volumes_removed (ThunarVfsVolumeManager *volume_manager, - GList *volumes, +static void thunar_shortcuts_model_volume_changed (GVolumeMonitor *monitor, + GVolume *volume, ThunarShortcutsModel *model); static void thunar_shortcut_free (ThunarShortcut *shortcut, ThunarShortcutsModel *model); @@ -142,22 +145,21 @@ struct _ThunarShortcutsModelClass struct _ThunarShortcutsModel { - GObject __parent__; + GObject __parent__; /* the model stamp is only used when debugging is * enabled, to make sure we don't accept iterators * generated by another model. */ #ifndef NDEBUG - gint stamp; + gint stamp; #endif - GList *shortcuts; - GList *hidden_volumes; - ThunarVfsVolumeManager *volume_manager; + GList *shortcuts; + GList *hidden_volumes; + GVolumeMonitor *volume_monitor; - ThunarVfsMonitor *monitor; - ThunarVfsMonitorHandle *handle; + GFileMonitor *monitor; }; struct _ThunarShortcut @@ -166,7 +168,7 @@ struct _ThunarShortcut gchar *name; ThunarFile *file; - ThunarVfsVolume *volume; + GVolume *volume; }; @@ -266,67 +268,50 @@ thunar_shortcuts_model_drag_source_init (GtkTreeDragSourceIface *iface) static void thunar_shortcuts_model_init (ThunarShortcutsModel *model) { - ThunarVfsVolume *volume; ThunarShortcut *shortcut; - ThunarVfsPath *system_path_list[4]; - ThunarVfsPath *fhome; - ThunarVfsPath *fpath; GtkTreePath *path; ThunarFile *file; + GVolume *volume; + GFile *bookmarks; + GFile *desktop; + GFile *home; + GList *system_paths = NULL; GList *volumes; GList *lp; - guint n; - gchar *desktop_path = NULL; - guint desktop_index; #ifndef NDEBUG model->stamp = g_random_int (); #endif - /* connect to the volume manager */ - model->volume_manager = thunar_vfs_volume_manager_get_default (); - g_signal_connect (G_OBJECT (model->volume_manager), "volumes-added", G_CALLBACK (thunar_shortcuts_model_volumes_added), model); - g_signal_connect (G_OBJECT (model->volume_manager), "volumes-removed", G_CALLBACK (thunar_shortcuts_model_volumes_removed), model); + /* connect to the volume monitor */ + model->volume_monitor = g_volume_monitor_get (); + g_signal_connect (model->volume_monitor, "volume-added", G_CALLBACK (thunar_shortcuts_model_volume_added), model); + g_signal_connect (model->volume_monitor, "volume-removed", G_CALLBACK (thunar_shortcuts_model_volume_removed), model); + g_signal_connect (model->volume_monitor, "volume-changed", G_CALLBACK (thunar_shortcuts_model_volume_changed), model); + + home = thunar_g_file_new_for_home (); /* determine the system-defined paths */ - system_path_list[0] = thunar_vfs_path_get_for_home (); - system_path_list[1] = thunar_vfs_path_get_for_trash (); + system_paths = g_list_append (system_paths, g_object_ref (home)); + system_paths = g_list_append (system_paths, thunar_g_file_new_for_trash ()); -#if GLIB_CHECK_VERSION(2,14,0) - desktop_path = g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)); -#else /* GLIB_CHECK_VERSION(2,14,0) */ - desktop_path = g_build_filename (G_DIR_SEPARATOR_S, xfce_get_homedir (), - "Desktop", NULL); -#endif /* GLIB_CHECK_VERSION(2,14,0) */ - system_path_list[2] = thunar_vfs_path_new (desktop_path, NULL); - if (G_UNLIKELY (system_path_list[2] == NULL)) - system_path_list[2] = thunar_vfs_path_relative (system_path_list[0], - "Desktop"); - desktop_index = 2; + desktop = thunar_g_file_new_for_desktop (); - g_free (desktop_path); + if (!g_file_equal (desktop, home)) + system_paths = g_list_append (system_paths, desktop); + else + g_object_unref (desktop); - system_path_list[3] = thunar_vfs_path_get_for_root (); + system_paths = g_list_append (system_paths, thunar_g_file_new_for_root ()); /* will be used to append the shortcuts to the list */ path = gtk_tree_path_new_from_indices (0, -1); /* append the system defined items ('Home', 'Trash', 'File System') */ - for (n = 0; n < G_N_ELEMENTS (system_path_list); ++n) + for (lp = system_paths; lp != NULL; lp = lp->next) { -#if GLIB_CHECK_VERSION(2, 14, 0) - /* we exclude the desktop if it points to home */ - if (n == desktop_index - && exo_str_is_equal (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP), - xfce_get_homedir ())) - { - thunar_vfs_path_unref (system_path_list[n]); - continue; - } -#endif - /* determine the file for the path */ - file = thunar_file_get_for_path (system_path_list[n], NULL); + file = thunar_file_get (lp->data, NULL); if (G_LIKELY (file != NULL)) { /* create the shortcut */ @@ -334,8 +319,7 @@ thunar_shortcuts_model_init (ThunarShortcutsModel *model) shortcut->type = THUNAR_SHORTCUT_SYSTEM_DEFINED; shortcut->file = file; -#if GLIB_CHECK_VERSION(2,14,0) - if (n == desktop_index) + if (thunar_g_file_is_desktop (lp->data)) { gchar *old_locale = NULL; gchar *locale = NULL; @@ -357,7 +341,6 @@ thunar_shortcuts_model_init (ThunarShortcutsModel *model) setlocale (LC_MESSAGES, old_locale); } -#endif /* GLIB_CHECK_VERSION(2,14,0) */ /* append the shortcut to the list */ thunar_shortcuts_model_add_shortcut (model, shortcut, path); @@ -365,21 +348,20 @@ thunar_shortcuts_model_init (ThunarShortcutsModel *model) } /* release the system defined path */ - thunar_vfs_path_unref (system_path_list[n]); + g_object_unref (lp->data); } + g_list_free (system_paths); + /* prepend the removable media volumes */ - volumes = thunar_vfs_volume_manager_get_volumes (model->volume_manager); + volumes = g_volume_monitor_get_volumes (model->volume_monitor); for (lp = volumes; lp != NULL; lp = lp->next) { /* monitor the volume for changes */ - volume = THUNAR_VFS_VOLUME (lp->data); - g_object_ref (G_OBJECT (volume)); - g_signal_connect (G_OBJECT (volume), "changed", - G_CALLBACK (thunar_shortcuts_model_volume_changed), model); + volume = G_VOLUME (lp->data); /* we list only present, removable devices here */ - if (thunar_vfs_volume_is_removable (volume) && thunar_vfs_volume_is_present (volume)) + if (thunar_g_volume_is_removable (volume) && thunar_g_volume_is_present (volume)) { /* generate the shortcut (w/o a file, else we might * prevent the volume from being unmounted) @@ -394,33 +376,33 @@ thunar_shortcuts_model_init (ThunarShortcutsModel *model) } else { - /* schedule the volume for later checking, not removable or there's no medium present */ + /* schedule the volume for later checking, not removable or + * there's no medium present */ model->hidden_volumes = g_list_prepend (model->hidden_volumes, volume); } } + g_list_free (volumes); - /* prepend the row separator (only supported with Gtk+ 2.6) */ -#if GTK_CHECK_VERSION(2,6,0) + /* prepend the row separator */ shortcut = _thunar_slice_new0 (ThunarShortcut); shortcut->type = THUNAR_SHORTCUT_SEPARATOR; thunar_shortcuts_model_add_shortcut (model, shortcut, path); gtk_tree_path_next (path); -#endif /* determine the URI to the Gtk+ bookmarks file */ - fhome = thunar_vfs_path_get_for_home (); - fpath = thunar_vfs_path_relative (fhome, ".gtk-bookmarks"); - thunar_vfs_path_unref (fhome); + bookmarks = g_file_resolve_relative_path (home, ".gtk-bookmarks"); /* register with the alteration monitor for the bookmarks file */ - model->monitor = thunar_vfs_monitor_get_default (); - model->handle = thunar_vfs_monitor_add_file (model->monitor, fpath, thunar_shortcuts_model_monitor, G_OBJECT (model)); + model->monitor = g_file_monitor_file (bookmarks, G_FILE_MONITOR_NONE, NULL, NULL); + if (G_LIKELY (model->monitor != NULL)) + g_signal_connect (model->monitor, "changed", G_CALLBACK (thunar_shortcuts_model_monitor), model); /* read the Gtk+ bookmarks file */ thunar_shortcuts_model_load (model); /* cleanup */ - thunar_vfs_path_unref (fpath); + g_object_unref (bookmarks); + g_object_unref (home); gtk_tree_path_free (path); } @@ -430,7 +412,6 @@ static void thunar_shortcuts_model_finalize (GObject *object) { ThunarShortcutsModel *model = THUNAR_SHORTCUTS_MODEL (object); - GList *lp; _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model)); @@ -439,20 +420,19 @@ thunar_shortcuts_model_finalize (GObject *object) g_list_free (model->shortcuts); /* free all hidden volumes */ - for (lp = model->hidden_volumes; lp != NULL; lp = lp->next) - { - g_signal_handlers_disconnect_by_func (G_OBJECT (lp->data), thunar_shortcuts_model_volume_changed, model); - g_object_unref (G_OBJECT (lp->data)); - } + g_list_foreach (model->hidden_volumes, (GFunc) g_object_unref, NULL); g_list_free (model->hidden_volumes); - /* detach from the VFS monitor */ - thunar_vfs_monitor_remove (model->monitor, model->handle); - g_object_unref (G_OBJECT (model->monitor)); + /* detach from the file monitor */ + if (model->monitor != NULL) + { + g_file_monitor_cancel (model->monitor); + g_object_unref (model->monitor); + } - /* unlink from the volume manager */ - g_signal_handlers_disconnect_matched (G_OBJECT (model->volume_manager), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model); - g_object_unref (G_OBJECT (model->volume_manager)); + /* unlink from the volume monitor */ + g_signal_handlers_disconnect_matched (model->volume_monitor, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model); + g_object_unref (model->volume_monitor); (*G_OBJECT_CLASS (thunar_shortcuts_model_parent_class)->finalize) (object); } @@ -488,7 +468,7 @@ thunar_shortcuts_model_get_column_type (GtkTreeModel *tree_model, return THUNAR_TYPE_FILE; case THUNAR_SHORTCUTS_MODEL_COLUMN_VOLUME: - return THUNAR_VFS_TYPE_VOLUME; + return G_TYPE_VOLUME; case THUNAR_SHORTCUTS_MODEL_COLUMN_MUTABLE: return G_TYPE_BOOLEAN; @@ -555,6 +535,8 @@ thunar_shortcuts_model_get_value (GtkTreeModel *tree_model, { ThunarShortcut *shortcut; ThunarFile *file; + GMount *mount; + GFile *mount_point; _thunar_return_if_fail (iter->stamp == THUNAR_SHORTCUTS_MODEL (tree_model)->stamp); _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (tree_model)); @@ -567,7 +549,7 @@ thunar_shortcuts_model_get_value (GtkTreeModel *tree_model, case THUNAR_SHORTCUTS_MODEL_COLUMN_NAME: g_value_init (value, G_TYPE_STRING); if (G_UNLIKELY (shortcut->volume != NULL)) - g_value_set_static_string (value, thunar_vfs_volume_get_name (shortcut->volume)); + g_value_take_string (value, g_volume_get_name (shortcut->volume)); else if (shortcut->name != NULL) g_value_set_static_string (value, shortcut->name); else if (shortcut->file != NULL) @@ -580,10 +562,22 @@ thunar_shortcuts_model_get_value (GtkTreeModel *tree_model, g_value_init (value, THUNAR_TYPE_FILE); if (shortcut->volume != NULL && shortcut->file == NULL) { - /* try to determine the file on-demand */ - file = thunar_file_get_for_path (thunar_vfs_volume_get_mount_point (shortcut->volume), NULL); - if (G_LIKELY (file != NULL)) - g_value_take_object (value, file); + /* determine the mount of the volume */ + mount = g_volume_get_mount (shortcut->volume); + + if (G_LIKELY (mount != NULL)) + { + /* the volume is mounted, get the mount point */ + mount_point = g_mount_get_root (mount); + + /* try to allocate/reference a file pointing to the mount point */ + file = thunar_file_get (mount_point, NULL); + g_value_take_object (value, file); + + /* release resources */ + g_object_unref (mount_point); + g_object_unref (mount); + } } else { @@ -592,7 +586,7 @@ thunar_shortcuts_model_get_value (GtkTreeModel *tree_model, break; case THUNAR_SHORTCUTS_MODEL_COLUMN_VOLUME: - g_value_init (value, THUNAR_VFS_TYPE_VOLUME); + g_value_init (value, G_TYPE_VOLUME); g_value_set_object (value, shortcut->volume); break; @@ -807,7 +801,6 @@ thunar_shortcuts_model_remove_shortcut (ThunarShortcutsModel *model, } } -#if GLIB_CHECK_VERSION(2, 14, 0) /* Reads the current xdg user dirs locale from ~/.config/xdg-user-dirs.locale * Notice that the result shall be freed by using g_free (). */ gchar * @@ -836,21 +829,23 @@ _thunar_get_xdg_user_dirs_locale (void) return locale; } -#endif static void thunar_shortcuts_model_load (ThunarShortcutsModel *model) { ThunarShortcut *shortcut; - ThunarVfsPath *file_path; GtkTreePath *path; + const gchar *user_special_dir = NULL; ThunarFile *file; + GFile *file_path; + GFile *home; gchar *bookmarks_path; gchar line[2048]; gchar *name; FILE *fp; gint i; - gchar *user_special_dir = NULL; + + home = thunar_g_file_new_for_home (); /* determine the path to the GTK+ bookmarks file */ bookmarks_path = xfce_get_homefile (".gtk-bookmarks", NULL); @@ -879,39 +874,38 @@ thunar_shortcuts_model_load (ThunarShortcutsModel *model) ; /* parse the URI */ - file_path = thunar_vfs_path_new (line, NULL); - if (G_UNLIKELY (file_path == NULL)) - continue; + file_path = g_file_new_for_uri (line); /* try to open the file corresponding to the uri */ - file = thunar_file_get_for_path (file_path, NULL); - thunar_vfs_path_unref (file_path); + file = thunar_file_get (file_path, NULL); + g_object_unref (file_path); + if (G_UNLIKELY (file == NULL)) continue; /* make sure the file refers to a directory */ - if (G_UNLIKELY (!thunar_file_is_directory (file))) + if (G_UNLIKELY (thunar_file_is_directory (file))) { - g_object_unref (G_OBJECT (file)); - continue; + /* create the shortcut entry */ + shortcut = _thunar_slice_new0 (ThunarShortcut); + shortcut->type = THUNAR_SHORTCUT_USER_DEFINED; + shortcut->file = file; + shortcut->name = (*name != '\0') ? g_strdup (name) : NULL; + + /* append the shortcut to the list */ + thunar_shortcuts_model_add_shortcut (model, shortcut, path); + gtk_tree_path_next (path); + } + else + { + g_object_unref (file); } - - /* create the shortcut entry */ - shortcut = _thunar_slice_new0 (ThunarShortcut); - shortcut->type = THUNAR_SHORTCUT_USER_DEFINED; - shortcut->file = file; - shortcut->name = (*name != '\0') ? g_strdup (name) : NULL; - - /* append the shortcut to the list */ - thunar_shortcuts_model_add_shortcut (model, shortcut, path); - gtk_tree_path_next (path); } /* clean up */ gtk_tree_path_free (path); fclose (fp); } -#if GLIB_CHECK_VERSION(2,14,0) else { /* ~/.gtk-bookmarks wasn't there or it was unreadable. @@ -935,9 +929,9 @@ thunar_shortcuts_model_load (ThunarShortcutsModel *model) path = gtk_tree_path_new_from_indices (g_list_length (model->shortcuts), -1); for (i = G_USER_DIRECTORY_DESKTOP; i < G_USER_N_DIRECTORIES && _thunar_user_directory_names[i] != NULL; - i++) + ++i) { - /* let's ignore some directories we don't want in the side pane*/ + /* let's ignore some directories we don't want in the side pane */ if (i == G_USER_DIRECTORY_DESKTOP || i == G_USER_DIRECTORY_PUBLIC_SHARE || i == G_USER_DIRECTORY_TEMPLATES) @@ -945,29 +939,29 @@ thunar_shortcuts_model_load (ThunarShortcutsModel *model) continue; } - user_special_dir = (gchar *) g_get_user_special_dir (i); + user_special_dir = g_get_user_special_dir (i); + + if (G_UNLIKELY (user_special_dir == NULL)) + continue; - if (G_UNLIKELY (user_special_dir == NULL) - || exo_str_is_equal (user_special_dir, xfce_get_homedir ())) + file_path = g_file_new_for_path (user_special_dir); + if (G_UNLIKELY (g_file_equal (file_path, home))) { - continue; + g_object_unref (file_path); + continue; } - /* parse the URI */ - file_path = thunar_vfs_path_new (user_special_dir, NULL); - if (G_UNLIKELY (file_path == NULL)) - continue; - /* try to open the file corresponding to the uri */ - file = thunar_file_get_for_path (file_path, NULL); - thunar_vfs_path_unref (file_path); + file = thunar_file_get (file_path, NULL); + g_object_unref (file_path); + if (G_UNLIKELY (file == NULL)) continue; /* make sure the file refers to a directory */ if (G_UNLIKELY (!thunar_file_is_directory (file))) { - g_object_unref (G_OBJECT (file)); + g_object_unref (file); continue; } @@ -975,7 +969,8 @@ thunar_shortcuts_model_load (ThunarShortcutsModel *model) shortcut = _thunar_slice_new0 (ThunarShortcut); shortcut->type = THUNAR_SHORTCUT_USER_DEFINED; shortcut->file = file; - shortcut->name = g_strdup (dgettext (XDG_USER_DIRS_PACKAGE, (gchar *) _thunar_user_directory_names[i])); + shortcut->name = g_strdup (dgettext (XDG_USER_DIRS_PACKAGE, + (gchar *) _thunar_user_directory_names[i])); /* append the shortcut to the list */ thunar_shortcuts_model_add_shortcut (model, shortcut, path); @@ -990,31 +985,29 @@ thunar_shortcuts_model_load (ThunarShortcutsModel *model) /* we try to save the obtained new model */ thunar_shortcuts_model_save (model); } -#endif /* GLIB_CHECK_VERSION(2,14,0) */ /* clean up */ + g_object_unref (home); g_free (bookmarks_path); } static void -thunar_shortcuts_model_monitor (ThunarVfsMonitor *monitor, - ThunarVfsMonitorHandle *handle, - ThunarVfsMonitorEvent event, - ThunarVfsPath *handle_path, - ThunarVfsPath *event_path, - gpointer user_data) +thunar_shortcuts_model_monitor (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) { ThunarShortcutsModel *model = THUNAR_SHORTCUTS_MODEL (user_data); ThunarShortcut *shortcut; - GtkTreePath *path; - GList *lp; - gint index; + GtkTreePath *path; + GList *lp; + gint index; _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model)); _thunar_return_if_fail (model->monitor == monitor); - _thunar_return_if_fail (model->handle == handle); /* drop all existing user-defined shortcuts from the model */ for (index = 0, lp = model->shortcuts; lp != NULL; ) @@ -1055,12 +1048,12 @@ static void thunar_shortcuts_model_save (ThunarShortcutsModel *model) { ThunarShortcut *shortcut; - gchar *bookmarks_path; - gchar *tmp_path; - gchar *uri; - GList *lp; - FILE *fp; - gint fd; + gchar *bookmarks_path; + gchar *tmp_path; + gchar *uri; + GList *lp; + FILE *fp; + gint fd; _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model)); @@ -1082,7 +1075,7 @@ thunar_shortcuts_model_save (ThunarShortcutsModel *model) shortcut = THUNAR_SHORTCUT (lp->data); if (shortcut->type == THUNAR_SHORTCUT_USER_DEFINED) { - uri = thunar_vfs_path_dup_uri (thunar_file_get_path (shortcut->file)); + uri = g_file_get_uri (thunar_file_get_file (shortcut->file)); if (G_LIKELY (shortcut->name != NULL)) fprintf (fp, "%s %s\n", uri, shortcut->name); else @@ -1100,7 +1093,7 @@ thunar_shortcuts_model_save (ThunarShortcutsModel *model) { g_warning ("Failed to write `%s': %s", bookmarks_path, g_strerror (errno)); - unlink (tmp_path); + g_unlink (tmp_path); } /* cleanup */ @@ -1115,18 +1108,18 @@ thunar_shortcuts_model_file_changed (ThunarFile *file, ThunarShortcutsModel *model) { ThunarShortcut *shortcut; - GtkTreePath *path; - GtkTreeIter iter; - GList *lp; - gint index; + GtkTreePath *path; + GtkTreeIter iter; + GList *lp; + gint index; _thunar_return_if_fail (THUNAR_IS_FILE (file)); _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model)); - /* check if the file still refers to a directory, else we cannot keep - * it on the shortcuts list, and so we'll treat it like the file - * was destroyed (and thereby removed) - */ + /* check if the file still refers to a directory or a not mounted URI, + * otherwise we cannot keep it on the shortcuts list, and so we'll treat + * it like the file was destroyed (and thereby removed) */ + if (G_UNLIKELY (!thunar_file_is_directory (file))) { thunar_shortcuts_model_file_destroy (file, model); @@ -1179,16 +1172,19 @@ thunar_shortcuts_model_file_destroy (ThunarFile *file, static void -thunar_shortcuts_model_volume_changed (ThunarVfsVolume *volume, +thunar_shortcuts_model_volume_changed (GVolumeMonitor *volume_monitor, + GVolume *volume, ThunarShortcutsModel *model) { ThunarShortcut *shortcut = NULL; - GtkTreePath *path; - GtkTreeIter iter; - GList *lp; - gint index; + GtkTreePath *path; + GtkTreeIter iter; + GList *lp; + gint index; - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (model->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_VOLUME (volume)); _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model)); /* check if the volume is on the hidden list */ @@ -1196,7 +1192,7 @@ thunar_shortcuts_model_volume_changed (ThunarVfsVolume *volume, if (lp != NULL) { /* check if we need to display the volume now */ - if (thunar_vfs_volume_is_present (volume) && thunar_vfs_volume_is_removable (volume)) + if (thunar_g_volume_is_removable (volume) && thunar_g_volume_is_present (volume)) { /* remove the volume from the list of hidden volumes */ model->hidden_volumes = g_list_delete_link (model->hidden_volumes, lp); @@ -1224,11 +1220,12 @@ thunar_shortcuts_model_volume_changed (ThunarVfsVolume *volume, else { /* lookup the shortcut that contains the given volume */ - for (index = 0, lp = model->shortcuts; lp != NULL; ++index, lp = lp->next) + for (index = 0, lp = model->shortcuts; + shortcut == NULL && lp != NULL; + ++index, lp = lp->next) { - shortcut = THUNAR_SHORTCUT (lp->data); - if (shortcut->volume == volume) - break; + if (THUNAR_SHORTCUT (lp->data)->volume == volume) + shortcut = lp->data; } /* verify that we actually found the shortcut */ @@ -1236,19 +1233,14 @@ thunar_shortcuts_model_volume_changed (ThunarVfsVolume *volume, _thunar_assert (shortcut->volume == volume); /* check if we need to hide the volume now */ - if (!thunar_vfs_volume_is_present (volume) || !thunar_vfs_volume_is_removable (volume)) + if (!thunar_g_volume_is_removable (volume) || !thunar_g_volume_is_present (volume)) { - /* need to ref here, because the file_destroy() handler will drop the refcount. */ - g_object_ref (G_OBJECT (volume)); - /* move the volume to the hidden list */ - model->hidden_volumes = g_list_prepend (model->hidden_volumes, volume); + model->hidden_volumes = g_list_prepend (model->hidden_volumes, + g_object_ref (volume)); /* remove the shortcut from the user interface */ thunar_shortcuts_model_remove_shortcut (model, shortcut); - - /* need to reconnect to the volume, as the shortcut removal drops the handler */ - g_signal_connect (G_OBJECT (volume), "changed", G_CALLBACK (thunar_shortcuts_model_volume_changed), model); } else { @@ -1266,75 +1258,56 @@ thunar_shortcuts_model_volume_changed (ThunarVfsVolume *volume, static void -thunar_shortcuts_model_volumes_added (ThunarVfsVolumeManager *volume_manager, - GList *volumes, - ThunarShortcutsModel *model) +thunar_shortcuts_model_volume_added (GVolumeMonitor *volume_monitor, + GVolume *volume, + ThunarShortcutsModel *model) { - GList *lp; - - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager)); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (model->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_VOLUME (volume)); _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model)); - _thunar_return_if_fail (model->volume_manager == volume_manager); - - /* process all newly added volumes */ - for (lp = volumes; lp != NULL; lp = lp->next) - { - /* take a reference on the volume... */ - g_object_ref (G_OBJECT (lp->data)); - - /* ...place the volume on the hidden list... */ - model->hidden_volumes = g_list_prepend (model->hidden_volumes, lp->data); - /* ...connect the "changed" signal handler ... */ - g_signal_connect (G_OBJECT (lp->data), "changed", G_CALLBACK (thunar_shortcuts_model_volume_changed), model); + /* place the volume on the hidden list */ + model->hidden_volumes = g_list_prepend (model->hidden_volumes, g_object_ref (volume)); - /* ...and let the "changed" handler place the volume where appropriate */ - thunar_shortcuts_model_volume_changed (lp->data, model); - } + /* let the "changed" handler place the volume where appropriate */ + thunar_shortcuts_model_volume_changed (volume_monitor, volume, model); } static void -thunar_shortcuts_model_volumes_removed (ThunarVfsVolumeManager *volume_manager, - GList *volumes, - ThunarShortcutsModel *model) +thunar_shortcuts_model_volume_removed (GVolumeMonitor *volume_monitor, + GVolume *volume, + ThunarShortcutsModel *model) { - GList *hp; GList *lp; - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager)); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (model->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_VOLUME (volume)); _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model)); - _thunar_return_if_fail (model->volume_manager == volume_manager); - /* process all removed volumes */ - for (lp = volumes; lp != NULL; lp = lp->next) + lp = g_list_find (model->hidden_volumes, volume); + if (G_LIKELY (lp != NULL)) { - /* disconnect the "changed" signal handler from the volume */ - g_signal_handlers_disconnect_by_func (G_OBJECT (lp->data), thunar_shortcuts_model_volume_changed, model); - - /* check if the volume is on the hidden list */ - hp = g_list_find (model->hidden_volumes, lp->data); - if (G_LIKELY (hp != NULL)) - { - /* drop the volume from the hidden list and drop our reference */ - model->hidden_volumes = g_list_delete_link (model->hidden_volumes, hp); - g_object_unref (G_OBJECT (lp->data)); - } - else - { - /* must be an active shortcut then... */ - for (hp = model->shortcuts; hp != NULL; hp = hp->next) - if (THUNAR_SHORTCUT (hp->data)->volume == lp->data) - break; + /* remove the volume from the hidden list and drop our reference */ + model->hidden_volumes = g_list_delete_link (model->hidden_volumes, lp); + g_object_unref (volume); + } + else + { + /* must be an active shortcut then... */ + for (lp = model->shortcuts; lp != NULL; lp = lp->next) + if (THUNAR_SHORTCUT (lp->data)->volume == volume) + break; - /* something is broken if we don't have a shortcut here */ - _thunar_assert (hp != NULL); - _thunar_assert (THUNAR_SHORTCUT (hp->data)->volume == lp->data); + /* something is broken if we don't have a shortcut here */ + _thunar_assert (lp != NULL); + _thunar_assert (THUNAR_SHORTCUT (lp->data)->volume == volume); - /* drop the shortcut from the model */ - thunar_shortcuts_model_remove_shortcut (model, hp->data); - } + /* drop the shortcut from the model */ + thunar_shortcuts_model_remove_shortcut (model, lp->data); } } @@ -1350,18 +1323,18 @@ thunar_shortcut_free (ThunarShortcut *shortcut, thunar_file_unwatch (shortcut->file); /* unregister from the file */ - g_signal_handlers_disconnect_matched (G_OBJECT (shortcut->file), + g_signal_handlers_disconnect_matched (shortcut->file, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model); - g_object_unref (G_OBJECT (shortcut->file)); + g_object_unref (shortcut->file); } if (G_LIKELY (shortcut->volume != NULL)) { - g_signal_handlers_disconnect_matched (G_OBJECT (shortcut->volume), + g_signal_handlers_disconnect_matched (shortcut->volume, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model); - g_object_unref (G_OBJECT (shortcut->volume)); + g_object_unref (shortcut->volume); } /* release the shortcut name */ @@ -1422,8 +1395,9 @@ thunar_shortcuts_model_iter_for_file (ThunarShortcutsModel *model, ThunarFile *file, GtkTreeIter *iter) { - ThunarVfsPath *mount_point; - GList *lp; + GMount *mount; + GFile *mount_point; + GList *lp; _thunar_return_val_if_fail (THUNAR_IS_SHORTCUTS_MODEL (model), FALSE); _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); @@ -1439,14 +1413,24 @@ thunar_shortcuts_model_iter_for_file (ThunarShortcutsModel *model, } /* but maybe we have a mounted(!) volume with a matching mount point */ - if (THUNAR_SHORTCUT (lp->data)->volume != NULL && thunar_vfs_volume_is_mounted (THUNAR_SHORTCUT (lp->data)->volume)) + if (THUNAR_SHORTCUT (lp->data)->volume != NULL) { - /* check if we have a mount point for the volume */ - mount_point = thunar_vfs_volume_get_mount_point (THUNAR_SHORTCUT (lp->data)->volume); - if (G_LIKELY (mount_point != NULL && thunar_vfs_path_equal (mount_point, thunar_file_get_path (file)))) + mount = g_volume_get_mount (THUNAR_SHORTCUT (lp->data)->volume); + + if (G_LIKELY (mount != NULL)) { - GTK_TREE_ITER_INIT (*iter, model->stamp, lp); - return TRUE; + mount_point = g_mount_get_root (mount); + + if (G_LIKELY (g_file_equal (mount_point, thunar_file_get_file (file)))) + { + GTK_TREE_ITER_INIT (*iter, model->stamp, lp); + g_object_unref (mount_point); + g_object_unref (mount); + return TRUE; + } + + g_object_unref (mount_point); + g_object_unref (mount); } } } diff --git a/thunar/thunar-shortcuts-view.c b/thunar/thunar-shortcuts-view.c index 127ffda19..f5895df41 100644 --- a/thunar/thunar-shortcuts-view.c +++ b/thunar/thunar-shortcuts-view.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -32,8 +33,10 @@ #endif #include <thunar/thunar-application.h> +#include <thunar/thunar-browser.h> #include <thunar/thunar-dialogs.h> #include <thunar/thunar-dnd.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-gtk-extensions.h> #include <thunar/thunar-preferences.h> #include <thunar/thunar-private.h> @@ -59,73 +62,72 @@ enum -static void thunar_shortcuts_view_class_init (ThunarShortcutsViewClass *klass); -static void thunar_shortcuts_view_init (ThunarShortcutsView *view); -static void thunar_shortcuts_view_finalize (GObject *object); -static gboolean thunar_shortcuts_view_button_press_event (GtkWidget *widget, - GdkEventButton *event); -static gboolean thunar_shortcuts_view_button_release_event (GtkWidget *widget, - GdkEventButton *event); -static void thunar_shortcuts_view_drag_begin (GtkWidget *widget, - GdkDragContext *context); -static void thunar_shortcuts_view_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time); -static gboolean thunar_shortcuts_view_drag_drop (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); -static gboolean thunar_shortcuts_view_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); -static void thunar_shortcuts_view_drag_leave (GtkWidget *widget, - GdkDragContext *context, - guint time); -static gboolean thunar_shortcuts_view_popup_menu (GtkWidget *widget); -static void thunar_shortcuts_view_row_activated (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column); -static void thunar_shortcuts_view_context_menu (ThunarShortcutsView *view, - GdkEventButton *event, - GtkTreeModel *model, - GtkTreeIter *iter); -static void thunar_shortcuts_view_remove_activated (GtkWidget *item, - ThunarShortcutsView *view); -static void thunar_shortcuts_view_rename_activated (GtkWidget *item, - ThunarShortcutsView *view); -static void thunar_shortcuts_view_renamed (GtkCellRenderer *renderer, - const gchar *path_string, - const gchar *text, - ThunarShortcutsView *view); -static GdkDragAction thunar_shortcuts_view_compute_drop_actions (ThunarShortcutsView *view, - GdkDragContext *context, - gint x, - gint y, - GtkTreePath **path_return, - GdkDragAction *action_return, - GtkTreeViewDropPosition *position_return); -static GtkTreePath *thunar_shortcuts_view_compute_drop_position (ThunarShortcutsView *view, - gint x, - gint y); -static void thunar_shortcuts_view_drop_uri_list (ThunarShortcutsView *view, - GList *path_list, - GtkTreePath *dst_path); -static void thunar_shortcuts_view_open (ThunarShortcutsView *view); -static void thunar_shortcuts_view_open_in_new_window (ThunarShortcutsView *view); -static void thunar_shortcuts_view_empty_trash (ThunarShortcutsView *view); -static gboolean thunar_shortcuts_view_eject (ThunarShortcutsView *view); -static gboolean thunar_shortcuts_view_mount (ThunarShortcutsView *view); -static gboolean thunar_shortcuts_view_unmount (ThunarShortcutsView *view); -static gboolean thunar_shortcuts_view_separator_func (GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data); +static void thunar_shortcuts_view_finalize (GObject *object); +static gboolean thunar_shortcuts_view_button_press_event (GtkWidget *widget, + GdkEventButton *event); +static gboolean thunar_shortcuts_view_button_release_event (GtkWidget *widget, + GdkEventButton *event); +static void thunar_shortcuts_view_drag_begin (GtkWidget *widget, + GdkDragContext *context); +static void thunar_shortcuts_view_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time); +static gboolean thunar_shortcuts_view_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static gboolean thunar_shortcuts_view_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static void thunar_shortcuts_view_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time); +static gboolean thunar_shortcuts_view_popup_menu (GtkWidget *widget); +static void thunar_shortcuts_view_row_activated (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column); +static void thunar_shortcuts_view_context_menu (ThunarShortcutsView *view, + GdkEventButton *event, + GtkTreeModel *model, + GtkTreeIter *iter); +static void thunar_shortcuts_view_remove_activated (GtkWidget *item, + ThunarShortcutsView *view); +static void thunar_shortcuts_view_rename_activated (GtkWidget *item, + ThunarShortcutsView *view); +static void thunar_shortcuts_view_renamed (GtkCellRenderer *renderer, + const gchar *path_string, + const gchar *text, + ThunarShortcutsView *view); +static GdkDragAction thunar_shortcuts_view_compute_drop_actions (ThunarShortcutsView *view, + GdkDragContext *context, + gint x, + gint y, + GtkTreePath **path_return, + GdkDragAction *action_return, + GtkTreeViewDropPosition *position_return); +static GtkTreePath *thunar_shortcuts_view_compute_drop_position (ThunarShortcutsView *view, + gint x, + gint y); +static void thunar_shortcuts_view_drop_uri_list (ThunarShortcutsView *view, + GList *path_list, + GtkTreePath *dst_path); +static void thunar_shortcuts_view_open_clicked (ThunarShortcutsView *view); +static void thunar_shortcuts_view_open (ThunarShortcutsView *view, + gboolean new_window); +static void thunar_shortcuts_view_open_in_new_window_clicked (ThunarShortcutsView *view); +static void thunar_shortcuts_view_empty_trash (ThunarShortcutsView *view); +static void thunar_shortcuts_view_eject (ThunarShortcutsView *view); +static void thunar_shortcuts_view_mount (ThunarShortcutsView *view); +static gboolean thunar_shortcuts_view_separator_func (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data); @@ -151,14 +153,12 @@ struct _ThunarShortcutsView /* drop site support */ guint drop_data_ready : 1; /* whether the drop data was received already */ guint drop_occurred : 1; - GList *drop_path_list; /* the list of URIs that are contained in the drop data */ + GList *drop_file_list; /* the list of URIs that are contained in the drop data */ -#if GTK_CHECK_VERSION(2,8,0) /* id of the signal used to queue a resize on the * column whenever the shortcuts icon size is changed. */ gint queue_resize_signal_id; -#endif }; @@ -176,37 +176,12 @@ static const GtkTargetEntry drop_targets[] = { -static GObjectClass *thunar_shortcuts_view_parent_class; -static guint view_signals[LAST_SIGNAL]; - +static guint view_signals[LAST_SIGNAL]; -GType -thunar_shortcuts_view_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - static const GTypeInfo info = - { - sizeof (ThunarShortcutsViewClass), - NULL, - NULL, - (GClassInitFunc) thunar_shortcuts_view_class_init, - NULL, - NULL, - sizeof (ThunarShortcutsView), - 0, - (GInstanceInitFunc) thunar_shortcuts_view_init, - NULL, - }; - - type = g_type_register_static (GTK_TYPE_TREE_VIEW, I_("ThunarShortcutsView"), &info, 0); - } - return type; -} +G_DEFINE_TYPE_WITH_CODE (ThunarShortcutsView, thunar_shortcuts_view, GTK_TYPE_TREE_VIEW, + G_IMPLEMENT_INTERFACE (THUNAR_TYPE_BROWSER, NULL)); @@ -217,9 +192,6 @@ thunar_shortcuts_view_class_init (ThunarShortcutsViewClass *klass) GtkWidgetClass *gtkwidget_class; GObjectClass *gobject_class; - /* determine the parent type class */ - thunar_shortcuts_view_parent_class = g_type_class_peek_parent (klass); - gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = thunar_shortcuts_view_finalize; @@ -281,10 +253,8 @@ thunar_shortcuts_view_init (ThunarShortcutsView *view) gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); /* queue a resize on the column whenever the icon size is changed */ -#if GTK_CHECK_VERSION(2,8,0) view->queue_resize_signal_id = g_signal_connect_swapped (G_OBJECT (view->preferences), "notify::shortcuts-icon-size", G_CALLBACK (gtk_tree_view_column_queue_resize), column); -#endif /* allocate the special icon renderer */ view->icon_renderer = thunar_shortcuts_icon_renderer_new (); @@ -334,15 +304,13 @@ thunar_shortcuts_view_finalize (GObject *object) ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (object); /* release drop path list (if drag_leave wasn't called) */ - thunar_vfs_path_list_free (view->drop_path_list); + thunar_g_file_list_free (view->drop_file_list); /* release the provider factory */ g_object_unref (G_OBJECT (view->provider_factory)); /* disconnect the queue resize signal handler */ -#if GTK_CHECK_VERSION(2,8,0) g_signal_handler_disconnect (G_OBJECT (view->preferences), view->queue_resize_signal_id); -#endif /* disconnect from the preferences object */ g_signal_handlers_disconnect_matched (G_OBJECT (view->preferences), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); @@ -417,9 +385,9 @@ thunar_shortcuts_view_button_release_event (GtkWidget *widget, { /* check if we should simply open or open in new window */ if (G_LIKELY (event->button == 1)) - thunar_shortcuts_view_open (view); + thunar_shortcuts_view_open (view, FALSE); else if (G_UNLIKELY (event->button == 2)) - thunar_shortcuts_view_open_in_new_window (view); + thunar_shortcuts_view_open (view, TRUE); } /* reset the pressed button state */ @@ -473,7 +441,7 @@ thunar_shortcuts_view_drag_data_received (GtkWidget *widget, { /* extract the URI list from the selection data (if valid) */ if (info == TEXT_URI_LIST && selection_data->format == 8 && selection_data->length > 0) - view->drop_path_list = thunar_vfs_path_list_from_string ((const gchar *) selection_data->data, NULL); + view->drop_file_list = thunar_g_file_list_new_from_string ((const gchar *) selection_data->data); /* reset the state */ view->drop_data_ready = TRUE; @@ -502,7 +470,7 @@ thunar_shortcuts_view_drag_data_received (GtkWidget *widget, gtk_tree_path_next (path); /* just add the required shortcuts then */ - thunar_shortcuts_view_drop_uri_list (view, view->drop_path_list, path); + thunar_shortcuts_view_drop_uri_list (view, view->drop_file_list, path); } else if (G_LIKELY ((actions & (GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK)) != 0)) { @@ -518,13 +486,13 @@ thunar_shortcuts_view_drag_data_received (GtkWidget *widget, { /* ask the user what to do with the drop data */ if (G_UNLIKELY (action == GDK_ACTION_ASK)) - action = thunar_dnd_ask (widget, file, view->drop_path_list, time, actions); + action = thunar_dnd_ask (widget, file, view->drop_file_list, time, actions); /* perform the requested action */ if (G_LIKELY (action != 0)) { /* really perform the drop :-) */ - succeed = thunar_dnd_perform (widget, file, view->drop_path_list, action, NULL); + succeed = thunar_dnd_perform (widget, file, view->drop_file_list, action, NULL); } /* release the file */ @@ -719,9 +687,9 @@ thunar_shortcuts_view_drag_leave (GtkWidget *widget, /* reset the "drop data ready" status and free the URI list */ if (G_LIKELY (view->drop_data_ready)) { - thunar_vfs_path_list_free (view->drop_path_list); + thunar_g_file_list_free (view->drop_file_list); view->drop_data_ready = FALSE; - view->drop_path_list = NULL; + view->drop_file_list = NULL; } /* schedule a repaint to make sure the special drop icon for the target row @@ -776,7 +744,7 @@ thunar_shortcuts_view_row_activated (GtkTreeView *tree_view, (*GTK_TREE_VIEW_CLASS (thunar_shortcuts_view_parent_class)->row_activated) (tree_view, path, column); /* open the selected shortcut */ - thunar_shortcuts_view_open (view); + thunar_shortcuts_view_open (view, FALSE); } @@ -787,16 +755,16 @@ thunar_shortcuts_view_context_menu (ThunarShortcutsView *view, GtkTreeModel *model, GtkTreeIter *iter) { - ThunarVfsVolume *volume; - GtkTreePath *path; - ThunarFile *file; - GtkWidget *image; - GtkWidget *menu; - GtkWidget *item; - gboolean mutable; - GtkWidget *window; - GList *providers, *lp; - GList *actions = NULL, *tmp; + GtkTreePath *path; + ThunarFile *file; + GtkWidget *image; + GtkWidget *menu; + GtkWidget *item; + GtkWidget *window; + gboolean mutable; + GVolume *volume; + GList *providers, *lp; + GList *actions = NULL, *tmp; /* determine the tree path for the given iter */ path = gtk_tree_model_get_path (model, iter); @@ -815,7 +783,7 @@ thunar_shortcuts_view_context_menu (ThunarShortcutsView *view, /* append the "Open" menu action */ item = gtk_image_menu_item_new_with_mnemonic (_("_Open")); - g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_open), view); + g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_open_clicked), view); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); @@ -826,7 +794,7 @@ thunar_shortcuts_view_context_menu (ThunarShortcutsView *view, /* append the "Open in New Window" menu action */ item = gtk_image_menu_item_new_with_mnemonic (_("Open in New Window")); - g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_open_in_new_window), view); + g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_open_in_new_window_clicked), view); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); @@ -840,13 +808,13 @@ thunar_shortcuts_view_context_menu (ThunarShortcutsView *view, { /* append the "Mount Volume" menu action */ item = gtk_image_menu_item_new_with_mnemonic (_("_Mount Volume")); - gtk_widget_set_sensitive (item, !thunar_vfs_volume_is_mounted (volume)); + gtk_widget_set_sensitive (item, !thunar_g_volume_is_mounted (volume)); g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_mount), view); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* check if the volume is ejectable */ - if (thunar_vfs_volume_is_ejectable (volume)) + if (thunar_g_volume_is_removable (volume)) { /* append the "Eject Volume" menu action */ item = gtk_image_menu_item_new_with_mnemonic (_("E_ject Volume")); @@ -854,15 +822,6 @@ thunar_shortcuts_view_context_menu (ThunarShortcutsView *view, gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); } - else - { - /* append the "Unmount Volume" menu item */ - item = gtk_image_menu_item_new_with_mnemonic (_("_Unmount Volume")); - gtk_widget_set_sensitive (item, thunar_vfs_volume_is_mounted (volume)); - g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_shortcuts_view_unmount), view); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); - } /* append a menu separator */ item = gtk_separator_menu_item_new (); @@ -1076,7 +1035,7 @@ thunar_shortcuts_view_compute_drop_actions (ThunarShortcutsView *view, if (G_LIKELY (file != NULL)) { /* check if the file accepts the drop */ - actions = thunar_file_accepts_drop (file, view->drop_path_list, context, action_return); + actions = thunar_file_accepts_drop (file, view->drop_file_list, context, action_return); if (G_LIKELY (actions != 0)) { /* we can drop into this location */ @@ -1191,8 +1150,6 @@ thunar_shortcuts_view_drop_uri_list (ThunarShortcutsView *view, GtkTreePath *path; ThunarFile *file; GError *error = NULL; - gchar *display_string; - gchar *uri_string; GList *lp; /* take a copy of the destination path */ @@ -1202,26 +1159,22 @@ thunar_shortcuts_view_drop_uri_list (ThunarShortcutsView *view, model = gtk_tree_view_get_model (GTK_TREE_VIEW (view)); for (lp = path_list; lp != NULL; lp = lp->next) { - file = thunar_file_get_for_path (lp->data, &error); + file = thunar_file_get (lp->data, &error); if (G_UNLIKELY (file == NULL)) break; /* make sure, that only directories gets added to the shortcuts list */ if (G_UNLIKELY (!thunar_file_is_directory (file))) { - uri_string = thunar_vfs_path_dup_string (lp->data); - display_string = g_filename_display_name (uri_string); g_set_error (&error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR, _("The path \"%s\" does not refer to a directory"), - display_string); - g_object_unref (G_OBJECT (file)); - g_free (display_string); - g_free (uri_string); + thunar_file_get_display_name (file)); + g_object_unref (file); break; } thunar_shortcuts_model_add (THUNAR_SHORTCUTS_MODEL (model), path, file); - g_object_unref (G_OBJECT (file)); + g_object_unref (file); gtk_tree_path_next (path); } @@ -1241,70 +1194,141 @@ thunar_shortcuts_view_drop_uri_list (ThunarShortcutsView *view, static void -thunar_shortcuts_view_open (ThunarShortcutsView *view) +thunar_shortcuts_view_open_clicked (ThunarShortcutsView *view) { - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - ThunarFile *file; - _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view)); + thunar_shortcuts_view_open (view, FALSE); +} - /* make sure to mount the volume first (if it's a volume) */ - if (!thunar_shortcuts_view_mount (view)) - return; - /* determine the selected item */ - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) + +static void +thunar_shortcuts_view_poke_file_finish (ThunarBrowser *browser, + ThunarFile *file, + ThunarFile *target_file, + GError *error, + gpointer user_data) +{ + ThunarApplication *application; + gboolean new_window = GPOINTER_TO_UINT (user_data); + + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + if (error == NULL) { - /* determine the file for the shortcut at the given tree iterator */ - gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file, -1); - if (G_LIKELY (file != NULL)) + if (new_window) + { + /* open a new window for the target folder */ + application = thunar_application_get (); + thunar_application_open_window (application, target_file, + gtk_widget_get_screen (GTK_WIDGET (browser)), NULL); + g_object_unref (application); + } + else { /* invoke the signal to change to that folder */ - g_signal_emit (G_OBJECT (view), view_signals[SHORTCUT_ACTIVATED], 0, file); - g_object_unref (G_OBJECT (file)); + g_signal_emit (browser, view_signals[SHORTCUT_ACTIVATED], 0, target_file); } } + else + { + thunar_dialogs_show_error (GTK_WIDGET (browser), error, _("Failed to open \"%s\""), + thunar_file_get_display_name (file)); + } } static void -thunar_shortcuts_view_open_in_new_window (ThunarShortcutsView *view) +thunar_shortcuts_view_poke_volume_finish (ThunarBrowser *browser, + GVolume *volume, + ThunarFile *mount_point, + GError *error, + gpointer user_data) { - ThunarApplication *application; - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - ThunarFile *file; + gboolean new_window = GPOINTER_TO_UINT (user_data); + gchar *volume_name; + + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (browser)); + _thunar_return_if_fail (G_IS_VOLUME (volume)); + + if (error == NULL) + { + thunar_browser_poke_file (browser, mount_point, GTK_WIDGET (browser), + thunar_shortcuts_view_poke_file_finish, + GUINT_TO_POINTER (new_window)); + } + else + { + volume_name = g_volume_get_name (volume); + thunar_dialogs_show_error (GTK_WIDGET (browser), error, + _("Failed to mount \"%s\""), volume_name); + g_free (volume_name); + } +} - _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view)); - /* make sure to mount the volume first (if it's a volume) */ - if (!thunar_shortcuts_view_mount (view)) - return; + +static void +thunar_shortcuts_view_open (ThunarShortcutsView *view, + gboolean new_window) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + ThunarFile *file; + GVolume *volume; + + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view)); /* determine the selected item */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); + + /* avoid dealing with invalid selections */ + if (!GTK_IS_TREE_SELECTION (selection)) + return; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { /* determine the file for the shortcut at the given tree iterator */ - gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file, -1); - if (G_LIKELY (file != NULL)) + gtk_tree_model_get (model, &iter, + THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file, + THUNAR_SHORTCUTS_MODEL_COLUMN_VOLUME, &volume, + -1); + + if (G_LIKELY (volume != NULL)) { - /* open a new window for the shortcut target folder */ - application = thunar_application_get (); - thunar_application_open_window (application, file, gtk_widget_get_screen (GTK_WIDGET (view))); - g_object_unref (G_OBJECT (application)); - g_object_unref (G_OBJECT (file)); + thunar_browser_poke_volume (THUNAR_BROWSER (view), volume, view, + thunar_shortcuts_view_poke_volume_finish, + GUINT_TO_POINTER (new_window)); } + else if (file != NULL) + { + thunar_browser_poke_file (THUNAR_BROWSER (view), file, view, + thunar_shortcuts_view_poke_file_finish, + GUINT_TO_POINTER (new_window)); + } + + if (file != NULL) + g_object_unref (file); + + if (volume != NULL) + g_object_unref (volume); } } +static void +thunar_shortcuts_view_open_in_new_window_clicked (ThunarShortcutsView *view) +{ + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view)); + thunar_shortcuts_view_open (view, TRUE); +} + + + static void thunar_shortcuts_view_empty_trash (ThunarShortcutsView *view) { @@ -1320,61 +1344,90 @@ thunar_shortcuts_view_empty_trash (ThunarShortcutsView *view) -static gboolean -thunar_shortcuts_view_eject (ThunarShortcutsView *view) +static void +thunar_shortcuts_view_eject_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) { - GtkTreeSelection *selection; - ThunarVfsVolume *volume; - GtkTreeModel *model; - GtkTreeIter iter; - GtkWidget *window; - gboolean result = TRUE; - GError *error = NULL; + ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (user_data); + GtkWidget *window; + GVolume *volume = G_VOLUME (object); + GError *error = NULL; + gchar *volume_name; + + _thunar_return_if_fail (G_IS_VOLUME (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view)); - _thunar_return_val_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view), FALSE); + /* check if there was an error */ + if (!g_volume_eject_finish (volume, result, &error)) + { + /* ignore GIO errors already handled */ + if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_FAILED_HANDLED) + { + window = gtk_widget_get_toplevel (GTK_WIDGET (view)); - /* determine the selected item */ - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) + /* display an error dialog to inform the user */ + volume_name = g_volume_get_name (volume); + thunar_dialogs_show_error (window, error, _("Failed to eject \"%s\""), volume_name); + g_free (volume_name); + + g_error_free (error); + } + } + + g_object_unref (view); +} + + + +static void +thunar_shortcuts_view_unmount_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (user_data); + GtkWidget *window; + GMount *mount = G_MOUNT (object); + GError *error = NULL; + gchar *mount_name; + + _thunar_return_if_fail (G_IS_MOUNT (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view)); + + /* check if there was an error */ + if (!g_mount_unmount_finish (mount, result, &error)) { - /* determine the volume for the shortcut at the given tree iterator */ - gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_VOLUME, &volume, -1); - if (G_UNLIKELY (volume != NULL)) + /* ignore GIO errors already handled */ + if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_FAILED_HANDLED) { - /* determine the toplevel window */ window = gtk_widget_get_toplevel (GTK_WIDGET (view)); - /* try to eject the volume */ - result = thunar_vfs_volume_eject (volume, window, &error); - if (G_UNLIKELY (!result)) - { - /* display an error dialog to inform the user */ - thunar_dialogs_show_error (window, error, _("Failed to eject \"%s\""), thunar_vfs_volume_get_name (volume)); - g_error_free (error); - } + /* display an error dialog to inform the user */ + mount_name = g_mount_get_name (mount); + thunar_dialogs_show_error (window, error, _("Failed to eject \"%s\""), mount_name); + g_free (mount_name); - /* cleanup */ - g_object_unref (G_OBJECT (volume)); + g_error_free (error); } } - return result; + g_object_unref (view); } -static gboolean -thunar_shortcuts_view_mount (ThunarShortcutsView *view) +static void +thunar_shortcuts_view_eject (ThunarShortcutsView *view) { GtkTreeSelection *selection; - ThunarVfsVolume *volume; GtkTreeModel *model; GtkTreeIter iter; - GtkWidget *window; - gboolean result = TRUE; - GError *error = NULL; + GVolume *volume; + GMount *mount; - _thunar_return_val_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view), FALSE); + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view)); /* determine the selected item */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); @@ -1384,71 +1437,94 @@ thunar_shortcuts_view_mount (ThunarShortcutsView *view) gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_VOLUME, &volume, -1); if (G_UNLIKELY (volume != NULL)) { - /* check if the volume isn't already mounted */ - if (G_LIKELY (!thunar_vfs_volume_is_mounted (volume))) + /* determine what the appropriate method is: eject or unmount */ + if (g_volume_can_eject (volume)) { - /* determine the toplevel window */ - window = gtk_widget_get_toplevel (GTK_WIDGET (view)); - - /* try to mount the volume */ - result = thunar_vfs_volume_mount (volume, window, &error); - if (G_UNLIKELY (!result)) + /* try to to eject the volume asynchronously */ + g_volume_eject (volume, G_MOUNT_UNMOUNT_NONE, NULL, + thunar_shortcuts_view_eject_finish, + g_object_ref (view)); + } + else + { + /* determine the mount of the volume */ + mount = g_volume_get_mount (volume); + if (G_LIKELY (mount != NULL)) { - /* display an error dialog to inform the user */ - thunar_dialogs_show_error (window, error, _("Failed to mount \"%s\""), thunar_vfs_volume_get_name (volume)); - g_error_free (error); + /* the volume is mounted, try to unmount the mount */ + g_mount_unmount (mount, G_MOUNT_UNMOUNT_NONE, NULL, + thunar_shortcuts_view_unmount_finish, + g_object_ref (view)); + + /* release the mount */ + g_object_unref (mount); } } /* cleanup */ - g_object_unref (G_OBJECT (volume)); + g_object_unref (volume); } } +} - return result; + + +static void +thunar_shortcuts_view_poke_volume_mount_finish (ThunarBrowser *browser, + GVolume *volume, + ThunarFile *mount_point, + GError *error, + gpointer ignored) +{ + gchar *volume_name; + + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (browser)); + _thunar_return_if_fail (G_IS_VOLUME (volume)); + + if (error != NULL) + { + volume_name = g_volume_get_name (volume); + thunar_dialogs_show_error (GTK_WIDGET (browser), error, + _("Failed to mount \"%s\""), volume_name); + g_free (volume_name); + } } -static gboolean -thunar_shortcuts_view_unmount (ThunarShortcutsView *view) + +static void +thunar_shortcuts_view_mount (ThunarShortcutsView *view) { GtkTreeSelection *selection; - ThunarVfsVolume *volume; GtkTreeModel *model; GtkTreeIter iter; - GtkWidget *window; - gboolean result = TRUE; - GError *error = NULL; + GVolume *volume; - _thunar_return_val_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view), FALSE); + _thunar_return_if_fail (THUNAR_IS_SHORTCUTS_VIEW (view)); /* determine the selected item */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); + + /* avoid dealing with invalid selections */ + if (!GTK_IS_TREE_SELECTION (selection)) + return; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - /* determine the volume for the shortcut at the given tree iterator */ - gtk_tree_model_get (model, &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_VOLUME, &volume, -1); - if (G_UNLIKELY (volume != NULL)) - { - /* determine the toplevel window */ - window = gtk_widget_get_toplevel (GTK_WIDGET (view)); - - /* try to unmount the volume */ - result = thunar_vfs_volume_unmount (volume, window, &error); - if (G_UNLIKELY (!result)) - { - /* display an error dialog to inform the user */ - thunar_dialogs_show_error (window, error, _("Failed to unmount \"%s\""), thunar_vfs_volume_get_name (volume)); - g_error_free (error); - } + /* determine the file for the shortcut at the given tree iterator */ + gtk_tree_model_get (model, &iter, + THUNAR_SHORTCUTS_MODEL_COLUMN_VOLUME, &volume, + -1); - /* cleanup */ - g_object_unref (G_OBJECT (volume)); + if (G_LIKELY (volume != NULL)) + { + thunar_browser_poke_volume (THUNAR_BROWSER (view), volume, view, + thunar_shortcuts_view_poke_volume_mount_finish, + NULL); + g_object_unref (volume); } } - - return result; } diff --git a/thunar/thunar-simple-job.c b/thunar/thunar-simple-job.c new file mode 100644 index 000000000..1df1a83b8 --- /dev/null +++ b/thunar/thunar-simple-job.c @@ -0,0 +1,232 @@ +/* $Id$ */ +/*- + * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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_MEMORY_H +#include <memory.h> +#endif +#ifdef HAVE_STDARG_H +#include <stdarg.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#include <gobject/gvaluecollector.h> + +#include <thunar/thunar-job.h> +#include <thunar/thunar-private.h> +#include <thunar/thunar-simple-job.h> + + + +static void thunar_simple_job_class_init (ThunarSimpleJobClass *klass); +static void thunar_simple_job_finalize (GObject *object); +static gboolean thunar_simple_job_execute (ExoJob *job, + GError **error); + + + +struct _ThunarSimpleJobClass +{ + ThunarJobClass __parent__; +}; + +struct _ThunarSimpleJob +{ + ThunarJob __parent__; + ThunarSimpleJobFunc func; + GValueArray *param_values; +}; + + + +static GObjectClass *thunar_simple_job_parent_class; + + + +GType +thunar_simple_job_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + type = g_type_register_static_simple (THUNAR_TYPE_JOB, + "ThunarSimpleJob", + sizeof (ThunarSimpleJobClass), + (GClassInitFunc) thunar_simple_job_class_init, + sizeof (ThunarSimpleJob), + NULL, + 0); + } + + return type; +} + + + +static void +thunar_simple_job_class_init (ThunarSimpleJobClass *klass) +{ + GObjectClass *gobject_class; + ExoJobClass *exojob_class; + + /* determine the parent type class */ + thunar_simple_job_parent_class = g_type_class_peek_parent (klass); + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = thunar_simple_job_finalize; + + exojob_class = EXO_JOB_CLASS (klass); + exojob_class->execute = thunar_simple_job_execute; +} + + + +static void +thunar_simple_job_finalize (GObject *object) +{ + ThunarSimpleJob *simple_job = THUNAR_SIMPLE_JOB (object); + + /* release the param values */ + g_value_array_free (simple_job->param_values); + + (*G_OBJECT_CLASS (thunar_simple_job_parent_class)->finalize) (object); +} + + + +static gboolean +thunar_simple_job_execute (ExoJob *job, + GError **error) +{ + ThunarSimpleJob *simple_job = THUNAR_SIMPLE_JOB (job); + gboolean success = TRUE; + GError *err = NULL; + + _thunar_return_val_if_fail (THUNAR_IS_SIMPLE_JOB (job), FALSE); + _thunar_return_val_if_fail (simple_job->func != NULL, FALSE); + + /* try to execute the job using the supplied function */ + success = (*simple_job->func) (THUNAR_JOB (job), simple_job->param_values, &err); + + if (!success) + { + g_assert (err != NULL || exo_job_is_cancelled (job)); + + /* set error if the job was cancelled. otherwise just propagate + * the results of the processing function */ + if (exo_job_set_error_if_cancelled (job, error)) + { + g_clear_error (&err); + } + else + { + if (err != NULL) + g_propagate_error (error, err); + } + + return FALSE; + } + else + return TRUE; +} + + + +/** + * thunar_simple_job_launch: + * @func : the #ThunarSimpleJobFunc to execute the job. + * @n_param_values : the number of parameters to pass to the @func. + * @... : a list of #GType and parameter pairs (exactly + * @n_param_values pairs) that are passed to @func. + * + * Allocates a new #ThunarSimpleJob, which executes the specified + * @func with the specified parameters. + * + * For example the listdir @func expects a #ThunarPath for the + * folder to list, so the call to thunar_simple_job_launch() + * would look like this: + * + * <informalexample><programlisting> + * thunar_simple_job_launch (_thunar_io_jobs_listdir, 1, + * THUNAR_TYPE_PATH, path); + * </programlisting></informalexample> + * + * The caller is responsible to release the returned object using + * thunar_job_unref() when no longer needed. + * + * Return value: the launched #ThunarJob. + **/ +ThunarJob * +thunar_simple_job_launch (ThunarSimpleJobFunc func, + guint n_param_values, + ...) +{ + ThunarSimpleJob *simple_job; + va_list var_args; + GValue value = { 0, }; + gchar *error_message; + gint n; + + /* allocate and initialize the simple job */ + simple_job = g_object_new (THUNAR_TYPE_SIMPLE_JOB, NULL); + simple_job->func = func; + simple_job->param_values = g_value_array_new (n_param_values); + + /* collect the parameters */ + va_start (var_args, n_param_values); + for (n = 0; n < n_param_values; ++n) + { + /* initialize the value to hold the next parameter */ + g_value_init (&value, va_arg (var_args, GType)); + + /* collect the value from the stack */ + G_VALUE_COLLECT (&value, var_args, 0, &error_message); + + /* check if an error occurred */ + if (G_UNLIKELY (error_message != NULL)) + { + g_error ("%s: %s", G_STRLOC, error_message); + g_free (error_message); + } + + g_value_array_insert (simple_job->param_values, n, &value); + g_value_unset (&value); + } + va_end (var_args); + + /* launch the job */ + return THUNAR_JOB (exo_job_launch (EXO_JOB (simple_job))); +} + + + +GValueArray * +thunar_simple_job_get_param_values (ThunarSimpleJob *job) +{ + _thunar_return_val_if_fail (THUNAR_IS_SIMPLE_JOB (job), NULL); + return job->param_values; +} diff --git a/thunar/thunar-simple-job.h b/thunar/thunar-simple-job.h new file mode 100644 index 000000000..bb325d8fa --- /dev/null +++ b/thunar/thunar-simple-job.h @@ -0,0 +1,64 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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 __THUNAR_SIMPLE_JOB_H__ +#define __THUNAR_SIMPLE_JOB_H__ + +#include <thunar/thunar-job.h> + +G_BEGIN_DECLS + +/** + * ThunarSimpleJobFunc: + * @job : a #ThunarJob. + * @param_values : a #GValueArray of the #GValue<!---->s passed to + * thunar_simple_job_launch(). + * @error : return location for errors. + * + * Used by the #ThunarSimpleJob to process the @job. See thunar_simple_job_launch() + * for further details. + * + * Return value: %TRUE on success, %FALSE in case of an error. + **/ +typedef gboolean (*ThunarSimpleJobFunc) (ThunarJob *job, + GValueArray *param_values, + GError **error); + + +typedef struct _ThunarSimpleJobClass ThunarSimpleJobClass; +typedef struct _ThunarSimpleJob ThunarSimpleJob; + +#define THUNAR_TYPE_SIMPLE_JOB (thunar_simple_job_get_type ()) +#define THUNAR_SIMPLE_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_SIMPLE_JOB, ThunarSimpleJob)) +#define THUNAR_SIMPLE_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_SIMPLE_JOB, ThunarSimpleJobClass)) +#define THUNAR_IS_SIMPLE_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_SIMPLE_JOB)) +#define THUNAR_IS_SIMPLE_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_SIMPLE_JOB)) +#define THUNAR_SIMPLE_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_SIMPLE_JOB, ThunarSimpleJobClass)) + +GType thunar_simple_job_get_type (void) G_GNUC_CONST; + +ThunarJob *thunar_simple_job_launch (ThunarSimpleJobFunc func, + guint n_param_values, + ...) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +GValueArray *thunar_simple_job_get_param_values (ThunarSimpleJob *job); + +G_END_DECLS + +#endif /* !__THUNAR_SIMPLE_JOB_H__ */ diff --git a/thunar/thunar-size-label.c b/thunar/thunar-size-label.c index 8f6aab99a..25102b55a 100644 --- a/thunar/thunar-size-label.c +++ b/thunar/thunar-size-label.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -32,6 +33,7 @@ #include <thunar/thunar-private.h> #include <thunar/thunar-size-label.h> #include <thunar/thunar-throbber.h> +#include <thunar/thunar-deep-count-job.h> @@ -60,12 +62,12 @@ static gboolean thunar_size_label_button_press_event (GtkWidget *e ThunarSizeLabel *size_label); static void thunar_size_label_file_changed (ThunarFile *file, ThunarSizeLabel *size_label); -static void thunar_size_label_error (ThunarVfsJob *job, +static void thunar_size_label_error (ExoJob *job, const GError *error, ThunarSizeLabel *size_label); -static void thunar_size_label_finished (ThunarVfsJob *job, +static void thunar_size_label_finished (ExoJob *job, ThunarSizeLabel *size_label); -static void thunar_size_label_status_ready (ThunarVfsJob *job, +static void thunar_size_label_status_update (ThunarDeepCountJob *job, guint64 total_size, guint file_count, guint directory_count, @@ -83,16 +85,17 @@ struct _ThunarSizeLabelClass struct _ThunarSizeLabel { - GtkHBox __parent__; - ThunarVfsJob *job; + GtkHBox __parent__; - ThunarFile *file; + ThunarDeepCountJob *job; - GtkWidget *label; - GtkWidget *throbber; + ThunarFile *file; + + GtkWidget *label; + GtkWidget *throbber; /* the throbber animation is started after a timeout */ - gint animate_timer_id; + gint animate_timer_id; }; @@ -206,8 +209,8 @@ thunar_size_label_finalize (GObject *object) if (G_UNLIKELY (size_label->job != NULL)) { g_signal_handlers_disconnect_matched (G_OBJECT (size_label->job), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, size_label); - thunar_vfs_job_cancel (THUNAR_VFS_JOB (size_label->job)); - g_object_unref (G_OBJECT (size_label->job)); + exo_job_cancel (EXO_JOB (size_label->job)); + g_object_unref (size_label->job); } /* reset the file property */ @@ -284,9 +287,9 @@ thunar_size_label_button_press_event (GtkWidget *ebox, /* cancel the pending job (if any) */ if (G_UNLIKELY (size_label->job != NULL)) { - g_signal_handlers_disconnect_matched (G_OBJECT (size_label->job), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, size_label); - thunar_vfs_job_cancel (THUNAR_VFS_JOB (size_label->job)); - g_object_unref (G_OBJECT (size_label->job)); + g_signal_handlers_disconnect_matched (size_label->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, size_label); + exo_job_cancel (EXO_JOB (size_label->job)); + g_object_unref (size_label->job); size_label->job = NULL; } @@ -307,7 +310,7 @@ thunar_size_label_button_press_event (GtkWidget *ebox, static gchar* -tsl_format_size_string (ThunarVfsFileSize size) +tsl_format_size_string (guint64 size) { GString *result; gchar *grouping; @@ -356,11 +359,10 @@ static void thunar_size_label_file_changed (ThunarFile *file, ThunarSizeLabel *size_label) { - ThunarVfsFileSize size; - GError *error = NULL; - gchar *size_humanized; - gchar *size_string; - gchar *text; + guint64 size; + gchar *size_humanized; + gchar *size_string; + gchar *text; _thunar_return_if_fail (THUNAR_IS_SIZE_LABEL (size_label)); _thunar_return_if_fail (size_label->file == file); @@ -373,9 +375,9 @@ thunar_size_label_file_changed (ThunarFile *file, /* cancel the pending job (if any) */ if (G_UNLIKELY (size_label->job != NULL)) { - g_signal_handlers_disconnect_matched (G_OBJECT (size_label->job), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, size_label); - thunar_vfs_job_cancel (THUNAR_VFS_JOB (size_label->job)); - g_object_unref (G_OBJECT (size_label->job)); + g_signal_handlers_disconnect_matched (size_label->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, size_label); + exo_job_cancel (EXO_JOB (size_label->job)); + g_object_unref (size_label->job); size_label->job = NULL; } @@ -387,23 +389,16 @@ thunar_size_label_file_changed (ThunarFile *file, if (thunar_file_is_directory (file)) { /* schedule a new job to determine the total size of the directory (not following symlinks) */ - size_label->job = thunar_vfs_deep_count (thunar_file_get_path (file), THUNAR_VFS_DEEP_COUNT_FLAGS_NONE, &error); - if (G_UNLIKELY (size_label->job == NULL)) - { - /* display the error to the user */ - gtk_label_set_text (GTK_LABEL (size_label->label), error->message); - g_error_free (error); - } - else - { - /* connect to the job */ - g_signal_connect (G_OBJECT (size_label->job), "error", G_CALLBACK (thunar_size_label_error), size_label); - g_signal_connect (G_OBJECT (size_label->job), "finished", G_CALLBACK (thunar_size_label_finished), size_label); - g_signal_connect (G_OBJECT (size_label->job), "status-ready", G_CALLBACK (thunar_size_label_status_ready), size_label); + size_label->job = thunar_deep_count_job_new (thunar_file_get_file (file), G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS); + g_signal_connect (size_label->job, "error", G_CALLBACK (thunar_size_label_error), size_label); + g_signal_connect (size_label->job, "finished", G_CALLBACK (thunar_size_label_finished), size_label); + g_signal_connect (size_label->job, "status-update", G_CALLBACK (thunar_size_label_status_update), size_label); - /* tell the user that we started calculation */ - gtk_label_set_text (GTK_LABEL (size_label->label), _("Calculating...")); - } + /* tell the user that we started calculation */ + gtk_label_set_text (GTK_LABEL (size_label->label), _("Calculating...")); + + /* launch the job */ + exo_job_launch (EXO_JOB (size_label->job)); } else { @@ -419,7 +414,7 @@ thunar_size_label_file_changed (ThunarFile *file, if (G_LIKELY (size > 1024ul)) { /* prepend the humanized size */ - size_humanized = thunar_vfs_humanize_size (size, NULL, 0); + size_humanized = g_format_size_for_display (size); text = g_strdup_printf ("%s (%s)", size_humanized, size_string); g_free (size_humanized); g_free (size_string); @@ -437,13 +432,13 @@ thunar_size_label_file_changed (ThunarFile *file, static void -thunar_size_label_error (ThunarVfsJob *job, +thunar_size_label_error (ExoJob *job, const GError *error, ThunarSizeLabel *size_label) { + _thunar_return_if_fail (THUNAR_IS_JOB (job)); _thunar_return_if_fail (THUNAR_IS_SIZE_LABEL (size_label)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_return_if_fail (size_label->job == job); + _thunar_return_if_fail (size_label->job == THUNAR_DEEP_COUNT_JOB (job)); /* setup the error text as label */ gtk_label_set_text (GTK_LABEL (size_label->label), error->message); @@ -452,12 +447,12 @@ thunar_size_label_error (ThunarVfsJob *job, static void -thunar_size_label_finished (ThunarVfsJob *job, +thunar_size_label_finished (ExoJob *job, ThunarSizeLabel *size_label) { + _thunar_return_if_fail (THUNAR_IS_JOB (job)); _thunar_return_if_fail (THUNAR_IS_SIZE_LABEL (size_label)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); - _thunar_return_if_fail (size_label->job == job); + _thunar_return_if_fail (size_label->job == THUNAR_DEEP_COUNT_JOB (job)); /* be sure to cancel the animate timer */ if (G_UNLIKELY (size_label->animate_timer_id >= 0)) @@ -468,27 +463,27 @@ thunar_size_label_finished (ThunarVfsJob *job, gtk_widget_hide (size_label->throbber); /* disconnect from the job */ - g_signal_handlers_disconnect_matched (G_OBJECT (size_label->job), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, size_label); - g_object_unref (G_OBJECT (size_label->job)); + g_signal_handlers_disconnect_matched (size_label->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, size_label); + g_object_unref (size_label->job); size_label->job = NULL; } static void -thunar_size_label_status_ready (ThunarVfsJob *job, - guint64 total_size, - guint file_count, - guint directory_count, - guint unreadable_directory_count, - ThunarSizeLabel *size_label) +thunar_size_label_status_update (ThunarDeepCountJob *job, + guint64 total_size, + guint file_count, + guint directory_count, + guint unreadable_directory_count, + ThunarSizeLabel *size_label) { gchar *size_string; gchar *text; guint n; + _thunar_return_if_fail (THUNAR_IS_DEEP_COUNT_JOB (job)); _thunar_return_if_fail (THUNAR_IS_SIZE_LABEL (size_label)); - _thunar_return_if_fail (THUNAR_VFS_IS_JOB (job)); _thunar_return_if_fail (size_label->job == job); /* check if the animate timer is already running */ @@ -503,7 +498,7 @@ thunar_size_label_status_ready (ThunarVfsJob *job, n = file_count + directory_count + unreadable_directory_count; /* update the label */ - size_string = thunar_vfs_humanize_size (total_size, NULL, 0); + size_string = g_format_size_for_display (total_size); text = g_strdup_printf (ngettext ("%u item, totalling %s", "%u items, totalling %s", n), n, size_string); gtk_label_set_text (GTK_LABEL (size_label->label), text); g_free (size_string); diff --git a/thunar/thunar-standard-view.c b/thunar/thunar-standard-view.c index 085927246..f30d66c55 100644 --- a/thunar/thunar-standard-view.c +++ b/thunar/thunar-standard-view.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -35,6 +36,7 @@ #include <thunar/thunar-dialogs.h> #include <thunar/thunar-dnd.h> #include <thunar/thunar-enum-types.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-gtk-extensions.h> #include <thunar/thunar-icon-renderer.h> @@ -42,6 +44,7 @@ #include <thunar/thunar-private.h> #include <thunar/thunar-properties-dialog.h> #include <thunar/thunar-renamer-dialog.h> +#include <thunar/thunar-simple-job.h> #include <thunar/thunar-standard-view.h> #include <thunar/thunar-standard-view-ui.h> #include <thunar/thunar-templates-action.h> @@ -160,7 +163,7 @@ static void thunar_standard_view_action_create_empty_file (Gtk static void thunar_standard_view_action_create_folder (GtkAction *action, ThunarStandardView *standard_view); static void thunar_standard_view_action_create_template (GtkAction *action, - const ThunarVfsInfo *info, + const ThunarFile *file, ThunarStandardView *standard_view); static void thunar_standard_view_action_properties (GtkAction *action, ThunarStandardView *standard_view); @@ -290,7 +293,7 @@ struct _ThunarStandardViewPrivate gint custom_merge_id; /* right-click drag/popup support */ - GList *drag_path_list; + GList *drathunar_g_file_list; gint drag_scroll_timer_id; gint drag_timer_id; gint drag_x; @@ -300,10 +303,10 @@ struct _ThunarStandardViewPrivate guint drop_data_ready : 1; /* whether the drop data was received already */ guint drop_highlight : 1; guint drop_occurred : 1; /* whether the data was dropped */ - GList *drop_path_list; /* the list of URIs that are contained in the drop data */ + GList *drop_file_list; /* the list of URIs that are contained in the drop data */ /* the "new-files" closure, which is used to select files whenever - * new files are created by a ThunarVfsJob associated with this view + * new files are created by a ThunarJob associated with this view */ GClosure *new_files_closure; @@ -762,10 +765,10 @@ thunar_standard_view_finalize (GObject *object) g_object_unref (G_OBJECT (standard_view->priv->provider_factory)); /* release the drag path list (just in case the drag-end wasn't fired before) */ - thunar_vfs_path_list_free (standard_view->priv->drag_path_list); + thunar_g_file_list_free (standard_view->priv->drathunar_g_file_list); /* release the drop path list (just in case the drag-leave wasn't fired before) */ - thunar_vfs_path_list_free (standard_view->priv->drop_path_list); + thunar_g_file_list_free (standard_view->priv->drop_file_list); /* release the reference on the name renderer */ g_object_unref (G_OBJECT (standard_view->name_renderer)); @@ -785,7 +788,7 @@ thunar_standard_view_finalize (GObject *object) } /* drop any remaining "new-files" paths */ - thunar_vfs_path_list_free (standard_view->priv->new_files_path_list); + thunar_g_file_list_free (standard_view->priv->new_files_path_list); /* release our reference on the preferences */ g_object_unref (G_OBJECT (standard_view->preferences)); @@ -958,9 +961,7 @@ thunar_standard_view_expose_event (GtkWidget *widget, GdkEventExpose *event) { gboolean result = FALSE; -#if GTK_CHECK_VERSION(2,7,2) cairo_t *cr; -#endif gint x, y, width, height; /* let the scrolled window do it's work */ @@ -979,7 +980,6 @@ thunar_standard_view_expose_event (GtkWidget *widget, NULL, widget, "dnd", x, y, width, height); -#if GTK_CHECK_VERSION(2,7,2) /* the cairo version looks better here, so we use it if possible */ cr = gdk_cairo_create (widget->window); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); @@ -987,10 +987,6 @@ thunar_standard_view_expose_event (GtkWidget *widget, cairo_rectangle (cr, x + 0.5, y + 0.5, width - 1, height - 1); cairo_stroke (cr); cairo_destroy (cr); -#else - gdk_draw_rectangle (widget->window, widget->style->black_gc, - FALSE, x, y, width - 1, height - 1); -#endif } return result; @@ -1281,7 +1277,7 @@ thunar_standard_view_set_loading (ThunarStandardView *standard_view, thunar_standard_view_new_files (standard_view, new_files_path_list); /* cleanup */ - thunar_vfs_path_list_free (new_files_path_list); + thunar_g_file_list_free (new_files_path_list); } /* notify listeners */ @@ -1547,7 +1543,7 @@ thunar_standard_view_get_dest_actions (ThunarStandardView *standard_view, if (G_LIKELY (file != NULL)) { /* determine the possible drop actions for the file (and the suggested action if any) */ - actions = thunar_file_accepts_drop (file, standard_view->priv->drop_path_list, context, &action); + actions = thunar_file_accepts_drop (file, standard_view->priv->drop_file_list, context, &action); if (G_LIKELY (actions != 0)) { /* tell the caller about the file (if it's interested) */ @@ -1784,22 +1780,19 @@ static void thunar_standard_view_action_create_empty_file (GtkAction *action, ThunarStandardView *standard_view) { - ThunarVfsMimeDatabase *mime_database; - ThunarVfsMimeInfo *mime_info; - ThunarApplication *application; - ThunarFile *current_directory; - GList path_list; - gchar *name; + ThunarApplication *application; + ThunarFile *current_directory; + GList path_list; + gchar *name; _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); - /* lookup "text/plain" mime info */ - mime_database = thunar_vfs_mime_database_get_default (); - mime_info = thunar_vfs_mime_database_get_info (mime_database, "text/plain"); - /* ask the user to enter a name for the new empty file */ - name = thunar_show_create_dialog (GTK_WIDGET (standard_view), mime_info, _("New Empty File"), _("New Empty File...")); + name = thunar_show_create_dialog (GTK_WIDGET (standard_view), + "text/plain", + _("New Empty File"), + _("New Empty File...")); if (G_LIKELY (name != NULL)) { /* determine the ThunarFile for the current directory */ @@ -1807,26 +1800,22 @@ thunar_standard_view_action_create_empty_file (GtkAction *action, if (G_LIKELY (current_directory != NULL)) { /* fake the path list */ - path_list.data = thunar_vfs_path_relative (thunar_file_get_path (current_directory), name); + path_list.data = g_file_resolve_relative_path (thunar_file_get_file (current_directory), name); path_list.next = path_list.prev = NULL; /* launch the operation */ application = thunar_application_get (); thunar_application_creat (application, GTK_WIDGET (standard_view), &path_list, thunar_standard_view_new_files_closure (standard_view)); - g_object_unref (G_OBJECT (application)); + g_object_unref (application); /* release the path */ - thunar_vfs_path_unref (path_list.data); + g_object_unref (path_list.data); } /* release the file name in the local encoding */ g_free (name); } - - /* cleanup */ - g_object_unref (G_OBJECT (mime_database)); - thunar_vfs_mime_info_unref (mime_info); } @@ -1835,22 +1824,19 @@ static void thunar_standard_view_action_create_folder (GtkAction *action, ThunarStandardView *standard_view) { - ThunarVfsMimeDatabase *mime_database; - ThunarVfsMimeInfo *mime_info; - ThunarApplication *application; - ThunarFile *current_directory; - GList path_list; - gchar *name; + ThunarApplication *application; + ThunarFile *current_directory; + GList path_list; + gchar *name; _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); - /* lookup "inode/directory" mime info */ - mime_database = thunar_vfs_mime_database_get_default (); - mime_info = thunar_vfs_mime_database_get_info (mime_database, "inode/directory"); - /* ask the user to enter a name for the new folder */ - name = thunar_show_create_dialog (GTK_WIDGET (standard_view), mime_info, _("New Folder"), _("Create New Folder")); + name = thunar_show_create_dialog (GTK_WIDGET (standard_view), + "inode/directory", + _("New Folder"), + _("Create New Folder")); if (G_LIKELY (name != NULL)) { /* determine the ThunarFile for the current directory */ @@ -1858,7 +1844,7 @@ thunar_standard_view_action_create_folder (GtkAction *action, if (G_LIKELY (current_directory != NULL)) { /* fake the path list */ - path_list.data = thunar_vfs_path_relative (thunar_file_get_path (current_directory), name); + path_list.data = g_file_resolve_relative_path (thunar_file_get_file (current_directory), name); path_list.next = path_list.prev = NULL; /* launch the operation */ @@ -1868,41 +1854,41 @@ thunar_standard_view_action_create_folder (GtkAction *action, g_object_unref (G_OBJECT (application)); /* release the path */ - thunar_vfs_path_unref (path_list.data); + g_object_unref (path_list.data); } /* release the file name */ g_free (name); } - - /* cleanup */ - g_object_unref (G_OBJECT (mime_database)); - thunar_vfs_mime_info_unref (mime_info); } static void thunar_standard_view_action_create_template (GtkAction *action, - const ThunarVfsInfo *info, + const ThunarFile *file, ThunarStandardView *standard_view) { ThunarApplication *application; ThunarFile *current_directory; GList source_path_list; GList target_path_list; - gchar *title; gchar *name; + gchar *title; - _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); _thunar_return_if_fail (GTK_IS_ACTION (action)); - _thunar_return_if_fail (info != NULL); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); /* generate a title for the create dialog */ - title = g_strdup_printf (_("Create Document from template \"%s\""), info->display_name); + title = g_strdup_printf (_("Create Document from template \"%s\""), + thunar_file_get_display_name (file)); /* ask the user to enter a name for the new document */ - name = thunar_show_create_dialog (GTK_WIDGET (standard_view), info->mime_info, info->display_name, title); + name = thunar_show_create_dialog (GTK_WIDGET (standard_view), + thunar_file_get_content_type (file), + thunar_file_get_display_name (file), + title); if (G_LIKELY (name != NULL)) { /* determine the ThunarFile for the current directory */ @@ -1910,12 +1896,12 @@ thunar_standard_view_action_create_template (GtkAction *action, if (G_LIKELY (current_directory != NULL)) { /* fake the source path list */ - source_path_list.data = info->path; + source_path_list.data = thunar_file_get_file (file); source_path_list.next = NULL; source_path_list.prev = NULL; /* fake the target path list */ - target_path_list.data = thunar_vfs_path_relative (thunar_file_get_path (current_directory), name); + target_path_list.data = g_file_get_child (thunar_file_get_file (current_directory), name); target_path_list.next = NULL; target_path_list.prev = NULL; @@ -1926,7 +1912,7 @@ thunar_standard_view_action_create_template (GtkAction *action, g_object_unref (G_OBJECT (application)); /* release the target path */ - thunar_vfs_path_unref (target_path_list.data); + g_object_unref (target_path_list.data); } /* release the file name */ @@ -2020,7 +2006,7 @@ thunar_standard_view_action_paste (GtkAction *action, current_directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view)); if (G_LIKELY (current_directory != NULL)) { - thunar_clipboard_manager_paste_files (standard_view->clipboard, thunar_file_get_path (current_directory), + thunar_clipboard_manager_paste_files (standard_view->clipboard, thunar_file_get_file (current_directory), GTK_WIDGET (standard_view), thunar_standard_view_new_files_closure (standard_view)); } } @@ -2056,7 +2042,7 @@ thunar_standard_view_action_paste_into_folder (GtkAction *action, /* determine the first selected file and verify that it's a folder */ file = g_list_nth_data (standard_view->selected_files, 0); if (G_LIKELY (file != NULL && thunar_file_is_directory (file))) - thunar_clipboard_manager_paste_files (standard_view->clipboard, thunar_file_get_path (file), GTK_WIDGET (standard_view), NULL); + thunar_clipboard_manager_paste_files (standard_view->clipboard, thunar_file_get_file (file), GTK_WIDGET (standard_view), NULL); } @@ -2144,7 +2130,7 @@ thunar_standard_view_action_duplicate (GtkAction *action, ThunarApplication *application; ThunarFile *current_directory; GClosure *new_files_closure; - GList *selected_paths; + GList *selected_files; _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); @@ -2153,21 +2139,21 @@ thunar_standard_view_action_duplicate (GtkAction *action, current_directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view)); if (G_LIKELY (current_directory != NULL)) { - /* determine the selected paths for the view */ - selected_paths = thunar_file_list_to_path_list (standard_view->selected_files); - if (G_LIKELY (selected_paths != NULL)) + /* determine the selected files for the view */ + selected_files = thunar_file_list_to_thunar_g_file_list (standard_view->selected_files); + if (G_LIKELY (selected_files != NULL)) { /* copy the selected files into the current directory, which effectively * creates duplicates of the files. */ application = thunar_application_get (); new_files_closure = thunar_standard_view_new_files_closure (standard_view); - thunar_application_copy_into (application, GTK_WIDGET (standard_view), selected_paths, - thunar_file_get_path (current_directory), new_files_closure); + thunar_application_copy_into (application, GTK_WIDGET (standard_view), selected_files, + thunar_file_get_file (current_directory), new_files_closure); g_object_unref (G_OBJECT (application)); /* clean up */ - thunar_vfs_path_list_free (selected_paths); + thunar_g_file_list_free (selected_files); } } } @@ -2181,7 +2167,7 @@ thunar_standard_view_action_make_link (GtkAction *action, ThunarApplication *application; ThunarFile *current_directory; GClosure *new_files_closure; - GList *selected_paths; + GList *selected_files; _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); @@ -2191,32 +2177,84 @@ thunar_standard_view_action_make_link (GtkAction *action, if (G_LIKELY (current_directory != NULL)) { /* determine the selected paths for the view */ - selected_paths = thunar_file_list_to_path_list (standard_view->selected_files); - if (G_LIKELY (selected_paths != NULL)) + selected_files = thunar_file_list_to_thunar_g_file_list (standard_view->selected_files); + if (G_LIKELY (selected_files != NULL)) { /* link the selected files into the current directory, which effectively * creates new unique links for the files. */ application = thunar_application_get (); new_files_closure = thunar_standard_view_new_files_closure (standard_view); - thunar_application_link_into (application, GTK_WIDGET (standard_view), selected_paths, - thunar_file_get_path (current_directory), new_files_closure); + thunar_application_link_into (application, GTK_WIDGET (standard_view), selected_files, + thunar_file_get_file (current_directory), new_files_closure); g_object_unref (G_OBJECT (application)); /* clean up */ - thunar_vfs_path_list_free (selected_paths); + thunar_g_file_list_free (selected_files); } } } +static void +thunar_standard_view_rename_error (ExoJob *job, + GError *error, + ThunarStandardView *standard_view) +{ + GValueArray *param_values; + ThunarFile *file; + + _thunar_return_if_fail (EXO_IS_JOB (job)); + _thunar_return_if_fail (error != NULL); + _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); + + param_values = thunar_simple_job_get_param_values (THUNAR_SIMPLE_JOB (job)); + file = g_value_get_object (g_value_array_get_nth (param_values, 0)); + + /* display an error message */ + thunar_dialogs_show_error (GTK_WIDGET (standard_view), error, + _("Failed to rename \"%s\""), + thunar_file_get_display_name (file)); +} + + + +static void +thunar_standard_view_rename_finished (ExoJob *job, + ThunarStandardView *standard_view) +{ + GValueArray *param_values; + ThunarFile *file; + + _thunar_return_if_fail (EXO_IS_JOB (job)); + _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); + + param_values = thunar_simple_job_get_param_values (THUNAR_SIMPLE_JOB (job)); + file = g_value_get_object (g_value_array_get_nth (param_values, 0)); + + /* make sure the file is still visible */ + thunar_view_scroll_to_file (THUNAR_VIEW (standard_view), file, TRUE, FALSE, 0.0f, 0.0f); + + /* update the selection, so we get updated actions, statusbar, + * etc. with the new file name and probably new mime type. + */ + thunar_standard_view_selection_changed (standard_view); + + /* destroy the job */ + g_signal_handlers_disconnect_matched (job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, standard_view); + g_object_unref (job); +} + + + static void thunar_standard_view_action_rename (GtkAction *action, ThunarStandardView *standard_view) { ThunarFile *file; GtkWidget *window; + ThunarJob *job; _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); @@ -2231,15 +2269,11 @@ thunar_standard_view_action_rename (GtkAction *action, file = THUNAR_FILE (standard_view->selected_files->data); /* run the rename dialog */ - if (thunar_dialogs_show_rename_file (GTK_WINDOW (window), file)) + job = thunar_dialogs_show_rename_file (GTK_WINDOW (window), file); + if (G_LIKELY (job != NULL)) { - /* make sure the file is still visible */ - thunar_view_scroll_to_file (THUNAR_VIEW (standard_view), file, TRUE, FALSE, 0.0f, 0.0f); - - /* update the selection, so we get updated actions, statusbar, - * etc. with the new file name and probably new mime type. - */ - thunar_standard_view_selection_changed (standard_view); + g_signal_connect (job, "error", G_CALLBACK (thunar_standard_view_rename_error), standard_view); + g_signal_connect (job, "finished", G_CALLBACK (thunar_standard_view_rename_finished), standard_view); } } else if (g_list_length (standard_view->selected_files) > 1) @@ -2248,7 +2282,7 @@ thunar_standard_view_action_rename (GtkAction *action, file = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (standard_view)); /* display the bulk rename dialog */ - thunar_show_renamer_dialog (GTK_WIDGET (standard_view), file, standard_view->selected_files, FALSE); + thunar_show_renamer_dialog (GTK_WIDGET (standard_view), file, standard_view->selected_files, FALSE, NULL); } } @@ -2306,7 +2340,7 @@ thunar_standard_view_new_files (ThunarStandardView *standard_view, /* release the previous "new-files" paths (if any) */ if (G_UNLIKELY (standard_view->priv->new_files_path_list != NULL)) { - thunar_vfs_path_list_free (standard_view->priv->new_files_path_list); + thunar_g_file_list_free (standard_view->priv->new_files_path_list); standard_view->priv->new_files_path_list = NULL; } @@ -2314,7 +2348,7 @@ thunar_standard_view_new_files (ThunarStandardView *standard_view, if (G_UNLIKELY (standard_view->loading)) { /* schedule the "new-files" paths for later processing */ - standard_view->priv->new_files_path_list = thunar_vfs_path_list_copy (path_list); + standard_view->priv->new_files_path_list = thunar_g_file_list_copy (path_list); } else if (G_LIKELY (path_list != NULL)) { @@ -2495,12 +2529,12 @@ thunar_standard_view_drag_drop (GtkWidget *view, guint time, ThunarStandardView *standard_view) { - ThunarVfsPath *path; - ThunarFile *file = NULL; - GdkAtom target; - guchar *prop_text; - gint prop_len; - gchar *uri = NULL; + ThunarFile *file = NULL; + GdkAtom target; + guchar *prop_text; + GFile *path; + gchar *uri = NULL; + gint prop_len; target = gtk_drag_dest_find_target (view, context, NULL); if (G_UNLIKELY (target == GDK_NONE)) @@ -2527,10 +2561,11 @@ thunar_standard_view_drag_drop (GtkWidget *view, if (G_LIKELY (*prop_text != '\0' && strchr ((const gchar *) prop_text, G_DIR_SEPARATOR) == NULL)) { /* allocate the relative path for the target */ - path = thunar_vfs_path_relative (thunar_file_get_path (file), (const gchar *) prop_text); + path = g_file_resolve_relative_path (thunar_file_get_file (file), + (const gchar *)prop_text); /* determine the new URI */ - uri = thunar_vfs_path_dup_uri (path); + uri = g_file_get_uri (path); /* setup the property */ gdk_property_change (GDK_DRAWABLE (context->source_window), @@ -2540,7 +2575,7 @@ thunar_standard_view_drag_drop (GtkWidget *view, strlen (uri)); /* cleanup */ - thunar_vfs_path_unref (path); + g_object_unref (path); g_free (uri); } else @@ -2583,19 +2618,21 @@ tsv_reload_directory (GPid pid, gint status, gpointer user_data) { - ThunarVfsMonitor *monitor; - ThunarVfsPath *path; + GFileMonitor *monitor; + GFile *file; /* determine the path for the directory */ - path = thunar_vfs_path_new (user_data, NULL); - if (G_LIKELY (path != NULL)) + file = g_file_new_for_uri (user_data); + + /* schedule a changed event for the directory */ + monitor = g_file_monitor (file, G_FILE_MONITOR_NONE, NULL, NULL); + if (monitor != NULL) { - /* schedule a changed event for the directory */ - monitor = thunar_vfs_monitor_get_default (); - thunar_vfs_monitor_feed (monitor, THUNAR_VFS_MONITOR_EVENT_CHANGED, path); - g_object_unref (G_OBJECT (monitor)); - thunar_vfs_path_unref (path); + g_file_monitor_emit_event (monitor, file, NULL, G_FILE_MONITOR_EVENT_CHANGED); + g_object_unref (monitor); } + + g_object_unref (file); } @@ -2628,7 +2665,7 @@ thunar_standard_view_drag_data_received (GtkWidget *view, { /* extract the URI list from the selection data (if valid) */ if (info == TARGET_TEXT_URI_LIST && selection_data->format == 8 && selection_data->length > 0) - standard_view->priv->drop_path_list = thunar_vfs_path_list_from_string ((gchar *) selection_data->data, NULL); + standard_view->priv->drop_file_list = thunar_g_file_list_new_from_string ((gchar *) selection_data->data); /* reset the state */ standard_view->priv->drop_data_ready = TRUE; @@ -2689,7 +2726,7 @@ thunar_standard_view_drag_data_received (GtkWidget *view, if (G_LIKELY (file != NULL)) { /* determine the absolute path to the target directory */ - working_directory = thunar_vfs_path_dup_string (thunar_file_get_path (file)); + working_directory = g_file_get_uri (thunar_file_get_file (file)); /* prepare the basic part of the command */ argv[n++] = "exo-desktop-item-edit"; @@ -2750,13 +2787,13 @@ thunar_standard_view_drag_data_received (GtkWidget *view, { /* ask the user what to do with the drop data */ action = (context->action == GDK_ACTION_ASK) - ? thunar_dnd_ask (GTK_WIDGET (standard_view), file, standard_view->priv->drop_path_list, time, actions) + ? thunar_dnd_ask (GTK_WIDGET (standard_view), file, standard_view->priv->drop_file_list, time, actions) : context->action; /* perform the requested action */ if (G_LIKELY (action != 0)) { - succeed = thunar_dnd_perform (GTK_WIDGET (standard_view), file, standard_view->priv->drop_path_list, + succeed = thunar_dnd_perform (GTK_WIDGET (standard_view), file, standard_view->priv->drop_file_list, action, thunar_standard_view_new_files_closure (standard_view)); } } @@ -2799,8 +2836,8 @@ thunar_standard_view_drag_leave (GtkWidget *widget, /* reset the "drop data ready" status and free the URI list */ if (G_LIKELY (standard_view->priv->drop_data_ready)) { - thunar_vfs_path_list_free (standard_view->priv->drop_path_list); - standard_view->priv->drop_path_list = NULL; + thunar_g_file_list_free (standard_view->priv->drop_file_list); + standard_view->priv->drop_file_list = NULL; standard_view->priv->drop_data_ready = FALSE; } @@ -2834,8 +2871,13 @@ thunar_standard_view_drag_motion (GtkWidget *view, file = thunar_standard_view_get_drop_file (standard_view, x, y, &path); /* check if we can save here */ - if (G_LIKELY (file != NULL && thunar_file_is_local (file) && thunar_file_is_directory (file) && thunar_file_is_writable (file))) - action = context->suggested_action; + if (G_LIKELY (file != NULL + && thunar_file_is_local (file) + && thunar_file_is_directory (file) + && thunar_file_is_writable (file))) + { + action = context->suggested_action; + } /* reset path if we cannot drop */ if (G_UNLIKELY (action == 0 && path != NULL)) @@ -2901,14 +2943,14 @@ thunar_standard_view_drag_begin (GtkWidget *view, gint size; /* release the drag path list (just in case the drag-end wasn't fired before) */ - thunar_vfs_path_list_free (standard_view->priv->drag_path_list); + thunar_g_file_list_free (standard_view->priv->drathunar_g_file_list); /* query the list of selected URIs */ - standard_view->priv->drag_path_list = thunar_file_list_to_path_list (standard_view->selected_files); - if (G_LIKELY (standard_view->priv->drag_path_list != NULL)) + standard_view->priv->drathunar_g_file_list = thunar_file_list_to_thunar_g_file_list (standard_view->selected_files); + if (G_LIKELY (standard_view->priv->drathunar_g_file_list != NULL)) { /* determine the first selected file */ - file = thunar_file_get_for_path (standard_view->priv->drag_path_list->data, NULL); + file = thunar_file_get (standard_view->priv->drathunar_g_file_list->data, NULL); if (G_LIKELY (file != NULL)) { /* generate an icon based on that file */ @@ -2936,7 +2978,7 @@ thunar_standard_view_drag_data_get (GtkWidget *view, gchar *uri_string; /* set the URI list for the drag selection */ - uri_string = thunar_vfs_path_list_to_string (standard_view->priv->drag_path_list); + uri_string = thunar_g_file_list_to_string (standard_view->priv->drathunar_g_file_list); gtk_selection_data_set (selection_data, selection_data->target, 8, (guchar *) uri_string, strlen (uri_string)); g_free (uri_string); } @@ -2964,8 +3006,8 @@ thunar_standard_view_drag_end (GtkWidget *view, g_source_remove (standard_view->priv->drag_scroll_timer_id); /* release the list of dragged URIs */ - thunar_vfs_path_list_free (standard_view->priv->drag_path_list); - standard_view->priv->drag_path_list = NULL; + thunar_g_file_list_free (standard_view->priv->drathunar_g_file_list); + standard_view->priv->drathunar_g_file_list = NULL; } diff --git a/thunar/thunar-templates-action.c b/thunar/thunar-templates-action.c index 6af367de5..d78129c99 100644 --- a/thunar/thunar-templates-action.c +++ b/thunar/thunar-templates-action.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -21,8 +22,11 @@ #include <config.h> #endif -#include <thunar-vfs/thunar-vfs.h> +#include <gio/gio.h> +#include <thunar/thunar-icon-factory.h> +#include <thunar/thunar-job.h> +#include <thunar/thunar-misc-jobs.h> #include <thunar/thunar-private.h> #include <thunar/thunar-templates-action.h> @@ -39,10 +43,9 @@ enum static void thunar_templates_action_class_init (ThunarTemplatesActionClass *klass); +static void thunar_templates_action_init (ThunarTemplatesAction *templates_action); +static void thunar_templates_action_finalize (GObject *object); static GtkWidget *thunar_templates_action_create_menu_item (GtkAction *action); -static void thunar_templates_action_fill_menu (ThunarTemplatesAction *templates_action, - ThunarVfsPath *templates_path, - GtkWidget *menu); static void thunar_templates_action_menu_shown (GtkWidget *menu, ThunarTemplatesAction *templates_action); @@ -54,12 +57,14 @@ struct _ThunarTemplatesActionClass void (*create_empty_file) (ThunarTemplatesAction *templates_action); void (*create_template) (ThunarTemplatesAction *templates_action, - const ThunarVfsInfo *info); + const ThunarFile *file); }; struct _ThunarTemplatesAction { - GtkAction __parent__; + GtkAction __parent__; + + ThunarJob *job; }; @@ -76,21 +81,13 @@ thunar_templates_action_get_type (void) if (G_UNLIKELY (type == G_TYPE_INVALID)) { - static const GTypeInfo info = - { - sizeof (ThunarTemplatesActionClass), - NULL, - NULL, - (GClassInitFunc) thunar_templates_action_class_init, - NULL, - NULL, - sizeof (ThunarTemplatesAction), - 0, - NULL, - NULL, - }; - - type = g_type_register_static (GTK_TYPE_ACTION, I_("ThunarTemplatesAction"), &info, 0); + type = g_type_register_static_simple (GTK_TYPE_ACTION, + I_("ThunarTemplatesAction"), + sizeof (ThunarTemplatesActionClass), + (GClassInitFunc) thunar_templates_action_class_init, + sizeof (ThunarTemplatesAction), + (GInstanceInitFunc) thunar_templates_action_init, + 0); } return type; @@ -102,10 +99,14 @@ static void thunar_templates_action_class_init (ThunarTemplatesActionClass *klass) { GtkActionClass *gtkaction_class; + GObjectClass *gobject_class; /* determine the parent type class */ thunar_templates_action_parent_class = g_type_class_peek_parent (klass); + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = thunar_templates_action_finalize; + gtkaction_class = GTK_ACTION_CLASS (klass); gtkaction_class->create_menu_item = thunar_templates_action_create_menu_item; @@ -127,19 +128,45 @@ thunar_templates_action_class_init (ThunarTemplatesActionClass *klass) /** * ThunarTemplatesAction::create-template: * @templates_action : a #ThunarTemplatesAction. - * @info : the #ThunarVfsInfo of the template file. + * @file : the #ThunarFile of the template file. * * Emitted by @templates_action whenever the user requests to * create a new file based on the template referred to by - * @info. + * @file. **/ templates_action_signals[CREATE_TEMPLATE] = g_signal_new (I_("create-template"), G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (ThunarTemplatesActionClass, create_template), - NULL, NULL, g_cclosure_marshal_VOID__BOXED, - G_TYPE_NONE, 1, THUNAR_VFS_TYPE_INFO); + NULL, NULL, g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, THUNAR_TYPE_FILE); +} + + + +static void +thunar_templates_action_init (ThunarTemplatesAction *templates_action) +{ + templates_action->job = NULL; +} + + + +static void +thunar_templates_action_finalize (GObject *object) +{ + ThunarTemplatesAction *templates_action = THUNAR_TEMPLATES_ACTION (object); + + if (templates_action->job != NULL) + { + g_signal_handlers_disconnect_matched (templates_action->job, + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, + templates_action); + g_object_unref (templates_action->job); + } + + (*G_OBJECT_CLASS (thunar_templates_action_parent_class)->finalize) (object); } @@ -165,259 +192,365 @@ thunar_templates_action_create_menu_item (GtkAction *action) -static gint -info_compare (gconstpointer a, - gconstpointer b) -{ - const ThunarVfsInfo *info_a = a; - const ThunarVfsInfo *info_b = b; - gchar *name_a; - gchar *name_b; - gint result; - - /* sort folders before files */ - if (info_a->type == THUNAR_VFS_FILE_TYPE_DIRECTORY && info_b->type != THUNAR_VFS_FILE_TYPE_DIRECTORY) - return -1; - else if (info_a->type != THUNAR_VFS_FILE_TYPE_DIRECTORY && info_b->type == THUNAR_VFS_FILE_TYPE_DIRECTORY) - return 1; - - /* compare by name */ - name_a = g_utf8_casefold (info_a->display_name, -1); - name_b = g_utf8_casefold (info_b->display_name, -1); - result = g_utf8_collate (name_a, name_b); - g_free (name_b); - g_free (name_a); - - return result; -} - - - static void item_activated (GtkWidget *item, ThunarTemplatesAction *templates_action) { - const ThunarVfsInfo *info; + const ThunarFile *file; _thunar_return_if_fail (THUNAR_IS_TEMPLATES_ACTION (templates_action)); _thunar_return_if_fail (GTK_IS_WIDGET (item)); - /* check if an info is set for the item (else it's the "Empty File" item) */ - info = g_object_get_data (G_OBJECT (item), I_("thunar-vfs-info")); - if (G_UNLIKELY (info != NULL)) - g_signal_emit (G_OBJECT (templates_action), templates_action_signals[CREATE_TEMPLATE], 0, info); + /* check if a file is set for the item (else it's the "Empty File" item) */ + file = g_object_get_data (G_OBJECT (item), I_("thunar-file")); + if (G_UNLIKELY (file != NULL)) + { + g_signal_emit (G_OBJECT (templates_action), + templates_action_signals[CREATE_TEMPLATE], 0, file); + } else - g_signal_emit (G_OBJECT (templates_action), templates_action_signals[CREATE_EMPTY_FILE], 0); + { + g_signal_emit (G_OBJECT (templates_action), + templates_action_signals[CREATE_EMPTY_FILE], 0); + } } -static void -thunar_templates_action_fill_menu (ThunarTemplatesAction *templates_action, - ThunarVfsPath *templates_path, - GtkWidget *menu) +static GtkWidget * +find_parent_menu (ThunarFile *file, + GList *dirs, + GList *items) { - ThunarVfsInfo *info; - ThunarVfsPath *path; - GtkIconTheme *icon_theme; - const gchar *icon_name; - const gchar *name; - GtkWidget *submenu; - GtkWidget *image; - GtkWidget *item; - gchar *absolute_path; - gchar *label; - gchar *dot; - GList *info_list = NULL; - GList *lp; - GDir *dp; - - /* try to open the templates (sub)directory */ - absolute_path = thunar_vfs_path_dup_string (templates_path); - dp = g_dir_open (absolute_path, 0, NULL); - g_free (absolute_path); - - /* read the directory contents (if opened successfully) */ - if (G_LIKELY (dp != NULL)) + GtkWidget *parent_menu = NULL; + GFile *parent; + GList *lp; + GList *ip; + + /* determine the parent of the file */ + parent = g_file_get_parent (thunar_file_get_file (file)); + + /* check if the file has a parent at all */ + if (parent == NULL) + return NULL; + + /* iterate over all dirs and menu items */ + for (lp = g_list_first (dirs), ip = g_list_first (items); + parent_menu == NULL && lp != NULL && ip != NULL; + lp = lp->next, ip = ip->next) { - /* process all files within the directory */ - for (;;) + /* check if the current dir/item is the parent of our file */ + if (g_file_equal (parent, thunar_file_get_file (lp->data))) { - /* read the name of the next file */ - name = g_dir_read_name (dp); - if (G_UNLIKELY (name == NULL)) - break; - else if (name[0] == '.') - continue; - - /* determine the info for that file */ - path = thunar_vfs_path_relative (templates_path, name); - info = thunar_vfs_info_new_for_path (path, NULL); - thunar_vfs_path_unref (path); - - /* add the info (if any) to our list */ - if (G_LIKELY (info != NULL)) - info_list = g_list_insert_sorted (info_list, info, info_compare); + /* we want to insert an item for the file in this menu */ + parent_menu = gtk_menu_item_get_submenu (ip->data); } + } + + /* destroy the parent GFile */ + g_object_unref (parent); + + return parent_menu; +} + + + +static gint +compare_files (ThunarFile *a, + ThunarFile *b) +{ + GFile *file_a; + GFile *file_b; + GFile *parent_a; + GFile *parent_b; + + file_a = thunar_file_get_file (a); + file_b = thunar_file_get_file (b); + + /* check whether the files are equal */ + if (g_file_equal (file_a, file_b)) + return 0; + + /* directories always come first */ + if (thunar_file_get_kind (a) == G_FILE_TYPE_DIRECTORY + && thunar_file_get_kind (b) != G_FILE_TYPE_DIRECTORY) + { + return -1; + } + else if (thunar_file_get_kind (a) != G_FILE_TYPE_DIRECTORY + && thunar_file_get_kind (b) == G_FILE_TYPE_DIRECTORY) + { + return 1; + } + + /* ancestors come first */ + if (g_file_has_prefix (file_b, file_a)) + return -1; + else if (g_file_has_prefix (file_a, file_b)) + return 1; - /* close the directory handle */ - g_dir_close (dp); + parent_a = g_file_get_parent (file_a); + parent_b = g_file_get_parent (file_b); + + if (g_file_equal (parent_a, parent_b)) + { + g_object_unref (parent_a); + g_object_unref (parent_b); + + /* compare siblings by their display name */ + return g_utf8_collate (thunar_file_get_display_name (a), + thunar_file_get_display_name (b)); + } + + /* again, ancestors come first */ + if (g_file_has_prefix (file_b, parent_a)) + { + g_object_unref (parent_a); + g_object_unref (parent_b); + + return -1; + } + else if (g_file_has_prefix (file_a, parent_b)) + { + g_object_unref (parent_a); + g_object_unref (parent_b); + + return 1; } - /* check if we have any infos */ - if (G_UNLIKELY (info_list == NULL)) - return; + g_object_unref (parent_a); + g_object_unref (parent_b); + + return 0; +} + - /* determine the icon theme for the menu */ - icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (menu)); - /* add menu items for all infos */ - for (lp = info_list; lp != NULL; lp = lp->next) +static gboolean +thunar_templates_action_files_ready (ThunarJob *job, + GList *files, + ThunarTemplatesAction *templates_action) +{ + ThunarIconFactory *icon_factory; + ThunarFile *file; + GdkPixbuf *icon; + GtkWidget *menu; + GtkWidget *parent_menu; + GtkWidget *submenu; + GtkWidget *image; + GtkWidget *item; + GList *lp; + GList *dirs = NULL; + GList *items = NULL; + GList *parent_menus = NULL; + GList *pp; + gchar *label; + gchar *dot; + + /* determine the menu to add the items and submenus to */ + menu = g_object_get_data (G_OBJECT (job), "menu"); + + /* do nothing if there is no menu */ + if (menu == NULL) + return FALSE; + + /* get the icon factory */ + icon_factory = thunar_icon_factory_get_default (); + + /* sort items so that directories come before files and ancestors come + * before descendants */ + files = g_list_sort (files, (GCompareFunc) compare_files); + + for (lp = g_list_first (files); lp != NULL; lp = lp->next) { - /* determine the info */ - info = lp->data; + file = lp->data; + + /* determine the parent menu for this file/directory */ + parent_menu = find_parent_menu (file, dirs, items); + parent_menu = parent_menu == NULL ? menu : parent_menu; + + if (thunar_file_get_kind (file) == G_FILE_TYPE_DIRECTORY) + { + /* allocate a new submenu for the directory */ + submenu = gtk_menu_new (); + g_object_ref_sink (G_OBJECT (submenu)); + gtk_menu_set_screen (GTK_MENU (submenu), gtk_widget_get_screen (menu)); + + /* allocate a new menu item for the directory */ + item = gtk_image_menu_item_new_with_label (thunar_file_get_display_name (file)); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu); - /* check if we have a regular file or a directory here */ - if (G_LIKELY (info->type == THUNAR_VFS_FILE_TYPE_REGULAR)) + /* prepend the directory, its item and the parent menu it should + * later be added to to the respective lists */ + dirs = g_list_prepend (dirs, file); + items = g_list_prepend (items, item); + parent_menus = g_list_prepend (parent_menus, parent_menu); + } + else { /* generate a label by stripping off the extension */ - label = g_strdup (info->display_name); + label = g_strdup (thunar_file_get_display_name (file)); dot = g_utf8_strrchr (label, -1, '.'); if (G_LIKELY (dot != NULL)) *dot = '\0'; /* allocate a new menu item */ item = gtk_image_menu_item_new_with_label (label); - g_object_set_data_full (G_OBJECT (item), I_("thunar-vfs-info"), thunar_vfs_info_ref (info), (GDestroyNotify) thunar_vfs_info_unref); - g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (item_activated), templates_action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + g_object_set_data_full (G_OBJECT (item), I_("thunar-file"), + g_object_ref (file), g_object_unref); + g_signal_connect (item, "activate", G_CALLBACK (item_activated), + templates_action); + gtk_menu_shell_append (GTK_MENU_SHELL (parent_menu), item); gtk_widget_show (item); + } - /* lookup the icon for the mime type of that file */ - icon_name = thunar_vfs_mime_info_lookup_icon_name (info->mime_info, icon_theme); + /* determine the icon for this file/directory */ + icon = thunar_icon_factory_load_file_icon (icon_factory, file, + THUNAR_FILE_ICON_STATE_DEFAULT, + GTK_ICON_SIZE_MENU); - /* generate an image based on the named icon */ - image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_widget_show (image); + /* allocate an image based on the icon */ + image = gtk_image_new_from_pixbuf (icon); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); + gtk_widget_show (image); + + /* release the icon reference */ + g_object_unref (icon); + } - /* cleanup */ - g_free (label); + /* add all non-empty directory items to their parent menu */ + for (lp = items, pp = parent_menus; + lp != NULL && pp != NULL; + lp = lp->next, pp = pp->next) + { + /* determine the submenu for this directory item */ + submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (lp->data)); + + if (GTK_MENU_SHELL (submenu)->children == NULL) + { + /* the directory submenu is empty, destroy it */ + gtk_widget_destroy (lp->data); } - else if (info->type == THUNAR_VFS_FILE_TYPE_DIRECTORY) + else { - /* allocate a new submenu for the directory */ - submenu = gtk_menu_new (); - g_object_ref_sink (G_OBJECT (submenu)); - gtk_menu_set_screen (GTK_MENU (submenu), gtk_widget_get_screen (menu)); - - /* fill the submenu from the folder contents */ - thunar_templates_action_fill_menu (templates_action, info->path, submenu); - - /* check if any items were added to the submenu */ - if (G_LIKELY (GTK_MENU_SHELL (submenu)->children != NULL)) - { - /* hook up the submenu */ - item = gtk_image_menu_item_new_with_label (info->display_name); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); - - /* lookup the icon for the mime type of that file */ - icon_name = thunar_vfs_mime_info_lookup_icon_name (info->mime_info, icon_theme); - - /* generate an image based on the named icon */ - image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_widget_show (image); - } - - /* cleanup */ - g_object_unref (G_OBJECT (submenu)); + /* the directory has template files, so add it to its parent menu */ + gtk_menu_shell_prepend (GTK_MENU_SHELL (pp->data), lp->data); + gtk_widget_show (lp->data); } } - /* release the info list */ - thunar_vfs_info_list_free (info_list); + /* destroy lists */ + g_list_free (dirs); + g_list_free (items); + g_list_free (parent_menus); + + /* release the icon factory */ + g_object_unref (icon_factory); + + /* let the job destroy the file list */ + return FALSE; } static void -thunar_templates_action_menu_shown (GtkWidget *menu, +thunar_templates_action_load_error (ThunarJob *job, + GError *error, ThunarTemplatesAction *templates_action) { - ThunarVfsPath *templates_path; - ThunarVfsPath *home_path; - GtkWidget *image; - GtkWidget *item; - GList *children; - gchar *templates_dir = NULL; + GtkWidget *item; + GtkWidget *menu; + _thunar_return_if_fail (THUNAR_IS_JOB (job)); + _thunar_return_if_fail (error != NULL); _thunar_return_if_fail (THUNAR_IS_TEMPLATES_ACTION (templates_action)); - _thunar_return_if_fail (GTK_IS_MENU_SHELL (menu)); - - /* drop all existing children of the menu first */ - children = gtk_container_get_children (GTK_CONTAINER (menu)); - g_list_foreach (children, (GFunc) gtk_widget_destroy, NULL); - g_list_free (children); + _thunar_return_if_fail (templates_action->job == job); - /* determine the path to the ~/Templates folder */ - home_path = thunar_vfs_path_get_for_home (); + menu = g_object_get_data (G_OBJECT (job), "menu"); -#if GLIB_CHECK_VERSION(2,14,0) - templates_dir = g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES)); -#endif /* GLIB_CHECK_VERSION(2,14,0) */ - if (G_UNLIKELY (templates_dir == NULL)) + /* check if any items were added to the menu */ + if (G_LIKELY (menu != NULL && GTK_MENU_SHELL (menu)->children == NULL)) { - templates_dir = g_build_filename (G_DIR_SEPARATOR_S, xfce_get_homedir (), - "Templates", NULL); + /* tell the user that no templates were found */ + item = gtk_menu_item_new_with_label (error->message); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_set_sensitive (item, FALSE); + gtk_widget_show (item); } +} - templates_path = thunar_vfs_path_new (templates_dir, NULL); - if (G_UNLIKELY (templates_path == NULL)) - templates_path = thunar_vfs_path_relative (home_path,"Templates"); - g_free (templates_dir); - thunar_vfs_path_unref (home_path); +static void +thunar_templates_action_load_finished (ThunarJob *job, + ThunarTemplatesAction *templates_action) +{ + GtkWidget *image; + GtkWidget *item; + GtkWidget *menu; -#if GLIB_CHECK_VERSION(2, 14, 0) - if (!exo_str_is_equal (g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES), xfce_get_homedir ())) - { - /* fill the menu with files/folders from the ~/Templates folder */ - thunar_templates_action_fill_menu (templates_action, templates_path, menu); - } -#endif + _thunar_return_if_fail (THUNAR_IS_JOB (job)); + _thunar_return_if_fail (THUNAR_IS_TEMPLATES_ACTION (templates_action)); + _thunar_return_if_fail (templates_action->job == job); - /* check if any items were added to the menu */ - if (G_UNLIKELY (GTK_MENU_SHELL (menu)->children == NULL)) + menu = g_object_get_data (G_OBJECT (job), "menu"); + if (G_LIKELY (menu != NULL)) { - /* tell the user that no templates were found */ - item = gtk_menu_item_new_with_label (_("No Templates installed")); + /* append a menu separator */ + item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_set_sensitive (item, FALSE); gtk_widget_show (item); + + /* add the "Empty File" item */ + item = gtk_image_menu_item_new_with_mnemonic (_("_Empty File")); + g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (item_activated), + templates_action); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + + /* add the icon for the emtpy file item */ + image = gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); + gtk_widget_show (image); } - /* append a menu separator */ - item = gtk_separator_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); + g_signal_handlers_disconnect_matched (job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, + templates_action); + g_object_unref (job); +} + + + +static void +thunar_templates_action_menu_shown (GtkWidget *menu, + ThunarTemplatesAction *templates_action) +{ + GList *children; - /* add the "Empty File" item */ - item = gtk_image_menu_item_new_with_mnemonic (_("_Empty File")); - g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (item_activated), templates_action); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); + _thunar_return_if_fail (THUNAR_IS_TEMPLATES_ACTION (templates_action)); + _thunar_return_if_fail (GTK_IS_MENU_SHELL (menu)); - /* add the icon for the emtpy file item */ - image = gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - gtk_widget_show (image); + /* drop all existing children of the menu first */ + children = gtk_container_get_children (GTK_CONTAINER (menu)); + g_list_foreach (children, (GFunc) gtk_widget_destroy, NULL); + g_list_free (children); - /* cleanup */ - thunar_vfs_path_unref (templates_path); + if (G_LIKELY (templates_action->job == NULL)) + { + templates_action->job = thunar_misc_jobs_load_template_files (menu); + g_object_add_weak_pointer (G_OBJECT (templates_action->job), + (gpointer) &templates_action->job); + + g_signal_connect (templates_action->job, "files-ready", + G_CALLBACK (thunar_templates_action_files_ready), + templates_action); + g_signal_connect (templates_action->job, "error", + G_CALLBACK (thunar_templates_action_load_error), + templates_action); + g_signal_connect (templates_action->job, "finished", + G_CALLBACK (thunar_templates_action_load_finished), + templates_action); + } } diff --git a/thunar/thunar-text-renderer.c b/thunar/thunar-text-renderer.c index 90a51f14f..25e52d494 100644 --- a/thunar/thunar-text-renderer.c +++ b/thunar/thunar-text-renderer.c @@ -488,11 +488,7 @@ thunar_text_renderer_render (GtkCellRenderer *renderer, { ThunarTextRenderer *text_renderer = THUNAR_TEXT_RENDERER (renderer); GtkStateType state; -#if !GTK_CHECK_VERSION(2,8,0) - GdkPoint points[8]; -#else cairo_t *cr; -#endif gint x0, x1, y0, y1; gint text_width; gint text_height; @@ -570,7 +566,6 @@ thunar_text_renderer_render (GtkCellRenderer *renderer, x1 = x0 + text_width; y1 = y0 + text_height; -#if GTK_CHECK_VERSION(2,8,0) /* Cairo produces nicer results than using a polygon * and so we use it directly if possible. */ @@ -587,20 +582,6 @@ thunar_text_renderer_render (GtkCellRenderer *renderer, gdk_cairo_set_source_color (cr, &widget->style->base[state]); cairo_fill (cr); cairo_destroy (cr); -#else - /* calculate a (more or less rounded) polygon */ - points[0].x = x0 + 2; points[0].y = y0; - points[1].x = x1 - 2; points[1].y = y0; - points[2].x = x1; points[2].y = y0 + 2; - points[3].x = x1; points[3].y = y1 - 2; - points[4].x = x1 - 2; points[4].y = y1; - points[5].x = x0 + 2; points[5].y = y1; - points[6].x = x0; points[6].y = y1 - 2; - points[7].x = x0; points[7].y = y0 + 2; - - /* render the indicator */ - gdk_draw_polygon (window, widget->style->base_gc[state], TRUE, points, G_N_ELEMENTS (points)); -#endif } /* draw the focus indicator */ diff --git a/thunar/thunar-thumbnail-generator.c b/thunar/thunar-thumbnail-generator.c deleted file mode 100644 index be3cf7e71..000000000 --- a/thunar/thunar-thumbnail-generator.c +++ /dev/null @@ -1,368 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> - * - * 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., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <thunar/thunar-private.h> -#include <thunar/thunar-thumbnail-generator.h> - - - -typedef struct _ThunarThumbnailInfo ThunarThumbnailInfo; - - - -static void thunar_thumbnail_generator_class_init (ThunarThumbnailGeneratorClass *klass); -static void thunar_thumbnail_generator_init (ThunarThumbnailGenerator *generator); -static void thunar_thumbnail_generator_finalize (GObject *object); -static gboolean thunar_thumbnail_generator_idle (gpointer user_data); -static gpointer thunar_thumbnail_generator_thread (gpointer user_data); -static void thunar_thumbnail_info_free (ThunarThumbnailInfo *info); - - - -struct _ThunarThumbnailGeneratorClass -{ - GObjectClass __parent__; -}; - -struct _ThunarThumbnailGenerator -{ - GObject __parent__; - - ThunarVfsThumbFactory *factory; - volatile GThread *thread; - GMutex *lock; - GCond *cond; - gint idle_id; - - GList *requests; - GList *replies; -}; - -struct _ThunarThumbnailInfo -{ - ThunarFile *file; - ThunarVfsInfo *info; -}; - - - -static GObjectClass *thunar_thumbnail_generator_parent_class; - - - -GType -thunar_thumbnail_generator_get_type (void) -{ - static GType type = G_TYPE_INVALID; - - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - static const GTypeInfo info = - { - sizeof (ThunarThumbnailGeneratorClass), - NULL, - NULL, - (GClassInitFunc) thunar_thumbnail_generator_class_init, - NULL, - NULL, - sizeof (ThunarThumbnailGenerator), - 0, - (GInstanceInitFunc) thunar_thumbnail_generator_init, - NULL, - }; - - type = g_type_register_static (G_TYPE_OBJECT, I_("ThunarThumbnailGenerator"), &info, 0); - } - - return type; -} - - - -static void -thunar_thumbnail_generator_class_init (ThunarThumbnailGeneratorClass *klass) -{ - GObjectClass *gobject_class; - - /* determine the parent type class */ - thunar_thumbnail_generator_parent_class = g_type_class_peek_parent (klass); - - gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_thumbnail_generator_finalize; -} - - - -static void -thunar_thumbnail_generator_init (ThunarThumbnailGenerator *generator) -{ - generator->lock = g_mutex_new (); - generator->cond = g_cond_new (); - generator->idle_id = -1; -} - - - -static void -thunar_thumbnail_generator_finalize (GObject *object) -{ - ThunarThumbnailGenerator *generator = THUNAR_THUMBNAIL_GENERATOR (object); - - /* acquire the generator lock */ - g_mutex_lock (generator->lock); - - /* release all requests */ - g_list_foreach (generator->requests, (GFunc) thunar_thumbnail_info_free, NULL); - g_list_free (generator->requests); - generator->requests = NULL; - - /* wait for the generator thread to terminate */ - while (G_UNLIKELY (generator->thread != NULL)) - g_cond_wait (generator->cond, generator->lock); - - /* release all replies */ - g_list_foreach (generator->replies, (GFunc) thunar_thumbnail_info_free, NULL); - g_list_free (generator->replies); - generator->replies = NULL; - - /* drop the idle source (if any) */ - if (G_UNLIKELY (generator->idle_id >= 0)) - g_source_remove (generator->idle_id); - - /* release the thumbnail factory */ - g_object_unref (G_OBJECT (generator->factory)); - - /* release the generator lock */ - g_mutex_unlock (generator->lock); - - /* release the cond and mutex */ - g_mutex_free (generator->lock); - g_cond_free (generator->cond); - - (*G_OBJECT_CLASS (thunar_thumbnail_generator_parent_class)->finalize) (object); -} - - - -static gboolean -thunar_thumbnail_generator_idle (gpointer user_data) -{ - ThunarThumbnailGenerator *generator = THUNAR_THUMBNAIL_GENERATOR (user_data); - ThunarThumbnailInfo *info; - GList *infos; - GList *lp; - - /* acquire the lock on the generator */ - g_mutex_lock (generator->lock); - - /* grab the infos returned from the thumbnailer thread */ - infos = generator->replies; - generator->replies = NULL; - - /* reset the process idle id */ - generator->idle_id = -1; - - /* release the lock on the generator */ - g_mutex_unlock (generator->lock); - - /* acquire the GDK thread lock */ - GDK_THREADS_ENTER (); - - /* invoke "changed" signals on all files */ - for (lp = infos; lp != NULL; lp = lp->next) - { - /* invoke "changed" and release the info */ - info = (ThunarThumbnailInfo *) lp->data; - thunar_file_changed (THUNAR_FILE (info->file)); - thunar_thumbnail_info_free (info); - } - g_list_free (infos); - - /* release the GDK thread lock */ - GDK_THREADS_LEAVE (); - - return FALSE; -} - - - -static gpointer -thunar_thumbnail_generator_thread (gpointer user_data) -{ - ThunarThumbnailGenerator *generator = THUNAR_THUMBNAIL_GENERATOR (user_data); - ThunarThumbnailInfo *info; - GdkPixbuf *icon; - - for (;;) - { - /* lock the factory */ - g_mutex_lock (generator->lock); - - /* grab the first thumbnail from the request list */ - if (G_LIKELY (generator->requests != NULL)) - { - info = generator->requests->data; - generator->requests = g_list_remove (generator->requests, info); - } - else - { - info = NULL; - } - - /* check if we have something to generate */ - if (G_UNLIKELY (info == NULL)) - { - /* reset the thread pointer */ - generator->thread = NULL; - g_cond_signal (generator->cond); - g_mutex_unlock (generator->lock); - break; - } - - /* release the lock */ - g_mutex_unlock (generator->lock); - - /* don't generate thumbnails for files for which only we own a reference */ - if (G_LIKELY (G_OBJECT (info->file)->ref_count > 1)) - { - /* try to generate the thumbnail */ - icon = thunar_vfs_thumb_factory_generate_thumbnail (generator->factory, info->info); - - /* store the thumbnail (or the failed notice) */ - thunar_vfs_thumb_factory_store_thumbnail (generator->factory, icon, info->info, NULL); - } - else - { - icon = NULL; - } - - /* place the thumbnail on the reply list and schedule the idle source */ - g_mutex_lock (generator->lock); - generator->replies = g_list_prepend (generator->replies, info); - if (G_UNLIKELY (generator->idle_id < 0)) - generator->idle_id = g_idle_add_full (G_PRIORITY_LOW, thunar_thumbnail_generator_idle, generator, NULL); - g_mutex_unlock (generator->lock); - - /* release the icon (if any) */ - if (G_LIKELY (icon != NULL)) - g_object_unref (G_OBJECT (icon)); - } - - return NULL; -} - - - -static void -thunar_thumbnail_info_free (ThunarThumbnailInfo *info) -{ - g_object_unref (G_OBJECT (info->file)); - thunar_vfs_info_unref (info->info); - _thunar_slice_free (ThunarThumbnailInfo, info); -} - - - -/** - * thunar_thumbnail_generator_new: - * @factory : a #ThunarVfsThumbFactory. - * - * Allocates a new #ThunarThumbnailGenerator object, - * which can be used to generate and store thumbnails - * for files. - * - * The caller is responsible to free the returned - * object using g_object_unref() when no longer needed. - * - * Return value: a newly allocated #ThunarThumbnailGenerator. - **/ -ThunarThumbnailGenerator* -thunar_thumbnail_generator_new (ThunarVfsThumbFactory *factory) -{ - ThunarThumbnailGenerator *generator; - - _thunar_return_val_if_fail (THUNAR_VFS_IS_THUMB_FACTORY (factory), NULL); - - /* allocate the generator object */ - generator = g_object_new (THUNAR_TYPE_THUMBNAIL_GENERATOR, NULL); - generator->factory = g_object_ref (G_OBJECT (factory)); - - return generator; -} - - - -/** - * thunar_thumbnail_generator_enqueue: - * @generator - * @file - **/ -void -thunar_thumbnail_generator_enqueue (ThunarThumbnailGenerator *generator, - ThunarFile *file) -{ - ThunarThumbnailInfo *info; - GError *error = NULL; - GList *lp; - - _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_GENERATOR (generator)); - _thunar_return_if_fail (THUNAR_IS_FILE (file)); - - /* acquire the generator lock */ - g_mutex_lock (generator->lock); - - /* check if the file is already on the request list */ - for (lp = generator->requests; lp != NULL; lp = lp->next) - if (((ThunarThumbnailInfo *) lp->data)->file == file) - break; - - /* schedule a request for the file if it's not already done */ - if (G_LIKELY (lp == NULL)) - { - /* allocate a thumbnail info for the file */ - info = _thunar_slice_new (ThunarThumbnailInfo); - info->file = g_object_ref (G_OBJECT (file)); - info->info = thunar_vfs_info_copy (thunar_file_get_info (file)); - - /* schedule the request */ - generator->requests = g_list_append (generator->requests, info); - - /* start the generator thread on-demand */ - if (G_UNLIKELY (generator->thread == NULL)) - { - generator->thread = g_thread_create_full (thunar_thumbnail_generator_thread, generator, 0, - FALSE, FALSE, G_THREAD_PRIORITY_LOW, &error); - if (G_UNLIKELY (generator->thread == NULL)) - { - g_warning ("Failed to launch thumbnail generator thread: %s", error->message); - g_error_free (error); - } - } - } - - /* release the generator lock */ - g_mutex_unlock (generator->lock); -} - - - diff --git a/thunar/thunar-thumbnail-generator.h b/thunar/thunar-thumbnail-generator.h deleted file mode 100644 index 9b833acae..000000000 --- a/thunar/thunar-thumbnail-generator.h +++ /dev/null @@ -1,46 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2005 Benedikt Meurer <benny@xfce.org> - * - * 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., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __THUNAR_THUMBNAIL_GENERATOR_H__ -#define __THUNAR_THUMBNAIL_GENERATOR_H__ - -#include <thunar/thunar-file.h> - -G_BEGIN_DECLS; - -typedef struct _ThunarThumbnailGeneratorClass ThunarThumbnailGeneratorClass; -typedef struct _ThunarThumbnailGenerator ThunarThumbnailGenerator; - -#define THUNAR_TYPE_THUMBNAIL_GENERATOR (thunar_thumbnail_generator_get_type ()) -#define THUNAR_THUMBNAIL_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_THUMBNAIL_GENERATOR, ThunarThumbnailGenerator)) -#define THUNAR_THUMBNAIL_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_THUMBNAIL_GENERATOR, ThunarThumbnailGeneratorClass)) -#define THUNAR_IS_THUMBNAIL_GENERATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_THUMBNAIL_GENERATOR)) -#define THUNAR_IS_THUMBNAIL_GENERATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_THUMBNAIL_GENERATOR)) -#define THUNAR_THUMBNAIL_GENERATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_THUMBNAIL_GENERATOR, ThunarThumbnailGeneratorClass)) - -GType thunar_thumbnail_generator_get_type (void) G_GNUC_CONST; - -ThunarThumbnailGenerator *thunar_thumbnail_generator_new (ThunarVfsThumbFactory *factory) G_GNUC_MALLOC; - -void thunar_thumbnail_generator_enqueue (ThunarThumbnailGenerator *generator, - ThunarFile *file); - -G_END_DECLS; - -#endif /* !__THUNAR_THUMBNAIL_GENERATOR_H__ */ diff --git a/thunar/thunar-thumbnailer-dbus.xml b/thunar/thunar-thumbnailer-dbus.xml new file mode 100644 index 000000000..ebd1e58f9 --- /dev/null +++ b/thunar/thunar-thumbnailer-dbus.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<node name="/org/freedesktop/thumbnails/Thumbnailer"> + <interface name="org.freedesktop.thumbnails.Thumbnailer"> + <method name="Queue"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <arg type="as" name="uris" direction="in" /> + <arg type="as" name="mime_hints" direction="in" /> + <arg type="u" name="handle_to_unqueue" direction="in" /> + <arg type="u" name="handle" direction="out" /> + </method> + + <method name="Unqueue"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <arg type="u" name="handle" direction="in" /> + </method> + + <signal name="Started"> + <arg type="u" name="handle" /> + </signal> + + <signal name="Finished"> + <arg type="u" name="handle" /> + </signal> + + <signal name="Ready"> + <arg type="as" name="uris" /> + </signal> + + <signal name="Error"> + <arg type="u" name="handle" /> + <arg type="as" name="failed_uris" /> + <arg type="i" name="error_code" /> + <arg type="s" name="message" /> + </signal> + </interface> +</node> diff --git a/thunar/thunar-thumbnailer-manager-dbus.xml b/thunar/thunar-thumbnailer-manager-dbus.xml new file mode 100644 index 000000000..7ce682b8b --- /dev/null +++ b/thunar/thunar-thumbnailer-manager-dbus.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<node name="/org/freedesktop/thumbnails/Manager"> + <interface name="org.freedesktop.thumbnails.Manager"> + <method name="Register"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <arg type="s" name="uri_scheme" direction="in" /> + <arg type="s" name="mime_type" direction="in" /> + </method> + <method name="GetSupported"> + <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> + <arg type="as" name="mime_types" direction="out" /> + </method> + </interface> +</node> diff --git a/thunar/thunar-thumbnailer.c b/thunar/thunar-thumbnailer.c new file mode 100644 index 000000000..c50edecc7 --- /dev/null +++ b/thunar/thunar-thumbnailer.c @@ -0,0 +1,1096 @@ +/* vi:set et ai sw=2 sts=2 ts=2: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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_DBUS +#include <dbus/dbus.h> +#include <dbus/dbus-glib.h> + +#include <thunar/thunar-thumbnailer-proxy.h> +#include <thunar/thunar-thumbnailer-manager-proxy.h> +#endif + +#include <thunar/thunar-marshal.h> +#include <thunar/thunar-private.h> +#include <thunar/thunar-thumbnailer.h> + + + +#if HAVE_DBUS +typedef enum +{ + THUNAR_THUMBNAILER_IDLE_ERROR, + THUNAR_THUMBNAILER_IDLE_READY, + THUNAR_THUMBNAILER_IDLE_STARTED, +} ThunarThumbnailerIdleType; + + + +typedef struct _ThunarThumbnailerCall ThunarThumbnailerCall; +typedef struct _ThunarThumbnailerIdle ThunarThumbnailerIdle; +#endif + + + +static void thunar_thumbnailer_finalize (GObject *object); +#ifdef HAVE_DBUS +static void thunar_thumbnailer_init_thumbnailer_proxy (ThunarThumbnailer *thumbnailer, + DBusGConnection *connection); +static void thunar_thumbnailer_init_manager_proxy (ThunarThumbnailer *thumbnailer, + DBusGConnection *connection); +static gboolean thunar_thumbnailer_file_is_supported (ThunarThumbnailer *thumbnailer, + ThunarFile *file); +static void thunar_thumbnailer_thumbnailer_finished (DBusGProxy *proxy, + guint handle, + ThunarThumbnailer *thumbnailer); +static void thunar_thumbnailer_thumbnailer_error (DBusGProxy *proxy, + guint handle, + const gchar **uris, + gint code, + const gchar *message, + ThunarThumbnailer *thumbnailer); +static void thunar_thumbnailer_thumbnailer_ready (DBusGProxy *proxy, + const gchar **uris, + ThunarThumbnailer *thumbnailer); +static void thunar_thumbnailer_thumbnailer_started (DBusGProxy *proxy, + guint handle, + ThunarThumbnailer *thumbnailer); +static gpointer thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer, + const gchar **uris, + const gchar **mime_hints); +static gboolean thunar_thumbnailer_error_idle (gpointer user_data); +static gboolean thunar_thumbnailer_ready_idle (gpointer user_data); +static gboolean thunar_thumbnailer_started_idle (gpointer user_data); +static void thunar_thumbnailer_call_free (ThunarThumbnailerCall *call); +static void thunar_thumbnailer_idle_free (gpointer data); +#endif + + + +struct _ThunarThumbnailerClass +{ + GObjectClass __parent__; +}; + +struct _ThunarThumbnailer +{ + GObject __parent__; + +#ifdef HAVE_DBUS + /* proxies to communicate with D-Bus services */ + DBusGProxy *manager_proxy; + DBusGProxy *thumbnailer_proxy; + + /* hash table to map D-Bus service handles to ThunarThumbnailer requests */ + GHashTable *handle_request_mapping; + + /* hash table to map ThunarThumbnailer requests to D-Bus service handles */ + GHashTable *request_handle_mapping; + + /* hash table to map ThunarThumbnailer requests to DBusGProxyCalls */ + GHashTable *request_call_mapping; + + /* hash table to map ThunarThumbnailer requests to URI arrays */ + GHashTable *request_uris_mapping; + + GMutex *lock; + + /* cached array of MIME types for which thumbnails can be generated */ + gchar **supported_types; + + /* last ThunarThumbnailer request ID */ + gpointer last_request; + + /* IDs of idle functions */ + GList *idles; +#endif +}; + +#ifdef HAVE_DBUS +struct _ThunarThumbnailerCall +{ + ThunarThumbnailer *thumbnailer; + gpointer request; +}; + +struct _ThunarThumbnailerIdle +{ + ThunarThumbnailerIdleType type; + ThunarThumbnailer *thumbnailer; + guint id; + + union + { + char **uris; + gpointer request; + } data; +}; +#endif + + + +#ifdef HAVE_DBUS +static DBusGProxy *thunar_thumbnailer_manager_proxy; +static DBusGProxy *thunar_thumbnailer_proxy; +static DBusGProxy *thunar_manager_proxy; +#endif + + + +G_DEFINE_TYPE (ThunarThumbnailer, thunar_thumbnailer, G_TYPE_OBJECT); + + + +static void +thunar_thumbnailer_class_init (ThunarThumbnailerClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = thunar_thumbnailer_finalize; +} + + + +static void +thunar_thumbnailer_init (ThunarThumbnailer *thumbnailer) +{ +#ifdef HAVE_DBUS + DBusGConnection *connection; + + thumbnailer->lock = g_mutex_new (); + thumbnailer->supported_types = NULL; + thumbnailer->last_request = GUINT_TO_POINTER (0); + thumbnailer->idles = NULL; + + /* try to connect to D-Bus */ + connection = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + + /* initialize the proxies */ + thunar_thumbnailer_init_thumbnailer_proxy (thumbnailer, connection); + thunar_thumbnailer_init_manager_proxy (thumbnailer, connection); + + /* check if we have a thumbnailer proxy */ + if (thumbnailer->thumbnailer_proxy != NULL) + { + /* we do, set up the hash tables */ + thumbnailer->request_handle_mapping = + g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); + thumbnailer->handle_request_mapping = + g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); + thumbnailer->request_call_mapping = + g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); + thumbnailer->request_uris_mapping = + g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, + (GDestroyNotify) g_strfreev); + } + + /* release the D-Bus connection if we have one */ + if (connection != NULL) + dbus_g_connection_unref (connection); +#endif +} + + + +static void +thunar_thumbnailer_finalize (GObject *object) +{ +#ifdef HAVE_DBUS + ThunarThumbnailerIdle *idle; + ThunarThumbnailer *thumbnailer = THUNAR_THUMBNAILER (object); + GList *list; + GList *lp; + + /* acquire the thumbnailer lock */ + g_mutex_lock (thumbnailer->lock); + + /* abort all pending idle functions */ + for (lp = thumbnailer->idles; lp != NULL; lp = lp->next) + { + idle = lp->data; + g_source_remove (idle->id); + } + + /* free the idle list */ + g_list_free (thumbnailer->idles); + + if (thumbnailer->manager_proxy != NULL) + { + /* disconnect from the manager proxy */ + g_signal_handlers_disconnect_matched (thumbnailer->manager_proxy, + G_SIGNAL_MATCH_DATA, 0, 0, + NULL, NULL, thumbnailer); + + /* release the manager proxy */ + g_object_unref (thumbnailer->manager_proxy); + } + + if (thumbnailer->thumbnailer_proxy != NULL) + { + /* cancel all pending D-Bus calls */ + list = g_hash_table_get_values (thumbnailer->request_call_mapping); + for (lp = list; lp != NULL; lp = lp->next) + dbus_g_proxy_cancel_call (thumbnailer->thumbnailer_proxy, lp->data); + g_list_free (list); + + g_hash_table_unref (thumbnailer->request_call_mapping); + +#if 0 + /* unqueue all pending requests */ + list = g_hash_table_get_keys (thumbnailer->handle_request_mapping); + for (lp = list; lp != NULL; lp = lp->next) + thunar_thumbnailer_unqueue_internal (thumbnailer, GPOINTER_TO_UINT (lp->data)); + g_list_free (list); +#endif + + g_hash_table_unref (thumbnailer->handle_request_mapping); + g_hash_table_unref (thumbnailer->request_handle_mapping); + g_hash_table_unref (thumbnailer->request_uris_mapping); + + /* disconnect from the thumbnailer proxy */ + g_signal_handlers_disconnect_matched (thumbnailer->thumbnailer_proxy, + G_SIGNAL_MATCH_DATA, 0, 0, + NULL, NULL, thumbnailer); + + /* release the thumbnailer proxy */ + g_object_unref (thumbnailer->thumbnailer_proxy); + } + + /* free the cached MIME types array */ + g_strfreev (thumbnailer->supported_types); + + /* release the thumbnailer lock */ + g_mutex_unlock (thumbnailer->lock); + + /* release the mutex */ + g_mutex_free (thumbnailer->lock); +#endif + + (*G_OBJECT_CLASS (thunar_thumbnailer_parent_class)->finalize) (object); +} + + + +#ifdef HAVE_DBUS +static void +thunar_thumbnailer_init_thumbnailer_proxy (ThunarThumbnailer *thumbnailer, + DBusGConnection *connection) +{ + /* we can't have a proxy without a D-Bus connection */ + if (connection == NULL) + { + thumbnailer->thumbnailer_proxy = NULL; + return; + } + + /* create the thumbnailer proxy shared by all ThunarThumbnailers on demand */ + if (thunar_thumbnailer_proxy == NULL) + { + /* create the shared thumbnailer proxy */ + thunar_thumbnailer_proxy = + dbus_g_proxy_new_for_name (connection, + "org.freedesktop.thumbnails.Thumbnailer", + "/org/freedesktop/thumbnails/Thumbnailer", + "org.freedesktop.thumbnails.Thumbnailer"); + + /* make sure to set it to NULL when the last reference is dropped */ + g_object_add_weak_pointer (G_OBJECT (thunar_thumbnailer_proxy), + (gpointer) &thunar_thumbnailer_proxy); + + thumbnailer->thumbnailer_proxy = thunar_thumbnailer_proxy; + + /* TODO this should actually be VOID:UINT,POINTER,INT,STRING */ + dbus_g_object_register_marshaller (_thunar_marshal_VOID__UINT_POINTER_UINT_STRING, + G_TYPE_NONE, + G_TYPE_UINT, + G_TYPE_STRV, + G_TYPE_UINT, + G_TYPE_STRING, + G_TYPE_INVALID); + + dbus_g_object_register_marshaller ((GClosureMarshal) g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + G_TYPE_STRV, + G_TYPE_INVALID); + + dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Error", + G_TYPE_UINT, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Finished", + G_TYPE_UINT, G_TYPE_INVALID); + dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Ready", + G_TYPE_STRV, G_TYPE_INVALID); + dbus_g_proxy_add_signal (thumbnailer->thumbnailer_proxy, "Started", + G_TYPE_UINT, G_TYPE_INVALID); + } + else + { + thumbnailer->thumbnailer_proxy = g_object_ref (thunar_thumbnailer_proxy); + } + + dbus_g_proxy_connect_signal (thumbnailer->thumbnailer_proxy, "Error", + G_CALLBACK (thunar_thumbnailer_thumbnailer_error), + thumbnailer, NULL); + dbus_g_proxy_connect_signal (thumbnailer->thumbnailer_proxy, "Finished", + G_CALLBACK (thunar_thumbnailer_thumbnailer_finished), + thumbnailer, NULL); + dbus_g_proxy_connect_signal (thumbnailer->thumbnailer_proxy, "Ready", + G_CALLBACK (thunar_thumbnailer_thumbnailer_ready), + thumbnailer, NULL); + dbus_g_proxy_connect_signal (thumbnailer->thumbnailer_proxy, "Started", + G_CALLBACK (thunar_thumbnailer_thumbnailer_started), + thumbnailer, NULL); +} + + + +static void +thunar_thumbnailer_init_manager_proxy (ThunarThumbnailer *thumbnailer, + DBusGConnection *connection) +{ + /* we cannot have a proxy without a D-Bus connection */ + if (connection == NULL) + { + thumbnailer->manager_proxy = NULL; + return; + } + + /* create the manager proxy shared by all ThunarThumbnailers on demand */ + if (thunar_manager_proxy == NULL) + { + /* create the shared manager proxy */ + thunar_thumbnailer_manager_proxy = + dbus_g_proxy_new_for_name (connection, + "org.freedesktop.thumbnails.Manager", + "/org/freedesktop/thumbnails/Manager", + "org.freedesktop.thumbnails.Manager"); + + /* make sure to set it to NULL when the last reference is dropped */ + g_object_add_weak_pointer (G_OBJECT (thunar_thumbnailer_manager_proxy), + (gpointer) &thunar_thumbnailer_manager_proxy); + + thumbnailer->manager_proxy = thunar_thumbnailer_manager_proxy; + } + else + { + thumbnailer->manager_proxy = g_object_ref (thunar_thumbnailer_manager_proxy); + } +} + + + +static gboolean +thunar_thumbnailer_file_is_supported (ThunarThumbnailer *thumbnailer, + ThunarFile *file) +{ + const gchar *content_type; + gboolean supported = FALSE; + guint n; + + _thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + /* acquire the thumbnailer lock */ + g_mutex_lock (thumbnailer->lock); + + /* just assume all types are supported if we don't have a manager */ + if (thumbnailer->manager_proxy == NULL) + { + /* release the thumbnailer lock */ + g_mutex_unlock (thumbnailer->lock); + return TRUE; + } + + /* request the supported types on demand */ + if (thumbnailer->supported_types == NULL) + { + /* request the supported types from the manager D-Bus service. We only do + * this once, so using a non-async call should be ok */ + thunar_thumbnailer_manager_proxy_get_supported (thumbnailer->manager_proxy, + &thumbnailer->supported_types, + NULL); + } + + /* check if we have supported types now */ + if (thumbnailer->supported_types != NULL) + { + /* determine the content type of the passed file */ + content_type = thunar_file_get_content_type (file); + + /* go through all the types */ + for (n = 0; !supported && thumbnailer->supported_types[n] != NULL; ++n) + { + /* check if the type of the file is a subtype of the supported type */ + if (g_content_type_is_a (content_type, thumbnailer->supported_types[n])) + supported = TRUE; + } + } + + /* release the thumbnailer lock */ + g_mutex_unlock (thumbnailer->lock); + + return supported; +} + + + +static void +thunar_thumbnailer_thumbnailer_error (DBusGProxy *proxy, + guint handle, + const gchar **uris, + gint code, + const gchar *message, + ThunarThumbnailer *thumbnailer) +{ + ThunarThumbnailerIdle *idle; + gpointer request; + + _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy)); + _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer)); + + /* look up the request ID for this D-Bus service handle */ + request = g_hash_table_lookup (thumbnailer->handle_request_mapping, + GUINT_TO_POINTER (handle)); + + /* check if we have a request for this handle */ + if (request != NULL) + { + /* allocate a new idle struct */ + idle = _thunar_slice_new0 (ThunarThumbnailerIdle); + idle->type = THUNAR_THUMBNAILER_IDLE_ERROR; + idle->thumbnailer = g_object_ref (thumbnailer); + + /* copy the URIs because we need them in the idle function */ + idle->data.uris = g_strdupv ((gchar **)uris); + + /* remember the idle struct because we might have to remove it in finalize() */ + thumbnailer->idles = g_list_prepend (thumbnailer->idles, idle); + + /* call the error idle function when we have the time */ + idle->id = g_idle_add_full (G_PRIORITY_LOW, + thunar_thumbnailer_error_idle, idle, + thunar_thumbnailer_idle_free); + } +} + + + +static void +thunar_thumbnailer_thumbnailer_finished (DBusGProxy *proxy, + guint handle, + ThunarThumbnailer *thumbnailer) +{ + gpointer request; + + _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy)); + _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer)); + + /* look up the request ID for this D-Bus service handle */ + request = g_hash_table_lookup (thumbnailer->handle_request_mapping, + GUINT_TO_POINTER (handle)); + + /* check if we have a request for this handle */ + if (request != NULL) + { + /* the request is finished, drop all the information about it */ + g_hash_table_remove (thumbnailer->handle_request_mapping, request); + g_hash_table_remove (thumbnailer->request_handle_mapping, request); + g_hash_table_remove (thumbnailer->request_uris_mapping, request); + } +} + + + +static void +thunar_thumbnailer_thumbnailer_ready (DBusGProxy *proxy, + const gchar **uris, + ThunarThumbnailer *thumbnailer) +{ + ThunarThumbnailerIdle *idle; + + _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy)); + _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer)); + + /* check if we have any ready URIs */ + if (uris != NULL) + { + /* allocate a new idle struct */ + idle = _thunar_slice_new0 (ThunarThumbnailerIdle); + idle->type = THUNAR_THUMBNAILER_IDLE_READY; + idle->thumbnailer = g_object_ref (thumbnailer); + + /* copy the URI array because we need it in the idle function */ + idle->data.uris = g_strdupv ((gchar **)uris); + + /* remember the idle struct because we might have to remove it in finalize() */ + thumbnailer->idles = g_list_prepend (thumbnailer->idles, idle); + + /* call the ready idle function when we have the time */ + idle->id = g_idle_add_full (G_PRIORITY_LOW, + thunar_thumbnailer_ready_idle, idle, + thunar_thumbnailer_idle_free); + } +} + + + +static void +thunar_thumbnailer_thumbnailer_started (DBusGProxy *proxy, + guint handle, + ThunarThumbnailer *thumbnailer) +{ + ThunarThumbnailerIdle *idle; + gpointer request; + + _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy)); + _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer)); + + /* look up the request for this D-Bus service handle */ + request = g_hash_table_lookup (thumbnailer->handle_request_mapping, + GUINT_TO_POINTER (handle)); + + /* check if we have a request for this handle */ + if (request != NULL) + { + /* allocate a new idle struct */ + idle = _thunar_slice_new0 (ThunarThumbnailerIdle); + idle->type = THUNAR_THUMBNAILER_IDLE_STARTED; + idle->thumbnailer = g_object_ref (thumbnailer); + + /* remember the request because we need it in the idle function */ + idle->data.request = request; + + /* remember the idle struct because we might have to remove it in finalize() */ + thumbnailer->idles = g_list_prepend (thumbnailer->idles, idle); + + /* call the started idle function when we have the time */ + idle->id = g_idle_add_full (G_PRIORITY_LOW, + thunar_thumbnailer_started_idle, idle, + thunar_thumbnailer_idle_free); + } +} + + + +static void +thunar_thumbnailer_queue_async_reply (DBusGProxy *proxy, + guint handle, + GError *error, + gpointer user_data) +{ + ThunarThumbnailerCall *call = user_data; + ThunarThumbnailer *thumbnailer = THUNAR_THUMBNAILER (call->thumbnailer); + gchar **uris; + + _thunar_return_if_fail (DBUS_IS_G_PROXY (proxy)); + _thunar_return_if_fail (call != NULL); + _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer)); + + g_mutex_lock (thumbnailer->lock); + + if (error != NULL) + { + /* get the URIs array for this request */ + uris = g_hash_table_lookup (thumbnailer->request_uris_mapping, call->request); + + /* the array should always exist, otherwise there's a bug in the program */ + _thunar_assert (uris != NULL); + + /* the request is "finished", forget about its URIs */ + g_hash_table_remove (thumbnailer->request_uris_mapping, call->request); + } + else + { + /* remember that this request and D-Bus handle belong together */ + g_hash_table_insert (thumbnailer->request_handle_mapping, + call->request, GUINT_TO_POINTER (handle)); + g_hash_table_insert (thumbnailer->handle_request_mapping, + GUINT_TO_POINTER (handle), call->request); + } + + /* the queue call is finished, we can forget about its proxy call */ + g_hash_table_remove (thumbnailer->request_call_mapping, call->request); + + thunar_thumbnailer_call_free (call); + + g_mutex_unlock (thumbnailer->lock); +} + + + +static gpointer +thunar_thumbnailer_queue_async (ThunarThumbnailer *thumbnailer, + const gchar **uris, + const gchar **mime_hints) +{ + ThunarThumbnailerCall *thumbnailer_call; + DBusGProxyCall *call; + gpointer request; + guint request_no; + + _thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), 0); + _thunar_return_val_if_fail (uris != NULL, 0); + _thunar_return_val_if_fail (mime_hints != NULL, 0); + _thunar_return_val_if_fail (DBUS_IS_G_PROXY (thumbnailer->thumbnailer_proxy), 0); + + /* compute the next request ID, making sure it's never 0 */ + request_no = GPOINTER_TO_UINT (thumbnailer->last_request) + 1; + request_no = MAX (request_no, 1); + + /* remember the ID for the next request */ + thumbnailer->last_request = GUINT_TO_POINTER (request_no); + + /* use the new request ID for this request */ + request = thumbnailer->last_request; + + /* allocate a new call struct for the async D-Bus call */ + thumbnailer_call = _thunar_slice_new0 (ThunarThumbnailerCall); + thumbnailer_call->request = request; + thumbnailer_call->thumbnailer = g_object_ref (thumbnailer); + + /* queue thumbnails for the given URIs asynchronously */ + call = thunar_thumbnailer_proxy_queue_async (thumbnailer->thumbnailer_proxy, + uris, mime_hints, 0, + thunar_thumbnailer_queue_async_reply, + thumbnailer_call); + + /* remember to which request the call struct belongs */ + g_hash_table_insert (thumbnailer->request_call_mapping, request, call); + + /* return the request ID used for this request */ + return request; +} + + + +static gboolean +thunar_thumbnailer_error_idle (gpointer user_data) +{ + ThunarThumbnailerIdle *idle = user_data; + ThunarFile *file; + GFile *gfile; + guint n; + + _thunar_return_val_if_fail (idle != NULL, FALSE); + _thunar_return_val_if_fail (idle->type == THUNAR_THUMBNAILER_IDLE_ERROR, FALSE); + + /* iterate over all failed URIs */ + for (n = 0; idle->data.uris != NULL && idle->data.uris[n] != NULL; ++n) + { + /* look up the corresponding ThunarFile from the cache */ + gfile = g_file_new_for_uri (idle->data.uris[n]); + file = thunar_file_cache_lookup (gfile); + g_object_unref (gfile); + + /* check if we have a file for this URI in the cache */ + if (file != NULL) + { + /* set thumbnail state to none unless the thumbnail has already been created. + * This is to prevent race conditions with the other idle functions */ + if (thunar_file_get_thumb_state (file) != THUNAR_FILE_THUMB_STATE_READY) + thunar_file_set_thumb_state (file, THUNAR_FILE_THUMB_STATE_NONE); + } + } + + /* remove the idle struct */ + g_mutex_lock (idle->thumbnailer->lock); + idle->thumbnailer->idles = g_list_remove (idle->thumbnailer->idles, idle); + g_mutex_unlock (idle->thumbnailer->lock); + + /* remove the idle source, which also destroys the idle struct */ + return FALSE; +} + + + +static gboolean +thunar_thumbnailer_ready_idle (gpointer user_data) +{ + ThunarThumbnailerIdle *idle = user_data; + ThunarFile *file; + GFile *gfile; + guint n; + + _thunar_return_val_if_fail (idle != NULL, FALSE); + _thunar_return_val_if_fail (idle->type == THUNAR_THUMBNAILER_IDLE_READY, FALSE); + + /* iterate over all failed URIs */ + for (n = 0; idle->data.uris != NULL && idle->data.uris[n] != NULL; ++n) + { + /* look up the corresponding ThunarFile from the cache */ + gfile = g_file_new_for_uri (idle->data.uris[n]); + file = thunar_file_cache_lookup (gfile); + g_object_unref (gfile); + + /* check if we have a file for this URI in the cache */ + if (file != NULL) + { + /* set thumbnail state to ready - we now have a thumbnail */ + thunar_file_set_thumb_state (file, THUNAR_FILE_THUMB_STATE_READY); + } + } + + /* remove the idle struct */ + g_mutex_lock (idle->thumbnailer->lock); + idle->thumbnailer->idles = g_list_remove (idle->thumbnailer->idles, idle); + g_mutex_unlock (idle->thumbnailer->lock); + + /* remove the idle source, which also destroys the idle struct */ + return FALSE; +} + + + +static gboolean +thunar_thumbnailer_started_idle (gpointer user_data) +{ + ThunarThumbnailerIdle *idle = user_data; + const gchar **uris; + ThunarFile *file; + GFile *gfile; + guint n; + + _thunar_return_val_if_fail (idle != NULL, FALSE); + _thunar_return_val_if_fail (idle->type == THUNAR_THUMBNAILER_IDLE_STARTED, FALSE); + + g_mutex_lock (idle->thumbnailer->lock); + + /* look up the URIs that belong to this request */ + uris = g_hash_table_lookup (idle->thumbnailer->request_uris_mapping, + idle->data.request); + + /* iterate over all URIs if there are any */ + for (n = 0; uris != NULL && uris[n] != NULL; ++n) + { + /* look up the corresponding ThunarFile from the cache */ + gfile = g_file_new_for_uri (uris[n]); + file = thunar_file_cache_lookup (gfile); + g_object_unref (gfile); + + /* check if we have a file in the cache */ + if (file != NULL) + { + /* set the thumbnail state to loading unless we already have a thumbnail. + * This is to prevent race conditions with the other idle functions */ + if (thunar_file_get_thumb_state (file) != THUNAR_FILE_THUMB_STATE_READY) + thunar_file_set_thumb_state (file, THUNAR_FILE_THUMB_STATE_LOADING); + } + } + + + /* remove the idle struct */ + idle->thumbnailer->idles = g_list_remove (idle->thumbnailer->idles, idle); + + g_mutex_unlock (idle->thumbnailer->lock); + + /* remove the idle source, which also destroys the idle struct */ + return FALSE; +} + + + +static gboolean +thunar_thumbnailer_file_is_queued (ThunarThumbnailer *thumbnailer, + ThunarFile *file) +{ + gboolean is_queued = FALSE; + GList *values; + GList *lp; + gchar **uris; + gchar *uri; + guint n; + + /* get a list with all URI arrays of already queued requests */ + values = g_hash_table_get_values (thumbnailer->request_uris_mapping); + + /* if we have none, the file cannot be queued ... or can it? ;) */ + if (values == NULL) + return FALSE; + + /* determine the URI for this file */ + uri = thunar_file_dup_uri (file); + + /* iterate over all URI arrays */ + for (lp = values; !is_queued && lp != NULL; lp = lp->next) + { + uris = lp->data; + + /* check if the file is included in the URI array of the current request */ + for (n = 0; !is_queued && uris != NULL && uris[n] != NULL; ++n) + if (g_utf8_collate (uri, uris[n]) == 0) + is_queued = TRUE; + } + + /* free the file URI */ + g_free (uri); + + /* free the URI array list */ + g_list_free (values); + + return is_queued; +} + + + +static gboolean +thunar_thumbnailer_file_is_ready (ThunarThumbnailer *thumbnailer, + ThunarFile *file) +{ + ThunarThumbnailerIdle *idle; + gboolean is_ready = FALSE; + GList *lp; + gchar *uri; + guint n; + + /* determine the URI or this file */ + uri = thunar_file_dup_uri (file); + + /* iterate over all idle structs */ + for (lp = thumbnailer->idles; !is_ready && lp != NULL; lp = lp->next) + { + /* skip invalid idles */ + if (lp->data != NULL) + continue; + + idle = lp->data; + + /* skip non-ready idles and idles without any URIs */ + if (idle->type != THUNAR_THUMBNAILER_IDLE_READY || idle->data.uris == NULL) + continue; + + /* check if the file is included in this ready idle */ + for (n = 0; !is_ready && idle->data.uris[n] != NULL; ++n) + if (g_utf8_collate (uri, idle->data.uris[n]) == 0) + is_ready = TRUE; + } + + /* free the file URI */ + g_free (uri); + + return is_ready; +} + + + +static void +thunar_thumbnailer_call_free (ThunarThumbnailerCall *call) +{ + _thunar_return_if_fail (call != NULL); + + /* drop the thumbnailer reference */ + g_object_unref (call->thumbnailer); + + /* free the struct */ + _thunar_slice_free (ThunarThumbnailerCall, call); +} + + + +static void +thunar_thumbnailer_idle_free (gpointer data) +{ + ThunarThumbnailerIdle *idle = data; + + _thunar_return_if_fail (idle != NULL); + + /* free the URI array if necessary */ + if (idle->type == THUNAR_THUMBNAILER_IDLE_READY + || idle->type == THUNAR_THUMBNAILER_IDLE_ERROR) + { + g_strfreev (idle->data.uris); + } + + /* drop the thumbnailer reference */ + g_object_unref (idle->thumbnailer); + + /* free the struct */ + _thunar_slice_free (ThunarThumbnailerIdle, idle); +} +#endif /* HAVE_DBUS */ + + + +/** + * thunar_thumbnailer_new: + * + * Allocates a new #ThunarThumbnailer object, which can be used to + * generate and store thumbnails for files. + * + * The caller is responsible to free the returned + * object using g_object_unref() when no longer needed. + * + * Return value: a newly allocated #ThunarThumbnailer. + **/ +ThunarThumbnailer* +thunar_thumbnailer_new (void) +{ + return g_object_new (THUNAR_TYPE_THUMBNAILER, NULL); +} + + + +gboolean +thunar_thumbnailer_queue_file (ThunarThumbnailer *thumbnailer, + ThunarFile *file) +{ + GList files; + + _thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE); + _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE); + + /* fake a file list */ + files.data = file; + files.next = NULL; + files.prev = NULL; + + /* queue a thumbnail request for the file */ + return thunar_thumbnailer_queue_files (thumbnailer, &files); +} + + + +gboolean +thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer, + GList *files) +{ + gboolean success = FALSE; +#ifdef HAVE_DBUS + const gchar **mime_hints; + gpointer request; + GList *lp; + GList *supported_files = NULL; + gchar **uris; + guint n_supported = 0; + guint n; +#endif + + _thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE); + _thunar_return_val_if_fail (files != NULL, FALSE); + +#ifdef HAVE_DBUS + /* acquire the thumbnailer lock */ + g_mutex_lock (thumbnailer->lock); + + if (thumbnailer->thumbnailer_proxy != NULL) + { + g_mutex_unlock (thumbnailer->lock); + + /* collect all supported files from the list */ + for (lp = g_list_last (files); lp != NULL; lp = lp->prev) + if (thunar_thumbnailer_file_is_supported (thumbnailer, lp->data)) + { + supported_files = g_list_prepend (supported_files, lp->data); + n_supported += 1; + } + + /* remove all files from the supported list for which we have pending requests */ + for (lp = supported_files; lp != NULL; lp = lp->next) + { + /* check queued requests and ready idle structs */ + if (thunar_thumbnailer_file_is_queued (thumbnailer, lp->data) + || thunar_thumbnailer_file_is_ready (thumbnailer, lp->data)) + { + /* remove the link if the file is present in either of the above */ + supported_files = g_list_delete_link (supported_files, lp); + } + } + + g_mutex_lock (thumbnailer->lock); + + /* check if we have any supported files */ + if (supported_files != NULL) + { + /* allocate arrays for URIs and mime hints */ + uris = g_new0 (gchar *, n_supported + 1); + mime_hints = g_new0 (const gchar *, n_supported + 1); + + /* fill arrays with data from the supported files */ + for (lp = supported_files, n = 0; lp != NULL; lp = lp->next, ++n) + { + uris[n] = thunar_file_dup_uri (lp->data); + mime_hints[n] = thunar_file_get_content_type (lp->data); + } + + /* NULL-terminate both arrays */ + uris[n] = NULL; + mime_hints[n] = NULL; + + /* queue a thumbnail request for the supported files */ + request = thunar_thumbnailer_queue_async (thumbnailer, + (const gchar **)uris, + mime_hints); + + /* remember the URIs for this request */ + g_hash_table_insert (thumbnailer->request_uris_mapping, request, uris); + + /* free mime hints array */ + g_free (mime_hints); + + /* free the list of supported files */ + g_list_free (supported_files); + + /* we assume success if we've come so far */ + success = TRUE; + } + } + + /* release the thumbnailer lock */ + g_mutex_unlock (thumbnailer->lock); +#endif /* HAVE_DBUS */ + + return success; +} + + + +void +thunar_thumbnailer_unqueue (ThunarThumbnailer *thumbnailer, + gpointer request) +{ +#ifdef HAVE_DBUS + gpointer handle; +#endif + + _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer)); + +#ifdef HAVE_DBUS + /* acquire the thumbnailer lock */ + g_mutex_lock (thumbnailer->lock); + + if (thumbnailer->thumbnailer_proxy != NULL) + { + handle = g_hash_table_lookup (thumbnailer->request_handle_mapping, request); + + thunar_thumbnailer_proxy_unqueue (thumbnailer->thumbnailer_proxy, + GPOINTER_TO_UINT (handle), NULL); + + g_hash_table_remove (thumbnailer->handle_request_mapping, handle); + g_hash_table_remove (thumbnailer->request_handle_mapping, request); + g_hash_table_remove (thumbnailer->request_uris_mapping, request); + } + + /* release the thumbnailer lock */ + g_mutex_unlock (thumbnailer->lock); +#endif +} diff --git a/thunar/thunar-thumbnailer.h b/thunar/thunar-thumbnailer.h new file mode 100644 index 000000000..83fa4ce6d --- /dev/null +++ b/thunar/thunar-thumbnailer.h @@ -0,0 +1,48 @@ +/* $Id$ */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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., 59 Temple + * Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __THUNAR_THUMBNAILER_H__ +#define __THUNAR_THUMBNAILER_H__ + +#include <thunar/thunar-file.h> + +G_BEGIN_DECLS; + +typedef struct _ThunarThumbnailerClass ThunarThumbnailerClass; +typedef struct _ThunarThumbnailer ThunarThumbnailer; + +#define THUNAR_TYPE_THUMBNAILER (thunar_thumbnailer_get_type ()) +#define THUNAR_THUMBNAILER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_THUMBNAILER, ThunarThumbnailer)) +#define THUNAR_THUMBNAILER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_THUMBNAILER, ThunarThumbnailerClass)) +#define THUNAR_IS_THUMBNAILER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_THUMBNAILER)) +#define THUNAR_IS_THUMBNAILER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_THUMBNAILER)) +#define THUNAR_THUMBNAILER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_THUMBNAILER, ThunarThumbnailerClass)) + +GType thunar_thumbnailer_get_type (void) G_GNUC_CONST; + +ThunarThumbnailer *thunar_thumbnailer_new (void) G_GNUC_MALLOC; + +gboolean thunar_thumbnailer_queue_file (ThunarThumbnailer *generator, + ThunarFile *file); +gboolean thunar_thumbnailer_queue_files (ThunarThumbnailer *generator, + GList *files); + +G_END_DECLS; + +#endif /* !__THUNAR_THUMBNAILER_H__ */ diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c new file mode 100644 index 000000000..0fbc5de18 --- /dev/null +++ b/thunar/thunar-transfer-job.c @@ -0,0 +1,887 @@ +/* vi:set sw=2 sts=2 ts=2 et ai: */ +/*- + * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gio/gio.h> + +#include <thunar/thunar-gio-extensions.h> +#include <thunar/thunar-io-scan-directory.h> +#include <thunar/thunar-io-jobs-util.h> +#include <thunar/thunar-job.h> +#include <thunar/thunar-private.h> +#include <thunar/thunar-transfer-job.h> + + + +typedef struct _ThunarTransferNode ThunarTransferNode; + + + +static void thunar_transfer_job_class_init (ThunarTransferJobClass *klass); +static void thunar_transfer_job_init (ThunarTransferJob *job); +static void thunar_transfer_job_finalize (GObject *object); +static gboolean thunar_transfer_job_execute (ExoJob *job, + GError **error); +static void thunar_transfer_node_free (ThunarTransferNode *node); + + + +struct _ThunarTransferJobClass +{ + ThunarJobClass __parent__; +}; + +struct _ThunarTransferJob +{ + ThunarJob __parent__; + + ThunarTransferJobType type; + GList *source_node_list; + GList *target_file_list; + + guint64 total_size; + guint64 total_progress; + guint64 file_progress; +}; + +struct _ThunarTransferNode +{ + ThunarTransferNode *next; + ThunarTransferNode *children; + GFile *source_file; +}; + + + +static GObjectClass *thunar_transfer_job_parent_class = NULL; + + + +GType +thunar_transfer_job_get_type (void) +{ + static GType type = G_TYPE_INVALID; + + if (G_UNLIKELY (type == G_TYPE_INVALID)) + { + type = g_type_register_static_simple (THUNAR_TYPE_JOB, + "ThunarTransferJob", + sizeof (ThunarTransferJobClass), + (GClassInitFunc) thunar_transfer_job_class_init, + sizeof (ThunarTransferJob), + (GInstanceInitFunc) thunar_transfer_job_init, + 0); + } + + return type; +} + + + +static void +thunar_transfer_job_class_init (ThunarTransferJobClass *klass) +{ + GObjectClass *gobject_class; + ExoJobClass *exojob_class; + + /* Determine the parent type class */ + thunar_transfer_job_parent_class = g_type_class_peek_parent (klass); + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = thunar_transfer_job_finalize; + + exojob_class = EXO_JOB_CLASS (klass); + exojob_class->execute = thunar_transfer_job_execute; +} + + + +static void +thunar_transfer_job_init (ThunarTransferJob *job) +{ + job->type = 0; + job->source_node_list = NULL; + job->target_file_list = NULL; + job->total_size = 0; + job->total_progress = 0; + job->file_progress = 0; +} + + + +static void +thunar_transfer_job_finalize (GObject *object) +{ + ThunarTransferJob *job = THUNAR_TRANSFER_JOB (object); + + g_list_foreach (job->source_node_list, (GFunc) thunar_transfer_node_free, NULL); + g_list_free (job->source_node_list); + + thunar_g_file_list_free (job->target_file_list); + + (*G_OBJECT_CLASS (thunar_transfer_job_parent_class)->finalize) (object); +} + + + +static void +thunar_transfer_job_progress (goffset current_num_bytes, + goffset total_num_bytes, + gpointer user_data) +{ + ThunarTransferJob *job = user_data; + + _thunar_return_if_fail (THUNAR_IS_TRANSFER_JOB (job)); + + if (G_LIKELY (job->total_size > 0)) + { + /* update total progress */ + job->total_progress += (current_num_bytes - job->file_progress); + + /* update file progress */ + job->file_progress = current_num_bytes; + + /* notify callers about the progress we made */ + exo_job_percent (EXO_JOB (job), (job->total_progress * 100.0) / job->total_size); + } +} + + + +static gboolean +thunar_transfer_job_collect_node (ThunarTransferJob *job, + ThunarTransferNode *node, + GError **error) +{ + ThunarTransferNode *child_node; + GFileInfo *info; + GError *err = NULL; + GList *file_list; + GList *lp; + + _thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (job), FALSE); + _thunar_return_val_if_fail (node != NULL && G_IS_FILE (node->source_file), FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return FALSE; + + info = g_file_query_info (node->source_file, + G_FILE_ATTRIBUTE_STANDARD_SIZE "," + G_FILE_ATTRIBUTE_STANDARD_TYPE, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + + if (G_UNLIKELY (info == NULL)) + return FALSE; + + job->total_size += g_file_info_get_size (info); + + /* check if we have a directory here */ + if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + { + /* scan the directory for immediate children */ + file_list = thunar_io_scan_directory (THUNAR_JOB (job), node->source_file, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + FALSE, &err); + + /* add children to the transfer node */ + for (lp = file_list; err == NULL && lp != NULL; lp = lp->next) + { + /* allocate a new transfer node for the child */ + child_node = _thunar_slice_new0 (ThunarTransferNode); + child_node->source_file = g_object_ref (lp->data); + + /* hook the child node into the child list */ + child_node->next = node->children; + node->children = child_node; + + /* collect the child node */ + thunar_transfer_job_collect_node (job, child_node, &err); + } + + /* release the child files */ + thunar_g_file_list_free (file_list); + } + + /* release file info */ + g_object_unref (info); + + if (G_UNLIKELY (err != NULL)) + { + g_propagate_error (error, err); + return FALSE; + } + + return TRUE; +} + + + +static gboolean +ttj_copy_file (ThunarTransferJob *job, + GFile *source_file, + GFile *target_file, + GFileCopyFlags copy_flags, + gboolean merge_directories, + GError **error) +{ + GFileType source_type; + GFileType target_type; + gboolean target_exists; + GError *err = NULL; + + _thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (job), FALSE); + _thunar_return_val_if_fail (G_IS_FILE (source_file), FALSE); + _thunar_return_val_if_fail (G_IS_FILE (target_file), FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* reset the file progress */ + job->file_progress = 0; + + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return FALSE; + + source_type = g_file_query_file_type (source_file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job))); + + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return FALSE; + + target_type = g_file_query_file_type (target_file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job))); + + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return FALSE; + + /* check if the target is a symlink and we are in overwrite mode */ + if (target_type == G_FILE_TYPE_SYMBOLIC_LINK && (copy_flags & G_FILE_COPY_OVERWRITE) != 0) + { + /* try to delete the symlink */ + if (!g_file_delete (target_file, exo_job_get_cancellable (EXO_JOB (job)), &err)) + { + g_propagate_error (error, err); + return FALSE; + } + } + + /* try to copy the file */ + g_file_copy (source_file, target_file, copy_flags, + exo_job_get_cancellable (EXO_JOB (job)), + thunar_transfer_job_progress, job, &err); + + /* check if there were errors */ + if (G_UNLIKELY (err != NULL && err->domain == G_IO_ERROR)) + { + if (err->code == G_IO_ERROR_WOULD_MERGE + || (err->code == G_IO_ERROR_EXISTS + && source_type == G_FILE_TYPE_DIRECTORY + && target_type == G_FILE_TYPE_DIRECTORY)) + { + /* we tried to overwrite a directory with a directory. this normally results + * in a merge. ignore the error we actually *want* to merge */ + if (merge_directories) + g_clear_error (&err); + } + else if (err->code == G_IO_ERROR_WOULD_RECURSE) + { + g_clear_error (&err); + + /* we tried to copy a directory and either + * + * - the target did not exist which means we simple have to + * create the target directory + * + * or + * + * - the target is not a directory and we tried to overwrite it in + * which case we have to delete it first and then create the target + * directory + */ + + /* check if the target file exists */ + target_exists = g_file_query_exists (target_file, + exo_job_get_cancellable (EXO_JOB (job))); + + /* abort on cancellation, continue otherwise */ + if (!exo_job_set_error_if_cancelled (EXO_JOB (job), &err)) + { + if (target_exists) + { + /* the target still exists and thus is not a directory. try to remove it */ + g_file_delete (target_file, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + } + + /* abort on error or cancellation, continue otherwise */ + if (err == NULL) + { + /* now try to create the directory */ + g_file_make_directory (target_file, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + } + } + } + } + + if (G_UNLIKELY (err != NULL)) + { + g_propagate_error (error, err); + return FALSE; + } + else + { + return TRUE; + } +} + + + +/** + * thunar_transfer_job_copy_file: + * @job : a #ThunarTransferJob. + * @source_file : the source #GFile to copy. + * @target_file : the destination #GFile to copy to. + * @error : return location for errors or %NULL. + * + * Tries to copy @source_file to @target_file. The real destination is the + * return value and may differ from @target_file (e.g. if you try to copy + * the file "/foo/bar" into the same directory you'll end up with something + * like "/foo/copy of bar" instead of "/foo/bar". + * + * The return value is guaranteed to be %NULL on errors and @error will + * always be set in those cases. If the file is skipped, the return value + * will be @source_file. + * + * Return value: the destination #GFile to which @source_file was copied + * or linked. The caller is reposible to release it with + * g_object_unref() if no longer needed. It points to + * @source_file if the file was skipped and will be %NULL + * on error or cancellation. + **/ +static GFile * +thunar_transfer_job_copy_file (ThunarTransferJob *job, + GFile *source_file, + GFile *target_file, + GError **error) +{ + ThunarJobResponse response; + GFileCopyFlags copy_flags = G_FILE_COPY_NOFOLLOW_SYMLINKS; + GError *err = NULL; + gint n; + + _thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (job), NULL); + _thunar_return_val_if_fail (G_IS_FILE (source_file), NULL); + _thunar_return_val_if_fail (G_IS_FILE (target_file), NULL); + _thunar_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* abort on cancellation */ + if (exo_job_set_error_if_cancelled (EXO_JOB (job), error)) + return NULL; + + /* various attempts to copy the file */ + while (err == NULL) + { + if (G_LIKELY (!g_file_equal (source_file, target_file))) + { + /* try to copy the file from source_file to the target_file */ + if (ttj_copy_file (job, source_file, target_file, copy_flags, TRUE, &err)) + { + /* return the real target file */ + return g_object_ref (target_file); + } + } + else + { + for (n = 1; err == NULL; ++n) + { + GFile *duplicate_file = thunar_io_jobs_util_next_duplicate_file (THUNAR_JOB (job), + source_file, + TRUE, n, + &err); + + if (err == NULL) + { + /* try to copy the file from source file to the duplicate file */ + if (ttj_copy_file (job, source_file, duplicate_file, copy_flags, TRUE, &err)) + { + /* return the real target file */ + return duplicate_file; + } + + g_object_unref (duplicate_file); + } + + if (err != NULL && err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS) + { + /* this duplicate already exists => clear the error to try the next alternative */ + g_clear_error (&err); + } + } + } + + /* check if we can recover from this error */ + if (err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS) + { + /* reset the error */ + g_clear_error (&err); + + /* ask the user whether to replace the target file */ + response = thunar_job_ask_replace (THUNAR_JOB (job), source_file, + target_file, &err); + + if (err != NULL) + break; + + /* check if we should retry */ + if (response == THUNAR_JOB_RESPONSE_RETRY) + continue; + + /* add overwrite flag and retry if we should overwrite */ + if (response == THUNAR_JOB_RESPONSE_YES) + { + copy_flags |= G_FILE_COPY_OVERWRITE; + continue; + } + + /* tell the caller we skipped the file if the user + * doesn't want to retry/overwrite */ + if (response == THUNAR_JOB_RESPONSE_NO) + return g_object_ref (source_file); + } + } + + _thunar_assert (err != NULL); + + g_propagate_error (error, err); + return NULL; +} + + + +static void +thunar_transfer_job_copy_node (ThunarTransferJob *job, + ThunarTransferNode *node, + GFile *target_file, + GFile *target_parent_file, + GList **target_file_list_return, + GError **error) +{ + ThunarJobResponse response; + GFileInfo *info; + GError *err = NULL; + GFile *real_target_file = NULL; + gchar *basename; + + _thunar_return_if_fail (THUNAR_IS_TRANSFER_JOB (job)); + _thunar_return_if_fail (node != NULL && G_IS_FILE (node->source_file)); + _thunar_return_if_fail (target_file == NULL || node->next == NULL); + _thunar_return_if_fail ((target_file == NULL && target_parent_file != NULL) || (target_file != NULL && target_parent_file == NULL)); + _thunar_return_if_fail (error == NULL || *error == NULL); + + /* The caller can either provide a target_file or a target_parent_file, but not both. The toplevel + * transfer_nodes (for which next is NULL) should be called with target_file, to get proper behavior + * wrt restoring files from the trash. Other transfer_nodes will be called with target_parent_file. + */ + + for (; err == NULL && node != NULL; node = node->next) + { + /* guess the target file for this node (unless already provided) */ + if (G_LIKELY (target_file == NULL)) + { + basename = g_file_get_basename (node->source_file); + target_file = g_file_get_child (target_parent_file, basename); + g_free (basename); + } + else + target_file = g_object_ref (target_file); + + /* query file info */ + info = g_file_query_info (node->source_file, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (EXO_JOB (job)), + &err); + + /* abort on error or cancellation */ + if (info == NULL) + { + g_object_unref (target_file); + break; + } + + /* update progress information */ + exo_job_info_message (EXO_JOB (job), g_file_info_get_display_name (info)); + +retry_copy: + /* copy the item specified by this node (not recursively) */ + real_target_file = thunar_transfer_job_copy_file (job, node->source_file, + target_file, &err); + if (G_LIKELY (real_target_file != NULL)) + { + /* node->source_file == real_target_file means to skip the file */ + if (G_LIKELY (node->source_file != real_target_file)) + { + /* check if we have children to copy */ + if (node->children != NULL) + { + /* copy all children of this node */ + thunar_transfer_job_copy_node (job, node->children, NULL, real_target_file, NULL, &err); + + /* free resources allocted for the children */ + thunar_transfer_node_free (node->children); + node->children = NULL; + } + + /* check if the child copy failed */ + if (G_UNLIKELY (err != NULL)) + { + /* outa here, freeing the target paths */ + g_object_unref (real_target_file); + g_object_unref (target_file); + break; + } + + /* add the real target file to the return list */ + if (G_LIKELY (target_file_list_return != NULL)) + *target_file_list_return = thunar_g_file_list_prepend (*target_file_list_return, real_target_file); + +retry_remove: + /* try to remove the source directory if we are on copy+remove fallback for move */ + if (job->type == THUNAR_TRANSFER_JOB_MOVE && + !g_file_delete (node->source_file, exo_job_get_cancellable (EXO_JOB (job)), &err)) + { + /* ask the user to retry */ + response = thunar_job_ask_skip (THUNAR_JOB (job), "%s", err->message); + + /* reset the error */ + g_clear_error (&err); + + /* check whether to retry */ + if (G_UNLIKELY (response == THUNAR_JOB_RESPONSE_RETRY)) + goto retry_remove; + } + } + + g_object_unref (real_target_file); + } + else if (err != NULL) + { + /* we can only skip if there is space left on the device */ + if (err->domain != G_IO_ERROR || err->code != G_IO_ERROR_NO_SPACE) + { + /* ask the user to skip this node and all subnodes */ + response = thunar_job_ask_skip (THUNAR_JOB (job), "%s", err->message); + + /* reset the error */ + g_clear_error (&err); + + /* check whether to retry */ + if (G_UNLIKELY (response == THUNAR_JOB_RESPONSE_RETRY)) + goto retry_copy; + } + } + + /* release the guessed target file */ + g_object_unref (target_file); + target_file = NULL; + + /* release file info */ + g_object_unref (info); + } + + /* propagate error if we failed or the job was cancelled */ + if (G_UNLIKELY (err != NULL)) + g_propagate_error (error, err); +} + + +static gboolean +thunar_transfer_job_execute (ExoJob *job, + GError **error) +{ + ThunarTransferNode *node; + ThunarJobResponse response; + ThunarTransferJob *transfer_job = THUNAR_TRANSFER_JOB (job); + GFileInfo *info; + gboolean parent_exists; + GError *err = NULL; + GList *new_files_list = NULL; + GList *snext; + GList *sp; + GList *tnext; + GList *tp; + GFile *target_parent; + gchar *basename; + gchar *parent_display_name; + + _thunar_return_val_if_fail (THUNAR_IS_TRANSFER_JOB (job), FALSE); + _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (exo_job_set_error_if_cancelled (job, error)) + return FALSE; + + exo_job_info_message (job, _("Collecting files...")); + + for (sp = transfer_job->source_node_list, tp = transfer_job->target_file_list; + sp != NULL && tp != NULL && err == NULL; + sp = snext, tp = tnext) + { + /* determine the next list items */ + snext = sp->next; + tnext = tp->next; + + /* determine the current source transfer node */ + node = sp->data; + + info = g_file_query_info (node->source_file, + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + exo_job_get_cancellable (job), + &err); + + if (G_UNLIKELY (info == NULL)) + break; + + /* check if we are moving a file out of the trash */ + if (transfer_job->type == THUNAR_TRANSFER_JOB_MOVE + && thunar_g_file_is_trashed (node->source_file)) + { + /* update progress information */ + exo_job_info_message (job, _("Trying to restore \"%s\""), + g_file_info_get_display_name (info)); + + /* determine the parent file */ + target_parent = g_file_get_parent (tp->data); + + /* check if the parent exists */ + parent_exists = g_file_query_exists (target_parent, exo_job_get_cancellable (job)); + + /* abort on cancellation */ + if (exo_job_set_error_if_cancelled (job, &err)) + { + g_object_unref (target_parent); + break; + } + + if (G_LIKELY (!parent_exists)) + { + /* determine the display name of the parent */ + basename = g_file_get_basename (target_parent); + parent_display_name = g_filename_display_name (basename); + g_free (basename); + + /* ask the user whether he wants to create the parent folder because its gone */ + response = thunar_job_ask_create (THUNAR_JOB (job), + _("The folder \"%s\" does not exist anymore but is " + "required to restore the file \"%s\" from the " + "trash"), + parent_display_name, + g_file_info_get_display_name (info)); + + /* abort if cancelled */ + if (G_UNLIKELY (response == THUNAR_JOB_RESPONSE_CANCEL)) + { + g_object_unref (target_parent); + g_free (parent_display_name); + break; + } + + /* try to create the parent directory */ + if (!g_file_make_directory_with_parents (target_parent, + exo_job_get_cancellable (job), + &err)) + { + if (!exo_job_is_cancelled (job)) + { + g_clear_error (&err); + + /* overwrite the internal GIO error with something more user-friendly */ + g_set_error (&err, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Failed to restore the folder \"%s\""), + parent_display_name); + } + + g_object_unref (target_parent); + g_free (parent_display_name); + break; + } + + /* clean up */ + g_free (parent_display_name); + } + } + + if (transfer_job->type == THUNAR_TRANSFER_JOB_MOVE) + { + /* update progress information */ + exo_job_info_message (job, _("Trying to move \"%s\""), + g_file_info_get_display_name (info)); + + if (g_file_move (node->source_file, tp->data, + G_FILE_COPY_NOFOLLOW_SYMLINKS + | G_FILE_COPY_NO_FALLBACK_FOR_MOVE, + exo_job_get_cancellable (job), + NULL, NULL, &err)) + { + /* add the target file to the new files list */ + new_files_list = thunar_g_file_list_prepend (new_files_list, tp->data); + + /* release source and target files */ + thunar_transfer_node_free (node); + g_object_unref (tp->data); + + /* drop the matching list items */ + transfer_job->source_node_list = g_list_delete_link (transfer_job->source_node_list, sp); + transfer_job->target_file_list = g_list_delete_link (transfer_job->target_file_list, tp); + } + else if (!exo_job_is_cancelled (job)) + { + g_clear_error (&err); + + /* update progress information */ + exo_job_info_message (job, _("Could not move \"%s\" directly. " + "Collecting files for copying..."), + g_file_info_get_display_name (info)); + + if (!thunar_transfer_job_collect_node (transfer_job, node, &err)) + { + /* failed to collect, cannot continue */ + g_object_unref (info); + break; + } + } + } + else if (transfer_job->type == THUNAR_TRANSFER_JOB_COPY) + { + if (!thunar_transfer_job_collect_node (THUNAR_TRANSFER_JOB (job), node, &err)) + break; + } + + g_object_unref (info); + } + + /* continue if there were no errors yet */ + if (G_LIKELY (err == NULL)) + { + /* perform the copy recursively for all source transfer nodes */ + for (sp = transfer_job->source_node_list, tp = transfer_job->target_file_list; + sp != NULL && tp != NULL && err == NULL; + sp = sp->next, tp = tp->next) + { + thunar_transfer_job_copy_node (transfer_job, sp->data, tp->data, NULL, + &new_files_list, &err); + } + } + + /* check if we failed */ + if (G_UNLIKELY (err != NULL)) + { + g_propagate_error (error, err); + return FALSE; + } + else + { + thunar_job_new_files (THUNAR_JOB (job), new_files_list); + thunar_g_file_list_free (new_files_list); + return TRUE; + } +} + + + +static void +thunar_transfer_node_free (ThunarTransferNode *node) +{ + ThunarTransferNode *next; + + /* free all nodes in a row */ + while (node != NULL) + { + /* free all children of this node */ + thunar_transfer_node_free (node->children); + + /* determine the next node */ + next = node->next; + + /* drop the source file of this node */ + g_object_unref (node->source_file); + + /* release the resources of this node */ + _thunar_slice_free (ThunarTransferNode, node); + + /* continue with the next node */ + node = next; + } +} + + + +ThunarJob * +thunar_transfer_job_new (GList *source_node_list, + GList *target_file_list, + ThunarTransferJobType type) +{ + ThunarTransferNode *node; + ThunarTransferJob *job; + GList *sp; + GList *tp; + + _thunar_return_val_if_fail (source_node_list != NULL, NULL); + _thunar_return_val_if_fail (target_file_list != NULL, NULL); + _thunar_return_val_if_fail (g_list_length (source_node_list) == g_list_length (target_file_list), NULL); + + job = g_object_new (THUNAR_TYPE_TRANSFER_JOB, NULL); + job->type = type; + + /* add a transfer node for each source path and a matching target parent path */ + for (sp = source_node_list, tp = target_file_list; + sp != NULL; + sp = sp->next, tp = tp->next) + { + /* make sure we don't transfer root directories. this should be prevented in the GUI */ + if (G_UNLIKELY (thunar_g_file_is_root (sp->data) || thunar_g_file_is_root (tp->data))) + continue; + + /* only process non-equal pairs unless we're copying */ + if (G_LIKELY (type != THUNAR_TRANSFER_JOB_MOVE || !g_file_equal (sp->data, tp->data))) + { + /* append transfer node for this source file */ + node = _thunar_slice_new0 (ThunarTransferNode); + node->source_file = g_object_ref (sp->data); + job->source_node_list = g_list_append (job->source_node_list, node); + + /* append target file */ + job->target_file_list = thunar_g_file_list_append (job->target_file_list, tp->data); + } + } + + /* make sure we didn't mess things up */ + _thunar_assert (g_list_length (job->source_node_list) == g_list_length (job->target_file_list)); + + return THUNAR_JOB (job); +} diff --git a/thunar/thunar-transfer-job.h b/thunar/thunar-transfer-job.h new file mode 100644 index 000000000..49f94a594 --- /dev/null +++ b/thunar/thunar-transfer-job.h @@ -0,0 +1,60 @@ +/* vi:set sw=2 sts=2 ts=2 et ai: */ +/*- + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __THUNAR_TRANSFER_JOB_H__ +#define __THUNAR_TRANSFER_JOB_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/** + * ThunarTransferJobFlags: + * + * Flags to control the behavior of the transfer job. + **/ +typedef enum /*< enum >*/ +{ + THUNAR_TRANSFER_JOB_COPY, + THUNAR_TRANSFER_JOB_LINK, + THUNAR_TRANSFER_JOB_MOVE, + THUNAR_TRANSFER_JOB_TRASH, +} ThunarTransferJobType; + +typedef struct _ThunarTransferJobPrivate ThunarTransferJobPrivate; +typedef struct _ThunarTransferJobClass ThunarTransferJobClass; +typedef struct _ThunarTransferJob ThunarTransferJob; + +#define THUNAR_TYPE_TRANSFER_JOB (thunar_transfer_job_get_type ()) +#define THUNAR_TRANSFER_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_TRANSFER_JOB, ThunarTransferJob)) +#define THUNAR_TRANSFER_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_TRANSFER_JOB, ThunarTransferJobClass)) +#define THUNAR_IS_TRANSFER_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_TRANSFER_JOB)) +#define THUNAR_IS_TRANSFER_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_TRANSFER_JOB) +#define THUNAR_TRANSFER_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_TRANSFER_JOB, ThunarTransferJobClass)) + +GType thunar_transfer_job_get_type (void) G_GNUC_CONST; + +ThunarJob *thunar_transfer_job_new (GList *source_file_list, + GList *target_file_list, + ThunarTransferJobType type) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +G_END_DECLS + +#endif /* !__THUNAR_TRANSFER_JOB_H__ */ diff --git a/thunar/thunar-trash-action.c b/thunar/thunar-trash-action.c index 17925406f..39f89bcaa 100644 --- a/thunar/thunar-trash-action.c +++ b/thunar/thunar-trash-action.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -98,12 +99,12 @@ thunar_trash_action_class_init (ThunarTrashActionClass *klass) static void thunar_trash_action_init (ThunarTrashAction *trash_action) { - ThunarVfsPath *trash_bin_path; + GFile *trash_bin; /* try to connect to the trash bin */ - trash_bin_path = thunar_vfs_path_get_for_trash (); - trash_action->trash_bin = thunar_file_get_for_path (trash_bin_path, NULL); - thunar_vfs_path_unref (trash_bin_path); + trash_bin = thunar_g_file_new_for_trash (); + trash_action->trash_bin = thunar_file_get (trash_bin, NULL); + g_object_unref (trash_bin); /* safety check for trash bin... */ if (G_LIKELY (trash_action->trash_bin != NULL)) diff --git a/thunar/thunar-tree-model.c b/thunar/thunar-tree-model.c index 10f3464be..0ae408227 100644 --- a/thunar/thunar-tree-model.c +++ b/thunar/thunar-tree-model.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org>. + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>. * * 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 @@ -30,6 +31,7 @@ #include <thunar/thunar-file-monitor.h> #include <thunar/thunar-folder.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-pango-extensions.h> #include <thunar/thunar-preferences.h> #include <thunar/thunar-private.h> @@ -114,21 +116,22 @@ static void thunar_tree_model_cleanup_idle_destroy (gpointer static void thunar_tree_model_file_changed (ThunarFileMonitor *file_monitor, ThunarFile *file, ThunarTreeModel *model); -static void thunar_tree_model_volume_changed (ThunarVfsVolume *volume, +static void thunar_tree_model_mount_pre_unmount (GVolumeMonitor *volume_monitor, + GMount *mount, ThunarTreeModel *model); -static void thunar_tree_model_volume_pre_unmount (ThunarVfsVolumeManager *volume_manager, - ThunarVfsVolume *volume, +static void thunar_tree_model_volume_added (GVolumeMonitor *volume_monitor, + GVolume *volume, ThunarTreeModel *model); -static void thunar_tree_model_volumes_added (ThunarVfsVolumeManager *volume_manager, - GList *volumes, +static void thunar_tree_model_volume_removed (GVolumeMonitor *volume_monitor, + GVolume *volume, ThunarTreeModel *model); -static void thunar_tree_model_volumes_removed (ThunarVfsVolumeManager *volume_manager, - GList *volumes, +static void thunar_tree_model_volume_changed (GVolumeMonitor *volume_monitor, + GVolume *volume, ThunarTreeModel *model); static ThunarTreeModelItem *thunar_tree_model_item_new_with_file (ThunarTreeModel *model, ThunarFile *file) G_GNUC_MALLOC; static ThunarTreeModelItem *thunar_tree_model_item_new_with_volume (ThunarTreeModel *model, - ThunarVfsVolume *volume) G_GNUC_MALLOC; + GVolume *volume) G_GNUC_MALLOC; static void thunar_tree_model_item_free (ThunarTreeModelItem *item); static void thunar_tree_model_item_reset (ThunarTreeModelItem *item); static void thunar_tree_model_item_load_folder (ThunarTreeModelItem *item); @@ -180,7 +183,7 @@ struct _ThunarTreeModel #endif /* removable volumes */ - ThunarVfsVolumeManager *volume_manager; + GVolumeMonitor *volume_monitor; GList *hidden_volumes; ThunarFileMonitor *file_monitor; @@ -201,7 +204,7 @@ struct _ThunarTreeModelItem guint load_idle_id; ThunarFile *file; ThunarFolder *folder; - ThunarVfsVolume *volume; + GVolume *volume; ThunarTreeModel *model; /* list of children of this node that are @@ -313,9 +316,14 @@ static void thunar_tree_model_init (ThunarTreeModel *model) { ThunarTreeModelItem *item; - ThunarVfsPath *system_path_list[3] = { thunar_vfs_path_get_for_home (), thunar_vfs_path_get_for_trash (), thunar_vfs_path_get_for_root () }; ThunarFile *file; + GFile *system_path_list[3] = { + thunar_g_file_new_for_home (), + thunar_g_file_new_for_trash (), + thunar_g_file_new_for_root () + }; GList *volumes; + GList *lp; GNode *node; guint n; @@ -337,17 +345,18 @@ thunar_tree_model_init (ThunarTreeModel *model) /* allocate the "virtual root node" */ model->root = g_node_new (NULL); - /* connect to the volume manager */ - model->volume_manager = thunar_vfs_volume_manager_get_default (); - g_signal_connect (G_OBJECT (model->volume_manager), "volumes-added", G_CALLBACK (thunar_tree_model_volumes_added), model); - g_signal_connect (G_OBJECT (model->volume_manager), "volumes-removed", G_CALLBACK (thunar_tree_model_volumes_removed), model); - g_signal_connect (G_OBJECT (model->volume_manager), "volume-pre-unmount", G_CALLBACK (thunar_tree_model_volume_pre_unmount), model); + /* connect to the volume monitor */ + model->volume_monitor = g_volume_monitor_get (); + g_signal_connect (model->volume_monitor, "mount-pre-unmount", G_CALLBACK (thunar_tree_model_mount_pre_unmount), model); + g_signal_connect (model->volume_monitor, "volume-added", G_CALLBACK (thunar_tree_model_volume_added), model); + g_signal_connect (model->volume_monitor, "volume-removed", G_CALLBACK (thunar_tree_model_volume_removed), model); + g_signal_connect (model->volume_monitor, "volume-changed", G_CALLBACK (thunar_tree_model_volume_changed), model); /* append the system defined nodes ('Home', 'Trash', 'File System') */ for (n = 0; n < G_N_ELEMENTS (system_path_list); ++n) { /* determine the file for the path */ - file = thunar_file_get_for_path (system_path_list[n], NULL); + file = thunar_file_get (system_path_list[n], NULL); if (G_LIKELY (file != NULL)) { /* watch the trash bin for changes */ @@ -364,13 +373,17 @@ thunar_tree_model_init (ThunarTreeModel *model) } /* release the system defined path */ - thunar_vfs_path_unref (system_path_list[n]); + g_object_unref (system_path_list[n]); } /* setup the initial volumes */ - volumes = thunar_vfs_volume_manager_get_volumes (model->volume_manager); - if (G_LIKELY (volumes != NULL)) - thunar_tree_model_volumes_added (model->volume_manager, volumes, model); + volumes = g_volume_monitor_get_volumes (model->volume_monitor); + for (lp = volumes; lp != NULL; lp = lp->next) + { + thunar_tree_model_volume_added (model->volume_monitor, lp->data, model); + g_object_unref (lp->data); + } + g_list_free (volumes); } @@ -379,31 +392,26 @@ static void thunar_tree_model_finalize (GObject *object) { ThunarTreeModel *model = THUNAR_TREE_MODEL (object); - GList *lp; /* remove the cleanup idle */ if (model->cleanup_idle_id != 0) g_source_remove (model->cleanup_idle_id); /* disconnect from the file monitor */ - g_signal_handlers_disconnect_by_func (G_OBJECT (model->file_monitor), thunar_tree_model_file_changed, model); - g_object_unref (G_OBJECT (model->file_monitor)); + g_signal_handlers_disconnect_by_func (model->file_monitor, thunar_tree_model_file_changed, model); + g_object_unref (model->file_monitor); /* release all hidden volumes */ - for (lp = model->hidden_volumes; lp != NULL; lp = lp->next) - { - g_signal_handlers_disconnect_by_func (G_OBJECT (lp->data), thunar_tree_model_volume_changed, model); - g_object_unref (G_OBJECT (lp->data)); - } + g_list_foreach (model->hidden_volumes, (GFunc) g_object_unref, NULL); g_list_free (model->hidden_volumes); /* release all resources allocated to the model */ g_node_traverse (model->root, G_POST_ORDER, G_TRAVERSE_ALL, -1, thunar_tree_model_node_traverse_free, NULL); g_node_destroy (model->root); - /* disconnect from the volume manager */ - g_signal_handlers_disconnect_matched (G_OBJECT (model->volume_manager), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model); - g_object_unref (G_OBJECT (model->volume_manager)); + /* disconnect from the volume monitor */ + g_signal_handlers_disconnect_matched (model->volume_monitor, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model); + g_object_unref (model->volume_monitor); (*G_OBJECT_CLASS (thunar_tree_model_parent_class)->finalize) (object); } @@ -486,7 +494,7 @@ thunar_tree_model_get_column_type (GtkTreeModel *tree_model, return PANGO_TYPE_ATTR_LIST; case THUNAR_TREE_MODEL_COLUMN_VOLUME: - return THUNAR_VFS_TYPE_VOLUME; + return G_TYPE_VOLUME; default: _thunar_assert_not_reached (); @@ -623,7 +631,7 @@ thunar_tree_model_get_value (GtkTreeModel *tree_model, case THUNAR_TREE_MODEL_COLUMN_NAME: g_value_init (value, G_TYPE_STRING); if (G_LIKELY (item != NULL && item->volume != NULL)) - g_value_set_static_string (value, thunar_vfs_volume_get_name (item->volume)); + g_value_take_string (value, g_volume_get_name (item->volume)); else if (G_LIKELY (item != NULL && item->file != NULL)) g_value_set_static_string (value, thunar_file_get_display_name (item->file)); else @@ -639,7 +647,7 @@ thunar_tree_model_get_value (GtkTreeModel *tree_model, break; case THUNAR_TREE_MODEL_COLUMN_VOLUME: - g_value_init (value, THUNAR_VFS_TYPE_VOLUME); + g_value_init (value, G_TYPE_VOLUME); g_value_set_object (value, (item != NULL) ? item->volume : NULL); break; @@ -968,17 +976,21 @@ thunar_tree_model_file_changed (ThunarFileMonitor *file_monitor, static void -thunar_tree_model_volume_changed (ThunarVfsVolume *volume, +thunar_tree_model_volume_changed (GVolumeMonitor *volume_monitor, + GVolume *volume, ThunarTreeModel *model) { ThunarTreeModelItem *item = NULL; GtkTreePath *path; GtkTreeIter iter; + GMount *mount; + GFile *mount_point; GNode *node; - GList list; GList *lp; - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (model->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_VOLUME (volume)); _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (model)); /* check if the volume is on the hidden list */ @@ -986,7 +998,7 @@ thunar_tree_model_volume_changed (ThunarVfsVolume *volume, if (G_LIKELY (lp != NULL)) { /* check if we need to display the volume now */ - if (thunar_vfs_volume_is_present (volume) && thunar_vfs_volume_is_removable (volume)) + if (thunar_g_volume_is_removable (volume) && thunar_g_volume_is_present (volume)) { /* remove the volume from the list of hidden volumes */ model->hidden_volumes = g_list_delete_link (model->hidden_volumes, lp); @@ -1010,7 +1022,7 @@ thunar_tree_model_volume_changed (ThunarVfsVolume *volume, thunar_tree_model_node_insert_dummy (node, model); /* drop our reference on the volume */ - g_object_unref (G_OBJECT (volume)); + g_object_unref (volume); } } else @@ -1028,20 +1040,13 @@ thunar_tree_model_volume_changed (ThunarVfsVolume *volume, _thunar_assert (item->volume == volume); /* check if we need to hide the volume now */ - if (!thunar_vfs_volume_is_present (volume) || !thunar_vfs_volume_is_removable (volume)) + if (!thunar_g_volume_is_removable (volume) || !thunar_g_volume_is_present (volume)) { /* need to ref here, because the volumes_removed() handler will drop the reference */ - g_object_ref (G_OBJECT (volume)); + g_object_ref (volume); - /* fake a list with only the volume */ - list.next = list.prev = NULL; - list.data = volume; - - /* use "volumes-removed" handler to hide the volume */ - thunar_tree_model_volumes_removed (model->volume_manager, &list, model); - - /* need to reconnect to the volume as the item removable drops the handler */ - g_signal_connect (G_OBJECT (volume), "changed", G_CALLBACK (thunar_tree_model_volume_changed), model); + /* use "volume-removed" handler to hide the volume */ + thunar_tree_model_volume_removed (model->volume_monitor, volume, model); /* move the volume to the hidden list */ model->hidden_volumes = g_list_prepend (model->hidden_volumes, volume); @@ -1049,15 +1054,25 @@ thunar_tree_model_volume_changed (ThunarVfsVolume *volume, else { /* check if the volume is mounted and we don't have a file yet */ - if (thunar_vfs_volume_is_mounted (volume) && item->file == NULL) + if (thunar_g_volume_is_mounted (volume) && item->file == NULL) { - /* try to determine the file for the mount point */ - item->file = thunar_file_get_for_path (thunar_vfs_volume_get_mount_point (volume), NULL); + mount = g_volume_get_mount (volume); + + if (G_LIKELY (mount != NULL)) + { + mount_point = g_mount_get_root (mount); + + /* try to determine the file for the mount point */ + item->file = thunar_file_get (mount_point, NULL); + + /* because the volume node is already reffed, we need to load the folder manually here */ + thunar_tree_model_item_load_folder (item); - /* because the volume node is already reffed, we need to load the folder manually here */ - thunar_tree_model_item_load_folder (item); + g_object_unref (mount_point); + g_object_unref (mount); + } } - else if (!thunar_vfs_volume_is_mounted (volume) && item->file != NULL) + else if (!thunar_g_volume_is_mounted (volume) && item->file != NULL) { /* reset the item for the node */ thunar_tree_model_item_reset (item); @@ -1084,21 +1099,31 @@ thunar_tree_model_volume_changed (ThunarVfsVolume *volume, static void -thunar_tree_model_volume_pre_unmount (ThunarVfsVolumeManager *volume_manager, - ThunarVfsVolume *volume, - ThunarTreeModel *model) +thunar_tree_model_mount_pre_unmount (GVolumeMonitor *volume_monitor, + GMount *mount, + ThunarTreeModel *model) { - GNode *node; + GVolume *volume; + GNode *node; - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager)); - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (model->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_MOUNT (mount)); _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (model)); + /* determine the mount to which this mount belongs */ + volume = g_mount_get_volume (mount); + + if (volume == NULL) + return; + /* lookup the node for the volume (if visible) */ for (node = model->root->children; node != NULL; node = node->next) if (THUNAR_TREE_MODEL_ITEM (node->data)->volume == volume) break; + g_object_unref (volume); + /* check if we have a node */ if (G_UNLIKELY (node == NULL)) return; @@ -1117,74 +1142,58 @@ thunar_tree_model_volume_pre_unmount (ThunarVfsVolumeManager *volume_manager, static void -thunar_tree_model_volumes_added (ThunarVfsVolumeManager *volume_manager, - GList *volumes, - ThunarTreeModel *model) +thunar_tree_model_volume_added (GVolumeMonitor *volume_monitor, + GVolume *volume, + ThunarTreeModel *model) { - GList *lp; - - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager)); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (model->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_VOLUME (volume)); _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (model)); - /* process all newly added volumes */ - for (lp = volumes; lp != NULL; lp = lp->next) - { - /* take a reference on the volume... */ - g_object_ref (G_OBJECT (lp->data)); - - /* ...place the volume on the hidden list... */ - model->hidden_volumes = g_list_prepend (model->hidden_volumes, lp->data); + /* place the volume on the hidden list */ + model->hidden_volumes = g_list_prepend (model->hidden_volumes, g_object_ref (volume)); - /* ...connect the "changed" signal handler... */ - g_signal_connect (G_OBJECT (lp->data), "changed", G_CALLBACK (thunar_tree_model_volume_changed), model); - - /* ...and let the "changed" handler place the volume where appropriate */ - thunar_tree_model_volume_changed (lp->data, model); - } + /* and let the "volume-changed" handler place the volume where appropriate */ + thunar_tree_model_volume_changed (volume_monitor, volume, model); } static void -thunar_tree_model_volumes_removed (ThunarVfsVolumeManager *volume_manager, - GList *volumes, - ThunarTreeModel *model) +thunar_tree_model_volume_removed (GVolumeMonitor *volume_monitor, + GVolume *volume, + ThunarTreeModel *model) { GNode *node; - GList *hp; GList *lp; - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager)); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (model->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_VOLUME (volume)); _thunar_return_if_fail (THUNAR_IS_TREE_MODEL (model)); - /* process all removed volumes */ - for (lp = volumes; lp != NULL; lp = lp->next) + /* check if the volume is on the hidden list */ + lp = g_list_find (model->hidden_volumes, volume); + if (G_LIKELY (lp != NULL)) { - /* check if the volume is on the hidden list */ - hp = g_list_find (model->hidden_volumes, lp->data); - if (G_LIKELY (hp != NULL)) - { - /* disconnect the "changed" signal handler from the volume */ - g_signal_handlers_disconnect_by_func (G_OBJECT (lp->data), thunar_tree_model_volume_changed, model); - - /* drop the volume from the hidden list and drop our reference */ - model->hidden_volumes = g_list_delete_link (model->hidden_volumes, hp); - g_object_unref (G_OBJECT (lp->data)); - } - else - { - /* must be a visible volume then... */ - for (node = model->root->children; node != NULL; node = node->next) - if (THUNAR_TREE_MODEL_ITEM (node->data)->volume == lp->data) - break; + /* remove the volume from the hidden list and drop our reference */ + model->hidden_volumes = g_list_delete_link (model->hidden_volumes, lp); + g_object_unref (volume); + } + else + { + /* must be a visible volume then... */ + for (node = model->root->children; node != NULL; node = node->next) + if (THUNAR_TREE_MODEL_ITEM (node->data)->volume == volume) + break; - /* something is broken if we don't have an item here */ - _thunar_assert (node != NULL); - _thunar_assert (THUNAR_TREE_MODEL_ITEM (node->data)->volume == lp->data); + /* something is broken if we don't have an item here */ + _thunar_assert (node != NULL); + _thunar_assert (THUNAR_TREE_MODEL_ITEM (node->data)->volume == volume); - /* drop the node from the model */ - g_node_traverse (node, G_POST_ORDER, G_TRAVERSE_ALL, -1, thunar_tree_model_node_traverse_remove, model); - } + /* drop the node from the model */ + g_node_traverse (node, G_POST_ORDER, G_TRAVERSE_ALL, -1, thunar_tree_model_node_traverse_remove, model); } } @@ -1207,21 +1216,31 @@ thunar_tree_model_item_new_with_file (ThunarTreeModel *model, static ThunarTreeModelItem* thunar_tree_model_item_new_with_volume (ThunarTreeModel *model, - ThunarVfsVolume *volume) + GVolume *volume) { ThunarTreeModelItem *item; - ThunarVfsPath *path; + GMount *mount; + GFile *mount_point; item = _thunar_slice_new0 (ThunarTreeModelItem); item->volume = g_object_ref (G_OBJECT (volume)); item->model = model; /* check if the volume is mounted */ - if (thunar_vfs_volume_is_mounted (volume)) + if (thunar_g_volume_is_mounted (volume)) { - /* try to determine the file for the mount point */ - path = thunar_vfs_volume_get_mount_point (volume); - item->file = thunar_file_get_for_path (path, NULL); + mount = g_volume_get_mount (volume); + + if (G_LIKELY (mount != NULL)) + { + mount_point = g_mount_get_root (mount); + + /* try to determine the file for the mount point */ + item->file = thunar_file_get (mount_point, NULL); + + g_object_unref (mount_point); + g_object_unref (mount); + } } return item; @@ -1234,10 +1253,7 @@ thunar_tree_model_item_free (ThunarTreeModelItem *item) { /* disconnect from the volume */ if (G_UNLIKELY (item->volume != NULL)) - { - g_signal_handlers_disconnect_by_func (G_OBJECT (item->volume), thunar_tree_model_volume_changed, item->model); - g_object_unref (G_OBJECT (item->volume)); - } + g_object_unref (item->volume); /* reset the remaining resources */ thunar_tree_model_item_reset (item); @@ -1484,6 +1500,8 @@ static gboolean thunar_tree_model_item_load_idle (gpointer user_data) { ThunarTreeModelItem *item = user_data; + GMount *mount; + GFile *mount_point; GList *files; _thunar_return_val_if_fail (item->folder == NULL, FALSE); @@ -1501,10 +1519,20 @@ thunar_tree_model_item_load_idle (gpointer user_data) GDK_THREADS_ENTER (); /* check if we don't have a file yet and this is a mounted volume */ - if (item->file == NULL && item->volume != NULL && thunar_vfs_volume_is_mounted (item->volume)) + if (item->file == NULL && item->volume != NULL && thunar_g_volume_is_mounted (item->volume)) { - /* try to determine the file for the mount point */ - item->file = thunar_file_get_for_path (thunar_vfs_volume_get_mount_point (item->volume), NULL); + mount = g_volume_get_mount (item->volume); + + if (G_LIKELY (mount != NULL)) + { + mount_point = g_mount_get_root (mount); + + /* try to determine the file for the mount point */ + item->file = thunar_file_get (mount_point, NULL); + + g_object_unref (mount_point); + g_object_unref (mount); + } } /* verify that we have a file */ diff --git a/thunar/thunar-tree-model.h b/thunar/thunar-tree-model.h index e040dc5b2..4cc7e2eaf 100644 --- a/thunar/thunar-tree-model.h +++ b/thunar/thunar-tree-model.h @@ -43,7 +43,7 @@ typedef gboolean (* ThunarTreeModelVisibleFunc) (ThunarTreeModel *model, * @THUNAR_TREE_MODEL_COLUMN_FILE : the index of the file column. * @THUNAR_TREE_MODEL_COLUMN_NAME : the index of the name column. * @THUNAR_TREE_MODEL_COLUMN_ATTR : the index of the #PangoAttrList column. - * @THUNAR_TREE_MODEL_COLUMN_VOLUME : the index of the #ThunarVfsVolume column. + * @THUNAR_TREE_MODEL_COLUMN_VOLUME : the index of the #GVolume column. * * Columns exported by the #ThunarTreeModel using the * #GtkTreeModel interface. diff --git a/thunar/thunar-tree-view.c b/thunar/thunar-tree-view.c index 449d41b78..83dc7e23d 100644 --- a/thunar/thunar-tree-view.c +++ b/thunar/thunar-tree-view.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -28,12 +29,15 @@ #include <thunar/thunar-create-dialog.h> #include <thunar/thunar-dialogs.h> #include <thunar/thunar-dnd.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-gtk-extensions.h> +#include <thunar/thunar-job.h> #include <thunar/thunar-marshal.h> #include <thunar/thunar-preferences.h> #include <thunar/thunar-private.h> #include <thunar/thunar-properties-dialog.h> #include <thunar/thunar-shortcuts-icon-renderer.h> +#include <thunar/thunar-simple-job.h> #include <thunar/thunar-tree-model.h> #include <thunar/thunar-tree-view.h> @@ -44,6 +48,10 @@ +typedef struct _ThunarTreeViewMountData ThunarTreeViewMountData; + + + /* Property identifiers */ enum { @@ -67,105 +75,117 @@ enum -static void thunar_tree_view_class_init (ThunarTreeViewClass *klass); -static void thunar_tree_view_navigator_init (ThunarNavigatorIface *iface); -static void thunar_tree_view_init (ThunarTreeView *view); -static void thunar_tree_view_finalize (GObject *object); -static void thunar_tree_view_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static void thunar_tree_view_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static ThunarFile *thunar_tree_view_get_current_directory (ThunarNavigator *navigator); -static void thunar_tree_view_set_current_directory (ThunarNavigator *navigator, - ThunarFile *current_directory); -static void thunar_tree_view_realize (GtkWidget *widget); -static void thunar_tree_view_unrealize (GtkWidget *widget); -static gboolean thunar_tree_view_button_press_event (GtkWidget *widget, - GdkEventButton *event); -static gboolean thunar_tree_view_button_release_event (GtkWidget *widget, - GdkEventButton *event); -static void thunar_tree_view_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *selection_data, - guint info, - guint time); -static gboolean thunar_tree_view_drag_drop (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); -static gboolean thunar_tree_view_drag_motion (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - guint time); -static void thunar_tree_view_drag_leave (GtkWidget *widget, - GdkDragContext *context, - guint time); -static gboolean thunar_tree_view_popup_menu (GtkWidget *widget); -static void thunar_tree_view_row_activated (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column); -static gboolean thunar_tree_view_test_expand_row (GtkTreeView *tree_view, - GtkTreeIter *iter, - GtkTreePath *path); -static void thunar_tree_view_row_collapsed (GtkTreeView *tree_view, - GtkTreeIter *iter, - GtkTreePath *path); -static gboolean thunar_tree_view_delete_selected_files (ThunarTreeView *view); -static void thunar_tree_view_context_menu (ThunarTreeView *view, - GdkEventButton *event, - GtkTreeModel *model, - GtkTreeIter *iter); -static GdkDragAction thunar_tree_view_get_dest_actions (ThunarTreeView *view, - GdkDragContext *context, - gint x, - gint y, - guint time, - ThunarFile **file_return); -static gboolean thunar_tree_view_find_closest_ancestor (ThunarTreeView *view, - GtkTreePath *path, - GtkTreePath **ancestor_return, - gboolean *exact_return); -static ThunarFile *thunar_tree_view_get_selected_file (ThunarTreeView *view); -static ThunarVfsVolume *thunar_tree_view_get_selected_volume (ThunarTreeView *view); -static void thunar_tree_view_action_copy (ThunarTreeView *view); -static void thunar_tree_view_action_create_folder (ThunarTreeView *view); -static void thunar_tree_view_action_cut (ThunarTreeView *view); -static void thunar_tree_view_action_delete (ThunarTreeView *view); -static void thunar_tree_view_action_rename (ThunarTreeView *view); -static void thunar_tree_view_action_eject (ThunarTreeView *view); -static void thunar_tree_view_action_empty_trash (ThunarTreeView *view); -static gboolean thunar_tree_view_action_mount (ThunarTreeView *view); -static void thunar_tree_view_action_open (ThunarTreeView *view); -static void thunar_tree_view_action_open_in_new_window (ThunarTreeView *view); -static void thunar_tree_view_action_paste_into_folder (ThunarTreeView *view); -static void thunar_tree_view_action_properties (ThunarTreeView *view); -static void thunar_tree_view_action_unmount (ThunarTreeView *view); -static GClosure *thunar_tree_view_new_files_closure (ThunarTreeView *view); -static void thunar_tree_view_new_files (ThunarVfsJob *job, - GList *path_list, - ThunarTreeView *view); -static gboolean thunar_tree_view_visible_func (ThunarTreeModel *model, - ThunarFile *file, - gpointer user_data); -static gboolean thunar_tree_view_selection_func (GtkTreeSelection *selection, - GtkTreeModel *model, - GtkTreePath *path, - gboolean path_currently_selected, - gpointer user_data); -static gboolean thunar_tree_view_cursor_idle (gpointer user_data); -static void thunar_tree_view_cursor_idle_destroy (gpointer user_data); -static gboolean thunar_tree_view_drag_scroll_timer (gpointer user_data); -static void thunar_tree_view_drag_scroll_timer_destroy (gpointer user_data); -static gboolean thunar_tree_view_expand_timer (gpointer user_data); -static void thunar_tree_view_expand_timer_destroy (gpointer user_data); +static void thunar_tree_view_class_init (ThunarTreeViewClass *klass); +static void thunar_tree_view_navigator_init (ThunarNavigatorIface *iface); +static void thunar_tree_view_init (ThunarTreeView *view); +static void thunar_tree_view_finalize (GObject *object); +static void thunar_tree_view_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static void thunar_tree_view_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static ThunarFile *thunar_tree_view_get_current_directory (ThunarNavigator *navigator); +static void thunar_tree_view_set_current_directory (ThunarNavigator *navigator, + ThunarFile *current_directory); +static void thunar_tree_view_realize (GtkWidget *widget); +static void thunar_tree_view_unrealize (GtkWidget *widget); +static gboolean thunar_tree_view_button_press_event (GtkWidget *widget, + GdkEventButton *event); +static gboolean thunar_tree_view_button_release_event (GtkWidget *widget, + GdkEventButton *event); +static void thunar_tree_view_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time); +static gboolean thunar_tree_view_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static gboolean thunar_tree_view_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time); +static void thunar_tree_view_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time); +static gboolean thunar_tree_view_popup_menu (GtkWidget *widget); +static void thunar_tree_view_row_activated (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column); +static gboolean thunar_tree_view_test_expand_row (GtkTreeView *tree_view, + GtkTreeIter *iter, + GtkTreePath *path); +static void thunar_tree_view_row_collapsed (GtkTreeView *tree_view, + GtkTreeIter *iter, + GtkTreePath *path); +static gboolean thunar_tree_view_delete_selected_files (ThunarTreeView *view); +static void thunar_tree_view_context_menu (ThunarTreeView *view, + GdkEventButton *event, + GtkTreeModel *model, + GtkTreeIter *iter); +static GdkDragAction thunar_tree_view_get_dest_actions (ThunarTreeView *view, + GdkDragContext *context, + gint x, + gint y, + guint time, + ThunarFile **file_return); +static gboolean thunar_tree_view_find_closest_ancestor (ThunarTreeView *view, + GtkTreePath *path, + GtkTreePath **ancestor_return, + gboolean *exact_return); +static ThunarFile *thunar_tree_view_get_selected_file (ThunarTreeView *view); +static GVolume *thunar_tree_view_get_selected_volume (ThunarTreeView *view); +static void thunar_tree_view_action_copy (ThunarTreeView *view); +static void thunar_tree_view_action_create_folder (ThunarTreeView *view); +static void thunar_tree_view_action_cut (ThunarTreeView *view); +static void thunar_tree_view_action_delete (ThunarTreeView *view); +static void thunar_tree_view_action_rename (ThunarTreeView *view); +static void thunar_tree_view_action_eject (ThunarTreeView *view); +static void thunar_tree_view_action_empty_trash (ThunarTreeView *view); +static void thunar_tree_view_action_mount (ThunarTreeView *view); +static void thunar_tree_view_mount_finish (GObject *object, + GAsyncResult *result, + gpointer user_data); +static void thunar_tree_view_mount (ThunarTreeView *view, + gboolean open_after_mounting, + gboolean open_in_new_window); +static void thunar_tree_view_action_open (ThunarTreeView *view); +static void thunar_tree_view_open_selection (ThunarTreeView *view); +static void thunar_tree_view_action_open_in_new_window (ThunarTreeView *view); +static void thunar_tree_view_open_selection_in_new_window (ThunarTreeView *view); +static void thunar_tree_view_action_paste_into_folder (ThunarTreeView *view); +static void thunar_tree_view_action_properties (ThunarTreeView *view); +static GClosure *thunar_tree_view_new_files_closure (ThunarTreeView *view); +static void thunar_tree_view_new_files (ThunarJob *job, + GList *path_list, + ThunarTreeView *view); +static gboolean thunar_tree_view_visible_func (ThunarTreeModel *model, + ThunarFile *file, + gpointer user_data); +static gboolean thunar_tree_view_selection_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer user_data); +static gboolean thunar_tree_view_cursor_idle (gpointer user_data); +static void thunar_tree_view_cursor_idle_destroy (gpointer user_data); +static gboolean thunar_tree_view_drag_scroll_timer (gpointer user_data); +static void thunar_tree_view_drag_scroll_timer_destroy (gpointer user_data); +static gboolean thunar_tree_view_expand_timer (gpointer user_data); +static void thunar_tree_view_expand_timer_destroy (gpointer user_data); +static ThunarTreeViewMountData *thunar_tree_view_mount_data_new (ThunarTreeView *view, + GtkTreePath *path, + gboolean open_after_mounting, + gboolean open_in_new_window); +static void thunar_tree_view_mount_data_free (ThunarTreeViewMountData *data); @@ -194,7 +214,7 @@ struct _ThunarTreeView /* drop site support */ guint drop_data_ready : 1; /* whether the drop data was received already */ guint drop_occurred : 1; - GList *drop_path_list; /* the list of URIs that are contained in the drop data */ + GList *drop_file_list; /* the list of URIs that are contained in the drop data */ /* the "new-files" closure, which is used to * open newly created directories once done. @@ -207,12 +227,10 @@ struct _ThunarTreeView */ gint pressed_button; -#if GTK_CHECK_VERSION(2,8,0) /* id of the signal used to queue a resize on the * column whenever the shortcuts icon size is changed. */ gint queue_resize_signal_id; -#endif /* set cursor to current directory idle source */ gint cursor_idle_id; @@ -224,6 +242,14 @@ struct _ThunarTreeView gint expand_timer_id; }; +struct _ThunarTreeViewMountData +{ + ThunarTreeView *view; + GtkTreePath *path; + gboolean open_after_mounting; + gboolean open_in_new_window; +}; + /* Target types for dropping into the tree view */ @@ -402,10 +428,8 @@ thunar_tree_view_init (ThunarTreeView *view) gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); /* queue a resize on the column whenever the icon size is changed */ -#if GTK_CHECK_VERSION(2,8,0) view->queue_resize_signal_id = g_signal_connect_swapped (G_OBJECT (view->preferences), "notify::tree-icon-size", G_CALLBACK (gtk_tree_view_column_queue_resize), column); -#endif /* allocate the special icon renderer */ view->icon_renderer = thunar_shortcuts_icon_renderer_new (); @@ -447,15 +471,13 @@ thunar_tree_view_finalize (GObject *object) ThunarTreeView *view = THUNAR_TREE_VIEW (object); /* release drop path list (if drag_leave wasn't called) */ - thunar_vfs_path_list_free (view->drop_path_list); + thunar_g_file_list_free (view->drop_file_list); /* release the provider factory */ g_object_unref (G_OBJECT (view->provider_factory)); /* disconnect the queue resize signal handler */ -#if GTK_CHECK_VERSION(2,8,0) g_signal_handler_disconnect (G_OBJECT (view->preferences), view->queue_resize_signal_id); -#endif /* be sure to cancel the cursor idle source */ if (G_UNLIKELY (view->cursor_idle_id >= 0)) @@ -742,7 +764,7 @@ thunar_tree_view_drag_data_received (GtkWidget *widget, { /* extract the URI list from the selection data (if valid) */ if (info == TARGET_TEXT_URI_LIST && selection_data->format == 8 && selection_data->length > 0) - view->drop_path_list = thunar_vfs_path_list_from_string ((const gchar *) selection_data->data, NULL); + view->drop_file_list = thunar_g_file_list_new_from_string ((const gchar *) selection_data->data); /* reset the state */ view->drop_data_ready = TRUE; @@ -760,12 +782,12 @@ thunar_tree_view_drag_data_received (GtkWidget *widget, { /* ask the user what to do with the drop data */ action = (context->action == GDK_ACTION_ASK) - ? thunar_dnd_ask (GTK_WIDGET (view), file, view->drop_path_list, time, actions) + ? thunar_dnd_ask (GTK_WIDGET (view), file, view->drop_file_list, time, actions) : context->action; /* perform the requested action */ if (G_LIKELY (action != 0)) - succeed = thunar_dnd_perform (GTK_WIDGET (view), file, view->drop_path_list, action, NULL); + succeed = thunar_dnd_perform (GTK_WIDGET (view), file, view->drop_file_list, action, NULL); } /* release the file reference */ @@ -884,9 +906,9 @@ thunar_tree_view_drag_leave (GtkWidget *widget, /* reset the "drop data ready" status and free the URI list */ if (G_LIKELY (view->drop_data_ready)) { - thunar_vfs_path_list_free (view->drop_path_list); + thunar_g_file_list_free (view->drop_file_list); view->drop_data_ready = FALSE; - view->drop_path_list = NULL; + view->drop_file_list = NULL; } /* call the parent's handler */ @@ -950,11 +972,12 @@ thunar_tree_view_test_expand_row (GtkTreeView *tree_view, GtkTreeIter *iter, GtkTreePath *path) { - ThunarVfsVolume *volume; - ThunarTreeView *view = THUNAR_TREE_VIEW (tree_view); - GtkWidget *window; - gboolean expandable = TRUE; - GError *error = NULL; + ThunarTreeViewMountData *data; + GMountOperation *mount_operation; + ThunarTreeView *view = THUNAR_TREE_VIEW (tree_view); + GtkWidget *window; + gboolean expandable = TRUE; + GVolume *volume; /* determine the volume for the iterator */ gtk_tree_model_get (GTK_TREE_MODEL (view->model), iter, THUNAR_TREE_MODEL_COLUMN_VOLUME, &volume, -1); @@ -963,19 +986,25 @@ thunar_tree_view_test_expand_row (GtkTreeView *tree_view, if (G_UNLIKELY (volume != NULL)) { /* check if we need to mount the volume first */ - if (!thunar_vfs_volume_is_mounted (volume)) + if (!thunar_g_volume_is_mounted (volume)) { - /* determine the toplevel window */ + /* we need to mount the volume before we can expand the row */ + expandable = FALSE; + + /* allocate a mount data struct */ + data = thunar_tree_view_mount_data_new (view, path, FALSE, FALSE); + + /* allocate a GTK+ mount operation */ window = gtk_widget_get_toplevel (GTK_WIDGET (view)); + mount_operation = gtk_mount_operation_new (GTK_WINDOW (window)); - /* try to mount the volume */ - expandable = thunar_vfs_volume_mount (volume, window, &error); - if (G_UNLIKELY (!expandable)) - { - /* display an error dialog to inform the user */ - thunar_dialogs_show_error (window, error, _("Failed to mount \"%s\""), thunar_vfs_volume_get_name (volume)); - g_error_free (error); - } + /* try to mount the volume and expand the row on success. the + * data is destroyed in the finish callback */ + g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_operation, NULL, + thunar_tree_view_mount_finish, data); + + /* release the mount operation */ + g_object_unref (mount_operation); } /* release the volume */ @@ -1036,15 +1065,15 @@ thunar_tree_view_context_menu (ThunarTreeView *view, GtkTreeModel *model, GtkTreeIter *iter) { - ThunarVfsVolume *volume; - ThunarFile *parent_file; - ThunarFile *file; - GtkWidget *image; - GtkWidget *menu; - GtkWidget *item; - GtkWidget *window; - GList *providers, *lp; - GList *actions = NULL, *tmp; + GVolume *volume; + ThunarFile *parent_file; + ThunarFile *file; + GtkWidget *image; + GtkWidget *menu; + GtkWidget *item; + GtkWidget *window; + GList *providers, *lp; + GList *actions = NULL, *tmp; /* verify that we're connected to the clipboard manager */ if (G_UNLIKELY (view->clipboard == NULL)) @@ -1087,13 +1116,13 @@ thunar_tree_view_context_menu (ThunarTreeView *view, { /* append the "Mount Volume" menu action */ item = gtk_image_menu_item_new_with_mnemonic (_("_Mount Volume")); - gtk_widget_set_sensitive (item, !thunar_vfs_volume_is_mounted (volume)); + gtk_widget_set_sensitive (item, !thunar_g_volume_is_mounted (volume)); g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_tree_view_action_mount), view); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* check if the volume is ejectable */ - if (thunar_vfs_volume_is_ejectable (volume)) + if (thunar_g_volume_is_removable (volume)) { /* append the "Eject Volume" menu action */ item = gtk_image_menu_item_new_with_mnemonic (_("E_ject Volume")); @@ -1101,15 +1130,6 @@ thunar_tree_view_context_menu (ThunarTreeView *view, gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); } - else - { - /* append the "Unmount Volume" menu item */ - item = gtk_image_menu_item_new_with_mnemonic (_("_Unmount Volume")); - gtk_widget_set_sensitive (item, thunar_vfs_volume_is_mounted (volume)); - g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_tree_view_action_unmount), view); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show (item); - } /* append a menu separator */ item = gtk_separator_menu_item_new (); @@ -1339,7 +1359,7 @@ thunar_tree_view_get_dest_actions (ThunarTreeView *view, if (G_LIKELY (file != NULL)) { /* check if the file accepts the drop */ - actions = thunar_file_accepts_drop (file, view->drop_path_list, context, &action); + actions = thunar_file_accepts_drop (file, view->drop_file_list, context, &action); if (G_UNLIKELY (actions == 0)) { /* reset file */ @@ -1462,6 +1482,12 @@ thunar_tree_view_get_selected_file (ThunarTreeView *view) /* determine file for the selected row */ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); + + /* avoid dealing with invalid selections (may occur when the mount_finish() + * handler is called and the tree view has been hidden already) */ + if (!GTK_IS_TREE_SELECTION (selection)) + return NULL; + if (gtk_tree_selection_get_selected (selection, &model, &iter)) gtk_tree_model_get (model, &iter, THUNAR_TREE_MODEL_COLUMN_FILE, &file, -1); @@ -1470,11 +1496,11 @@ thunar_tree_view_get_selected_file (ThunarTreeView *view) -static ThunarVfsVolume* +static GVolume* thunar_tree_view_get_selected_volume (ThunarTreeView *view) { GtkTreeSelection *selection; - ThunarVfsVolume *volume = NULL; + GVolume *volume = NULL; GtkTreeModel *model; GtkTreeIter iter; @@ -1522,12 +1548,10 @@ thunar_tree_view_action_copy (ThunarTreeView *view) static void thunar_tree_view_action_create_folder (ThunarTreeView *view) { - ThunarVfsMimeDatabase *mime_database; - ThunarVfsMimeInfo *mime_info; - ThunarApplication *application; - ThunarFile *directory; - GList path_list; - gchar *name; + ThunarApplication *application; + ThunarFile *directory; + GList path_list; + gchar *name; _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); @@ -1536,16 +1560,15 @@ thunar_tree_view_action_create_folder (ThunarTreeView *view) if (G_UNLIKELY (directory == NULL)) return; - /* lookup "inode/directory" mime info */ - mime_database = thunar_vfs_mime_database_get_default (); - mime_info = thunar_vfs_mime_database_get_info (mime_database, "inode/directory"); - /* ask the user to enter a name for the new folder */ - name = thunar_show_create_dialog (GTK_WIDGET (view), mime_info, _("New Folder"), _("Create New Folder")); + name = thunar_show_create_dialog (GTK_WIDGET (view), + "inode/directory", + _("New Folder"), + _("Create New Folder")); if (G_LIKELY (name != NULL)) { /* fake the path list */ - path_list.data = thunar_vfs_path_relative (thunar_file_get_path (directory), name); + path_list.data = g_file_resolve_relative_path (thunar_file_get_file (directory), name); path_list.next = path_list.prev = NULL; /* launch the operation */ @@ -1554,15 +1577,13 @@ thunar_tree_view_action_create_folder (ThunarTreeView *view) g_object_unref (G_OBJECT (application)); /* release the path */ - thunar_vfs_path_unref (path_list.data); + g_object_unref (path_list.data); /* release the file name */ g_free (name); } /* cleanup */ - g_object_unref (G_OBJECT (mime_database)); - thunar_vfs_mime_info_unref (mime_info); g_object_unref (G_OBJECT (directory)); } @@ -1629,11 +1650,48 @@ thunar_tree_view_action_delete (ThunarTreeView *view) +static void +thunar_tree_view_rename_error (ExoJob *job, + GError *error, + ThunarTreeView *view) +{ + GValueArray *param_values; + ThunarFile *file; + + _thunar_return_if_fail (EXO_IS_JOB (job)); + _thunar_return_if_fail (error != NULL); + _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); + + param_values = thunar_simple_job_get_param_values (THUNAR_SIMPLE_JOB (job)); + file = g_value_get_object (g_value_array_get_nth (param_values, 0)); + + /* display an error message */ + thunar_dialogs_show_error (GTK_WIDGET (view), error, _("Failed to rename \"%s\""), + thunar_file_get_display_name (file)); +} + + + +static void +thunar_tree_view_rename_finished (ExoJob *job, + ThunarTreeView *view) +{ + _thunar_return_if_fail (EXO_IS_JOB (job)); + _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); + + /* destroy the job */ + g_signal_handlers_disconnect_matched (job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, view); + g_object_unref (job); +} + + + static void thunar_tree_view_action_rename (ThunarTreeView *view) { ThunarFile *file; GtkWidget *window; + ThunarJob *job; _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); @@ -1645,21 +1703,99 @@ thunar_tree_view_action_rename (ThunarTreeView *view) window = gtk_widget_get_toplevel (GTK_WIDGET (view)); /* run the rename dialog */ - thunar_dialogs_show_rename_file (GTK_WINDOW (window), file); + job = thunar_dialogs_show_rename_file (GTK_WINDOW (window), file); + if (G_LIKELY (job != NULL)) + { + g_signal_connect (job, "error", G_CALLBACK (thunar_tree_view_rename_error), view); + g_signal_connect (job, "finished", G_CALLBACK (thunar_tree_view_rename_finished), view); + } /* release the file */ - g_object_unref (G_OBJECT (file)); + g_object_unref (file); } } +static void +thunar_tree_view_action_eject_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + ThunarTreeView *view = THUNAR_TREE_VIEW (user_data); + GtkWidget *window; + GVolume *volume = G_VOLUME (object); + GError *error = NULL; + gchar *volume_name; + + _thunar_return_if_fail (G_IS_VOLUME (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); + + /* check if there was an error */ + if (!g_volume_eject_finish (volume, result, &error)) + { + /* ignore GIO errors already handled */ + if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_FAILED_HANDLED) + { + window = gtk_widget_get_toplevel (GTK_WIDGET (view)); + + /* display an error dialog to inform the user */ + volume_name = g_volume_get_name (volume); + thunar_dialogs_show_error (window, error, _("Failed to eject \"%s\""), volume_name); + g_free (volume_name); + + g_error_free (error); + } + } + + g_object_unref (view); +} + + + +static void +thunar_tree_view_action_unmount_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + ThunarTreeView *view = THUNAR_TREE_VIEW (user_data); + GtkWidget *window; + GMount *mount = G_MOUNT (object); + GError *error = NULL; + gchar *mount_name; + + _thunar_return_if_fail (G_IS_MOUNT (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); + + /* check if there was an error */ + if (!g_mount_unmount_finish (mount, result, &error)) + { + /* ignore GIO errors already handled */ + if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_FAILED_HANDLED) + { + window = gtk_widget_get_toplevel (GTK_WIDGET (view)); + + /* display an error dialog to inform the user */ + mount_name = g_mount_get_name (mount); + thunar_dialogs_show_error (window, error, _("Failed to eject \"%s\""), mount_name); + g_free (mount_name); + + g_error_free (error); + } + } + + g_object_unref (view); +} + + + static void thunar_tree_view_action_eject (ThunarTreeView *view) { - ThunarVfsVolume *volume; - GtkWidget *window; - GError *error = NULL; + GVolume *volume; + GMount *mount; _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); @@ -1667,19 +1803,32 @@ thunar_tree_view_action_eject (ThunarTreeView *view) volume = thunar_tree_view_get_selected_volume (view); if (G_LIKELY (volume != NULL)) { - /* determine the toplevel window */ - window = gtk_widget_get_toplevel (GTK_WIDGET (view)); - - /* try to eject the volume */ - if (!thunar_vfs_volume_eject (volume, window, &error)) + /* determine what the appropriate method is: eject or unmount */ + if (g_volume_can_eject (volume)) { - /* display an error dialog to inform the user */ - thunar_dialogs_show_error (window, error, _("Failed to eject \"%s\""), thunar_vfs_volume_get_name (volume)); - g_error_free (error); + /* try to to eject the volume asynchronously */ + g_volume_eject (volume, G_MOUNT_UNMOUNT_NONE, NULL, + thunar_tree_view_action_eject_finish, + g_object_ref (view)); + } + else + { + /* determine the mount of the volume */ + mount = g_volume_get_mount (volume); + if (G_LIKELY (mount != NULL)) + { + /* the volume is mounted, try to unmount the mount */ + g_mount_unmount (mount, G_MOUNT_UNMOUNT_NONE, NULL, + thunar_tree_view_action_unmount_finish, + g_object_ref (view)); + + /* release the mount */ + g_object_unref (mount); + } } /* release the volume */ - g_object_unref (G_OBJECT (volume)); + g_object_unref (volume); } } @@ -1700,41 +1849,109 @@ thunar_tree_view_action_empty_trash (ThunarTreeView *view) -static gboolean +static void thunar_tree_view_action_mount (ThunarTreeView *view) { - ThunarVfsVolume *volume; - GtkWidget *window; - gboolean result = TRUE; - GError *error = NULL; + _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); + thunar_tree_view_mount (view, FALSE, FALSE); +} - _thunar_return_val_if_fail (THUNAR_IS_TREE_VIEW (view), FALSE); + + +static void +thunar_tree_view_mount_finish (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + ThunarTreeViewMountData *data = user_data; + GtkWidget *window; + GVolume *volume = G_VOLUME (object); + GError *error = NULL; + gchar *volume_name; + + _thunar_return_if_fail (G_IS_VOLUME (object)); + _thunar_return_if_fail (G_IS_ASYNC_RESULT (result)); + _thunar_return_if_fail (data != NULL && THUNAR_IS_TREE_VIEW (data->view)); + + /* check if there was an error */ + if (!g_volume_mount_finish (volume, result, &error)) + { + /* ignore GIO already handled errors or errors due to pending mount actions */ + if (error->domain != G_IO_ERROR + || (error->code != G_IO_ERROR_FAILED_HANDLED + && error->code != G_IO_ERROR_ALREADY_MOUNTED + && error->code != G_IO_ERROR_PENDING)) + { + window = gtk_widget_get_toplevel (GTK_WIDGET (data->view)); + + /* display an error dialog to inform the user */ + volume_name = g_volume_get_name (volume); + thunar_dialogs_show_error (window, error, _("Failed to mount \"%s\""), volume_name); + g_free (volume_name); + + /* free the error */ + g_error_free (error); + } + } + else + { + if (G_LIKELY (data->open_after_mounting)) + { + if (data->open_in_new_window) + thunar_tree_view_open_selection_in_new_window (data->view); + else + thunar_tree_view_open_selection (data->view); + } + else if (data->path != NULL) + { + gtk_tree_view_expand_row (GTK_TREE_VIEW (data->view), data->path, FALSE); + } + } + + thunar_tree_view_mount_data_free (data); +} + + + +static void +thunar_tree_view_mount (ThunarTreeView *view, + gboolean open_after_mounting, + gboolean open_in_new_window) +{ + ThunarTreeViewMountData *data; + GMountOperation *mount_operation; + GtkWidget *window; + GVolume *volume; + + _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); /* determine the selected volume */ volume = thunar_tree_view_get_selected_volume (view); - if (G_UNLIKELY (volume != NULL)) + if (volume != NULL) { - /* check if the volume is not already mounted */ - if (!thunar_vfs_volume_is_mounted (volume)) + /* check if we need to mount the volume at all */ + if (!thunar_g_volume_is_mounted (volume)) { - /* determine the toplevel window */ + /* allocate mount data */ + data = thunar_tree_view_mount_data_new (view, NULL, open_after_mounting, + open_in_new_window); + + /* allocate a GTK+ mount operation */ window = gtk_widget_get_toplevel (GTK_WIDGET (view)); + mount_operation = gtk_mount_operation_new (GTK_WINDOW (window)); - /* try to mount the volume */ - result = thunar_vfs_volume_mount (volume, window, &error); - if (G_UNLIKELY (!result)) - { - /* display an error dialog to inform the user */ - thunar_dialogs_show_error (window, error, _("Failed to mount \"%s\""), thunar_vfs_volume_get_name (volume)); - g_error_free (error); - } + /* try to mount the volume and expand the row on success. the + * data is destroyed in the finish callback */ + g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_operation, NULL, + thunar_tree_view_mount_finish, data); + + /* release the mount operation */ + g_object_unref (mount_operation); } /* release the volume */ - g_object_unref (G_OBJECT (volume)); + g_object_unref (volume); } - - return result; } @@ -1743,12 +1960,38 @@ static void thunar_tree_view_action_open (ThunarTreeView *view) { ThunarFile *file; + GVolume *volume; _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); - /* if its a volume, make sure its mounted */ - if (!thunar_tree_view_action_mount (view)) - return; + /* determine the selected volume and file */ + volume = thunar_tree_view_get_selected_volume (view); + file = thunar_tree_view_get_selected_file (view); + + if (volume != NULL) + { + if (thunar_g_volume_is_mounted (volume)) + thunar_tree_view_open_selection (view); + else + thunar_tree_view_mount (view, TRUE, FALSE); + + g_object_unref (volume); + } + else if (file != NULL) + { + thunar_tree_view_open_selection (view); + g_object_unref (file); + } +} + + + +static void +thunar_tree_view_open_selection (ThunarTreeView *view) +{ + ThunarFile *file; + + _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); /* determine the selected file */ file = thunar_tree_view_get_selected_file (view); @@ -1756,7 +1999,7 @@ thunar_tree_view_action_open (ThunarTreeView *view) { /* open that folder in the main view */ thunar_navigator_change_directory (THUNAR_NAVIGATOR (view), file); - g_object_unref (G_OBJECT (file)); + g_object_unref (file); } } @@ -1764,25 +2007,52 @@ thunar_tree_view_action_open (ThunarTreeView *view) static void thunar_tree_view_action_open_in_new_window (ThunarTreeView *view) +{ + ThunarFile *file; + GVolume *volume; + + _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); + + /* determine the selected volume and file */ + volume = thunar_tree_view_get_selected_volume (view); + file = thunar_tree_view_get_selected_file (view); + + if (volume != NULL) + { + if (thunar_g_volume_is_mounted (volume)) + thunar_tree_view_open_selection_in_new_window (view); + else + thunar_tree_view_mount (view, TRUE, FALSE); + + g_object_unref (volume); + } + else if (file != NULL) + { + thunar_tree_view_open_selection_in_new_window (view); + g_object_unref (file); + } +} + + + +static void +thunar_tree_view_open_selection_in_new_window (ThunarTreeView *view) { ThunarApplication *application; ThunarFile *file; _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); - /* if its a volume, make sure its mounted */ - if (!thunar_tree_view_action_mount (view)) - return; - /* determine the selected file */ file = thunar_tree_view_get_selected_file (view); if (G_LIKELY (file != NULL)) { /* open a new window for the selected folder */ application = thunar_application_get (); - thunar_application_open_window (application, file, gtk_widget_get_screen (GTK_WIDGET (view))); - g_object_unref (G_OBJECT (application)); - g_object_unref (G_OBJECT (file)); + thunar_application_open_window (application, file, + gtk_widget_get_screen (GTK_WIDGET (view)), NULL); + g_object_unref (application); + g_object_unref (file); } } @@ -1804,7 +2074,7 @@ thunar_tree_view_action_paste_into_folder (ThunarTreeView *view) if (G_LIKELY (file != NULL)) { /* paste the files from the clipboard to the selected folder */ - thunar_clipboard_manager_paste_files (view->clipboard, thunar_file_get_path (file), GTK_WIDGET (view), NULL); + thunar_clipboard_manager_paste_files (view->clipboard, thunar_file_get_file (file), GTK_WIDGET (view), NULL); /* release the file reference */ g_object_unref (G_OBJECT (file)); @@ -1845,37 +2115,6 @@ thunar_tree_view_action_properties (ThunarTreeView *view) -static void -thunar_tree_view_action_unmount (ThunarTreeView *view) -{ - ThunarVfsVolume *volume; - GtkWidget *window; - GError *error = NULL; - - _thunar_return_if_fail (THUNAR_IS_TREE_VIEW (view)); - - /* determine the selected volume */ - volume = thunar_tree_view_get_selected_volume (view); - if (G_LIKELY (volume != NULL)) - { - /* determine the toplevel window */ - window = gtk_widget_get_toplevel (GTK_WIDGET (view)); - - /* try to unmount the volume */ - if (!thunar_vfs_volume_unmount (volume, window, &error)) - { - /* display an error dialog */ - thunar_dialogs_show_error (window, error, _("Failed to unmount \"%s\""), thunar_vfs_volume_get_name (volume)); - g_error_free (error); - } - - /* release the volume */ - g_object_unref (G_OBJECT (volume)); - } -} - - - static GClosure* thunar_tree_view_new_files_closure (ThunarTreeView *view) { @@ -1898,7 +2137,7 @@ thunar_tree_view_new_files_closure (ThunarTreeView *view) static void -thunar_tree_view_new_files (ThunarVfsJob *job, +thunar_tree_view_new_files (ThunarJob *job, GList *path_list, ThunarTreeView *view) { @@ -1950,13 +2189,13 @@ thunar_tree_view_selection_func (GtkTreeSelection *selection, gboolean path_currently_selected, gpointer user_data) { - ThunarVfsVolume *volume; - GtkTreeIter iter; - ThunarFile *file; - gboolean result = FALSE; + GtkTreeIter iter; + ThunarFile *file; + gboolean result = FALSE; + GVolume *volume; /* every row may be unselected at any time */ - if (G_UNLIKELY (path_currently_selected)) + if (path_currently_selected) return TRUE; /* determine the iterator for the path */ @@ -1970,7 +2209,7 @@ thunar_tree_view_selection_func (GtkTreeSelection *selection, result = TRUE; /* release file */ - g_object_unref (G_OBJECT (file)); + g_object_unref (file); } else { @@ -1982,7 +2221,7 @@ thunar_tree_view_selection_func (GtkTreeSelection *selection, result = TRUE; /* release volume */ - g_object_unref (G_OBJECT (volume)); + g_object_unref (volume); } } } @@ -2071,11 +2310,9 @@ thunar_tree_view_drag_scroll_timer (gpointer user_data) { ThunarTreeView *view = THUNAR_TREE_VIEW (user_data); GtkAdjustment *vadjustment; -#if GTK_CHECK_VERSION(2,8,0) GtkTreePath *start_path; GtkTreePath *end_path; GtkTreePath *path; -#endif gfloat value; gint offset; gint y, h; @@ -2109,7 +2346,6 @@ thunar_tree_view_drag_scroll_timer (gpointer user_data) /* apply the new value */ gtk_adjustment_set_value (vadjustment, value); -#if GTK_CHECK_VERSION(2,8,0) /* drop any pending expand timer source, as its confusing * if a path is expanded while scrolling through the view. * reschedule it if the drag dest path is still visible. @@ -2144,7 +2380,6 @@ thunar_tree_view_drag_scroll_timer (gpointer user_data) gtk_tree_path_free (end_path); } } -#endif } } } @@ -2200,6 +2435,38 @@ thunar_tree_view_expand_timer_destroy (gpointer user_data) +static ThunarTreeViewMountData * +thunar_tree_view_mount_data_new (ThunarTreeView *view, + GtkTreePath *path, + gboolean open_after_mounting, + gboolean open_in_new_window) +{ + ThunarTreeViewMountData *data; + + data = _thunar_slice_new0 (ThunarTreeViewMountData); + data->path = path == NULL ? NULL : gtk_tree_path_copy (path); + data->view = g_object_ref (view); + data->open_after_mounting = open_after_mounting; + data->open_in_new_window = open_in_new_window; + + return data; +} + + + +static void +thunar_tree_view_mount_data_free (ThunarTreeViewMountData *data) +{ + _thunar_return_if_fail (data != NULL && THUNAR_IS_TREE_VIEW (data->view)); + + if (data->path != NULL) + gtk_tree_path_free (data->path); + g_object_unref (data->view); + _thunar_slice_free (ThunarTreeViewMountData, data); +} + + + /** * thunar_tree_view_new: * diff --git a/thunar-vfs/thunar-vfs-user.c b/thunar/thunar-user.c similarity index 51% rename from thunar-vfs/thunar-vfs-user.c rename to thunar/thunar-user.c index eab6d2126..0d1be62c7 100644 --- a/thunar-vfs/thunar-vfs-user.c +++ b/thunar/thunar-user.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -45,57 +46,59 @@ #include <unistd.h> #endif -#include <thunar-vfs/thunar-vfs-private.h> -#include <thunar-vfs/thunar-vfs-user.h> -#include <thunar-vfs/thunar-vfs-alias.h> +#include <glib-object.h> + +#include <exo/exo.h> + +#include <thunar/thunar-user.h> /* the interval in which the user/group cache is flushed (in ms) */ -#define THUNAR_VFS_USER_MANAGER_FLUSH_INTERVAL (10 * 60 * 1000) +#define THUNAR_USER_MANAGER_FLUSH_INTERVAL (10 * 60 * 1000) -static void thunar_vfs_group_class_init (ThunarVfsGroupClass *klass); -static void thunar_vfs_group_finalize (GObject *object); -static ThunarVfsGroup *thunar_vfs_group_new (ThunarVfsGroupId id); +static void thunar_group_class_init (ThunarGroupClass *klass); +static void thunar_group_finalize (GObject *object); +static ThunarGroup *thunar_group_new (guint32 id); -struct _ThunarVfsGroupClass +struct _ThunarGroupClass { GObjectClass __parent__; }; -struct _ThunarVfsGroup +struct _ThunarGroup { GObject __parent__; - ThunarVfsGroupId id; - gchar *name; + guint32 id; + gchar *name; }; -static GObjectClass *thunar_vfs_group_parent_class; +static GObjectClass *thunar_group_parent_class; GType -thunar_vfs_group_get_type (void) +thunar_group_get_type (void) { static GType type = G_TYPE_INVALID; if (G_UNLIKELY (type == G_TYPE_INVALID)) { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsGroup", - sizeof (ThunarVfsGroupClass), - thunar_vfs_group_class_init, - sizeof (ThunarVfsGroup), - NULL, - 0); + type = g_type_register_static_simple (G_TYPE_OBJECT, + "ThunarGroup", + sizeof (ThunarGroupClass), + (GClassInitFunc) thunar_group_class_init, + sizeof (ThunarGroup), + NULL, + 0); } return type; @@ -104,38 +107,38 @@ thunar_vfs_group_get_type (void) static void -thunar_vfs_group_class_init (ThunarVfsGroupClass *klass) +thunar_group_class_init (ThunarGroupClass *klass) { GObjectClass *gobject_class; /* determine the parent class */ - thunar_vfs_group_parent_class = g_type_class_peek_parent (klass); + thunar_group_parent_class = g_type_class_peek_parent (klass); gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_group_finalize; + gobject_class->finalize = thunar_group_finalize; } static void -thunar_vfs_group_finalize (GObject *object) +thunar_group_finalize (GObject *object) { - ThunarVfsGroup *group = THUNAR_VFS_GROUP (object); + ThunarGroup *group = THUNAR_GROUP (object); /* release the group's name */ g_free (group->name); - (*G_OBJECT_CLASS (thunar_vfs_group_parent_class)->finalize) (object); + (*G_OBJECT_CLASS (thunar_group_parent_class)->finalize) (object); } -static ThunarVfsGroup* -thunar_vfs_group_new (ThunarVfsGroupId id) +static ThunarGroup* +thunar_group_new (guint32 id) { - ThunarVfsGroup *group; + ThunarGroup *group; - group = g_object_new (THUNAR_VFS_TYPE_GROUP, NULL); + group = g_object_new (THUNAR_TYPE_GROUP, NULL); group->id = id; return group; @@ -144,25 +147,25 @@ thunar_vfs_group_new (ThunarVfsGroupId id) /** - * thunar_vfs_group_get_id: - * @group : a #ThunarVfsGroup. + * thunar_group_get_id: + * @group : a #ThunarGroup. * * Returns the unique id of the given @group. * * Return value: the unique id of @group. **/ -ThunarVfsGroupId -thunar_vfs_group_get_id (ThunarVfsGroup *group) +guint32 +thunar_group_get_id (ThunarGroup *group) { - g_return_val_if_fail (THUNAR_VFS_IS_GROUP (group), 0); + g_return_val_if_fail (THUNAR_IS_GROUP (group), 0); return group->id; } /** - * thunar_vfs_group_get_name: - * @group : a #ThunarVfsGroup. + * thunar_group_get_name: + * @group : a #ThunarGroup. * * Returns the name of the @group. If the system is * unable to determine the name of @group, it'll @@ -171,11 +174,11 @@ thunar_vfs_group_get_id (ThunarVfsGroup *group) * Return value: the name of @group. **/ const gchar* -thunar_vfs_group_get_name (ThunarVfsGroup *group) +thunar_group_get_name (ThunarGroup *group) { struct group *grp; - g_return_val_if_fail (THUNAR_VFS_IS_GROUP (group), NULL); + g_return_val_if_fail (THUNAR_IS_GROUP (group), NULL); /* determine the name on-demand */ if (G_UNLIKELY (group->name == NULL)) @@ -193,50 +196,50 @@ thunar_vfs_group_get_name (ThunarVfsGroup *group) -static void thunar_vfs_user_class_init (ThunarVfsUserClass *klass); -static void thunar_vfs_user_finalize (GObject *object); -static void thunar_vfs_user_load (ThunarVfsUser *user); -static ThunarVfsUser *thunar_vfs_user_new (ThunarVfsUserId id); +static void thunar_user_class_init (ThunarUserClass *klass); +static void thunar_user_finalize (GObject *object); +static void thunar_user_load (ThunarUser *user); +static ThunarUser *thunar_user_new (guint32 id); -struct _ThunarVfsUserClass +struct _ThunarUserClass { GObjectClass __parent__; }; -struct _ThunarVfsUser +struct _ThunarUser { GObject __parent__; - GList *groups; - ThunarVfsGroup *primary_group; - ThunarVfsUserId id; - gchar *name; - gchar *real_name; + GList *groups; + ThunarGroup *primary_group; + guint32 id; + gchar *name; + gchar *real_name; }; -static ThunarVfsUserId thunar_vfs_user_effective_uid; -static GObjectClass *thunar_vfs_user_parent_class; +static guint32 thunar_user_effective_uid; +static GObjectClass *thunar_user_parent_class; GType -thunar_vfs_user_get_type (void) +thunar_user_get_type (void) { static GType type = G_TYPE_INVALID; if (G_UNLIKELY (type == G_TYPE_INVALID)) { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsUser", - sizeof (ThunarVfsUserClass), - thunar_vfs_user_class_init, - sizeof (ThunarVfsUser), - NULL, - 0); + type = g_type_register_static_simple (G_TYPE_OBJECT, + "ThunarUser", + sizeof (ThunarUserClass), + (GClassInitFunc) thunar_user_class_init, + sizeof (ThunarUser), + NULL, + 0); } return type; @@ -245,29 +248,29 @@ thunar_vfs_user_get_type (void) static void -thunar_vfs_user_class_init (ThunarVfsUserClass *klass) +thunar_user_class_init (ThunarUserClass *klass) { GObjectClass *gobject_class; /* determine the parent class */ - thunar_vfs_user_parent_class = g_type_class_peek_parent (klass); + thunar_user_parent_class = g_type_class_peek_parent (klass); /* determine the current process' effective user id, we do * this only once to avoid the syscall overhead on every * is_me() invokation. */ - thunar_vfs_user_effective_uid = geteuid (); + thunar_user_effective_uid = geteuid (); gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_user_finalize; + gobject_class->finalize = thunar_user_finalize; } static void -thunar_vfs_user_finalize (GObject *object) +thunar_user_finalize (GObject *object) { - ThunarVfsUser *user = THUNAR_VFS_USER (object); + ThunarUser *user = THUNAR_USER (object); /* unref the associated groups */ g_list_foreach (user->groups, (GFunc) g_object_unref, NULL); @@ -281,30 +284,30 @@ thunar_vfs_user_finalize (GObject *object) g_free (user->real_name); g_free (user->name); - (*G_OBJECT_CLASS (thunar_vfs_user_parent_class)->finalize) (object); + (*G_OBJECT_CLASS (thunar_user_parent_class)->finalize) (object); } static void -thunar_vfs_user_load (ThunarVfsUser *user) +thunar_user_load (ThunarUser *user) { - ThunarVfsUserManager *manager; - struct passwd *pw; - const gchar *s; - gchar *name; - gchar *t; + ThunarUserManager *manager; + struct passwd *pw; + const gchar *s; + gchar *name; + gchar *t; g_return_if_fail (user->name == NULL); pw = getpwuid (user->id); if (G_LIKELY (pw != NULL)) { - manager = thunar_vfs_user_manager_get_default (); + manager = thunar_user_manager_get_default (); /* query name and primary group */ user->name = g_strdup (pw->pw_name); - user->primary_group = thunar_vfs_user_manager_get_group_by_id (manager, pw->pw_gid); + user->primary_group = thunar_user_manager_get_group_by_id (manager, pw->pw_gid); /* try to figure out the real name */ s = strchr (pw->pw_gecos, ','); @@ -339,12 +342,12 @@ thunar_vfs_user_load (ThunarVfsUser *user) -static ThunarVfsUser* -thunar_vfs_user_new (ThunarVfsUserId id) +static ThunarUser* +thunar_user_new (guint32 id) { - ThunarVfsUser *user; + ThunarUser *user; - user = g_object_new (THUNAR_VFS_TYPE_USER, NULL); + user = g_object_new (THUNAR_TYPE_USER, NULL); user->id = id; return user; @@ -353,11 +356,11 @@ thunar_vfs_user_new (ThunarVfsUserId id) /** - * thunar_vfs_user_get_groups: - * @user : a #ThunarVfsUser. + * thunar_user_get_groups: + * @user : a #ThunarUser. * - * Returns all #ThunarVfsGroup<!---->s that @user - * belongs to. The returned list and the #ThunarVfsGroup<!---->s + * Returns all #ThunarGroup<!---->s that @user + * belongs to. The returned list and the #ThunarGroup<!---->s * contained within the list are owned by @user and must not be * freed or altered by the caller. * @@ -367,36 +370,36 @@ thunar_vfs_user_new (ThunarVfsUserId id) * Return value: the groups that @user belongs to. **/ GList* -thunar_vfs_user_get_groups (ThunarVfsUser *user) +thunar_user_get_groups (ThunarUser *user) { - ThunarVfsUserManager *manager; - ThunarVfsGroup *primary_group; - ThunarVfsGroup *group; - gid_t gidset[NGROUPS_MAX]; - gint gidsetlen; - gint n; + ThunarUserManager *manager; + ThunarGroup *primary_group; + ThunarGroup *group; + gid_t gidset[NGROUPS_MAX]; + gint gidsetlen; + gint n; - g_return_val_if_fail (THUNAR_VFS_IS_USER (user), NULL); + g_return_val_if_fail (THUNAR_IS_USER (user), NULL); /* load the groups on-demand */ if (G_UNLIKELY (user->groups == NULL)) { - primary_group = thunar_vfs_user_get_primary_group (user); + primary_group = thunar_user_get_primary_group (user); /* we can only determine the groups list for the current * process owner in a portable fashion, and in fact, we * only need the list for the current user. */ - if (thunar_vfs_user_is_me (user)) + if (thunar_user_is_me (user)) { - manager = thunar_vfs_user_manager_get_default (); + manager = thunar_user_manager_get_default (); /* add all supplementary groups */ gidsetlen = getgroups (G_N_ELEMENTS (gidset), gidset); for (n = 0; n < gidsetlen; ++n) - if (primary_group == NULL || thunar_vfs_group_get_id (primary_group) != gidset[n]) + if (primary_group == NULL || thunar_group_get_id (primary_group) != gidset[n]) { - group = thunar_vfs_user_manager_get_group_by_id (manager, gidset[n]); + group = thunar_user_manager_get_group_by_id (manager, gidset[n]); if (G_LIKELY (group != NULL)) user->groups = g_list_append (user->groups, group); } @@ -418,8 +421,8 @@ thunar_vfs_user_get_groups (ThunarVfsUser *user) /** - * thunar_vfs_user_get_primary_group: - * @user : a #ThunarVfsUser. + * thunar_user_get_primary_group: + * @user : a #ThunarUser. * * Returns the primary group of @user or %NULL if @user * has no primary group. @@ -429,14 +432,14 @@ thunar_vfs_user_get_groups (ThunarVfsUser *user) * * Return value: the primary group of @user or %NULL. **/ -ThunarVfsGroup* -thunar_vfs_user_get_primary_group (ThunarVfsUser *user) +ThunarGroup* +thunar_user_get_primary_group (ThunarUser *user) { - g_return_val_if_fail (THUNAR_VFS_IS_USER (user), NULL); + g_return_val_if_fail (THUNAR_IS_USER (user), NULL); /* load the user data on-demand */ if (G_UNLIKELY (user->name == NULL)) - thunar_vfs_user_load (user); + thunar_user_load (user); return user->primary_group; } @@ -444,25 +447,25 @@ thunar_vfs_user_get_primary_group (ThunarVfsUser *user) /** - * thunar_vfs_user_get_id: - * @user : a #ThunarVfsUser. + * thunar_user_get_id: + * @user : a #ThunarUser. * * Returns the unique id of @user. * * Return value: the unique id of @user. **/ -ThunarVfsUserId -thunar_vfs_user_get_id (ThunarVfsUser *user) +guint32 +thunar_user_get_id (ThunarUser *user) { - g_return_val_if_fail (THUNAR_VFS_IS_USER (user), 0); + g_return_val_if_fail (THUNAR_IS_USER (user), 0); return user->id; } /** - * thunar_vfs_user_get_name: - * @user : a #ThunarVfsUser. + * thunar_user_get_name: + * @user : a #ThunarUser. * * Returns the name of @user. If the system is * unable to determine the account name of @user, @@ -471,13 +474,13 @@ thunar_vfs_user_get_id (ThunarVfsUser *user) * Return value: the name of @user. **/ const gchar* -thunar_vfs_user_get_name (ThunarVfsUser *user) +thunar_user_get_name (ThunarUser *user) { - g_return_val_if_fail (THUNAR_VFS_IS_USER (user), 0); + g_return_val_if_fail (THUNAR_IS_USER (user), 0); /* load the user's data on-demand */ if (G_UNLIKELY (user->name == NULL)) - thunar_vfs_user_load (user); + thunar_user_load (user); return user->name; } @@ -485,8 +488,8 @@ thunar_vfs_user_get_name (ThunarVfsUser *user) /** - * thunar_vfs_user_get_real_name: - * @user : a #ThunarVfsUser. + * thunar_user_get_real_name: + * @user : a #ThunarUser. * * Returns the real name of @user or %NULL if the * real name for @user is not known to the underlying @@ -495,13 +498,13 @@ thunar_vfs_user_get_name (ThunarVfsUser *user) * Return value: the real name for @user or %NULL. **/ const gchar* -thunar_vfs_user_get_real_name (ThunarVfsUser *user) +thunar_user_get_real_name (ThunarUser *user) { - g_return_val_if_fail (THUNAR_VFS_IS_USER (user), 0); + g_return_val_if_fail (THUNAR_IS_USER (user), 0); /* load the user's data on-demand */ if (G_UNLIKELY (user->name == NULL)) - thunar_vfs_user_load (user); + thunar_user_load (user); return user->real_name; } @@ -509,8 +512,8 @@ thunar_vfs_user_get_real_name (ThunarVfsUser *user) /** - * thunar_vfs_user_is_me: - * @user : a #ThunarVfsUser. + * thunar_user_is_me: + * @user : a #ThunarUser. * * Checks whether the owner of the current process is * described by @user. @@ -519,29 +522,29 @@ thunar_vfs_user_get_real_name (ThunarVfsUser *user) * process, else %FALSE. **/ gboolean -thunar_vfs_user_is_me (ThunarVfsUser *user) +thunar_user_is_me (ThunarUser *user) { - g_return_val_if_fail (THUNAR_VFS_IS_USER (user), FALSE); - return (user->id == thunar_vfs_user_effective_uid); + g_return_val_if_fail (THUNAR_IS_USER (user), FALSE); + return (user->id == thunar_user_effective_uid); } -static void thunar_vfs_user_manager_class_init (ThunarVfsUserManagerClass *klass); -static void thunar_vfs_user_manager_init (ThunarVfsUserManager *manager); -static void thunar_vfs_user_manager_finalize (GObject *object); -static gboolean thunar_vfs_user_manager_flush_timer (gpointer user_data); -static void thunar_vfs_user_manager_flush_timer_destroy (gpointer user_data); +static void thunar_user_manager_class_init (ThunarUserManagerClass *klass); +static void thunar_user_manager_init (ThunarUserManager *manager); +static void thunar_user_manager_finalize (GObject *object); +static gboolean thunar_user_manager_flush_timer (gpointer user_data); +static void thunar_user_manager_flush_timer_destroy (gpointer user_data); -struct _ThunarVfsUserManagerClass +struct _ThunarUserManagerClass { GObjectClass __parent__; }; -struct _ThunarVfsUserManager +struct _ThunarUserManager { GObject __parent__; @@ -553,24 +556,24 @@ struct _ThunarVfsUserManager -static GObjectClass *thunar_vfs_user_manager_parent_class; +static GObjectClass *thunar_user_manager_parent_class; GType -thunar_vfs_user_manager_get_type (void) +thunar_user_manager_get_type (void) { static GType type = G_TYPE_INVALID; if (G_UNLIKELY (type == G_TYPE_INVALID)) { - type = _thunar_vfs_g_type_register_simple (G_TYPE_OBJECT, - "ThunarVfsUserManager", - sizeof (ThunarVfsUserManagerClass), - thunar_vfs_user_manager_class_init, - sizeof (ThunarVfsUserManager), - thunar_vfs_user_manager_init, - 0); + type = g_type_register_static_simple (G_TYPE_OBJECT, + "ThunarUserManager", + sizeof (ThunarUserManagerClass), + (GClassInitFunc) thunar_user_manager_class_init, + sizeof (ThunarUserManager), + (GInstanceInitFunc) thunar_user_manager_init, + 0); } return type; @@ -579,21 +582,21 @@ thunar_vfs_user_manager_get_type (void) static void -thunar_vfs_user_manager_class_init (ThunarVfsUserManagerClass *klass) +thunar_user_manager_class_init (ThunarUserManagerClass *klass) { GObjectClass *gobject_class; /* determine the parent type class */ - thunar_vfs_user_manager_parent_class = g_type_class_peek_parent (klass); + thunar_user_manager_parent_class = g_type_class_peek_parent (klass); gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = thunar_vfs_user_manager_finalize; + gobject_class->finalize = thunar_user_manager_finalize; } static void -thunar_vfs_user_manager_init (ThunarVfsUserManager *manager) +thunar_user_manager_init (ThunarUserManager *manager) { manager->groups = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); manager->users = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); @@ -609,17 +612,17 @@ thunar_vfs_user_manager_init (ThunarVfsUserManager *manager) #endif /* start the flush timer */ - manager->flush_timer_id = g_timeout_add_full (G_PRIORITY_LOW, THUNAR_VFS_USER_MANAGER_FLUSH_INTERVAL, - thunar_vfs_user_manager_flush_timer, manager, - thunar_vfs_user_manager_flush_timer_destroy); + manager->flush_timer_id = g_timeout_add_full (G_PRIORITY_LOW, THUNAR_USER_MANAGER_FLUSH_INTERVAL, + thunar_user_manager_flush_timer, manager, + thunar_user_manager_flush_timer_destroy); } static void -thunar_vfs_user_manager_finalize (GObject *object) +thunar_user_manager_finalize (GObject *object) { - ThunarVfsUserManager *manager = THUNAR_VFS_USER_MANAGER (object); + ThunarUserManager *manager = THUNAR_USER_MANAGER (object); /* stop the flush timer */ if (G_LIKELY (manager->flush_timer_id >= 0)) @@ -635,16 +638,16 @@ thunar_vfs_user_manager_finalize (GObject *object) /* unload the passwd file */ endpwent (); - (*G_OBJECT_CLASS (thunar_vfs_user_manager_parent_class)->finalize) (object); + (*G_OBJECT_CLASS (thunar_user_manager_parent_class)->finalize) (object); } static gboolean -thunar_vfs_user_manager_flush_timer (gpointer user_data) +thunar_user_manager_flush_timer (gpointer user_data) { - ThunarVfsUserManager *manager = THUNAR_VFS_USER_MANAGER (user_data); - guint size = 0; + ThunarUserManager *manager = THUNAR_USER_MANAGER (user_data); + guint size = 0; GDK_THREADS_ENTER (); @@ -677,30 +680,30 @@ thunar_vfs_user_manager_flush_timer (gpointer user_data) static void -thunar_vfs_user_manager_flush_timer_destroy (gpointer user_data) +thunar_user_manager_flush_timer_destroy (gpointer user_data) { - THUNAR_VFS_USER_MANAGER (user_data)->flush_timer_id = -1; + THUNAR_USER_MANAGER (user_data)->flush_timer_id = -1; } /** - * thunar_vfs_user_manager_get_default: + * thunar_user_manager_get_default: * - * Returns the default #ThunarVfsUserManager instance, which is shared + * Returns the default #ThunarUserManager instance, which is shared * by all modules using the user module. Call g_object_unref() on the * returned object when you are done with it. * - * Return value: the default #ThunarVfsUserManager instance. + * Return value: the default #ThunarUserManager instance. **/ -ThunarVfsUserManager* -thunar_vfs_user_manager_get_default (void) +ThunarUserManager* +thunar_user_manager_get_default (void) { - static ThunarVfsUserManager *manager = NULL; + static ThunarUserManager *manager = NULL; if (G_UNLIKELY (manager == NULL)) { - manager = g_object_new (THUNAR_VFS_TYPE_USER_MANAGER, NULL); + manager = g_object_new (THUNAR_TYPE_USER_MANAGER, NULL); g_object_add_weak_pointer (G_OBJECT (manager), (gpointer) &manager); } else @@ -714,30 +717,30 @@ thunar_vfs_user_manager_get_default (void) /** - * thunar_vfs_user_manager_get_group_by_id: - * @manager : a #ThunarVfsUserManager. + * thunar_user_manager_get_group_by_id: + * @manager : a #ThunarUserManager. * @id : the group id. * - * Looks up the #ThunarVfsGroup corresponding to @id in @manager. Returns - * %NULL if @manager is unable to determine the #ThunarVfsGroup for @id, - * else a pointer to the corresponding #ThunarVfsGroup. The caller is + * Looks up the #ThunarGroup corresponding to @id in @manager. Returns + * %NULL if @manager is unable to determine the #ThunarGroup for @id, + * else a pointer to the corresponding #ThunarGroup. The caller is * responsible for freeing the returned object using g_object_unref(). * - * Return value: the #ThunarVfsGroup corresponding to @id or %NULL. + * Return value: the #ThunarGroup corresponding to @id or %NULL. **/ -ThunarVfsGroup* -thunar_vfs_user_manager_get_group_by_id (ThunarVfsUserManager *manager, - ThunarVfsGroupId id) +ThunarGroup* +thunar_user_manager_get_group_by_id (ThunarUserManager *manager, + guint32 id) { - ThunarVfsGroup *group; + ThunarGroup *group; - g_return_val_if_fail (THUNAR_VFS_IS_USER_MANAGER (manager), NULL); + g_return_val_if_fail (THUNAR_IS_USER_MANAGER (manager), NULL); /* lookup/load the group corresponding to id */ group = g_hash_table_lookup (manager->groups, GINT_TO_POINTER (id)); if (group == NULL) { - group = thunar_vfs_group_new (id); + group = thunar_group_new (id); g_hash_table_insert (manager->groups, GINT_TO_POINTER (id), group); } @@ -750,30 +753,30 @@ thunar_vfs_user_manager_get_group_by_id (ThunarVfsUserManager *manager, /** - * thunar_vfs_user_manager_get_user_by_id: - * @manager : a #ThunarVfsUserManager. + * thunar_user_manager_get_user_by_id: + * @manager : a #ThunarUserManager. * @id : the user id. * - * Looks up the #ThunarVfsUser corresponding to @id in @manager. Returns - * %NULL if @manager is unable to determine the #ThunarVfsUser for @id, - * else a pointer to the corresponding #ThunarVfsUser. The caller is + * Looks up the #ThunarUser corresponding to @id in @manager. Returns + * %NULL if @manager is unable to determine the #ThunarUser for @id, + * else a pointer to the corresponding #ThunarUser. The caller is * responsible for freeing the returned object using g_object_unref(). * - * Return value: the #ThunarVfsUser corresponding to @id or %NULL. + * Return value: the #ThunarUser corresponding to @id or %NULL. **/ -ThunarVfsUser* -thunar_vfs_user_manager_get_user_by_id (ThunarVfsUserManager *manager, - ThunarVfsUserId id) +ThunarUser* +thunar_user_manager_get_user_by_id (ThunarUserManager *manager, + guint32 id) { - ThunarVfsUser *user; + ThunarUser *user; - g_return_val_if_fail (THUNAR_VFS_IS_USER_MANAGER (manager), NULL); + g_return_val_if_fail (THUNAR_IS_USER_MANAGER (manager), NULL); /* lookup/load the user corresponding to id */ user = g_hash_table_lookup (manager->users, GINT_TO_POINTER (id)); if (user == NULL) { - user = thunar_vfs_user_new (id); + user = thunar_user_new (id); g_hash_table_insert (manager->users, GINT_TO_POINTER (id), user); } @@ -786,10 +789,10 @@ thunar_vfs_user_manager_get_user_by_id (ThunarVfsUserManager *manager, /** - * thunar_vfs_user_manager_get_all_groups: - * @manager : a #ThunarVfsUserManager. + * thunar_user_manager_get_all_groups: + * @manager : a #ThunarUserManager. * - * Returns the list of all #ThunarVfsGroup<!---->s in the system + * Returns the list of all #ThunarGroup<!---->s in the system * that are known to the @manager. * * The caller is responsible to free the returned list using: @@ -801,13 +804,13 @@ thunar_vfs_user_manager_get_user_by_id (ThunarVfsUserManager *manager, * Return value: the list of all groups known to the @manager. **/ GList* -thunar_vfs_user_manager_get_all_groups (ThunarVfsUserManager *manager) +thunar_user_manager_get_all_groups (ThunarUserManager *manager) { - ThunarVfsGroup *group; - struct group *grp; - GList *groups = NULL; + ThunarGroup *group; + struct group *grp; + GList *groups = NULL; - g_return_val_if_fail (THUNAR_VFS_IS_USER_MANAGER (manager), NULL); + g_return_val_if_fail (THUNAR_IS_USER_MANAGER (manager), NULL); /* make sure we reload the groups list */ endgrent (); @@ -821,15 +824,10 @@ thunar_vfs_user_manager_get_all_groups (ThunarVfsUserManager *manager) break; /* lookup our version of the group */ - group = thunar_vfs_user_manager_get_group_by_id (manager, grp->gr_gid); + group = thunar_user_manager_get_group_by_id (manager, grp->gr_gid); if (G_LIKELY (group != NULL)) groups = g_list_append (groups, group); } return groups; } - - - -#define __THUNAR_VFS_USER_C__ -#include <thunar-vfs/thunar-vfs-aliasdef.c> diff --git a/thunar/thunar-user.h b/thunar/thunar-user.h new file mode 100644 index 000000000..d0e788696 --- /dev/null +++ b/thunar/thunar-user.h @@ -0,0 +1,88 @@ +/* $Id$ */ +/*- + * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __THUNAR_USER_H__ +#define __THUNAR_USER_H__ + +#include <glib-object.h> + +G_BEGIN_DECLS; + +typedef struct _ThunarGroupClass ThunarGroupClass; +typedef struct _ThunarGroup ThunarGroup; + +#define THUNAR_TYPE_GROUP (thunar_group_get_type ()) +#define THUNAR_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_GROUP, ThunarGroup)) +#define THUNAR_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_GROUP, ThunarGroupClass)) +#define THUNAR_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_GROUP)) +#define THUNAR_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_GROUP)) +#define THUNAR_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_GROUP, ThunarGroupClass)) + +GType thunar_group_get_type (void) G_GNUC_CONST; + +guint32 thunar_group_get_id (ThunarGroup *group); +const gchar *thunar_group_get_name (ThunarGroup *group); + + +typedef struct _ThunarUserClass ThunarUserClass; +typedef struct _ThunarUser ThunarUser; + +#define THUNAR_TYPE_USER (thunar_user_get_type ()) +#define THUNAR_USER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_USER, ThunarUser)) +#define THUNAR_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_USER, ThunarUserClass)) +#define THUNAR_IS_USER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_USER)) +#define THUNAR_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_USER)) +#define THUNAR_USER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_USER, ThunarUserClass)) + +GType thunar_user_get_type (void) G_GNUC_CONST; + +GList *thunar_user_get_groups (ThunarUser *user); +ThunarGroup *thunar_user_get_primary_group (ThunarUser *user); +guint32 thunar_user_get_id (ThunarUser *user); +const gchar *thunar_user_get_name (ThunarUser *user); +const gchar *thunar_user_get_real_name (ThunarUser *user); +gboolean thunar_user_is_me (ThunarUser *user); + + +typedef struct _ThunarUserManagerClass ThunarUserManagerClass; +typedef struct _ThunarUserManager ThunarUserManager; + +#define THUNAR_TYPE_USER_MANAGER (thunar_user_manager_get_type ()) +#define THUNAR_USER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THUNAR_TYPE_USER_MANAGER, ThunarUserManager)) +#define THUNAR_USER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), THUNAR_TYPE_USER_MANAGER, ThunarUserManagerClass)) +#define THUNAR_IS_USER_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THUNAR_TYPE_USER_MANAGER)) +#define THUNAR_IS_USER_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), THUNAR_TYPE_USER_MANAGER)) +#define THUNAR_USER_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THUNAR_TYPE_USER_MANAGER, ThunarUserManagerClass)) + +GType thunar_user_manager_get_type (void) G_GNUC_CONST; + +ThunarUserManager *thunar_user_manager_get_default (void) G_GNUC_WARN_UNUSED_RESULT; + +ThunarGroup *thunar_user_manager_get_group_by_id (ThunarUserManager *manager, + guint32 id) G_GNUC_WARN_UNUSED_RESULT; +ThunarUser *thunar_user_manager_get_user_by_id (ThunarUserManager *manager, + guint32 id) G_GNUC_WARN_UNUSED_RESULT; + +GList *thunar_user_manager_get_all_groups (ThunarUserManager *manager) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; + +G_END_DECLS; + +#endif /* !__THUNAR_USER_H__ */ diff --git a/thunar/thunar-util.c b/thunar/thunar-util.c index 209dc7a10..4c766b6ae 100644 --- a/thunar/thunar-util.c +++ b/thunar/thunar-util.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -21,9 +22,16 @@ #include <config.h> #endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + #ifdef HAVE_MEMORY_H #include <memory.h> #endif +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif @@ -69,9 +77,88 @@ thunar_util_looks_like_an_uri (const gchar *string) +/** + * thunar_util_expand_filename: + * @filename : a local filename. + * @error : return location for errors or %NULL. + * + * Takes a user-typed @filename and expands a tilde at the + * beginning of the @filename. + * + * The caller is responsible to free the returned string using + * g_free() when no longer needed. + * + * Return value: the expanded @filename or %NULL on error. + **/ +gchar * +thunar_util_expand_filename (const gchar *filename, + GError **error) +{ + struct passwd *passwd; + const gchar *replacement; + const gchar *remainder; + const gchar *slash; + gchar *username; + + g_return_val_if_fail (filename != NULL, NULL); + + /* check if we have a valid (non-empty!) filename */ + if (G_UNLIKELY (*filename == '\0')) + { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid path")); + return NULL; + } + + /* check if we start with a '~' */ + if (G_LIKELY (*filename != '~')) + return g_strdup (filename); + + /* examine the remainder of the filename */ + remainder = filename + 1; + + /* if we have only the slash, then we want the home dir */ + if (G_UNLIKELY (*remainder == '\0')) + return g_strdup (xfce_get_homedir ()); + + /* lookup the slash */ + for (slash = remainder; *slash != '\0' && *slash != G_DIR_SEPARATOR; ++slash) + ; + + /* check if a username was given after the '~' */ + if (G_LIKELY (slash == remainder)) + { + /* replace the tilde with the home dir */ + replacement = xfce_get_homedir (); + } + else + { + /* lookup the pwd entry for the username */ + username = g_strndup (remainder, slash - remainder); + passwd = getpwnam (username); + g_free (username); + + /* check if we have a valid entry */ + if (G_UNLIKELY (passwd == NULL)) + { + username = g_strndup (remainder, slash - remainder); + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Unknown user \"%s\""), username); + g_free (username); + return NULL; + } + + /* use the homedir of the specified user */ + replacement = passwd->pw_dir; + } + + /* generate the filename */ + return g_build_filename (replacement, slash, NULL); +} + + + /** * thunar_util_humanize_file_time: - * @file_time : a #ThunarVfsFileTime. + * @file_time : a #guint64 timestamp. * @date_format : the #ThunarDateFormat used to humanize the @file_time. * * Returns a human readable date representation of the specified @@ -82,11 +169,12 @@ thunar_util_looks_like_an_uri (const gchar *string) * according to the @date_format. **/ gchar* -thunar_util_humanize_file_time (ThunarVfsFileTime file_time, - ThunarDateStyle date_style) +thunar_util_humanize_file_time (guint64 file_time, + ThunarDateStyle date_style) { const gchar *date_format; struct tm *tfile; + time_t ftime; GDate dfile; GDate dnow; gint diff; @@ -94,20 +182,17 @@ thunar_util_humanize_file_time (ThunarVfsFileTime file_time, /* check if the file_time is valid */ if (G_LIKELY (file_time != 0)) { + ftime = (time_t) file_time; + /* determine the local file time */ - tfile = localtime (&file_time); + tfile = localtime (&ftime); /* check which style to use to format the time */ if (date_style == THUNAR_DATE_STYLE_SIMPLE || date_style == THUNAR_DATE_STYLE_SHORT) { /* setup the dates for the time values */ -#if GLIB_CHECK_VERSION(2,10,0) - g_date_set_time_t (&dfile, file_time); + g_date_set_time_t (&dfile, (time_t) ftime); g_date_set_time_t (&dnow, time (NULL)); -#else - g_date_set_time (&dfile, (GTime) file_time); - g_date_set_time (&dnow, (GTime) time (NULL)); -#endif /* determine the difference in days */ diff = g_date_get_julian (&dnow) - g_date_get_julian (&dfile); diff --git a/thunar/thunar-util.h b/thunar/thunar-util.h index ecc18b20c..448314a63 100644 --- a/thunar/thunar-util.h +++ b/thunar/thunar-util.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2006-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -20,21 +21,22 @@ #ifndef __THUNAR_UTIL_H__ #define __THUNAR_UTIL_H__ -#include <thunar-vfs/thunar-vfs.h> - #include <thunar/thunar-enum-types.h> G_BEGIN_DECLS; gboolean thunar_util_looks_like_an_uri (const gchar *string) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -gchar *thunar_util_humanize_file_time (ThunarVfsFileTime file_time, - ThunarDateStyle date_style) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +gchar *thunar_util_expand_filename (const gchar *filename, + GError **error); + +gchar *thunar_util_humanize_file_time (guint64 file_time, + ThunarDateStyle date_style) G_GNUC_INTERNAL G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; -GdkScreen *thunar_util_parse_parent (gpointer parent, - GtkWindow **window_return) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; +GdkScreen *thunar_util_parse_parent (gpointer parent, + GtkWindow **window_return) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; -time_t thunar_util_time_from_rfc3339 (const gchar *date_string) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; +time_t thunar_util_time_from_rfc3339 (const gchar *date_string) G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT; G_END_DECLS; diff --git a/thunar/thunar-window.c b/thunar/thunar-window.c index 9367ffe35..ef5421583 100644 --- a/thunar/thunar-window.c +++ b/thunar/thunar-window.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * 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 @@ -31,11 +32,13 @@ #include <gdk/gdkkeysyms.h> #include <thunar/thunar-application.h> +#include <thunar/thunar-browser.h> #include <thunar/thunar-clipboard-manager.h> #include <thunar/thunar-compact-view.h> #include <thunar/thunar-details-view.h> #include <thunar/thunar-dialogs.h> #include <thunar/thunar-shortcuts-pane.h> +#include <thunar/thunar-gio-extensions.h> #include <thunar/thunar-gobject-extensions.h> #include <thunar/thunar-gtk-extensions.h> #include <thunar/thunar-history.h> @@ -60,6 +63,7 @@ #include <glib.h> + /* Property identifiers */ enum { @@ -195,8 +199,8 @@ static void thunar_window_menu_item_deselected (GtkWidget static void thunar_window_notify_loading (ThunarView *view, GParamSpec *pspec, ThunarWindow *window); -static void thunar_window_volume_pre_unmount (ThunarVfsVolumeManager *volume_manager, - ThunarVfsVolume *volume, +static void thunar_window_mount_pre_unmount (GVolumeMonitor *volume_monitor, + GMount *mount, ThunarWindow *window); static gboolean thunar_window_merge_idle (gpointer user_data); static void thunar_window_merge_idle_destroy (gpointer user_data); @@ -235,8 +239,8 @@ struct _ThunarWindow GtkActionGroup *action_group; GtkUIManager *ui_manager; - /* to be able to change folder on "volume-pre-unmount" if required */ - ThunarVfsVolumeManager *volume_manager; + /* to be able to change folder on "mount-pre-unmount" if required */ + GVolumeMonitor *volume_monitor; /* closures for the menu_item_selected()/menu_item_deselected() callbacks */ GClosure *menu_item_selected_closure; @@ -325,37 +329,12 @@ static const GtkToggleActionEntry toggle_action_entries[] = -static GObjectClass *thunar_window_parent_class; -static guint window_signals[LAST_SIGNAL]; - - +static guint window_signals[LAST_SIGNAL]; -GType -thunar_window_get_type (void) -{ - static GType type = G_TYPE_INVALID; - if (G_UNLIKELY (type == G_TYPE_INVALID)) - { - static const GTypeInfo info = - { - sizeof (ThunarWindowClass), - NULL, - NULL, - (GClassInitFunc) thunar_window_class_init, - NULL, - NULL, - sizeof (ThunarWindow), - 0, - (GInstanceInitFunc) thunar_window_init, - NULL, - }; - - type = g_type_register_static (GTK_TYPE_WINDOW, I_("ThunarWindow"), &info, 0); - } - return type; -} +G_DEFINE_TYPE_WITH_CODE (ThunarWindow, thunar_window, GTK_TYPE_WINDOW, + G_IMPLEMENT_INTERFACE (THUNAR_TYPE_BROWSER, NULL)); @@ -366,9 +345,6 @@ thunar_window_class_init (ThunarWindowClass *klass) GtkBindingSet *binding_set; GObjectClass *gobject_class; - /* determine the parent type class */ - thunar_window_parent_class = g_type_class_peek_parent (klass); - gobject_class = G_OBJECT_CLASS (klass); gobject_class->dispose = thunar_window_dispose; gobject_class->finalize = thunar_window_finalize; @@ -610,28 +586,25 @@ view_index2type (gint index) static void thunar_window_setup_user_dir_menu_entries (ThunarWindow *window) { - gint i; static const gchar *callback_names[] = { - "open-desktop", "open-documents", "open-downloads", "open-music", - "open-pictures", "open-public", "open-templates", "open-videos" + "open-desktop", + "open-documents", + "open-downloads", + "open-music", + "open-pictures", + "open-public", + "open-templates", + "open-videos", + NULL }; - -#if !GLIB_CHECK_VERSION(2, 14, 0) - - for (i = 0; i < G_N_ELEMENTS(callback_names); i++) - { - GtkAction *action = gtk_action_group_get_action (window->action_group, - callback_names[i]); - gtk_action_set_visible (GTK_ACTION (action), FALSE); - } - -#else /* GLIB_CHECK_VERSION(2, 14, 0) */ - - gchar *old_locale = NULL; - gchar *locale = NULL; - gchar *translation = NULL; - /* gchar *dir_name = NULL; */ // see below - const gchar *home_dir = NULL; + GtkAction *action; + GFile *home_dir; + GFile *dir; + gchar *locale; + gchar *old_locale; + const gchar *path; + gchar *translation; + gint i; bindtextdomain (XDG_USER_DIRS_PACKAGE, PACKAGE_LOCALE_DIR); #ifdef HAVE_BIND_TEXTDOMAIN_CODESET @@ -646,48 +619,37 @@ thunar_window_setup_user_dir_menu_entries (ThunarWindow *window) setlocale (LC_MESSAGES, locale); g_free (locale); - home_dir = xfce_get_homedir (); + home_dir = thunar_g_file_new_for_home (); - for (i = 0; i < THUNAR_USER_N_DIRECTORIES; i++) + for (i = 0; i < G_USER_N_DIRECTORIES; i++) { - gboolean visible = FALSE; - GtkAction *action = gtk_action_group_get_action (window->action_group, - callback_names[i]); - gchar *path = g_strdup (g_get_user_special_dir (i)); + action = gtk_action_group_get_action (window->action_group, callback_names[i]); + path = g_get_user_special_dir (i); /* special case: got NULL for the templates dir. Force it to ~/Templates */ - if (G_UNLIKELY (path == NULL && i == THUNAR_USER_DIRECTORY_TEMPLATES)) - path = g_build_path (home_dir, _thunar_user_directory_names[i], NULL); - - /* xdg user dirs pointing to $HOME must be considered disabled */ - if (G_LIKELY((path != NULL) && (!exo_str_is_equal (path, home_dir)))) { - ThunarVfsPath *vfs_path = thunar_vfs_path_new (path, NULL); - - if (G_LIKELY(vfs_path != NULL)) - { - visible = TRUE; - thunar_vfs_path_unref (vfs_path); - } - } - - gtk_action_set_visible (GTK_ACTION (action), visible); - - /* if an entry is invisible don't waste time translating it */ - if (G_UNLIKELY (visible == FALSE)) { - g_free (path); + if (G_UNLIKELY (path == NULL && i == G_USER_DIRECTORY_TEMPLATES)) + dir = g_file_resolve_relative_path (home_dir, _thunar_user_directory_names[i]); + else if (path != NULL) + dir = g_file_new_for_path (path); + else continue; - } - /* menu entry label translation */ - translation = dgettext (XDG_USER_DIRS_PACKAGE, (gchar *) _thunar_user_directory_names[i]); - g_object_set (action, "label", translation, NULL); + /* xdg user dirs pointing to $HOME must be considered disabled */ + if (G_LIKELY (path != NULL && !g_file_equal (dir, home_dir))) + { + /* menu entry label translation */ + translation = dgettext (XDG_USER_DIRS_PACKAGE, (gchar *) _thunar_user_directory_names[i]); + g_object_set (action, "label", translation, NULL); + } + else + gtk_action_set_visible (GTK_ACTION (action), FALSE); - g_free (path); + g_object_unref (dir); } - setlocale (LC_MESSAGES, old_locale); + g_object_unref (home_dir); -#endif /* GLIB_CHECK_VERSION(2,14,0) */ + setlocale (LC_MESSAGES, old_locale); } @@ -720,9 +682,9 @@ thunar_window_init (ThunarWindow *window) /* allocate the scroll_to_files mapping */ window->scroll_to_files = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, g_object_unref); - /* connect to the volume manager */ - window->volume_manager = thunar_vfs_volume_manager_get_default (); - g_signal_connect (G_OBJECT (window->volume_manager), "volume-pre-unmount", G_CALLBACK (thunar_window_volume_pre_unmount), window); + /* connect to the volume monitor */ + window->volume_monitor = g_volume_monitor_get (); + g_signal_connect (window->volume_monitor, "mount-pre-unmount", G_CALLBACK (thunar_window_mount_pre_unmount), window); /* allocate a closure for the menu_item_selected() callback */ window->menu_item_selected_closure = g_cclosure_new_object (G_CALLBACK (thunar_window_menu_item_selected), G_OBJECT (window)); @@ -968,24 +930,24 @@ thunar_window_finalize (GObject *object) g_closure_unref (window->menu_item_deselected_closure); g_closure_unref (window->menu_item_selected_closure); - /* disconnect from the volume manager */ - g_signal_handlers_disconnect_matched (G_OBJECT (window->volume_manager), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window); - g_object_unref (G_OBJECT (window->volume_manager)); + /* disconnect from the volume monitor */ + g_signal_handlers_disconnect_matched (window->volume_monitor, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window); + g_object_unref (window->volume_monitor); /* disconnect from the ui manager */ - g_signal_handlers_disconnect_matched (G_OBJECT (window->ui_manager), G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window); - g_object_unref (G_OBJECT (window->ui_manager)); + g_signal_handlers_disconnect_matched (window->ui_manager, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window); + g_object_unref (window->ui_manager); - g_object_unref (G_OBJECT (window->action_group)); - g_object_unref (G_OBJECT (window->icon_factory)); - g_object_unref (G_OBJECT (window->launcher)); - g_object_unref (G_OBJECT (window->history)); + g_object_unref (window->action_group); + g_object_unref (window->icon_factory); + g_object_unref (window->launcher); + g_object_unref (window->history); /* release our reference on the provider factory */ - g_object_unref (G_OBJECT (window->provider_factory)); + g_object_unref (window->provider_factory); /* release the preferences reference */ - g_object_unref (G_OBJECT (window->preferences)); + g_object_unref (window->preferences); /* release the scroll_to_files hash table */ g_hash_table_destroy (window->scroll_to_files); @@ -1419,13 +1381,66 @@ thunar_window_merge_custom_preferences (ThunarWindow *window) +static void +thunar_window_open_or_launch (ThunarWindow *window, + ThunarFile *file) +{ + GError *error = NULL; + + _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + if (thunar_file_is_directory (file)) + { + /* open the new directory */ + thunar_window_set_current_directory (window, file); + } + else + { + /* try to launch the selected file */ + if (!thunar_file_launch (file, window, NULL, &error)) + { + thunar_dialogs_show_error (window, error, _("Failed to launch \"%s\""), + thunar_file_get_display_name (file)); + g_error_free (error); + } + } +} + + + +static void +thunar_window_poke_file_finish (ThunarBrowser *browser, + ThunarFile *file, + ThunarFile *target_file, + GError *error, + gpointer ignored) +{ + _thunar_return_if_fail (THUNAR_IS_WINDOW (browser)); + _thunar_return_if_fail (THUNAR_IS_FILE (file)); + + if (error == NULL) + { + thunar_window_open_or_launch (THUNAR_WINDOW (browser), target_file); + } + else + { + thunar_dialogs_show_error (GTK_WIDGET (browser), error, + _("Failed to open \"%s\""), + thunar_file_get_display_name (file)); + } +} + + + static void thunar_window_start_open_location (ThunarWindow *window, const gchar *initial_text) { ThunarFile *selected_file; GtkWidget *dialog; - GError *error = NULL; + + _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); /* bring up the "Open Location"-dialog if the window has no location bar or the location bar * in the window does not support text entry by the user. @@ -1452,24 +1467,15 @@ thunar_window_start_open_location (ThunarWindow *window, /* run the dialog */ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { + /* be sure to hide the location dialog first */ + gtk_widget_hide (dialog); + /* check if we have a new directory or a file to launch */ selected_file = thunar_location_dialog_get_selected_file (THUNAR_LOCATION_DIALOG (dialog)); - if (thunar_file_is_directory (selected_file)) - { - /* open the new directory */ - thunar_window_set_current_directory (window, selected_file); - } - else + if (selected_file != NULL) { - /* be sure to hide the location dialog first */ - gtk_widget_hide (dialog); - - /* try to launch the selected file */ - if (!thunar_file_launch (selected_file, GTK_WIDGET (window), &error)) - { - thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to launch \"%s\""), thunar_file_get_display_name (selected_file)); - g_error_free (error); - } + thunar_browser_poke_file (THUNAR_BROWSER (window), selected_file, window, + thunar_window_poke_file_finish, NULL); } } @@ -1491,7 +1497,7 @@ thunar_window_action_open_new_window (GtkAction *action, /* popup a new window */ application = thunar_application_get (); new_window = thunar_application_open_window (application, window->current_directory, - gtk_widget_get_screen (GTK_WIDGET (window))); + gtk_widget_get_screen (GTK_WIDGET (window)), NULL); g_object_unref (G_OBJECT (application)); /* determine the first visible file in the current window */ @@ -1878,18 +1884,17 @@ static void thunar_window_action_open_home (GtkAction *action, ThunarWindow *window) { - ThunarVfsPath *home_path; + GFile *home; ThunarFile *home_file; GError *error = NULL; - _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); /* determine the path to the home directory */ - home_path = thunar_vfs_path_get_for_home (); + home = thunar_g_file_new_for_home (); /* determine the file for the home directory */ - home_file = thunar_file_get_for_path (home_path, &error); + home_file = thunar_file_get (home, &error); if (G_UNLIKELY (home_file == NULL)) { /* display an error to the user */ @@ -1904,7 +1909,7 @@ thunar_window_action_open_home (GtkAction *action, } /* release our reference on the home path */ - thunar_vfs_path_unref (home_path); + g_object_unref (home); } gboolean @@ -1914,29 +1919,33 @@ thunar_window_open_user_folder (GtkAction *action, const gchar *default_name) { ThunarFile *user_file = NULL; - GError *error = NULL; - gchar *user_dir = NULL; - gboolean result = FALSE; + gboolean result = FALSE; + GError *error = NULL; + GFile *home_dir; + GFile *user_dir; + gchar *path = NULL; -#if GLIB_CHECK_VERSION(2, 14, 0) - user_dir = g_strdup (g_get_user_special_dir (thunar_user_dir)); -#endif + path = g_strdup (g_get_user_special_dir (thunar_user_dir)); - if (G_UNLIKELY (user_dir == NULL)) + if (G_UNLIKELY (path == NULL)) { - user_dir = g_build_filename (G_DIR_SEPARATOR_S, xfce_get_homedir (), - default_name, NULL); + home_dir = thunar_g_file_new_for_home (); + user_dir = g_file_resolve_relative_path (home_dir, default_name); + path = g_file_get_path (user_dir); + g_object_unref (home_dir); } + else + user_dir = g_file_new_for_path (path); - user_file = thunar_file_get_for_uri (user_dir, &error); - if (G_UNLIKELY (user_file == NULL && error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_EXIST)) + user_file = thunar_file_get (user_dir, &error); + if (G_UNLIKELY (user_file == NULL && error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT)) { g_error_free (error); error = NULL; /* try to create the folder */ - if (G_LIKELY (xfce_mkdirhier (user_dir, 0755, &error))) - user_file = thunar_file_get_for_uri (user_dir, &error); + if (G_LIKELY (xfce_mkdirhier (path, 0755, &error))) + user_file = thunar_file_get (user_dir, &error); } if (G_LIKELY (user_file != NULL)) @@ -1956,7 +1965,8 @@ thunar_window_open_user_folder (GtkAction *action, g_error_free (error); } - g_free (user_dir); + g_object_unref (user_dir); + g_free (path); return result; } @@ -1965,84 +1975,72 @@ static void thunar_window_action_open_desktop (GtkAction *action, ThunarWindow *window) { -#if GLIB_CHECK_VERSION(2, 14, 0) _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); thunar_window_open_user_folder (action, window, THUNAR_USER_DIRECTORY_DESKTOP, "Desktop"); -#endif } static void thunar_window_action_open_documents (GtkAction *action, ThunarWindow *window) { -#if GLIB_CHECK_VERSION(2, 14, 0) _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); thunar_window_open_user_folder (action, window, THUNAR_USER_DIRECTORY_DOCUMENTS, "Documents"); -#endif } static void thunar_window_action_open_downloads (GtkAction *action, ThunarWindow *window) { -#if GLIB_CHECK_VERSION(2, 14, 0) _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); thunar_window_open_user_folder (action, window, THUNAR_USER_DIRECTORY_DOWNLOAD, "Downloads"); -#endif } static void thunar_window_action_open_music (GtkAction *action, ThunarWindow *window) { -#if GLIB_CHECK_VERSION(2, 14, 0) _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); thunar_window_open_user_folder (action, window, THUNAR_USER_DIRECTORY_MUSIC, "Music"); -#endif } static void thunar_window_action_open_pictures (GtkAction *action, ThunarWindow *window) { -#if GLIB_CHECK_VERSION(2, 14, 0) _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); thunar_window_open_user_folder (action, window, THUNAR_USER_DIRECTORY_PICTURES, "Pictures"); -#endif } static void thunar_window_action_open_public (GtkAction *action, ThunarWindow *window) { -#if GLIB_CHECK_VERSION(2, 14, 0) _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); thunar_window_open_user_folder (action, window, THUNAR_USER_DIRECTORY_PUBLIC_SHARE, "Public"); -#endif } static void @@ -2129,14 +2127,12 @@ static void thunar_window_action_open_videos (GtkAction *action, ThunarWindow *window) { -#if GLIB_CHECK_VERSION(2, 14, 0) _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); thunar_window_open_user_folder (action, window, THUNAR_USER_DIRECTORY_VIDEOS, "Videos"); -#endif } @@ -2144,19 +2140,19 @@ static void thunar_window_action_open_trash (GtkAction *action, ThunarWindow *window) { - ThunarVfsPath *trash_bin_path; - ThunarFile *trash_bin; - GError *error = NULL; + GFile *trash_bin; + ThunarFile *trash_bin_file; + GError *error = NULL; _thunar_return_if_fail (GTK_IS_ACTION (action)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); /* determine the path to the trash bin */ - trash_bin_path = thunar_vfs_path_get_for_trash (); + trash_bin = thunar_g_file_new_for_trash (); /* determine the file for the trash bin */ - trash_bin = thunar_file_get_for_path (trash_bin_path, &error); - if (G_UNLIKELY (trash_bin == NULL)) + trash_bin_file = thunar_file_get (trash_bin, &error); + if (G_UNLIKELY (trash_bin_file == NULL)) { /* display an error to the user */ thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to display the contents of the trash can")); @@ -2165,12 +2161,12 @@ thunar_window_action_open_trash (GtkAction *action, else { /* open the trash folder */ - thunar_window_set_current_directory (window, trash_bin); + thunar_window_set_current_directory (window, trash_bin_file); g_object_unref (G_OBJECT (trash_bin)); } /* release our reference on the trash bin path */ - thunar_vfs_path_unref (trash_bin_path); + g_object_unref (trash_bin); } @@ -2254,41 +2250,65 @@ static void thunar_window_current_directory_destroy (ThunarFile *current_directory, ThunarWindow *window) { - ThunarVfsPath *path; - ThunarVfsInfo *info; - ThunarFile *file = NULL; + ThunarFile *new_directory = NULL; + GFile *path; + GFile *tmp; _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); _thunar_return_if_fail (THUNAR_IS_FILE (current_directory)); _thunar_return_if_fail (window->current_directory == current_directory); /* determine the path of the current directory */ - path = thunar_file_get_path (current_directory); + path = g_object_ref (thunar_file_get_file (current_directory)); - /* determine the first still present parent directory */ - for (path = thunar_vfs_path_get_parent (path); file == NULL && path != NULL; path = thunar_vfs_path_get_parent (path)) + /* try to find a parent directory that still exists */ + while (new_directory == NULL) { - /* try to determine the info for the path */ - info = thunar_vfs_info_new_for_path (path, NULL); - if (G_LIKELY (info != NULL)) + /* check whether the current directory exists */ + if (g_file_query_exists (path, NULL)) { - /* check if we have a directory here */ - if (info->type == THUNAR_VFS_FILE_TYPE_DIRECTORY) - file = thunar_file_get_for_info (info); + /* it does, try to load the file */ + new_directory = thunar_file_get (path, NULL); - /* release the file info */ - thunar_vfs_info_unref (info); + /* fall back to $HOME if loading the file failed */ + if (new_directory == NULL) + break; + } + else + { + /* determine the parent of the directory */ + tmp = g_file_get_parent (path); + + /* if there's no parent this means that we've found no parent + * that still exists at all. Fall back to $HOME then */ + if (tmp == NULL) + break; + + /* free the old directory */ + g_object_unref (path); + + /* check the parent next */ + path = tmp; } } + /* make sure we don't leak */ + if (path != NULL) + g_object_unref (path); + /* check if we have a new folder */ - if (G_LIKELY (file != NULL)) + if (G_LIKELY (new_directory != NULL)) { /* enter the new folder */ - thunar_window_set_current_directory (window, file); + thunar_window_set_current_directory (window, new_directory); /* release the file reference */ - g_object_unref (G_OBJECT (file)); + g_object_unref (new_directory); + } + else + { + /* enter the home folder */ + thunar_window_action_open_home (NULL, window); } } @@ -2402,29 +2422,28 @@ thunar_window_notify_loading (ThunarView *view, static void -thunar_window_volume_pre_unmount (ThunarVfsVolumeManager *volume_manager, - ThunarVfsVolume *volume, - ThunarWindow *window) +thunar_window_mount_pre_unmount (GVolumeMonitor *volume_monitor, + GMount *mount, + ThunarWindow *window) { - ThunarVfsPath *path; - ThunarFile *file; - GtkAction *action; + ThunarFile *file; + GtkAction *action; + GFile *mount_point; - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME_MANAGER (volume_manager)); - _thunar_return_if_fail (THUNAR_VFS_IS_VOLUME (volume)); + _thunar_return_if_fail (G_IS_VOLUME_MONITOR (volume_monitor)); + _thunar_return_if_fail (window->volume_monitor == volume_monitor); + _thunar_return_if_fail (G_IS_MOUNT (mount)); _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); /* nothing to do if we don't have a current directory */ if (G_UNLIKELY (window->current_directory == NULL)) return; - /* determine the mount point for the volume */ - path = thunar_vfs_volume_get_mount_point (volume); - if (G_UNLIKELY (path == NULL)) - return; + /* try to get the ThunarFile for the mount point from the file cache */ + mount_point = g_mount_get_root (mount); + file = thunar_file_cache_lookup (mount_point); + g_object_unref (mount_point); - /* check if a ThunarFile is known for the mount point */ - file = thunar_file_cache_lookup (path); if (G_UNLIKELY (file == NULL)) return; @@ -2559,7 +2578,7 @@ thunar_window_set_current_directory (ThunarWindow *window, _thunar_return_if_fail (THUNAR_IS_WINDOW (window)); _thunar_return_if_fail (current_directory == NULL || THUNAR_IS_FILE (current_directory)); - + /* check if we already display the requested directory */ if (G_UNLIKELY (window->current_directory == current_directory)) return; diff --git a/thunarx/Makefile.am b/thunarx/Makefile.am index 901aa7376..4bd7e25ef 100644 --- a/thunarx/Makefile.am +++ b/thunarx/Makefile.am @@ -4,7 +4,7 @@ INCLUDES = \ -I$(top_srcdir) \ -DG_LOG_DOMAIN=\"thunarx\" \ -DTHUNARX_COMPILATION \ - -DTHUNARX_DIRECTORY=\"$(libdir)/thunarx-$(THUNAR_VERSION_API)\" \ + -DTHUNARX_DIRECTORY=\"$(libdir)/thunarx-$(THUNARX_VERSION_API)\" \ $(PLATFORM_CPPFLAGS) libthunarx_built_sources = \ @@ -25,15 +25,15 @@ libthunarx_headers = \ thunarx-renamer-provider.h libthunarx_includedir = \ - $(includedir)/thunarx-$(THUNAR_VERSION_API)/thunarx + $(includedir)/thunarx-$(THUNARX_VERSION_API)/thunarx libthunarx_include_HEADERS = \ $(libthunarx_headers) lib_LTLIBRARIES = \ - libthunarx-1.la + libthunarx-2.la -libthunarx_1_la_SOURCES = \ +libthunarx_2_la_SOURCES = \ $(libthunarx_built_sources) \ $(libthunarx_headers) \ thunarx-config.c \ @@ -51,21 +51,25 @@ libthunarx_1_la_SOURCES = \ thunarx-renamer.c \ thunarx-renamer-provider.c -libthunarx_1_la_CFLAGS = \ +libthunarx_2_la_CFLAGS = \ + $(GLIB_CFLAGS) \ + $(GIO_CFLAGS) \ $(GTK_CFLAGS) \ $(PLATFORM_CFLAGS) -libthunarx_1_la_LDFLAGS = \ +libthunarx_2_la_LDFLAGS = \ -export-dynamic \ -export-symbols-regex "^[^_].*" \ - -version-info $(THUNAR_VERINFO) \ + -version-info $(THUNARX_VERINFO) \ $(PLATFORM_LDFLAGS) -libthunarx_1_la_LIBADD = \ +libthunarx_2_la_LIBADD = \ + $(GLIB_LIBS) \ + $(GIO_LIBS) \ $(GTK_LIBS) pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = thunarx-1.pc +pkgconfig_DATA = thunarx-2.pc EXTRA_DIST = \ abicheck.sh \ diff --git a/thunarx/abicheck.sh b/thunarx/abicheck.sh index cbdbd9cf5..b40607dc8 100755 --- a/thunarx/abicheck.sh +++ b/thunarx/abicheck.sh @@ -20,5 +20,5 @@ # cpp -P -DALL_FILES ${srcdir:-.}/thunarx.symbols | sed -e '/^$/d' -e 's/ G_GNUC.*$//' -e 's/ PRIVATE//' | sort > expected-abi -nm -D .libs/libthunarx-1.so | grep " T\|R " | cut -d ' ' -f 3 | grep -v '^_.*' | sort > actual-abi +nm -D .libs/libthunarx-2.so | grep " T\|R " | cut -d ' ' -f 3 | grep -v '^_.*' | sort > actual-abi diff -u expected-abi actual-abi && rm expected-abi actual-abi diff --git a/thunarx/thunarx-1.pc.in b/thunarx/thunarx-1.pc.in deleted file mode 100644 index 0b3179a28..000000000 --- a/thunarx/thunarx-1.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -extensionsdir=${libdir}/thunarx-@THUNAR_VERSION_API@ - -Name: thunarx -Description: A library to create Thunar extensions -Requires: gtk+-2.0 -Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lthunarx-@THUNAR_VERSION_API@ -Cflags: -I${includedir}/thunarx-@THUNAR_VERSION_API@ diff --git a/thunarx/thunarx-2.pc.in b/thunarx/thunarx-2.pc.in new file mode 100644 index 000000000..8dea27179 --- /dev/null +++ b/thunarx/thunarx-2.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +extensionsdir=${libdir}/thunarx-@THUNARX_VERSION_API@ + +Name: thunarx +Description: A library to create Thunar extensions +Requires: gtk+-2.0 gio-2.0 +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lthunarx-@THUNARX_VERSION_API@ +Cflags: -I${includedir}/thunarx-@THUNARX_VERSION_API@ diff --git a/thunarx/thunarx-file-info.c b/thunarx/thunarx-file-info.c index d4340f4f9..5552b4f94 100644 --- a/thunarx/thunarx-file-info.c +++ b/thunarx/thunarx-file-info.c @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -292,30 +293,67 @@ thunarx_file_info_is_directory (ThunarxFileInfo *file_info) /** - * thunarx_file_info_get_vfs_info: + * thunarx_file_info_get_file_info: * @file_info : a #ThunarxFileInfo. * - * Returns the #ThunarVfsInfo associated with @file_info, + * Returns the #GFileInfo associated with @file_info, * which includes additional information about the @file_info - * as queried from the VFS library earlier. The caller is - * responsible to free the returned #ThunarVfsInfo object - * using thunar_vfs_info_unref() when no longer needed. - * - * Note that the <application>thunarx</application> library itself - * is not linked to the <application>thunar-vfs</application> library, - * and so, if you need to use this method, you'll need to include - * <code><thunar-vfs/thunar-vfs.h></code> in your code and - * add <code>`pkg-config --cflags thunar-vfs-1`</code> to your - * <envar>CFLAGS</envar>. - * - * Return value: the #ThunarVfsInfo object associated with @file_info, - * which MUST be freed using thunar_vfs_info_unref(). + * as queried from GIO earlier. The caller is responsible to free the + * returned #GFileInfo object using g_object_unref() when + * no longer needed. + * + * Return value: the #GFileInfo object associated with @file_info, + * which MUST be freed using g_object_unref(). + **/ +GFileInfo* +thunarx_file_info_get_file_info (ThunarxFileInfo *file_info) +{ + g_return_val_if_fail (THUNARX_IS_FILE_INFO (file_info), NULL); + return (*THUNARX_FILE_INFO_GET_IFACE (file_info)->get_file_info) (file_info); +} + + + +/** + * thunarx_file_info_get_filesystem_info: + * @file_info : a #ThunarxFileInfo. + * + * Returns the #GFileInfo which includes additional information about + * the filesystem @file_info resides on. The caller is responsible to + * free the returned #GFileInfo object using g_object_unref() when + * no longer needed. + * + * Return value: the #GFileInfo containing information about the + * filesystem of @file_info or %NULL if no filesystem + * information is available. It MUST be released using + * g_object_unref(). + **/ +GFileInfo* +thunarx_file_info_get_filesystem_info (ThunarxFileInfo *file_info) +{ + g_return_val_if_fail (THUNARX_IS_FILE_INFO (file_info), NULL); + return (*THUNARX_FILE_INFO_GET_IFACE (file_info)->get_filesystem_info) (file_info); +} + + + +/** + * thunarx_file_info_get_location: + * @file_info : a #ThunarxFileInfo. + * + * Returns the #GFile @file_info points to. The #GFile is a more + * powerful tool than just the URI or the path. The caller + * is responsible to release the returned #GFile using g_object_unref() + * when no longer needed. + * + * Return value: the #GFile to which @file_info points. It MUST be + * released using g_object_unref(). **/ -ThunarVfsInfo* -thunarx_file_info_get_vfs_info (ThunarxFileInfo *file_info) +GFile* +thunarx_file_info_get_location (ThunarxFileInfo *file_info) { g_return_val_if_fail (THUNARX_IS_FILE_INFO (file_info), NULL); - return (*THUNARX_FILE_INFO_GET_IFACE (file_info)->get_vfs_info) (file_info); + return (*THUNARX_FILE_INFO_GET_IFACE (file_info)->get_location) (file_info); } diff --git a/thunarx/thunarx-file-info.h b/thunarx/thunarx-file-info.h index c6a00b07d..5c81c80d9 100644 --- a/thunarx/thunarx-file-info.h +++ b/thunarx/thunarx-file-info.h @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,15 +26,32 @@ #ifndef __THUNARX_FILE_INFO_H__ #define __THUNARX_FILE_INFO_H__ +#include <gio/gio.h> + #include <thunarx/thunarx-config.h> G_BEGIN_DECLS; -/* Used to avoid a dependency of thunarx on thunar-vfs */ -#ifndef __THUNAR_VFS_INFO_DEFINED__ -#define __THUNAR_VFS_INFO_DEFINED__ -typedef struct _ThunarVfsInfo ThunarVfsInfo; -#endif +/** + * File information namespaces available in the #GFileInfo returned by + * thunarx_file_info_get_file_info(). + **/ +#define THUNARX_FILE_INFO_NAMESPACE \ + "access::*," \ + "id::*," \ + "mountable::*," \ + "preview::*," \ + "standard::*," \ + "time::*," \ + "thumbnail::*," \ + "unix::*" + +/** + * Filesystem information namespaces available in the #GFileInfo + * returned by thunarx_file_info_get_filesystem_info(). + **/ +#define THUNARX_FILESYSTEM_INFO_NAMESPACE \ + "filesystem::*" typedef struct _ThunarxFileInfoIface ThunarxFileInfoIface; typedef struct _ThunarxFileInfo ThunarxFileInfo; @@ -51,19 +69,21 @@ struct _ThunarxFileInfoIface /*< public >*/ /* virtual methods */ - gchar *(*get_name) (ThunarxFileInfo *file_info); + gchar *(*get_name) (ThunarxFileInfo *file_info); - gchar *(*get_uri) (ThunarxFileInfo *file_info); - gchar *(*get_parent_uri) (ThunarxFileInfo *file_info); - gchar *(*get_uri_scheme) (ThunarxFileInfo *file_info); + gchar *(*get_uri) (ThunarxFileInfo *file_info); + gchar *(*get_parent_uri) (ThunarxFileInfo *file_info); + gchar *(*get_uri_scheme) (ThunarxFileInfo *file_info); - gchar *(*get_mime_type) (ThunarxFileInfo *file_info); - gboolean (*has_mime_type) (ThunarxFileInfo *file_info, + gchar *(*get_mime_type) (ThunarxFileInfo *file_info); + gboolean (*has_mime_type) (ThunarxFileInfo *file_info, const gchar *mime_type); - gboolean (*is_directory) (ThunarxFileInfo *file_info); + gboolean (*is_directory) (ThunarxFileInfo *file_info); - ThunarVfsInfo *(*get_vfs_info) (ThunarxFileInfo *file_info); + GFileInfo *(*get_file_info) (ThunarxFileInfo *file_info); + GFileInfo *(*get_filesystem_info) (ThunarxFileInfo *file_info); + GFile *(*get_location) (ThunarxFileInfo *file_info); /*< private >*/ void (*reserved0) (void); @@ -86,31 +106,33 @@ struct _ThunarxFileInfoIface void (*reserved9) (void); }; -GType thunarx_file_info_get_type (void) G_GNUC_CONST; +GType thunarx_file_info_get_type (void) G_GNUC_CONST; -gchar *thunarx_file_info_get_name (ThunarxFileInfo *file_info); -gchar *thunarx_file_info_get_uri (ThunarxFileInfo *file_info); -gchar *thunarx_file_info_get_parent_uri (ThunarxFileInfo *file_info); -gchar *thunarx_file_info_get_uri_scheme (ThunarxFileInfo *file_info); +gchar *thunarx_file_info_get_name (ThunarxFileInfo *file_info); +gchar *thunarx_file_info_get_uri (ThunarxFileInfo *file_info); +gchar *thunarx_file_info_get_parent_uri (ThunarxFileInfo *file_info); +gchar *thunarx_file_info_get_uri_scheme (ThunarxFileInfo *file_info); -gchar *thunarx_file_info_get_mime_type (ThunarxFileInfo *file_info); -gboolean thunarx_file_info_has_mime_type (ThunarxFileInfo *file_info, - const gchar *mime_type); +gchar *thunarx_file_info_get_mime_type (ThunarxFileInfo *file_info); +gboolean thunarx_file_info_has_mime_type (ThunarxFileInfo *file_info, + const gchar *mime_type); -gboolean thunarx_file_info_is_directory (ThunarxFileInfo *file_info); +gboolean thunarx_file_info_is_directory (ThunarxFileInfo *file_info); -ThunarVfsInfo *thunarx_file_info_get_vfs_info (ThunarxFileInfo *file_info); +GFileInfo *thunarx_file_info_get_file_info (ThunarxFileInfo *file_info); +GFileInfo *thunarx_file_info_get_filesystem_info (ThunarxFileInfo *file_info); +GFile *thunarx_file_info_get_location (ThunarxFileInfo *file_info); -void thunarx_file_info_changed (ThunarxFileInfo *file_info); -void thunarx_file_info_renamed (ThunarxFileInfo *file_info); +void thunarx_file_info_changed (ThunarxFileInfo *file_info); +void thunarx_file_info_renamed (ThunarxFileInfo *file_info); #define THUNARX_TYPE_FILE_INFO_LIST (thunarx_file_info_list_get_type ()) -GType thunarx_file_info_list_get_type (void) G_GNUC_CONST; +GType thunarx_file_info_list_get_type (void) G_GNUC_CONST; -GList *thunarx_file_info_list_copy (GList *file_infos); -void thunarx_file_info_list_free (GList *file_infos); +GList *thunarx_file_info_list_copy (GList *file_infos); +void thunarx_file_info_list_free (GList *file_infos); G_END_DECLS; diff --git a/thunarx/thunarx.symbols b/thunarx/thunarx.symbols index ebb82cee5..c0424a236 100644 --- a/thunarx/thunarx.symbols +++ b/thunarx/thunarx.symbols @@ -1,6 +1,7 @@ /* $Id$ */ /*- * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>. + * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -55,7 +56,9 @@ thunarx_file_info_get_uri_scheme thunarx_file_info_get_mime_type thunarx_file_info_has_mime_type thunarx_file_info_is_directory -thunarx_file_info_get_vfs_info +thunarx_file_info_get_file_info +thunarx_file_info_get_filesystem_info +thunarx_file_info_get_location thunarx_file_info_changed thunarx_file_info_renamed thunarx_file_info_list_get_type -- GitLab