gnome-shell/js/ui/shellMountOperation.js
Giovanni Campagna 17c46c2452 Port everything to class framework
The last patch in the sequence. Every place that was previously
setting prototype has been ported to Lang.Class, to make code more
concise and allow for better toString().

https://bugzilla.gnome.org/show_bug.cgi?id=664436
2011-11-24 09:50:04 +01:00

387 lines
14 KiB
JavaScript

// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const Params = imports.misc.params;
const LIST_ITEM_ICON_SIZE = 48;
/* ------ Common Utils ------- */
function _setLabelText(label, text) {
if (text) {
label.set_text(text);
label.show();
} else {
label.set_text('');
label.hide();
}
}
function _setButtonsForChoices(dialog, choices) {
let buttons = [];
for (let idx = 0; idx < choices.length; idx++) {
let button = idx;
buttons.unshift({ label: choices[idx],
action: Lang.bind(dialog, function() {
dialog.emit('response', button);
})});
}
dialog.setButtons(buttons);
}
function _setLabelsForMessage(dialog, message) {
let labels = message.split('\n');
_setLabelText(dialog.subjectLabel, labels[0]);
if (labels.length > 1)
_setLabelText(dialog.descriptionLabel, labels[1]);
}
/* -------------------------------------------------------- */
const ListItem = new Lang.Class({
Name: 'ListItem',
_init: function(app) {
this._app = app;
let layout = new St.BoxLayout({ vertical: false});
this.actor = new St.Button({ style_class: 'show-processes-dialog-app-list-item',
can_focus: true,
child: layout,
reactive: true,
x_align: St.Align.START,
x_fill: true });
this._icon = this._app.create_icon_texture(LIST_ITEM_ICON_SIZE);
let iconBin = new St.Bin({ style_class: 'show-processes-dialog-app-list-item-icon',
child: this._icon });
layout.add(iconBin);
this._nameLabel = new St.Label({ text: this._app.get_name(),
style_class: 'show-processes-dialog-app-list-item-name' });
let labelBin = new St.Bin({ y_align: St.Align.MIDDLE,
child: this._nameLabel });
layout.add(labelBin);
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
},
_onClicked: function() {
this.emit('activate');
this._app.activate();
}
});
Signals.addSignalMethods(ListItem.prototype);
const ShellMountOperation = new Lang.Class({
Name: 'ShellMountOperation',
_init: function(source, params) {
params = Params.parse(params, { reaskPassword: false });
this._reaskPassword = params.reaskPassword;
this._dialog = null;
this._processesDialog = null;
this.mountOp = new Shell.MountOperation();
this.mountOp.connect('ask-question',
Lang.bind(this, this._onAskQuestion));
this.mountOp.connect('ask-password',
Lang.bind(this, this._onAskPassword));
this.mountOp.connect('show-processes-2',
Lang.bind(this, this._onShowProcesses2));
this.mountOp.connect('aborted',
Lang.bind(this, this._onAborted));
this._icon = new St.Icon({ gicon: source.get_icon(),
style_class: 'shell-mount-operation-icon' });
},
_onAskQuestion: function(op, message, choices) {
this._dialog = new ShellMountQuestionDialog(this._icon);
this._dialog.connect('response',
Lang.bind(this, function(object, choice) {
this.mountOp.set_choice(choice);
this.mountOp.reply(Gio.MountOperationResult.HANDLED);
this._dialog.close(global.get_current_time());
this._dialog = null;
}));
this._dialog.update(message, choices);
this._dialog.open(global.get_current_time());
},
_onAskPassword: function(op, message) {
this._notificationShowing = true;
this._source = new ShellMountPasswordSource(message, this._icon, this._reaskPassword);
this._source.connect('password-ready',
Lang.bind(this, function(source, password) {
this.mountOp.set_password(password);
this.mountOp.reply(Gio.MountOperationResult.HANDLED);
this._notificationShowing = false;
this._source.destroy();
}));
this._source.connect('destroy',
Lang.bind(this, function() {
if (!this._notificationShowing)
return;
this._notificationShowing = false;
this.mountOp.reply(Gio.MountOperationResult.ABORTED);
}));
},
_onAborted: function(op) {
if (!this._dialog)
return;
this._dialog.close(global.get_current_time());
this._dialog = null;
},
_onShowProcesses2: function(op) {
let processes = op.get_show_processes_pids();
let choices = op.get_show_processes_choices();
let message = op.get_show_processes_message();
if (!this._processesDialog) {
this._processesDialog = new ShellProcessesDialog(this._icon);
this._dialog = this._processesDialog;
this._processesDialog.connect('response',
Lang.bind(this, function(object, choice) {
if (choice == -1) {
this.mountOp.reply(Gio.MountOperationResult.ABORTED);
} else {
this.mountOp.set_choice(choice);
this.mountOp.reply(Gio.MountOperationResult.HANDLED);
}
this._processesDialog.close(global.get_current_time());
this._dialog = null;
}));
this._processesDialog.open(global.get_current_time());
}
this._processesDialog.update(message, processes, choices);
},
});
const ShellMountQuestionDialog = new Lang.Class({
Name: 'ShellMountQuestionDialog',
Extends: ModalDialog.ModalDialog,
_init: function(icon) {
this.parent({ styleClass: 'mount-question-dialog' });
let mainContentLayout = new St.BoxLayout();
this.contentLayout.add(mainContentLayout, { x_fill: true,
y_fill: false });
this._iconBin = new St.Bin({ child: icon });
mainContentLayout.add(this._iconBin,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
let messageLayout = new St.BoxLayout({ vertical: true });
mainContentLayout.add(messageLayout,
{ y_align: St.Align.START });
this.subjectLabel = new St.Label({ style_class: 'mount-question-dialog-subject' });
messageLayout.add(this.subjectLabel,
{ y_fill: false,
y_align: St.Align.START });
this.descriptionLabel = new St.Label({ style_class: 'mount-question-dialog-description' });
this.descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this.descriptionLabel.clutter_text.line_wrap = true;
messageLayout.add(this.descriptionLabel,
{ y_fill: true,
y_align: St.Align.START });
},
update: function(message, choices) {
_setLabelsForMessage(this, message);
_setButtonsForChoices(this, choices);
}
});
Signals.addSignalMethods(ShellMountQuestionDialog.prototype);
const ShellMountPasswordSource = new Lang.Class({
Name: 'ShellMountPasswordSource',
Extends: MessageTray.Source,
_init: function(message, icon, reaskPassword) {
let strings = message.split('\n');
this.parent(strings[0]);
this._notification = new ShellMountPasswordNotification(this, strings, icon, reaskPassword);
// add ourselves as a source, and popup the notification
Main.messageTray.add(this);
this.notify(this._notification);
},
});
Signals.addSignalMethods(ShellMountPasswordSource.prototype);
const ShellMountPasswordNotification = new Lang.Class({
Name: 'ShellMountPasswordNotification',
Extends: MessageTray.Notification,
_init: function(source, strings, icon, reaskPassword) {
this.parent(source, strings[0], null, { customContent: true, icon: icon });
// set the notification to transient and urgent, so that it
// expands out
this.setTransient(true);
this.setUrgency(MessageTray.Urgency.CRITICAL);
if (strings[1])
this.addBody(strings[1]);
if (reaskPassword) {
let label = new St.Label({ style_class: 'mount-password-reask',
text: _("Wrong password, please try again") });
this.addActor(label);
}
this._responseEntry = new St.Entry({ style_class: 'mount-password-entry',
can_focus: true });
this.setActionArea(this._responseEntry);
this._responseEntry.clutter_text.connect('activate',
Lang.bind(this, this._onEntryActivated));
this._responseEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
this._responseEntry.grab_key_focus();
},
_onEntryActivated: function() {
let text = this._responseEntry.get_text();
if (text == '')
return;
this.source.emit('password-ready', text);
}
});
const ShellProcessesDialog = new Lang.Class({
Name: 'ShellProcessesDialog',
Extends: ModalDialog.ModalDialog,
_init: function(icon) {
this.parent({ styleClass: 'show-processes-dialog' });
let mainContentLayout = new St.BoxLayout();
this.contentLayout.add(mainContentLayout, { x_fill: true,
y_fill: false });
this._iconBin = new St.Bin({ child: icon });
mainContentLayout.add(this._iconBin,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
let messageLayout = new St.BoxLayout({ vertical: true });
mainContentLayout.add(messageLayout,
{ y_align: St.Align.START });
this.subjectLabel = new St.Label({ style_class: 'show-processes-dialog-subject' });
messageLayout.add(this.subjectLabel,
{ y_fill: false,
y_align: St.Align.START });
this.descriptionLabel = new St.Label({ style_class: 'show-processes-dialog-description' });
this.descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this.descriptionLabel.clutter_text.line_wrap = true;
messageLayout.add(this.descriptionLabel,
{ y_fill: true,
y_align: St.Align.START });
let scrollView = new St.ScrollView({ style_class: 'show-processes-dialog-app-list'});
scrollView.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.AUTOMATIC);
this.contentLayout.add(scrollView,
{ x_fill: true,
y_fill: true });
scrollView.hide();
this._applicationList = new St.BoxLayout({ vertical: true });
scrollView.add_actor(this._applicationList,
{ x_fill: true,
y_fill: true,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
this._applicationList.connect('actor-added',
Lang.bind(this, function() {
if (this._applicationList.get_children().length == 1)
scrollView.show();
}));
this._applicationList.connect('actor-removed',
Lang.bind(this, function() {
if (this._applicationList.get_children().length == 0)
scrollView.hide();
}));
},
_setAppsForPids: function(pids) {
// remove all the items
this._applicationList.destroy_children();
pids.forEach(Lang.bind(this, function(pid) {
let tracker = Shell.WindowTracker.get_default();
let app = tracker.get_app_from_pid(pid);
if (!app)
return;
let item = new ListItem(app);
this._applicationList.add(item.actor, { x_fill: true });
item.connect('activate',
Lang.bind(this, function() {
// use -1 to indicate Cancel
this.emit('response', -1);
}));
}));
},
update: function(message, processes, choices) {
this._setAppsForPids(processes);
_setLabelsForMessage(this, message);
_setButtonsForChoices(this, choices);
}
});
Signals.addSignalMethods(ShellProcessesDialog.prototype);