327 lines
9.3 KiB
JavaScript
327 lines
9.3 KiB
JavaScript
|
const { Clutter, GObject, Pango, Shell, St } = imports.gi;
|
||
|
|
||
|
const Search = imports.ui.search;
|
||
|
const Main = imports.ui.main;
|
||
|
const Util = imports.misc.util;
|
||
|
|
||
|
// Based on ProviderInfo in search.js
|
||
|
var RealmProviderInfo = GObject.registerClass(
|
||
|
class RealmProviderInfo extends St.Button {
|
||
|
_init() {
|
||
|
super._init({
|
||
|
style_class: 'search-provider-icon',
|
||
|
reactive: false,
|
||
|
can_focus: false,
|
||
|
accessible_name: "Realms",
|
||
|
track_hover: false,
|
||
|
y_align: Clutter.ActorAlign.START,
|
||
|
});
|
||
|
|
||
|
this._content = new St.BoxLayout({ vertical: false,
|
||
|
style_class: 'list-search-provider-content' });
|
||
|
this.set_child(this._content);
|
||
|
|
||
|
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
|
||
|
icon_name: 'computer' });
|
||
|
|
||
|
let detailsBox = new St.BoxLayout({ style_class: 'list-search-provider-details',
|
||
|
vertical: true,
|
||
|
x_expand: true });
|
||
|
|
||
|
let nameLabel = new St.Label({
|
||
|
text: "Realms",
|
||
|
x_align: Clutter.ActorAlign.START
|
||
|
});
|
||
|
|
||
|
this._moreLabel = new St.Label({ x_align: Clutter.ActorAlign.START });
|
||
|
|
||
|
detailsBox.add_actor(nameLabel);
|
||
|
detailsBox.add_actor(this._moreLabel);
|
||
|
|
||
|
|
||
|
this._content.add_actor(icon);
|
||
|
this._content.add_actor(detailsBox);
|
||
|
}
|
||
|
|
||
|
get PROVIDER_ICON_SIZE() {
|
||
|
return 48;
|
||
|
}
|
||
|
|
||
|
setMoreCount(count) {
|
||
|
this._moreLabel.text = ngettext("%d more", "%d more", count).format(count);
|
||
|
this._moreLabel.visible = count > 0;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
var MAX_LIST_SEARCH_RESULTS_ROWS = 10;
|
||
|
|
||
|
// Based on ListSearchResult in search.js
|
||
|
var RealmSearchResult = GObject.registerClass(
|
||
|
class ListSearchResult extends Search.SearchResult {
|
||
|
_init(provider, metaInfo, resultsView) {
|
||
|
super._init(provider, metaInfo, resultsView);
|
||
|
|
||
|
this.style_class = 'list-search-result';
|
||
|
|
||
|
let content = new St.BoxLayout({
|
||
|
style_class: 'list-search-result-content',
|
||
|
vertical: false,
|
||
|
x_align: Clutter.ActorAlign.FILL,
|
||
|
x_expand: true,
|
||
|
y_expand: true,
|
||
|
});
|
||
|
this.set_child(content);
|
||
|
|
||
|
this._termsChangedId = 0;
|
||
|
|
||
|
let titleBox = new St.BoxLayout({
|
||
|
style_class: 'list-search-result-title',
|
||
|
y_align: Clutter.ActorAlign.CENTER,
|
||
|
});
|
||
|
|
||
|
content.add_child(titleBox);
|
||
|
|
||
|
// An icon for, or thumbnail of, content
|
||
|
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
|
||
|
if (icon)
|
||
|
titleBox.add(icon);
|
||
|
|
||
|
let title = new St.Label({
|
||
|
text: this.metaInfo['name'],
|
||
|
y_align: Clutter.ActorAlign.CENTER,
|
||
|
});
|
||
|
titleBox.add_child(title);
|
||
|
|
||
|
this.label_actor = title;
|
||
|
|
||
|
if (this.metaInfo['description']) {
|
||
|
this._descriptionLabel = new St.Label({
|
||
|
style_class: 'list-search-result-description',
|
||
|
x_expand: true,
|
||
|
x_align: Clutter.ActorAlign.START,
|
||
|
y_align: Clutter.ActorAlign.CENTER,
|
||
|
});
|
||
|
this._descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||
|
content.add_child(this._descriptionLabel);
|
||
|
|
||
|
this._termsChangedId =
|
||
|
this._resultsView.connect('terms-changed',
|
||
|
this._highlightTerms.bind(this));
|
||
|
|
||
|
this._highlightTerms();
|
||
|
}
|
||
|
|
||
|
let id = this.metaInfo['id'];
|
||
|
|
||
|
if (id != ':new:') {
|
||
|
this.configButton = new St.Button({
|
||
|
style_class: 'button',
|
||
|
track_hover: true,
|
||
|
can_focus: true,
|
||
|
child: new St.Icon({
|
||
|
style_class: 'realm-config-icon',
|
||
|
icon_name: 'emblem-system-symbolic',
|
||
|
icon_size: 24,
|
||
|
}),
|
||
|
});
|
||
|
|
||
|
this.configButton.connect('clicked', () => {
|
||
|
Main.overview.toggle();
|
||
|
Util.spawn(['/usr/libexec/realm-config-ui', id]);
|
||
|
});
|
||
|
content.add_child(this.configButton);
|
||
|
}
|
||
|
|
||
|
this.connect('destroy', this._onDestroy.bind(this));
|
||
|
}
|
||
|
|
||
|
get ICON_SIZE() {
|
||
|
return 24;
|
||
|
}
|
||
|
|
||
|
_highlightTerms() {
|
||
|
let markup = this._resultsView.highlightTerms(this.metaInfo['description'].split('\n')[0]);
|
||
|
this._descriptionLabel.clutter_text.set_markup(markup);
|
||
|
}
|
||
|
|
||
|
_onDestroy() {
|
||
|
if (this._termsChangedId)
|
||
|
this._resultsView.disconnect(this._termsChangedId);
|
||
|
this._termsChangedId = 0;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Based on ListSearchResults in search.js
|
||
|
var RealmSearchResults = GObject.registerClass(
|
||
|
class RealmSearchResults extends Search.SearchResultsBase {
|
||
|
_init(provider, resultsView) {
|
||
|
super._init(provider, resultsView);
|
||
|
|
||
|
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
|
||
|
this.providerInfo = new RealmProviderInfo();
|
||
|
this.providerInfo.connect('key-focus-in', this._keyFocusIn.bind(this));
|
||
|
this.providerInfo.connect('clicked', () => {
|
||
|
Main.overview.toggle();
|
||
|
});
|
||
|
|
||
|
this._container.add_child(this.providerInfo);
|
||
|
|
||
|
this._content = new St.BoxLayout({
|
||
|
style_class: 'list-search-results',
|
||
|
vertical: true,
|
||
|
x_expand: true,
|
||
|
});
|
||
|
this._container.add_child(this._content);
|
||
|
|
||
|
this._resultDisplayBin.set_child(this._container);
|
||
|
}
|
||
|
|
||
|
_setMoreCount(count) {
|
||
|
this.providerInfo.setMoreCount(count);
|
||
|
}
|
||
|
|
||
|
_getMaxDisplayedResults() {
|
||
|
return MAX_LIST_SEARCH_RESULTS_ROWS;
|
||
|
}
|
||
|
|
||
|
_clearResultDisplay() {
|
||
|
this._content.remove_all_children();
|
||
|
}
|
||
|
|
||
|
_createResultDisplay(meta) {
|
||
|
return super._createResultDisplay(meta) ||
|
||
|
new RealmSearchResult(this.provider, meta, this._resultsView);
|
||
|
}
|
||
|
|
||
|
_addItem(display) {
|
||
|
this._content.add_actor(display);
|
||
|
}
|
||
|
|
||
|
getFirstResult() {
|
||
|
if (this._content.get_n_children() > 0)
|
||
|
return this._content.get_child_at_index(0);
|
||
|
else
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
});
|
||
|
|
||
|
var RealmSearchProvider = class RealmSearchProvider {
|
||
|
constructor() {
|
||
|
this._shellRealms = Shell.Realms.get_default();
|
||
|
this.id = 'realms';
|
||
|
this.isRemoteProvider = false;
|
||
|
this.canLaunchSearch = false;
|
||
|
this.display = null;
|
||
|
}
|
||
|
|
||
|
createResultDisplay(resultsView) {
|
||
|
this.display = new RealmSearchResults(this, resultsView);
|
||
|
this.display.connect('notify::focus-child', resultsView._focusChildChanged.bind(resultsView));
|
||
|
this.display.hide();
|
||
|
resultsView._content.add(this.display);
|
||
|
}
|
||
|
|
||
|
createIcon(size, realm) {
|
||
|
if (realm.is_running()) {
|
||
|
return new St.Icon({ icon_name: 'emblem-synchronizing', icon_size: size });
|
||
|
} else {
|
||
|
return new St.Icon({ icon_name: 'exaile', icon_size: size });
|
||
|
}
|
||
|
}
|
||
|
|
||
|
createRealmMeta(realm) {
|
||
|
let id = realm.get_realm_name();
|
||
|
let description = '';
|
||
|
if (realm.is_running()) {
|
||
|
description = `Set realm-${id} as current realm`;
|
||
|
} else {
|
||
|
description = `Start realm-${id}`;
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
id: id,
|
||
|
name: `realm-${id}`,
|
||
|
description: description,
|
||
|
createIcon: size => {
|
||
|
return this.createIcon(size, realm);
|
||
|
},
|
||
|
};
|
||
|
}
|
||
|
|
||
|
createNewRealmMeta() {
|
||
|
return {
|
||
|
id: ':new:',
|
||
|
name: 'New Realm',
|
||
|
description: 'Create a new realm',
|
||
|
createIcon: size => {
|
||
|
return new St.Icon({
|
||
|
icon_name: 'computer',
|
||
|
icon_size: size,
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
getResultMetas (ids, callback) {
|
||
|
let metas = [];
|
||
|
|
||
|
for (let id of ids) {
|
||
|
if (id == ":new:") {
|
||
|
metas.push(this.createNewRealmMeta());
|
||
|
} else {
|
||
|
let realm = this._shellRealms.realm_by_name(id);
|
||
|
if (realm && !realm.is_current()) {
|
||
|
metas.push(this.createRealmMeta(realm));
|
||
|
} else {
|
||
|
log(`No realm found for ${id}`);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
callback(metas);
|
||
|
}
|
||
|
|
||
|
activateResult (resultId, _terms) {
|
||
|
|
||
|
if (resultId == ':new:') {
|
||
|
Main.overview.toggle();
|
||
|
Util.spawn(['/usr/libexec/realm-config-ui', '--new']);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
let realm = this._shellRealms.realm_by_name(resultId);
|
||
|
if (realm) {
|
||
|
realm.set_current();
|
||
|
} else {
|
||
|
log(`No realm found for ${resultId}`);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
filterResults(results, maxNumber) {
|
||
|
return results.slice(0, maxNumber)
|
||
|
}
|
||
|
|
||
|
getInitialResultSet(terms, callback, _cancellable) {
|
||
|
let realms = this._shellRealms.get_all_realms();
|
||
|
let matches = [];
|
||
|
|
||
|
if (terms.length == 1 && "new".startsWith(terms[0])) {
|
||
|
matches.push(":new:");
|
||
|
}
|
||
|
|
||
|
for (let realm of realms) {
|
||
|
if (!realm.is_current()) {
|
||
|
let name = realm.get_realm_name();
|
||
|
if (terms.every(t => name.indexOf(t) != -1)) {
|
||
|
matches.push(name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
callback(matches);
|
||
|
}
|
||
|
|
||
|
getSubsearchResultSet(previousResults, terms, callback, cancellable) {
|
||
|
this.getInitialResultSet(terms, callback, cancellable)
|
||
|
}
|
||
|
}
|