mount-operation: turn the passphrase prompt into a dialog

Instead of a notification. This also adds space for a checkbox allowing
to remember the passphrase.

https://bugzilla.gnome.org/show_bug.cgi?id=674962
This commit is contained in:
Cosimo Cecchi 2012-06-19 18:12:11 -04:00
parent 61de3de909
commit d1815a36d0

View File

@ -1,5 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang; const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
@ -8,10 +9,12 @@ const Pango = imports.gi.Pango;
const St = imports.gi.St; const St = imports.gi.St;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const CheckBox = imports.ui.checkBox;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const Params = imports.misc.params; const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
const LIST_ITEM_ICON_SIZE = 48; const LIST_ITEM_ICON_SIZE = 48;
@ -134,42 +137,37 @@ const ShellMountOperation = new Lang.Class({
}, },
_onAskPassword: function(op, message) { _onAskPassword: function(op, message) {
this._notificationShowing = true; this._dialog = new ShellMountPasswordDialog(
this._source = new ShellMountPasswordSource(message, this._gicon, this._reaskPassword); message, this._gicon, this._reaskPassword);
this._source.connect('password-ready', this._dialog.connect('response', Lang.bind(this,
Lang.bind(this, function(source, password) { function(object, choice, password, remember) {
this.mountOp.set_password(password); if (choice == '-1') {
this.mountOp.reply(Gio.MountOperationResult.HANDLED); this.mountOp.reply(Gio.MountOperationResult.ABORTED);
} else {
if (remember)
this.mountOp.set_password_save(Gio.PasswordSave.PERMANENTLY);
else
this.mountOp.set_password_save(Gio.PasswordSave.NEVER);
this._notificationShowing = false; this.mountOp.set_password(password);
this._source.destroy(); this.mountOp.reply(Gio.MountOperationResult.HANDLED);
})); }
this._source.connect('destroy', this._dialog.close(global.get_current_time());
Lang.bind(this, function() { this._dialog = null;
if (!this._notificationShowing) }));
return; this._dialog.open(global.get_current_time());
this._notificationShowing = false;
this.mountOp.reply(Gio.MountOperationResult.ABORTED);
}));
}, },
_onAborted: function(op) { _onAborted: function(op) {
if (!this._dialog && !this._source) if (!this._dialog)
return; return;
if (this._dialog) { if (this._dialog) {
this._dialog.close(global.get_current_time()); this._dialog.close(global.get_current_time());
this._dialog = null; this._dialog = null;
} }
if (this._source) {
this._notificationShowing = false;
this._source.destroy();
this._source = null;
}
}, },
_onShowProcesses2: function(op) { _onShowProcesses2: function(op) {
@ -181,7 +179,7 @@ const ShellMountOperation = new Lang.Class({
this._processesDialog = new ShellProcessesDialog(this._gicon); this._processesDialog = new ShellProcessesDialog(this._gicon);
this._dialog = this._processesDialog; this._dialog = this._processesDialog;
this._processesDialog.connect('response', this._processesDialog.connect('response',
Lang.bind(this, function(object, choice) { Lang.bind(this, function(object, choice) {
if (choice == -1) { if (choice == -1) {
this.mountOp.reply(Gio.MountOperationResult.ABORTED); this.mountOp.reply(Gio.MountOperationResult.ABORTED);
@ -246,67 +244,98 @@ const ShellMountQuestionDialog = new Lang.Class({
}); });
Signals.addSignalMethods(ShellMountQuestionDialog.prototype); Signals.addSignalMethods(ShellMountQuestionDialog.prototype);
const ShellMountPasswordSource = new Lang.Class({ const ShellMountPasswordDialog = new Lang.Class({
Name: 'ShellMountPasswordSource', Name: 'ShellMountPasswordDialog',
Extends: MessageTray.Source, Extends: ModalDialog.ModalDialog,
_init: function(message, gicon, reaskPassword) { _init: function(message, gicon, reaskPassword) {
this._gicon = gicon;
let strings = message.split('\n'); let strings = message.split('\n');
this.parent(strings[0]); this.parent({ styleClass: 'prompt-dialog' });
this._notification = new ShellMountPasswordNotification(this, strings, reaskPassword);
// add ourselves as a source, and popup the notification let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
Main.messageTray.add(this); vertical: false });
this.notify(this._notification); this.contentLayout.add(mainContentBox);
},
createNotificationIcon: function() { let icon = _createIcon(gicon);
return _createIcon(this._gicon); mainContentBox.add(icon,
}, { x_fill: true,
}); y_fill: false,
Signals.addSignalMethods(ShellMountPasswordSource.prototype); x_align: St.Align.END,
y_align: St.Align.START });
const ShellMountPasswordNotification = new Lang.Class({ this._messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
Name: 'ShellMountPasswordNotification', vertical: true });
Extends: MessageTray.Notification, mainContentBox.add(this._messageBox,
{ y_align: St.Align.START, expand: true, x_fill: true, y_fill: true });
_init: function(source, strings, reaskPassword) { let subject = new St.Label({ style_class: 'prompt-dialog-headline' });
this.parent(source, strings[0], null, { customContent: true }); this._messageBox.add(subject,
{ y_fill: false,
// set the notification to transient and urgent, so that it y_align: St.Align.START });
// expands out if (strings[0])
this.setTransient(true); subject.set_text(strings[0]);
this.setUrgency(MessageTray.Urgency.CRITICAL);
let description = new St.Label({ style_class: 'prompt-dialog-description' });
description.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
description.clutter_text.line_wrap = true;
this._messageBox.add(description,
{ y_fill: true,
y_align: St.Align.START });
if (strings[1]) if (strings[1])
this.addBody(strings[1]); description.set_text(strings[1]);
this._passwordBox = new St.BoxLayout({ vertical: false });
this._messageBox.add(this._passwordBox);
this._passwordLabel = new St.Label(({ style_class: 'prompt-dialog-password-label',
text: _("Passphrase") }));
this._passwordBox.add(this._passwordLabel);
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: "",
can_focus: true});
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivate));
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
this._passwordBox.add(this._passwordEntry, {expand: true });
this.setInitialKeyFocus(this._passwordEntry);
if (reaskPassword) { if (reaskPassword) {
let label = new St.Label({ style_class: 'mount-password-reask', this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label',
text: _("Wrong password, please try again") }); text: _("Sorry, that didn\'t work. Please try again.") });
this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this.addActor(label); this._errorMessageLabel.clutter_text.line_wrap = true;
this._messageBox.add(this._errorMessageLabel);
} }
this._responseEntry = new St.Entry({ style_class: 'mount-password-entry', this._rememberChoice = new CheckBox.CheckBox();
can_focus: true }); this._rememberChoice.getLabelActor().text = _("Remember Passphrase");
this.setActionArea(this._responseEntry); this._rememberChoice.actor.checked = true;
this._messageBox.add(this._rememberChoice.actor);
this._responseEntry.clutter_text.connect('activate', let buttons = [{ label: _("Cancel"),
Lang.bind(this, this._onEntryActivated)); action: Lang.bind(this, this._onCancelButton),
this._responseEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE key: Clutter.Escape
},
{ label: _("Unlock"),
action: Lang.bind(this, this._onUnlockButton)
}];
this._responseEntry.grab_key_focus(); this.setButtons(buttons);
}, },
_onEntryActivated: function() { _onCancelButton: function() {
let text = this._responseEntry.get_text(); this.emit('response', -1, '', false);
if (text == '') },
return;
this.source.emit('password-ready', text); _onUnlockButton: function() {
this._onEntryActivate();
},
_onEntryActivate: function() {
this.emit('response', 1,
this._passwordEntry.get_text(),
this._rememberChoice.actor.checked);
} }
}); });