diff --git a/object_collection_manager/__init__.py b/object_collection_manager/__init__.py
index 72a279d1abed317840825539897e11fa636889a8..792f5d1c2e0414d665ca0ed6476433d7ce2bedcb 100644
--- a/object_collection_manager/__init__.py
+++ b/object_collection_manager/__init__.py
@@ -22,7 +22,7 @@ bl_info = {
     "name": "Collection Manager",
     "description": "Manage collections and their objects",
     "author": "Ryan Inch",
-    "version": (2, 14, 3),
+    "version": (2, 15, 0),
     "blender": (2, 80, 0),
     "location": "View3D - Object Mode (Shortcut - M)",
     "warning": '',  # used for warning icon and text in addons panel
diff --git a/object_collection_manager/internals.py b/object_collection_manager/internals.py
index 163e98048f7b3792a2d6f806d8d2985326ab8e5b..34e66737c8ed85c2b7d7af5bcb0635b8e59345fb 100644
--- a/object_collection_manager/internals.py
+++ b/object_collection_manager/internals.py
@@ -39,6 +39,7 @@ move_active = None
 layer_collections = {}
 collection_tree = []
 collection_state = {}
+qcd_collection_state = {}
 expanded = set()
 row_index = 0
 max_lvl = 0
@@ -60,6 +61,8 @@ rto_history = {
     "indirect_all": {},
 }
 
+qcd_history = {}
+
 expand_history = {
     "target": "",
     "history": [],
@@ -131,6 +134,13 @@ class QCDSlots():
 
         raise
 
+    def object_in_slots(self, obj):
+        for collection in obj.users_collection:
+            if self.contains(name=collection.name):
+                return True
+
+        return False
+
     def get_data_for_blend(self):
         return f"{self._slots.__repr__()}\n{self.overrides.__repr__()}"
 
@@ -584,8 +594,9 @@ def get_modifiers(event):
     return set(modifiers)
 
 
-def generate_state():
+def generate_state(*, qcd=False):
     global layer_collections
+    global qcd_slots
 
     state = {
         "name": [],
@@ -608,6 +619,9 @@ def generate_state():
         state["holdout"].append(laycol["ptr"].holdout)
         state["indirect"].append(laycol["ptr"].indirect_only)
 
+    if qcd:
+        state["qcd"] = dict(qcd_slots)
+
     return state
 
 
diff --git a/object_collection_manager/operator_utils.py b/object_collection_manager/operator_utils.py
index 20c7dee7a9863ec76c2daf280fcf8a843c9c993b..2544b76ba4a8ef584b5eba10ed31f01bb8c3280e 100644
--- a/object_collection_manager/operator_utils.py
+++ b/object_collection_manager/operator_utils.py
@@ -31,6 +31,29 @@ from .internals import (
     get_move_selection,
 )
 
+mode_converter = {
+    'EDIT_MESH': 'EDIT',
+    'EDIT_CURVE': 'EDIT',
+    'EDIT_SURFACE': 'EDIT',
+    'EDIT_TEXT': 'EDIT',
+    'EDIT_ARMATURE': 'EDIT',
+    'EDIT_METABALL': 'EDIT',
+    'EDIT_LATTICE': 'EDIT',
+    'POSE': 'POSE',
+    'SCULPT': 'SCULPT',
+    'PAINT_WEIGHT': 'WEIGHT_PAINT',
+    'PAINT_VERTEX': 'VERTEX_PAINT',
+    'PAINT_TEXTURE': 'TEXTURE_PAINT',
+    'PARTICLE': 'PARTICLE_EDIT',
+    'OBJECT': 'OBJECT',
+    'PAINT_GPENCIL': 'PAINT_GPENCIL',
+    'EDIT_GPENCIL': 'EDIT_GPENCIL',
+    'SCULPT_GPENCIL': 'SCULPT_GPENCIL',
+    'WEIGHT_GPENCIL': 'WEIGHT_GPENCIL',
+    'VERTEX_GPENCIL': 'VERTEX_GPENCIL',
+    }
+
+
 rto_path = {
     "exclude": "exclude",
     "select": "collection.hide_select",
@@ -469,7 +492,7 @@ def remove_collection(laycol, collection, context):
             cm.cm_list_index = laycol["row_index"]
 
 
-def select_collection_objects(is_master_collection, collection_name, replace, nested):
+def select_collection_objects(is_master_collection, collection_name, replace, nested, selection_state=None):
     if is_master_collection:
         target_collection = bpy.context.view_layer.layer_collection.collection
 
@@ -480,7 +503,8 @@ def select_collection_objects(is_master_collection, collection_name, replace, ne
     if replace:
         bpy.ops.object.select_all(action='DESELECT')
 
-    selection_state = get_move_selection().isdisjoint(target_collection.objects)
+    if selection_state == None:
+        selection_state = get_move_selection().isdisjoint(target_collection.objects)
 
     def select_objects(collection):
             for obj in collection.objects:
@@ -493,3 +517,21 @@ def select_collection_objects(is_master_collection, collection_name, replace, ne
 
     if nested:
         apply_to_children(target_collection, select_objects)
+
+def set_exclude_state(target_layer_collection, state):
+    # get current child exclusion state
+    child_exclusion = []
+
+    def get_child_exclusion(layer_collection):
+        child_exclusion.append([layer_collection, layer_collection.exclude])
+
+    apply_to_children(target_layer_collection, get_child_exclusion)
+
+
+    # set exclusion
+    target_layer_collection.exclude = state
+
+
+    # set correct state for all children
+    for laycol in child_exclusion:
+        laycol[0].exclude = laycol[1]
diff --git a/object_collection_manager/operators.py b/object_collection_manager/operators.py
index 1e265e52b673a96003d3145f65efbf788ada0d85..b18fc44a8d1e41d93d6f37c59d2dd51c9e78e9e8 100644
--- a/object_collection_manager/operators.py
+++ b/object_collection_manager/operators.py
@@ -66,6 +66,7 @@ from .operator_utils import (
     link_child_collections_to_parent,
     remove_collection,
     select_collection_objects,
+    set_exclude_state,
 )
 
 class SetActiveCollection(Operator):
@@ -424,23 +425,7 @@ class CMExcludeOperator(Operator):
             # reset exclude history
             del rto_history["exclude"][view_layer]
 
-
-            # get current child exclusion state
-            child_exclusion = []
-
-            def get_child_exclusion(layer_collection):
-                child_exclusion.append([layer_collection, layer_collection.exclude])
-
-            apply_to_children(laycol_ptr, get_child_exclusion)
-
-
-            # toggle exclusion of collection
-            laycol_ptr.exclude = not laycol_ptr.exclude
-
-
-            # set correct state for all children
-            for laycol in child_exclusion:
-                laycol[0].exclude = laycol[1]
+            set_exclude_state(laycol_ptr, not laycol_ptr.exclude)
 
             cls.isolated = False
 
diff --git a/object_collection_manager/qcd_init.py b/object_collection_manager/qcd_init.py
index 358d76171ec403c73c5a031a4a65ad0a84f85622..035d62a0b6f90ed8b2660d99429d6a4ac4ab138f 100644
--- a/object_collection_manager/qcd_init.py
+++ b/object_collection_manager/qcd_init.py
@@ -16,10 +16,18 @@ addon_qcd_view_edit_mode_hotkey_keymaps = []
 
 qcd_classes = (
     qcd_move_widget.QCDMoveWidget,
+    qcd_operators.EnableAllQCDSlotsMeta,
+    qcd_operators.EnableAllQCDSlots,
+    qcd_operators.EnableAllQCDSlotsIsolated,
+    qcd_operators.DisableAllNonQCDSlots,
+    qcd_operators.DisableAllCollections,
+    qcd_operators.SelectAllQCDObjects,
+    qcd_operators.DiscardQCDHistory,
     qcd_operators.MoveToQCDSlot,
     qcd_operators.ViewQCDSlot,
     qcd_operators.ViewMoveQCDSlot,
     qcd_operators.RenumerateQCDSlots,
+    ui.EnableAllQCDSlotsMenu,
     )
 
 
@@ -41,6 +49,13 @@ def load_internal_data(dummy):
     internals.qcd_slots.load_blend_data(data)
 
 
+@persistent
+def load_pre_handler(dummy):
+    internals.qcd_collection_state.clear()
+    for key in list(internals.qcd_history.keys()):
+        del internals.qcd_history[key]
+
+
 def register_qcd():
     for cls in qcd_classes:
         bpy.utils.register_class(cls)
@@ -60,6 +75,7 @@ def register_qcd():
 
     bpy.app.handlers.save_pre.append(save_internal_data)
     bpy.app.handlers.load_post.append(load_internal_data)
+    bpy.app.handlers.load_pre.append(load_pre_handler)
 
     prefs = bpy.context.preferences.addons[__package__].preferences
 
@@ -114,6 +130,27 @@ def register_qcd_view_hotkeys():
                 kmi.properties.toggle = True
                 addon_qcd_view_hotkey_keymaps.append((km, kmi))
 
+                km = wm.keyconfigs.addon.keymaps.new(name=mode)
+                kmi = km.keymap_items.new('view3d.enable_all_qcd_slots', 'PLUS', 'PRESS', shift=True)
+                addon_qcd_view_hotkey_keymaps.append((km, kmi))
+
+                km = wm.keyconfigs.addon.keymaps.new(name=mode)
+                kmi = km.keymap_items.new('view3d.enable_all_qcd_slots_isolated', 'PLUS', 'PRESS', shift=True, alt=True)
+                addon_qcd_view_hotkey_keymaps.append((km, kmi))
+
+                km = wm.keyconfigs.addon.keymaps.new(name=mode)
+                kmi = km.keymap_items.new('view3d.disable_all_non_qcd_slots', 'PLUS', 'PRESS', shift=True, ctrl=True)
+                addon_qcd_view_hotkey_keymaps.append((km, kmi))
+
+                km = wm.keyconfigs.addon.keymaps.new(name=mode)
+                kmi = km.keymap_items.new('view3d.disable_all_collections', 'EQUAL', 'PRESS', alt=True, ctrl=True)
+                addon_qcd_view_hotkey_keymaps.append((km, kmi))
+
+                if mode == 'Object Mode':
+                    km = wm.keyconfigs.addon.keymaps.new(name=mode)
+                    kmi = km.keymap_items.new('view3d.select_all_qcd_objects', 'EQUAL', 'PRESS', alt=True)
+                    addon_qcd_view_hotkey_keymaps.append((km, kmi))
+
 
 def register_qcd_view_edit_mode_hotkeys():
     wm = bpy.context.window_manager
@@ -156,6 +193,22 @@ def register_qcd_view_edit_mode_hotkeys():
                 kmi.properties.toggle = True
                 addon_qcd_view_edit_mode_hotkey_keymaps.append((km, kmi))
 
+                km = wm.keyconfigs.addon.keymaps.new(name=mode)
+                kmi = km.keymap_items.new('view3d.enable_all_qcd_slots', 'PLUS', 'PRESS', shift=True)
+                addon_qcd_view_edit_mode_hotkey_keymaps.append((km, kmi))
+
+                km = wm.keyconfigs.addon.keymaps.new(name=mode)
+                kmi = km.keymap_items.new('view3d.enable_all_qcd_slots_isolated', 'PLUS', 'PRESS', shift=True, alt=True)
+                addon_qcd_view_edit_mode_hotkey_keymaps.append((km, kmi))
+
+                km = wm.keyconfigs.addon.keymaps.new(name=mode)
+                kmi = km.keymap_items.new('view3d.disable_all_non_qcd_slots', 'PLUS', 'PRESS', shift=True, ctrl=True)
+                addon_qcd_view_edit_mode_hotkey_keymaps.append((km, kmi))
+
+                km = wm.keyconfigs.addon.keymaps.new(name=mode)
+                kmi = km.keymap_items.new('view3d.disable_all_collections', 'EQUAL', 'PRESS', alt=True, ctrl=True)
+                addon_qcd_view_edit_mode_hotkey_keymaps.append((km, kmi))
+
 
         km = wm.keyconfigs.addon.keymaps.new(name="Mesh")
         kmi = km.keymap_items.new('wm.call_menu', 'ACCENT_GRAVE', 'PRESS')
@@ -173,6 +226,7 @@ def unregister_qcd():
 
     bpy.app.handlers.save_pre.remove(save_internal_data)
     bpy.app.handlers.load_post.remove(load_internal_data)
+    bpy.app.handlers.load_pre.remove(load_pre_handler)
 
     for pcoll in ui.preview_collections.values():
         bpy.utils.previews.remove(pcoll)
diff --git a/object_collection_manager/qcd_operators.py b/object_collection_manager/qcd_operators.py
index 6b5bce4a93dada8522100ed922f1de0ed0d29064..f53fe6bc8ba571d23df4495896c8d449cbab4994 100644
--- a/object_collection_manager/qcd_operators.py
+++ b/object_collection_manager/qcd_operators.py
@@ -35,8 +35,12 @@ from . import internals
 from .internals import (
     layer_collections,
     rto_history,
+    qcd_history,
     qcd_slots,
+    qcd_collection_state,
+    update_collection_tree,
     update_property_group,
+    generate_state,
     get_modifiers,
     get_move_selection,
     get_move_active,
@@ -44,10 +48,443 @@ from .internals import (
 )
 
 from .operator_utils import (
+    mode_converter,
     apply_to_children,
     select_collection_objects,
+    set_exclude_state,
 )
 
+class LockedObjects():
+    def __init__(self):
+        self.objs = []
+        self.mode = ""
+
+def get_locked_objs(context):
+    # get objects not in object mode
+    locked = LockedObjects()
+    if context.mode == 'OBJECT':
+        return locked
+
+    if context.view_layer.objects.active:
+        active = context.view_layer.objects.active
+        locked.mode = mode_converter[context.mode]
+
+        for obj in context.view_layer.objects:
+            if obj.mode != 'OBJECT':
+                if obj.mode not in ['POSE', 'WEIGHT_PAINT'] or obj == active:
+                    if obj.mode == active.mode:
+                        locked.objs.append(obj)
+
+    return locked
+
+
+
+class QCDAllBase():
+    meta_op = False
+    meta_report = None
+
+    context = None
+    view_layer = ""
+    history = None
+    orig_active_collection = None
+    orig_active_object = None
+    locked = None
+
+    @classmethod
+    def init(cls, context):
+        cls.context = context
+        cls.orig_active_collection = context.view_layer.active_layer_collection
+        cls.view_layer = context.view_layer.name
+        cls.orig_active_object = context.view_layer.objects.active
+
+        if not cls.view_layer in qcd_history:
+            qcd_history[cls.view_layer] = []
+
+        cls.history = qcd_history[cls.view_layer]
+
+        cls.locked = get_locked_objs(context)
+
+    @classmethod
+    def apply_history(cls):
+        for x, item in enumerate(layer_collections.values()):
+            item["ptr"].exclude = cls.history[x]
+
+        # clear rto history
+        del qcd_history[cls.view_layer]
+
+        internals.qcd_collection_state.clear()
+        cls.history = None
+
+    @classmethod
+    def finalize(cls):
+        # restore active collection
+        cls.context.view_layer.active_layer_collection = cls.orig_active_collection
+
+        # restore active object if possible
+        if cls.orig_active_object:
+            if cls.orig_active_object.name in cls.context.view_layer.objects:
+                cls.context.view_layer.objects.active = cls.orig_active_object
+
+        # restore locked objects back to their original mode
+        # needed because of exclude child updates
+        if cls.context.view_layer.objects.active:
+            if cls.locked.objs:
+                bpy.ops.object.mode_set(mode=cls.locked.mode)
+
+    @classmethod
+    def clear(cls):
+
+        cls.context = None
+        cls.view_layer = ""
+        cls.history = None
+        cls.orig_active_collection = None
+        cls.orig_active_object = None
+        cls.locked = {}
+
+
+class EnableAllQCDSlotsMeta(Operator):
+    '''QCD All Meta Operator'''
+    bl_label = "Quick View Toggles"
+    bl_description = (
+        "  * LMB - Enable all slots/Restore.\n"
+        "  * Alt+LMB - Select all objects in QCD slots.\n"
+        "  * LMB+Hold - Menu"
+        )
+    bl_idname = "view3d.enable_all_qcd_slots_meta"
+
+    def invoke(self, context, event):
+        global qcd_slots
+        global layer_collections
+        qab = QCDAllBase
+
+        modifiers = get_modifiers(event)
+
+        qab.meta_op = True
+
+        if modifiers == {"alt"}:
+            bpy.ops.view3d.select_all_qcd_objects()
+
+        else:
+            qab.init(context)
+
+            if not qab.history:
+                bpy.ops.view3d.enable_all_qcd_slots()
+
+            else:
+                qab.apply_history()
+                qab.finalize()
+
+
+        if qab.meta_report:
+            self.report({"INFO"}, qab.meta_report)
+            qab.meta_report = None
+
+        qab.meta_op = False
+
+
+        return {'FINISHED'}
+
+
+class EnableAllQCDSlots(Operator):
+    '''Toggles between the current state and all enabled'''
+    bl_label = "Enable All QCD Slots"
+    bl_idname = "view3d.enable_all_qcd_slots"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    def execute(self, context):
+        global qcd_slots
+        global layer_collections
+        qab = QCDAllBase
+
+        # validate qcd slots
+        if not dict(qcd_slots):
+            if qab.meta_op:
+                qab.meta_report = "No QCD slots."
+            else:
+                self.report({"INFO"}, "No QCD slots.")
+
+            return {'CANCELLED'}
+
+        qab.init(context)
+
+        if not qab.history:
+            keep_history = False
+
+            for laycol in layer_collections.values():
+                is_qcd_slot = qcd_slots.contains(name=laycol["name"])
+
+                qab.history.append(laycol["ptr"].exclude)
+
+                if is_qcd_slot and laycol["ptr"].exclude:
+                    keep_history = True
+                    set_exclude_state(laycol["ptr"], False)
+
+
+            if not keep_history:
+                # clear rto history
+                del qcd_history[qab.view_layer]
+                qab.clear()
+
+                if qab.meta_op:
+                    qab.meta_report = "All QCD slots are already enabled."
+
+                else:
+                    self.report({"INFO"}, "All QCD slots are already enabled.")
+
+                return {'CANCELLED'}
+
+            internals.qcd_collection_state.clear()
+            internals.qcd_collection_state.update(internals.generate_state(qcd=True))
+
+        else:
+            qab.apply_history()
+
+        qab.finalize()
+
+        return {'FINISHED'}
+
+class EnableAllQCDSlotsIsolated(Operator):
+    '''Toggles between the current state and all enabled (non-QCD collections disabled)'''
+    bl_label = "Enable All QCD Slots Isolated"
+    bl_idname = "view3d.enable_all_qcd_slots_isolated"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    def execute(self, context):
+        global qcd_slots
+        global layer_collections
+        qab = QCDAllBase
+
+        # validate qcd slots
+        if not dict(qcd_slots):
+            self.report({"INFO"}, "No QCD slots.")
+
+            return {'CANCELLED'}
+
+        qab.init(context)
+
+        if qab.locked.objs and not qcd_slots.object_in_slots(qab.orig_active_object):
+            # clear rto history
+            del qcd_history[qab.view_layer]
+            qab.clear()
+
+            self.report({"WARNING"}, "Cannot execute.  The active object would be lost.")
+
+            return {'CANCELLED'}
+
+        if not qab.history:
+            keep_history = False
+
+            for laycol in layer_collections.values():
+                is_qcd_slot = qcd_slots.contains(name=laycol["name"])
+
+                qab.history.append(laycol["ptr"].exclude)
+
+                if is_qcd_slot and laycol["ptr"].exclude:
+                    keep_history = True
+                    set_exclude_state(laycol["ptr"], False)
+
+                if not is_qcd_slot and not laycol["ptr"].exclude:
+                    keep_history = True
+                    set_exclude_state(laycol["ptr"], True)
+
+
+            if not keep_history:
+                # clear rto history
+                del qcd_history[qab.view_layer]
+                qab.clear()
+
+                self.report({"INFO"}, "All QCD slots are already enabled and isolated.")
+                return {'CANCELLED'}
+
+            internals.qcd_collection_state.clear()
+            internals.qcd_collection_state.update(internals.generate_state(qcd=True))
+
+        else:
+            qab.apply_history()
+
+        qab.finalize()
+
+        return {'FINISHED'}
+
+class DisableAllNonQCDSlots(Operator):
+    '''Toggles between the current state and all non-QCD collections disabled'''
+    bl_label = "Disable All Non QCD Slots"
+    bl_idname = "view3d.disable_all_non_qcd_slots"
+    bl_options = {'REGISTER', 'UNDO'}
+
+
+    def execute(self, context):
+        global qcd_slots
+        global layer_collections
+        qab = QCDAllBase
+
+        # validate qcd slots
+        if not dict(qcd_slots):
+            self.report({"INFO"}, "No QCD slots.")
+
+            return {'CANCELLED'}
+
+        qab.init(context)
+
+        if qab.locked.objs and not qcd_slots.object_in_slots(qab.orig_active_object):
+            # clear rto history
+            del qcd_history[qab.view_layer]
+            qab.clear()
+
+            self.report({"WARNING"}, "Cannot execute.  The active object would be lost.")
+
+            return {'CANCELLED'}
+
+        if not qab.history:
+            keep_history = False
+
+            for laycol in layer_collections.values():
+                is_qcd_slot = qcd_slots.contains(name=laycol["name"])
+
+                qab.history.append(laycol["ptr"].exclude)
+
+                if not is_qcd_slot and not laycol["ptr"].exclude:
+                    keep_history = True
+                    set_exclude_state(laycol["ptr"], True)
+
+            if not keep_history:
+                # clear rto history
+                del qcd_history[qab.view_layer]
+                qab.clear()
+
+                self.report({"INFO"}, "All non QCD slots are already disabled.")
+                return {'CANCELLED'}
+
+            internals.qcd_collection_state.clear()
+            internals.qcd_collection_state.update(internals.generate_state(qcd=True))
+
+        else:
+            qab.apply_history()
+
+        qab.finalize()
+
+        return {'FINISHED'}
+
+
+class DisableAllCollections(Operator):
+    '''Toggles between the current state and all collections disabled'''
+    bl_label = "Disable All collections"
+    bl_idname = "view3d.disable_all_collections"
+    bl_options = {'REGISTER', 'UNDO'}
+
+
+    def execute(self, context):
+        global qcd_slots
+        global layer_collections
+        qab = QCDAllBase
+
+        qab.init(context)
+
+        if qab.locked.objs:
+            # clear rto history
+            del qcd_history[qab.view_layer]
+            qab.clear()
+
+            self.report({"WARNING"}, "Cannot execute.  The active object would be lost.")
+
+            return {'CANCELLED'}
+
+        if not qab.history:
+            for laycol in layer_collections.values():
+
+                qab.history.append(laycol["ptr"].exclude)
+
+            if all(qab.history): # no collections are enabled
+                # clear rto history
+                del qcd_history[qab.view_layer]
+                qab.clear()
+
+                self.report({"INFO"}, "All collections are already disabled.")
+                return {'CANCELLED'}
+
+            for laycol in layer_collections.values():
+                laycol["ptr"].exclude = True
+
+            internals.qcd_collection_state.clear()
+            internals.qcd_collection_state.update(internals.generate_state(qcd=True))
+
+        else:
+            qab.apply_history()
+
+        qab.finalize()
+
+        return {'FINISHED'}
+
+
+class SelectAllQCDObjects(Operator):
+    '''Select all objects in QCD slots'''
+    bl_label = "Select All QCD Objects"
+    bl_idname = "view3d.select_all_qcd_objects"
+    bl_options = {'REGISTER', 'UNDO'}
+
+
+    def execute(self, context):
+        global qcd_slots
+        global layer_collections
+        qab = QCDAllBase
+
+        if context.mode != 'OBJECT':
+            return {'CANCELLED'}
+
+        if not context.selectable_objects:
+            if qab.meta_op:
+                qab.meta_report = "No objects present to select."
+
+            else:
+                self.report({"INFO"}, "No objects present to select.")
+
+            return {'CANCELLED'}
+
+        orig_selected_objects = context.selected_objects
+
+        bpy.ops.object.select_all(action='DESELECT')
+
+        for slot, collection_name in qcd_slots:
+            select_collection_objects(
+                is_master_collection=False,
+                collection_name=collection_name,
+                replace=False,
+                nested=False,
+                selection_state=True
+                )
+
+        if context.selected_objects == orig_selected_objects:
+            for slot, collection_name in qcd_slots:
+                select_collection_objects(
+                    is_master_collection=False,
+                    collection_name=collection_name,
+                    replace=False,
+                    nested=False,
+                    selection_state=False
+                    )
+
+
+        return {'FINISHED'}
+
+
+class DiscardQCDHistory(Operator):
+    '''Discard QCD History'''
+    bl_label = "Discard History"
+    bl_idname = "view3d.discard_qcd_history"
+
+    def execute(self, context):
+        global qcd_slots
+        global layer_collections
+        qab = QCDAllBase
+
+        view_layer = context.view_layer.name
+
+        if view_layer in qcd_history:
+            del qcd_history[view_layer]
+            qab.clear()
+
+        return {'FINISHED'}
+
 
 class MoveToQCDSlot(Operator):
     '''Move object(s) to QCD slot'''
@@ -209,46 +646,25 @@ class ViewQCDSlot(Operator):
             return {'CANCELLED'}
 
 
-        # get objects not in object mode
-        locked_active_obj = context.view_layer.objects.active
-        locked_objs = []
-        locked_objs_mode = ""
-        for obj in context.view_layer.objects:
-            if obj.mode != 'OBJECT':
-                if obj.mode not in ['POSE', 'WEIGHT_PAINT'] or obj == locked_active_obj:
-                    locked_objs.append(obj)
-                    locked_objs_mode = obj.mode
+        orig_active_object = context.view_layer.objects.active
+        locked = get_locked_objs(context)
 
 
         if self.toggle:
             # check if slot can be toggled off.
             if not qcd_laycol.exclude:
-                for obj in qcd_laycol.collection.objects:
-                    if obj.mode != 'OBJECT':
-                        if obj.mode not in ['POSE', 'WEIGHT_PAINT'] or obj == locked_active_obj:
-                            return {'CANCELLED'}
-
-            # get current child exclusion state
-            child_exclusion = []
-
-            def get_child_exclusion(layer_collection):
-                child_exclusion.append([layer_collection, layer_collection.exclude])
-
-            apply_to_children(qcd_laycol, get_child_exclusion)
+                if not set(locked.objs).isdisjoint(qcd_laycol.collection.objects):
+                    return {'CANCELLED'}
 
             # toggle exclusion of qcd_laycol
-            qcd_laycol.exclude = not qcd_laycol.exclude
-
-            # set correct state for all children
-            for laycol in child_exclusion:
-                laycol[0].exclude = laycol[1]
+            set_exclude_state(qcd_laycol, not qcd_laycol.exclude)
 
         else:
             # exclude all collections
             for laycol in layer_collections.values():
                 if laycol["name"] != qcd_laycol.name:
                     # prevent exclusion if locked objects in this collection
-                    if set(locked_objs).isdisjoint(laycol["ptr"].collection.objects):
+                    if set(locked.objs).isdisjoint(laycol["ptr"].collection.objects):
                         laycol["ptr"].exclude = True
                     else:
                         laycol["ptr"].exclude = False
@@ -259,21 +675,22 @@ class ViewQCDSlot(Operator):
             # exclude all children
             def exclude_all_children(layer_collection):
                 # prevent exclusion if locked objects in this collection
-                if set(locked_objs).isdisjoint(layer_collection.collection.objects):
+                if set(locked.objs).isdisjoint(layer_collection.collection.objects):
                     layer_collection.exclude = True
                 else:
                     layer_collection.exclude = False
 
             apply_to_children(qcd_laycol, exclude_all_children)
 
+        if orig_active_object:
+            if orig_active_object.name in context.view_layer.objects:
+                context.view_layer.objects.active = orig_active_object
 
         # restore locked objects back to their original mode
         # needed because of exclude child updates
-        if locked_objs:
-            context.view_layer.objects.active = locked_active_obj
-
-            if context.view_layer.objects.active:
-                bpy.ops.object.mode_set(mode=locked_objs_mode)
+        if context.view_layer.objects.active:
+            if locked.objs:
+                bpy.ops.object.mode_set(mode=locked.mode)
 
         # set layer as active layer collection
         context.view_layer.active_layer_collection = qcd_laycol
diff --git a/object_collection_manager/ui.py b/object_collection_manager/ui.py
index 4c1eb077269bf3cc0beae1b367886cd4548a85b0..8d7acc30fb1ac70b8e1edcd036feafd4d7ea01c1 100644
--- a/object_collection_manager/ui.py
+++ b/object_collection_manager/ui.py
@@ -35,10 +35,12 @@ from bpy.props import (
 from .internals import (
     collection_tree,
     collection_state,
+    qcd_collection_state,
     expanded,
     get_max_lvl,
     layer_collections,
     rto_history,
+    qcd_history,
     expand_history,
     phantom_history,
     copy_buffer,
@@ -52,6 +54,10 @@ from .internals import (
     update_qcd_header,
 )
 
+from .qcd_operators import (
+    QCDAllBase,
+)
+
 
 preview_collections = {}
 last_icon_theme_text = None
@@ -842,18 +848,70 @@ class SpecialsMenu(Menu):
         prop.without_objects = True
 
 
+class EnableAllQCDSlotsMenu(Menu):
+    bl_label = "Global QCD Slot Actions"
+    bl_idname = "VIEW3D_MT_CM_qcd_enable_all_menu"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("view3d.enable_all_qcd_slots")
+        layout.operator("view3d.enable_all_qcd_slots_isolated")
+
+        layout.separator()
+
+        layout.operator("view3d.disable_all_non_qcd_slots")
+        layout.operator("view3d.disable_all_collections")
+
+        if context.mode == 'OBJECT':
+            layout.separator()
+            layout.operator("view3d.select_all_qcd_objects")
+
+        layout.separator()
+
+        layout.operator("view3d.discard_qcd_history")
+
+
 def view3d_header_qcd_slots(self, context):
+    global qcd_collection_state
+
+    update_collection_tree(context)
+
+    view_layer = context.view_layer
+
     layout = self.layout
 
     idx = 1
 
-    split = layout.split()
+    if qcd_collection_state:
+        view_layer = context.view_layer
+        new_state = generate_state(qcd=True)
+
+        if (new_state["name"] != qcd_collection_state["name"]
+        or  new_state["exclude"] != qcd_collection_state["exclude"]
+        or  new_state["exclude"] != qcd_collection_state["exclude"]
+        or  new_state["qcd"] != qcd_collection_state["qcd"]):
+            if view_layer.name in qcd_history:
+                del qcd_history[view_layer.name]
+                qcd_collection_state.clear()
+                QCDAllBase.clear()
+
+
+    main_row = layout.row(align=True)
+    current_qcd_history = qcd_history.get(context.view_layer.name, [])
+
+    main_row.operator_menu_hold("view3d.enable_all_qcd_slots_meta",
+                                text="",
+                                icon='HIDE_OFF',
+                                depress=bool(current_qcd_history),
+                                menu="VIEW3D_MT_CM_qcd_enable_all_menu")
+
+
+    split = main_row.split()
     col = split.column(align=True)
     row = col.row(align=True)
     row.scale_y = 0.5
 
-    update_collection_tree(context)
-
     selected_objects = get_move_selection()
     active_object = get_move_active()