diff options
| author | Nick Dedekind <nicholas.dedekind@gmail.com> | 2012-08-22 11:03:52 +0100 |
|---|---|---|
| committer | Nick Dedekind <nicholas.dedekind@gmail.com> | 2012-08-22 11:03:52 +0100 |
| commit | 642a1de32bc551c1d76be7ec2769b951b43b04e1 (patch) | |
| tree | 03f239833bf55c0aa507ad9799dc6051ff1355b5 /unity-shared | |
| parent | 3f3b2209db2ce4151cd848ced4949b0e9bb1ccb9 (diff) | |
| parent | 23bb038d712302bbd87400ed39530c31fd5cd016 (diff) | |
Merge with trunk
(bzr r2588.1.4)
Diffstat (limited to 'unity-shared')
| -rw-r--r-- | unity-shared/CoverArt.cpp | 56 | ||||
| -rw-r--r-- | unity-shared/CoverArt.h | 13 | ||||
| -rwxr-xr-x[-rw-r--r--] | unity-shared/DashStyle.cpp | 0 | ||||
| -rwxr-xr-x[-rw-r--r--] | unity-shared/DashStyle.h | 0 | ||||
| -rw-r--r-- | unity-shared/IconLoader.cpp | 264 | ||||
| -rw-r--r-- | unity-shared/IconRenderer.cpp | 8 | ||||
| -rw-r--r-- | unity-shared/Introspectable.cpp | 17 | ||||
| -rw-r--r-- | unity-shared/Introspectable.h | 5 | ||||
| -rw-r--r-- | unity-shared/IntrospectableWrappers.cpp | 8 | ||||
| -rw-r--r-- | unity-shared/IntrospectableWrappers.h | 4 | ||||
| -rw-r--r-- | unity-shared/RatingsButton.cpp | 15 | ||||
| -rw-r--r-- | unity-shared/RatingsButton.h | 7 | ||||
| -rw-r--r-- | unity-shared/ThumbnailGenerator.cpp | 3 |
13 files changed, 359 insertions, 41 deletions
diff --git a/unity-shared/CoverArt.cpp b/unity-shared/CoverArt.cpp index c6949d499..f05666461 100644 --- a/unity-shared/CoverArt.cpp +++ b/unity-shared/CoverArt.cpp @@ -72,6 +72,19 @@ CoverArt::~CoverArt() notifier_->Cancel(); } +std::string CoverArt::GetName() const +{ + return "CoverArt"; +} + +void CoverArt::AddProperties(GVariantBuilder* builder) +{ + variant::BuilderWrapper(builder) + .add(GetAbsoluteGeometry()) + .add("image-hint", image_hint_) + .add("waiting", waiting_); +} + void CoverArt::SetImage(std::string const& image_hint) { spinner_timeout_.reset(); @@ -126,11 +139,18 @@ void CoverArt::SetImage(std::string const& image_hint) void CoverArt::GenerateImage(std::string const& uri) { - StartWaiting(); notifier_ = ThumbnailGenerator::Instance().GetThumbnail(uri, 512); - - notifier_->ready.connect(sigc::mem_fun(this, &CoverArt::OnThumbnailGenerated)); - notifier_->error.connect(sigc::mem_fun(this, &CoverArt::OnThumbnailError)); + if (notifier_) + { + StartWaiting(); + notifier_->ready.connect(sigc::mem_fun(this, &CoverArt::OnThumbnailGenerated)); + notifier_->error.connect(sigc::mem_fun(this, &CoverArt::OnThumbnailError)); + } + else + { + StopWaiting(); + SetNoImageAvailable(); + } } void CoverArt::StartWaiting() @@ -145,9 +165,9 @@ void CoverArt::StartWaiting() spinner_timeout_.reset(new glib::TimeoutSeconds(5, [&] { - texture_screenshot_.Release(); - waiting_ = false; + StopWaiting(); + texture_screenshot_.Release(); SetNoImageAvailable(); return false; })); @@ -155,6 +175,13 @@ void CoverArt::StartWaiting() QueueDraw(); } +void CoverArt::StopWaiting() +{ + spinner_timeout_.reset(); + frame_timeout_.reset(); + waiting_ = false; +} + void CoverArt::SetNoImageAvailable() { if (GetLayout()) @@ -170,9 +197,7 @@ void CoverArt::SetNoImageAvailable() void CoverArt::IconLoaded(std::string const& texid, unsigned size, glib::Object<GdkPixbuf> const& pixbuf) { // Finished waiting - spinner_timeout_.reset(); - frame_timeout_.reset(); - waiting_ = false; + StopWaiting(); stretch_image_ = false; if (!pixbuf) @@ -251,9 +276,7 @@ void CoverArt::IconLoaded(std::string const& texid, unsigned size, glib::Object< void CoverArt::TextureLoaded(std::string const& texid, unsigned size, glib::Object<GdkPixbuf> const& pixbuf) { // Finished waiting - spinner_timeout_.reset(); - frame_timeout_.reset(); - waiting_ = false; + StopWaiting(); stretch_image_ = true; if (!pixbuf) @@ -384,11 +407,6 @@ void CoverArt::DrawContent(nux::GraphicsEngine& gfx_engine, bool force_draw) gfx_engine.PopClippingRectangle(); } -std::string CoverArt::GetName() const -{ - return "CoverArt"; -} - void CoverArt::SetupViews() { nux::VLayout* layout = new nux::VLayout(); @@ -425,9 +443,7 @@ void CoverArt::OnThumbnailGenerated(std::string const& uri) void CoverArt::OnThumbnailError(std::string const& error_hint) { LOG_WARNING(logger) << "Failed to generate thumbnail: " << error_hint; - spinner_timeout_.reset(); - frame_timeout_.reset(); - waiting_ = false; + StopWaiting(); texture_screenshot_.Release(); if (GetLayout()) diff --git a/unity-shared/CoverArt.h b/unity-shared/CoverArt.h index 52c2a7f86..12215fe0b 100644 --- a/unity-shared/CoverArt.h +++ b/unity-shared/CoverArt.h @@ -30,6 +30,7 @@ #include <UnityCore/GLibSource.h> #include <NuxCore/ObjectPtr.h> #include "unity-shared/StaticCairoText.h" +#include "unity-shared/Introspectable.h" #include "ThumbnailGenerator.h" namespace unity @@ -39,7 +40,7 @@ namespace dash namespace previews { -class CoverArt : public nux::View +class CoverArt : public nux::View, public unity::debug::Introspectable { public: typedef nux::ObjectPtr<CoverArt> Ptr; @@ -52,9 +53,8 @@ public: void SetImage(std::string const& image_hint); // Use for generating an image for a uri which is not necessarily an image. void GenerateImage(std::string const& uri); - - // From debug::Introspectable - std::string GetName() const; + + void SetNoImageAvailable(); void SetFont(std::string const& font); @@ -74,7 +74,10 @@ protected: void TextureLoaded(std::string const& texid, unsigned size, glib::Object<GdkPixbuf> const& pixbuf); void StartWaiting(); - void SetNoImageAvailable(); + void StopWaiting(); + + virtual std::string GetName() const; + virtual void AddProperties(GVariantBuilder* builder); private: nux::ObjectPtr<nux::BaseTexture> texture_screenshot_; diff --git a/unity-shared/DashStyle.cpp b/unity-shared/DashStyle.cpp index 8ac12c7d7..8ac12c7d7 100644..100755 --- a/unity-shared/DashStyle.cpp +++ b/unity-shared/DashStyle.cpp diff --git a/unity-shared/DashStyle.h b/unity-shared/DashStyle.h index 440914d7d..440914d7d 100644..100755 --- a/unity-shared/DashStyle.h +++ b/unity-shared/DashStyle.h diff --git a/unity-shared/IconLoader.cpp b/unity-shared/IconLoader.cpp index 78c9e9ea9..7d236cb19 100644 --- a/unity-shared/IconLoader.cpp +++ b/unity-shared/IconLoader.cpp @@ -22,8 +22,13 @@ #include <queue> #include <sstream> #include <boost/algorithm/string.hpp> +#include <unity-protocol.h> +#include <pango/pango.h> +#include <pango/pangocairo.h> +#include <Nux/Nux.h> #include <NuxCore/Logger.h> +#include <NuxGraphics/CairoGraphics.h> #include <UnityCore/GLibSource.h> #include <UnityCore/GLibSignal.h> @@ -43,6 +48,8 @@ public: // The Handle typedef is used to explicitly indicate which integers are // infact our opaque handles. typedef int Handle; + static const int FONT_SIZE = 10; + static const int MIN_FONT_SIZE = 6; Impl(); @@ -64,6 +71,8 @@ public: void DisconnectHandle(Handle handle); + static void CalculateTextHeight(int* width, int* height); + private: enum IconLoaderRequestType @@ -85,9 +94,12 @@ private: Handle handle; Impl* impl; GtkIconInfo* icon_info; + bool no_cache; + int helper_handle; glib::Object<GdkPixbuf> result; glib::Error error; std::list<IconLoaderTask::Ptr> shadow_tasks; + unsigned idle_id; IconLoaderTask(IconLoaderRequestType type_, std::string const& data_, @@ -98,13 +110,17 @@ private: Impl* self_) : type(type_), data(data_), size(size_), key(key_) , slot(slot_), handle(handle_), impl(self_) - , icon_info(nullptr) + , icon_info(nullptr), no_cache(false), helper_handle(0), idle_id(0) {} ~IconLoaderTask() { if (icon_info) ::gtk_icon_info_free(icon_info); + if (helper_handle != 0) + impl->DisconnectHandle(helper_handle); + if (idle_id != 0) + g_source_remove(idle_id); } void InvokeSlot() @@ -180,7 +196,21 @@ private: glib::Error error; glib::Object<GIcon> icon(::g_icon_new_for_string(data.c_str(), &error)); - if (G_IS_FILE_ICON(icon.RawPtr())) + if (icon.IsType(UNITY_PROTOCOL_TYPE_ANNOTATED_ICON)) + { + UnityProtocolAnnotatedIcon *anno; + anno = UNITY_PROTOCOL_ANNOTATED_ICON(icon.RawPtr()); + GIcon* base_icon = unity_protocol_annotated_icon_get_icon(anno); + glib::String gicon_string(g_icon_to_string(base_icon)); + + no_cache = true; + auto helper_slot = sigc::bind(sigc::mem_fun(this, &IconLoaderTask::BaseIconLoaded), glib::object_cast<UnityProtocolAnnotatedIcon>(icon)); + helper_handle = impl->LoadFromGIconString(gicon_string.Str(), + size, helper_slot); + + return false; + } + else if (icon.IsType(G_TYPE_FILE_ICON)) { // [trasfer none] GFile* file = ::g_file_icon_get_file(G_FILE_ICON(icon.RawPtr())); @@ -191,7 +221,7 @@ private: return ProcessURITask(); } - else if (G_IS_ICON(icon.RawPtr())) + else if (icon.IsType(G_TYPE_ICON)) { GtkIconInfo* info = ::gtk_icon_theme_lookup_by_gicon(impl->theme_, icon, size, static_cast<GtkIconLookupFlags>(0)); @@ -241,6 +271,177 @@ private: return false; } + void CategoryIconLoaded(std::string const& base_icon_string, unsigned size, + glib::Object<GdkPixbuf> const& category_pixbuf, + glib::Object<UnityProtocolAnnotatedIcon> const& anno_icon) + { + helper_handle = 0; + if (category_pixbuf) + { + // assuming the category pixbuf is smaller than result + gdk_pixbuf_composite(category_pixbuf, result, // src, dest + 0, 0, // dest_x, dest_y + gdk_pixbuf_get_width(category_pixbuf), // dest_w + gdk_pixbuf_get_height(category_pixbuf), // dest_h + 0.0, 0.0, // offset_x, offset_y + 1.0, 1.0, // scale_x, scale_y + GDK_INTERP_NEAREST, // interpolation + 255); // src_alpha + } + + const gchar* detail_text = unity_protocol_annotated_icon_get_ribbon(anno_icon); + if (detail_text) + { + int icon_w = gdk_pixbuf_get_width(result); + int icon_h = gdk_pixbuf_get_height(result); + + int max_font_height; + CalculateTextHeight(nullptr, &max_font_height); + + max_font_height = max_font_height * 9 / 8; // let's have some padding on the stripe + int pixbuf_size = static_cast<int>( + sqrt(max_font_height*max_font_height*8)); + if (pixbuf_size > icon_w) pixbuf_size = icon_w; + + nux::CairoGraphics cairo_graphics(CAIRO_FORMAT_ARGB32, + pixbuf_size, pixbuf_size); + std::shared_ptr<cairo_t> cr(cairo_graphics.GetContext(), cairo_destroy); + + glib::Object<PangoLayout> layout; + PangoContext* pango_context = NULL; + GdkScreen* screen = gdk_screen_get_default(); // not ref'ed + glib::String font; + int dpi = -1; + + g_object_get(gtk_settings_get_default(), "gtk-font-name", &font, NULL); + g_object_get(gtk_settings_get_default(), "gtk-xft-dpi", &dpi, NULL); + cairo_set_font_options(cr.get(), gdk_screen_get_font_options(screen)); + layout = pango_cairo_create_layout(cr.get()); + std::shared_ptr<PangoFontDescription> desc(pango_font_description_from_string(font), pango_font_description_free); + pango_font_description_set_weight(desc.get(), PANGO_WEIGHT_BOLD); + int font_size = FONT_SIZE; + pango_font_description_set_size (desc.get(), font_size * PANGO_SCALE); + + pango_layout_set_font_description(layout, desc.get()); + pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); + + double size_dbl = static_cast<double>(pixbuf_size); + // we'll allow tiny bit of overflow since the text is rotated and there + // is some space left... FIXME: 10/9? / 11/10? + double max_text_width = sqrt(size_dbl*size_dbl / 2) * 9/8; + + pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); + pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); + + glib::String escaped_text(g_markup_escape_text(detail_text, -1)); + pango_layout_set_markup(layout, escaped_text, -1); + + pango_context = pango_layout_get_context(layout); // is not ref'ed + // FIXME: for reasons unknown, it looks better without this + //pango_cairo_context_set_font_options(pango_context, + // gdk_screen_get_font_options(screen)); + pango_cairo_context_set_resolution(pango_context, + dpi == -1 ? 96.0f : dpi/(float) PANGO_SCALE); + pango_layout_context_changed(layout); + + // find proper font size (can we do this before the rotation?) + int text_width, text_height; + pango_layout_get_pixel_size(layout, &text_width, nullptr); + while (text_width > max_text_width && font_size > MIN_FONT_SIZE) + { + font_size--; + pango_font_description_set_size (desc.get(), font_size * PANGO_SCALE); + pango_layout_set_font_description(layout, desc.get()); + pango_layout_get_pixel_size(layout, &text_width, nullptr); + } + pango_layout_set_width(layout, static_cast<int>(max_text_width * PANGO_SCALE)); + + cairo_set_operator(cr.get(), CAIRO_OPERATOR_CLEAR); + cairo_paint(cr.get()); + + cairo_set_operator(cr.get(), CAIRO_OPERATOR_OVER); + + // draw the trapezoid + cairo_move_to(cr.get(), 0.0, size_dbl); + cairo_line_to(cr.get(), size_dbl, 0.0); + cairo_line_to(cr.get(), size_dbl, size_dbl / 2.0); + cairo_line_to(cr.get(), size_dbl / 2.0, size_dbl); + cairo_close_path(cr.get()); + + // this should be #dd4814 + cairo_set_source_rgba(cr.get(), 0.86666f, 0.28235f, 0.07843f, 1.0f); + cairo_fill(cr.get()); + + // draw the text (rotated!) + cairo_set_source_rgba(cr.get(), 1.0f, 1.0f, 1.0f, 1.0f); + cairo_move_to(cr.get(), size_dbl * 0.25, size_dbl); + cairo_rotate(cr.get(), -G_PI_4); // rotate by -45 degrees + + pango_cairo_update_layout(cr.get(), layout); + pango_layout_get_pixel_size(layout, nullptr, &text_height); + // current point is now in the middle of the stripe, need to translate + // it, so that the text is centered + cairo_rel_move_to(cr.get(), 0.0, text_height / -2.0); + double diagonal = sqrt(size_dbl*size_dbl*2); + // x coordinate also needs to be shifted + cairo_rel_move_to(cr.get(), (diagonal - max_text_width) / 4, 0.0); + pango_cairo_show_layout(cr.get(), layout); + + // FIXME: going from image_surface to pixbuf, and then to texture :( + glib::Object<GdkPixbuf> detail_pb( + gdk_pixbuf_get_from_surface(cairo_graphics.GetSurface(), + 0, 0, + cairo_graphics.GetWidth(), + cairo_graphics.GetHeight())); + + gdk_pixbuf_composite(detail_pb, result, // src, dest + icon_w - pixbuf_size, // dest_x + icon_h - pixbuf_size, // dest_y + pixbuf_size, // dest_w + pixbuf_size, // dest_h + icon_w - pixbuf_size, // offset_x + icon_h - pixbuf_size, // offset_y + 1.0, 1.0, // scale_x, scale_y + GDK_INTERP_NEAREST, // interpolation + 255); // src_alpha + } + + idle_id = g_idle_add(LoadIconComplete, this); + } + + void BaseIconLoaded(std::string const& base_icon_string, unsigned size, + glib::Object<GdkPixbuf> const& base_pixbuf, + glib::Object<UnityProtocolAnnotatedIcon> const& anno_icon) + { + helper_handle = 0; + if (base_pixbuf) + { + result = gdk_pixbuf_copy(base_pixbuf); + // FIXME: can we composite the pixbuf in helper thread? + UnityProtocolCategoryType category = unity_protocol_annotated_icon_get_category(anno_icon); + auto helper_slot = sigc::bind(sigc::mem_fun(this, &IconLoaderTask::CategoryIconLoaded), anno_icon); + unsigned cat_size = size / 4; + // FIXME: we still don't have the category assets + switch (category) + { + case UNITY_PROTOCOL_CATEGORY_TYPE_MUSIC: + helper_handle = + impl->LoadFromIconName("emblem-favorite", cat_size, helper_slot); + break; + default: + // rest of the processing is the CategoryIconLoaded, lets invoke it + glib::Object<GdkPixbuf> null_pixbuf; + helper_slot("", cat_size, null_pixbuf); + break; + } + } + else + { + result = nullptr; + idle_id = g_idle_add(LoadIconComplete, this); + } + } + void PushSchedulerJob() { ::g_io_scheduler_push_job (LoaderJobFunc, this, nullptr, G_PRIORITY_HIGH_IDLE, nullptr); @@ -298,9 +499,9 @@ private: auto task = static_cast<IconLoaderTask*>(data); auto impl = task->impl; - if (GDK_IS_PIXBUF(task->result.RawPtr())) + if (task->result.IsType(GDK_TYPE_PIXBUF)) { - impl->cache_[task->key] = task->result; + if (!task->no_cache) impl->cache_[task->key] = task->result; } else { @@ -350,6 +551,13 @@ private: private: std::map<std::string, glib::Object<GdkPixbuf>> cache_; + /* FIXME: the reference counting of IconLoaderTasks with shared pointers + * is currently somewhat broken, and the queued_tasks_ member is what keeps + * it from crashing randomly. + * The IconLoader instance is assuming that it is the only owner of the loader + * tasks, but when they are being completed in a worker thread, the thread + * should own them as well (yet it doesn't), this could cause trouble + * in the future... You've been warned! */ std::map<std::string, IconLoaderTask::Ptr> queued_tasks_; std::queue<IconLoaderTask::Ptr> tasks_; std::map<Handle, IconLoaderTask::Ptr> task_map_; @@ -379,6 +587,16 @@ IconLoader::Impl::Impl() * apply immediately. */ cache_.clear(); }); + + // make sure the AnnotatedIcon type is registered, so we can deserialize it +#if GLIB_CHECK_VERSION(2, 34, 0) + g_type_ensure(unity_protocol_annotated_icon_get_type()); +#else + // we need to fool the compiler cause get_type is marked as G_GNUC_CONST, + // which isn't exactly true + volatile GType proto_icon = unity_protocol_annotated_icon_get_type(); + g_type_name(proto_icon); +#endif } int IconLoader::Impl::LoadFromIconName(std::string const& icon_name, @@ -440,6 +658,42 @@ void IconLoader::Impl::DisconnectHandle(Handle handle) } } +void IconLoader::Impl::CalculateTextHeight(int* width, int* height) +{ + // FIXME: what about CJK? + const char* const SAMPLE_MAX_TEXT = "Chromium Web Browser"; + GtkSettings* settings = gtk_settings_get_default(); + + nux::CairoGraphics util_cg(CAIRO_FORMAT_ARGB32, 1, 1); + cairo_t* cr = util_cg.GetInternalContext(); + + glib::String font; + int dpi = 0; + g_object_get(settings, + "gtk-font-name", &font, + "gtk-xft-dpi", &dpi, + NULL); + std::shared_ptr<PangoFontDescription> desc(pango_font_description_from_string(font), pango_font_description_free); + pango_font_description_set_weight(desc.get(), PANGO_WEIGHT_BOLD); + pango_font_description_set_size(desc.get(), FONT_SIZE * PANGO_SCALE); + + glib::Object<PangoLayout> layout(pango_cairo_create_layout(cr)); + pango_layout_set_font_description(layout, desc.get()); + pango_layout_set_text(layout, SAMPLE_MAX_TEXT, -1); + + PangoContext* cxt = pango_layout_get_context(layout); + GdkScreen* screen = gdk_screen_get_default(); + pango_cairo_context_set_font_options(cxt, gdk_screen_get_font_options(screen)); + pango_cairo_context_set_resolution(cxt, dpi / (double) PANGO_SCALE); + pango_layout_context_changed(layout); + + PangoRectangle log_rect; + pango_layout_get_extents(layout, NULL, &log_rect); + + if (width) *width = log_rect.width / PANGO_SCALE; + if (height) *height = log_rect.height / PANGO_SCALE; +} + // // Private Methods // diff --git a/unity-shared/IconRenderer.cpp b/unity-shared/IconRenderer.cpp index 2c37cc89c..aa3a9ccd5 100644 --- a/unity-shared/IconRenderer.cpp +++ b/unity-shared/IconRenderer.cpp @@ -745,7 +745,7 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, // Perspective correct v0.x, v0.y, 0.0f, 1.0f, s0 / v0.w, t0 / v0.w, 0.0f, 1.0f / v0.w, v1.x, v1.y, 0.0f, 1.0f, s1 / v1.w, t1 / v1.w, 0.0f, 1.0f / v1.w, -#ifdef USE_MODERN_COMPIZ_GL +#ifdef USE_GLES v3.x, v3.y, 0.0f, 1.0f, s3 / v3.w, t3 / v3.w, 0.0f, 1.0f / v3.w, v2.x, v2.y, 0.0f, 1.0f, s2 / v2.w, t2 / v2.w, 0.0f, 1.0f / v2.w, #else @@ -783,7 +783,7 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, local::shader_program_uv_persp_correction->SetUniformLocMatrix4fv((GLint)VPMatrixLocation, 1, false, (GLfloat*) & (_stored_projection_matrix.m)); } } -#ifndef USE_MODERN_COMPIZ_GL +#ifndef USE_GLES else { local::asm_shader->Begin(); @@ -821,13 +821,13 @@ void IconRenderer::RenderElement(nux::GraphicsEngine& GfxContext, CHECKGL(glUniform4fARB(DesatFactor, arg.saturation, arg.saturation, arg.saturation, arg.saturation)); nux::GetWindowThread()->GetGraphicsEngine().SetTexture(GL_TEXTURE0, icon); -#ifdef USE_MODERN_COMPIZ_GL +#ifdef USE_GLES CHECKGL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); #else CHECKGL(glDrawArrays(GL_QUADS, 0, 4)); #endif } -#ifndef USE_MODERN_COMPIZ_GL +#ifndef USE_GLES else { CHECKGL(glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, bg_color.red, bg_color.green, bg_color.blue, bg_color.alpha)); diff --git a/unity-shared/Introspectable.cpp b/unity-shared/Introspectable.cpp index 4ecd0fc18..bfd024c1e 100644 --- a/unity-shared/Introspectable.cpp +++ b/unity-shared/Introspectable.cpp @@ -82,10 +82,13 @@ Introspectable::AddChild(Introspectable* child) } void -Introspectable::RemoveChild(Introspectable* child) +Introspectable::RemoveChild(Introspectable* child, child_destructor destr) { _children.remove(child); child->_parents.remove(this); + + if (destr) + (*destr)(child); } std::string @@ -99,6 +102,18 @@ guint64 Introspectable::GetIntrospectionId() const return _id; } +void +Introspectable::RemoveAllChildren(child_destructor destr) +{ + for (auto child : _children) + { + child->_parents.remove(this); + if (destr) + (*destr)(child); + } + _children.clear(); +} + } } diff --git a/unity-shared/Introspectable.h b/unity-shared/Introspectable.h index 7814ca281..aab473cd5 100644 --- a/unity-shared/Introspectable.h +++ b/unity-shared/Introspectable.h @@ -32,13 +32,14 @@ class Introspectable { public: typedef std::list<Introspectable*> IntrospectableList; + typedef void(*child_destructor)(Introspectable*); Introspectable(); virtual ~Introspectable(); GVariant* Introspect(); virtual std::string GetName() const = 0; void AddChild(Introspectable* child); - void RemoveChild(Introspectable* child); + void RemoveChild(Introspectable* child, child_destructor = NULL); virtual void AddProperties(GVariantBuilder* builder) = 0; virtual IntrospectableList GetIntrospectableChildren(); guint64 GetIntrospectionId() const; @@ -48,6 +49,8 @@ protected: /// is if you have a property that simply *must* be called 'Children'. virtual std::string GetChildsName() const; + void RemoveAllChildren(child_destructor = NULL); + /* * AddProperties should be implemented as such ... * void ClassFoo::AddProperties (GVariantBuilder *builder) diff --git a/unity-shared/IntrospectableWrappers.cpp b/unity-shared/IntrospectableWrappers.cpp index dbf5b0de0..910628df4 100644 --- a/unity-shared/IntrospectableWrappers.cpp +++ b/unity-shared/IntrospectableWrappers.cpp @@ -25,11 +25,12 @@ namespace unity { namespace debug { - ResultWrapper::ResultWrapper(const dash::Result& result) + ResultWrapper::ResultWrapper(dash::Result const& result, nux::Geometry const& geo) : uri_(result.uri), name_(result.name), icon_hint_(result.icon_hint), - mime_type_(result.mimetype) + mime_type_(result.mimetype), + geo_(geo) { } @@ -44,7 +45,8 @@ namespace debug .add("uri", uri_) .add("name", name_) .add("icon_hint", icon_hint_) - .add("mimetype", mime_type_); + .add("mimetype", mime_type_) + .add(geo_); } } } diff --git a/unity-shared/IntrospectableWrappers.h b/unity-shared/IntrospectableWrappers.h index a999e52bb..5fae901ef 100644 --- a/unity-shared/IntrospectableWrappers.h +++ b/unity-shared/IntrospectableWrappers.h @@ -21,6 +21,7 @@ #define _INTROSPECTABLE_WRAPPERS_H #include <UnityCore/Result.h> +#include <Nux/Nux.h> #include "Introspectable.h" @@ -35,7 +36,7 @@ namespace debug class ResultWrapper: public Introspectable { public: - ResultWrapper(const dash::Result& result); + ResultWrapper(const dash::Result& result, nux::Geometry const& geo = nux::Geometry()); std::string GetName() const; void AddProperties(GVariantBuilder* builder); private: @@ -43,6 +44,7 @@ private: std::string name_; std::string icon_hint_; std::string mime_type_; + nux::Geometry geo_; }; } diff --git a/unity-shared/RatingsButton.cpp b/unity-shared/RatingsButton.cpp index b43ad9ba9..a4f44c639 100644 --- a/unity-shared/RatingsButton.cpp +++ b/unity-shared/RatingsButton.cpp @@ -23,6 +23,7 @@ #include <Nux/Nux.h> #include <NuxCore/Logger.h> +#include <UnityCore/Variant.h> #include "RatingsButton.h" #include "DashStyle.h" @@ -274,4 +275,18 @@ bool RatingsButton::AcceptKeyNavFocus() return editable_; } +std::string RatingsButton::GetName() const +{ + return "RatingsButton"; +} + +void RatingsButton::AddProperties(GVariantBuilder* builder) +{ + variant::BuilderWrapper(builder) + .add(GetAbsoluteGeometry()) + .add("rating", rating_) + .add("focused-star", focused_star_) + .add("editable", editable_); +} + } // namespace unity diff --git a/unity-shared/RatingsButton.h b/unity-shared/RatingsButton.h index 03fbb0f8d..7a8b57c62 100644 --- a/unity-shared/RatingsButton.h +++ b/unity-shared/RatingsButton.h @@ -26,11 +26,12 @@ #include <Nux/Nux.h> #include <Nux/ToggleButton.h> +#include "unity-shared/Introspectable.h" namespace unity { -class RatingsButton : public nux::ToggleButton +class RatingsButton : public unity::debug::Introspectable, public nux::ToggleButton { public: RatingsButton(int star_size, int star_gap, NUX_FILE_LINE_PROTO); @@ -47,6 +48,10 @@ protected: virtual bool AcceptKeyNavFocus(); virtual bool InspectKeyEvent(unsigned int eventType, unsigned int keysym, const char* character); + // Introspectable methods + std::string GetName() const; + void AddProperties(GVariantBuilder* builder); + private: void OnKeyDown(unsigned long event_type, unsigned long event_keysym, unsigned long event_state, const TCHAR* character, diff --git a/unity-shared/ThumbnailGenerator.cpp b/unity-shared/ThumbnailGenerator.cpp index c65f99ea0..a214afa07 100644 --- a/unity-shared/ThumbnailGenerator.cpp +++ b/unity-shared/ThumbnailGenerator.cpp @@ -457,6 +457,9 @@ ThumbnailGenerator& ThumbnailGenerator::Instance() ThumbnailNotifier::Ptr ThumbnailGenerator::GetThumbnail(std::string const& uri, int size) { + if (uri.empty()) + return ThumbnailNotifier::Ptr(); + return pimpl->GetThumbnail(uri, size); } |
