Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libnemo-private/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ nemo_private_sources = [
'nemo-directory-async.c',
'nemo-directory.c',
'nemo-dnd.c',
'nemo-emblem.c',
'nemo-emblemed-icon.c',
'nemo-entry.c',
'nemo-file-changes-queue.c',
'nemo-file-conflict-dialog.c',
Expand Down
136 changes: 136 additions & 0 deletions libnemo-private/nemo-emblem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/* nemo-emblem.c - Custom emblem with size and position control
*
* Copyright (C) 2026 Linux Mint
*
* 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.
*/

#include <config.h>
#include "nemo-emblem.h"

struct _NemoEmblem {
GObject parent_instance;

GIcon *icon;
NemoEmblemSize size;
NemoEmblemPosition position;
};

static void nemo_emblem_icon_iface_init (GIconIface *iface);

G_DEFINE_TYPE_WITH_CODE (NemoEmblem, nemo_emblem, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_ICON, nemo_emblem_icon_iface_init))

static void
nemo_emblem_finalize (GObject *object)
{
NemoEmblem *emblem = NEMO_EMBLEM (object);

g_clear_object (&emblem->icon);

G_OBJECT_CLASS (nemo_emblem_parent_class)->finalize (object);
}

static guint
nemo_emblem_hash (GIcon *icon)
{
NemoEmblem *emblem = NEMO_EMBLEM (icon);

return g_icon_hash (emblem->icon) ^ (emblem->size << 8) ^ (emblem->position << 16);
}

static gboolean
nemo_emblem_equal (GIcon *icon1, GIcon *icon2)
{
NemoEmblem *a = NEMO_EMBLEM (icon1);
NemoEmblem *b = NEMO_EMBLEM (icon2);

return g_icon_equal (a->icon, b->icon) &&
a->size == b->size &&
a->position == b->position;
}

static GVariant *
nemo_emblem_serialize (GIcon *icon)
{
NemoEmblem *emblem = NEMO_EMBLEM (icon);
GVariant *inner;

inner = g_icon_serialize (emblem->icon);
if (inner == NULL) {
return NULL;
}

GVariant *result = g_variant_new ("(vii)", inner, (gint32) emblem->size, (gint32) emblem->position);
return result;
}

static void
nemo_emblem_icon_iface_init (GIconIface *iface)
{
iface->hash = nemo_emblem_hash;
iface->equal = nemo_emblem_equal;
iface->serialize = nemo_emblem_serialize;
}

static void
nemo_emblem_class_init (NemoEmblemClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);

object_class->finalize = nemo_emblem_finalize;
}

static void
nemo_emblem_init (NemoEmblem *emblem)
{
}

NemoEmblem *
nemo_emblem_new (GIcon *icon,
NemoEmblemSize size,
NemoEmblemPosition position)
{
NemoEmblem *emblem;

g_return_val_if_fail (G_IS_ICON (icon), NULL);

emblem = g_object_new (NEMO_TYPE_EMBLEM, NULL);
emblem->icon = g_object_ref (icon);
emblem->size = size;
emblem->position = position;

return emblem;
}

GIcon *
nemo_emblem_get_icon (NemoEmblem *emblem)
{
g_return_val_if_fail (NEMO_IS_EMBLEM (emblem), NULL);

return emblem->icon;
}

NemoEmblemSize
nemo_emblem_get_size (NemoEmblem *emblem)
{
g_return_val_if_fail (NEMO_IS_EMBLEM (emblem), NEMO_EMBLEM_SIZE_SMALL);

return emblem->size;
}

NemoEmblemPosition
nemo_emblem_get_position (NemoEmblem *emblem)
{
g_return_val_if_fail (NEMO_IS_EMBLEM (emblem), NEMO_EMBLEM_POSITION_DEFAULT);

return emblem->position;
}
51 changes: 51 additions & 0 deletions libnemo-private/nemo-emblem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* nemo-emblem.h - Custom emblem with size and position control
*
* Copyright (C) 2026 Linux Mint
*
* 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.
*/

#ifndef NEMO_EMBLEM_H
#define NEMO_EMBLEM_H

#include <gio/gio.h>

G_BEGIN_DECLS

typedef enum {
NEMO_EMBLEM_SIZE_EXTRA_SMALL, /* ~15% of icon size */
NEMO_EMBLEM_SIZE_SMALL, /* ~25% of icon size */
NEMO_EMBLEM_SIZE_MEDIUM, /* ~33% of icon size */
NEMO_EMBLEM_SIZE_LARGE /* ~50% of icon size */
} NemoEmblemSize;

typedef enum {
NEMO_EMBLEM_POSITION_DEFAULT, /* auto-assign: cycles LR -> LL -> UR -> UL */
NEMO_EMBLEM_POSITION_UPPER_LEFT,
NEMO_EMBLEM_POSITION_UPPER_RIGHT,
NEMO_EMBLEM_POSITION_LOWER_LEFT,
NEMO_EMBLEM_POSITION_LOWER_RIGHT
} NemoEmblemPosition;

#define NEMO_TYPE_EMBLEM (nemo_emblem_get_type ())

G_DECLARE_FINAL_TYPE (NemoEmblem, nemo_emblem, NEMO, EMBLEM, GObject)

NemoEmblem * nemo_emblem_new (GIcon *icon,
NemoEmblemSize size,
NemoEmblemPosition position);
GIcon * nemo_emblem_get_icon (NemoEmblem *emblem);
NemoEmblemSize nemo_emblem_get_size (NemoEmblem *emblem);
NemoEmblemPosition nemo_emblem_get_position (NemoEmblem *emblem);

G_END_DECLS

#endif /* NEMO_EMBLEM_H */
171 changes: 171 additions & 0 deletions libnemo-private/nemo-emblemed-icon.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/* nemo-emblemed-icon.c - Icon with custom emblem compositing
*
* Copyright (C) 2026 Linux Mint
*
* 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.
*/

#include <config.h>
#include "nemo-emblemed-icon.h"

struct _NemoEmblemedIcon {
GObject parent_instance;

GIcon *icon;
GList *emblems;
};

static void nemo_emblemed_icon_icon_iface_init (GIconIface *iface);

G_DEFINE_TYPE_WITH_CODE (NemoEmblemedIcon, nemo_emblemed_icon, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_ICON, nemo_emblemed_icon_icon_iface_init))

static void
nemo_emblemed_icon_finalize (GObject *object)
{
NemoEmblemedIcon *self = NEMO_EMBLEMED_ICON (object);

g_clear_object (&self->icon);
g_list_free_full (self->emblems, g_object_unref);

G_OBJECT_CLASS (nemo_emblemed_icon_parent_class)->finalize (object);
}

static guint
nemo_emblemed_icon_hash (GIcon *icon)
{
NemoEmblemedIcon *self = NEMO_EMBLEMED_ICON (icon);
guint hash;
GList *l;

hash = g_icon_hash (self->icon);

for (l = self->emblems; l != NULL; l = l->next) {
hash ^= g_icon_hash (G_ICON (l->data));
}

return hash;
}

static gboolean
nemo_emblemed_icon_equal (GIcon *icon1, GIcon *icon2)
{
NemoEmblemedIcon *a = NEMO_EMBLEMED_ICON (icon1);
NemoEmblemedIcon *b = NEMO_EMBLEMED_ICON (icon2);
GList *la, *lb;

if (!g_icon_equal (a->icon, b->icon)) {
return FALSE;
}

if (g_list_length (a->emblems) != g_list_length (b->emblems)) {
return FALSE;
}

for (la = a->emblems, lb = b->emblems; la != NULL; la = la->next, lb = lb->next) {
if (!g_icon_equal (G_ICON (la->data), G_ICON (lb->data))) {
return FALSE;
}
}

return TRUE;
}

static GVariant *
nemo_emblemed_icon_serialize (GIcon *icon)
{
NemoEmblemedIcon *self = NEMO_EMBLEMED_ICON (icon);
GVariantBuilder builder;
GVariant *inner;
GList *l;

inner = g_icon_serialize (self->icon);
if (inner == NULL) {
return NULL;
}

g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));

for (l = self->emblems; l != NULL; l = l->next) {
GVariant *emblem_v = g_icon_serialize (G_ICON (l->data));
if (emblem_v != NULL) {
g_variant_builder_add (&builder, "v", emblem_v);
}
}

return g_variant_new ("(vav)", inner, &builder);
}

static void
nemo_emblemed_icon_icon_iface_init (GIconIface *iface)
{
iface->hash = nemo_emblemed_icon_hash;
iface->equal = nemo_emblemed_icon_equal;
iface->serialize = nemo_emblemed_icon_serialize;
}

static void
nemo_emblemed_icon_class_init (NemoEmblemedIconClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);

object_class->finalize = nemo_emblemed_icon_finalize;
}

static void
nemo_emblemed_icon_init (NemoEmblemedIcon *self)
{
}

GIcon *
nemo_emblemed_icon_new (GIcon *icon,
NemoEmblem *emblem)
{
NemoEmblemedIcon *self;

g_return_val_if_fail (G_IS_ICON (icon), NULL);

self = g_object_new (NEMO_TYPE_EMBLEMED_ICON, NULL);
self->icon = g_object_ref (icon);

if (emblem != NULL) {
self->emblems = g_list_append (self->emblems, g_object_ref (emblem));
}

return G_ICON (self);
}

void
nemo_emblemed_icon_add_emblem (NemoEmblemedIcon *emblemed_icon,
NemoEmblem *emblem)
{
g_return_if_fail (NEMO_IS_EMBLEMED_ICON (emblemed_icon));
g_return_if_fail (NEMO_IS_EMBLEM (emblem));

emblemed_icon->emblems = g_list_append (emblemed_icon->emblems,
g_object_ref (emblem));
}

GIcon *
nemo_emblemed_icon_get_icon (NemoEmblemedIcon *emblemed_icon)
{
g_return_val_if_fail (NEMO_IS_EMBLEMED_ICON (emblemed_icon), NULL);

return emblemed_icon->icon;
}

GList *
nemo_emblemed_icon_get_emblems (NemoEmblemedIcon *emblemed_icon)
{
g_return_val_if_fail (NEMO_IS_EMBLEMED_ICON (emblemed_icon), NULL);

return emblemed_icon->emblems;
}
Loading
Loading