SugarCRM 7 - Conditional Read Only Fields

Posted on Sat 06 February 2016 in SugarCRM • Tagged with javascript, sugarcrmLeave a comment

SugarCRM has a few ways to set fields as read-only, but it leaves a lot to be desired. One of the missing features that you might need to implement is having a module flagged as read-only on the record view based on a field on the module or the result of an API request.

I have found a way to do it but it is mostly basic UI hacking and doesn't set the field read-only everywhere on the UI, just the record view page. So it will remain on the recordlist view or within other subpanels as editable, so bear this in mind as it's only useful for very specific cases.

Here's a quick javascript function that'll iterate over all sidecar metadata panels and flag every field on the UI. Simply add in a conditional to flag only certain fields and wrap it in whatever checks you need to make. Stick this in your record.js.

setReadOnly: function() {
    if(this.readOnly) {
        // set fields to read-only
        _.each(this.meta.panels, function(panel) {
            _.each(panel.fields, function(field) {

NetworkX - Get all Paths from all sources to sinks

Posted on Wed 04 November 2015 in Python • Tagged with python, snippet, networkx, graphLeave a comment

Often when I'm working with graphs and a set of masses in a spectrum I need to be able to iterate over all paths for all sources and sinks in that graph. Especially if I'm looking to compare multiple ideal spectrums against a given spectrum. Here's some code that will allow me to quickly iterate over all source->sink paths in a given graph G.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
Shane Dowling, 04 Nov 2015
Will iterate over all sources, sinks and get all paths
import networkx as nx

G = nx.DiGraph()
# Fill in a few edges
sink_nodes = [node for node, outdegree in G.out_degree(G.nodes()).items() if outdegree == 0]
source_nodes = [node for node, indegree in G.in_degree(G.nodes()).items() if indegree == 0]
for  [(source, sink) for sink in sink_nodes for source in source_nodes]:
    for path in nx.all_simple_paths(G, source=source, target=sink):

Generate Binary Tree From String

Posted on Tue 27 October 2015 in Python • Tagged with python, snippet, networkx, graphLeave a comment

Recently while implementing the Small Parsimony Problem I had the need to generate a binary tree from a string in Python.

The pseudo-code in the question implicitly assumes you have some functionality that will generate a DNA sequence like CAAATCCC into a binary tree, then run SmallParsimony on it. I couldn't find that functionality anywhere, so I decided to implement something simple in networkx. Hopefully it's useful.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
Shane Dowling, 27 Oct 2015
To run simply call generate_leaf_graph and pass in s string.

def count_predecessors(T):
    pred = 0
    for v in T.nodes():
        if len(T.predecessors(v)) == 0:
            pred += 1
    return pred

def generate_leaf_graph(s):
    Will generate a leaf graph and return it along
    with the Character dictionary representing the characters
    at each leaf node position
    T = nx.DiGraph()
    Character = {}
    i = 0
    parI = len(s)
    for (son, daughter) in zip(s[0::2], s[1::2]):
        Character[i] = son
        Character[i+1] = daughter
        T.add_edge(parI, i)
        T.add_edge(parI, i+1)
        i += 2
        parI += 1

    while count_predecessors(T) > 1:
        for v in T.nodes():
            if len(T.predecessors(v)) == 0:
                T.add_edge(parI, v)
                T.add_edge(parI, v+1)
                parI += 1
    return [T, Character]

SugarCRM - Conditional Actions

Posted on Thu 15 October 2015 in SugarCRM • Tagged with php, javascriptLeave a comment


Say you need to hide certain actions in Sugar depending on the status of a field, I've come across a great snippet of code from an awesome comment by Felix Nilam on the SugarCRM forums and wanted to show you a brief snippet of how it could work.

Make sure to call it before render, otherwise I had issues with this.meta.buttons already having rendered.

    extendsFrom: 'RecordView',

    initialize: function (options) {
        app.view.invokeParent(this, {type: 'view', name: 'record', method: 'initialize', args:[options]});
        this.before('render', this.mycustom_button_visibility, this);
        this.before('render', this.mycustom2_button_visibility, this);
    mycustom_button_visibility : function() {
        if(typeof this.model.get('some_field') != 'undefined'
        && this.model.get('some_field') != 'some_value') {
    mycustom2_button_visibility : function() {
        if(typeof this.model.get('some_second_field') != 'undefined'
        && this.model.get('some_second_field') != 'some_value') {
    hide_button: function(name) {
        var button_sel = '';
        var button_index = '';
        // find the buttons index for the share button
        _.find(this.meta.buttons, function(bn, idx) {
            if( == 'main_dropdown') {
                button_sel = idx;
                _.find(bn.buttons, function(bbn, idx_bbn) {
                    if( == name) {
                        button_index = idx_bbn;
                        return true;
                return true;
        if(button_sel != '' && button_index != '')
            //remove the meta
            this.meta.buttons[button_sel].buttons.splice(button_index, 1);

Props to Felix for the snippet and I hope this helps others.

Simple Python Text-Entry

Posted on Sun 04 October 2015 in Projects • Tagged with projects, python, emacsLeave a comment


Recently for my biogen project I needed a way to create pop-up text entries for users using virtualenv. Sadly, neither wxPython nor TkInter would work easily without ugly hacks involving symlinking to system directories. Eventually I worked out that Gtk would work via pip. However, I couldn't find sample code anywhere that ran synchronously(not via signals), so I could wait to grab the users input before proceeding along execution. So I cooked up some sample code that might help others.

from pgi.repository import Gtk, GObject

class EntryWindow(Gtk.Window):

    def __init__(self, ask_title="Title", ask_body="Body", message="Message"):
        Gtk.Window.__init__(self, title=ask_title)
        self.set_size_request(200, 100)

        self.timeout_id = None

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)

        label = Gtk.Label(message)
        vbox.pack_start(label, True, True, 0)

        self.entry = Gtk.Entry()
        vbox.pack_start(self.entry, True, True, 0)

        hbox = Gtk.Box(spacing=6)
        vbox.pack_start(hbox, True, True, 0)

        button = Gtk.Button(label="OK")
        vbox.pack_start(button, True, True, 0)

    def on_ok_button_clicked(self,button):

    def run(self):
        result = self.entry.get_text()
        return result

The import uses pgi.repositories not gi.repositories as I needed it to be compatible with PyPy for speed.

To then run this code(and grab it's input), use something like this.

win = EntryWindow("My Title", "Enter Some Text", "Some message")
response_text =

Bioinformatics/Rosalind - Skeleton Generator

Posted on Sun 27 September 2015 in Projects • Tagged with python, bioinformatics, testing, courseraLeave a comment


Working through part 4 of my Cousera Bioinformatics specialisation, I decided to write a generator that creates a standardised approach to structure, write and test your algorithmic code. It also works for Rosalind problems.

Explanations are in the README. If you have any issues or are confused by anything, feel free to get in touch!

You can find the code here.

Tiddlywiki to Org-Mode

Posted on Mon 31 August 2015 in Projects • Tagged with projects, python, emacsLeave a comment


Okay, I swear this is the last document conversion script I’m writing this year. I’ve been on a bit of a rampage to move all of my life in Emacs Org-Mode and converting all of my Tiddlywiki notes into Org mode has been on my list for a while. Thankfully both formats are pretty simple so the script was fairly straightforward.

You can find it here, simply fill in the folder locations and give it a run.

A heads up. If you’re merging the newly generated Org notes into an existing directory, do a dry run in a dummy folder first then compare the dummy results with your existing Org folder. You need to ensure you won’t overwrite any existing files(the script doesn’t do any clever checking).

You can do something like

comm -12 <(ls ~/Documents/OrgFolder) <(ls ~/Documents/DummyFolder/org)

to run an intersection on the two filesets.

OSQA to Tiddlywiki

Posted on Mon 27 July 2015 in Projects • Tagged with projects, pythonLeave a comment


Recently I've been trying out Tiddlywiki as an alternative to Evernote. I decided to try convert my existing OSQA install to Tiddlywiki as I'm travelling a lot and don't always have access to my servers via the internet. Here's a python script I wrote that might help anyones trying to do the same.

You can find it here on github.

Any questions or queries, just let me know!

Verify you're hidden with conky

Posted on Sun 26 July 2015 in Security • • Leave a comment


I run a few scripts to ensure my identity stays hidden day to day on my laptop. Here's a few conky scripts to verify things are as they should be.


Because I don't always know my ip or what my VPN's ip is, I wanted conky to display the location I currently appear at from my VPN. If the location was the same as where I physically am, something's gone wrong. To implement this, I wrote a python script and using grab my location and print it to conky.

Here's the script I use to pull my location.

import requests

def main():
    headers = {
            'User-Agent': 'curl/7.9.8 (i686-pc-linux-gnu) libcurl 7.9.8 (OpenSSL 0.9.6b) (ipv6 enabled)'

    r = requests.get('', headers=headers)
    ipdata = r.json()
    print(ipdata['city'] + ', ' + ipdata['region'] + ', ' + ipdata['country'])

if __name__ == "__main__":

And here's the conky configuration I use to call it.

${goto 40}Location: ${execpi 600 python ~/scripts/conky/}

Note: VPN's don't always completely hide your location. See for an example of how it can be circumvented.

Mac Address

For my mac address I wanted to be able to see my wifi adaptors physical address and what it should be spoofed to. If the two are the same, something's else has gone wrong.

${if_existing /proc/net/route wlan0}
${goto 40}${execpi 600 ethtool -P wlan0}
${goto 40}Spoofed address: ${wireless_ap wlan0}


I also like to randomise my hostname on startup using this script.

${goto 40}Hostname: ${execpi 1000 hostname}

SugarCRM 7 - Adding an action to the listview headerpanel

Posted on Sat 25 July 2015 in SugarCRM • Tagged with php, sugarcrmLeave a comment

A red button with the words "Take action" on it

This tutorial should show you how to add a custom button/action that will appear across all modules. It's a little similar to this tutorial with a few changes to how the button gets rendered and the actions get called.

1. Adding the button to the headerpanel

Firstly you'll need to create a new folder to store the headerpane actions, so create this folder in the sugarcrm root directory custom/clients/base/views/list-headerpane/. Then create the file list-headerpane.php with this content. This will add a button next to the Create button for all modules.

if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

 * Your installation or use of this SugarCRM file is subject to the applicable
 * terms available at
 * If you do not agree to all of the applicable terms or do not have the
 * authority to bind the entity as an authorized representative, then do not
 * install or use this SugarCRM file.
 * Copyright (C) SugarCRM Inc. All rights reserved.

$viewdefs['base']['view']['list-headerpane'] = array(
    'template' => 'headerpane',
    'title' => 'LBL_MODULE_NAME',
    'buttons' => array(
            'name'    => 'new_button',
            'type'    => 'button',
            'label'   => 'LBL_NEW_BUTTON_LABEL',
            'css_class' => 'btn-secondary',
            'acl_action' => 'list',
            'events' => array(
                'click' => 'list:new_button:fire'
            'name'    => 'create_button',
            'type'    => 'button',
            'label'   => 'LBL_CREATE_BUTTON_LABEL',
            'css_class' => 'btn-primary',
            'acl_action' => 'create',
            'route' => array(
            'name' => 'sidebar_toggle',
            'type' => 'sidebartoggle',

2. Adding the action hook

To fire this action you'll need to add some code custom/clients/base/views/recordlist/recordlist.js, in the initialize function add a line like this:

this.context.on('list:new_button:fire', this.applyFxn, this);

Now populate applyFxn with whatever code you want to run and it will work across every module.

3. Quick Repair and Rebuilt(as always)

Any questions feel free to ask!

Extra tip.

Only want to do this for a single module. Instead of placing the code in custom/clients place it in custom/modules/<MODULE_NAME>/clients and it should work for just that one module.