2019-01-31 14:07:06 +00:00
/* exported main */
2019-08-21 17:36:42 +00:00
imports . gi . versions . Gdk = '3.0' ;
imports . gi . versions . Gtk = '3.0' ;
2012-01-19 02:21:56 +00:00
const Gettext = imports . gettext ;
2019-02-09 03:21:36 +00:00
const { Gdk , GLib , Gio , GObject , Gtk , Pango } = imports . gi ;
2012-05-04 21:23:08 +00:00
const Format = imports . format ;
2012-01-19 02:21:56 +00:00
const _ = Gettext . gettext ;
const Config = imports . misc . config ;
const ExtensionUtils = imports . misc . extensionUtils ;
2018-09-06 00:55:20 +00:00
const { loadInterfaceXML } = imports . misc . fileUtils ;
2012-01-19 02:21:56 +00:00
2018-11-01 12:55:17 +00:00
const { ExtensionState } = ExtensionUtils ;
2018-09-06 00:55:20 +00:00
const GnomeShellIface = loadInterfaceXML ( 'org.gnome.Shell.Extensions' ) ;
2012-01-19 02:21:56 +00:00
const GnomeShellProxy = Gio . DBusProxy . makeProxyWrapper ( GnomeShellIface ) ;
function stripPrefix ( string , prefix ) {
if ( string . slice ( 0 , prefix . length ) == prefix )
return string . slice ( prefix . length ) ;
return string ;
}
2019-05-28 21:22:37 +00:00
var Application = GObject . registerClass ( {
GTypeName : 'ExtensionPrefs_Application'
} , class Application extends Gtk . Application {
_init ( ) {
2012-01-19 02:21:56 +00:00
GLib . set _prgname ( 'gnome-shell-extension-prefs' ) ;
2019-05-28 21:22:37 +00:00
super . _init ( {
2012-01-19 02:21:56 +00:00
application _id : 'org.gnome.shell.ExtensionPrefs' ,
flags : Gio . ApplicationFlags . HANDLES _COMMAND _LINE
} ) ;
2013-02-28 13:50:56 +00:00
this . _startupUuid = null ;
2014-05-26 23:36:41 +00:00
this . _loaded = false ;
this . _skipMainWindow = false ;
2018-11-01 12:55:17 +00:00
this . _shellProxy = null ;
}
get shellProxy ( ) {
return this . _shellProxy ;
2017-10-31 01:19:44 +00:00
}
2012-01-19 02:21:56 +00:00
2018-11-01 12:50:30 +00:00
_showPrefs ( uuid ) {
let row = this . _extensionSelector . get _children ( ) . find ( c => {
return c . uuid === uuid && c . hasPrefs ;
} ) ;
2012-01-19 02:21:56 +00:00
2018-11-01 12:50:30 +00:00
if ( ! row )
2012-01-19 02:21:56 +00:00
return false ;
let widget ;
try {
2018-11-01 12:50:30 +00:00
widget = row . prefsModule . buildPrefsWidget ( ) ;
2012-01-19 02:21:56 +00:00
} catch ( e ) {
2018-11-01 12:50:30 +00:00
widget = this . _buildErrorUI ( row , e ) ;
2012-01-19 02:21:56 +00:00
}
2018-11-01 12:50:30 +00:00
let dialog = new Gtk . Window ( {
modal : ! this . _skipMainWindow ,
type _hint : Gdk . WindowTypeHint . DIALOG
} ) ;
dialog . set _titlebar ( new Gtk . HeaderBar ( {
show _close _button : true ,
title : row . name ,
visible : true
} ) ) ;
2014-05-26 23:36:41 +00:00
if ( this . _skipMainWindow ) {
2019-05-28 21:22:37 +00:00
this . add _window ( dialog ) ;
2014-05-26 23:36:41 +00:00
if ( this . _window )
this . _window . destroy ( ) ;
this . _window = dialog ;
this . _window . window _position = Gtk . WindowPosition . CENTER ;
} else {
dialog . transient _for = this . _window ;
}
2014-05-23 02:49:37 +00:00
dialog . set _default _size ( 600 , 400 ) ;
2017-04-20 15:00:10 +00:00
dialog . add ( widget ) ;
2014-05-23 02:49:37 +00:00
dialog . show ( ) ;
2019-07-20 22:07:00 +00:00
return true ;
2017-10-31 01:19:44 +00:00
}
2012-01-19 02:21:56 +00:00
2018-11-01 12:50:30 +00:00
_buildErrorUI ( row , exc ) {
2018-08-06 02:15:12 +00:00
let scroll = new Gtk . ScrolledWindow ( {
hscrollbar _policy : Gtk . PolicyType . NEVER ,
propagate _natural _height : true
} ) ;
let box = new Gtk . Box ( {
orientation : Gtk . Orientation . VERTICAL ,
spacing : 12 ,
margin : 100 ,
margin _bottom : 60
} ) ;
scroll . add ( box ) ;
2012-01-19 02:21:56 +00:00
let label = new Gtk . Label ( {
2019-02-01 19:11:39 +00:00
label : '<span size="x-large">%s</span>' . format ( _ ( "Something’ s gone wrong" ) ) ,
2018-08-06 02:15:12 +00:00
use _markup : true
} ) ;
label . get _style _context ( ) . add _class ( Gtk . STYLE _CLASS _DIM _LABEL ) ;
box . add ( label ) ;
label = new Gtk . Label ( {
label : _ ( "We’ re very sorry, but there’ s been a problem: the settings for this extension can’ t be displayed. We recommend that you report the issue to the extension authors." ) ,
justify : Gtk . Justification . CENTER ,
wrap : true
2012-01-19 02:21:56 +00:00
} ) ;
box . add ( label ) ;
2018-08-06 02:15:12 +00:00
let expander = new Expander ( {
label : _ ( "Technical Details" ) ,
margin _top : 12
} ) ;
box . add ( expander ) ;
2012-01-19 02:21:56 +00:00
2018-08-06 02:15:12 +00:00
let errortext = ` ${ exc } \n \n Stack trace: \n ${
// Indent stack trace.
exc . stack . split ( '\n' ) . map ( line => ` ${ line } ` ) . join ( '\n' )
} ` ;
2012-01-19 02:21:56 +00:00
let buffer = new Gtk . TextBuffer ( { text : errortext } ) ;
2018-08-06 02:15:12 +00:00
let textview = new Gtk . TextView ( {
buffer : buffer ,
wrap _mode : Gtk . WrapMode . WORD ,
monospace : true ,
editable : false ,
top _margin : 12 ,
bottom _margin : 12 ,
left _margin : 12 ,
right _margin : 12
} ) ;
let toolbar = new Gtk . Toolbar ( ) ;
let provider = new Gtk . CssProvider ( ) ;
provider . load _from _data ( ` * {
border : 0 solid @ borders ;
border - top - width : 1 px ;
} ` );
toolbar . get _style _context ( ) . add _provider (
provider ,
Gtk . STYLE _PROVIDER _PRIORITY _APPLICATION
) ;
let copyButton = new Gtk . ToolButton ( {
icon _name : 'edit-copy-symbolic' ,
tooltip _text : _ ( "Copy Error" )
} ) ;
toolbar . add ( copyButton ) ;
copyButton . connect ( 'clicked' , w => {
let clipboard = Gtk . Clipboard . get _default ( w . get _display ( ) ) ;
2019-02-12 14:16:08 +00:00
// markdown for pasting in gitlab issues
let lines = [
2018-11-01 12:50:30 +00:00
` The settings of extension ${ row . uuid } had an error: ` ,
2019-02-12 14:16:08 +00:00
'```' ,
` ${ exc } ` ,
'```' ,
'' ,
'Stack trace:' ,
'```' ,
exc . stack . replace ( /\n$/ , '' ) , // stack without trailing newline
'```' ,
''
] ;
clipboard . set _text ( lines . join ( '\n' ) , - 1 ) ;
2018-08-06 02:15:12 +00:00
} ) ;
2012-01-19 02:21:56 +00:00
2018-08-06 02:15:12 +00:00
let spacing = new Gtk . SeparatorToolItem ( { draw : false } ) ;
toolbar . add ( spacing ) ;
toolbar . child _set _property ( spacing , "expand" , true ) ;
let urlButton = new Gtk . ToolButton ( {
label : _ ( "Homepage" ) ,
tooltip _text : _ ( "Visit extension homepage" ) ,
no _show _all : true ,
2018-11-01 12:50:30 +00:00
visible : row . url != null
2018-08-06 02:15:12 +00:00
} ) ;
toolbar . add ( urlButton ) ;
urlButton . connect ( 'clicked' , w => {
let context = w . get _display ( ) . get _app _launch _context ( ) ;
2018-11-01 12:50:30 +00:00
Gio . AppInfo . launch _default _for _uri ( row . url , context ) ;
2018-08-06 02:15:12 +00:00
} ) ;
let expandedBox = new Gtk . Box ( {
orientation : Gtk . Orientation . VERTICAL
} ) ;
expandedBox . add ( textview ) ;
expandedBox . add ( toolbar ) ;
expander . add ( expandedBox ) ;
scroll . show _all ( ) ;
return scroll ;
2017-10-31 01:19:44 +00:00
}
2012-01-19 02:21:56 +00:00
2019-05-28 21:22:37 +00:00
_buildUI ( ) {
this . _window = new Gtk . ApplicationWindow ( { application : this ,
2014-05-23 02:49:37 +00:00
window _position : Gtk . WindowPosition . CENTER } ) ;
2012-01-19 02:21:56 +00:00
2015-12-14 23:37:47 +00:00
this . _window . set _default _size ( 800 , 500 ) ;
2012-01-19 02:21:56 +00:00
2014-05-23 02:49:37 +00:00
this . _titlebar = new Gtk . HeaderBar ( { show _close _button : true ,
2015-12-14 23:37:47 +00:00
title : _ ( "Shell Extensions" ) } ) ;
2014-05-23 02:49:37 +00:00
this . _window . set _titlebar ( this . _titlebar ) ;
2012-01-19 02:21:56 +00:00
2015-12-14 23:15:33 +00:00
let killSwitch = new Gtk . Switch ( { valign : Gtk . Align . CENTER } ) ;
this . _titlebar . pack _end ( killSwitch ) ;
this . _settings = new Gio . Settings ( { schema _id : 'org.gnome.shell' } ) ;
this . _settings . bind ( 'disable-user-extensions' , killSwitch , 'active' ,
2017-04-20 15:09:18 +00:00
Gio . SettingsBindFlags . DEFAULT |
2015-12-14 23:15:33 +00:00
Gio . SettingsBindFlags . INVERT _BOOLEAN ) ;
2018-08-06 00:31:18 +00:00
this . _mainStack = new Gtk . Stack ( {
transition _type : Gtk . StackTransitionType . CROSSFADE
} ) ;
this . _window . add ( this . _mainStack ) ;
2015-12-14 23:37:47 +00:00
let scroll = new Gtk . ScrolledWindow ( { hscrollbar _policy : Gtk . PolicyType . NEVER } ) ;
2012-01-19 02:21:56 +00:00
2014-05-23 02:49:37 +00:00
this . _extensionSelector = new Gtk . ListBox ( { selection _mode : Gtk . SelectionMode . NONE } ) ;
2017-12-02 00:27:35 +00:00
this . _extensionSelector . set _sort _func ( this . _sortList . bind ( this ) ) ;
this . _extensionSelector . set _header _func ( this . _updateHeader . bind ( this ) ) ;
2012-01-19 02:21:56 +00:00
2014-05-23 02:49:37 +00:00
scroll . add ( this . _extensionSelector ) ;
2012-01-19 02:21:56 +00:00
2018-08-06 00:31:18 +00:00
this . _mainStack . add _named ( scroll , 'listing' ) ;
this . _mainStack . add _named ( new EmptyPlaceholder ( ) , 'placeholder' ) ;
2012-01-19 02:21:56 +00:00
this . _shellProxy = new GnomeShellProxy ( Gio . DBus . session , 'org.gnome.Shell' , '/org/gnome/Shell' ) ;
2018-11-01 12:55:17 +00:00
this . _shellProxy . connectSignal ( 'ExtensionStateChanged' ,
this . _onExtensionStateChanged . bind ( this ) ) ;
2012-01-19 02:21:56 +00:00
this . _window . show _all ( ) ;
2017-10-31 01:19:44 +00:00
}
2012-01-19 02:21:56 +00:00
2017-10-31 00:03:21 +00:00
_sortList ( row1 , row2 ) {
2018-11-01 12:50:30 +00:00
return row1 . name . localeCompare ( row2 . name ) ;
2017-10-31 01:19:44 +00:00
}
2014-05-23 02:49:37 +00:00
2017-10-31 00:03:21 +00:00
_updateHeader ( row , before ) {
2014-05-23 02:49:37 +00:00
if ( ! before || row . get _header ( ) )
return ;
let sep = new Gtk . Separator ( { orientation : Gtk . Orientation . HORIZONTAL } ) ;
row . set _header ( sep ) ;
2017-10-31 01:19:44 +00:00
}
2014-05-23 02:49:37 +00:00
2018-11-01 12:55:17 +00:00
_findExtensionRow ( uuid ) {
return this . _extensionSelector . get _children ( ) . find ( c => c . uuid === uuid ) ;
}
_onExtensionStateChanged ( proxy , senderName , [ uuid , newState ] ) {
let row = this . _findExtensionRow ( uuid ) ;
if ( row ) {
let { state } = ExtensionUtils . deserializeExtension ( newState ) ;
if ( state == ExtensionState . UNINSTALLED )
row . destroy ( ) ;
return ; // we only deal with new and deleted extensions here
}
this . _shellProxy . GetExtensionInfoRemote ( uuid , ( [ serialized ] ) => {
let extension = ExtensionUtils . deserializeExtension ( serialized ) ;
if ( ! extension )
return ;
// check the extension wasn't added in between
if ( this . _findExtensionRow ( uuid ) != null )
return ;
this . _addExtensionRow ( extension ) ;
} ) ;
}
2017-10-31 00:03:21 +00:00
_scanExtensions ( ) {
2018-11-01 12:55:17 +00:00
this . _shellProxy . ListExtensionsRemote ( ( [ extensionsMap ] , e ) => {
if ( e ) {
if ( e instanceof Gio . DBusError ) {
log ( ` Failed to connect to shell proxy: ${ e } ` ) ;
this . _mainStack . add _named ( new NoShellPlaceholder ( ) , 'noshell' ) ;
this . _mainStack . visible _child _name = 'noshell' ;
} else
throw e ;
return ;
}
for ( let uuid in extensionsMap ) {
let extension = ExtensionUtils . deserializeExtension ( extensionsMap [ uuid ] ) ;
this . _addExtensionRow ( extension ) ;
}
this . _extensionsLoaded ( ) ;
} ) ;
2017-10-31 01:19:44 +00:00
}
2012-01-19 02:21:56 +00:00
2018-11-01 12:55:17 +00:00
_addExtensionRow ( extension ) {
2018-11-01 12:50:30 +00:00
let row = new ExtensionRow ( extension ) ;
2014-05-23 02:49:37 +00:00
2017-10-31 00:38:18 +00:00
row . prefsButton . connect ( 'clicked' , ( ) => {
2018-11-01 12:50:30 +00:00
this . _showPrefs ( row . uuid ) ;
2017-10-31 00:38:18 +00:00
} ) ;
2014-05-23 02:49:37 +00:00
row . show _all ( ) ;
this . _extensionSelector . add ( row ) ;
2017-10-31 01:19:44 +00:00
}
2012-06-04 21:14:18 +00:00
2017-10-31 00:03:21 +00:00
_extensionsLoaded ( ) {
2018-08-06 00:31:18 +00:00
if ( this . _extensionSelector . get _children ( ) . length > 0 )
this . _mainStack . visible _child _name = 'listing' ;
else
this . _mainStack . visible _child _name = 'placeholder' ;
2018-11-01 12:50:30 +00:00
if ( this . _startupUuid )
this . _showPrefs ( this . _startupUuid ) ;
2013-02-28 13:50:56 +00:00
this . _startupUuid = null ;
2014-05-26 23:36:41 +00:00
this . _skipMainWindow = false ;
this . _loaded = true ;
2017-10-31 01:19:44 +00:00
}
2012-06-04 21:14:18 +00:00
2019-05-28 21:22:37 +00:00
vfunc _activate ( ) {
2012-01-19 02:21:56 +00:00
this . _window . present ( ) ;
2017-10-31 01:19:44 +00:00
}
2012-01-19 02:21:56 +00:00
2019-05-28 21:22:37 +00:00
vfunc _startup ( ) {
super . vfunc _startup ( ) ;
this . _buildUI ( ) ;
2012-01-19 02:21:56 +00:00
this . _scanExtensions ( ) ;
2017-10-31 01:19:44 +00:00
}
2012-01-19 02:21:56 +00:00
2019-05-28 21:22:37 +00:00
vfunc _command _line ( commandLine ) {
this . activate ( ) ;
2012-01-19 02:21:56 +00:00
let args = commandLine . get _arguments ( ) ;
2014-05-26 23:36:41 +00:00
2012-01-19 02:21:56 +00:00
if ( args . length ) {
let uuid = args [ 0 ] ;
2014-05-26 23:36:41 +00:00
this . _skipMainWindow = true ;
2012-01-19 02:21:56 +00:00
// Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix ( uuid , "extension:///" ) ;
2018-11-01 12:50:30 +00:00
if ( ! this . _loaded )
2013-02-28 13:50:56 +00:00
this . _startupUuid = uuid ;
2018-11-01 12:50:30 +00:00
else if ( ! this . _showPrefs ( uuid ) )
2014-05-26 23:36:41 +00:00
this . _skipMainWindow = false ;
2012-01-19 02:21:56 +00:00
}
return 0 ;
}
2019-05-28 21:22:37 +00:00
} ) ;
2012-01-19 02:21:56 +00:00
2018-08-06 02:15:12 +00:00
var Expander = GObject . registerClass ( {
Properties : {
'label' : GObject . ParamSpec . string (
'label' , 'label' , 'label' ,
GObject . ParamFlags . READWRITE ,
null
)
}
} , class Expander extends Gtk . Box {
_init ( params = { } ) {
this . _labelText = null ;
super . _init ( Object . assign ( params , {
orientation : Gtk . Orientation . VERTICAL ,
spacing : 0
} ) ) ;
this . _frame = new Gtk . Frame ( {
shadow _type : Gtk . ShadowType . IN ,
hexpand : true
} ) ;
let eventBox = new Gtk . EventBox ( ) ;
this . _frame . add ( eventBox ) ;
let hbox = new Gtk . Box ( {
spacing : 6 ,
margin : 12
} ) ;
eventBox . add ( hbox ) ;
this . _arrow = new Gtk . Image ( {
icon _name : 'pan-end-symbolic'
} ) ;
hbox . add ( this . _arrow ) ;
this . _label = new Gtk . Label ( { label : this . _labelText } ) ;
hbox . add ( this . _label ) ;
this . _revealer = new Gtk . Revealer ( ) ;
this . _childBin = new Gtk . Frame ( {
shadow _type : Gtk . ShadowType . IN
} ) ;
this . _revealer . add ( this . _childBin ) ;
// Directly chain up to parent for internal children
super . add ( this . _frame ) ;
super . add ( this . _revealer ) ;
let provider = new Gtk . CssProvider ( ) ;
provider . load _from _data ( '* { border-top-width: 0; }' ) ;
this . _childBin . get _style _context ( ) . add _provider (
provider ,
Gtk . STYLE _PROVIDER _PRIORITY _APPLICATION
) ;
this . _gesture = new Gtk . GestureMultiPress ( {
widget : this . _frame ,
button : 0 ,
exclusive : true
} ) ;
this . _gesture . connect ( 'released' , ( gesture , nPress ) => {
if ( nPress == 1 )
this . _revealer . reveal _child = ! this . _revealer . reveal _child ;
} ) ;
this . _revealer . connect ( 'notify::reveal-child' , ( ) => {
if ( this . _revealer . reveal _child )
this . _arrow . icon _name = 'pan-down-symbolic' ;
else
this . _arrow . icon _name = 'pan-end-symbolic' ;
} ) ;
}
get label ( ) {
return this . _labelText ;
}
set label ( text ) {
if ( this . _labelText == text )
return ;
if ( this . _label )
this . _label . label = text ;
this . _labelText = text ;
this . notify ( 'label' ) ;
}
add ( child ) {
// set expanded child
this . _childBin . get _children ( ) . forEach ( c => {
this . _childBin . remove ( c ) ;
} ) ;
if ( child )
this . _childBin . add ( child ) ;
}
} ) ;
2018-08-06 00:31:18 +00:00
var EmptyPlaceholder = GObject . registerClass (
class EmptyPlaceholder extends Gtk . Box {
_init ( ) {
super . _init ( {
orientation : Gtk . Orientation . VERTICAL ,
spacing : 6 ,
margin : 32
} ) ;
let image = new Gtk . Image ( {
icon _name : 'application-x-addon-symbolic' ,
pixel _size : 96 ,
visible : true ,
vexpand : true ,
valign : Gtk . Align . END
} ) ;
image . get _style _context ( ) . add _class ( Gtk . STYLE _CLASS _DIM _LABEL ) ;
this . add ( image ) ;
let label = new Gtk . Label ( {
label : ` <b><span size="x-large"> ${ _ ( "No Extensions Installed" ) } </span></b> ` ,
use _markup : true ,
visible : true
} ) ;
label . get _style _context ( ) . add _class ( Gtk . STYLE _CLASS _DIM _LABEL ) ;
this . add ( label ) ;
let appInfo = Gio . DesktopAppInfo . new ( 'org.gnome.Software.desktop' ) ;
let desc = new Gtk . Label ( {
label : _ ( "Extensions can be installed through Software or <a href=\"https://extensions.gnome.org\">extensions.gnome.org</a>." ) ,
use _markup : true ,
wrap : true ,
justify : Gtk . Justification . CENTER ,
visible : true ,
max _width _chars : 50 ,
hexpand : true ,
vexpand : ( appInfo == null ) ,
halign : Gtk . Align . CENTER ,
valign : Gtk . Align . START
} ) ;
this . add ( desc ) ;
if ( appInfo ) {
let button = new Gtk . Button ( {
label : _ ( "Browse in Software" ) ,
image : new Gtk . Image ( {
icon _name : "org.gnome.Software-symbolic"
} ) ,
always _show _image : true ,
margin _top : 12 ,
visible : true ,
halign : Gtk . Align . CENTER ,
valign : Gtk . Align . START ,
vexpand : true
} ) ;
this . add ( button ) ;
button . connect ( 'clicked' , w => {
let context = w . get _display ( ) . get _app _launch _context ( ) ;
appInfo . launch ( [ ] , context ) ;
} ) ;
}
}
} ) ;
2018-11-01 12:55:17 +00:00
var NoShellPlaceholder = GObject . registerClass (
class NoShellPlaceholder extends Gtk . Box {
_init ( ) {
super . _init ( {
orientation : Gtk . Orientation . VERTICAL ,
spacing : 12 ,
margin : 100 ,
margin _bottom : 60
} ) ;
let label = new Gtk . Label ( {
label : '<span size="x-large">%s</span>' . format (
_ ( "Something’ s gone wrong" ) ) ,
use _markup : true
} ) ;
label . get _style _context ( ) . add _class ( Gtk . STYLE _CLASS _DIM _LABEL ) ;
this . add ( label ) ;
label = new Gtk . Label ( {
label : _ ( "We’ re very sorry, but it was not possible to get the list of installed extensions. Make sure you are logged into GNOME and try again." ) ,
justify : Gtk . Justification . CENTER ,
wrap : true
} ) ;
this . add ( label ) ;
this . show _all ( ) ;
}
} ) ;
2017-10-31 01:23:39 +00:00
var DescriptionLabel = GObject . registerClass (
class DescriptionLabel extends Gtk . Label {
2017-10-31 00:03:21 +00:00
vfunc _get _preferred _height _for _width ( width ) {
2015-12-14 23:37:47 +00:00
// Hack: Request the maximum height allowed by the line limit
if ( this . lines > 0 )
2017-10-31 01:23:39 +00:00
return super . vfunc _get _preferred _height _for _width ( 0 ) ;
return super . vfunc _get _preferred _height _for _width ( width ) ;
2015-12-14 23:37:47 +00:00
}
} ) ;
2017-10-31 01:23:39 +00:00
var ExtensionRow = GObject . registerClass (
class ExtensionRow extends Gtk . ListBoxRow {
2018-11-01 12:50:30 +00:00
_init ( extension ) {
2017-10-31 01:23:39 +00:00
super . _init ( ) ;
2014-05-23 02:49:37 +00:00
2018-11-01 12:55:17 +00:00
this . _app = Gio . Application . get _default ( ) ;
2018-11-01 12:50:30 +00:00
this . _extension = extension ;
this . _prefsModule = null ;
2014-05-23 02:49:37 +00:00
2019-09-09 15:06:55 +00:00
this . connect ( 'destroy' , this . _onDestroy . bind ( this ) ) ;
this . _buildUI ( ) ;
2018-11-01 12:55:17 +00:00
this . _extensionStateChangedId = this . _app . shellProxy . connectSignal (
'ExtensionStateChanged' , ( p , sender , [ uuid , newState ] ) => {
if ( this . uuid !== uuid )
return ;
this . _extension = ExtensionUtils . deserializeExtension ( newState ) ;
let state = ( this . _extension . state == ExtensionState . ENABLED ) ;
2019-09-09 15:08:53 +00:00
GObject . signal _handler _block ( this . _switch , this . _notifyActiveId ) ;
2018-11-01 12:55:17 +00:00
this . _switch . state = state ;
2019-09-09 15:08:53 +00:00
GObject . signal _handler _unblock ( this . _switch , this . _notifyActiveId ) ;
2018-11-01 12:55:17 +00:00
this . _switch . sensitive = this . _canToggle ( ) ;
2017-10-31 00:38:18 +00:00
} ) ;
2017-10-31 01:23:39 +00:00
}
2014-05-23 02:49:37 +00:00
2018-11-01 12:50:30 +00:00
get uuid ( ) {
return this . _extension . uuid ;
}
get name ( ) {
return this . _extension . metadata . name ;
}
get hasPrefs ( ) {
return this . _extension . hasPrefs ;
}
2014-05-23 02:49:37 +00:00
2018-11-01 12:50:30 +00:00
get url ( ) {
return this . _extension . metadata . url ;
}
2018-11-01 12:55:17 +00:00
_onDestroy ( ) {
if ( ! this . _app . shellProxy )
return ;
if ( this . _extensionStateChangedId )
this . _app . shellProxy . disconnectSignal ( this . _extensionStateChangedId ) ;
this . _extensionStateChangedId = 0 ;
}
2018-11-01 12:50:30 +00:00
_buildUI ( ) {
2014-05-23 02:49:37 +00:00
let hbox = new Gtk . Box ( { orientation : Gtk . Orientation . HORIZONTAL ,
2015-12-14 23:37:47 +00:00
hexpand : true , margin _end : 24 , spacing : 24 ,
margin : 12 } ) ;
2014-05-23 02:49:37 +00:00
this . add ( hbox ) ;
let vbox = new Gtk . Box ( { orientation : Gtk . Orientation . VERTICAL ,
spacing : 6 , hexpand : true } ) ;
hbox . add ( vbox ) ;
2018-11-01 12:50:30 +00:00
let name = GLib . markup _escape _text ( this . name , - 1 ) ;
2014-05-23 02:49:37 +00:00
let label = new Gtk . Label ( { label : '<b>' + name + '</b>' ,
use _markup : true ,
halign : Gtk . Align . START } ) ;
vbox . add ( label ) ;
2018-11-01 12:50:30 +00:00
let desc = this . _extension . metadata . description . split ( '\n' ) [ 0 ] ;
2015-12-14 23:37:47 +00:00
label = new DescriptionLabel ( { label : desc , wrap : true , lines : 2 ,
ellipsize : Pango . EllipsizeMode . END ,
xalign : 0 , yalign : 0 } ) ;
2014-05-23 02:49:37 +00:00
vbox . add ( label ) ;
let button = new Gtk . Button ( { valign : Gtk . Align . CENTER ,
2018-11-01 12:50:30 +00:00
visible : this . hasPrefs ,
2014-05-23 02:49:37 +00:00
no _show _all : true } ) ;
2019-04-05 16:24:09 +00:00
button . set _image ( new Gtk . Image ( { icon _name : 'emblem-system-symbolic' ,
icon _size : Gtk . IconSize . BUTTON ,
visible : true } ) ) ;
2016-03-03 23:48:02 +00:00
button . get _style _context ( ) . add _class ( 'circular' ) ;
2014-05-23 02:49:37 +00:00
hbox . add ( button ) ;
this . prefsButton = button ;
2014-05-26 21:40:26 +00:00
2018-11-01 12:55:17 +00:00
this . _switch = new Gtk . Switch ( {
valign : Gtk . Align . CENTER ,
sensitive : this . _canToggle ( ) ,
state : this . _extension . state === ExtensionState . ENABLED
} ) ;
2019-09-09 15:08:53 +00:00
this . _notifyActiveId = this . _switch . connect ( 'notify::active' , ( ) => {
2017-10-31 00:38:18 +00:00
if ( this . _switch . active )
2018-11-01 12:55:17 +00:00
this . _app . shellProxy . EnableExtensionRemote ( this . uuid ) ;
2017-10-31 00:38:18 +00:00
else
2018-11-01 12:55:17 +00:00
this . _app . shellProxy . DisableExtensionRemote ( this . uuid ) ;
2017-10-31 00:38:18 +00:00
} ) ;
this . _switch . connect ( 'state-set' , ( ) => true ) ;
2014-05-26 21:40:26 +00:00
hbox . add ( this . _switch ) ;
2017-10-31 01:23:39 +00:00
}
2014-05-26 21:40:26 +00:00
2018-11-01 12:55:17 +00:00
_canToggle ( ) {
return this . _extension . canChange ;
2014-05-23 02:49:37 +00:00
}
2018-11-01 12:50:30 +00:00
get prefsModule ( ) {
if ( ! this . _prefsModule ) {
ExtensionUtils . installImporter ( this . _extension ) ;
2019-07-05 23:48:05 +00:00
// give extension prefs access to their own extension object
ExtensionUtils . getCurrentExtension = ( ) => this . _extension ;
2018-11-01 12:50:30 +00:00
this . _prefsModule = this . _extension . imports . prefs ;
this . _prefsModule . init ( this . _extension . metadata ) ;
}
return this . _prefsModule ;
}
2014-05-23 02:49:37 +00:00
} ) ;
2012-01-19 02:21:56 +00:00
function initEnvironment ( ) {
// Monkey-patch in a "global" object that fakes some Shell utilities
// that ExtensionUtils depends on.
window . global = {
2019-02-12 11:24:30 +00:00
log ( ... args ) {
print ( args . join ( ', ' ) ) ;
2012-01-19 02:21:56 +00:00
} ,
2017-10-31 00:03:21 +00:00
logError ( s ) {
2019-01-30 00:18:24 +00:00
log ( ` ERROR: ${ s } ` ) ;
2012-01-19 02:21:56 +00:00
} ,
userdatadir : GLib . build _filenamev ( [ GLib . get _user _data _dir ( ) , 'gnome-shell' ] )
} ;
String . prototype . format = Format . format ;
}
function main ( argv ) {
initEnvironment ( ) ;
Gettext . bindtextdomain ( Config . GETTEXT _PACKAGE , Config . LOCALEDIR ) ;
Gettext . textdomain ( Config . GETTEXT _PACKAGE ) ;
2019-05-28 21:22:37 +00:00
new Application ( ) . run ( argv ) ;
2012-01-19 02:21:56 +00:00
}