From 771bad2d59f9f3ad68f50306ad3ede219cc3ba96 Mon Sep 17 00:00:00 2001 From: abakkk Date: Fri, 11 Sep 2020 04:06:21 +0200 Subject: [PATCH] improve images * Let the user choose the directory. * Rework of Files.Images. * area.currentImage is now an ... image, not an index. * Add 'switch-image-file-reverse' keybinding. * Add image gicons (from thumbnails) in the submenu. * Images are reset on drawing mode left or on images added from the clipboard. --- README.md | 2 +- area.js | 43 ++++--- extension.js | 3 +- files.js | 117 ++++++++++++++---- locale/draw-on-your-screen.pot | 16 ++- menu.js | 80 ++++++------ prefs.js | 43 ++++++- schemas/gschemas.compiled | Bin 7216 -> 7392 bytes ...extensions.draw-on-your-screen.gschema.xml | 15 ++- shortcuts.js | 3 +- 10 files changed, 225 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 7ca6ea9..3877926 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Then save your beautiful work by taking a screenshot. * Insertable images: - Add your images (jpeg, png, svg) to `~/.local/share/drawOnYourScreen/images/`. + You can insert images (jpeg, png, svg) in your drawings. By default images are sought in `~/.local/share/drawOnYourScreen/images/` but the location is configurable in the preferences. Another way is to copy-past the images from Nautilus or any clipboard source by using the usual `Ctrl + V` shortcut inside the drawing mode. * Eraser and SVG: diff --git a/area.js b/area.js index 56abb52..1978efb 100644 --- a/area.js +++ b/area.js @@ -86,7 +86,7 @@ var DrawingArea = new Lang.Class({ this.undoneElements = []; this.currentElement = null; this.currentTool = Shapes.NONE; - this.currentImage = 0; + this.currentImage = null; this.currentTextRightAligned = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL; let fontName = St.Settings && St.Settings.get().font_name || Convenience.getSettings('org.gnome.desktop.interface').get_string('font-name'); this.currentFont = Pango.FontDescription.from_string(fontName); @@ -150,6 +150,17 @@ var DrawingArea = new Lang.Class({ this.colors.push(Clutter.Color.get_static(Clutter.StaticColor.WHITE)); }, + get currentImage() { + if (!this._currentImage) + this._currentImage = Files.Images.getNext(this._currentImage); + + return this._currentImage; + }, + + set currentImage(image) { + this._currentImage = image; + }, + get currentFontFamily() { return this.currentFont.get_family(); }, @@ -188,13 +199,6 @@ var DrawingArea = new Lang.Class({ this.currentFillRule = evenodd ? Cairo.FillRule.EVEN_ODD : Cairo.FillRule.WINDING; }, - getImages() { - let images = Files.Images.getImages(); - if (!images[this.currentImage]) - this.currentImage = Math.max(images.length - 1, 0); - return images; - }, - get fontFamilies() { if (!this._fontFamilies) { let otherFontFamilies = Elements.getAllFontFamilies().filter(family => { @@ -601,14 +605,11 @@ var DrawingArea = new Lang.Class({ points: [] }); } else if (this.currentTool == Shapes.IMAGE) { - let images = this.getImages(); - if (!images.length) - return; this.currentElement = new Elements.DrawingElement({ shape: this.currentTool, color: this.currentColor.to_string(), eraser: eraser, - image: images[this.currentImage], + image: this.currentImage, operator: this.currentOperator, points: [] }); @@ -988,21 +989,18 @@ var DrawingArea = new Lang.Class({ this.emit('show-osd', null, DisplayStrings.getTextAlignment(this.currentTextRightAligned), "", -1, false); }, - switchImageFile: function() { - let images = this.getImages(); - if (!images.length) - return; - if (images.length > 1) - this.currentImage = this.currentImage == images.length - 1 ? 0 : this.currentImage + 1; - this.emit('show-osd', images[this.currentImage].gicon, images[this.currentImage].toString(), "", -1, false); + switchImageFile: function(reverse) { + this.currentImage = Files.Images[reverse ? 'getPrevious' : 'getNext'](this.currentImage); + if (this.currentImage) + this.emit('show-osd', this.currentImage.gicon, this.currentImage.toString(), "", -1, false); }, pasteImageFiles: function() { - Files.Images.addImagesFromClipboard((images, index) => { - this.currentImage = index; + Files.Images.addImagesFromClipboard(lastImage => { + this.currentImage = lastImage; this.currentTool = Shapes.IMAGE; this.updatePointerCursor(); - this.emit('show-osd', images[this.currentImage].gicon, images[this.currentImage].toString(), "", -1, false); + this.emit('show-osd', this.currentImage.gicon, this.currentImage.toString(), "", -1, false); }); }, @@ -1088,6 +1086,7 @@ var DrawingArea = new Lang.Class({ this._redisplay(); this.closeMenu(); this.get_parent().set_background_color(null); + Files.Images.reset(); if (save) this.savePersistent(); }, diff --git a/extension.js b/extension.js index ec5a10e..7e60fb4 100644 --- a/extension.js +++ b/extension.js @@ -183,7 +183,8 @@ const AreaManager = new Lang.Class({ 'switch-fill-rule': this.activeArea.switchFillRule.bind(this.activeArea), 'switch-dash' : this.activeArea.switchDash.bind(this.activeArea), 'switch-fill' : this.activeArea.switchFill.bind(this.activeArea), - 'switch-image-file' : this.activeArea.switchImageFile.bind(this.activeArea), + 'switch-image-file' : this.activeArea.switchImageFile.bind(this.activeArea, false), + 'switch-image-file-reverse' : this.activeArea.switchImageFile.bind(this.activeArea, true), 'select-none-shape': () => this.activeArea.selectTool(Area.Tools.NONE), 'select-line-shape': () => this.activeArea.selectTool(Area.Tools.LINE), 'select-ellipse-shape': () => this.activeArea.selectTool(Area.Tools.ELLIPSE), diff --git a/files.js b/files.js index 867d1ff..492c506 100644 --- a/files.js +++ b/files.js @@ -31,8 +31,8 @@ const St = imports.gi.St; const ExtensionUtils = imports.misc.extensionUtils; const Me = ExtensionUtils.getCurrentExtension(); -const EXAMPLE_IMAGES = Me.dir.get_child('data').get_child('images'); -const USER_IMAGES = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir'], 'images'])); +const EXAMPLE_IMAGE_DIRECTORY = Me.dir.get_child('data').get_child('images'); +const DEFAULT_USER_IMAGE_LOCATION = GLib.build_filenamev([GLib.get_user_data_dir(), Me.metadata['data-dir'], 'images']); const Clipboard = St.Clipboard.get_default(); const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD; const ICON_DIR = Me.dir.get_child('data').get_child('icons'); @@ -66,6 +66,11 @@ var Image = new Lang.Class({ _init: function(params) { for (let key in params) this[key] = params[key]; + + if (this.info) { + this.displayName = this.info.get_display_name(); + this.contentType = this.info.get_content_type(); + } }, toString: function() { @@ -81,13 +86,31 @@ var Image = new Lang.Class({ }; }, - // only called from menu so file exists + get thumbnailFile() { + if (!this._thumbnailFile) { + if (this.info.has_attribute('thumbnail::path') && this.info.get_attribute_boolean('thumbnail::is-valid')) { + let thumbnailPath = this.info.get_attribute_as_string('thumbnail::path'); + this._thumbnailFile = Gio.File.new_for_path(thumbnailPath); + } + } + return this._thumbnailFile || null; + }, + + // only called from menu or area so this.file exists get gicon() { if (!this._gicon) - this._gicon = new Gio.FileIcon({ file: this.file }); + this._gicon = new Gio.FileIcon({ file: this.thumbnailFile || this.file }); return this._gicon; }, + // use only thumbnails in menu (memory) + get thumbnailGicon() { + if (this.contentType != 'image/svg+xml' && !this.thumbnailFile) + return null; + + return this.gicon; + }, + get bytes() { if (!this._bytes) { if (this.file) @@ -95,7 +118,7 @@ var Image = new Lang.Class({ // load_bytes available in GLib 2.56+ this._bytes = this.file.load_bytes(null)[0]; } catch(e) { - let [success_, contents] = this.file.load_contents(null); + let [, contents] = this.file.load_contents(null); if (contents instanceof Uint8Array) this._bytes = ByteArray.toGBytes(contents); else @@ -151,34 +174,73 @@ var Image = new Lang.Class({ } }); +// Get images with getPrevious, getNext, or by iterating over it. var Images = { - clipboardImages: [], + _images: [], + _clipboardImages: [], + _upToDate: false, - getImages: function() { - let images = []; + _clipboardImagesContains: function(file) { + return this._clipboardImages.some(image => image.file.equal(file)); + }, + + _getImages: function() { + if (this._upToDate) + return this._images; - [EXAMPLE_IMAGES, USER_IMAGES].forEach(directory => { + let images = []; + let userLocation = Me.drawingSettings.get_string('image-location') || DEFAULT_USER_IMAGE_LOCATION; + let userDirectory = Gio.File.new_for_commandline_arg(userLocation); + + [EXAMPLE_IMAGE_DIRECTORY, userDirectory].forEach(directory => { let enumerator; try { - enumerator = directory.enumerate_children('standard::display-name,standard::content-type', Gio.FileQueryInfoFlags.NONE, null); + enumerator = directory.enumerate_children('standard::,thumbnail::', Gio.FileQueryInfoFlags.NONE, null); } catch(e) { return; } - let fileInfo = enumerator.next_file(null); - while (fileInfo) { - if (fileInfo.get_content_type().indexOf('image') == 0) - images.push(new Image({ file: enumerator.get_child(fileInfo), contentType: fileInfo.get_content_type(), displayName: fileInfo.get_display_name() })); - fileInfo = enumerator.next_file(null); + let info = enumerator.next_file(null); + while (info) { + let file = enumerator.get_child(info); + + if (info.get_content_type().indexOf('image') == 0 && !this._clipboardImagesContains(file)) { + let index = this._images.findIndex(image => image.file.equal(file)); + if (index != -1) + images.push(this._images[index]); + else + images.push(new Image({ file, info })); + } + + info = enumerator.next_file(null); } enumerator.close(null); }); - images.sort((a, b) => { - return a.displayName.localeCompare(b.displayName); - }); - - return images.concat(this.clipboardImages); + this._images = images.concat(this._clipboardImages) + .sort((a, b) => a.toString().localeCompare(b.toString())); + this._upToDate = true; + return this._images; + }, + + [Symbol.iterator]: function() { + return this._getImages()[Symbol.iterator](); + }, + + getNext: function(currentImage) { + let images = this._getImages(); + let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : 0; + return images[index == images.length - 1 ? 0 : index + 1] || null; + }, + + getPrevious: function(currentImage) { + let images = this._getImages(); + let index = currentImage ? images.findIndex(image => image.file.equal(currentImage.file)) : 0; + return images[index <= 0 ? images.length - 1 : index - 1] || null; + }, + + reset: function() { + this._upToDate = false; }, addImagesFromClipboard: function(callback) { @@ -193,20 +255,21 @@ var Images = { let images = lines.filter(line => !!line) .map(line => Gio.File.new_for_commandline_arg(line)) .filter(file => file.query_exists(null)) - .map(file => [file, file.query_info('standard::display-name,standard::content-type', Gio.FileQueryInfoFlags.NONE, null)]) + .map(file => [file, file.query_info('standard::,thumbnail::', Gio.FileQueryInfoFlags.NONE, null)]) .filter(pair => pair[1].get_content_type().indexOf('image') == 0) - .map(pair => new Image({ file: pair[0], contentType: pair[1].get_content_type(), displayName: pair[1].get_display_name() })); + .map(pair => new Image({ file: pair[0], info: pair[1] })); // Prevent duplicated - images.filter(image => !this.clipboardImages.map(clipboardImage => clipboardImage.file).some(clipboardFile => clipboardFile.equal(image.file))) - .forEach(image => this.clipboardImages.push(image)); + images.filter(image => !this._clipboardImagesContains(image.file)) + .forEach(image => this._clipboardImages.push(image)); if (images.length) { + this.reset(); + let allImages = this._getImages(); let lastFile = images[images.length - 1].file; - let allImages = this.getImages(); let index = allImages.findIndex(image => image.file.equal(lastFile)); - callback(allImages, index); - } + callback(allImages[index]); + } }); } }; diff --git a/locale/draw-on-your-screen.pot b/locale/draw-on-your-screen.pot index 588f5f6..e4f93a3 100644 --- a/locale/draw-on-your-screen.pot +++ b/locale/draw-on-your-screen.pot @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: Draw On Your Screen\n" "Report-Msgid-Bugs-To: https://framagit.org/abakkk/DrawOnYourScreen/issues\n" -"POT-Creation-Date: 2020-09-09 08:40+0200\n" +"POT-Creation-Date: 2020-09-11 03:43+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -502,6 +502,12 @@ msgstr "" msgid "The line width in pixels" msgstr "" +msgid "Image location" +msgstr "" + +msgid "The location of the directory in which the image tool picks" +msgstr "" + msgid "Color palettes" msgstr "" @@ -544,6 +550,9 @@ msgstr "" msgid "Open previous drawing" msgstr "" +msgid "Paste images from the clipboard" +msgstr "" + msgid "Redo last brushstroke" msgstr "" @@ -640,7 +649,10 @@ msgstr "" msgid "Change font weight" msgstr "" -msgid "Change image file" +msgid "Change image" +msgstr "" + +msgid "Change image (reverse)" msgstr "" msgid "Change linecap" diff --git a/menu.js b/menu.js index 5d28811..12e8e5c 100644 --- a/menu.js +++ b/menu.js @@ -262,12 +262,7 @@ var DrawingMenu = new Lang.Class({ this.fontSection = fontSection; let imageSection = new PopupMenu.PopupMenuSection(); - let images = this.area.getImages(); - if (images.length) { - if (this.area.currentImage > images.length - 1) - this.area.currentImage = images.length - 1; - this._addSubMenuItem(imageSection, null, images, this.area, 'currentImage'); - } + this._addImageSubMenuItem(imageSection); this._addSeparator(imageSection); this.menu.addMenuItem(imageSection); imageSection.itemActivated = () => {}; @@ -398,34 +393,27 @@ var DrawingMenu = new Lang.Class({ }, _addSubMenuItem: function(menu, icon, obj, target, targetProperty, callback) { - if (targetProperty == 'currentImage') - icon = obj[target[targetProperty]].gicon; let item = new PopupMenu.PopupSubMenuMenuItem(String(obj[target[targetProperty]]), icon ? true : false); if (icon && icon instanceof GObject.Object && GObject.type_is_a(icon, Gio.Icon)) item.icon.set_gicon(icon); else if (icon) item.icon.set_icon_name(icon); - item.menu.itemActivated = () => { - item.menu.close(); - }; + item.menu.itemActivated = item.menu.close; GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { - for (let i in obj) { + Object.keys(obj).forEach(key => { let text; if (targetProperty == 'currentFontWeight') - text = `${obj[i]}`; + text = `${obj[key]}`; else if (targetProperty == 'currentFontStyle') - text = `${obj[i]}`; + text = `${obj[key]}`; else - text = String(obj[i]); + text = String(obj[key]); - let iCaptured = Number(i); let subItem = item.menu.addAction(text, () => { - item.label.set_text(String(obj[iCaptured])); - target[targetProperty] = iCaptured; - if (targetProperty == 'currentImage') - item.icon.set_gicon(obj[iCaptured].gicon); + item.label.set_text(String(obj[key])); + target[targetProperty] = Number(key); if (callback) callback(); }); @@ -434,13 +422,14 @@ var DrawingMenu = new Lang.Class({ getActor(subItem).connect('key-focus-in', updateSubMenuAdjustment); // change the display order of tools - if (obj == DisplayStrings.Tool && i == this.drawingTools.POLYGON) + if (obj == DisplayStrings.Tool && Number(key) == this.drawingTools.POLYGON) item.menu.moveMenuItem(subItem, 4); - else if (obj == DisplayStrings.Tool && i == this.drawingTools.POLYLINE) + else if (obj == DisplayStrings.Tool && Number(key) == this.drawingTools.POLYLINE) item.menu.moveMenuItem(subItem, 5); - } + }); return GLib.SOURCE_REMOVE; }); + menu.addMenuItem(item); }, @@ -449,9 +438,7 @@ var DrawingMenu = new Lang.Class({ let item = new PopupMenu.PopupSubMenuMenuItem(text, true); item.icon.set_gicon(Files.Icons.PALETTE); - item.menu.itemActivated = () => { - item.menu.close(); - }; + item.menu.itemActivated = item.menu.close; GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { this.area.palettes.forEach(palette => { @@ -468,6 +455,7 @@ var DrawingMenu = new Lang.Class({ }); return GLib.SOURCE_REMOVE; }); + menu.addMenuItem(item); return item; }, @@ -478,9 +466,7 @@ var DrawingMenu = new Lang.Class({ item.icon.set_gicon(Files.Icons.COLOR); item.icon.set_style(`color:${this.area.currentColor.to_string().slice(0, 7)};`); - item.menu.itemActivated = () => { - item.menu.close(); - }; + item.menu.itemActivated = item.menu.close; this._populateColorSubMenu(); menu.addMenuItem(item); @@ -508,9 +494,7 @@ var DrawingMenu = new Lang.Class({ let item = new PopupMenu.PopupSubMenuMenuItem(DisplayStrings.getFontFamily(this.area.currentFontFamily), true); item.icon.set_icon_name(icon); - item.menu.itemActivated = () => { - item.menu.close(); - }; + item.menu.itemActivated = item.menu.close; item.menu.openOld = item.menu.open; item.menu.open = (animate) => { @@ -531,6 +515,30 @@ var DrawingMenu = new Lang.Class({ menu.addMenuItem(item); }, + _addImageSubMenuItem: function(menu, images) { + let item = new PopupMenu.PopupSubMenuMenuItem(this.area.currentImage.toString(), true); + item.icon.set_gicon(this.area.currentImage.gicon); + + item.menu.itemActivated = item.menu.close; + + item.menu.openOld = item.menu.open; + item.menu.open = (animate) => { + if (!item.menu.isOpen && item.menu.isEmpty()) { + [...Files.Images].forEach(image => { + let subItem = item.menu.addAction(image.toString(), () => { + item.label.set_text(image.toString()); + this.area.currentImage = image; + item.icon.set_gicon(image.gicon); + }, image.thumbnailGicon || undefined); + getActor(subItem).connect('key-focus-in', updateSubMenuAdjustment); + }); + } + item.menu.openOld(); + }; + + menu.addMenuItem(item); + }, + _addDrawingNameItem: function(menu) { this.drawingNameMenuItem = new PopupMenu.PopupMenuItem('', { reactive: false, activate: false }); this.drawingNameMenuItem.setSensitive(false); @@ -554,9 +562,7 @@ var DrawingMenu = new Lang.Class({ item.setSensitive(Boolean(Files.getJsons().length)); item.icon.set_icon_name('document-open-symbolic'); - item.menu.itemActivated = () => { - item.menu.close(); - }; + item.menu.itemActivated = item.menu.close; item.menu.openOld = item.menu.open; item.menu.open = (animate) => { @@ -609,9 +615,7 @@ var DrawingMenu = new Lang.Class({ this.saveDrawingSubMenu = item.menu; item.icon.set_icon_name('document-save-symbolic'); - item.menu.itemActivated = () => { - item.menu.close(); - }; + item.menu.itemActivated = item.menu.close; item.menu.openOld = item.menu.open; item.menu.open = (animate) => { diff --git a/prefs.js b/prefs.js index a8d4c30..d334e29 100644 --- a/prefs.js +++ b/prefs.js @@ -23,6 +23,7 @@ const Atk = imports.gi.Atk; const Gdk = imports.gi.Gdk; +const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; const GObject = imports.gi.GObject; const Gtk = imports.gi.Gtk; @@ -268,6 +269,14 @@ const DrawingPage = new GObject.Class({ dashOffsetRow.addWidget(dashOffsetButton); toolsListBox.add(dashOffsetRow); + let imageLocationRow = new PrefRow({ label: this.schema.get_key('image-location').get_summary() }); + let imageLocationButton = new FileChooserButton({ action: Gtk.FileChooserAction.SELECT_FOLDER, + name: this.schema.get_key('image-location').get_summary(), + tooltip_text: this.schema.get_key('image-location').get_description() }); + this.settings.bind('image-location', imageLocationButton, 'location', 0); + imageLocationRow.addWidget(imageLocationButton); + toolsListBox.add(imageLocationRow); + let resetButton = new Gtk.Button({ label: _("Reset settings"), halign: Gtk.Align.CENTER }); resetButton.get_style_context().add_class('destructive-action'); resetButton.connect('clicked', () => this.schema.list_keys().forEach(key => this.settings.reset(key))); @@ -565,8 +574,7 @@ const ColorStringButton = new GObject.Class({ Extends: Gtk.ColorButton, Properties: { 'color-string': GObject.ParamSpec.string('color-string', 'colorString', 'A string that describes the color', - GObject.ParamFlags.READWRITE, - 'black') + GObject.ParamFlags.READWRITE, 'black') }, get color_string() { @@ -593,6 +601,37 @@ const ColorStringButton = new GObject.Class({ } }); +const FileChooserButton = new GObject.Class({ + Name: 'DrawOnYourScreenFileChooserButton', + GTypeName: 'DrawOnYourScreenFileChooserButton', + Extends: Gtk.FileChooserButton, + Properties: { + 'location': GObject.ParamSpec.string('location', 'location', 'location', + GObject.ParamFlags.READWRITE, '') + }, + + get location() { + return this.get_file().get_path(); + }, + + set location(location) { + if (!location) { + this.unselect_all(); + if (this.get_file()) + this.set_file(Gio.File.new_for_path('aFileThatDoesNotExist')); + return; + } + + let file = Gio.File.new_for_commandline_arg(location); + if (file.query_exists(null)) + this.set_file(file); + }, + + vfunc_file_set: function(args) { + this.notify('location'); + } +}); + // this code comes from Sticky Notes View by Sam Bull, https://extensions.gnome.org/extension/568/notes/ const KeybindingsWidget = new GObject.Class({ Name: 'DrawOnYourScreenKeybindings.Widget', diff --git a/schemas/gschemas.compiled b/schemas/gschemas.compiled index 0dcf5fba49ed9dbd8e6ce1ab30bc9e3d255b7906..5873a004f7d1fe0519ee087c1c5a4b82969803af 100644 GIT binary patch literal 7392 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 Ti0L%EU@2_>5~TLjcuvzQIy zBZRYLENTRe2ImsXh-Psb<(~zYxRJSROtYmXTZT@e%aUorqWiu}sc6>Z*YCUEIrrRi z&pr2^6IvN8>-HN4VuUz%>8n4Ygb=4yLaY~?#W-{00r0%apH9WH9xo9mc8MU=fl4uHLOjKfUWhHi3GD?F8Gj#TeflKSADAlw;wBEx z^ta`+fIblg z^a;p2p+lhU+koc+3wXdDjX-Yz@7*oynbW5r4?!ovwfFa_cxUu6$T=LVfbQ{Y^OXz3 z$0OeitpOQdpKvp$S0S&39t0;RS1LDfP=^EFK_8S)r^W7e`27yw(0J^HSsQRB$3G5m z{O15QKt1KzU{pjj;E&IQ&#BSts<*gZ%??YOtKRRF4`P z_*}aka&PPcc{{!wsH2)?Fuqh~$0o@VRe?MjTfSIns?Ou~c+qa9*WMvSjxV>~?sHl^ z4GlhrAF+^~s(fk01-hdv@YqF8DO3EWC(j&NrOpbldr2S}qyP;_odHjsCLLZ63}K8= z6POof0rW){B72c6WQ#zyz%;|3$O)4R%?Aa*3W`86C;`>&6QgG67<$R6G7gPHZ}(N3 zeq&Cbirfr+7i{mnc#1haXG%M?3*;X-zL7b-N(6R^UYN6BhqbbV1@xSwUqY{g@=Mb9!DlPK(Zh^RFJ?%bb2T@-nCm7&A^NIX(03P*(tdhBq@kJi!Ie zx!4Zv0uKk=PnpvzQxQ52KI+dKV@_}8h4H*Hz^-wD)Px96vwx$msdVMxeLA^k;~kpP>*mTPH+c?ZpPRL(dMCL90M<;J&t>1w3FuEwmkc za=9kRoSu`e8+sZ{f5GYb1s{O6abg>56{Wi4eba2R$sOuAL6}i+qBlE-C(!c_#-S`pyzvUhL(ek)yI_gn4TT7K^vHd z>(jG-JG2)hSH(@TeR_5@2pu-y`ET2KKbr-^2>5!8K_7yb!wu21A%V}G8Tj|yP%ccb zJWFU5*q(FsW41%j8>ofu1e?O`(6gQW&^}Pf+=df)z=9xj6l@NkK+ik`<#)C!oYON; zhFXEo;da#dEy{whQXV#C$vfKAC?T8lTa3zr<8#_u9B4y`)i$rI$?ok~>lP}xI&HB$ zt24`>MwhS=ZTKBn$a3tyTp7wpxdm%~M@(@whu?_B2wdReH5cvcflro;Nxy z|8p}gTxV3H!-9Zcyc5~LfNTXDD9eD`J=|5 z^!S0soY>%L_FH`Z4!1IVa-QBO9~-h|RGL-}rftGFW%L;4WrpwH>2SA1n%=YwpHvP` zL5m%${p;zK^TW5%?7<#j>MkO+ThOytOeSq42=~k-G;*oV6nJ(I4r~?Nc$L{S?luZ6 z0Wp9(5zJL(XM(pEvwUiqpeSyw^doXIds^ADfA<&$-QQ6Sq&? zPDz_FPkwLAmdSV=A-(R|gxMuO&=h2b2eHZJ^?JM(zsKXoN%%!Zu1?<4R>>i~r6+BJ zdd8cvToxEI)xI{Dzs_mlUP;J9sm7!kH8>9Pi~+AtdanE;y-;2^6v_c~Co_FX!pxVf dL>3rx<#&dd=u#m+G-k>XgF1SJkWY+n{0D{OSY7}C diff --git a/schemas/org.gnome.shell.extensions.draw-on-your-screen.gschema.xml b/schemas/org.gnome.shell.extensions.draw-on-your-screen.gschema.xml index 7735448..47cad92 100644 --- a/schemas/org.gnome.shell.extensions.draw-on-your-screen.gschema.xml +++ b/schemas/org.gnome.shell.extensions.draw-on-your-screen.gschema.xml @@ -87,6 +87,11 @@ Grid overlay line width The line width in pixels + + "" + Image location + The location of the directory in which the image tool picks + [ @@ -148,7 +153,7 @@ ["<Primary>v"] - Paste image files from the clipboard + Paste images from the clipboard ["<Primary><Shift>z"] @@ -284,8 +289,12 @@ Change font weight - ["<Primary><Shift>i"] - Change image file + ["<Primary><Alt>i"] + Change image + + + ["<Primary><Alt><Shift>i"] + Change image (reverse) ["<Primary>k"] diff --git a/shortcuts.js b/shortcuts.js index f99b448..de77083 100644 --- a/shortcuts.js +++ b/shortcuts.js @@ -49,7 +49,8 @@ var INTERNAL_KEYBINDINGS = [ ['switch-fill', 'switch-fill-rule', 'switch-color-palette', 'switch-color-palette-reverse'], ['increment-line-width', 'increment-line-width-more', 'decrement-line-width', 'decrement-line-width-more', 'switch-linejoin', 'switch-linecap', 'switch-dash'], - ['switch-font-family', 'switch-font-family-reverse', 'switch-font-weight', 'switch-font-style', 'switch-text-alignment', 'switch-image-file'], + ['switch-font-family', 'switch-font-family-reverse', 'switch-font-weight', 'switch-font-style', 'switch-text-alignment'], + ['switch-image-file', 'switch-image-file-reverse', 'paste-image-files'], ['toggle-panel-and-dock-visibility', 'toggle-background', 'toggle-grid', 'toggle-square-area'], ['open-next-json', 'open-previous-json', 'save-as-json', 'save-as-svg', 'open-preferences', 'toggle-help'], ];