diff options
Diffstat (limited to 'deluge/plugins/Scheduler/deluge_scheduler/data')
4 files changed, 624 insertions, 0 deletions
diff --git a/deluge/plugins/Scheduler/deluge_scheduler/data/green.svg b/deluge/plugins/Scheduler/deluge_scheduler/data/green.svg new file mode 100644 index 0000000..ff3f5d6 --- /dev/null +++ b/deluge/plugins/Scheduler/deluge_scheduler/data/green.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 16 16" width="16" height="16"><defs><clipPath id="_clipPath_Ng8EWXQF95Gs7ywflmaKe8f73244LGgx"><rect width="16" height="16"/></clipPath></defs><g clip-path="url(#_clipPath_Ng8EWXQF95Gs7ywflmaKe8f73244LGgx)"><clipPath id="_clipPath_fEKXMbJwavdXcwSIsEYpsxFyYERCnK2c"><rect x="0" y="0" width="16" height="16" transform="matrix(1,0,0,1,0,0)" fill="rgb(255,255,255)"/></clipPath><g clip-path="url(#_clipPath_fEKXMbJwavdXcwSIsEYpsxFyYERCnK2c)"><g><g><radialGradient id="_rgradient_9" fx="0.5" fy="0.5" cx="0.5" cy="0.5" r="0.5" gradientTransform="matrix(12,0,0,12,1.5,1.5)" gradientUnits="userSpaceOnUse"><stop offset="0%" stop-opacity="1" style="stop-color:rgb(22,200,22)"/><stop offset="100%" stop-opacity="1" style="stop-color:rgb(22,200,22)"/></radialGradient><circle vector-effect="non-scaling-stroke" cx="7.5" cy="7.5" r="6" fill="url(#_rgradient_9)"/><path d=" M 7.5 0.013 C 3.37 0.013 0.013 3.37 0.013 7.5 C 0.013 11.63 3.37 14.987 7.5 14.987 C 11.63 14.987 14.987 11.63 14.987 7.5 C 14.987 3.37 11.63 0.013 7.5 0.013 Z M 7.5 1.987 C 10.549 1.987 13.013 4.451 13.013 7.5 C 13.013 10.549 10.549 13.013 7.5 13.013 C 4.451 13.013 1.987 10.549 1.987 7.5 C 1.987 4.451 4.451 1.987 7.5 1.987 Z " fill="rgb(18,155,0)"/><path d=" M 10.406 4 C 10.309 4.026 10.222 4.08 10.156 4.156 L 7.5 6.813 L 5.844 5.156 C 5.736 4.98 5.53 4.888 5.326 4.925 C 5.123 4.963 4.963 5.123 4.925 5.326 C 4.888 5.53 4.98 5.736 5.156 5.844 L 7.156 7.844 C 7.349 8.026 7.651 8.026 7.844 7.844 L 10.844 4.844 C 10.995 4.689 11.03 4.455 10.931 4.263 C 10.831 4.071 10.62 3.965 10.406 4 Z " fill="rgb(43,46,57)"/></g></g></g></g></svg> diff --git a/deluge/plugins/Scheduler/deluge_scheduler/data/red.svg b/deluge/plugins/Scheduler/deluge_scheduler/data/red.svg new file mode 100644 index 0000000..ccb0822 --- /dev/null +++ b/deluge/plugins/Scheduler/deluge_scheduler/data/red.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 16 16" width="16" height="16"><defs><clipPath id="_clipPath_b9idtDkK5ON8Jka415AjKueNrp89rRRq"><rect width="16" height="16"/></clipPath></defs><g clip-path="url(#_clipPath_b9idtDkK5ON8Jka415AjKueNrp89rRRq)"><clipPath id="_clipPath_vxaOVU0QEXAkOxrpA9AlU4ChkMqnhw1h"><rect x="0" y="0" width="16" height="16" transform="matrix(1,0,0,1,0,0)" fill="rgb(255,255,255)"/></clipPath><g clip-path="url(#_clipPath_vxaOVU0QEXAkOxrpA9AlU4ChkMqnhw1h)"><g><g><g style="opacity:0.98;"><g opacity="0.98"><circle vector-effect="non-scaling-stroke" cx="7.5" cy="7.5" r="6" fill="rgb(230,56,31)"/></g></g><path d=" M 7.5 0.013 C 3.37 0.013 0.013 3.37 0.013 7.5 C 0.013 11.63 3.37 14.987 7.5 14.987 C 11.63 14.987 14.987 11.63 14.987 7.5 C 14.987 3.37 11.63 0.013 7.5 0.013 Z M 7.5 1.987 C 10.549 1.987 13.013 4.451 13.013 7.5 C 13.013 10.549 10.549 13.013 7.5 13.013 C 4.451 13.013 1.987 10.549 1.987 7.5 C 1.987 4.451 4.451 1.987 7.5 1.987 Z " fill="rgb(166,14,14)"/><path d=" M 10.406 4 C 10.309 4.026 10.222 4.08 10.156 4.156 L 7.5 6.813 L 5.844 5.156 C 5.736 4.98 5.53 4.888 5.326 4.925 C 5.123 4.963 4.963 5.123 4.925 5.326 C 4.888 5.53 4.98 5.736 5.156 5.844 L 7.156 7.844 C 7.349 8.026 7.651 8.026 7.844 7.844 L 10.844 4.844 C 10.995 4.689 11.03 4.455 10.931 4.263 C 10.831 4.071 10.62 3.965 10.406 4 Z " fill="rgb(43,46,57)"/></g></g></g></g></svg> diff --git a/deluge/plugins/Scheduler/deluge_scheduler/data/scheduler.js b/deluge/plugins/Scheduler/deluge_scheduler/data/scheduler.js new file mode 100644 index 0000000..f59068c --- /dev/null +++ b/deluge/plugins/Scheduler/deluge_scheduler/data/scheduler.js @@ -0,0 +1,621 @@ +/** + * scheduler.js + * The client-side javascript code for the Scheduler plugin. + * + * Copyright (C) samuel337 2011 + * + * This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with + * the additional special exception to link portions of this program with the OpenSSL library. + * See LICENSE for more details. + * + */ + +Ext.ns('Deluge.ux'); + +Deluge.ux.ScheduleSelector = Ext.extend(Ext.form.FieldSet, { + title: _('Schedule'), + autoHeight: true, + style: 'margin-bottom: 0px; padding-bottom: 0px;', + border: false, + + states: [ + { + name: 'Normal', + backgroundColor: 'LightGreen', + borderColor: 'DarkGreen', + value: 0, + }, + { + name: 'Throttled', + backgroundColor: 'Yellow', + borderColor: 'Gold', + value: 1, + }, + { + name: 'Paused', + backgroundColor: 'OrangeRed', + borderColor: 'FireBrick', + value: 2, + }, + ], + daysOfWeek: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + + initComponent: function () { + Deluge.ux.ScheduleSelector.superclass.initComponent.call(this); + + // ExtJS' radiogroup implementation is very broken for styling. + /*this.stateBrush = this.add({ + xtype: 'radiogroup', + fieldLabel: _('State Brush'), + name: 'current_state_brush', + submitValue: false, + items: [ + { boxLabel: 'Normal', name: 'current_state_brush', inputValue: 0 }, + { boxLabel: 'Throttled', name: 'current_state_brush', inputValue: 1, checked: true }, + { boxLabel: 'Paused', name: 'current_state_brush', inputValue: 2 }, + ] + });*/ + }, + + onRender: function (ct, position) { + Deluge.ux.ScheduleSelector.superclass.onRender.call(this, ct, position); + + var dom = this.body.dom; + + function createEl(parent, type) { + var el = document.createElement(type); + parent.appendChild(el); + return el; + } + + // create state brushes + // tack a random number to the end to avoid clashes + this.stateBrushName = + 'schedule-state-brush-' + Math.round(Math.random() * 10000); + + var el1 = createEl(dom, 'div'); + + var el2 = createEl(el1, 'div'); + this.stateBrush = el2; + el2.id = this.stateBrushName; + + // for webkit + var floatAttr = 'float'; + if (el2.style.float == undefined) { + // for firefox + if (el2.style.cssFloat != undefined) floatAttr = 'cssFloat'; + // for IE + if (el2.style.styleFloat != undefined) floatAttr = 'styleFloat'; + } + el2.style[floatAttr] = 'right'; + + for (var i = 0; i < this.states.length; i++) { + var el3 = createEl(el2, 'input'); + el3.type = 'radio'; + el3.value = this.states[i].value; + el3.name = this.stateBrushName; + el3.id = this.stateBrushName + '-' + this.states[i].name; + + // isn't the first one + if (i > 0) el3.style.marginLeft = '7px'; + + // assume the first is the default state, so make the 2nd one the default brush + if (i == 1) el3.checked = true; + + var el4 = createEl(el2, 'label'); + el4.appendChild(document.createTextNode(this.states[i].name)); + el4.htmlFor = el3.id; + el4.style.backgroundColor = this.states[i].backgroundColor; + el4.style.borderBottom = '2px solid ' + this.states[i].borderColor; + el4.style.padding = '2px 3px'; + el4.style.marginLeft = '3px'; + } + + el1.appendChild(document.createTextNode('Select a state brush:')); + + el1.style.marginBottom = '10px'; + + // keep the radio buttons separate from the time bars + createEl(dom, 'div').style.clear = 'both'; + + var table = createEl(dom, 'table'); + table.cellSpacing = 0; + + // cache access to cells for easier access later + this.scheduleCells = {}; + + Ext.each( + this.daysOfWeek, + function (day) { + var cells = []; + var row = createEl(table, 'tr'); + var label = createEl(row, 'th'); + label.setAttribute( + 'style', + 'font-weight: bold; padding-right: 5px;' + ); + label.appendChild(document.createTextNode(day)); + for (var hour = 0; hour < 24; hour++) { + var cell = createEl(row, 'td'); + + // assume the first state is the default state + cell.currentValue = cell.oldValue = this.states[0].value; + cell.day = day; + cell.hour = hour; + + cell.width = '16px'; + cell.height = '20px'; + + cell.style.border = '1px solid #999999'; + // don't repeat borders in between cells + if (hour != 23) + // not the last cell + cell.style.borderRight = 'none'; + + this.updateCell(cell); + + cells.push(cell); + + cell = Ext.get(cell); + cell.on('click', this.onCellClick, this); + cell.on('mouseover', this.onCellMouseOver, this); + cell.on('mouseout', this.onCellMouseOut, this); + cell.on('mousedown', this.onCellMouseDown, this); + cell.on('mouseup', this.onCellMouseUp, this); + } + + // insert gap row to provide visual separation + row = createEl(table, 'tr'); + // blank cell to create gap + createEl(row, 'td').height = '3px'; + + this.scheduleCells[day] = cells; + }, + this + ); + }, + + updateCell: function (cell) { + // sanity check + if (cell.currentValue == undefined) return; + + for (var i in this.states) { + var curState = this.states[i]; + if (curState.value == cell.currentValue) { + cell.style.background = curState.backgroundColor; + break; + } + } + }, + + getCurrentBrushValue: function () { + var v = null; + var brushes = Ext.get(this.body.dom).findParent('form').elements[ + this.stateBrushName + ]; + Ext.each(brushes, function (b) { + if (b.checked) v = b.value; + }); + + return v; + }, + + onCellClick: function (event, cell) { + cell.oldValue = cell.currentValue; + + this.dragAnchor = null; + }, + + onCellMouseDown: function (event, cell) { + this.dragAnchor = cell; + }, + + onCellMouseUp: function (event, cell) { + // if we're dragging... + if (this.dragAnchor) { + // set all those between here and the anchor to the new values + if (cell.hour > this.dragAnchor.hour) + this.confirmCells(cell.day, this.dragAnchor.hour, cell.hour); + else if (cell.hour < this.dragAnchor.hour) + this.confirmCells(cell.day, cell.hour, this.dragAnchor.hour); + else this.confirmCells(cell.day, cell.hour, cell.hour); + + this.hideCellLeftTooltip(); + this.hideCellRightTooltip(); + this.dragAnchor = null; + } + }, + + onCellMouseOver: function (event, cell) { + // LEFT TOOL TIP + // if it isn't showing and we're dragging, show it. + // otherwise if dragging, leave it alone unless we're dragging to the left. + // if we're not dragging, show it. + var leftTooltipCell = null; + if (!this.dragAnchor) leftTooltipCell = cell; + else if ( + (this.dragAnchor && this.isCellLeftTooltipHidden()) || + (this.dragAnchor && this.dragAnchor.hour > cell.hour) + ) + leftTooltipCell = this.dragAnchor; + + if (leftTooltipCell) { + var hour = leftTooltipCell.hour; + var pm = false; + + // convert to 12-hour time + if (hour >= 12) { + pm = true; + if (hour > 12) hour -= 12; + } else if (hour == 0) { + // change 0 hour to 12am + hour = 12; + } + this.showCellLeftTooltip( + hour + ' ' + (pm ? 'pm' : 'am'), + leftTooltipCell + ); + } + + // RIGHT TOOL TIP + var rightTooltipCell = null; + if (this.dragAnchor) { + if (this.dragAnchor.hour == cell.hour) this.hideCellRightTooltip(); + else if ( + this.dragAnchor.hour > cell.hour && + this.isCellRightTooltipHidden() + ) + rightTooltipCell = this.dragAnchor; + // cell.hour > this.dragAnchor.hour + else rightTooltipCell = cell; + } + + if (rightTooltipCell) { + var hour = rightTooltipCell.hour; + var pm = false; + + // convert to 12-hour time + if (hour >= 12) { + pm = true; + if (hour > 12) hour -= 12; + } else if (hour == 0) { + // change 0 hour to 12am + hour = 12; + } + this.showCellRightTooltip( + hour + ' ' + (pm ? 'pm' : 'am'), + rightTooltipCell + ); + } + + // preview colour change and + // revert state for all those on the outer side of the drag if dragging + if (this.dragAnchor) { + if (cell.day != this.dragAnchor.day) { + // dragged into another day. Abort! Abort! + Ext.each( + this.daysOfWeek, + function (day) { + this.revertCells(day, 0, 23); + }, + this + ); + this.dragAnchor = null; + this.hideCellLeftTooltip(); + this.hideCellRightTooltip(); + } else if (cell.hour > this.dragAnchor.hour) { + // dragging right + this.revertCells(cell.day, cell.hour + 1, 23); + this.previewCells(cell.day, this.dragAnchor.hour, cell.hour); + } else if (cell.hour < this.dragAnchor.hour) { + // dragging left + this.revertCells(cell.day, 0, cell.hour - 1); + this.previewCells(cell.day, cell.hour, this.dragAnchor.hour); + } else { + // back to anchor cell + // don't know if it is from right or left, so revert all except this + this.revertCells(cell.day, cell.hour + 1, 23); + this.revertCells(cell.day, 0, cell.hour - 1); + } + } else { + // not dragging, just preview this cell + this.previewCells(cell.day, cell.hour, cell.hour); + } + }, + + onCellMouseOut: function (event, cell) { + if (!this.dragAnchor) this.hideCellLeftTooltip(); + + // revert state. If new state has been set, old and new will be equal. + // if dragging, this will be handled by the next mouse over + if (this.dragAnchor == null && cell.oldValue != cell.currentValue) { + this.revertCells(cell.day, cell.hour, cell.hour); + } + }, + + previewCells: function (day, fromHour, toHour) { + var cells = this.scheduleCells[day]; + var curBrushValue = this.getCurrentBrushValue(); + + if (toHour > cells.length) toHour = cells.length; + + for (var i = fromHour; i <= toHour; i++) { + if (cells[i].currentValue != curBrushValue) { + cells[i].oldValue = cells[i].currentValue; + cells[i].currentValue = curBrushValue; + this.updateCell(cells[i]); + } + } + }, + + revertCells: function (day, fromHour, toHour) { + var cells = this.scheduleCells[day]; + + if (toHour > cells.length) toHour = cells.length; + + for (var i = fromHour; i <= toHour; i++) { + cells[i].currentValue = cells[i].oldValue; + this.updateCell(cells[i]); + } + }, + + confirmCells: function (day, fromHour, toHour) { + var cells = this.scheduleCells[day]; + + if (toHour > cells.length) toHour = cells.length; + + for (var i = fromHour; i <= toHour; i++) { + if (cells[i].currentValue != cells[i].oldValue) { + cells[i].oldValue = cells[i].currentValue; + } + } + }, + + showCellLeftTooltip: function (text, cell) { + var tooltip = this.cellLeftTooltip; + + if (!tooltip) { + // no cached left tooltip exists, create one + tooltip = document.createElement('div'); + this.cellLeftTooltip = tooltip; + this.body.dom.appendChild(tooltip); + tooltip.style.position = 'absolute'; + tooltip.style.backgroundColor = '#F2F2F2'; + tooltip.style.border = '1px solid #333333'; + tooltip.style.padding = '1px 3px'; + tooltip.style.opacity = 0.8; + } + + // remove all existing children + while (tooltip.childNodes.length > 0) { + tooltip.removeChild(tooltip.firstChild); + } + // add the requested text + tooltip.appendChild(document.createTextNode(text)); + + // place the tooltip + Ext.get(tooltip).alignTo(cell, 'br-tr'); + + // make it visible + tooltip.style.visibility = 'visible'; + }, + + hideCellLeftTooltip: function () { + if (this.cellLeftTooltip) { + this.cellLeftTooltip.style.visibility = 'hidden'; + } + }, + + isCellLeftTooltipHidden: function () { + if (this.cellLeftTooltip) + return this.cellLeftTooltip.style.visibility == 'hidden'; + else return true; + }, + + showCellRightTooltip: function (text, cell) { + var tooltip = this.cellRightTooltip; + + if (!tooltip) { + // no cached left tooltip exists, create one + tooltip = document.createElement('div'); + this.cellRightTooltip = tooltip; + this.body.dom.appendChild(tooltip); + tooltip.style.position = 'absolute'; + tooltip.style.backgroundColor = '#F2F2F2'; + tooltip.style.border = '1px solid #333333'; + tooltip.style.padding = '1px 3px'; + tooltip.style.opacity = 0.8; + } + + // remove all existing children + while (tooltip.childNodes.length > 0) { + tooltip.removeChild(tooltip.firstChild); + } + // add the requested text + tooltip.appendChild(document.createTextNode(text)); + + // place the tooltip + Ext.get(tooltip).alignTo(cell, 'bl-tl'); + + // make it visible + tooltip.style.visibility = 'visible'; + }, + + hideCellRightTooltip: function () { + if (this.cellRightTooltip) { + this.cellRightTooltip.style.visibility = 'hidden'; + } + }, + + isCellRightTooltipHidden: function () { + if (this.cellRightTooltip) + return this.cellRightTooltip.style.visibility == 'hidden'; + else return true; + }, + + getConfig: function () { + var config = []; + + for (var i = 0; i < 24; i++) { + var hourConfig = [0, 0, 0, 0, 0, 0, 0]; + + for (var j = 0; j < this.daysOfWeek.length; j++) { + hourConfig[j] = parseInt( + this.scheduleCells[this.daysOfWeek[j]][i].currentValue + ); + } + + config.push(hourConfig); + } + + return config; + }, + + setConfig: function (config) { + for (var i = 0; i < 24; i++) { + var hourConfig = config[i]; + + for (var j = 0; j < this.daysOfWeek.length; j++) { + if (this.scheduleCells == undefined) { + var cell = hourConfig[j]; + } else { + var cell = this.scheduleCells[this.daysOfWeek[j]][i]; + } + cell.currentValue = cell.oldValue = hourConfig[j]; + this.updateCell(cell); + } + } + }, +}); + +Ext.ns('Deluge.ux.preferences'); + +Deluge.ux.preferences.SchedulerPage = Ext.extend(Ext.Panel, { + border: false, + title: _('Scheduler'), + header: false, + layout: 'fit', + + initComponent: function () { + Deluge.ux.preferences.SchedulerPage.superclass.initComponent.call(this); + + this.form = this.add({ + xtype: 'form', + layout: 'form', + border: false, + autoHeight: true, + }); + + this.schedule = this.form.add(new Deluge.ux.ScheduleSelector()); + + this.slowSettings = this.form.add({ + xtype: 'fieldset', + border: false, + title: _('Throttled Settings'), + autoHeight: true, + defaultType: 'spinnerfield', + defaults: { + minValue: -1, + maxValue: 99999, + }, + style: 'margin-top: 5px; margin-bottom: 0px; padding-bottom: 0px;', + labelWidth: 200, + }); + + this.downloadLimit = this.slowSettings.add({ + fieldLabel: _('Maximum Download Speed (KiB/s)'), + name: 'download_limit', + width: 80, + value: -1, + decimalPrecision: 0, + }); + this.uploadLimit = this.slowSettings.add({ + fieldLabel: _('Maximum Upload Speed (KiB/s)'), + name: 'upload_limit', + width: 80, + value: -1, + decimalPrecision: 0, + }); + this.activeTorrents = this.slowSettings.add({ + fieldLabel: _('Active Torrents'), + name: 'active_torrents', + width: 80, + value: -1, + decimalPrecision: 0, + }); + this.activeDownloading = this.slowSettings.add({ + fieldLabel: _('Active Downloading'), + name: 'active_downloading', + width: 80, + value: -1, + decimalPrecision: 0, + }); + this.activeSeeding = this.slowSettings.add({ + fieldLabel: _('Active Seeding'), + name: 'active_seeding', + width: 80, + value: -1, + decimalPrecision: 0, + }); + + this.on('show', this.updateConfig, this); + }, + + onRender: function (ct, position) { + Deluge.ux.preferences.SchedulerPage.superclass.onRender.call( + this, + ct, + position + ); + this.form.layout = new Ext.layout.FormLayout(); + this.form.layout.setContainer(this); + this.form.doLayout(); + }, + + onApply: function () { + // build settings object + var config = {}; + + config['button_state'] = this.schedule.getConfig(); + config['low_down'] = this.downloadLimit.getValue(); + config['low_up'] = this.uploadLimit.getValue(); + config['low_active'] = this.activeTorrents.getValue(); + config['low_active_down'] = this.activeDownloading.getValue(); + config['low_active_up'] = this.activeSeeding.getValue(); + + deluge.client.scheduler.set_config(config); + }, + + onOk: function () { + this.onApply(); + }, + + updateConfig: function () { + deluge.client.scheduler.get_config({ + success: function (config) { + this.schedule.setConfig(config['button_state']); + this.downloadLimit.setValue(config['low_down']); + this.uploadLimit.setValue(config['low_up']); + this.activeTorrents.setValue(config['low_active']); + this.activeDownloading.setValue(config['low_active_down']); + this.activeSeeding.setValue(config['low_active_up']); + }, + scope: this, + }); + }, +}); + +Deluge.plugins.SchedulerPlugin = Ext.extend(Deluge.Plugin, { + name: 'Scheduler', + + onDisable: function () { + deluge.preferences.removePage(this.prefsPage); + }, + + onEnable: function () { + this.prefsPage = deluge.preferences.addPage( + new Deluge.ux.preferences.SchedulerPage() + ); + }, +}); +Deluge.registerPlugin('Scheduler', Deluge.plugins.SchedulerPlugin); diff --git a/deluge/plugins/Scheduler/deluge_scheduler/data/yellow.svg b/deluge/plugins/Scheduler/deluge_scheduler/data/yellow.svg new file mode 100644 index 0000000..8881a8c --- /dev/null +++ b/deluge/plugins/Scheduler/deluge_scheduler/data/yellow.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 16 16" width="16" height="16"><defs><clipPath id="_clipPath_FTEVJ02JqQbaAkGq0zxCClZ8ovSf28LF"><rect width="16" height="16"/></clipPath></defs><g clip-path="url(#_clipPath_FTEVJ02JqQbaAkGq0zxCClZ8ovSf28LF)"><clipPath id="_clipPath_kMUc2qeZPnpfemB5VN1mID2bTbctQK6V"><rect x="0" y="0" width="16" height="16" transform="matrix(1,0,0,1,0,0)" fill="rgb(255,255,255)"/></clipPath><g clip-path="url(#_clipPath_kMUc2qeZPnpfemB5VN1mID2bTbctQK6V)"><g><clipPath id="_clipPath_O3gUc8WX8CfJdh8CMbdOfLtRtmBkIQPk"><rect x="0" y="0" width="16" height="16" transform="matrix(1,0,0,1,0,0)" fill="rgb(255,255,255)"/></clipPath><g clip-path="url(#_clipPath_O3gUc8WX8CfJdh8CMbdOfLtRtmBkIQPk)"><g><g><g><path d=" M 7.5 0.013 C 3.37 0.013 0.013 3.37 0.013 7.5 C 0.013 11.63 3.37 14.987 7.5 14.987 C 11.63 14.987 14.987 11.63 14.987 7.5 C 14.987 3.37 11.63 0.013 7.5 0.013 Z M 7.5 1.987 C 10.549 1.987 13.013 4.451 13.013 7.5 C 13.013 10.549 10.549 13.013 7.5 13.013 C 4.451 13.013 1.987 10.549 1.987 7.5 C 1.987 4.451 4.451 1.987 7.5 1.987 Z " fill="rgb(180,180,0)"/><g style="opacity:0.99;"><g style="opacity:0.99;"><g opacity="0.99"><circle vector-effect="non-scaling-stroke" cx="7.5" cy="7.5" r="6" fill="rgb(220,220,0)"/></g></g></g><path d=" M 10.406 4 C 10.309 4.026 10.222 4.08 10.156 4.156 L 7.5 6.813 L 5.844 5.156 C 5.736 4.98 5.53 4.888 5.326 4.925 C 5.123 4.963 4.963 5.123 4.925 5.326 C 4.888 5.53 4.98 5.736 5.156 5.844 L 7.156 7.844 C 7.349 8.026 7.651 8.026 7.844 7.844 L 10.844 4.844 C 10.995 4.689 11.03 4.455 10.931 4.263 C 10.831 4.071 10.62 3.965 10.406 4 Z " fill="rgb(43,46,57)"/></g></g></g></g></g></g></g></svg> |