%PDF- %PDF-
Direktori : /usr/share/gnome-shell/extensions/ding@rastersoft.com/app/ |
Current File : //usr/share/gnome-shell/extensions/ding@rastersoft.com/app/desktopIconItem.js |
/* DING: Desktop Icons New Generation for GNOME Shell * * Copyright (C) 2021 Sundeep Mediratta (smedius@gmail.com) * Copyright (C) 2019 Sergio Costas (rastersoft@gmail.com) * Based on code original (C) Carlos Soriano * SwitcherooControl code based on code original from Marsch84 * * 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, version 3 of the License. * * 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, see <http://www.gnu.org/licenses/>. */ /* exported dropDestination */ 'use strict'; const Gtk = imports.gi.Gtk; const Gdk = imports.gi.Gdk; const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; const Pango = imports.gi.Pango; const GdkPixbuf = imports.gi.GdkPixbuf; const Cairo = imports.gi.cairo; const DesktopIconsUtil = imports.desktopIconsUtil; const Prefs = imports.preferences; const Enums = imports.enums; const ByteArray = imports.byteArray; const Signals = imports.signals; const Gettext = imports.gettext.domain('ding'); const _ = Gettext.gettext; var desktopIconItem = class desktopIconItem { constructor(desktopManager, fileExtra) { this._signalIds = []; this._desktopManager = desktopManager; this._fileExtra = fileExtra; this._loadThumbnailDataCancellable = null; this._queryFileInfoCancellable = null; this._grid = null; this._lastClickTime = 0; this._lastClickButton = 0; this._clickCount = 0; this._isSelected = false; this._isSpecial = false; this._primaryButtonPressed = false; this._savedCoordinates = null; this._dropCoordinates = null; this._destroyed = false; } /** ********************* * Destroyers * ***********************/ removeFromGrid(callOnDestroy) { if (this._grid) { this._grid.removeItem(this); this._grid = null; } if (callOnDestroy) { this._onDestroy(); } } _destroy() { /* Regular file data */ if (this._queryFileInfoCancellable) { this._queryFileInfoCancellable.cancel(); } /* Thumbnailing */ if (this._loadThumbnailDataCancellable) { this._loadThumbnailDataCancellable.cancel(); } /* Disconnect signals */ for (let [object, signalId] of this._signalIds) { object.disconnect(signalId); } this._signalIds = []; this.container.destroy(); this.container = null; this._eventBox = null; this._shieldEventBox = null; this._labelEventBox = null; this._shieldLabelEventBox = null; this._icon = null; this._iconContainer = null; this._label = null; this._labelContainer = null; this.iconRectangle = null; } _onDestroy() { if (!this._destroyed) { this._destroy(); this._destroyed = true; } } _connectSignal(object, signal, callback) { this._signalIds.push([object, object.connect(signal, callback)]); } /** ********************* * Creators * ***********************/ _createIconActor() { this.container = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL, halign: Gtk.Align.CENTER}); this._connectSignal(this.container, 'destroy', () => this._onDestroy()); this._eventBox = new Gtk.EventBox({visible: true, halign: Gtk.Align.CENTER}); this._shieldEventBox = new Gtk.EventBox({visible: true, halign: Gtk.Align.CENTER}); this._labelEventBox = new Gtk.EventBox({visible: true, halign: Gtk.Align.CENTER}); this._shieldLabelEventBox = new Gtk.EventBox({visible: true, halign: Gtk.Align.CENTER}); this._icon = new Gtk.Image(); this._iconContainer = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL}); this._iconContainer.pack_start(this._icon, true, true, 0); this._iconContainer.set_baseline_position(Gtk.BaselinePosition.CENTER); this._eventBox.add(this._iconContainer); this._shieldEventBox.add(this._eventBox); this._label = new Gtk.Label(); this._containerAccessibility = this._iconContainer; this._containerAccessibility.set_can_focus(true); this._labelContainer = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL, halign: Gtk.Align.CENTER}); let labelStyleContext = this._label.get_style_context(); if (this._desktopManager.darkText) { labelStyleContext.add_class('file-label-dark'); } else { labelStyleContext.add_class('file-label'); } labelStyleContext = undefined; // prevent memory leaks this._label.set_ellipsize(Pango.EllipsizeMode.END); this._label.set_line_wrap(true); this._label.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR); this._label.set_yalign(0.0); this._label.set_justify(Gtk.Justification.CENTER); this._label.set_lines(2); this._labelContainer.pack_start(this._label, false, true, 0); this._labelEventBox.add(this._labelContainer); this._shieldLabelEventBox.add(this._labelEventBox); this.container.pack_start(this._shieldEventBox, false, false, 0); this.container.pack_start(this._shieldLabelEventBox, false, false, 0); this._styleContext = this._iconContainer.get_style_context(); this._labelStyleContext = this._labelContainer.get_style_context(); this._styleContext.add_class('file-item'); this._labelStyleContext.add_class('file-item'); this.iconRectangle = new Gdk.Rectangle(); this.labelRectangle = new Gdk.Rectangle(); /* We need to allow the "button-press" event to pass through the callbacks, to allow the DnD to work * But we must avoid them to reach the main window. * The solution is to allow them to pass in a EventBox, used both for detecting the events and the DnD, and block them * in a second EventBox, located outside. */ this._connectSignal(this._shieldEventBox, 'button-press-event', (actor, event) => { return true; }); this._connectSignal(this._shieldLabelEventBox, 'button-press-event', (actor, event) => { return true; }); this._connectSignal(this._eventBox, 'button-press-event', (actor, event) => this._onPressButton(actor, event)); this._connectSignal(this._eventBox, 'enter-notify-event', (actor, event) => this._onEnter(this._eventBox)); this._connectSignal(this._eventBox, 'leave-notify-event', (actor, event) => this._onLeave(this._eventBox)); this._connectSignal(this._eventBox, 'button-release-event', (actor, event) => this._onReleaseButton(actor, event)); this._connectSignal(this._eventBox, 'drag-motion', (widget, context, x, y, time) => { this.highLightDropTarget(x, y); this._updateDragStatus(context, time); }); this._connectSignal(this._eventBox, 'drag-leave', () => { this.unHighLightDropTarget(); }); this._connectSignal(this._eventBox, 'size-allocate', () => this._calculateIconRectangle()); this._connectSignal(this._labelEventBox, 'button-press-event', (actor, event) => this._onPressButton(actor, event)); this._connectSignal(this._labelEventBox, 'enter-notify-event', (actor, event) => this._onEnter(this._labelEventBox)); this._connectSignal(this._labelEventBox, 'leave-notify-event', (actor, event) => this._onLeave(this._labelEventBox)); this._connectSignal(this._labelEventBox, 'button-release-event', (actor, event) => this._onReleaseButton(actor, event)); this._connectSignal(this._labelEventBox, 'drag-motion', (widget, context, x, y, time) => { this.highLightDropTarget(x, y); this._updateDragStatus(context, time); }); this._connectSignal(this._labelEventBox, 'drag-leave', () => { this.unHighLightDropTarget(); }); this._connectSignal(this._labelEventBox, 'size-allocate', () => { this._doLabelSizeAllocated(); }); this._connectSignal(this.container, 'drag-motion', (widget, context, x, y, time) => { this.highLightDropTarget(x, y); this._updateDragStatus(context, time); }); this._connectSignal(this.container, 'drag-leave', () => { this.unHighLightDropTarget(); }); if (this._desktopManager.showDropPlace) { this._setDropDestination(this.container); } else { this._setDropDestination(this._eventBox); this._setDropDestination(this._labelEventBox); } this._setDragSource(this._eventBox); this._setDragSource(this._labelEventBox); this.container.show_all(); } _doLabelSizeAllocated() { this._calculateLabelRectangle(); } _calculateIconRectangle() { this.iconwidth = this._iconContainer.get_allocated_width(); this.iconheight = this._iconContainer.get_allocated_height(); let [x, y] = this._grid.coordinatesLocalToGlobal(0, 0, this._iconContainer); this.iconRectangle.x = x; this.iconRectangle.y = y; this.iconRectangle.width = this.iconwidth; this.iconRectangle.height = this.iconheight; } _calculateLabelRectangle() { this.labelwidth = this._labelContainer.get_allocated_width(); this.labelheight = this._labelContainer.get_allocated_height(); let [x, y] = this._grid.coordinatesLocalToGlobal(0, 0, this._labelContainer); this.labelRectangle.x = x; this.labelRectangle.y = y; this.labelRectangle.width = this.labelwidth; this.labelRectangle.height = this.labelheight; } setCoordinates(x, y, width, height, margin, grid) { this._x1 = x; this._y1 = y; this.width = width; this.height = height; this._grid = grid; this.container.set_size_request(width, height); this._label.margin_start = margin; this._label.margin_end = margin; this._label.margin_bottom = margin; this._iconContainer.margin_top = margin; this._calculateIconRectangle(); this._calculateLabelRectangle(); } getCoordinates() { this._x2 = this._x1 + this.container.get_allocated_width() - 1; this._y2 = this._y1 + this.container.get_allocated_height() - 1; return [this._x1, this._y1, this._x2, this._y2, this._grid]; } _setLabelName(text) { this._currentFileName = text; this._eventBox.set_tooltip_text(text); let lastCutPos = -1; let newText = ''; for (let pos = 0; pos < text.length; pos++) { let character = text[pos]; newText += character; if (pos < (text.length - 1)) { var nextChar = text[pos + 1]; } else { var nextChar = ''; } if (character == ' ') { lastCutPos = pos; } if (['.', ',', '-', '_', '@', ':'].includes(character)) { /* if the next character is already an space or this is the last * character, the string will be naturally cut here, so we do * nothing. */ if ((nextChar == ' ') || (nextChar == '')) { continue; } /* if there is a cut element in the last four previous characters, * do not add a new cut element. */ if ((lastCutPos > -1) && ((pos - lastCutPos) < 4)) { continue; } newText += '\u200B'; } } this._label.label = newText; } /** ********************* * Button Clicks * ***********************/ _updateClickState(event) { let settings = Gtk.Settings.get_default(); if ((event.get_button()[1] == this._lastClickButton) && ((event.get_time() - this._lastClickTime) < settings.gtk_double_click_time)) { this._clickCount++; } else { this._clickCount = 1; } this._lastClickTime = event.get_time(); this._lastClickButton = event.get_button()[1]; } getClickCount() { return this._clickCount; } _onPressButton(actor, event) { this._updateClickState(event); let button = event.get_button()[1]; let [a, x, y] = event.get_coords(); let state = event.get_state()[1]; this._buttonPressInitialX = x; this._buttonPressInitialY = y; let shiftPressed = !!(state & Gdk.ModifierType.SHIFT_MASK); let controlPressed = !!(state & Gdk.ModifierType.CONTROL_MASK); if (button == 3) { this._doButtonThreePressed(event, shiftPressed, controlPressed); } else if (button == 1) { this._doButtonOnePressed(event, shiftPressed, controlPressed); } return false; } _onReleaseButton(actor, event) { let button = event.get_button()[1]; if (button == 1) { this._doButtonOneReleased(event); } return false; } _doButtonThreePressed(event) { if (!this._isSelected) { this._desktopManager.selected(this, Enums.Selection.RIGHT_BUTTON); } this._desktopManager.fileItemMenu.showMenu(this, event); } _doButtonOnePressed(event, shiftPressed, controlPressed) { if (this.getClickCount() == 1) { this._primaryButtonPressed = true; if (shiftPressed || controlPressed) { this._desktopManager.selected(this, Enums.Selection.WITH_SHIFT); } else { this._desktopManager.selected(this, Enums.Selection.ALONE); } } } _doButtonOneReleased(event) { } /** ********************* * Drag and Drop * ***********************/ _onEnter(element) { if (!this._styleContext.has_class('file-item-hover')) { this._styleContext.add_class('file-item-hover'); this._labelStyleContext.add_class('file-item-hover'); } if (Prefs.CLICK_POLICY_SINGLE) { let window = element.get_window(); if (window) { window.set_cursor(Gdk.Cursor.new_from_name(Gdk.Display.get_default(), 'hand')); } } return false; } _onLeave(element) { this._primaryButtonPressed = false; if (this._styleContext.has_class('file-item-hover')) { this._styleContext.remove_class('file-item-hover'); this._labelStyleContext.remove_class('file-item-hover'); } if (Prefs.CLICK_POLICY_SINGLE) { let window = element.get_window(); if (window) { window.set_cursor(Gdk.Cursor.new_from_name(Gdk.Display.get_default(), 'default')); } } return false; } _hasToRouteDragToGrid() { if (this._grid) { return true; } return false; } _updateDragStatus(context, time) { if (DesktopIconsUtil.getModifiersInDnD(context, Gdk.ModifierType.CONTROL_MASK)) { Gdk.drag_status(context, Gdk.DragAction.COPY, time); } else { Gdk.drag_status(context, Gdk.DragAction.MOVE, time); } } highLightDropTarget() { if (this._hasToRouteDragToGrid()) { this._grid.receiveMotion(this._x1, this._y1, true); return; } if (!this._styleContext.has_class('desktop-icons-selected')) { this._styleContext.add_class('desktop-icons-selected'); this._labelStyleContext.add_class('desktop-icons-selected'); } this._grid.highLightGridAt(this._x1, this._y1); } unHighLightDropTarget() { if (this._hasToRouteDragToGrid()) { this._grid.receiveLeave(); return; } if (!this._isSelected && this._styleContext.has_class('desktop-icons-selected')) { this._styleContext.remove_class('desktop-icons-selected'); this._labelStyleContext.remove_class('desktop-icons-selected'); } this._grid.unHighLightGrids(); } setSelected() { this._isSelected = true; this._setSelectedStatus(); } unsetSelected() { this._isSelected = false; this._setSelectedStatus(); } toggleSelected() { this._isSelected = !this._isSelected; this._setSelectedStatus(); } _setSelectedStatus() { if (this._isSelected && !this._styleContext.has_class('desktop-icons-selected')) { this._styleContext.add_class('desktop-icons-selected'); this._labelStyleContext.add_class('desktop-icons-selected'); this._containerAccessibility.grab_focus(); } if (!this._isSelected && this._styleContext.has_class('desktop-icons-selected')) { this._styleContext.remove_class('desktop-icons-selected'); this._labelStyleContext.remove_class('desktop-icons-selected'); } } _setDragSource(widget) { widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, null, Gdk.DragAction.MOVE | Gdk.DragAction.COPY); let targets = new Gtk.TargetList(null); targets.add(Gdk.atom_intern('x-special/ding-icon-list', false), Gtk.TargetFlags.SAME_APP, Enums.DndTargetInfo.DING_ICON_LIST); if ((this._fileExtra != Enums.FileType.USER_DIRECTORY_TRASH) && (this._fileExtra != Enums.FileType.USER_DIRECTORY_HOME) && (this._fileExtra != Enums.FileType.EXTERNAL_DRIVE)) { targets.add(Gdk.atom_intern('x-special/gnome-icon-list', false), 0, Enums.DndTargetInfo.GNOME_ICON_LIST); targets.add(Gdk.atom_intern('text/uri-list', false), 0, Enums.DndTargetInfo.URI_LIST); } widget.drag_source_set_target_list(targets); targets = undefined; // prevent memory leaks this._connectSignal(widget, 'drag-begin', (w, context) => { const scale = this._icon.get_scale_factor(); let surf = new Cairo.ImageSurface(Cairo.SurfaceType.IMAGE, this.container.get_allocated_width() * scale, this.container.get_allocated_height() * scale); // setDeviceScale was introduced to GJS in version 1.69.2 if (scale != 1.0 && surf.setDeviceScale !== undefined) { surf.setDeviceScale(scale, scale); } let cr = new Cairo.Context(surf); this.container.draw(cr); let itemnumber = this._desktopManager.getNumberOfSelectedItems(); if (itemnumber > 1) { Gdk.cairo_set_source_rgba(cr, new Gdk.RGBA({ red: this._desktopManager.selectColor.red, green: this._desktopManager.selectColor.green, blue: this._desktopManager.selectColor.blue, alpha: 0.6, }) ); itemnumber -= 1; switch (itemnumber.toString().length) { case 1: cr.rectangle(1, 1, 30, 20); break; case 2: cr.rectangle(1, 1, 40, 20); break; default: cr.rectangle(1, 1, 50, 20); break; } cr.fill(); cr.setFontSize(18); Gdk.cairo_set_source_rgba(cr, new Gdk.RGBA({red: 1.0, green: 1.0, blue: 1.0, alpha: 1})); cr.moveTo(1, 17); cr.showText(`+${itemnumber}`); } Gtk.drag_set_icon_surface(context, surf); let [x, y] = this._calculateOffset(widget); context.set_hotspot(x, y); this._desktopManager.onDragBegin(this); cr.$dispose(); }); this._connectSignal(widget, 'drag-data-get', (w, context, data, info, time) => { let dragData = this._desktopManager.fillDragDataGet(info); if (dragData != null) { let list = ByteArray.fromString(dragData[1]); data.set(dragData[0], 8, list); } }); this._connectSignal(widget, 'drag-end', (w, context) => { this._desktopManager.onDragEnd(); }); } _calculateOffset(widget) { if (widget == this._eventBox) { return [((this.width - this.iconwidth) / 2) + this._buttonPressInitialX, this._buttonPressInitialY]; } else { return [((this.width - this.labelwidth) / 2) + this._buttonPressInitialX, (this.iconheight + 2) + this._buttonPressInitialY]; } } _setDropDestination(dropDestination) { } /** ********************* * Icon Rendering * ***********************/ updateIcon() { this._updateIcon(); } async _updateIcon() { if (this._destroyed) { return; } this._icon.set_padding(0, 0); try { let customIcon = this._fileInfo.get_attribute_as_string('metadata::custom-icon'); if (customIcon && (customIcon != '')) { let customIconFile = Gio.File.new_for_uri(customIcon); if (customIconFile.query_exists(null)) { let loadedImage = await this._loadImageAsIcon(customIconFile); if (loadedImage | this._destroyed) { return; } } } } catch (error) { print(`Error while updating icon: ${error.message}.\n${error.stack}`); } if (this._fileExtra == Enums.FileType.USER_DIRECTORY_TRASH) { let pixbuf = this._createEmblemedIcon(this._fileInfo.get_icon(), null); const scale = this._icon.get_scale_factor(); let surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, null); this._icon.set_from_surface(surface); return; } let iconSet = false; if (Prefs.nautilusSettings.get_string('show-image-thumbnails') != 'never') { let thumbnail = this._desktopManager.thumbnailLoader.getThumbnail(this, this._updateIcon.bind(this)); if (thumbnail != null) { let thumbnailFile = Gio.File.new_for_path(thumbnail); iconSet = await this._loadImageAsIcon(thumbnailFile); if (this._destroyed) { return; } } } if (!iconSet) { let pixbuf; if (this._isBrokenSymlink) { pixbuf = this._createEmblemedIcon(null, 'text-x-generic'); } else if (this._desktopFile && this._desktopFile.has_key('Icon')) { pixbuf = this._createEmblemedIcon(null, this._desktopFile.get_string('Icon')); } else { pixbuf = this._createEmblemedIcon(this._getDefaultIcon(), null); } const scale = this._icon.get_scale_factor(); let surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, null); this._icon.set_from_surface(surface); } } _getDefaultIcon() { if (this._fileExtra == Enums.FileType.EXTERNAL_DRIVE) { return this._custom.get_icon(); } return this._fileInfo.get_icon(); } _loadImageAsIcon(imageFile) { if (this._loadThumbnailDataCancellable) { this._loadThumbnailDataCancellable.cancel(); } this._loadThumbnailDataCancellable = new Gio.Cancellable(); return new Promise((resolve, reject) => { imageFile.load_bytes_async(this._loadThumbnailDataCancellable, (source, result) => { this._loadThumbnailDataCancellable = null; try { let [thumbnailData, etagOut] = source.load_bytes_finish(result); let thumbnailStream = Gio.MemoryInputStream.new_from_bytes(thumbnailData); let thumbnailPixbuf = GdkPixbuf.Pixbuf.new_from_stream(thumbnailStream, null); if (thumbnailPixbuf != null) { let width = Prefs.get_desired_width() - 8; let height = Prefs.get_icon_size() - 8; let aspectRatio = thumbnailPixbuf.width / thumbnailPixbuf.height; if ((width / height) > aspectRatio) { width = height * aspectRatio; } else { height = width / aspectRatio; } const scale = this._icon.get_scale_factor(); width *= scale; height *= scale; let pixbuf = thumbnailPixbuf.scale_simple(Math.floor(width), Math.floor(height), GdkPixbuf.InterpType.BILINEAR); pixbuf = this._addEmblemsToPixbufIfNeeded(pixbuf); let surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, scale, null); this._icon.set_from_surface(surface); this._icon.set_padding(4, 4); resolve(true); } resolve(false); } catch (e) { resolve(false); } }); }); } _copyAndResizeIfNeeded(pixbuf) { /** * If the pixbuf is the original from the theme, copies it into a new one, to be able * to paint the emblems without altering the cached pixbuf in the theme object. * Also, ensures that the copied pixbuf is, at least, as big as the desired icon size, * to ensure that the emblems fit. */ if (this._copiedPixbuf) { return pixbuf; } this._copiedPixbuf = true; let minsize = Prefs.get_icon_size(); if ((pixbuf.width < minsize) || (pixbuf.height < minsize)) { let width = pixbuf.width < minsize ? minsize : pixbuf.width; let height = pixbuf.height < minsize ? minsize : pixbuf.height; let newpixbuf = GdkPixbuf.Pixbuf.new(pixbuf.colorspace, true, pixbuf.bits_per_sample, width, height); newpixbuf.fill(0); let x = Math.floor((width - pixbuf.width) / 2); let y = Math.floor((height - pixbuf.height) / 2); pixbuf.composite(newpixbuf, x, y, pixbuf.width, pixbuf.height, x, y, 1, 1, GdkPixbuf.InterpType.NEAREST, 255); return newpixbuf; } else { return pixbuf.copy(); } } _addEmblemsToPixbufIfNeeded(pixbuf) { const scale = this._icon.get_scale_factor(); this._copiedPixbuf = false; let emblem = null; let finalSize = Math.floor(Prefs.get_icon_size() / 3) * scale; if (this._isDesktopFile && (!this._isValidDesktopFile || !this.trustedDesktopFile)) { pixbuf = this._copyAndResizeIfNeeded(pixbuf); pixbuf.saturate_and_pixelate(pixbuf, 0.5, true); emblem = Gio.ThemedIcon.new('emblem-unreadable'); pixbuf = this._copyAndResizeIfNeeded(pixbuf); let theme = Gtk.IconTheme.get_default(); let emblemIcon = theme.lookup_by_gicon_for_scale(emblem, finalSize / scale, scale, Gtk.IconLookupFlags.FORCE_SIZE).load_icon(); emblemIcon.composite(pixbuf, pixbuf.width - finalSize, pixbuf.height - finalSize, finalSize, finalSize, pixbuf.width - finalSize, pixbuf.height - finalSize, 1, 1, GdkPixbuf.InterpType.BILINEAR, 255); } if (this._isSymlink && (this._desktopManager.showLinkEmblem || this._isBrokenSymlink)) { if (this._isBrokenSymlink) { emblem = Gio.ThemedIcon.new('emblem-unreadable'); } else { emblem = Gio.ThemedIcon.new('emblem-symbolic-link'); } pixbuf = this._copyAndResizeIfNeeded(pixbuf); let theme = Gtk.IconTheme.get_default(); let emblemIcon = theme.lookup_by_gicon_for_scale(emblem, finalSize / scale, scale, Gtk.IconLookupFlags.FORCE_SIZE).load_icon(); emblemIcon.composite(pixbuf, pixbuf.width - finalSize, pixbuf.height - finalSize, finalSize, finalSize, pixbuf.width - finalSize, pixbuf.height - finalSize, 1, 1, GdkPixbuf.InterpType.BILINEAR, 255); } if (this.isStackTop && !this.stackUnique) { pixbuf = this._copyAndResizeIfNeeded(pixbuf); let theme = Gtk.IconTheme.get_default(); emblem = Gio.ThemedIcon.new('emblem-downloads'); let emblemIcon = theme.lookup_by_gicon_for_scale(emblem, finalSize / scale, scale, Gtk.IconLookupFlags.FORCE_SIZE).load_icon(); emblemIcon.composite(pixbuf, 0, 0, finalSize, finalSize, 0, 0, 1, 1, GdkPixbuf.InterpType.BILINEAR, 255); } return pixbuf; } _createEmblemedIcon(icon, iconName) { if (icon == null) { if (GLib.path_is_absolute(iconName)) { try { let iconFile = Gio.File.new_for_commandline_arg(iconName); icon = new Gio.FileIcon({file: iconFile}); } catch (e) { icon = Gio.ThemedIcon.new_with_default_fallbacks(iconName); } } else { icon = Gio.ThemedIcon.new_with_default_fallbacks(iconName); } } let theme = Gtk.IconTheme.get_default(); const scale = this._icon.get_scale_factor(); let itemIcon = null; try { itemIcon = theme.lookup_by_gicon_for_scale(icon, Prefs.get_icon_size(), scale, Gtk.IconLookupFlags.FORCE_SIZE).load_icon(); } catch (e) { itemIcon = theme.load_icon_for_scale('text-x-generic', Prefs.get_icon_size(), scale, Gtk.IconLookupFlags.FORCE_SIZE); } itemIcon = this._addEmblemsToPixbufIfNeeded(itemIcon); return itemIcon; } /** ********************* * Getters and setters * ***********************/ get state() { return this._state; } set state(state) { if (state == this._state) { return; } this._state = state; } get isDrive() { return this._fileExtra == Enums.FileType.EXTERNAL_DRIVE; } get isSelected() { return this._isSelected; } get isSpecial() { return this._isSpecial; } get dropCoordinates() { return this._dropCoordinates; } set dropCoordinates(pos) { this._dropCoordinates = pos; } }; Signals.addSignalMethods(desktopIconItem.prototype);