Index: src/sas/qtgui/MainWindow/CategoryManager.py
===================================================================
--- src/sas/qtgui/MainWindow/CategoryManager.py	(revision 3d18691df01d447d24aab707b6772ce6ab95e36c)
+++ src/sas/qtgui/MainWindow/CategoryManager.py	(revision 3d18691df01d447d24aab707b6772ce6ab95e36c)
@@ -0,0 +1,432 @@
+import json
+import os
+
+from PyQt5 import QtGui
+from PyQt5 import QtCore
+from PyQt5 import QtWidgets
+
+from collections import defaultdict
+from sas.qtgui.Utilities.CategoryInstaller import CategoryInstaller
+from sasmodels.sasview_model import load_standard_models
+
+from .UI.CategoryManagerUI import Ui_CategoryManagerUI
+from .UI.ChangeCategoryUI import Ui_ChangeCategoryUI
+
+class ToolTippedItemModel(QtGui.QStandardItemModel):
+    """
+    Subclass from QStandardItemModel to allow displaying tooltips in
+    QTableView model.
+    """
+    def __init__(self, parent=None):
+        QtGui.QStandardItemModel.__init__(self, parent)
+
+    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
+        """
+        Displays tooltip for each column's header
+        :param section:
+        :param orientation:
+        :param role:
+        :return:
+        """
+        if role == QtCore.Qt.ToolTipRole:
+            if orientation == QtCore.Qt.Horizontal:
+                return str(self.header_tooltips[section])
+
+        return QtGui.QStandardItemModel.headerData(self, section, orientation, role)
+
+class Categories(object):
+    """
+    Container class for accessing model categories
+    """
+    def __init__(self):
+        self.master_category_dict = defaultdict(list)
+        self.by_model_dict = defaultdict(list)
+        self.model_enabled_dict = defaultdict(bool)
+        self.models = {}
+
+        # Prepare the master category list
+        self.readCategoryInfo()
+
+        # Prepare model->category lookup
+        self.setupModelDict()
+
+    def readCategoryInfo(self):
+        """
+        Reads the categories in from file
+        """
+        categorization_file = CategoryInstaller.get_user_file()
+        if not os.path.isfile(categorization_file):
+            categorization_file = CategoryInstaller.get_default_file()
+        with open(categorization_file, 'rb') as cat_file:
+            self.master_category_dict = json.load(cat_file)
+            self.regenerateModelDict()
+
+        self.category_list = sorted(self.master_category_dict.keys())
+
+    def saveCategories(self):
+        """
+        Serializes categorization info to file
+        """
+        self.regenerateMasterDict()
+        with open(CategoryInstaller.get_user_file(), 'w') as cat_file:
+            json.dump(self.master_category_dict, cat_file)
+
+    def setupModelDict(self):
+        """
+        create a dictionary for model->category mapping
+        """
+        # Load the model dict
+        models = load_standard_models()
+        for model in models:
+            # {model name -> model object}
+            self.models[model.name] = model
+
+    def regenerateModelDict(self):
+        """
+        Regenerates self.by_model_dict which has each model name as the
+        key and the list of categories belonging to that model
+        along with the enabled mapping
+        """
+        self.by_model_dict = defaultdict(list)
+        for category in self.master_category_dict:
+            for (model, enabled) in self.master_category_dict[category]:
+                self.by_model_dict[model].append(category)
+                self.model_enabled_dict[model] = enabled
+
+    def regenerateMasterDict(self):
+        """
+        regenerates self.master_category_dict from
+        self.by_model_dict and self.model_enabled_dict
+        """
+        self.master_category_dict = defaultdict(list)
+        for model in self.by_model_dict:
+            for category in self.by_model_dict[model]:
+                self.master_category_dict[category].append\
+                    ((model, self.model_enabled_dict[model]))
+
+    def modelToCategory(self):
+        """
+        Getter for the model->category dict
+        """
+        return self.by_model_dict
+
+    def modelDict(self):
+        """
+        Getter for the model list
+        """
+        return self.models
+
+    def categoryDict(self):
+        """
+        Getter for the category dict
+        """
+        return self.master_category_dict
+
+    def categoryList(self):
+        """
+        Getter for the category list
+        """
+        return self.category_list
+
+
+
+class CategoryManager(QtWidgets.QDialog, Ui_CategoryManagerUI):
+    def __init__(self, parent=None, manager=None):
+        super(CategoryManager, self).__init__(parent)
+        self.setupUi(self)
+
+        self.communicator = manager.communicator()
+
+        self.setWindowTitle("Category Manager")
+
+        self.initializeGlobals()
+
+        self.initializeModels()
+
+        self.initializeSignals()
+
+    def initializeGlobals(self):
+        """
+        Initialize global variables used in this class
+        """
+        # Default checked state
+        self.chkEnable.setCheckState(QtCore.Qt.Checked)
+
+        # Modify is disabled by default
+        self.cmdModify.setEnabled(False)
+
+        # Data for chosen model
+        self.model_data = None
+
+        # Categories object
+        self.categories = Categories()
+
+    def initializeModels(self):
+        """
+        Set up models and views
+        """
+        # Set the main models
+        self._category_model = ToolTippedItemModel()
+        self.lstCategory.setModel(self._category_model)
+        # Proxy model for showing a subset of model content
+        self.model_proxy = QtCore.QSortFilterProxyModel(self)
+        self.model_proxy.setSourceModel(self._category_model)
+        self.lstCategory.setModel(self.model_proxy)
+
+        self.initializeModelList()
+
+        self.setTableProperties(self.lstCategory)
+
+        self.lstCategory.setAlternatingRowColors(True)
+        # self.lstCategory.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
+        # self.lstCategory.setAttribute(QtCore.Qt.WA_MacShowFocusRect, False)
+
+    def initializeModelList(self):
+        """
+        Model category combo setup
+        """
+        self._category_model.clear()
+        for ind, model in enumerate(self.categories.modelDict()):
+            item = QtGui.QStandardItem(model)
+            empty_item = QtGui.QStandardItem()
+            empty_item.setEditable(False)
+            # Add a checkbox to it
+            item.setCheckable(True)
+            item.setCheckState(QtCore.Qt.Checked)
+            item.setEditable(False)
+            current_category = self.categories.modelToCategory()[model]
+            self._category_model.appendRow([item, empty_item])
+            self._category_model.item(ind, 1).setText(', '.join(i for i in current_category))
+
+    def initializeSignals(self):
+        """
+        :return:
+        """
+        self.cmdOK.clicked.connect(self.onClose)
+        self.cmdModify.clicked.connect(self.onModify)
+        self.cmdReset.clicked.connect(self.onReset)
+
+        self.chkEnable.toggled.connect(self.onEnableAll)
+
+        # every change in txtSearch
+        self.txtSearch.textChanged.connect(self.onSearch)
+
+        # Signals from the list
+        selectionModel = self.lstCategory.selectionModel()
+        selectionModel.selectionChanged.connect(self.onListSelection)
+
+
+    def onClose(self):
+        """
+        Save the category file before exiting
+        """
+        self.categories.saveCategories()
+        # Ask the fitting widget to reload the comboboxes
+        self.communicator.updateModelCategoriesSignal.emit()
+
+        self.close()
+
+    def selectedModels(self):
+        """
+        Returns a list of selected models
+        """
+        selected_models = []
+        selectionModel = self.lstCategory.selectionModel()
+        selectedRows = selectionModel.selectedRows()
+        for row in selectedRows:
+            model_index = self.model_proxy.mapToSource(row)
+            current_text = self._category_model.itemFromIndex(model_index).text()
+            selected_models.append(self.categories.modelDict()[current_text])
+        return selected_models
+
+    def onListSelection(self):
+        """
+        Respond to row selection and update GUI
+        """
+        selected_items = self.selectedModels()
+        self.cmdModify.setEnabled(len(selected_items) == 1)
+
+    def onReset(self):
+        """
+        Reload the saved categories
+        """
+        self.initializeGlobals()
+        # Reload the Categories object
+        self.categories = Categories()
+        # Reload the model
+        self.initializeModelList()
+        self.setTableProperties(self.lstCategory)
+        self.lstCategory.setAlternatingRowColors(True)
+
+    def onEnableAll(self, isChecked):
+        """
+        Respond to the Enable/Disable All checkbox
+        """
+        select = QtCore.Qt.Checked if isChecked else QtCore.Qt.Unchecked
+        for row in range(self._category_model.rowCount()):
+            self._category_model.item(row).setCheckState(select)
+
+    def onSearch(self):
+        """
+        Respond to text entered in search field
+        """
+        if self.txtSearch.isModified():
+            input_to_check = str(self.txtSearch.text())
+
+        # redefine the proxy model
+        self.model_proxy.setFilterRegExp(QtCore.QRegExp(input_to_check,
+                         QtCore.Qt.CaseInsensitive, QtCore.QRegExp.FixedString))
+
+    def onModify(self):
+        """
+        Show the Change Category dialog - modal
+        """
+        # Selected category:
+        selected_models = self.selectedModels()
+        if len(selected_models) > 1:
+            # Somehow we got more than one model - complain!
+            raise AttributeError("Please select only one model.")
+        change_dialog = ChangeCategory(parent=self, categories=self.categories, model=selected_models[0])
+
+        if change_dialog.exec_() != QtWidgets.QDialog.Accepted:
+            return
+        # Reload the model
+        self.initializeModelList()
+        self.setTableProperties(self.lstCategory)
+        self.lstCategory.setAlternatingRowColors(True)
+
+    def setTableProperties(self, table):
+        """
+        Setting table properties
+        """
+        # Table properties
+        table.verticalHeader().setVisible(False)
+        table.setAlternatingRowColors(True)
+        #table.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
+        table.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+        table.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+        table.resizeColumnsToContents()
+
+        # Header
+        header = table.horizontalHeader()
+        header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
+        header.ResizeMode(QtWidgets.QHeaderView.Interactive)
+
+
+        self._category_model.setHeaderData(0, QtCore.Qt.Horizontal, "Model")
+        self._category_model.setHeaderData(1, QtCore.Qt.Horizontal, "Category")
+
+        self._category_model.header_tooltips = ['Select model',
+                                                'Change or create new category']
+
+class ChangeCategory(QtWidgets.QDialog, Ui_ChangeCategoryUI):
+    """
+    Dialog for adding/removing categories for a single model
+    """
+    def __init__(self, parent=None, categories=None, model=None):
+        super(ChangeCategory, self).__init__(parent)
+        self.setupUi(self)
+
+        self.model = model
+        self.parent = parent
+        self.categories = categories
+
+        self.initializeElements()
+
+        self.initializeList()
+
+        self.initializeSignals()
+
+    def initializeElements(self):
+        """
+        Initialize local GUI elements with information from the Categories object
+        """
+        self.cbCategories.addItems(self.categories.categoryList())
+        self.setWindowTitle("Change Category for: "+ self.model.name)
+        self.lblTitle.setText("Current categories for " + self.model.name)
+        self.rbExisting.setChecked(True)
+        self.onAddChoice()
+
+    def initializeList(self):
+        """
+        Initialize the category list for the given model
+        """
+        current_categories = self.categories.modelToCategory()[self.model.name]
+        for cat in current_categories:
+            self.lstCategories.addItem(cat)
+
+    def initializeSignals(self):
+        """
+        Initialize signals for UI elements
+        """
+        self.cmdAdd.clicked.connect(self.onAdd)
+        self.cmdRemove.clicked.connect(self.onRemove)
+        self.cmdOK.clicked.connect(self.onOK)
+        self.cmdCancel.clicked.connect(self.close)
+
+        # Signals from the list
+        self.lstCategories.itemSelectionChanged.connect(self.onListSelection)
+
+        # Signals from the radio buttons
+        self.rbExisting.toggled.connect(self.onAddChoice)
+
+    def onAddChoice(self):
+        """
+        Respond to the type selection for new category
+        """
+        isNew = self.rbNew.isChecked()
+        self.cbCategories.setEnabled(not isNew)
+        self.txtNewCategory.setEnabled(isNew)
+
+    def onListSelection(self):
+        """
+        Respond to selection in the category list view
+        """
+        selected_items = self.selectedModels()
+        self.cmdRemove.setEnabled(len(selected_items) > 0)
+
+    def selectedModels(self):
+        """
+        Returns a list of selected models
+        """
+        selected_categories = []
+        selectedRows = self.lstCategories.selectedItems()
+        selected_categories = [str(row.text()) for row in selectedRows]
+
+        return selected_categories
+
+    def onAdd(self):
+        """
+        Add the chosen category to the list
+        """
+        if self.rbExisting.isChecked():
+            new_category = self.cbCategories.currentText()
+        else:
+            new_category = self.txtNewCategory.text()
+        # Display the current value as txt
+        if new_category:
+            self.lstCategories.addItem(new_category)
+
+    def onRemove(self):
+        """
+        Remove selected categories in the list
+        """
+        selectedRows = self.lstCategories.selectedItems()
+        if not selectedRows:
+            return
+        for row in selectedRows:
+            self.lstCategories.takeItem(self.lstCategories.row(row))
+
+    def onOK(self):
+        """
+        Accept the new categories for the model
+        """
+        # Read in the categories
+        self.categories.modelToCategory()[self.model.name] = self.listCategories()
+        self.accept()
+
+    def listCategories(self):
+        """
+        Returns the list of categories from the QListWidget
+        """
+        return [str(self.lstCategories.item(i).text()) for i in range(self.lstCategories.count())]
Index: src/sas/qtgui/MainWindow/GuiManager.py
===================================================================
--- src/sas/qtgui/MainWindow/GuiManager.py	(revision 8e2cd7908505a021dacf288aaa6c69c2d7d505e5)
+++ src/sas/qtgui/MainWindow/GuiManager.py	(revision 060413cb937895c088815c31b92fc9252f723562)
@@ -27,4 +27,5 @@
 from sas.qtgui.MainWindow.AboutBox import AboutBox
 from sas.qtgui.MainWindow.WelcomePanel import WelcomePanel
+from sas.qtgui.MainWindow.CategoryManager import CategoryManager
 
 from sas.qtgui.MainWindow.DataManager import DataManager
@@ -134,4 +135,5 @@
         self.ackWidget = Acknowledgements()
         self.aboutWidget = AboutBox()
+        self.categoryManagerWidget = CategoryManager(self._parent, manager=self)
         self.welcomePanel = WelcomePanel()
         self.grid_window = None
@@ -419,5 +421,5 @@
         self._workspace.actionHide_Toolbar.triggered.connect(self.actionHide_Toolbar)
         self._workspace.actionStartup_Settings.triggered.connect(self.actionStartup_Settings)
-        self._workspace.actionCategry_Manager.triggered.connect(self.actionCategry_Manager)
+        self._workspace.actionCategory_Manager.triggered.connect(self.actionCategory_Manager)
         # Tools
         self._workspace.actionData_Operation.triggered.connect(self.actionData_Operation)
@@ -611,9 +613,8 @@
         pass
 
-    def actionCategry_Manager(self):
-        """
-        """
-        print("actionCategry_Manager TRIGGERED")
-        pass
+    def actionCategory_Manager(self):
+        """
+        """
+        self.categoryManagerWidget.show()
 
     #============ TOOLS =================
Index: src/sas/qtgui/MainWindow/MainWindow.py
===================================================================
--- src/sas/qtgui/MainWindow/MainWindow.py	(revision e4335ae394f216c131b40e0ebbd740e37d9c6aa7)
+++ src/sas/qtgui/MainWindow/MainWindow.py	(revision 3d18691df01d447d24aab707b6772ce6ab95e36c)
@@ -27,6 +27,6 @@
         except Exception as ex:
             import logging
-            logging.error("Application failed with: " + str(ex))
-            print("Application failed with: ", ex)
+            logging.error("Application failed with: "+str(ex))
+            print("Application failed with: ", str(ex))
 
     def closeEvent(self, event):
Index: src/sas/qtgui/MainWindow/UI/CategoryManagerUI.ui
===================================================================
--- src/sas/qtgui/MainWindow/UI/CategoryManagerUI.ui	(revision 3d18691df01d447d24aab707b6772ce6ab95e36c)
+++ src/sas/qtgui/MainWindow/UI/CategoryManagerUI.ui	(revision 3d18691df01d447d24aab707b6772ce6ab95e36c)
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CategoryManagerUI</class>
+ <widget class="QDialog" name="CategoryManagerUI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>548</width>
+    <height>717</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Category Manager</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_2">
+   <item row="0" column="0">
+    <widget class="QGroupBox" name="CategoryManagerGroup">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="minimumSize">
+      <size>
+       <width>300</width>
+       <height>150</height>
+      </size>
+     </property>
+     <property name="title">
+      <string>Category Manager</string>
+     </property>
+     <property name="checkable">
+      <bool>false</bool>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <item>
+         <widget class="QCheckBox" name="chkEnable">
+          <property name="text">
+           <string>Enable/Disable all</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer_2">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_2">
+          <item>
+           <widget class="QLabel" name="label">
+            <property name="text">
+             <string>Search</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QLineEdit" name="txtSearch">
+            <property name="text">
+             <string/>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+      <item row="1" column="0">
+       <widget class="QTableView" name="lstCategory">
+        <property name="enabled">
+         <bool>true</bool>
+        </property>
+        <property name="editTriggers">
+         <set>QAbstractItemView::AllEditTriggers</set>
+        </property>
+        <property name="alternatingRowColors">
+         <bool>true</bool>
+        </property>
+        <property name="selectionMode">
+         <enum>QAbstractItemView::ExtendedSelection</enum>
+        </property>
+        <property name="selectionBehavior">
+         <enum>QAbstractItemView::SelectRows</enum>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>78</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cmdModify">
+       <property name="toolTip">
+        <string>Add/Remove categories for the selected model.</string>
+       </property>
+       <property name="text">
+        <string>Modify</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cmdReset">
+       <property name="toolTip">
+        <string>Reset categories for selected models.</string>
+       </property>
+       <property name="text">
+        <string>Reset</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cmdOK">
+       <property name="text">
+        <string>OK</string>
+       </property>
+       <property name="autoDefault">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cmdHelp">
+       <property name="text">
+        <string>Help</string>
+       </property>
+       <property name="autoDefault">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: src/sas/qtgui/MainWindow/UI/ChangeCategoryUI.ui
===================================================================
--- src/sas/qtgui/MainWindow/UI/ChangeCategoryUI.ui	(revision 3d18691df01d447d24aab707b6772ce6ab95e36c)
+++ src/sas/qtgui/MainWindow/UI/ChangeCategoryUI.ui	(revision 3d18691df01d447d24aab707b6772ce6ab95e36c)
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ChangeCategoryUI</class>
+ <widget class="QDialog" name="ChangeCategoryUI">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>357</width>
+    <height>485</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Change Category:</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_2">
+   <item row="0" column="0">
+    <widget class="QLabel" name="lblTitle">
+     <property name="text">
+      <string>Current categories for </string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QListWidget" name="lstCategories">
+     <property name="selectionMode">
+      <enum>QAbstractItemView::MultiSelection</enum>
+     </property>
+     <property name="selectionBehavior">
+      <enum>QAbstractItemView::SelectRows</enum>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QGroupBox" name="groupBox">
+     <property name="title">
+      <string>Add Category</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="QRadioButton" name="rbExisting">
+        <property name="text">
+         <string>Choose existing</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1" colspan="2">
+       <widget class="QLineEdit" name="txtNewCategory"/>
+      </item>
+      <item row="0" column="1" colspan="2">
+       <widget class="QComboBox" name="cbCategories"/>
+      </item>
+      <item row="1" column="0">
+       <widget class="QRadioButton" name="rbNew">
+        <property name="text">
+         <string>Create new</string>
+        </property>
+       </widget>
+      </item>
+      <item row="2" column="0" colspan="2">
+       <spacer name="horizontalSpacer_2">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>208</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item row="2" column="2">
+       <widget class="QPushButton" name="cmdAdd">
+        <property name="text">
+         <string>Add</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+     <zorder>cbCategories</zorder>
+     <zorder>txtNewCategory</zorder>
+     <zorder>cmdAdd</zorder>
+     <zorder>horizontalSpacer_2</zorder>
+     <zorder>rbNew</zorder>
+     <zorder>rbExisting</zorder>
+    </widget>
+   </item>
+   <item row="3" column="0">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QPushButton" name="cmdRemove">
+       <property name="text">
+        <string>Remove</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cmdOK">
+       <property name="text">
+        <string>OK</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="cmdCancel">
+       <property name="text">
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
===================================================================
--- src/sas/qtgui/MainWindow/UI/MainWindowUI.ui	(revision 2b39feac4c8784d490c4e328f647f2eadd682546)
+++ src/sas/qtgui/MainWindow/UI/MainWindowUI.ui	(revision 3d18691df01d447d24aab707b6772ce6ab95e36c)
@@ -75,5 +75,5 @@
     <addaction name="actionStartup_Settings"/>
     <addaction name="separator"/>
-    <addaction name="actionCategry_Manager"/>
+    <addaction name="actionCategory_Manager"/>
    </widget>
    <widget class="QMenu" name="menuTool">
@@ -324,5 +324,5 @@
    </property>
   </action>
-  <action name="actionCategry_Manager">
+  <action name="actionCategory_Manager">
    <property name="text">
     <string>Category Manager</string>
Index: src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 97df8a93fcfe23a3b54f1f4b5365775da012c4a2)
+++ src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 060413cb937895c088815c31b92fc9252f723562)
@@ -373,5 +373,6 @@
         self.cbCategory.addItem(CATEGORY_DEFAULT)
         self.cbCategory.addItems(category_list)
-        self.cbCategory.addItem(CATEGORY_STRUCTURE)
+        if CATEGORY_STRUCTURE not in category_list:
+            self.cbCategory.addItem(CATEGORY_STRUCTURE)
         self.cbCategory.setCurrentIndex(0)
 
@@ -523,4 +524,7 @@
         self.communicate.copyFitParamsSignal.connect(self.onParameterCopy)
         self.communicate.pasteFitParamsSignal.connect(self.onParameterPaste)
+
+        # Communicator signal
+        self.communicate.updateModelCategoriesSignal.connect(self.onCategoriesChanged)
 
     def modelName(self):
@@ -1931,5 +1935,11 @@
             # custom kernel load requires full path
             name = os.path.join(ModelUtilities.find_plugins_dir(), model_name+".py")
-        kernel_module = generate.load_kernel_module(name)
+        try:
+            kernel_module = generate.load_kernel_module(name)
+        except ModuleNotFoundError:
+            # maybe it's a recategorised custom model?
+            name = os.path.join(ModelUtilities.find_plugins_dir(), model_name+".py")
+            # If this rises, it's a valid problem.
+            kernel_module = generate.load_kernel_module(name)
 
         if hasattr(kernel_module, 'parameters'):
@@ -2248,4 +2258,32 @@
         self.createNewIndex(residuals_plot)
 
+    def onCategoriesChanged(self):
+            """
+            Reload the category/model comboboxes
+            """
+            # Store the current combo indices
+            current_cat = self.cbCategory.currentText()
+            current_model = self.cbModel.currentText()
+
+            # reread the category file and repopulate the combo
+            self.cbCategory.blockSignals(True)
+            self.cbCategory.clear()
+            self.readCategoryInfo()
+            self.initializeCategoryCombo()
+
+            # Scroll back to the original index in Categories
+            new_index = self.cbCategory.findText(current_cat)
+            if new_index != -1:
+                self.cbCategory.setCurrentIndex(new_index)
+            self.cbCategory.blockSignals(False)
+            # ...and in the Models
+            self.cbModel.blockSignals(True)
+            new_index = self.cbModel.findText(current_model)
+            if new_index != -1:
+                self.cbModel.setCurrentIndex(new_index)
+            self.cbModel.blockSignals(False)
+
+            return
+
     def calcException(self, etype, value, tb):
         """
Index: src/sas/qtgui/Utilities/GuiUtils.py
===================================================================
--- src/sas/qtgui/Utilities/GuiUtils.py	(revision 8e2cd7908505a021dacf288aaa6c69c2d7d505e5)
+++ src/sas/qtgui/Utilities/GuiUtils.py	(revision 3d18691df01d447d24aab707b6772ce6ab95e36c)
@@ -260,4 +260,6 @@
     # Fitting parameter paste from clipboard
     pasteFitParamsSignal = QtCore.pyqtSignal()
+    # Notify about new categories/models from category manager
+    updateModelCategoriesSignal = QtCore.pyqtSignal()
 
 def updateModelItemWithPlot(item, update_data, name=""):
Index: src/sas/qtgui/Utilities/PluginDefinition.py
===================================================================
--- src/sas/qtgui/Utilities/PluginDefinition.py	(revision c5e0d844708c4a7f2071bbba6132d4b2a67ce73a)
+++ src/sas/qtgui/Utilities/PluginDefinition.py	(revision 060413cb937895c088815c31b92fc9252f723562)
@@ -30,9 +30,12 @@
         self.pd_parameter_dict = {}
 
+        # Initialize widgets
+        self.addWidgets()
+
+        # Wait for all widgets to finish processing
+        QtWidgets.QApplication.processEvents()
+
         # Initialize signals
         self.addSignals()
-
-        # Initialize widgets
-        self.addWidgets()
 
     def addTooltip(self):
@@ -160,7 +163,9 @@
         # keep in mind that this is called every time the text changes.
         # mind the performance!
-        self.addTooltip()
-        self.model['text'] = self.txtFunction.toPlainText().lstrip().rstrip()
-        self.modelModified.emit()
+        #self.addTooltip()
+        new_text = self.txtFunction.toPlainText().lstrip().rstrip()
+        if new_text != self.model['text']:
+            self.model['text'] = new_text
+            self.modelModified.emit()
 
     def onOverwrite(self):
