[solang] Basic ArchiveMaker for creating archives



commit b05c491a309d0f2f40da5bc4a1a2fd837b1114fc
Author: Debarshi Ray <rishi gnu org>
Date:   Sun Mar 7 04:13:07 2010 +0200

    Basic ArchiveMaker for creating archives
    
    Spawning file-roller for creating archives is sub-optimal. The photos
    need to be copied to a directory and then the directory has to be
    archived. Instead we can directly put the photos in the archive and
    avoid copying them.
    
    The ArchiveMaker is stateless and provides an asynchronous way of
    creating an archive from a list of photos. Currently it only creates
    ZIP archives, but other formats can be easily added.
    
    A new dependency has been introduced on libarchive.

 README                                 |    1 +
 configure.ac                           |    5 +
 src/application/Makefile.am            |    1 +
 src/common/Makefile.am                 |    2 +
 src/common/archive-maker.cpp           |  492 ++++++++++++++++++++++++++++++++
 src/common/archive-maker.h             |  123 ++++++++
 src/common/types.h                     |   16 +
 src/exporter/directory-destination.cpp |   82 ++----
 8 files changed, 659 insertions(+), 63 deletions(-)
---
diff --git a/README b/README
index e24112c..67964ce 100644
--- a/README
+++ b/README
@@ -50,6 +50,7 @@ Features:
 Dependencies:
 -------------
  - babl
+ - libarchive
  - libbrasero-burn >= 2.28.3
  - dbus-glib-1
  - gdl-1.0
diff --git a/configure.ac b/configure.ac
index 91c6d6f..5d4f8e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,6 +34,11 @@ if test x"$DBUS_BINDING_TOOL" = x"no"; then
     AC_MSG_ERROR([could not find dbus-binding-tool in \$PATH.])
 fi
 
+AC_CHECK_HEADERS([archive.h],
+                 [ARCHIVE_LIBS=-larchive
+                  AC_SUBST([ARCHIVE_LIBS])],
+                 [AC_MSG_FAILURE([Can't find libarchive.])])
+
 PKG_CHECK_MODULES(BABL, [babl])
 PKG_CHECK_MODULES(DBUS, [dbus-glib-1])
 PKG_CHECK_MODULES(GDL, [gdl-1.0])
diff --git a/src/application/Makefile.am b/src/application/Makefile.am
index c26dc18..74e7d21 100644
--- a/src/application/Makefile.am
+++ b/src/application/Makefile.am
@@ -21,6 +21,7 @@ solang_LDADD = \
 	$(top_builddir)/src/attribute/libattribute.la \
 	$(top_builddir)/src/editor/libeditor.la \
 	$(top_builddir)/src/common/libcommon.la \
+	$(ARCHIVE_LIBS) \
 	$(BRASERO_LIBS) \
 	$(DBUS_LIBS) \
 	$(GTKIMAGEVIEW_LIBS) \
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 69dc300..7794f16 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -10,6 +10,8 @@ BUILT_SOURCES = \
 
 libcommon_la_SOURCES = \
 	$(libcommon_la_built_sources) \
+	archive-maker.cpp \
+	archive-maker.h \
 	database.cpp \
 	database.h \
 	delete-action.cpp \
diff --git a/src/common/archive-maker.cpp b/src/common/archive-maker.cpp
new file mode 100644
index 0000000..ca84310
--- /dev/null
+++ b/src/common/archive-maker.cpp
@@ -0,0 +1,492 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * Copyright (C) 2010 Debarshi Ray <rishi gnu org>
+ *
+ * Solang 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Solang 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include <archive.h>
+#include <archive_entry.h>
+#include <giomm.h>
+
+#include "archive-maker.h"
+#include "i-progress-observer.h"
+#include "photo.h"
+
+namespace Solang
+{
+
+class Archive
+{
+    public:
+        static ArchivePtr
+        create(gint fd) throw();
+
+        static ArchivePtr
+        create(const std::string & filename) throw();
+
+        ~Archive() throw();
+
+        archive *
+        obj() throw();
+
+    private:
+        Archive(gint fd) throw();
+
+        Archive(const std::string & filename) throw();
+
+        archive * a_;
+};
+
+Archive::Archive(gint fd) throw() :
+    a_(archive_write_new())
+{
+    archive_write_set_compression_none(a_);
+    archive_write_set_format(a_, ARCHIVE_FORMAT_ZIP);
+    archive_write_open_fd(a_, fd);
+}
+
+Archive::Archive(const std::string & filename) throw() :
+    a_(archive_write_new())
+{
+    archive_write_set_compression_none(a_);
+    archive_write_set_format(a_, ARCHIVE_FORMAT_ZIP);
+    archive_write_open_filename(a_, filename.c_str());
+}
+
+Archive::~Archive() throw()
+{
+    archive_write_finish(a_);
+}
+
+ArchivePtr
+Archive::create(gint fd) throw()
+{
+    return ArchivePtr(new Archive(fd));
+}
+
+ArchivePtr
+Archive::create(const std::string & filename) throw()
+{
+    return ArchivePtr(new Archive(filename));
+}
+
+archive *
+Archive::obj() throw()
+{
+    return a_;
+}
+
+class ArchiveEntry
+{
+    public:
+        static ArchiveEntryPtr
+        create() throw();
+
+        ~ArchiveEntry() throw();
+
+        void
+        copy_stat(const FileInfoPtr & file_info) throw();
+
+        archive_entry *
+        obj() throw();
+
+    private:
+        ArchiveEntry() throw();
+
+        archive_entry * ae_;
+};
+
+ArchiveEntry::ArchiveEntry() throw() :
+    ae_(archive_entry_new())
+{
+}
+
+ArchiveEntry::~ArchiveEntry() throw()
+{
+    archive_entry_free(ae_);
+}
+
+ArchiveEntryPtr
+ArchiveEntry::create() throw()
+{
+    return ArchiveEntryPtr(new ArchiveEntry());
+}
+
+void
+ArchiveEntry::copy_stat(const FileInfoPtr & file_info) throw()
+{
+    {
+        const guint64 time = file_info->get_attribute_uint64(
+                                 G_FILE_ATTRIBUTE_TIME_ACCESS);
+        const guint32 time_m = file_info->get_attribute_uint32(
+                                   G_FILE_ATTRIBUTE_TIME_ACCESS_USEC)
+                               * 1000;
+        archive_entry_set_atime(ae_, time, time_m);
+    }
+
+    {
+        const guint64 time = file_info->get_attribute_uint64(
+                                 G_FILE_ATTRIBUTE_TIME_CHANGED);
+        const guint32 time_m = file_info->get_attribute_uint32(
+                                   G_FILE_ATTRIBUTE_TIME_CHANGED_USEC)
+                               * 1000;
+        archive_entry_set_ctime(ae_, time, time_m);
+    }
+
+    {
+        const guint64 time = file_info->get_attribute_uint64(
+                                 G_FILE_ATTRIBUTE_TIME_MODIFIED);
+        const guint32 time_m = file_info->get_attribute_uint32(
+                                   G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC)
+                               * 1000;
+        archive_entry_set_mtime(ae_, time, time_m);
+    }
+
+    {
+        const guint64 time = file_info->get_attribute_uint64(
+                                 G_FILE_ATTRIBUTE_TIME_MODIFIED);
+        const guint32 time_m = file_info->get_attribute_uint32(
+                                   G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC)
+                               * 1000;
+        archive_entry_set_mtime(ae_, time, time_m);
+    }
+
+    archive_entry_unset_birthtime(ae_);
+
+    {
+        const guint32 dev = file_info->get_attribute_uint32(
+                                G_FILE_ATTRIBUTE_UNIX_DEVICE);
+        archive_entry_set_dev(ae_, dev);
+    }
+
+    {
+        const guint32 gid = file_info->get_attribute_uint32(
+                                G_FILE_ATTRIBUTE_UNIX_GID);
+        archive_entry_set_gid(ae_, gid);
+    }
+
+    {
+        const guint32 uid = file_info->get_attribute_uint32(
+                                G_FILE_ATTRIBUTE_UNIX_UID);
+        archive_entry_set_uid(ae_, uid);
+    }
+
+    {
+        const guint64 ino = file_info->get_attribute_uint64(
+                                G_FILE_ATTRIBUTE_UNIX_INODE);
+        archive_entry_set_ino(ae_, ino);
+    }
+
+    {
+        const guint32 nlink = file_info->get_attribute_uint32(
+                                  G_FILE_ATTRIBUTE_UNIX_NLINK);
+        archive_entry_set_nlink(ae_, nlink);
+    }
+
+    {
+        const guint32 rdev = file_info->get_attribute_uint32(
+                                 G_FILE_ATTRIBUTE_UNIX_RDEV);
+        archive_entry_set_rdev(ae_, rdev);
+    }
+
+    {
+        const guint64 size = file_info->get_attribute_uint64(
+                                 G_FILE_ATTRIBUTE_STANDARD_SIZE);
+        archive_entry_set_size(ae_, size);
+    }
+
+    {
+        const guint32 mode = file_info->get_attribute_uint32(
+                                 G_FILE_ATTRIBUTE_UNIX_MODE);
+        archive_entry_set_mode(ae_, mode);
+    }
+}
+
+archive_entry *
+ArchiveEntry::obj() throw()
+{
+    return ae_;
+}
+
+const gsize ArchiveMaker::chunk_ = 4096;
+
+const std::string ArchiveMaker::prefix_ = "Photos/";
+
+ArchiveMaker::ArchiveMaker() throw() :
+    NonCopyable(),
+    sigc::trackable()
+{
+}
+
+ArchiveMaker::~ArchiveMaker() throw()
+{
+}
+
+ArchiveMakerPtr
+ArchiveMaker::create() throw()
+{
+    return ArchiveMakerPtr(new ArchiveMaker());
+}
+
+void
+ArchiveMaker::add_file_async(const Triplet & triplet,
+                             const SlotAsyncReady & slot,
+                             const ProgressObserverPtr & observer)
+                             const throw()
+{
+    const PhotoPtr & photo = triplet.second->back();
+    const FilePtr file = Gio::File::create_for_uri(photo->get_uri());
+
+    file->read_async(sigc::bind(
+                         sigc::mem_fun(
+                             *this,
+                             &ArchiveMaker::on_async_file_read_ready),
+                         triplet,
+                         file,
+                         slot,
+                         observer),
+                     observer,
+                     Glib::PRIORITY_DEFAULT);
+}
+
+void
+ArchiveMaker::make_async(const std::string & dest_path,
+                         const PhotoListPtr & photos,
+                         const SlotAsyncReady & slot,
+                         const ProgressObserverPtr & observer) const
+                         throw()
+{
+    if (true == photos->empty())
+    {
+        return;
+    }
+
+    const ArchivePtr archive = Archive::create(dest_path);
+
+    Triplet triplet;
+    triplet.first = dest_path;
+    triplet.second = photos;
+    triplet.third = archive;
+
+    add_file_async(triplet, slot, observer);
+}
+
+void
+ArchiveMaker::on_async_file_read_ready(
+                  const AsyncResultPtr & async_result,
+                  const Triplet & triplet,
+                  const FilePtr & file,
+                  const SlotAsyncReady & slot,
+                  const ProgressObserverPtr & observer) const throw()
+{
+    FileInputStreamPtr input_stream;
+
+    try
+    {
+        input_stream = file->read_finish(async_result);
+    }
+    catch (const Gio::Error & e)
+    {
+        switch (e.code())
+        {
+        case Gio::Error::CANCELLED:
+            break;
+
+        default:
+            g_warning("%s", e.what().c_str());
+            break;
+        }
+        return;
+    }
+
+    input_stream->query_info_async(
+        sigc::bind(sigc::mem_fun(
+                       *this,
+                       &ArchiveMaker::on_async_stream_query_ready),
+                   triplet,
+                   input_stream,
+                   slot,
+                   observer),
+        observer,
+        "*",
+        Glib::PRIORITY_DEFAULT);
+}
+
+void
+ArchiveMaker::on_async_stream_close_ready(
+                  const AsyncResultPtr & async_result,
+                  const FileInputStreamPtr & input_stream) const
+                  throw()
+{
+    try
+    {
+        input_stream->close_finish(async_result);
+    }
+    catch (const Gio::Error & e)
+    {
+        g_warning("%s", e.what().c_str());
+    }
+}
+
+void
+ArchiveMaker::on_async_stream_query_ready(
+                  const AsyncResultPtr & async_result,
+                  const Triplet & triplet,
+                  const FileInputStreamPtr & input_stream,
+                  const SlotAsyncReady & slot,
+                  const ProgressObserverPtr & observer) const throw()
+{
+    FileInfoPtr file_info;
+
+    try
+    {
+        file_info = input_stream->query_info_finish(async_result);
+    }
+    catch (const Gio::Error & e)
+    {
+        switch (e.code())
+        {
+        case Gio::Error::CANCELLED:
+            break;
+
+        default:
+            g_warning("%s", e.what().c_str());
+            break;
+        }
+        return;
+    }
+
+    const ArchiveEntryPtr & archive_entry = ArchiveEntry::create();
+    archive_entry->copy_stat(file_info);
+
+    const PhotoPtr & photo = triplet.second->back();
+    const FilePtr file = Gio::File::create_for_uri(photo->get_uri());
+    const std::string pathname = prefix_ + file->get_basename();
+
+    archive_entry_set_pathname(archive_entry->obj(),
+                               pathname.c_str());
+
+    archive_write_header(triplet.third->obj(), archive_entry->obj());
+
+    read_file_async(triplet,
+                    input_stream,
+                    archive_entry,
+                    slot,
+                    observer);
+}
+
+void
+ArchiveMaker::on_async_stream_read_ready(
+                  const AsyncResultPtr & async_result,
+                  const CharPtr & buffer,
+                  Triplet & triplet,
+                  const FileInputStreamPtr & input_stream,
+                  ArchiveEntryPtr & archive_entry,
+                  const SlotAsyncReady & slot,
+                  const ProgressObserverPtr & observer) const throw()
+{
+    gssize nread;
+
+    try
+    {
+        nread = input_stream->read_finish(async_result);
+    }
+    catch (const Gio::Error & e)
+    {
+        switch (e.code())
+        {
+        case Gio::Error::CANCELLED:
+            break;
+
+        default:
+            g_warning("%s", e.what().c_str());
+            break;
+        }
+        return;
+    }
+
+    if (0 >= nread)
+    {
+        archive_entry.reset();
+        input_stream->close_async(
+            sigc::bind(
+                sigc::mem_fun(
+                    *this,
+                    &ArchiveMaker::on_async_stream_close_ready),
+                input_stream),
+            Glib::PRIORITY_DEFAULT);
+
+        if (0 != observer)
+        {
+            observer->progress();
+        }
+
+        triplet.second->pop_back();
+
+        if (true == triplet.second->empty())
+        {
+            triplet.third.reset();
+            if (true == slot)
+            {
+                slot();
+            }
+        }
+        else
+        {
+            add_file_async(triplet, slot, observer);
+        }
+    }
+    else
+    {
+        archive_write_data(triplet.third->obj(), &*buffer, nread);
+        read_file_async(triplet,
+                        input_stream,
+                        archive_entry,
+                        slot,
+                        observer);
+    }
+}
+
+void
+ArchiveMaker::read_file_async(
+                  const Triplet & triplet,
+                  const FileInputStreamPtr & input_stream,
+                  const ArchiveEntryPtr & archive_entry,
+                  const SlotAsyncReady & slot,
+                  const ProgressObserverPtr & observer) const throw()
+{
+    const CharPtr buffer(new char[chunk_]);
+
+    input_stream->read_async(
+        &*buffer,
+        chunk_,
+        sigc::bind(sigc::mem_fun(
+                       *this,
+                       &ArchiveMaker::on_async_stream_read_ready),
+                   buffer,
+                   triplet,
+                   input_stream,
+                   archive_entry,
+                   slot,
+                   observer),
+        observer,
+        Glib::PRIORITY_DEFAULT);
+}
+
+} // namespace Solang
diff --git a/src/common/archive-maker.h b/src/common/archive-maker.h
new file mode 100644
index 0000000..53730de
--- /dev/null
+++ b/src/common/archive-maker.h
@@ -0,0 +1,123 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * Copyright (C) 2010 Debarshi Ray <rishi gnu org>
+ *
+ * Solang 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Solang 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SOLANG_ARCHIVE_MAKER_H
+#define SOLANG_ARCHIVE_MAKER_H
+
+#include <string>
+
+#include <sigc++/sigc++.h>
+
+#include "non-copyable.h"
+#include "types.h"
+
+namespace Solang
+{
+
+class Archive;
+typedef std::tr1::shared_ptr<const Archive> ConstArchivePtr;
+typedef std::tr1::shared_ptr<Archive> ArchivePtr;
+
+class ArchiveEntry;
+typedef std::tr1::shared_ptr<const ArchiveEntry> ConstArchiveEntryPtr;
+typedef std::tr1::shared_ptr<ArchiveEntry> ArchiveEntryPtr;
+
+class ArchiveMaker :
+    public NonCopyable,
+    public sigc::trackable
+{
+    public:
+        typedef sigc::slot<void> SlotAsyncReady;
+
+        static ArchiveMakerPtr
+        create() throw();
+
+        ~ArchiveMaker() throw();
+
+        void
+        make_async(const std::string & dest_path,
+                   const PhotoListPtr & photos,
+                   const SlotAsyncReady & slot,
+                   const ProgressObserverPtr & observer) const
+                   throw();
+
+    protected:
+
+    private:
+        struct Triplet
+        {
+            std::string first;
+            PhotoListPtr second;
+            ArchivePtr third;
+        };
+
+        static const gsize chunk_;
+
+        static const std::string prefix_;
+
+        ArchiveMaker() throw();
+
+        void
+        add_file_async(const Triplet & triplet,
+                       const SlotAsyncReady & slot,
+                       const ProgressObserverPtr & observer) const
+                       throw();
+
+        void
+        on_async_file_read_ready(
+            const AsyncResultPtr & async_result,
+            const Triplet & triplet,
+            const FilePtr & file,
+            const SlotAsyncReady & slot,
+            const ProgressObserverPtr & observer) const throw();
+
+        void
+        on_async_stream_close_ready(
+            const AsyncResultPtr & async_result,
+            const FileInputStreamPtr & input_stream) const throw();
+
+        void
+        on_async_stream_query_ready(
+            const AsyncResultPtr & async_result,
+            const Triplet & triplet,
+            const FileInputStreamPtr & input_stream,
+            const SlotAsyncReady & slot,
+            const ProgressObserverPtr & observer) const throw();
+
+        void
+        on_async_stream_read_ready(
+            const AsyncResultPtr & async_result,
+            const CharPtr & buffer,
+            Triplet & triplet,
+            const FileInputStreamPtr & input_stream,
+            ArchiveEntryPtr & archive_entry,
+            const SlotAsyncReady & slot,
+            const ProgressObserverPtr & observer) const throw();
+
+        void
+        read_file_async(
+            const Triplet & triplet,
+            const FileInputStreamPtr & input_stream,
+            const ArchiveEntryPtr & archive_entry,
+            const SlotAsyncReady & slot,
+            const ProgressObserverPtr & observer) const throw();
+};
+
+} // namespace Solang
+
+#endif // SOLANG_ARCHIVE_MAKER_H
diff --git a/src/common/types.h b/src/common/types.h
index cc05758..d0138be 100644
--- a/src/common/types.h
+++ b/src/common/types.h
@@ -54,6 +54,8 @@ namespace Gio
 class AsyncResult;
 class DataInputStream;
 class File;
+class FileInfo;
+class FileInputStream;
 
 } // namespace Gio
 
@@ -81,6 +83,9 @@ class UIManager;
 namespace Solang
 {
 
+typedef std::tr1::shared_ptr<const char> ConstCharPtr;
+typedef std::tr1::shared_ptr<char> CharPtr;
+
 typedef std::tr1::shared_ptr<const char *> ConstCharPtrPtr;
 
 typedef std::vector<std::string> StringList;
@@ -90,6 +95,10 @@ class Application;
 typedef const Application * ConstApplicationPtr;
 typedef Application * ApplicationPtr;
 
+class ArchiveMaker;
+typedef std::tr1::shared_ptr<const ArchiveMaker> ConstArchiveMakerPtr;
+typedef std::tr1::shared_ptr<ArchiveMaker> ArchiveMakerPtr;
+
 class ContentTypeRepo;
 typedef ContentTypeRepo * ContentTypeRepoPtr;
 
@@ -293,6 +302,13 @@ typedef Glib::RefPtr<Gio::DataInputStream> DataInputStreamPtr;
 typedef Glib::RefPtr<const Gio::File> ConstFilePtr;
 typedef Glib::RefPtr<Gio::File> FilePtr;
 
+typedef Glib::RefPtr<const Gio::FileInfo> ConstFileInfoPtr;
+typedef Glib::RefPtr<Gio::FileInfo> FileInfoPtr;
+
+typedef Glib::RefPtr<const Gio::FileInputStream>
+    ConstFileInputStreamPtr;
+typedef Glib::RefPtr<Gio::FileInputStream> FileInputStreamPtr;
+
 typedef Glib::RefPtr<const Gtk::Action> ConstActionPtr;
 typedef Glib::RefPtr<Gtk::Action> ActionPtr;
 typedef std::vector<ConstActionPtr> ConstActionList;
diff --git a/src/exporter/directory-destination.cpp b/src/exporter/directory-destination.cpp
index 919cd64..fcf017c 100644
--- a/src/exporter/directory-destination.cpp
+++ b/src/exporter/directory-destination.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
 /*
- * Copyright (C) 2009 Debarshi Ray <rishi gnu org>
+ * Copyright (C) 2009, 2010 Debarshi Ray <rishi gnu org>
  * Copyright (C) 2009 Santanu Sinha <santanu sinha gmail com>
  *
  * Solang is free software: you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 #include <glib/gstdio.h>
 #include <glibmm/i18n.h>
 
+#include "archive-maker.h"
 #include "directory-destination.h"
 #include "i-progress-observer.h"
 #include "photo.h"
@@ -96,34 +97,30 @@ DirectoryDestination::export_photos_async(
         observer->set_total(photos.size());
     }
 
+    const PhotoListPtr pending(new PhotoList(photos.begin(),
+                                             photos.end()));
+
     if (true == createArchive_)
     {
         Glib::Date date;
         date.set_time_current();
 
-        const std::string tmp_dirname = date.format_string("%Y%m%d");
+        const std::string dest = date.format_string("%Y%m%d") + ".zip";
         filename_ += "/";
-        filename_ += tmp_dirname;
+        filename_ += dest;
 
-        if (false == Glib::file_test(filename_,
-                                     Glib::FILE_TEST_EXISTS))
-        {
-            try
-            {
-                Gio::File::create_for_path(
-                    filename_)->make_directory_with_parents();
-            }
-            catch (const Gio::Error & e)
-            {
-                g_warning("%s", e.what().c_str());
-            }
-        }
+        const ArchiveMakerPtr archive_maker = ArchiveMaker::create();
+        archive_maker->make_async(
+            filename_,
+            pending,
+            sigc::bind(sigc::slot<void, const ArchiveMakerPtr &>(),
+                       archive_maker),
+            observer);
+    }
+    else
+    {
+        export_photo_async(pending->back(), pending, observer);
     }
-
-    const PhotoListPtr pending(new PhotoList(photos.begin(),
-                                             photos.end()));
-
-    export_photo_async(pending->back(), pending, observer);
 
     return;
 }
@@ -171,48 +168,7 @@ DirectoryDestination::on_async_copy_ready(
 
     pending->pop_back();
 
-    if (true == pending->empty())
-    {
-        if (true == createArchive_)
-        {
-            const std::string command_line
-                = Glib::find_program_in_path("file-roller")
-                  + " --add-to=" + filename_ + ".zip"
-                  + " --add " + filename_;
-
-            GPid pid;
-
-            try
-            {
-                Glib::spawn_async(
-                          "",
-                          Glib::shell_parse_argv(command_line),
-                          static_cast<Glib::SpawnFlags>(0),
-                          sigc::slot<void>(),
-                          &pid);
-            }
-            catch (const Glib::ShellError & e)
-            {
-                g_warning("%s", e.what().c_str());
-                return;
-            }
-            catch (const Glib::SpawnError & e)
-            {
-                g_warning("%s", e.what().c_str());
-                return;
-            }
-
-            Glib::signal_child_watch().connect(
-                sigc::bind(
-                    sigc::mem_fun(
-                        *this,
-                        &DirectoryDestination::on_child_watch),
-                    filename_),
-                pid,
-                Glib::PRIORITY_DEFAULT);
-        }
-    }
-    else
+    if (false == pending->empty())
     {
         export_photo_async(pending->back(), pending, observer);
     }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]