[solang] Mark photos in the export queue in the browser



commit e75b1df477eb37edce4c8726daa00dcc3e53176b
Author: Debarshi Ray <rishi gnu org>
Date:   Fri Mar 26 03:05:59 2010 +0200

    Mark photos in the export queue in the browser
    
    The following interfaces were added:
    + IRenderer::get_selected_paths
    + Photo::get_state_export_queue
    + Photo::set_state_export_queue
    
    New icon ("conduit-source") taken from Conduit.

 README                                     |    1 +
 data/icons/16x16/Makefile.am               |    4 +
 data/icons/16x16/status/conduit-source.png |  Bin 0 -> 594 bytes
 src/common/export-queue-operations.cpp     |  147 +++++++++++++++++++++++++++-
 src/common/i-renderer.h                    |    3 +
 src/common/photo.cpp                       |   15 +++
 src/common/photo.h                         |   17 +++-
 src/renderer/browser-renderer.cpp          |   73 ++++++++++++++
 src/renderer/browser-renderer.h            |    3 +
 src/renderer/cell-renderer-thumbnail.cpp   |   44 ++++++++-
 src/renderer/cell-renderer-thumbnail.h     |    5 +
 src/renderer/enlarged-renderer.cpp         |   13 +++
 src/renderer/enlarged-renderer.h           |    3 +
 src/renderer/slideshow-renderer.cpp        |   13 +++
 src/renderer/slideshow-renderer.h          |    3 +
 15 files changed, 337 insertions(+), 7 deletions(-)
---
diff --git a/README b/README
index 5ed971a..9f7f12a 100644
--- a/README
+++ b/README
@@ -73,6 +73,7 @@ The following pieces of artwork were borrowed from Conduit
 License version 2.
 
 + data/flickr.png
++ data/icons/16x16/status/conduit-source.png
 
 The following pieces of artwork were borrowed from Eye of GNOME
 (http://projects.gnome.org/eog/). These are copyrighted by Andreas Nilsson
diff --git a/data/icons/16x16/Makefile.am b/data/icons/16x16/Makefile.am
index af86bf0..018fab0 100644
--- a/data/icons/16x16/Makefile.am
+++ b/data/icons/16x16/Makefile.am
@@ -7,3 +7,7 @@ dist_actionicons_DATA = \
 appiconsdir = $(datadir)/icons/hicolor/$(size)/apps
 dist_appicons_DATA = \
 	apps/solang.png
+
+statusiconsdir = $(pkgdatadir)/icons/hicolor/$(size)/status
+dist_statusicons_DATA = \
+	status/conduit-source.png
diff --git a/data/icons/16x16/status/conduit-source.png b/data/icons/16x16/status/conduit-source.png
new file mode 100644
index 0000000..89274e9
Binary files /dev/null and b/data/icons/16x16/status/conduit-source.png differ
diff --git a/src/common/export-queue-operations.cpp b/src/common/export-queue-operations.cpp
index f0d265d..591d6c5 100644
--- a/src/common/export-queue-operations.cpp
+++ b/src/common/export-queue-operations.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>
  *
  * 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
@@ -23,12 +23,132 @@
 #include <algorithm>
 #include <iterator>
 
+#include <gtkmm.h>
+
 #include "application.h"
 #include "export-queue-operations.h"
 
 namespace Solang
 {
 
+class ExportMarker :
+    public std::unary_function<const PhotoPtr &, PhotoPtr>
+{
+    public:
+        ExportMarker(bool mark) throw();
+
+        ExportMarker(const ExportMarker & source) throw();
+
+        ~ExportMarker() throw();
+
+        ExportMarker &
+        operator=(const ExportMarker & source) throw();
+
+        PhotoPtr
+        operator()(const PhotoPtr & photo) throw();
+
+    protected:
+        bool mark_;
+};
+
+ExportMarker::ExportMarker(bool mark) throw() :
+    std::unary_function<const PhotoPtr &, PhotoPtr>(),
+    mark_(mark)
+{
+}
+
+ExportMarker::ExportMarker(const ExportMarker & source) throw() :
+    std::unary_function<const PhotoPtr &, PhotoPtr>(source),
+    mark_(source.mark_)
+{
+}
+
+ExportMarker::~ExportMarker() throw()
+{
+}
+
+ExportMarker &
+ExportMarker::operator=(const ExportMarker & source) throw()
+{
+    if (this != &source)
+    {
+        std::unary_function<const PhotoPtr &, PhotoPtr>::operator=(
+                                                             source);
+        mark_ = source.mark_;
+    }
+
+    return *this;
+}
+
+PhotoPtr
+ExportMarker::operator()(const PhotoPtr & photo) throw()
+{
+    photo->set_state_export_queue(mark_);
+    return photo;
+}
+
+class TreeModelRowChangedEmitter :
+    public std::unary_function<const Gtk::TreeModel::Path &, void>
+{
+    public:
+        TreeModelRowChangedEmitter(const TreeModelPtr & tree_model)
+                                   throw();
+
+        TreeModelRowChangedEmitter(
+            const TreeModelRowChangedEmitter & source) throw();
+
+        ~TreeModelRowChangedEmitter() throw();
+
+        TreeModelRowChangedEmitter &
+        operator=(const TreeModelRowChangedEmitter & source) throw();
+
+        void
+        operator()(const Gtk::TreeModel::Path & path) throw();
+
+    protected:
+        TreeModelPtr treeModel_;
+};
+
+TreeModelRowChangedEmitter::TreeModelRowChangedEmitter(
+                                const TreeModelPtr & tree_model)
+                                throw() :
+    std::unary_function<const Gtk::TreeModel::Path &, void>(),
+    treeModel_(tree_model)
+{
+}
+
+TreeModelRowChangedEmitter::TreeModelRowChangedEmitter(
+    const TreeModelRowChangedEmitter & source) throw() :
+    std::unary_function<const Gtk::TreeModel::Path &, void>(source),
+    treeModel_(source.treeModel_)
+{
+}
+
+TreeModelRowChangedEmitter::~TreeModelRowChangedEmitter() throw()
+{
+}
+
+TreeModelRowChangedEmitter &
+TreeModelRowChangedEmitter::operator=(
+    const TreeModelRowChangedEmitter & source) throw()
+{
+    if (this != &source)
+    {
+        std::unary_function<const Gtk::TreePath &, void>::operator=(
+                                                              source);
+        treeModel_ = source.treeModel_;
+    }
+
+    return *this;
+}
+
+void
+TreeModelRowChangedEmitter::operator()(const Gtk::TreePath & path)
+                                       throw()
+{
+    treeModel_->row_changed(path, treeModel_->get_iter(path));
+}
+
 ExportQueueCleaner::ExportQueueCleaner(Application & application)
                                        throw() :
     std::unary_function<void, void>(),
@@ -64,6 +184,21 @@ ExportQueueCleaner::operator()(void) throw()
 {
     Engine & engine = application_->get_engine();
     PhotoSet & queue = engine.get_export_queue();
+
+    std::for_each(queue.begin(), queue.end(), ExportMarker(false));
+    if (false == queue.empty())
+    {
+        const TreeModelPtr & tree_model
+                                 = application_->get_list_store();
+        TreeModelRowChangedEmitter emitter(tree_model);
+
+        tree_model->foreach_path(
+            sigc::bind_return(
+                sigc::mem_fun(
+                    emitter,
+                    &TreeModelRowChangedEmitter::operator()),
+                false));
+    }
     queue.clear();
 }
 
@@ -106,10 +241,16 @@ ExportQueueInserter::operator()(void) throw()
     RendererRegistry & renderer_registry
                            = application_->get_renderer_registry();
     const IRendererPtr renderer = renderer_registry.get_current();
+
     const PhotoList & photos = renderer->get_current_selection();
+    std::transform(photos.begin(), photos.end(),
+                   std::inserter(queue, queue.begin()),
+                   ExportMarker(true));
 
-    std::copy(photos.begin(), photos.end(),
-              std::inserter(queue, queue.begin()));
+    const TreeModelPtr & tree_model = application_->get_list_store();
+    const TreePathList & paths = renderer->get_selected_paths();
+    std::for_each(paths.begin(), paths.end(),
+                  TreeModelRowChangedEmitter(tree_model));
 }
 
 } // namespace Solang
diff --git a/src/common/i-renderer.h b/src/common/i-renderer.h
index 195169d..7c9a386 100644
--- a/src/common/i-renderer.h
+++ b/src/common/i-renderer.h
@@ -45,6 +45,9 @@ class IRenderer :
         virtual PhotoList
         get_current_selection() throw() = 0;
 
+        virtual TreePathList
+        get_selected_paths() const throw() = 0;
+
         virtual void
         present() throw() = 0;
 
diff --git a/src/common/photo.cpp b/src/common/photo.cpp
index 80e1355..e5571af 100644
--- a/src/common/photo.cpp
+++ b/src/common/photo.cpp
@@ -48,6 +48,7 @@ Photo::Photo(const Glib::ustring & uri,
     DBObject(),
     uri_(uri),
     contentType_(content_type),
+    state_(PHOTO_STATE_NONE),
     thumbnailPath_(),
     thumbnailState_(THUMBNAIL_STATE_NONE),
     buffer_( 0 ),
@@ -85,6 +86,20 @@ Photo::get_save_query() const throw()
     return Glib::ustring();
 }
 
+bool
+Photo::get_state_export_queue() const throw()
+{
+    return state_ & PHOTO_STATE_EXPORT_QUEUE;
+}
+
+void
+Photo::set_state_export_queue(bool export_queue) throw()
+{
+    state_ = (true == export_queue)
+             ? state_ | PHOTO_STATE_EXPORT_QUEUE
+             : state_ & ~PHOTO_STATE_EXPORT_QUEUE;
+}
+
 void
 Photo::save_async(Database & database, const SlotAsyncReady & slot)
                   const throw()
diff --git a/src/common/photo.h b/src/common/photo.h
index feab9f7..e93c091 100644
--- a/src/common/photo.h
+++ b/src/common/photo.h
@@ -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
@@ -100,6 +100,12 @@ class Photo :
         void
         set_buffer( const PixbufPtr &buffer ) throw();
 
+        bool
+        get_state_export_queue() const throw();
+
+        void
+        set_state_export_queue(bool export_queue) throw();
+
         inline const PixbufPtr &
         get_thumbnail_buffer( ) const throw();
 
@@ -124,6 +130,13 @@ class Photo :
     private:
         friend class PhotoFactory;
 
+        // States may not be mutually exclusive.
+        enum State
+        {
+            PHOTO_STATE_NONE            = 0,
+            PHOTO_STATE_EXPORT_QUEUE    = 1 << 0
+        };
+
         Photo(const Glib::ustring & uri,
               const Glib::ustring & content_type) throw();
 
@@ -131,6 +144,8 @@ class Photo :
 
         Glib::ustring contentType_; //content type
 
+        guint8 state_;
+
         std::string thumbnailPath_;
 
         ThumbnailState thumbnailState_;
diff --git a/src/renderer/browser-renderer.cpp b/src/renderer/browser-renderer.cpp
index 4888c42..5d644a9 100644
--- a/src/renderer/browser-renderer.cpp
+++ b/src/renderer/browser-renderer.cpp
@@ -21,6 +21,8 @@
 #include "config.h"
 #endif // HAVE_CONFIG_H
 
+#include <algorithm>
+#include <functional>
 #include <sstream>
 #include <vector>
 
@@ -40,6 +42,67 @@
 namespace Solang
 {
 
+class ChildPathConverter :
+    public std::unary_function<const Gtk::TreePath &, Gtk::TreePath>
+{
+    public:
+        ChildPathConverter(
+            const TreeModelFilterPtr & tree_model_filter) throw();
+
+        ChildPathConverter(const ChildPathConverter & source) throw();
+
+        ~ChildPathConverter() throw();
+
+        ChildPathConverter &
+        operator=(const ChildPathConverter & source) throw();
+
+        Gtk::TreeModel::Path
+        operator()(const Gtk::TreeModel::Path & path) throw();
+
+    protected:
+        TreeModelFilterPtr treeModelFilter_;
+};
+
+ChildPathConverter::ChildPathConverter(
+                        const TreeModelFilterPtr & tree_model_filter)
+                        throw() :
+    std::unary_function<const Gtk::TreePath &, Gtk::TreePath>(),
+    treeModelFilter_(tree_model_filter)
+{
+}
+
+ChildPathConverter::ChildPathConverter(
+    const ChildPathConverter & source) throw() :
+    std::unary_function<const Gtk::TreePath &, Gtk::TreePath>(source),
+    treeModelFilter_(source.treeModelFilter_)
+{
+}
+
+ChildPathConverter::~ChildPathConverter() throw()
+{
+}
+
+ChildPathConverter &
+ChildPathConverter::operator=(const ChildPathConverter & source)
+                              throw()
+{
+    if (this != &source)
+    {
+        std::unary_function<const Gtk::TreePath &,
+                            Gtk::TreePath>::operator=(source);
+        treeModelFilter_ = source.treeModelFilter_;
+    }
+
+    return *this;
+}
+
+Gtk::TreeModel::Path
+ChildPathConverter::operator()(const Gtk::TreeModel::Path & path)
+                               throw()
+{
+    return treeModelFilter_->convert_path_to_child_path(path);
+}
+
 static const guint lowerZoomValue = 20;
 static const guint higherZoomValue = 100;
 static const guint initialZoomValue
@@ -449,6 +512,16 @@ BrowserRenderer::get_current_selection() throw()
     return thumbnailView_.get_selected_photos();
 }
 
+TreePathList
+BrowserRenderer::get_selected_paths() const throw()
+{
+    TreePathList paths = thumbnailView_.get_selected_items();
+    std::transform(paths.begin(), paths.end(),
+                   paths.begin(),
+                   ChildPathConverter(treeModelFilter_));
+    return paths;
+}
+
 void
 BrowserRenderer::present() throw()
 {
diff --git a/src/renderer/browser-renderer.h b/src/renderer/browser-renderer.h
index 19e8128..9c4fd48 100644
--- a/src/renderer/browser-renderer.h
+++ b/src/renderer/browser-renderer.h
@@ -73,6 +73,9 @@ class BrowserRenderer :
         virtual PhotoList
         get_current_selection() throw();
 
+        virtual TreePathList
+        get_selected_paths() const throw();
+
         virtual void
         present() throw();
 
diff --git a/src/renderer/cell-renderer-thumbnail.cpp b/src/renderer/cell-renderer-thumbnail.cpp
index aa4085f..8161086 100644
--- a/src/renderer/cell-renderer-thumbnail.cpp
+++ b/src/renderer/cell-renderer-thumbnail.cpp
@@ -34,6 +34,7 @@ namespace Solang
 {
 CellRendererThumbnail::CellRendererThumbnail() throw() :
     Gtk::CellRendererPixbuf(),
+    exportIcon_(0),
     photo_(),
     imageLoading_(0)
 {
@@ -99,6 +100,27 @@ CellRendererThumbnail::create_thumbnail(gint thumbnail_height,
 }
 
 void
+CellRendererThumbnail::load_export_icon() throw()
+{
+    const IconThemePtr icon_theme = Gtk::IconTheme::get_default();
+    const Gtk::IconInfo icon_info
+        = icon_theme->lookup_icon(
+                          "conduit-source",
+                          22,
+                          Gtk::ICON_LOOKUP_FORCE_SIZE);
+
+    if (true == icon_info)
+    {
+        const Glib::ustring & filename = icon_info.get_filename();
+        exportIcon_ = Cairo::ImageSurface::create_from_png(filename);
+    }
+    else
+    {
+        exportIcon_.clear();
+    }
+}
+
+void
 CellRendererThumbnail::load_icons() throw()
 {
     const IconThemePtr icon_theme = Gtk::IconTheme::get_default();
@@ -137,6 +159,9 @@ CellRendererThumbnail::render_vfunc(
                          cell_area.get_width() - 6);
     }
 
+    const Cairo::RefPtr<Cairo::Context> context
+        = window->create_cairo_context();
+
     if (0 == (flags & (Gtk::CELL_RENDERER_SELECTED
                        | Gtk::CELL_RENDERER_PRELIT)))
     {
@@ -152,10 +177,7 @@ CellRendererThumbnail::render_vfunc(
         const gint x = background_area.get_x();
         const gint y = background_area.get_y();
 
-        const Cairo::RefPtr<Cairo::Context> context
-            = window->create_cairo_context();
         const StylePtr style = widget.get_style();
-
         const Gdk::Color color = style->get_dark(Gtk::STATE_NORMAL);
         Gdk::Cairo::set_source_color(context, color);
 
@@ -168,6 +190,22 @@ CellRendererThumbnail::render_vfunc(
 
     Gtk::CellRendererPixbuf::render_vfunc(window, widget, background_area,
                                           cell_area, expose_area, flags);
+
+    if (true == photo_->get_state_export_queue())
+    {
+        if (0 == exportIcon_)
+        {
+            load_export_icon();
+        }
+        if (0 != exportIcon_)
+        {
+            const gint x = background_area.get_x();
+            const gint y = background_area.get_y();
+
+            context->set_source(exportIcon_, x, y);
+            context->paint();
+        }
+    }
 }
 
 void
diff --git a/src/renderer/cell-renderer-thumbnail.h b/src/renderer/cell-renderer-thumbnail.h
index da4d1e9..da88c19 100644
--- a/src/renderer/cell-renderer-thumbnail.h
+++ b/src/renderer/cell-renderer-thumbnail.h
@@ -54,11 +54,16 @@ class CellRendererThumbnail :
                          gint thumbnail_width) throw();
 
         void
+        load_export_icon() throw();
+
+        void
         load_icons() throw();
 
         void
         on_icon_theme_changed() throw();
 
+        Cairo::RefPtr<Cairo::ImageSurface> exportIcon_;
+
         PhotoPtr photo_;
 
         PixbufPtr imageLoading_;
diff --git a/src/renderer/enlarged-renderer.cpp b/src/renderer/enlarged-renderer.cpp
index a7bc120..bb442c1 100644
--- a/src/renderer/enlarged-renderer.cpp
+++ b/src/renderer/enlarged-renderer.cpp
@@ -509,6 +509,19 @@ EnlargedRenderer::get_current_selection() throw()
     return photos;
 }
 
+TreePathList
+EnlargedRenderer::get_selected_paths() const throw()
+{
+    const TreeModelPtr & tree_model = application_->get_list_store();
+    const Gtk::TreeModel::iterator & iter
+        = application_->get_list_store_iter();
+
+    TreePathList paths;
+    paths.push_back(tree_model->get_path(iter));
+
+    return paths;
+}
+
 void
 EnlargedRenderer::present() throw()
 {
diff --git a/src/renderer/enlarged-renderer.h b/src/renderer/enlarged-renderer.h
index 6421288..35b025f 100644
--- a/src/renderer/enlarged-renderer.h
+++ b/src/renderer/enlarged-renderer.h
@@ -71,6 +71,9 @@ class EnlargedRenderer :
         virtual PhotoList
         get_current_selection() throw();
 
+        virtual TreePathList
+        get_selected_paths() const throw();
+
         virtual void
         present() throw();
 
diff --git a/src/renderer/slideshow-renderer.cpp b/src/renderer/slideshow-renderer.cpp
index 89ae6c4..3dfb27f 100644
--- a/src/renderer/slideshow-renderer.cpp
+++ b/src/renderer/slideshow-renderer.cpp
@@ -256,6 +256,19 @@ SlideshowRenderer::get_current_selection() throw()
     return photos;
 }
 
+TreePathList
+SlideshowRenderer::get_selected_paths() const throw()
+{
+    const TreeModelPtr & tree_model = application_->get_list_store();
+    const Gtk::TreeModel::iterator & iter
+        = application_->get_list_store_iter();
+
+    TreePathList paths;
+    paths.push_back(tree_model->get_path(iter));
+
+    return paths;
+}
+
 void
 SlideshowRenderer::present() throw()
 {
diff --git a/src/renderer/slideshow-renderer.h b/src/renderer/slideshow-renderer.h
index 94f82c9..ab9107d 100644
--- a/src/renderer/slideshow-renderer.h
+++ b/src/renderer/slideshow-renderer.h
@@ -66,6 +66,9 @@ class SlideshowRenderer :
         virtual PhotoList
         get_current_selection() throw();
 
+        virtual TreePathList
+        get_selected_paths() const throw();
+
         virtual void
         present() throw();
 



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