Below is javascript code for a gnome shell 3.4 extension that will add remmina configurations that are stored in a text file to the shell search results. I plan to update this extension in the future to read the contents .remmina directory instead of a text file. The text file is assumed to be ~/src/rdp and contain an rdp per line in the format: Server 1{tab}12312323.remmina Server 2{tab}23444324.remmina etc.
const St = imports.gi.St;
const Main = imports.ui.main;
const Search = imports.ui.search;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Util = imports.misc.util;
// define search provider object
var rdpSearchProvider = null;
// define file watch to detect changes in the source text file
var rdpConfigFileWatcher = null;
// define class
const RemminaSearchProvider = new Lang.Class({
Name: ‘RemminaSearchProvider’,
Extends: Search.SearchProvider,
// init
_init: function(name) {
global.log(‘init remmina-search’);
Search.SearchProvider.prototype._init.call(this, “Remote Desktops”);
// define remmina path
this.remminaPath = GLib.build_filenamev([GLib.get_home_dir(), “.remmina”]);
// define config path for remmina definitions
this.remminaConfigPath = GLib.build_filenamev([GLib.get_home_dir(), “src/rdp”]);
// define the remmina config list and read
this._remminaConfigs = [];
this._readRemminaConfigs();
// setup file monitor to detect changes
let fileWatch = Gio.file_new_for_path(this.remminaConfigPath);
rdpConfigFileWatcher = fileWatch.monitor(Gio.FileMonitorFlags.NONE, null);
rdpConfigFileWatcher.connect(‘changed’, Lang.bind(this, this._readRemminaConfigs));
return true;
},
// function that reads the configurations from the file
_readRemminaConfigs : function () {
// init list
this._remminaConfigs = [];
// get the file data
let filedata;
try {
filedata = GLib.file_get_contents(this.remminaConfigPath, null, 0);
} catch (e) {
Main.notifyError(“Error reading file”, e.message);
return false;
}
// attempt to parse the data
if ( (filedata[1].length != 0) && (filedata[1] != null) ) {
try {
// get each line
let rdpInfoLines = String(filedata[1]).trim().split(‘\n’);
for (var i=0; i<rdpInfoLines.length; i++) {
// parse rdp info: 0 = name, 1 = remmina config file
let rdpInfo = String(rdpInfoLines[i]).trim().split(‘\t’);
// push rdp info to the list
this._remminaConfigs.push([rdpInfo[0], this.remminaPath + “/” + rdpInfo[1]]);
}
} catch (e) {
Main.notifyError(“Error parsing file - “+ filedata, e.message);
return false;
}
} else {
Main.notifyError(“Error parsing file - Empty data”);
return false;
}
// ok
return true;
},
// return results back to search
getResultMetas: function(resultIds, callback) {
// define results
let metas = [];
// go through each result
for (let i = 0; i < resultIds.length; i++) {
let resultId = resultIds[i];
// get the rdp name, fallback to url if no name
let rdpInfoName = “”;
if (resultId.name)
rdpInfoName = resultId.name;
else
rdpInfoName = resultId.url;
// add the result to the list
metas.push({ ‘id’: resultId,
‘name’: rdpInfoName,
‘createIcon’: function(size) {
let xicon = new Gio.ThemedIcon({name: ‘remmina’});
return new St.Icon({icon_size: size, gicon: xicon});
}
});
}
// call back with results
callback(metas);
},
// define method to open fetched result
activateResult: function(id) {
Util.spawn([‘/usr/bin/remmina’, ‘-c’, id.url]);
},
// function that searches the rdp configs using terms passed
_checkRemminaConfigs: function(configs, terms) {
// define results
let searchResults = [];
// go through each rdp and term
for (var i=0; i<configs.length; i++) {
for (var j=0; j<terms.length; j++) {
try {
// get the name and url and build the string to search
let name = configs[i][0];
let url = configs[i][1];
let searchStr = name+url;
// search the string
let pattern = new RegExp(terms[j],“gi”);
if (searchStr.match(pattern)) {
// add to the list if matched
searchResults.push({
‘name’: name,
‘url’: url
});
}
}
catch(ex) {
continue;
}
}
}
// return results
return searchResults;
},
// function that returns the initial results
getInitialResultSet: function(terms) {
this.searchSystem.pushResults(this, this._checkRemminaConfigs(this._remminaConfigs, terms));
},
// call same initial search on subsearch
getSubsearchResultSet: function(previousResults, terms) {
this.getInitialResultSet(terms);
}
});
// init event
function init(meta) {
}
// enable event
function enable() {
// check if search provider already initialized, create new
if (rdpSearchProvider==null) {
rdpSearchProvider = new RemminaSearchProvider();
Main.overview.addSearchProvider(rdpSearchProvider);
}
}
// disable event
function disable() {
// if search provider exists, disable it
if (rdpSearchProvider!=null) {
Main.overview.removeSearchProvider(rdpSearchProvider);
rdpSearchProvider.rdpConfigFileWatcher.cancel();
rdpSearchProvider = null;
}
}