GNOME Shell 3.4 Extension that will add remmina configurations to the search results

Michael Roma on Jun 27, 2012

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;
    }
}