diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index bb94180..55572ad 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,6 +1,5 @@
 name: Bug report
 description: File a bug report to help us improve
-labels: 'bug'
 body:
   - type: markdown
     attributes:
@@ -39,9 +38,8 @@ body:
       description: You can find version information from the main menu bar [Help > About] within the software.
       multiple: false
       options:
+        - 1.7
         - 1.6
-        - 1.5
-        - 1.4
         - Nightly (Specify below)
         - Other (Specify below)
     validations:
diff --git a/appveyor.yml b/appveyor.yml
index eebb184..b2d19ac 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 1.7.0.{build}
+version: 1.7.1.{build}
 pull_requests:
   do_not_increment_build_number: true
 skip_tags: true
@@ -50,7 +50,7 @@ after_build:
     
     copy /Y ..\..\thirdparty\libmypaint\dist\64\libmypaint-1-4-0.dll %CONFIGURATION%\OpenToonz
 
-    copy /Y "C:\Tools\opencv\build\x64\vc15\bin\opencv_world460.dll" %CONFIGURATION%\OpenToonz
+    copy /Y "C:\Tools\opencv\build\x64\vc16\bin\opencv_world470.dll" %CONFIGURATION%\OpenToonz
 
     mkdir "%CONFIGURATION%\OpenToonz stuff"
 
diff --git a/doc/how_to_build_linux.md b/doc/how_to_build_linux.md
index f02cd37..c65e9f3 100644
--- a/doc/how_to_build_linux.md
+++ b/doc/how_to_build_linux.md
@@ -38,7 +38,7 @@ Notes:
 (it may include some useless packages)
 
 ```
-$ sudo dnf install gcc gcc-c++ automake git cmake boost boost-devel SuperLU SuperLU-devel lz4-devel lzma libusb-devel lzo-devel libjpeg-turbo-devel libGLEW glew-devel freeglut-devel freeglut freetype-devel libpng-devel qt5-qtbase-devel qt5-qtsvg qt5-qtsvg-devel qt5-qtscript qt5-qtscript-devel qt5-qttools qt5-qttools-devel qt5-qtmultimedia-devel blas blas-devel json-c-devel libtool intltool make qt5-qtmultimedia
+$ sudo dnf install gcc gcc-c++ automake git cmake boost boost-devel SuperLU SuperLU-devel lz4-devel lzma libusb-devel lzo-devel libjpeg-turbo-devel libGLEW glew-devel freeglut-devel freeglut freetype-devel libpng-devel qt5-qtbase-devel qt5-qtsvg qt5-qtsvg-devel qt5-qtscript qt5-qtscript-devel qt5-qttools qt5-qttools-devel qt5-qtmultimedia-devel blas blas-devel json-c-devel libtool intltool make qt5-qtmultimedia turbojpeg-devel opencv-devel qt5-qttools-static qt5-qtserialport-devel
 ```
 
 For newest versions of OS you may install libmypaint from repository and don't need to build it from source:
diff --git a/stuff/config/qss/Blue/Blue.qss b/stuff/config/qss/Blue/Blue.qss
index 2ee5fe4..73e6677 100644
--- a/stuff/config/qss/Blue/Blue.qss
+++ b/stuff/config/qss/Blue/Blue.qss
@@ -2372,6 +2372,7 @@ XsheetViewer {
   qproperty-XsheetPreviewButtonOnImage: url('../Default/imgs/white/x_prev_eye_on.svg');
   qproperty-XsheetPreviewButtonBgOffColor: transparent;
   qproperty-XsheetPreviewButtonOffImage: url('../Default/imgs/white/x_prev_eye_off.svg');
+  qproperty-XsheetUnifiedButtonTranspImage: url('../Default/imgs/white/x_prev_eye_transp.svg');
   qproperty-XsheetCamstandButtonBgOnColor: #eb906b;
   qproperty-XsheetCamstandButtonOnImage: url('../Default/imgs/white/x_table_view_on.svg');
   qproperty-XsheetCamstandButtonTranspImage: url('../Default/imgs/white/x_table_view_transp.svg');
@@ -2389,6 +2390,7 @@ XsheetViewer {
   qproperty-TimelinePreviewButtonOnImage: url('../Default/imgs/white/preview_small.svg');
   qproperty-TimelinePreviewButtonBgOffColor: #414345;
   qproperty-TimelinePreviewButtonOffImage: url('none');
+  qproperty-TimelineUnifiedButtonTranspImage: url('../Default/imgs/white/preview_trans_small.svg');
   qproperty-TimelineCamstandButtonBgOnColor: #414345;
   qproperty-TimelineCamstandButtonOnImage: url('../Default/imgs/white/table_small.svg');
   qproperty-TimelineCamstandButtonTranspImage: url('../Default/imgs/white/trans_small.svg');
diff --git a/stuff/config/qss/Dark/Dark.qss b/stuff/config/qss/Dark/Dark.qss
index 7f6c51b..10652ea 100644
--- a/stuff/config/qss/Dark/Dark.qss
+++ b/stuff/config/qss/Dark/Dark.qss
@@ -2372,6 +2372,7 @@ XsheetViewer {
   qproperty-XsheetPreviewButtonOnImage: url('../Default/imgs/white/x_prev_eye_on.svg');
   qproperty-XsheetPreviewButtonBgOffColor: transparent;
   qproperty-XsheetPreviewButtonOffImage: url('../Default/imgs/white/x_prev_eye_off.svg');
+  qproperty-XsheetUnifiedButtonTranspImage: url('../Default/imgs/white/x_prev_eye_transp.svg');
   qproperty-XsheetCamstandButtonBgOnColor: #eb906b;
   qproperty-XsheetCamstandButtonOnImage: url('../Default/imgs/white/x_table_view_on.svg');
   qproperty-XsheetCamstandButtonTranspImage: url('../Default/imgs/white/x_table_view_transp.svg');
@@ -2389,6 +2390,7 @@ XsheetViewer {
   qproperty-TimelinePreviewButtonOnImage: url('../Default/imgs/white/preview_small.svg');
   qproperty-TimelinePreviewButtonBgOffColor: #303030;
   qproperty-TimelinePreviewButtonOffImage: url('none');
+  qproperty-TimelineUnifiedButtonTranspImage: url('../Default/imgs/white/preview_trans_small.svg');
   qproperty-TimelineCamstandButtonBgOnColor: #303030;
   qproperty-TimelineCamstandButtonOnImage: url('../Default/imgs/white/table_small.svg');
   qproperty-TimelineCamstandButtonTranspImage: url('../Default/imgs/white/trans_small.svg');
diff --git a/stuff/config/qss/Default/Default.qss b/stuff/config/qss/Default/Default.qss
index e337927..f502d4d 100644
--- a/stuff/config/qss/Default/Default.qss
+++ b/stuff/config/qss/Default/Default.qss
@@ -2372,6 +2372,7 @@ XsheetViewer {
   qproperty-XsheetPreviewButtonOnImage: url('imgs/white/x_prev_eye_on.svg');
   qproperty-XsheetPreviewButtonBgOffColor: transparent;
   qproperty-XsheetPreviewButtonOffImage: url('imgs/white/x_prev_eye_off.svg');
+  qproperty-XsheetUnifiedButtonTranspImage: url('imgs/white/x_prev_eye_transp.svg');
   qproperty-XsheetCamstandButtonBgOnColor: #eb906b;
   qproperty-XsheetCamstandButtonOnImage: url('imgs/white/x_table_view_on.svg');
   qproperty-XsheetCamstandButtonTranspImage: url('imgs/white/x_table_view_transp.svg');
@@ -2389,6 +2390,7 @@ XsheetViewer {
   qproperty-TimelinePreviewButtonOnImage: url('imgs/white/preview_small.svg');
   qproperty-TimelinePreviewButtonBgOffColor: #484848;
   qproperty-TimelinePreviewButtonOffImage: url('none');
+  qproperty-TimelineUnifiedButtonTranspImage: url('imgs/white/preview_trans_small.svg');
   qproperty-TimelineCamstandButtonBgOnColor: #484848;
   qproperty-TimelineCamstandButtonOnImage: url('imgs/white/table_small.svg');
   qproperty-TimelineCamstandButtonTranspImage: url('imgs/white/trans_small.svg');
diff --git a/stuff/config/qss/Default/imgs/black/preview_trans_small.svg b/stuff/config/qss/Default/imgs/black/preview_trans_small.svg
new file mode 100644
index 0000000..99ad099
--- /dev/null
+++ b/stuff/config/qss/Default/imgs/black/preview_trans_small.svg
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="18px"
+   height="18px"
+   version="1.1"
+   xml:space="preserve"
+   style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
+   id="svg10"
+   sodipodi:docname="preview_trans_small.svg"
+   inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
+   id="defs14" /><sodipodi:namedview
+   id="namedview12"
+   pagecolor="#ffffff"
+   bordercolor="#000000"
+   borderopacity="0.25"
+   inkscape:showpageshadow="2"
+   inkscape:pageopacity="0.0"
+   inkscape:pagecheckerboard="0"
+   inkscape:deskcolor="#d1d1d1"
+   showgrid="true"
+   inkscape:zoom="40.34437"
+   inkscape:cx="14.314265"
+   inkscape:cy="11.178759"
+   inkscape:window-width="2560"
+   inkscape:window-height="1377"
+   inkscape:window-x="-8"
+   inkscape:window-y="-8"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="svg10" />
+    <rect
+   x="0"
+   y="0"
+   width="18"
+   height="18"
+   style="fill-opacity:0;"
+   id="rect2" />
+    <path
+   d="M3,8.991C3,8.991 5.248,5 9,5C12.752,5 15,8.991 15,8.991C15,8.991 12.761,13 9,13C5.239,13 3,8.991 3,8.991ZM9,6C10.656,6 12,7.344 12,9C12,10.656 10.656,12 9,12C7.344,12 6,10.656 6,9C6,7.344 7.344,6 9,6Z"
+   style="fill-opacity:0.8;stroke:#000000;stroke-opacity:0.7962963;fill:none;stroke-linejoin:miter"
+   id="path4" />
+    
+</svg>
diff --git a/stuff/config/qss/Default/imgs/black/x_prev_eye_transp.svg b/stuff/config/qss/Default/imgs/black/x_prev_eye_transp.svg
new file mode 100644
index 0000000..72e7a33
--- /dev/null
+++ b/stuff/config/qss/Default/imgs/black/x_prev_eye_transp.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="18px"
+   height="17px"
+   version="1.1"
+   xml:space="preserve"
+   style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
+   id="svg1414"
+   sodipodi:docname="x_prev_eye_transp.svg"
+   inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
+   id="defs1418"><linearGradient
+     inkscape:collect="always"
+     id="linearGradient3559"><stop
+       style="stop-color:#000000;stop-opacity:1;"
+       offset="0"
+       id="stop3555" /><stop
+       style="stop-color:#000000;stop-opacity:0;"
+       offset="1"
+       id="stop3557" /></linearGradient><linearGradient
+     inkscape:collect="always"
+     xlink:href="#linearGradient3559"
+     id="linearGradient3561"
+     x1="9.0022936"
+     y1="13.096883"
+     x2="9.0022936"
+     y2="4.9616437"
+     gradientUnits="userSpaceOnUse"
+     spreadMethod="pad" /></defs><sodipodi:namedview
+   id="namedview1416"
+   pagecolor="#ffffff"
+   bordercolor="#000000"
+   borderopacity="0.25"
+   inkscape:showpageshadow="2"
+   inkscape:pageopacity="0.0"
+   inkscape:pagecheckerboard="0"
+   inkscape:deskcolor="#d1d1d1"
+   showgrid="true"
+   inkscape:zoom="60.411765"
+   inkscape:cx="9.013145"
+   inkscape:cy="8.5082765"
+   inkscape:window-width="2560"
+   inkscape:window-height="1377"
+   inkscape:window-x="-8"
+   inkscape:window-y="-8"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="g1412"><inkscape:grid
+     type="xygrid"
+     id="grid1900" /></sodipodi:namedview>
+    <rect
+   x="0"
+   y="0"
+   width="18"
+   height="17"
+   style="fill:white;fill-opacity:0;"
+   id="rect1408" />
+    <g
+   transform="matrix(0.848485,0,0,0.848485,1.36364,1.36364)"
+   id="g1412">
+        <path
+   d="M 9,3.375 C 5.25,3.375 2.047,5.708 0.75,9 2.047,12.293 5.25,14.625 9,14.625 12.75,14.625 15.953,12.293 17.25,9 15.953,5.708 12.75,3.375 9,3.375 Z m 0,9.75 C 6.723,13.125 4.875,11.277 4.875,9 c 1.7618094,0 6.517777,0 8.25,0 0,2.277 -1.848,4.125 -4.125,4.125 z M 6.643,9 c 0,1.304 1.053,2.357 2.357,2.357 1.304,0 2.357,-1.053 2.357,-2.357 -1.155448,0 -3.5107138,0 -4.714,0 z"
+   style="fill-opacity:1;fill-rule:nonzero;fill:url(#linearGradient3561)"
+   id="path1410"
+   sodipodi:nodetypes="scscssccscscc" />
+    </g>
+</svg>
diff --git a/stuff/config/qss/Default/imgs/white/preview_trans_small.svg b/stuff/config/qss/Default/imgs/white/preview_trans_small.svg
new file mode 100644
index 0000000..abd0524
--- /dev/null
+++ b/stuff/config/qss/Default/imgs/white/preview_trans_small.svg
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="18px"
+   height="18px"
+   version="1.1"
+   xml:space="preserve"
+   style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
+   id="svg10"
+   sodipodi:docname="preview_trans_small.svg"
+   inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
+   id="defs14" /><sodipodi:namedview
+   id="namedview12"
+   pagecolor="#ffffff"
+   bordercolor="#000000"
+   borderopacity="0.25"
+   inkscape:showpageshadow="2"
+   inkscape:pageopacity="0.0"
+   inkscape:pagecheckerboard="0"
+   inkscape:deskcolor="#d1d1d1"
+   showgrid="true"
+   inkscape:zoom="40.34437"
+   inkscape:cx="14.339052"
+   inkscape:cy="11.178759"
+   inkscape:window-width="2560"
+   inkscape:window-height="1377"
+   inkscape:window-x="-8"
+   inkscape:window-y="-8"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="svg10" />
+    <rect
+   x="0"
+   y="0"
+   width="18"
+   height="18"
+   style="fill-opacity:0;"
+   id="rect2" />
+    <path
+   d="M3,8.991C3,8.991 5.248,5 9,5C12.752,5 15,8.991 15,8.991C15,8.991 12.761,13 9,13C5.239,13 3,8.991 3,8.991ZM9,6C10.656,6 12,7.344 12,9C12,10.656 10.656,12 9,12C7.344,12 6,10.656 6,9C6,7.344 7.344,6 9,6Z"
+   style="fill-opacity:0.80000001;fill:none;stroke:#ffffff;stroke-opacity:0.80000001"
+   id="path4" />
+    
+</svg>
diff --git a/stuff/config/qss/Default/imgs/white/x_prev_eye_transp.svg b/stuff/config/qss/Default/imgs/white/x_prev_eye_transp.svg
new file mode 100644
index 0000000..72e7a33
--- /dev/null
+++ b/stuff/config/qss/Default/imgs/white/x_prev_eye_transp.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="18px"
+   height="17px"
+   version="1.1"
+   xml:space="preserve"
+   style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
+   id="svg1414"
+   sodipodi:docname="x_prev_eye_transp.svg"
+   inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
+   id="defs1418"><linearGradient
+     inkscape:collect="always"
+     id="linearGradient3559"><stop
+       style="stop-color:#000000;stop-opacity:1;"
+       offset="0"
+       id="stop3555" /><stop
+       style="stop-color:#000000;stop-opacity:0;"
+       offset="1"
+       id="stop3557" /></linearGradient><linearGradient
+     inkscape:collect="always"
+     xlink:href="#linearGradient3559"
+     id="linearGradient3561"
+     x1="9.0022936"
+     y1="13.096883"
+     x2="9.0022936"
+     y2="4.9616437"
+     gradientUnits="userSpaceOnUse"
+     spreadMethod="pad" /></defs><sodipodi:namedview
+   id="namedview1416"
+   pagecolor="#ffffff"
+   bordercolor="#000000"
+   borderopacity="0.25"
+   inkscape:showpageshadow="2"
+   inkscape:pageopacity="0.0"
+   inkscape:pagecheckerboard="0"
+   inkscape:deskcolor="#d1d1d1"
+   showgrid="true"
+   inkscape:zoom="60.411765"
+   inkscape:cx="9.013145"
+   inkscape:cy="8.5082765"
+   inkscape:window-width="2560"
+   inkscape:window-height="1377"
+   inkscape:window-x="-8"
+   inkscape:window-y="-8"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="g1412"><inkscape:grid
+     type="xygrid"
+     id="grid1900" /></sodipodi:namedview>
+    <rect
+   x="0"
+   y="0"
+   width="18"
+   height="17"
+   style="fill:white;fill-opacity:0;"
+   id="rect1408" />
+    <g
+   transform="matrix(0.848485,0,0,0.848485,1.36364,1.36364)"
+   id="g1412">
+        <path
+   d="M 9,3.375 C 5.25,3.375 2.047,5.708 0.75,9 2.047,12.293 5.25,14.625 9,14.625 12.75,14.625 15.953,12.293 17.25,9 15.953,5.708 12.75,3.375 9,3.375 Z m 0,9.75 C 6.723,13.125 4.875,11.277 4.875,9 c 1.7618094,0 6.517777,0 8.25,0 0,2.277 -1.848,4.125 -4.125,4.125 z M 6.643,9 c 0,1.304 1.053,2.357 2.357,2.357 1.304,0 2.357,-1.053 2.357,-2.357 -1.155448,0 -3.5107138,0 -4.714,0 z"
+   style="fill-opacity:1;fill-rule:nonzero;fill:url(#linearGradient3561)"
+   id="path1410"
+   sodipodi:nodetypes="scscssccscscc" />
+    </g>
+</svg>
diff --git a/stuff/config/qss/Default/less/layouts/xsheet.less b/stuff/config/qss/Default/less/layouts/xsheet.less
index 8863560..5d7cbca 100644
--- a/stuff/config/qss/Default/less/layouts/xsheet.less
+++ b/stuff/config/qss/Default/less/layouts/xsheet.less
@@ -170,6 +170,8 @@ XsheetViewer {
   qproperty-XsheetPreviewButtonBgOffColor: transparent;
   qproperty-XsheetPreviewButtonOffImage: url('@{img-url}/x_prev_eye_off.svg');
 
+  qproperty-XsheetUnifiedButtonTranspImage: url('@{img-url}/x_prev_eye_transp.svg');
+
   qproperty-XsheetCamstandButtonBgOnColor: @xsheet-CamstandButtonBgOn-color;
   qproperty-XsheetCamstandButtonOnImage: url('@{img-url}/x_table_view_on.svg');
   qproperty-XsheetCamstandButtonTranspImage: url('@{img-url}/x_table_view_transp.svg');
@@ -192,6 +194,8 @@ XsheetViewer {
   qproperty-TimelinePreviewButtonOnImage: url('@{img-url}/preview_small.svg');
   qproperty-TimelinePreviewButtonBgOffColor: @bg;
   qproperty-TimelinePreviewButtonOffImage: url('none');
+  
+  qproperty-TimelineUnifiedButtonTranspImage: url('@{img-url}/preview_trans_small.svg');
 
   qproperty-TimelineCamstandButtonBgOnColor: @bg;
   qproperty-TimelineCamstandButtonOnImage: url('@{img-url}/table_small.svg');
diff --git a/stuff/config/qss/Light/Light.qss b/stuff/config/qss/Light/Light.qss
index 8a0e464..ebe296f 100644
--- a/stuff/config/qss/Light/Light.qss
+++ b/stuff/config/qss/Light/Light.qss
@@ -2372,6 +2372,7 @@ XsheetViewer {
   qproperty-XsheetPreviewButtonOnImage: url('../Default/imgs/black/x_prev_eye_on.svg');
   qproperty-XsheetPreviewButtonBgOffColor: transparent;
   qproperty-XsheetPreviewButtonOffImage: url('../Default/imgs/black/x_prev_eye_off.svg');
+  qproperty-XsheetUnifiedButtonTranspImage: url('../Default/imgs/black/x_prev_eye_transp.svg');
   qproperty-XsheetCamstandButtonBgOnColor: #ffa683;
   qproperty-XsheetCamstandButtonOnImage: url('../Default/imgs/black/x_table_view_on.svg');
   qproperty-XsheetCamstandButtonTranspImage: url('../Default/imgs/black/x_table_view_transp.svg');
@@ -2389,6 +2390,7 @@ XsheetViewer {
   qproperty-TimelinePreviewButtonOnImage: url('../Default/imgs/black/preview_small.svg');
   qproperty-TimelinePreviewButtonBgOffColor: #DBDBDB;
   qproperty-TimelinePreviewButtonOffImage: url('none');
+  qproperty-TimelineUnifiedButtonTranspImage: url('../Default/imgs/black/preview_trans_small.svg');
   qproperty-TimelineCamstandButtonBgOnColor: #DBDBDB;
   qproperty-TimelineCamstandButtonOnImage: url('../Default/imgs/black/table_small.svg');
   qproperty-TimelineCamstandButtonTranspImage: url('../Default/imgs/black/trans_small.svg');
diff --git a/stuff/config/qss/Neutral/Neutral.qss b/stuff/config/qss/Neutral/Neutral.qss
index f66f83d..7ac5da9 100644
--- a/stuff/config/qss/Neutral/Neutral.qss
+++ b/stuff/config/qss/Neutral/Neutral.qss
@@ -2372,6 +2372,7 @@ XsheetViewer {
   qproperty-XsheetPreviewButtonOnImage: url('../Default/imgs/black/x_prev_eye_on.svg');
   qproperty-XsheetPreviewButtonBgOffColor: transparent;
   qproperty-XsheetPreviewButtonOffImage: url('../Default/imgs/black/x_prev_eye_off.svg');
+  qproperty-XsheetUnifiedButtonTranspImage: url('../Default/imgs/black/x_prev_eye_transp.svg');
   qproperty-XsheetCamstandButtonBgOnColor: #eb906b;
   qproperty-XsheetCamstandButtonOnImage: url('../Default/imgs/black/x_table_view_on.svg');
   qproperty-XsheetCamstandButtonTranspImage: url('../Default/imgs/black/x_table_view_transp.svg');
@@ -2389,6 +2390,7 @@ XsheetViewer {
   qproperty-TimelinePreviewButtonOnImage: url('../Default/imgs/black/preview_small.svg');
   qproperty-TimelinePreviewButtonBgOffColor: #808080;
   qproperty-TimelinePreviewButtonOffImage: url('none');
+  qproperty-TimelineUnifiedButtonTranspImage: url('../Default/imgs/black/preview_trans_small.svg');
   qproperty-TimelineCamstandButtonBgOnColor: #808080;
   qproperty-TimelineCamstandButtonOnImage: url('../Default/imgs/black/table_small.svg');
   qproperty-TimelineCamstandButtonTranspImage: url('../Default/imgs/black/trans_small.svg');
diff --git a/stuff/library/textures/zottone_circle001.png b/stuff/library/textures/zottone_circle001.png
new file mode 100644
index 0000000..7c58b26
Binary files /dev/null and b/stuff/library/textures/zottone_circle001.png differ
diff --git a/stuff/library/textures/zottone_circle002.png b/stuff/library/textures/zottone_circle002.png
new file mode 100644
index 0000000..825ec88
Binary files /dev/null and b/stuff/library/textures/zottone_circle002.png differ
diff --git a/stuff/library/textures/zottone_cross001.png b/stuff/library/textures/zottone_cross001.png
new file mode 100644
index 0000000..009b072
Binary files /dev/null and b/stuff/library/textures/zottone_cross001.png differ
diff --git a/stuff/library/textures/zottone_cross002.png b/stuff/library/textures/zottone_cross002.png
new file mode 100644
index 0000000..7074265
Binary files /dev/null and b/stuff/library/textures/zottone_cross002.png differ
diff --git a/stuff/library/textures/zottone_cross003.png b/stuff/library/textures/zottone_cross003.png
new file mode 100644
index 0000000..aa6aa05
Binary files /dev/null and b/stuff/library/textures/zottone_cross003.png differ
diff --git a/stuff/library/textures/zottone_cross004.png b/stuff/library/textures/zottone_cross004.png
new file mode 100644
index 0000000..44079d1
Binary files /dev/null and b/stuff/library/textures/zottone_cross004.png differ
diff --git a/stuff/library/textures/zottone_cross005.png b/stuff/library/textures/zottone_cross005.png
new file mode 100644
index 0000000..943c3ab
Binary files /dev/null and b/stuff/library/textures/zottone_cross005.png differ
diff --git a/stuff/library/textures/zottone_dash001.png b/stuff/library/textures/zottone_dash001.png
new file mode 100644
index 0000000..9e7318e
Binary files /dev/null and b/stuff/library/textures/zottone_dash001.png differ
diff --git a/stuff/library/textures/zottone_dashd001.png b/stuff/library/textures/zottone_dashd001.png
new file mode 100644
index 0000000..6857e67
Binary files /dev/null and b/stuff/library/textures/zottone_dashd001.png differ
diff --git a/stuff/library/textures/zottone_dot001.png b/stuff/library/textures/zottone_dot001.png
new file mode 100644
index 0000000..f06d16d
Binary files /dev/null and b/stuff/library/textures/zottone_dot001.png differ
diff --git a/stuff/library/textures/zottone_dot002.png b/stuff/library/textures/zottone_dot002.png
new file mode 100644
index 0000000..7199c34
Binary files /dev/null and b/stuff/library/textures/zottone_dot002.png differ
diff --git a/stuff/library/textures/zottone_dot003.png b/stuff/library/textures/zottone_dot003.png
new file mode 100644
index 0000000..4124859
Binary files /dev/null and b/stuff/library/textures/zottone_dot003.png differ
diff --git a/stuff/library/textures/zottone_dot005.png b/stuff/library/textures/zottone_dot005.png
new file mode 100644
index 0000000..986d0e4
Binary files /dev/null and b/stuff/library/textures/zottone_dot005.png differ
diff --git a/stuff/library/textures/zottone_dot006.png b/stuff/library/textures/zottone_dot006.png
new file mode 100644
index 0000000..7ee171b
Binary files /dev/null and b/stuff/library/textures/zottone_dot006.png differ
diff --git a/stuff/library/textures/zottone_grid001.png b/stuff/library/textures/zottone_grid001.png
new file mode 100644
index 0000000..83427b0
Binary files /dev/null and b/stuff/library/textures/zottone_grid001.png differ
diff --git a/stuff/library/textures/zottone_grid002.png b/stuff/library/textures/zottone_grid002.png
new file mode 100644
index 0000000..19f1ad8
Binary files /dev/null and b/stuff/library/textures/zottone_grid002.png differ
diff --git a/stuff/library/textures/zottone_grid003.png b/stuff/library/textures/zottone_grid003.png
new file mode 100644
index 0000000..71ef62e
Binary files /dev/null and b/stuff/library/textures/zottone_grid003.png differ
diff --git a/stuff/library/textures/zottone_grid004.png b/stuff/library/textures/zottone_grid004.png
new file mode 100644
index 0000000..d2c9dd8
Binary files /dev/null and b/stuff/library/textures/zottone_grid004.png differ
diff --git a/stuff/library/textures/zottone_grid005.png b/stuff/library/textures/zottone_grid005.png
new file mode 100644
index 0000000..998842d
Binary files /dev/null and b/stuff/library/textures/zottone_grid005.png differ
diff --git a/stuff/library/textures/zottone_grid006.png b/stuff/library/textures/zottone_grid006.png
new file mode 100644
index 0000000..6f558ec
Binary files /dev/null and b/stuff/library/textures/zottone_grid006.png differ
diff --git a/stuff/library/textures/zottone_grid007.png b/stuff/library/textures/zottone_grid007.png
new file mode 100644
index 0000000..67306fc
Binary files /dev/null and b/stuff/library/textures/zottone_grid007.png differ
diff --git a/stuff/library/textures/zottone_grid020.png b/stuff/library/textures/zottone_grid020.png
new file mode 100644
index 0000000..85b66ca
Binary files /dev/null and b/stuff/library/textures/zottone_grid020.png differ
diff --git a/stuff/library/textures/zottone_grid030.png b/stuff/library/textures/zottone_grid030.png
new file mode 100644
index 0000000..4e6c135
Binary files /dev/null and b/stuff/library/textures/zottone_grid030.png differ
diff --git a/stuff/library/textures/zottone_grid031.png b/stuff/library/textures/zottone_grid031.png
new file mode 100644
index 0000000..803de10
Binary files /dev/null and b/stuff/library/textures/zottone_grid031.png differ
diff --git a/stuff/library/textures/zottone_lined001.png b/stuff/library/textures/zottone_lined001.png
new file mode 100644
index 0000000..749e084
Binary files /dev/null and b/stuff/library/textures/zottone_lined001.png differ
diff --git a/stuff/library/textures/zottone_lined002.png b/stuff/library/textures/zottone_lined002.png
new file mode 100644
index 0000000..8117663
Binary files /dev/null and b/stuff/library/textures/zottone_lined002.png differ
diff --git a/stuff/library/textures/zottone_lined011.png b/stuff/library/textures/zottone_lined011.png
new file mode 100644
index 0000000..3be6a54
Binary files /dev/null and b/stuff/library/textures/zottone_lined011.png differ
diff --git a/stuff/library/textures/zottone_lined012.png b/stuff/library/textures/zottone_lined012.png
new file mode 100644
index 0000000..bda0d1a
Binary files /dev/null and b/stuff/library/textures/zottone_lined012.png differ
diff --git a/stuff/library/textures/zottone_lineh001.png b/stuff/library/textures/zottone_lineh001.png
new file mode 100644
index 0000000..f363260
Binary files /dev/null and b/stuff/library/textures/zottone_lineh001.png differ
diff --git a/stuff/library/textures/zottone_lineh002.png b/stuff/library/textures/zottone_lineh002.png
new file mode 100644
index 0000000..b0c1938
Binary files /dev/null and b/stuff/library/textures/zottone_lineh002.png differ
diff --git a/stuff/library/textures/zottone_linev001.png b/stuff/library/textures/zottone_linev001.png
new file mode 100644
index 0000000..2353eef
Binary files /dev/null and b/stuff/library/textures/zottone_linev001.png differ
diff --git a/stuff/library/textures/zottone_linev002.png b/stuff/library/textures/zottone_linev002.png
new file mode 100644
index 0000000..181512e
Binary files /dev/null and b/stuff/library/textures/zottone_linev002.png differ
diff --git a/stuff/library/textures/zottone_wallbrick001.png b/stuff/library/textures/zottone_wallbrick001.png
new file mode 100644
index 0000000..e99ba33
Binary files /dev/null and b/stuff/library/textures/zottone_wallbrick001.png differ
diff --git a/stuff/library/textures/zottone_wave001.png b/stuff/library/textures/zottone_wave001.png
new file mode 100644
index 0000000..1b07ceb
Binary files /dev/null and b/stuff/library/textures/zottone_wave001.png differ
diff --git a/stuff/library/textures/zottone_wave002.png b/stuff/library/textures/zottone_wave002.png
new file mode 100644
index 0000000..d287658
Binary files /dev/null and b/stuff/library/textures/zottone_wave002.png differ
diff --git a/toonz/cmake/BundleInfo.plist.in b/toonz/cmake/BundleInfo.plist.in
index 8bc68f3..712cc6a 100644
--- a/toonz/cmake/BundleInfo.plist.in
+++ b/toonz/cmake/BundleInfo.plist.in
@@ -19,11 +19,11 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>1.7.0</string>
+	<string>1.7.1</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>1.7</string>
+	<string>1.7.1</string>
 	<key>CSResourcesFileMapped</key>
 	<true/>
 	<key>LSRequiresCarbon</key>
diff --git a/toonz/sources/common/tsound/tsound.cpp b/toonz/sources/common/tsound/tsound.cpp
index 1bb7c48..a887d90 100644
--- a/toonz/sources/common/tsound/tsound.cpp
+++ b/toonz/sources/common/tsound/tsound.cpp
@@ -82,7 +82,7 @@ TSoundTrackP TSoundTrack::create(TUINT32 sampleRate, int bitPerSample,
                                  int channelCount, TINT32 sampleCount,
                                  int sampleType) {
   TSoundTrackP st = 0;
-  int type = bitPerSample + channelCount;
+  int type        = bitPerSample + channelCount;
   switch (type) {
   case TRK_M8:
     if (sampleType == TSound::INT)
diff --git a/toonz/sources/include/orientation.h b/toonz/sources/include/orientation.h
index 2c382b8..d758a26 100644
--- a/toonz/sources/include/orientation.h
+++ b/toonz/sources/include/orientation.h
@@ -93,6 +93,9 @@ enum class PredefinedRect {
   PREVIEW_LAYER_AREA,  //! clickable area larger than preview icon, containing
                        //! it
   PREVIEW_LAYER,
+  UNIFIEDVIEW_LAYER_AREA,  //! used when unifying the preview and the camstand
+                           //! toggles
+  UNIFIEDVIEW_LAYER,
   LOCK_AREA,          //! clickable area larger than lock icon, containing it
   LOCK,               //! the lock icon itself
   CAMERA_LOCK_AREA,   //! lock area for the camera column
diff --git a/toonz/sources/include/tfarmtask.h b/toonz/sources/include/tfarmtask.h
index 23a1bcd..03751bc 100644
--- a/toonz/sources/include/tfarmtask.h
+++ b/toonz/sources/include/tfarmtask.h
@@ -135,6 +135,7 @@ public:
 
   QString getCommandLinePrgName() const;
   QString getCommandLineArguments() const;
+  QStringList getCommandLineArgumentsList() const;
   QString getCommandLine(bool isFarmTask = false) const;
   void parseCommandLine(QString commandLine);
 
diff --git a/toonz/sources/include/toonz/preferences.h b/toonz/sources/include/toonz/preferences.h
index eac1ace..957e7a1 100644
--- a/toonz/sources/include/toonz/preferences.h
+++ b/toonz/sources/include/toonz/preferences.h
@@ -396,6 +396,9 @@ public:
   bool isShowColumnNumbersEnabled() const {
     return getBoolValue(showColumnNumbers);
   }
+  bool isUnifyColumnVisibilityTogglesEnabled() const {
+    return getBoolValue(unifyColumnVisibilityToggles);
+  }
   bool isParentColorsInXsheetColumnEnabled() const {
     return getBoolValue(parentColorsInXsheetColumn);
   }
@@ -418,6 +421,9 @@ public:
   bool isShowFrameNumberWithLettersEnabled() const {
     return getBoolValue(showFrameNumberWithLetters);
   }
+  bool isLinkColumnNameWithLevelEnabled() const {
+    return getBoolValue(linkColumnNameWithLevel);
+  }
 
   // Animation  tab
   int getKeyframeType() const { return getIntValue(keyframeType); }
diff --git a/toonz/sources/include/toonz/preferencesitemids.h b/toonz/sources/include/toonz/preferencesitemids.h
index 4174fc3..1dd6454 100644
--- a/toonz/sources/include/toonz/preferencesitemids.h
+++ b/toonz/sources/include/toonz/preferencesitemids.h
@@ -132,6 +132,7 @@ enum PreferencesItemId {
   showXSheetToolbar,
   expandFunctionHeader,
   showColumnNumbers,
+  unifyColumnVisibilityToggles,
   parentColorsInXsheetColumn,
   highlightLineEverySecond,
   syncLevelRenumberWithXsheet,
@@ -139,6 +140,7 @@ enum PreferencesItemId {
   currentColumnColor,
   levelNameDisplayType,
   showFrameNumberWithLetters,
+  linkColumnNameWithLevel,
 
   //----------
   // Animation
diff --git a/toonz/sources/include/toonz/txshlevelcolumn.h b/toonz/sources/include/toonz/txshlevelcolumn.h
index e519264..6b50090 100644
--- a/toonz/sources/include/toonz/txshlevelcolumn.h
+++ b/toonz/sources/include/toonz/txshlevelcolumn.h
@@ -19,6 +19,7 @@
 // forward declarations
 class TLevelColumnFx;
 class TXshCell;
+class TXshLevel;
 
 //=============================================================================
 //! The TXshLevelColumn class provides a column of levels in xsheet and allows
@@ -86,7 +87,8 @@ Return \b TFx.
   TFx *getFx() const override;
 
   // Used in TCellData::getNumbers
-  bool setNumbers(int row, int rowCount, const TXshCell cells[]);
+  bool setNumbers(int row, int rowCount, const TXshCell cells[],
+                  TXshLevel *reservedLevel);
 
 private:
   // not implemented
diff --git a/toonz/sources/include/toonzqt/dvdialog.h b/toonz/sources/include/toonzqt/dvdialog.h
index f4af0e6..5917efd 100644
--- a/toonz/sources/include/toonzqt/dvdialog.h
+++ b/toonz/sources/include/toonzqt/dvdialog.h
@@ -261,7 +261,7 @@ public:
 
 public slots:
   void onCheckboxChanged(int checked);
-  void onButtonPressed(int id);
+  void onButtonClicked(int id);
 };
 
 //-----------------------------------------------------------------------------
diff --git a/toonz/sources/include/toonzqt/paramfield.h b/toonz/sources/include/toonzqt/paramfield.h
index ea0ee85..9ecde50 100644
--- a/toonz/sources/include/toonzqt/paramfield.h
+++ b/toonz/sources/include/toonzqt/paramfield.h
@@ -613,8 +613,7 @@ namespace component {
 class MyTextEdit : public QTextEdit {
   Q_OBJECT
 public:
-  MyTextEdit(const QString &text, QWidget *parent = Q_NULLPTR)
-      : QTextEdit(text, parent) {}
+  MyTextEdit(const QString &text, QWidget *parent = Q_NULLPTR);
 
 protected:
   void keyPressEvent(QKeyEvent *event) override;
diff --git a/toonz/sources/include/toonzqt/styleselection.h b/toonz/sources/include/toonzqt/styleselection.h
index 0c561f2..4074c7d 100644
--- a/toonz/sources/include/toonzqt/styleselection.h
+++ b/toonz/sources/include/toonzqt/styleselection.h
@@ -98,7 +98,9 @@ public:
   void removeLink();
   // get back the style from the studio palette (if linked)
   void getBackOriginalStyle();
-  // return true if there is at least one linked style in the selection
+
+  // return true if there is at least one linked style in the selection.
+  // link parent styles are not counted
   bool hasLinkedStyle();
 };
 
diff --git a/toonz/sources/include/tversion.h b/toonz/sources/include/tversion.h
index 591e8a0..b0069f4 100644
--- a/toonz/sources/include/tversion.h
+++ b/toonz/sources/include/tversion.h
@@ -19,8 +19,8 @@ public:
 private:
   const char *applicationName     = "OpenToonz";
   const float applicationVersion  = 1.7f;
-  const float applicationRevision = 0;
-  const char *applicationNote     = "RC";
+  const float applicationRevision = 1;
+  const char *applicationNote     = "";
 };
 
 std::string ToonzVersion::getAppName(void) {
diff --git a/toonz/sources/tnztools/fullcolorbrushtool.cpp b/toonz/sources/tnztools/fullcolorbrushtool.cpp
index 0204fe0..8675b4a 100644
--- a/toonz/sources/tnztools/fullcolorbrushtool.cpp
+++ b/toonz/sources/tnztools/fullcolorbrushtool.cpp
@@ -318,7 +318,7 @@ void FullColorBrushTool::handleMouseEvent(MouseEventType type, const TPointD &po
   bool shift = e.getModifiersMask() & TMouseEvent::SHIFT_KEY;
   bool control = e.getModifiersMask() & TMouseEvent::CTRL_KEY;
   
-  if ((control || shift) && type == ME_DOWN && e.button() == Qt::LeftButton && !m_started) {
+  if (shift && type == ME_DOWN && e.button() == Qt::LeftButton && !m_started) {
     m_modifierAssistants->drawOnly = true;
     m_inputmanager.clearModifiers();
     m_inputmanager.addModifier( TInputModifierP(m_modifierLine.getPointer()) );
diff --git a/toonz/sources/tnztools/rgbpickertool.cpp b/toonz/sources/tnztools/rgbpickertool.cpp
index 9737ea8..ba5838d 100644
--- a/toonz/sources/tnztools/rgbpickertool.cpp
+++ b/toonz/sources/tnztools/rgbpickertool.cpp
@@ -147,7 +147,7 @@ void setCurrentColor(const TPixel32 &color) {
       cs->setMainColor(color);
 
     cs->invalidateIcon();
-    ph->notifyColorStyleChanged();
+    ph->notifyColorStyleChanged(false);
 
     // per le palette animate
     int styleIndex    = ph->getStyleIndex();
diff --git a/toonz/sources/tnztools/toonzrasterbrushtool.cpp b/toonz/sources/tnztools/toonzrasterbrushtool.cpp
index 180f9ea..08207af 100644
--- a/toonz/sources/tnztools/toonzrasterbrushtool.cpp
+++ b/toonz/sources/tnztools/toonzrasterbrushtool.cpp
@@ -1288,7 +1288,7 @@ void ToonzRasterBrushTool::leftButtonDown(const TPointD &pos,
   }
 
   // Modifier to do straight line
-  if (e.isShiftPressed() || e.isCtrlPressed()) {
+  if (e.isShiftPressed()) {
     m_isStraight = true;
     m_firstPoint = pos;
     m_lastPoint  = pos;
diff --git a/toonz/sources/tnztools/toonzvectorbrushtool.cpp b/toonz/sources/tnztools/toonzvectorbrushtool.cpp
index a2e0d81..2f46d02 100644
--- a/toonz/sources/tnztools/toonzvectorbrushtool.cpp
+++ b/toonz/sources/tnztools/toonzvectorbrushtool.cpp
@@ -786,7 +786,7 @@ void ToonzVectorBrushTool::leftButtonDrag(const TPointD &pos,
     invalidateRect +=
         TRectD(m_lastSnapPoint - snapThick, m_lastSnapPoint + snapThick);
 
-  if (e.isCtrlPressed()) {
+  if (e.isShiftPressed() && e.isCtrlPressed()) {
     TPointD m_firstPoint = m_track.getFirstPoint();
 
     double denominator = m_lastSnapPoint.x - m_firstPoint.x;
diff --git a/toonz/sources/tnztools/vectorselectiontool.cpp b/toonz/sources/tnztools/vectorselectiontool.cpp
index a026b59..2a73d1e 100644
--- a/toonz/sources/tnztools/vectorselectiontool.cpp
+++ b/toonz/sources/tnztools/vectorselectiontool.cpp
@@ -416,12 +416,14 @@ void DragSelectionTool::UndoChangeStrokes::restoreRegions() const {
 void DragSelectionTool::UndoChangeStrokes::undo() const {
   transform(m_oldStrokes, m_oldBBox, m_oldCenter, m_oldDeformValues);
   restoreRegions();
+  m_tool->notifyImageChanged();
 }
 
 //-----------------------------------------------------------------------------
 
 void DragSelectionTool::UndoChangeStrokes::redo() const {
   transform(m_newStrokes, m_newBBox, m_newCenter, m_newDeformValues);
+  m_tool->notifyImageChanged();
 }
 
 //-----------------------------------------------------------------------------
@@ -521,6 +523,7 @@ void UndoChangeOutlineStyle::transform(
 void UndoChangeOutlineStyle::undo() const {
   transform(m_oldOptions, m_oldBBox);
   TTool::getApplication()->getCurrentTool()->notifyToolChanged();
+  m_tool->notifyImageChanged();
 }
 
 //-----------------------------------------------------------------------------
@@ -528,6 +531,7 @@ void UndoChangeOutlineStyle::undo() const {
 void UndoChangeOutlineStyle::redo() const {
   transform(m_newOptions, m_newBBox);
   TTool::getApplication()->getCurrentTool()->notifyToolChanged();
+  m_tool->notifyImageChanged();
 }
 
 //-----------------------------------------------------------------------------
diff --git a/toonz/sources/tnztools/vectortapetool.cpp b/toonz/sources/tnztools/vectortapetool.cpp
index 808e05b..1498ef3 100644
--- a/toonz/sources/tnztools/vectortapetool.cpp
+++ b/toonz/sources/tnztools/vectortapetool.cpp
@@ -23,7 +23,6 @@
 #include "tenv.h"
 // For Qt translation support
 #include <QCoreApplication>
-#include <QApplication>
 
 using namespace ToolUtils;
 
@@ -177,8 +176,6 @@ public:
 class VectorTapeTool final : public TTool {
   Q_DECLARE_TR_FUNCTIONS(VectorTapeTool)
 
-  bool m_draw;
-
   bool m_secondPoint;
   int m_strokeIndex1, m_strokeIndex2;
   double m_w1, m_w2, m_pixelSize;
@@ -203,7 +200,6 @@ public:
       , m_w1(-1.0)
       , m_w2(-1.0)
       , m_pixelSize(1)
-      , m_draw(false)
       , m_smooth("Smooth", false)  // W_ToolOptions_Smooth
       , m_joinStrokes("JoinStrokes", false)
       , m_mode("Mode")
@@ -277,7 +273,6 @@ public:
 
   void draw() override {
     TVectorImageP vi(getImage(false));
-    if (!m_draw) return;
     if (!vi) return;
 
     // TAffine viewMatrix = getViewer()->getViewMatrix();
@@ -326,10 +321,6 @@ public:
     TVectorImageP vi(getImage(false));
     if (!vi) return;
 
-    // BUTTA e rimetti (Dava problemi con la penna)
-    //if (!m_draw) return;  // Questa riga potrebbe non essere messa
-    // m_draw=true;   //Perche'??? Non basta dargli true in onEnter??
-
     if (m_type.getValue() == RECT) return;
 
     double minDistance2 = 10000000000.;
@@ -737,23 +728,11 @@ public:
 
   void onEnter() override {
     //      getApplication()->editImage();
-    m_draw          = true;
     m_selectionRect = TRectD();
     m_startRect     = TPointD();
   }
 
-  void onLeave() override {
-    m_draw = false;
-    // m_strokeIndex1=-1;
-  }
-
   void onActivate() override {
-    // enable drawing if we are in a scene viewer
-    QWidget *focusWidget = QApplication::focusWidget();
-    if (focusWidget &&
-        QString(focusWidget->metaObject()->className()) == "SceneViewer")
-      m_draw = true;
-
     if (!m_firstTime) return;
 
     std::wstring s = ::to_wstring(TapeMode.getValue());
diff --git a/toonz/sources/toonz/CMakeLists.txt b/toonz/sources/toonz/CMakeLists.txt
index 925afe4..1d46132 100644
--- a/toonz/sources/toonz/CMakeLists.txt
+++ b/toonz/sources/toonz/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(VERSION 1.7)
+set(VERSION 1.7.1)
 
 set(MOC_HEADERS
     addfilmstripframespopup.h
diff --git a/toonz/sources/toonz/batches.cpp b/toonz/sources/toonz/batches.cpp
index a0877c1..a0bd2d3 100644
--- a/toonz/sources/toonz/batches.cpp
+++ b/toonz/sources/toonz/batches.cpp
@@ -244,17 +244,7 @@ commandline += " -id " + task->m_id;*/
   }
 
   process->setProgram(task->getCommandLinePrgName());
-#if defined(_WIN32)
-  process->setNativeArguments(task->getCommandLineArguments());
-#else
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
-  process->setArguments(
-      task->getCommandLineArguments().split(" ", Qt::SkipEmptyParts));
-#else
-  process->setArguments(
-      task->getCommandLineArguments().split(" ", QString::SkipEmptyParts));
-#endif
-#endif
+  process->setArguments(task->getCommandLineArgumentsList());
   process->start();
   process->waitForFinished(-1);
 
diff --git a/toonz/sources/toonz/cameracapturelevelcontrol.cpp b/toonz/sources/toonz/cameracapturelevelcontrol.cpp
index 3714154..b9746fd 100644
--- a/toonz/sources/toonz/cameracapturelevelcontrol.cpp
+++ b/toonz/sources/toonz/cameracapturelevelcontrol.cpp
@@ -399,4 +399,35 @@ void CameraCaptureLevelControl::computeLut() {
 
     p[i] = (uchar)std::floor(value * maxChannelValueF);
   }
+}
+
+//-----------------------------------------------------------------------------
+
+void CameraCaptureLevelControl::getValues(int& black, int& white,
+                                          int& threshold, double& gamma) {
+  black     = m_histogram->black();
+  white     = m_histogram->white();
+  threshold = m_histogram->threshold();
+  gamma     = (double)m_histogram->gamma();
+}
+
+//-----------------------------------------------------------------------------
+
+void CameraCaptureLevelControl::setValues(const int black, const int white,
+                                          const int threshold,
+                                          const double gamma,
+                                          const bool color_grayscale) {
+  m_whiteFld->setRange(black + 2, 255);
+  m_blackFld->setRange(0, white - 2);
+  m_blackFld->setValue(black);
+  m_whiteFld->setValue(white);
+  m_gammaFld->setValue(gamma);
+  m_thresholdFld->setValue(threshold);
+
+  m_histogram->setValues(m_blackFld->getValue(), m_whiteFld->getValue(),
+                         m_gammaFld->getValue());
+  m_histogram->setThreshold(m_thresholdFld->getValue());
+
+  setMode(color_grayscale);
+  computeLut();
 }
\ No newline at end of file
diff --git a/toonz/sources/toonz/cameracapturelevelcontrol.h b/toonz/sources/toonz/cameracapturelevelcontrol.h
index 5e3c191..f89031a 100644
--- a/toonz/sources/toonz/cameracapturelevelcontrol.h
+++ b/toonz/sources/toonz/cameracapturelevelcontrol.h
@@ -89,6 +89,11 @@ public:
   void adjustLevel(cv::Mat& image);
   void binarize(cv::Mat& image);
 
+  // for saving / loading default
+  void getValues(int& black, int& white, int& threshold, double& gamma);
+  void setValues(const int black, const int white, const int threshold,
+                 const double gamma, const bool color_grayscale);
+
 protected slots:
   void onHistogramValueChanged(int itemId);
   void onFieldChanged();
diff --git a/toonz/sources/toonz/celldata.cpp b/toonz/sources/toonz/celldata.cpp
index 709f2fd..bee5fc1 100644
--- a/toonz/sources/toonz/celldata.cpp
+++ b/toonz/sources/toonz/celldata.cpp
@@ -11,6 +11,12 @@
 #include "toonz/tcolumnfx.h"
 #include "toonz/fxdag.h"
 #include "toonz/txshlevelcolumn.h"
+#include "toonz/preferences.h"
+#include "toonz/tstageobject.h"
+#include "tapp.h"
+#include "toonz/tscenehandle.h"
+#include "toonz/toonzscene.h"
+#include "toonz/levelset.h"
 
 //-----------------------------------------------------------------------------
 
@@ -106,15 +112,35 @@ bool TCellData::getCells(TXsheet *xsh, int r0, int c0, int &r1, int &c1,
 
 bool TCellData::getNumbers(TXsheet *xsh, int r0, int c0, int &r1,
                            int &c1) const {
-  r1                  = r0 + m_rowCount - 1;
-  bool oneToMulti     = m_colCount == 1 && c0 < c1;
+  r1              = r0 + m_rowCount - 1;
+  bool oneToMulti = m_colCount == 1 && c0 < c1;
   if (!oneToMulti) c1 = c0 + m_colCount - 1;
 
   bool cellSet = false;
 
   for (int c = c0; c <= c1; c++) {
-    TXshColumn *column = xsh->getColumn(c);
-    if (!column || column->isEmpty()) continue;
+    TXshColumn *column       = xsh->getColumn(c);
+    TXshLevel *reservedLevel = nullptr;
+    if (!column) continue;
+    if (column->isEmpty()) {
+      if (Preferences::instance()->isLinkColumnNameWithLevelEnabled() &&
+          xsh->getStageObject(TStageObjectId::ColumnId(c))
+              ->hasSpecifiedName()) {
+        std::string columnName =
+            xsh->getStageObject(TStageObjectId::ColumnId(c))->getName();
+        ToonzScene *scene   = TApp::instance()->getCurrentScene()->getScene();
+        TLevelSet *levelSet = scene->getLevelSet();
+        reservedLevel       = levelSet->getLevel(to_wstring(columnName));
+        if (!reservedLevel) continue;
+        // connect to xsheet
+        if (!column->getPaletteColumn()) {
+          TFx *fx = column->getFx();
+          if (fx) xsh->getFxDag()->addToXsheet(fx);
+        }
+
+      } else
+        continue;
+    }
     TXshLevelColumn *levelColumn = column->getLevelColumn();
     if (!levelColumn) continue;
 
@@ -125,8 +151,8 @@ bool TCellData::getNumbers(TXsheet *xsh, int r0, int c0, int &r1,
 
     if (!canChange(column, sourceColIndex)) continue;
 
-    bool isSet = levelColumn->setNumbers(r0, m_rowCount,
-                                         &cells[sourceColIndex * m_rowCount]);
+    bool isSet = levelColumn->setNumbers(
+        r0, m_rowCount, &cells[sourceColIndex * m_rowCount], reservedLevel);
 
     cellSet = cellSet || isSet;
   }
@@ -194,7 +220,7 @@ void TCellData::cloneZeraryFx(int index, std::vector<TXshCell> &cells) const {
     newFxLevel->setColumn(newFxColumn);
     // replace the zerary fx cells by the new fx
     int r;
-    for (r     = firstNotEmptyIndex; r < (index + 1) * m_rowCount; r++)
+    for (r = firstNotEmptyIndex; r < (index + 1) * m_rowCount; r++)
       cells[r] = TXshCell(newFxLevel, m_cells[r].getFrameId());
   }
 }
diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp
index cf127b1..0f5c6f1 100644
--- a/toonz/sources/toonz/cellselection.cpp
+++ b/toonz/sources/toonz/cellselection.cpp
@@ -58,6 +58,7 @@
 #include "tools/strokeselection.h"
 #include "toonz/sceneproperties.h"
 #include "toutputproperties.h"
+#include "toonz/tstageobjectcmd.h"
 
 // TnzCore includes
 #include "timagecache.h"
@@ -217,13 +218,17 @@ class PasteCellsUndo final : public TUndo {
   TCellData *m_data;
   std::vector<bool> m_areOldColumnsEmpty;
   bool m_containsSoundColumn;
+  std::map<int, std::string> m_oldEmptyColumnNames;
 
 public:
   PasteCellsUndo(int r0, int c0, int r1, int c1, int oldR0, int oldC0,
                  int oldR1, int oldC1, const std::vector<bool> &areColumnsEmpty,
-                 bool containsSoundColumn)
+                 bool containsSoundColumn,
+                 const std::map<int, std::string> &oldEmptyColumnNames =
+                     std::map<int, std::string>())
       : m_areOldColumnsEmpty(areColumnsEmpty)
-      , m_containsSoundColumn(containsSoundColumn) {
+      , m_containsSoundColumn(containsSoundColumn)
+      , m_oldEmptyColumnNames(oldEmptyColumnNames) {
     m_data       = new TCellData();
     TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
     m_data->setCells(xsh, r0, c0, r1, c1);
@@ -246,13 +251,18 @@ public:
     int oldR0, oldC0, oldR1, oldC1;
     m_oldSelection->getSelectedCells(oldR0, oldC0, oldR1, oldC1);
 
+    TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
+    for (const auto &item : m_oldEmptyColumnNames) {
+      xsh->getStageObject(TStageObjectId::ColumnId(item.first))
+          ->setName(item.second);
+    }
+
     int c0BeforeCut = c0;
     int c1BeforeCut = c1;
     // Cut delle celle che sono in newSelection
     cutCellsWithoutUndo(r0, c0, r1, c1);
     // Se le colonne erano vuote le resetto (e' necessario farlo per le colonne
     // particolari, colonne sount o palette)
-    TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
     assert(c1BeforeCut - c0BeforeCut + 1 == (int)m_areOldColumnsEmpty.size());
     int c;
     for (c = c0BeforeCut; c <= c1BeforeCut; c++) {
@@ -1502,7 +1512,8 @@ int TCellSelection::Range::getColCount() const { return m_c1 - m_c0 + 1; }
 // TCellSelection
 //-----------------------------------------------------------------------------
 
-TCellSelection::TCellSelection() : m_timeStretchPopup(0), m_reframePopup(0) {
+TCellSelection::TCellSelection()
+    : m_timeStretchPopup(0), m_reframePopup(0), m_resizePivotRow(-1) {
   setAlternativeCommandNames();
 }
 
@@ -1650,6 +1661,10 @@ void TCellSelection::selectCells(int r0, int c0, int r1, int c1) {
   m_range.m_r1            = r1;
   m_range.m_c1            = c1;
   bool onlyOneRasterLevel = containsOnlyOneRasterLevel(r0, c0, r1, c1);
+  // set the nearest row
+  m_resizePivotRow =
+      (std::abs(r0 - m_resizePivotRow) < std::abs(r1 - m_resizePivotRow)) ? r0
+                                                                          : r1;
   CommandManager::instance()->enable(MI_CanvasSize, onlyOneRasterLevel);
 }
 
@@ -1661,13 +1676,15 @@ void TCellSelection::selectCell(int row, int col) {
   m_range.m_r1            = row;
   m_range.m_c1            = col;
   bool onlyOneRasterLevel = containsOnlyOneRasterLevel(row, col, row, col);
+  m_resizePivotRow        = row;
   CommandManager::instance()->enable(MI_CanvasSize, onlyOneRasterLevel);
 }
 
 //-----------------------------------------------------------------------------
 
 void TCellSelection::selectNone() {
-  m_range = Range();
+  m_range          = Range();
+  m_resizePivotRow = -1;
   CommandManager::instance()->enable(MI_CanvasSize, false);
 }
 
@@ -1861,6 +1878,23 @@ void TCellSelection::pasteCells() {
       return;
     }
 
+    // pasting cells may change empty column names. So keep old column names for
+    // undo
+    std::map<int, std::string> emptyColumnNames;
+    if (Preferences::instance()->isLinkColumnNameWithLevelEnabled()) {
+      for (int c = c0; c < c0 + cellData->getColCount(); c++) {
+        TXshColumn *column = xsh->getColumn(c);
+        if (!column || column->isEmpty()) {
+          if (!xsh->getStageObject(TStageObjectId::ColumnId(c))
+                   ->hasSpecifiedName())
+            emptyColumnNames[c] = "";
+          else
+            emptyColumnNames[c] =
+                xsh->getStageObject(TStageObjectId::ColumnId(c))->getName();
+        }
+      }
+    }
+
     bool isPaste = pasteCellsWithoutUndo(cellData, r0, c0, r1, c1);
 
     // Se la selezione corrente e' TCellSelection selezione le celle copiate
@@ -1898,9 +1932,9 @@ void TCellSelection::pasteCells() {
     getLevelSetFromData(cellData, pastedLevels);
     LevelCmd::addMissingLevelsToCast(pastedLevels);
 
-    TUndoManager::manager()->add(
-        new PasteCellsUndo(r0, c0, r1, c1, oldR0, oldC0, oldR1, oldC1,
-                           areColumnsEmpty, containsSoundColumn));
+    TUndoManager::manager()->add(new PasteCellsUndo(
+        r0, c0, r1, c1, oldR0, oldC0, oldR1, oldC1, areColumnsEmpty,
+        containsSoundColumn, emptyColumnNames));
     TApp::instance()->getCurrentScene()->setDirtyFlag(true);
     if (containsSoundColumn)
       TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged();
@@ -2523,8 +2557,20 @@ void TCellSelection::deleteCells(bool withShift) {
     TUndoManager::manager()->beginBlock();
     // remove, then insert empty column
     for (auto colId : removedColIds) {
+      // keep column name if specified
+      std::string columnName = "";
+      if (Preferences::instance()->isLinkColumnNameWithLevelEnabled() &&
+          xsh->getStageObject(TStageObjectId::ColumnId(colId))
+              ->hasSpecifiedName())
+        columnName =
+            xsh->getStageObject(TStageObjectId::ColumnId(colId))->getName();
+
       ColumnCmd::deleteColumn(colId, true);
       ColumnCmd::insertEmptyColumn(colId);
+
+      if (!columnName.empty())
+        TStageObjectCmd::rename(TStageObjectId::ColumnId(colId), columnName,
+                                TApp::instance()->getCurrentXsheet());
     }
   }
 
diff --git a/toonz/sources/toonz/cellselection.h b/toonz/sources/toonz/cellselection.h
index 55d8f06..2ebb77d 100644
--- a/toonz/sources/toonz/cellselection.h
+++ b/toonz/sources/toonz/cellselection.h
@@ -33,6 +33,8 @@ public:
 
 private:
   Range m_range;
+  int m_resizePivotRow;  // pivot frame when resizing the selection with
+                         // ctrl+arrow keys
 
 public:
   TCellSelection();
@@ -129,6 +131,7 @@ public:
   void createBlankDrawing(int row, int col, bool inRange);
   void createBlankDrawings();
   void fillEmptyCell();
+  int getResizePivotRow() const { return m_resizePivotRow; }
 };
 
 #endif  // TCELLSELECTION_H
diff --git a/toonz/sources/toonz/columncommand.cpp b/toonz/sources/toonz/columncommand.cpp
index 8c0b71e..ed65e07 100644
--- a/toonz/sources/toonz/columncommand.cpp
+++ b/toonz/sources/toonz/columncommand.cpp
@@ -658,6 +658,48 @@ public:
   int getHistoryType() override { return HistoryType::Xsheet; }
 };
 
+//---------------------------------------------------------------------------
+
+void doUnifyColumnVisibilityToggles_Recursive(const TXsheet *xsh,
+                                              QStringList &modifiedColumnNames,
+                                              QList<TXsheet *> doneList,
+                                              QStringList &parentXshStack) {
+  for (int c = 0; c < xsh->getColumnCount(); c++) {
+    TXshColumn *column = xsh->getColumn(c);
+    if (!column || column->isEmpty()) continue;
+    int colType = column->getColumnType();
+    if (colType == TXshColumn::ePaletteType ||
+        colType == TXshColumn::eSoundType ||
+        colType == TXshColumn::eSoundTextType)
+      continue;
+    // visibility check
+    if (column->isPreviewVisible() != column->isCamstandVisible()) {
+      column->setCamstandVisible(column->isPreviewVisible());
+      QString colName = QString::fromStdString(
+          xsh->getStageObject(TStageObjectId::ColumnId(c))->getName());
+      modifiedColumnNames.append(parentXshStack.join(" > ") + colName);
+    }
+
+    // check subxsheet recursively
+    TXshCellColumn *cellCol = column->getCellColumn();
+    if (!cellCol) continue;
+    int r0, r1;
+    column->getRange(r0, r1);
+    TXshCell cell              = cellCol->getCell(r0);
+    TXshChildLevel *childLevel = cell.m_level->getChildLevel();
+    if (childLevel) {
+      TXsheet *subSheet = childLevel->getXsheet();
+      if (!doneList.contains(subSheet)) {
+        doneList.append(subSheet);
+        parentXshStack.append(QString::fromStdWString(childLevel->getName()));
+        doUnifyColumnVisibilityToggles_Recursive(xsh, modifiedColumnNames,
+                                                 doneList, parentXshStack);
+        parentXshStack.pop_back();
+      }
+    }
+  }
+}
+
 }  // namespace
 
 //*************************************************************************
@@ -1394,6 +1436,28 @@ bool ColumnCmd::checkExpressionReferences(
       colIdsToBeDeleted, fxsToBeDeleted, objIdsToBeDuplicated, true);
 }
 
+//---------------------------------------------------------------------------
+// Check if any column has visibility toggles with different states and the
+// "unify visibility toggles" option is enabled
+void ColumnCmd::unifyColumnVisibilityToggles() {
+  TApp *app         = TApp::instance();
+  ToonzScene *scene = app->getCurrentScene()->getScene();
+  QStringList modifiedColumnNames;
+  QList<TXsheet *> doneList;
+  QStringList parentStack;
+  doUnifyColumnVisibilityToggles_Recursive(
+      scene->getTopXsheet(), modifiedColumnNames, doneList, parentStack);
+  if (!modifiedColumnNames.isEmpty()) {
+    DVGui::warning(
+        QObject::tr(
+            "The visibility toggles of following columns are modified \n"
+            "due to \"Unify Preview and Camstand Visibility Toggles\" "
+            "preference option : \n  %1")
+            .arg(modifiedColumnNames.join("\n  ")));
+    app->getCurrentScene()->setDirtyFlag(true);
+  }
+}
+
 //=============================================================================
 
 namespace {
@@ -1482,6 +1546,10 @@ public:
           column->setPreviewVisible(negate);
         else
           column->setPreviewVisible(!column->isPreviewVisible());
+
+        // sync camstand visibility
+        if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+          column->setCamstandVisible(column->isPreviewVisible());
       }
       if (cmd &
           (CMD_ENABLE_CAMSTAND | CMD_DISABLE_CAMSTAND | CMD_TOGGLE_CAMSTAND)) {
diff --git a/toonz/sources/toonz/columncommand.h b/toonz/sources/toonz/columncommand.h
index a0754c5..1526067 100644
--- a/toonz/sources/toonz/columncommand.h
+++ b/toonz/sources/toonz/columncommand.h
@@ -54,6 +54,10 @@ bool checkExpressionReferences(const std::set<int> &indices,
 // checkInvert is always true for collapsing in stage schematic
 bool checkExpressionReferences(const QList<TStageObjectId> &objects);
 
+// Check if any column has visibility toggles with different states and the
+// "unify visibility toggles" option is enabled
+void unifyColumnVisibilityToggles();
+
 }  // namespace ColumnCmd
 
 #endif
diff --git a/toonz/sources/toonz/icons/dark/actions/16/gear_check.svg b/toonz/sources/toonz/icons/dark/actions/16/gear_check.svg
new file mode 100644
index 0000000..885734b
--- /dev/null
+++ b/toonz/sources/toonz/icons/dark/actions/16/gear_check.svg
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   width="16px"
+   height="16px"
+   version="1.1"
+   xml:space="preserve"
+   style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
+   id="svg698"
+   sodipodi:docname="gear_check.svg"
+   inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
+   id="defs702" /><sodipodi:namedview
+   id="namedview700"
+   pagecolor="#ffffff"
+   bordercolor="#000000"
+   borderopacity="0.25"
+   inkscape:showpageshadow="2"
+   inkscape:pageopacity="0.0"
+   inkscape:pagecheckerboard="0"
+   inkscape:deskcolor="#d1d1d1"
+   showgrid="false"
+   inkscape:zoom="45.387417"
+   inkscape:cx="9.088422"
+   inkscape:cy="7.7113884"
+   inkscape:window-width="2560"
+   inkscape:window-height="1377"
+   inkscape:window-x="-8"
+   inkscape:window-y="-8"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="svg698" />
+    <g
+   transform="matrix(1,0,0,1,-2,-2)"
+   id="g692">
+        <rect
+   x="0"
+   y="0"
+   width="20"
+   height="20"
+   style="fill-opacity:0;"
+   id="rect690" />
+    </g>
+    <g
+   transform="matrix(1,0,0,1,-314,-42.0002)"
+   id="g696">
+        <path
+   id="path694"
+   d="M 322 43.0002 C 321.63375 43.0002 321.2668 43.028638 320.9043 43.086137 C 320.6983 43.689137 320.58822 44.310466 320.57422 44.947466 C 320.17722 45.059466 319.79555 45.217169 319.43555 45.418169 C 318.97455 44.978169 318.45872 44.617137 317.88672 44.336137 C 317.29172 44.768137 316.76989 45.291919 316.33789 45.886919 C 316.61889 46.458918 316.97992 46.974747 317.41992 47.435747 C 317.21892 47.795747 317.05927 48.177419 316.94727 48.574419 C 316.31027 48.588419 315.68894 48.698497 315.08594 48.904497 C 314.97094 49.629496 314.97094 50.370904 315.08594 51.095903 C 315.68894 51.301903 316.31027 51.410028 316.94727 51.424028 C 317.05927 51.821028 317.21892 52.204653 317.41992 52.564653 C 316.97992 53.025653 316.61889 53.541482 316.33789 54.113481 C 316.76989 54.708481 317.29172 55.23031 317.88672 55.662309 C 318.45872 55.38131 318.97455 55.020278 319.43555 54.580278 C 319.79555 54.781278 320.17722 54.940934 320.57422 55.052934 C 320.58822 55.689934 320.6983 56.311263 320.9043 56.914262 C 321.6293 57.029262 322.3707 57.029262 323.0957 56.914262 C 323.3017 56.311263 323.41178 55.689934 323.42578 55.052934 C 323.82278 54.940934 324.20445 54.781278 324.56445 54.580278 C 325.02545 55.020278 325.54128 55.38131 326.11328 55.662309 C 326.70828 55.23031 327.23011 54.708481 327.66211 54.113481 C 327.38111 53.541482 327.02008 53.025653 326.58008 52.564653 C 326.78108 52.204653 326.94073 51.821028 327.05273 51.424028 C 327.68973 51.410028 328.31106 51.301903 328.91406 51.095903 C 329.02906 50.370904 329.02906 49.629496 328.91406 48.904497 C 328.31106 48.698497 327.68973 48.588419 327.05273 48.574419 C 326.94073 48.177419 326.78108 47.795747 326.58008 47.435747 C 327.02008 46.974747 327.38111 46.458918 327.66211 45.886919 C 327.23011 45.291919 326.70828 44.768137 326.11328 44.336137 C 325.54128 44.617137 325.02545 44.978169 324.56445 45.418169 C 324.20445 45.217169 323.82278 45.059466 323.42578 44.947466 C 323.41178 44.310466 323.3017 43.689137 323.0957 43.086137 C 322.7332 43.028638 322.36625 43.0002 322 43.0002 z M 322 46.074419 A 3.9262602 3.9262602 0 0 1 325.92578 50.0002 A 3.9262602 3.9262602 0 0 1 322 53.925981 A 3.9262602 3.9262602 0 0 1 318.07422 50.0002 A 3.9262602 3.9262602 0 0 1 322 46.074419 z " />
+    </g>
+<path
+   d="M 6.2228883,7.0365135 7.5149871,8.2801072 9.6224346,6.1458198 C 9.7917107,5.9742561 9.8969365,5.8358614 10.106244,6.0508879 l 0.675961,0.6919731 c 0.223032,0.2196017 0.210451,0.3477027 0.0011,0.5512923 L 7.9015784,10.130708 c -0.4414906,0.432341 -0.363715,0.458647 -0.8120681,0.01487 L 5.0848502,8.1528185 C 4.9922058,8.0521673 5.001356,7.950373 5.1031504,7.8485786 L 5.8877683,7.0342228 c 0.1178071,-0.1223817 0.212739,-0.1143761 0.3351211,0.00227 z"
+   style="clip-rule:evenodd;fill-rule:evenodd;stroke-width:1"
+   id="path2565"
+   sodipodi:nodetypes="ccccccccccccc" /></svg>
diff --git a/toonz/sources/toonz/iocommand.cpp b/toonz/sources/toonz/iocommand.cpp
index 14cfb28..d6c8744 100644
--- a/toonz/sources/toonz/iocommand.cpp
+++ b/toonz/sources/toonz/iocommand.cpp
@@ -22,6 +22,7 @@
 #include "xdtsio.h"
 #include "expressionreferencemanager.h"
 #include "levelcommand.h"
+#include "columncommand.h"
 
 // TnzTools includes
 #include "tools/toolhandle.h"
@@ -1200,7 +1201,6 @@ inline TPaletteP dirtyWhite(const TPaletteP &plt) {
   return out;
 }
 
-//---------------------------------------------------------------------------
 }  // namespace
 //---------------------------------------------------------------------------
 
@@ -2088,6 +2088,11 @@ bool IoCmd::loadScene(const TFilePath &path, bool updateRecentFile,
     }
   }
 
+  // Check if any column has visibility toggles with different states and the
+  // "unify visibility toggles" option is enabled
+  if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+    ColumnCmd::unifyColumnVisibilityToggles();
+
   // caching raster levels
   int cacheRasterBehavior =
       Preferences::instance()->getRasterLevelCachingBehavior();
diff --git a/toonz/sources/toonz/layerheaderpanel.cpp b/toonz/sources/toonz/layerheaderpanel.cpp
index d7b922c..b188fb6 100644
--- a/toonz/sources/toonz/layerheaderpanel.cpp
+++ b/toonz/sources/toonz/layerheaderpanel.cpp
@@ -66,7 +66,8 @@ void LayerHeaderPanel::paintEvent(QPaintEvent *event) {
                          : m_viewer->getLayerHeaderLockImage());
 
   drawIcon(p, PredefinedRect::PANEL_EYE, boost::none, preview);
-  drawIcon(p, PredefinedRect::PANEL_PREVIEW_LAYER, boost::none, camstand);
+  if (!Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+    drawIcon(p, PredefinedRect::PANEL_PREVIEW_LAYER, boost::none, camstand);
   drawIcon(p, PredefinedRect::PANEL_LOCK, boost::none, lock);
 }
 
diff --git a/toonz/sources/toonz/ocaio.cpp b/toonz/sources/toonz/ocaio.cpp
index e3692cd..51e5dc7 100644
--- a/toonz/sources/toonz/ocaio.cpp
+++ b/toonz/sources/toonz/ocaio.cpp
@@ -479,12 +479,14 @@ void ExportOCACommand::execute() {
   QDir saveDir(ocafolder);
 
   if (!saveFile.open(QIODevice::WriteOnly)) {
-    qWarning("Couldn't open save file.");
+    progressDialog->close();
+    DVGui::error(QObject::tr("Unable to open OCA file for saving."));
     return;
   }
   if (!saveDir.exists()) {
-    if (!saveDir.mkdir(".")) {
-      qWarning("Couldn't create folder.");
+    if (!saveDir.mkpath(".")) {
+      progressDialog->close();
+      DVGui::error(QObject::tr("Unable to create folder for saving layers."));
       return;
     }
   }
@@ -494,6 +496,7 @@ void ExportOCACommand::execute() {
   ocaData.build(scene, xsheet, QString::fromStdString(fp.getName()), ocafolder,
                 frameOffset, exrImageFmt, !rasterVecs);
   if (ocaData.isEmpty()) {
+    progressDialog->close();
     DVGui::error(QObject::tr("No columns can be exported."));
     return;
   }
diff --git a/toonz/sources/toonz/pane.cpp b/toonz/sources/toonz/pane.cpp
index 2f2662f..43e8f5b 100644
--- a/toonz/sources/toonz/pane.cpp
+++ b/toonz/sources/toonz/pane.cpp
@@ -34,6 +34,7 @@
 #include <QDesktopWidget>
 #include <QDialog>
 #include <QLineEdit>
+#include <QTextEdit>
 #include <QScreen>
 
 extern TEnv::StringVar EnvSafeAreaName;
@@ -123,7 +124,8 @@ void TPanel::enterEvent(QEvent *event) {
   if (w) {
     // grab the focus, unless a line-edit is focused currently
     QWidget *focusWidget = qApp->focusWidget();
-    if (focusWidget && dynamic_cast<QLineEdit *>(focusWidget)) {
+    if (focusWidget && (dynamic_cast<QLineEdit *>(focusWidget) ||
+                        dynamic_cast<QTextEdit *>(focusWidget))) {
       event->accept();
       return;
     }
diff --git a/toonz/sources/toonz/penciltestpopup.cpp b/toonz/sources/toonz/penciltestpopup.cpp
index 84e6a94..a96098e 100644
--- a/toonz/sources/toonz/penciltestpopup.cpp
+++ b/toonz/sources/toonz/penciltestpopup.cpp
@@ -124,6 +124,7 @@ TEnv::IntVar CamCapDoCalibration("CamCapDoCalibration", 0);
 TEnv::RectVar CamCapSubCameraRect("CamCapSubCameraRect", TRect());
 TEnv::IntVar CamCapDoAutoDpi("CamCapDoAutoDpi", 1);
 TEnv::DoubleVar CamCapCustomDpi("CamCapDpiForNewLevel", 120.0);
+TEnv::StringVar CamCapFileType("CamCapFileType", "jpg");
 
 namespace {
 
@@ -433,6 +434,38 @@ protected:
   }
 };
 
+// https://stackoverflow.com/a/50848100/6622587
+cv::Mat QImageToMat(const QImage& image) {
+  cv::Mat out;
+  switch (image.format()) {
+  case QImage::Format_Invalid: {
+    cv::Mat empty;
+    empty.copyTo(out);
+    break;
+  }
+  case QImage::Format_RGB32: {
+    cv::Mat view(image.height(), image.width(), CV_8UC4,
+                 (void*)image.constBits(), image.bytesPerLine());
+    view.copyTo(out);
+    break;
+  }
+  case QImage::Format_RGB888: {
+    cv::Mat view(image.height(), image.width(), CV_8UC3,
+                 (void*)image.constBits(), image.bytesPerLine());
+    cv::cvtColor(view, out, cv::COLOR_RGB2BGR);
+    break;
+  }
+  default: {
+    QImage conv = image.convertToFormat(QImage::Format_ARGB32);
+    cv::Mat view(conv.height(), conv.width(), CV_8UC4, (void*)conv.constBits(),
+                 conv.bytesPerLine());
+    view.copyTo(out);
+    break;
+  }
+  }
+  return out;
+}
+
 }  // namespace
 
 //=============================================================================
@@ -1556,8 +1589,9 @@ PencilTestPopup::PencilTestPopup()
   m_saveOnCaptureCB =
       new QCheckBox(tr("Save images as they are captured"), this);
 
-  QGroupBox* imageFrame = new QGroupBox(tr("Image adjust"), this);
-  m_colorTypeCombo      = new QComboBox(this);
+  QGroupBox* imageFrame        = new QGroupBox(tr("Image adjust"), this);
+  m_colorTypeCombo             = new QComboBox(this);
+  m_saveImgAdjustDefaultButton = new QPushButton(this);
 
   m_camCapLevelControl = new CameraCaptureLevelControl(this);
   m_upsideDownCB       = new QCheckBox(tr("Upside down"), this);
@@ -1610,7 +1644,7 @@ PencilTestPopup::PencilTestPopup()
 
   m_resolutionCombo->setMaximumWidth(fontMetrics().width("0000 x 0000") + 25);
   m_fileTypeCombo->addItems({"jpg", "png", "tga", "tif"});
-  m_fileTypeCombo->setCurrentIndex(0);
+  m_fileTypeCombo->setCurrentText(QString::fromStdString(CamCapFileType));
 
   fileFrame->setObjectName("CleanupSettingsFrame");
   m_frameNumberEdit->setObjectName("LargeSizedText");
@@ -1627,6 +1661,11 @@ PencilTestPopup::PencilTestPopup()
   m_colorTypeCombo->addItems(
       {tr("Color"), tr("Grayscale"), tr("Black & White")});
   m_colorTypeCombo->setCurrentIndex(0);
+  m_saveImgAdjustDefaultButton->setFixedSize(24, 24);
+  m_saveImgAdjustDefaultButton->setIconSize(QSize(16, 16));
+  m_saveImgAdjustDefaultButton->setIcon(createQIcon("gear_check"));
+  m_saveImgAdjustDefaultButton->setToolTip(
+      tr("Save Current Image Adjust Parameters As Default"));
   m_upsideDownCB->setChecked(false);
 
   m_bgReductionFld->setRange(0, 100);
@@ -1824,6 +1863,8 @@ PencilTestPopup::PencilTestPopup()
           imageLay->addWidget(new QLabel(tr("Color type:"), this), 0, 0,
                               Qt::AlignRight);
           imageLay->addWidget(m_colorTypeCombo, 0, 1);
+          imageLay->addWidget(m_saveImgAdjustDefaultButton, 0, 2,
+                              Qt::AlignRight);
 
           imageLay->addWidget(m_camCapLevelControl, 1, 0, 1, 3);
 
@@ -1918,6 +1959,8 @@ PencilTestPopup::PencilTestPopup()
                        SLOT(onPreviousName()));
   ret = ret && connect(m_colorTypeCombo, SIGNAL(currentIndexChanged(int)), this,
                        SLOT(onColorTypeComboChanged(int)));
+  ret = ret && connect(m_saveImgAdjustDefaultButton, SIGNAL(pressed()), this,
+                       SLOT(saveImageAdjustDefault()));
   ret = ret && connect(m_captureWhiteBGButton, SIGNAL(pressed()), this,
                        SLOT(onCaptureWhiteBGButtonPressed()));
   ret = ret && connect(m_onionSkinGBox, SIGNAL(toggled(bool)), this,
@@ -1942,8 +1985,12 @@ PencilTestPopup::PencilTestPopup()
                        SLOT(openSaveInFolderPopup()));
   ret = ret && connect(m_saveInFileFld, SIGNAL(pathChanged()), this,
                        SLOT(onSaveInPathEdited()));
-  ret = ret && connect(m_fileTypeCombo, SIGNAL(activated(int)), this,
-                       SLOT(refreshFrameInfo()));
+  ret = ret &&
+        connect(m_fileTypeCombo, QOverload<int>::of(&QComboBox::activated),
+                [&](int index) {
+                  CamCapFileType = m_fileTypeCombo->currentText().toStdString();
+                  refreshFrameInfo();
+                });
   ret = ret && connect(m_frameNumberEdit, SIGNAL(editingFinished()), this,
                        SLOT(refreshFrameInfo()));
 
@@ -2040,6 +2087,9 @@ PencilTestPopup::PencilTestPopup()
         m_videoWidget->setImage(dummyImg);
         m_subcameraButton->setChecked(true);
       }
+
+      // try loading the default parameter
+      loadImageAdjustDefault();
     }
   }
 
@@ -3466,6 +3516,13 @@ void PencilTestPopup::onSaveInPathEdited() {
 
 //-----------------------------------------------------------------------------
 
+void PencilTestPopup::onFileTypeChanged() {
+  CamCapFileType = m_fileTypeCombo->currentText().toStdString();
+  refreshFrameInfo();
+}
+
+//-----------------------------------------------------------------------------
+
 void PencilTestPopup::onSceneSwitched() {
   m_saveInFolderPopup->updateParentFolder();
   m_saveInFileFld->setPath(m_saveInFolderPopup->getParentPath());
@@ -3616,14 +3673,33 @@ void PencilTestPopup::resetCalibSettingsFromFile() {
 
 //-----------------------------------------------------------------------------
 
-QString PencilTestPopup::getCurrentCalibFilePath() {
+QString PencilTestPopup::getCameraConfigurationPath(const QString& folderName,
+                                                    const QString& ext) {
   QString cameraName = m_cameraListCombo->currentText();
   if (cameraName.isEmpty()) return QString();
   QString resolution   = m_resolutionCombo->currentText();
   QString hostName     = QHostInfo::localHostName();
-  TFilePath folderPath = ToonzFolder::getLibraryFolder() + "camera calibration";
-  return folderPath.getQString() + "\\" + hostName + "_" + cameraName + "_" +
-         resolution + ".xml";
+  TFilePath folderPath = ToonzFolder::getLibraryFolder();
+  return folderPath.getQString() + "\\" + folderName + "\\" + hostName + "_" +
+         cameraName + "_" + resolution + "." + ext;
+}
+
+//-----------------------------------------------------------------------------
+
+QString PencilTestPopup::getCurrentCalibFilePath() {
+  return getCameraConfigurationPath("camera calibration", "xml");
+}
+
+//-----------------------------------------------------------------------------
+
+QString PencilTestPopup::getImageAdjustSettingsPath() {
+  return getCameraConfigurationPath("camera image adjust", "ini");
+}
+
+//-----------------------------------------------------------------------------
+
+QString PencilTestPopup::getImageAdjustBgImgPath() {
+  return getCameraConfigurationPath("camera image adjust", "jpg");
 }
 
 //-----------------------------------------------------------------------------
@@ -3789,6 +3865,80 @@ void PencilTestPopup::onPreferenceChanged(const QString& prefName) {
 }
 
 //-----------------------------------------------------------------------------
+// called in ctor
+void PencilTestPopup::loadImageAdjustDefault() {
+  // find the configuration file
+  QString settingsPath = getImageAdjustSettingsPath();
+  if (!TFileStatus(TFilePath(settingsPath)).doesExist()) return;
+
+  QSettings imgAdjSettings(settingsPath, QSettings::IniFormat);
+  int colorType   = imgAdjSettings.value("ColorType", 0).toInt();
+  int black       = imgAdjSettings.value("BlackLevel", 0).toInt();
+  int white       = imgAdjSettings.value("WhiteLevel", 255).toInt();
+  double gamma    = imgAdjSettings.value("Gamma", 1.0).toDouble();
+  int threshold   = imgAdjSettings.value("Threshold", 128).toInt();
+  bool upsideDown = imgAdjSettings.value("UpsideDown", false).toBool();
+  int bgReduction = imgAdjSettings.value("BgReduction", 0).toInt();
+
+  m_colorTypeCombo->setCurrentIndex(colorType);
+  m_camCapLevelControl->setValues(black, white, threshold, gamma,
+                                  colorType != 2);
+  m_upsideDownCB->setChecked(upsideDown);
+  m_bgReductionFld->setValue(bgReduction);
+
+  QString bgPath = getImageAdjustBgImgPath();
+  if (!TFileStatus(TFilePath(bgPath)).doesExist()) {
+    if (bgReduction > 0)
+      warning(
+          tr("BG Reduction is set but the White BG image is missing. Please "
+             "capture the White BG again."));
+
+    m_whiteBGImg = cv::Mat();
+    m_bgReductionFld->setDisabled(true);
+    return;
+  }
+
+  QImage bgImg(bgPath);
+  if (bgImg.isNull()) {
+    m_whiteBGImg = cv::Mat();
+    m_bgReductionFld->setDisabled(true);
+    return;
+  }
+  cv::Mat tmpMat = QImageToMat(bgImg);
+  cv::cvtColor(tmpMat, m_whiteBGImg, cv::COLOR_RGBA2RGB);
+  m_bgReductionFld->setEnabled(true);
+}
+
+//-----------------------------------------------------------------------------
+
+void PencilTestPopup::saveImageAdjustDefault() {
+  QString question =
+      tr("Do you want to save the current parameters as the default values?");
+  int ret = DVGui::MsgBox(question, QObject::tr("Save"), QObject::tr("Cancel"));
+  if (ret == 0 || ret == 2) return;
+
+  QString settingsPath = getImageAdjustSettingsPath();
+  QSettings imgAdjSettings(settingsPath, QSettings::IniFormat);
+
+  imgAdjSettings.setValue("ColorType", m_colorTypeCombo->currentIndex());
+  int black, white, threshold;
+  double gamma;
+  m_camCapLevelControl->getValues(black, white, threshold, gamma);
+  imgAdjSettings.setValue("BlackLevel", black);
+  imgAdjSettings.setValue("WhiteLevel", white);
+  imgAdjSettings.setValue("Gamma", gamma);
+  imgAdjSettings.setValue("Threshold", threshold);
+  imgAdjSettings.setValue("UpsideDown", m_upsideDownCB->isChecked());
+  imgAdjSettings.setValue("BgReduction", m_bgReductionFld->getValue());
+
+  if (!m_whiteBGImg.empty()) {
+    QImage qimg(m_whiteBGImg.data, m_whiteBGImg.cols, m_whiteBGImg.rows,
+                QImage::Format_RGB888);
+    qimg.save(getImageAdjustBgImgPath());
+  }
+}
+
+//-----------------------------------------------------------------------------
 
 OpenPopupCommandHandler<PencilTestPopup> openPencilTestPopup(MI_PencilTest);
 
diff --git a/toonz/sources/toonz/penciltestpopup.h b/toonz/sources/toonz/penciltestpopup.h
index 60fe140..397cb97 100644
--- a/toonz/sources/toonz/penciltestpopup.h
+++ b/toonz/sources/toonz/penciltestpopup.h
@@ -271,7 +271,7 @@ class PencilTestPopup : public DVGui::Dialog {
   QCheckBox *m_upsideDownCB, *m_saveOnCaptureCB;
   QGroupBox *m_onionSkinGBox, *m_timerGBox;
   QPushButton *m_fileFormatOptionButton, *m_captureWhiteBGButton,
-      *m_captureButton, *m_loadImageButton;
+      *m_captureButton, *m_loadImageButton, *m_saveImgAdjustDefaultButton;
   DVGui::FileField* m_saveInFileFld;
   FrameNumberLineEdit* m_frameNumberEdit;
   DVGui::IntField *m_bgReductionFld, *m_onionOpacityFld, *m_timerIntervalFld;
@@ -341,8 +341,13 @@ class PencilTestPopup : public DVGui::Dialog {
   QMenu* createOptionsMenu();
 
   int translateIndex(int camIndex);
+  void loadImageAdjustDefault();
 
   QString getCurrentCalibFilePath();
+  QString getImageAdjustSettingsPath();
+  QString getImageAdjustBgImgPath();
+  QString getCameraConfigurationPath(const QString& folderName,
+                                     const QString& ext);
 
   QWidget* createDpiMenuWidget();
 
@@ -381,6 +386,7 @@ protected slots:
   void refreshFrameInfo();
 
   void onSaveInPathEdited();
+  void onFileTypeChanged();
   void onSceneSwitched();
 
   void onSubCameraToggled(bool);
@@ -398,6 +404,8 @@ protected slots:
   void onCalibReadme();
   void onPreferenceChanged(const QString&);
 
+  void saveImageAdjustDefault();
+
 public slots:
   void openSaveInFolderPopup();
 };
diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp
index e0199df..9e8ef56 100644
--- a/toonz/sources/toonz/preferencespopup.cpp
+++ b/toonz/sources/toonz/preferencespopup.cpp
@@ -9,6 +9,7 @@
 #include "tapp.h"
 #include "cleanupsettingsmodel.h"
 #include "formatsettingspopups.h"
+#include "columncommand.h"
 
 // TnzQt includes
 #include "toonzqt/tabbar.h"
@@ -679,6 +680,18 @@ void PreferencesPopup::onShowXSheetToolbarClicked() {
 
 //-----------------------------------------------------------------------------
 
+void PreferencesPopup::onUnifyColumnVisibilityTogglesChanged() {
+  // Check if any column has visibility toggles with different states and the
+  // "unify visibility toggles" option is enabled
+  if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+    ColumnCmd::unifyColumnVisibilityToggles();
+
+  TApp::instance()->getCurrentScene()->notifyPreferenceChanged(
+      "unifyColumnVisibilityToggles");
+}
+
+//-----------------------------------------------------------------------------
+
 void PreferencesPopup::onModifyExpressionOnMovingReferencesChanged() {
   TApp::instance()->getCurrentScene()->notifyPreferenceChanged(
       "modifyExpressionOnMovingReferences");
@@ -1279,6 +1292,8 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
       {expandFunctionHeader,
        tr("Expand Function Editor Header to Match Xsheet Toolbar Height*")},
       {showColumnNumbers, tr("Show Column Numbers in Column Headers")},
+      {unifyColumnVisibilityToggles,
+       tr("Unify Preview and Camstand Visibility Toggles")},
       {parentColorsInXsheetColumn,
        tr("Show Column Parent's Color in the Xsheet")},
       {highlightLineEverySecond, tr("Highlight Line Every Second")},
@@ -1291,6 +1306,7 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) {
       {levelNameDisplayType, tr("Level Name Display:")},
       {showFrameNumberWithLetters,
        tr("Show \"ABC\" Appendix to the Frame Number in Xsheet Cell")},
+      {linkColumnNameWithLevel, tr("Link Column Name with Level")},
 
       // Animation
       {keyframeType, tr("Default Interpolation:")},
@@ -1432,7 +1448,9 @@ QList<ComboBoxItem> PreferencesPopup::getComboItemList(
         {tr("Display on Column Header"),
          Preferences::ShowLevelNameOnColumnHeader}}},
       {DragCellsBehaviour,
-       {{tr("Cells Only"), 0}, {tr("Cells and Column Data"), 1}}},
+       {{tr("Cells Only"), 0},
+        {tr("Cells and Column Data"), 1},
+        {tr("Disable Dragging Cells"), 2}}},
       {deleteCommandBehavior,
        {{tr("Clear Cell / Frame"), 0},
         {tr("Remove and Shift Cells / Frames Up"), 1}}},
@@ -1998,6 +2016,7 @@ QWidget* PreferencesPopup::createXsheetPage() {
   insertUI(xsheetLayoutPreference, lay,
            getComboItemList(xsheetLayoutPreference));
   insertUI(levelNameDisplayType, lay, getComboItemList(levelNameDisplayType));
+  insertUI(linkColumnNameWithLevel, lay);
   insertUI(xsheetStep, lay);
   insertUI(xsheetAutopanEnabled, lay);
   insertUI(DragCellsBehaviour, lay, getComboItemList(DragCellsBehaviour));
@@ -2013,6 +2032,7 @@ QWidget* PreferencesPopup::createXsheetPage() {
   QGridLayout* xshToolbarLay = insertGroupBoxUI(showXSheetToolbar, lay);
   { insertUI(expandFunctionHeader, xshToolbarLay); }
   insertUI(showColumnNumbers, lay);
+  insertUI(unifyColumnVisibilityToggles, lay);
   insertUI(parentColorsInXsheetColumn, lay);
   insertUI(highlightLineEverySecond, lay);
   insertUI(syncLevelRenumberWithXsheet, lay);
@@ -2028,7 +2048,19 @@ QWidget* PreferencesPopup::createXsheetPage() {
                            &PreferencesPopup::onShowKeyframesOnCellAreaChanged);
   m_onEditedFuncMap.insert(showXsheetCameraColumn,
                            &PreferencesPopup::onShowKeyframesOnCellAreaChanged);
-
+  m_onEditedFuncMap.insert(
+      unifyColumnVisibilityToggles,
+      &PreferencesPopup::onUnifyColumnVisibilityTogglesChanged);
+
+  QCheckBox* linkColumnNameWithLevelCheck =
+      getUI<QCheckBox*>(linkColumnNameWithLevel);
+  linkColumnNameWithLevelCheck->setToolTip(
+      tr("This option will do the following:\n"
+         "- When setting a cell in the empty column, level name will be copied "
+         "to the column name\n"
+         "- Typing the cell without level name in the empty column will try to "
+         "use a level with the same name as the column\n"
+         "The behavior may be changed in the future development."));
   return widget;
 }
 
diff --git a/toonz/sources/toonz/preferencespopup.h b/toonz/sources/toonz/preferencespopup.h
index c1e1e1e..de08a94 100644
--- a/toonz/sources/toonz/preferencespopup.h
+++ b/toonz/sources/toonz/preferencespopup.h
@@ -139,6 +139,7 @@ private:
   // Xsheet
   void onShowKeyframesOnCellAreaChanged();
   void onShowXSheetToolbarClicked();
+  void onUnifyColumnVisibilityTogglesChanged();
   // Animation
   void onModifyExpressionOnMovingReferencesChanged();
   // Preview
diff --git a/toonz/sources/toonz/toonz.qrc b/toonz/sources/toonz/toonz.qrc
index dad7582..5070c00 100644
--- a/toonz/sources/toonz/toonz.qrc
+++ b/toonz/sources/toonz/toonz.qrc
@@ -76,7 +76,8 @@
 		<file>icons/dark/actions/16/save.svg</file>
 		<file>icons/dark/actions/16/saveas.svg</file>
 		<file>icons/dark/actions/16/saveall.svg</file>
-		<file>icons/dark/actions/16/gear.svg</file>
+    <file>icons/dark/actions/16/gear.svg</file>
+    <file>icons/dark/actions/16/gear_check.svg</file>
 		<file>icons/dark/actions/16/settings_reset.svg</file>
 		<file>icons/dark/actions/16/clear.svg</file>
 		<file>icons/dark/actions/16/undo.svg</file>
diff --git a/toonz/sources/toonz/tpanels.cpp b/toonz/sources/toonz/tpanels.cpp
index 00889eb..bf8e406 100644
--- a/toonz/sources/toonz/tpanels.cpp
+++ b/toonz/sources/toonz/tpanels.cpp
@@ -266,6 +266,13 @@ void SchematicScenePanel::onColumnPaste(const QList<TXshColumnP> &columns) {
 
 //-----------------------------------------------------------------------------
 
+void SchematicScenePanel::onPreferenceChanged(const QString &prefName) {
+  if (prefName == "unifyColumnVisibilityToggles")
+    m_schematicViewer->updateSchematic();
+}
+
+//-----------------------------------------------------------------------------
+
 void SchematicScenePanel::showEvent(QShowEvent *e) {
   if (m_schematicViewer->isStageSchematicViewed())
     setWindowTitle(QObject::tr("Stage Schematic"));
@@ -299,6 +306,8 @@ void SchematicScenePanel::showEvent(QShowEvent *e) {
           SLOT(updateSchematic()));
   connect(app->getCurrentScene(), SIGNAL(sceneSwitched()), m_schematicViewer,
           SLOT(onSceneSwitched()));
+  connect(app->getCurrentScene(), SIGNAL(preferenceChanged(const QString &)),
+          this, SLOT(onPreferenceChanged(const QString &)));
   connect(m_schematicViewer, SIGNAL(columnPasted(const QList<TXshColumnP> &)),
           this, SLOT(onColumnPaste(const QList<TXshColumnP> &)));
   m_schematicViewer->updateSchematic();
@@ -330,6 +339,8 @@ void SchematicScenePanel::hideEvent(QHideEvent *e) {
              m_schematicViewer, SLOT(updateSchematic()));
   disconnect(app->getCurrentScene(), SIGNAL(sceneSwitched()), m_schematicViewer,
              SLOT(onSceneSwitched()));
+  disconnect(app->getCurrentScene(), SIGNAL(preferenceChanged(const QString &)),
+             this, SLOT(onPreferenceChanged(const QString &)));
   disconnect(m_schematicViewer,
              SIGNAL(columnPasted(const QList<TXshColumnP> &)), this,
              SLOT(onColumnPaste(const QList<TXshColumnP> &)));
diff --git a/toonz/sources/toonz/tpanels.h b/toonz/sources/toonz/tpanels.h
index c06bc53..1102944 100644
--- a/toonz/sources/toonz/tpanels.h
+++ b/toonz/sources/toonz/tpanels.h
@@ -193,6 +193,7 @@ protected slots:
   void onDeleteFxs(const FxSelection *);
   void onDeleteStageObjects(const StageObjectSelection *);
   void onColumnPaste(const QList<TXshColumnP> &);
+  void onPreferenceChanged(const QString &);
 };
 
 //=========================================================
diff --git a/toonz/sources/toonz/xshcellviewer.cpp b/toonz/sources/toonz/xshcellviewer.cpp
index bf27a8b..2666bd5 100644
--- a/toonz/sources/toonz/xshcellviewer.cpp
+++ b/toonz/sources/toonz/xshcellviewer.cpp
@@ -76,7 +76,8 @@
 
 namespace {
 
-const bool checkContainsSingleLevel(TXshColumn *column) {
+const bool checkContainsSingleLevel(TXshColumn *column,
+                                    const std::string &columnName) {
   TXshLevel *level           = nullptr;
   TXshCellColumn *cellColumn = column->getCellColumn();
   if (cellColumn) {
@@ -91,7 +92,9 @@ const bool checkContainsSingleLevel(TXshColumn *column) {
       else if (lvl != level)
         return false;
     }
-    return level != nullptr;
+    // column name should be unspecified or same as the content level
+    return level != nullptr &&
+           (columnName.empty() || level->getName() == to_wstring(columnName));
   }
   return false;
 }
@@ -856,6 +859,26 @@ void RenameCellField::renameCell() {
       // previous frames
       // (when editing not empty column)
       if (xsheet->isColumnEmpty(c)) {
+        // find a level with name same as the column (if the preferences option
+        // is set to do so)
+        if (Preferences::instance()->isLinkColumnNameWithLevelEnabled() &&
+            xsheet->getStageObject(TStageObjectId::ColumnId(c))
+                ->hasSpecifiedName()) {
+          std::string columnName =
+              xsheet->getStageObject(TStageObjectId::ColumnId(c))->getName();
+          TLevelSet *levelSet = scene->getLevelSet();
+          TXshLevel *xl       = levelSet->getLevel(to_wstring(columnName));
+          TXshSimpleLevel *sl = (xl) ? xl->getSimpleLevel() : nullptr;
+          if (sl &&
+              (!sl->isEmpty() || sl->getFirstFid() != TFrameId::NO_FRAME)) {
+            sl->formatFId(fid, tmplFId);
+            cells.append(TXshCell(xl, fid));
+            changed      = true;
+            hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() &&
+                            xl->getSimpleLevel()->isFid(fid));
+            continue;
+          }
+        }
         cells.append(TXshCell());
         continue;
       }
@@ -1270,10 +1293,16 @@ void CellArea::drawCells(QPainter &p, const QRect toBeUpdated) {
       isPaletteColumn   = column->getPaletteColumn() != 0;
       isSoundTextColumn = column->getSoundTextColumn() != 0;
       if (Preferences::instance()->getLevelNameDisplayType() ==
-          Preferences::ShowLevelNameOnColumnHeader)
+          Preferences::ShowLevelNameOnColumnHeader) {
+        std::string columnName = "";
+        if (col >= 0 && xsh->getStageObject(TStageObjectId::ColumnId(col))
+                            ->hasSpecifiedName())
+          columnName =
+              xsh->getStageObject(TStageObjectId::ColumnId(col))->getName();
         showLevelName =
             (isSoundColumn || isPaletteColumn || isSoundTextColumn ||
-             !checkContainsSingleLevel(column));
+             !checkContainsSingleLevel(column, columnName));
+      }
     }
     // check if the column is reference
     bool isReference = true;
@@ -1413,6 +1442,9 @@ void CellArea::drawExtenderHandles(QPainter &p) {
   TCellSelection *cellSelection = m_viewer->getCellSelection();
   if (cellSelection->isEmpty() || m_viewer->areSoundCellsSelected()) return;
 
+  // if the drag move is disabled, the extender handles won't appear
+  if (Preferences::instance()->getDragCellsBehaviour() == 2) return;
+
   int selRow0, selCol0, selRow1, selCol1;
   cellSelection->getSelectedCells(selRow0, selCol0, selRow1, selCol1);
 
@@ -3332,7 +3364,7 @@ void CellArea::mousePressEvent(QMouseEvent *event) {
       if (TCellKeyframeSelection *cellKeyframeSelection =
               dynamic_cast<TCellKeyframeSelection *>(selection))
         setDragTool(XsheetGUI::DragTool::makeCellKeyframeMoverTool(m_viewer));
-      else
+      else if (Preferences::instance()->getDragCellsBehaviour() != 2)
         setDragTool(XsheetGUI::DragTool::makeLevelMoverTool(m_viewer));
     } else {
       m_viewer->getKeyframeSelection()->selectNone();
diff --git a/toonz/sources/toonz/xshcolumnviewer.cpp b/toonz/sources/toonz/xshcolumnviewer.cpp
index d9e38f3..c3b0416 100644
--- a/toonz/sources/toonz/xshcolumnviewer.cpp
+++ b/toonz/sources/toonz/xshcolumnviewer.cpp
@@ -49,6 +49,7 @@
 #include "toonz/tfxhandle.h"
 #include "toonz/tcamera.h"
 #include "toonz/tcolumnhandle.h"
+#include "toonz/levelset.h"
 
 // TnzCore includes
 #include "tconvert.h"
@@ -707,12 +708,18 @@ void RenameColumnField::renameColumn() {
                                        : TStageObjectId::CameraId(cameraIndex);
   TXshColumn *column =
       m_xsheetHandle->getXsheet()->getColumn(columnId.getIndex());
+  if (!column && m_col >= 0) {
+    m_xsheetHandle->getXsheet()->insertColumn(m_col);
+    column = m_xsheetHandle->getXsheet()->getColumn(columnId.getIndex());
+  }
+
   TXshZeraryFxColumn *zColumn = dynamic_cast<TXshZeraryFxColumn *>(column);
   if (zColumn)
     TFxCommand::renameFx(zColumn->getZeraryColumnFx(), ::to_wstring(newName),
                          m_xsheetHandle);
   else
     TStageObjectCmd::rename(columnId, newName, m_xsheetHandle);
+
   m_xsheetHandle->notifyXsheetChanged();
   m_col = -1;
   setText("");
@@ -745,7 +752,7 @@ const bool ColumnArea::isControlPressed() { return isCtrlPressed; }
 //-----------------------------------------------------------------------------
 
 ColumnArea::DrawHeader::DrawHeader(ColumnArea *nArea, QPainter &nP, int nCol)
-    : area(nArea), p(nP), col(nCol) {
+    : area(nArea), p(nP), col(nCol), reservedLevel(nullptr) {
   m_viewer = area->m_viewer;
   o        = m_viewer->orientation();
   app      = TApp::instance();
@@ -753,6 +760,18 @@ ColumnArea::DrawHeader::DrawHeader(ColumnArea *nArea, QPainter &nP, int nCol)
   column   = xsh->getColumn(col);
   isEmpty  = col >= 0 ? xsh->isColumnEmpty(col) : false;
 
+  if (isEmpty && Preferences::instance()->isLinkColumnNameWithLevelEnabled() &&
+      m_viewer->getXsheet()
+          ->getStageObject(TStageObjectId::ColumnId(col))
+          ->hasSpecifiedName()) {
+    std::string columnName = m_viewer->getXsheet()
+                                 ->getStageObject(TStageObjectId::ColumnId(col))
+                                 ->getName();
+    ToonzScene *scene   = TApp::instance()->getCurrentScene()->getScene();
+    TLevelSet *levelSet = scene->getLevelSet();
+    reservedLevel       = levelSet->getLevel(to_wstring(columnName));
+  }
+
   TStageObjectId currentColumnId = app->getCurrentObject()->getObjectId();
 
   // check if the column is current
@@ -816,7 +835,11 @@ void ColumnArea::DrawHeader::levelColors(QColor &columnColor,
     if (column->isRendered() || column->getMeshColumn()) usage = Normal;
   }
 
-  if (usage == Reference) {
+  if (reservedLevel) {
+    int ltype;
+    m_viewer->getCellTypeAndColors(ltype, columnColor, dragColor,
+                                   TXshCell(reservedLevel, TFrameId()));
+  } else if (usage == Reference) {
     columnColor = m_viewer->getReferenceColumnColor();
     dragColor   = m_viewer->getReferenceColumnBorderColor();
   } else
@@ -859,15 +882,17 @@ void ColumnArea::DrawHeader::drawBaseFill(const QColor &columnColor,
 
   // Fill base color, in timeline view adjust it right upto thumbnail so column
   // head color doesn't show under icon switches.
-  if (isEmpty)
+  if (isEmpty && !reservedLevel)
     p.fillRect(o->isVerticalTimeline() ? rect : rect.adjusted(80, 0, 0, 0),
                m_viewer->getEmptyColumnHeadColor());
   else if (col < 0)
     p.fillRect(o->isVerticalTimeline() ? rect : rect.adjusted(80, 0, 0, 0),
                columnColor);
   else {
+    QBrush brush(columnColor,
+                 (reservedLevel) ? Qt::DiagCrossPattern : Qt::SolidPattern);
     p.fillRect(o->isVerticalTimeline() ? rect : rect.adjusted(80, 0, 0, 0),
-               columnColor);
+               brush);
 
     if (o->flag(PredefinedFlag::DRAG_LAYER_VISIBLE)) {
       // column handle
@@ -976,6 +1001,43 @@ void ColumnArea::DrawHeader::drawPreviewToggle(int opacity) const {
   p.drawImage(tableViewImgRect, icon);
 }
 
+// shows united visibility toggle, which has the same state as the camstand
+// toggle (preview toggle should synchonize with the camstand toggle)
+void ColumnArea::DrawHeader::drawUnifiedViewToggle(int opacity) const {
+  if (isEmpty || !o->flag(PredefinedFlag::PREVIEW_LAYER_AREA_VISIBLE)) return;
+  if (col < 0 && o->isVerticalTimeline())
+    return;  // no camstand toggle in the camera column
+  // camstand visible toggle
+  QColor bgColor;
+  QImage icon;
+  int buttonType = !column->isCamstandVisible() ? PREVIEW_OFF_XSHBUTTON
+                   : opacity < 255              ? UNIFIED_TRANSP_XSHBUTTON
+                                                : PREVIEW_ON_XSHBUTTON;
+  m_viewer->getButton(buttonType, bgColor, icon, !o->isVerticalTimeline());
+
+  QRect unifiedViewRect =
+      o->rect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA).translated(orig);
+  QRect unifiedViewImgRect =
+      o->rect(PredefinedRect::UNIFIEDVIEW_LAYER).translated(orig);
+
+  if (o->isVerticalTimeline())
+    p.setPen(m_viewer->getColumnIconLineColor());  // border color
+  else
+    p.setPen(m_viewer->getTimelineIconLineColor());  // border color
+
+  if (col < 0 || column->getPaletteColumn() || column->getSoundTextColumn()) {
+    if (o->flag(PredefinedFlag::PREVIEW_LAYER_AREA_BORDER))
+      p.drawRect(unifiedViewRect);
+    return;
+  }
+
+  p.fillRect(unifiedViewRect, bgColor);
+  if (o->flag(PredefinedFlag::PREVIEW_LAYER_AREA_BORDER))
+    p.drawRect(unifiedViewRect);
+
+  p.drawImage(unifiedViewImgRect, icon);
+}
+
 void ColumnArea::DrawHeader::drawLock() const {
   if (isEmpty || !o->flag(PredefinedFlag::LOCK_AREA_VISIBLE)) return;
   QColor bgColor;
@@ -1582,65 +1644,19 @@ void ColumnArea::drawFoldedColumnHead(QPainter &p, int col) {
 }
 
 void ColumnArea::drawLevelColumnHead(QPainter &p, int col) {
-  TColumnSelection *selection = m_viewer->getColumnSelection();
-  const Orientation *o        = m_viewer->orientation();
-
-  // Preparing painter
-  QString fontName = Preferences::instance()->getInterfaceFont();
-  if (fontName == "") {
-#ifdef _WIN32
-    fontName = "Arial";
-#else
-    fontName = "Helvetica";
-#endif
-  }
-  static QFont font(fontName, -1, QFont::Normal);
-  font.setPixelSize(XSHEET_FONT_PX_SIZE);
-
-  p.setFont(font);
-  p.setRenderHint(QPainter::SmoothPixmapTransform, true);
-
-  // Retrieve reference coordinates
-  int currentColumnIndex = m_viewer->getCurrentColumn();
-  int layerAxis          = m_viewer->columnToLayerAxis(col);
-
-  QPoint orig = m_viewer->positionToXY(CellPosition(0, col));
-  QRect rect  = o->rect(PredefinedRect::LAYER_HEADER).translated(orig);
-
-  TApp *app    = TApp::instance();
-  TXsheet *xsh = m_viewer->getXsheet();
-
-  TStageObjectId columnId        = m_viewer->getObjectId(col);
-  TStageObjectId currentColumnId = app->getCurrentObject()->getObjectId();
-  TStageObjectId parentId        = xsh->getStageObjectParent(columnId);
-
-  // Retrieve column properties
-  // Check if the column is empty
-  bool isEmpty       = col >= 0 && xsh->isColumnEmpty(col);
-  TXshColumn *column = col >= 0 ? xsh->getColumn(col) : 0;
-
-  bool isEditingSpline = app->getCurrentObject()->isSpline();
-
-  // check if the column is current
-  bool isCurrent = false;
-  if (currentColumnId ==
-      TStageObjectId::CameraId(xsh->getCameraColumnIndex()))  // CAMERA
-    isCurrent = col == -1;
-  else
-    isCurrent = m_viewer->getCurrentColumn() == col;
-
-  bool isSelected =
-      m_viewer->getColumnSelection()->isColumnSelected(col) && !isEditingSpline;
-  // bool isCameraSelected = col == -1 && isCurrent && !isEditingSpline;
-
+  TXshColumn *column = col >= 0 ? m_viewer->getXsheet()->getColumn(col) : 0;
   // Draw column
   DrawHeader drawHeader(this, p, col);
   drawHeader.prepare();
   QColor columnColor, dragColor;
   drawHeader.levelColors(columnColor, dragColor);
   drawHeader.drawBaseFill(columnColor, dragColor);
-  drawHeader.drawEye();
-  drawHeader.drawPreviewToggle(column ? column->getOpacity() : 0);
+  if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+    drawHeader.drawUnifiedViewToggle(column ? column->getOpacity() : 0);
+  else {
+    drawHeader.drawEye();
+    drawHeader.drawPreviewToggle(column ? column->getOpacity() : 0);
+  }
   drawHeader.drawLock();
   drawHeader.drawColumnName();
   drawHeader.drawColumnNumber();
@@ -1655,37 +1671,10 @@ void ColumnArea::drawLevelColumnHead(QPainter &p, int col) {
 //-----------------------------------------------------------------------------
 
 void ColumnArea::drawSoundColumnHead(QPainter &p, int col) {  // AREA
-  TColumnSelection *selection = m_viewer->getColumnSelection();
-  const Orientation *o        = m_viewer->orientation();
-
-  int x = m_viewer->columnToLayerAxis(col);
-
-  p.setRenderHint(QPainter::SmoothPixmapTransform, true);
-  QString fontName = Preferences::instance()->getInterfaceFont();
-  if (fontName == "") {
-#ifdef _WIN32
-    fontName = "Arial";
-#else
-    fontName = "Helvetica";
-#endif
-  }
-  static QFont font(fontName, -1, QFont::Normal);
-  font.setPixelSize(XSHEET_FONT_PX_SIZE);
-  p.setFont(font);
-
   TXsheet *xsh = m_viewer->getXsheet();
   TXshSoundColumn *sc =
       xsh->getColumn(col) ? xsh->getColumn(col)->getSoundColumn() : 0;
 
-  QPoint orig = m_viewer->positionToXY(CellPosition(0, col));
-  QRect rect  = m_viewer->orientation()
-                   ->rect(PredefinedRect::LAYER_HEADER)
-                   .translated(orig);
-
-  QPoint columnNamePos = orig + QPoint(12, o->cellHeight());
-
-  bool isCurrent = m_viewer->getCurrentColumn() == col;
-
   DrawHeader drawHeader(this, p, col);
   drawHeader.prepare();
   QColor columnColor, dragColor;
@@ -1710,36 +1699,6 @@ void ColumnArea::drawSoundColumnHead(QPainter &p, int col) {  // AREA
 //-----------------------------------------------------------------------------
 
 void ColumnArea::drawPaletteColumnHead(QPainter &p, int col) {  // AREA
-  TColumnSelection *selection = m_viewer->getColumnSelection();
-  const Orientation *o        = m_viewer->orientation();
-
-  QPoint orig = m_viewer->positionToXY(CellPosition(0, std::max(col, -1)));
-
-  QString fontName = Preferences::instance()->getInterfaceFont();
-  if (fontName == "") {
-#ifdef _WIN32
-    fontName = "Arial";
-#else
-    fontName = "Helvetica";
-#endif
-  }
-  static QFont font(fontName, -1, QFont::Normal);
-  font.setPixelSize(XSHEET_FONT_PX_SIZE);
-
-  p.setFont(font);
-  p.setRenderHint(QPainter::SmoothPixmapTransform, true);
-
-  int currentColumnIndex = m_viewer->getCurrentColumn();
-  int x                  = m_viewer->columnToLayerAxis(col);
-
-  QRect rect(x, 0, o->cellWidth(), height());
-
-  TXsheet *xsh = m_viewer->getXsheet();
-
-  bool isEmpty = false;
-  if (col >= 0)  // Verifico se la colonna e' vuota
-    isEmpty = xsh->isColumnEmpty(col);
-
   DrawHeader drawHeader(this, p, col);
   drawHeader.prepare();
   QColor columnColor, dragColor;
@@ -2417,8 +2376,27 @@ void ColumnArea::mousePressEvent(QMouseEvent *event) {
         if (event->button() != Qt::LeftButton) return;
         m_doOnRelease = isCtrlPressed ? ToggleAllLock : ToggleLock;
       }
-      // preview button
-      else if (o->rect(PredefinedRect::EYE_AREA).contains(mouseInCell)) {
+      // unified view button
+      else if (Preferences::instance()
+                   ->isUnifyColumnVisibilityTogglesEnabled() &&
+               o->rect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA)
+                   .contains(mouseInCell)) {
+        if (event->button() != Qt::LeftButton) return;
+        if (column->getSoundTextColumn()) {
+          // do nothing
+        } else {
+          // sync eye button on release
+          m_doOnRelease =
+              isCtrlPressed ? ToggleAllTransparency : ToggleTransparency;
+          if (!o->flag(PredefinedFlag::CONFIG_AREA_VISIBLE) &&
+              !column->getSoundColumn())
+            startTransparencyPopupTimer(event);
+        }
+      }
+      // separated view - preview button
+      else if (!Preferences::instance()
+                    ->isUnifyColumnVisibilityTogglesEnabled() &&
+               o->rect(PredefinedRect::EYE_AREA).contains(mouseInCell)) {
         if (event->button() != Qt::LeftButton) return;
         if (column->getSoundTextColumn()) {
           // do nothing
@@ -2429,8 +2407,10 @@ void ColumnArea::mousePressEvent(QMouseEvent *event) {
             TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged();
         }
       }
-      // camstand button
-      else if (o->rect(PredefinedRect::PREVIEW_LAYER_AREA)
+      // separated view - camstand button
+      else if (!Preferences::instance()
+                    ->isUnifyColumnVisibilityTogglesEnabled() &&
+               o->rect(PredefinedRect::PREVIEW_LAYER_AREA)
                    .contains(mouseInCell)) {
         if (event->button() != Qt::LeftButton) return;
         if (column->getPaletteColumn() || column->getSoundTextColumn()) {
@@ -2683,6 +2663,10 @@ void ColumnArea::mouseReleaseEvent(QMouseEvent *event) {
     TXshColumn *column = xsh->getColumn(m_col);
     if (m_doOnRelease == ToggleTransparency) {
       column->setCamstandVisible(!column->isCamstandVisible());
+      // sync eye button
+      if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+        column->setPreviewVisible(column->isCamstandVisible());
+
       if (column->getSoundColumn())
         app->getCurrentXsheet()->notifyXsheetSoundChanged();
     } else if (m_doOnRelease == TogglePreviewVisible)
@@ -2757,6 +2741,9 @@ void ColumnArea::mouseReleaseEvent(QMouseEvent *event) {
         if (!xsh->isColumnEmpty(col) && !column->getPaletteColumn() &&
             !column->getSoundTextColumn()) {
           column->setCamstandVisible(!column->isCamstandVisible());
+          // sync eye button
+          if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+            column->setPreviewVisible(column->isCamstandVisible());
           if (column->getSoundColumn()) sound_changed = true;
         }
       }
@@ -2781,10 +2768,12 @@ void ColumnArea::mouseReleaseEvent(QMouseEvent *event) {
     // if necessary. it causes slowness when opening preview flipbook of large
     // scene.
     // KNOWN BUG: Side effect, transparency doesn't sync in schematic if false.
-    bool isTransparencyRendered = app->getCurrentScene()
-                                      ->getScene()
-                                      ->getProperties()
-                                      ->isColumnColorFilterOnRenderEnabled();
+    bool isTransparencyRendered =
+        app->getCurrentScene()
+            ->getScene()
+            ->getProperties()
+            ->isColumnColorFilterOnRenderEnabled() ||
+        Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled();
     bool isStateChanged = m_doOnRelease == TogglePreviewVisible ||
                           m_doOnRelease == ToggleAllPreviewVisible ||
                           m_doOnRelease == ToggleLock ||
@@ -2823,7 +2812,10 @@ void ColumnArea::mouseDoubleClickEvent(QMouseEvent *event) {
   if (!nameRect.contains(mouseInCell)) return;
 
   TXsheet *xsh = m_viewer->getXsheet();
-  if (col >= 0 && xsh->isColumnEmpty(col)) return;
+  // enable to rename empty column when the column name is linked to the level
+  if (!Preferences::instance()->isLinkColumnNameWithLevelEnabled() &&
+      col >= 0 && xsh->isColumnEmpty(col))
+    return;
 
   QPoint fieldPos =
       (col < 0 && o->isVerticalTimeline()) ? nameRect.topLeft() : topLeft;
@@ -2858,9 +2850,10 @@ void ColumnArea::contextMenuEvent(QContextMenuEvent *event) {
   QMenu menu(this);
   CommandManager *cmdManager = CommandManager::instance();
 
-  //---- Preview
+  //---- Unified
   if (((isCamera && !o->isVerticalTimeline()) || !xsh->isColumnEmpty(col)) &&
-      o->rect(PredefinedRect::EYE_AREA).contains(mouseInCell)) {
+      o->rect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA).contains(mouseInCell) &&
+      Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) {
     menu.setObjectName("xsheetColumnAreaMenu_Preview");
 
     menu.addAction(cmdManager->getAction("MI_EnableThisColumnOnly"));
@@ -2870,24 +2863,25 @@ void ColumnArea::contextMenuEvent(QContextMenuEvent *event) {
     menu.addAction(cmdManager->getAction("MI_DisableSelectedColumns"));
     menu.addAction(cmdManager->getAction("MI_SwapEnabledColumns"));
   }
-  //---- Lock
-  else if ((isCamera || !xsh->isColumnEmpty(col)) &&
-           o->rect((isCamera) ? PredefinedRect::CAMERA_LOCK_AREA
-                              : PredefinedRect::LOCK_AREA)
-               .contains(mouseInCell)) {
-    menu.setObjectName("xsheetColumnAreaMenu_Lock");
+  //---- Preview
+  else if (((isCamera && !o->isVerticalTimeline()) ||
+            !xsh->isColumnEmpty(col)) &&
+           o->rect(PredefinedRect::EYE_AREA).contains(mouseInCell) &&
+           !Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) {
+    menu.setObjectName("xsheetColumnAreaMenu_Preview");
 
-    menu.addAction(cmdManager->getAction("MI_LockThisColumnOnly"));
-    menu.addAction(cmdManager->getAction("MI_LockSelectedColumns"));
-    menu.addAction(cmdManager->getAction("MI_LockAllColumns"));
-    menu.addAction(cmdManager->getAction("MI_UnlockSelectedColumns"));
-    menu.addAction(cmdManager->getAction("MI_UnlockAllColumns"));
-    menu.addAction(cmdManager->getAction("MI_ToggleColumnLocks"));
+    menu.addAction(cmdManager->getAction("MI_EnableThisColumnOnly"));
+    menu.addAction(cmdManager->getAction("MI_EnableSelectedColumns"));
+    menu.addAction(cmdManager->getAction("MI_EnableAllColumns"));
+    menu.addAction(cmdManager->getAction("MI_DisableAllColumns"));
+    menu.addAction(cmdManager->getAction("MI_DisableSelectedColumns"));
+    menu.addAction(cmdManager->getAction("MI_SwapEnabledColumns"));
   }
   //---- Camstand
   else if (((isCamera && !o->isVerticalTimeline()) ||
             !xsh->isColumnEmpty(col)) &&
-           o->rect(PredefinedRect::PREVIEW_LAYER_AREA).contains(mouseInCell)) {
+           o->rect(PredefinedRect::PREVIEW_LAYER_AREA).contains(mouseInCell) &&
+           !Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled()) {
     menu.setObjectName("xsheetColumnAreaMenu_Camstand");
 
     menu.addAction(cmdManager->getAction("MI_ActivateThisColumnOnly"));
@@ -2899,6 +2893,20 @@ void ColumnArea::contextMenuEvent(QContextMenuEvent *event) {
     // hide all columns placed on the left
     menu.addAction(cmdManager->getAction("MI_DeactivateUpperColumns"));
   }
+  //---- Lock
+  else if ((isCamera || !xsh->isColumnEmpty(col)) &&
+           o->rect((isCamera) ? PredefinedRect::CAMERA_LOCK_AREA
+                              : PredefinedRect::LOCK_AREA)
+               .contains(mouseInCell)) {
+    menu.setObjectName("xsheetColumnAreaMenu_Lock");
+
+    menu.addAction(cmdManager->getAction("MI_LockThisColumnOnly"));
+    menu.addAction(cmdManager->getAction("MI_LockSelectedColumns"));
+    menu.addAction(cmdManager->getAction("MI_LockAllColumns"));
+    menu.addAction(cmdManager->getAction("MI_UnlockSelectedColumns"));
+    menu.addAction(cmdManager->getAction("MI_UnlockAllColumns"));
+    menu.addAction(cmdManager->getAction("MI_ToggleColumnLocks"));
+  }
   // right clicking another area / right clicking empty column head
   else {
     if (!isCamera) {
diff --git a/toonz/sources/toonz/xshcolumnviewer.h b/toonz/sources/toonz/xshcolumnviewer.h
index bad711f..ea091b6 100644
--- a/toonz/sources/toonz/xshcolumnviewer.h
+++ b/toonz/sources/toonz/xshcolumnviewer.h
@@ -321,6 +321,7 @@ class ColumnArea final : public QWidget {
     bool isEmpty, isCurrent;
     TXshColumn *column;
     QPoint orig;
+    TXshLevel *reservedLevel;
 
   public:
     DrawHeader(ColumnArea *area, QPainter &p, int col);
@@ -334,6 +335,7 @@ class ColumnArea final : public QWidget {
     void drawBaseFill(const QColor &columnColor, const QColor &dragColor) const;
     void drawEye() const;
     void drawPreviewToggle(int opacity) const;
+    void drawUnifiedViewToggle(int opacity) const;
     void drawLock() const;
     void drawConfig() const;
     void drawColumnNumber() const;
diff --git a/toonz/sources/toonz/xsheetviewer.cpp b/toonz/sources/toonz/xsheetviewer.cpp
index adbe05e..56afdc0 100644
--- a/toonz/sources/toonz/xsheetviewer.cpp
+++ b/toonz/sources/toonz/xsheetviewer.cpp
@@ -208,6 +208,12 @@ void XsheetViewer::getButton(const int &btype, QColor &bgColor,
     iconImage = (isTimeline) ? getTimelineConfigButtonImage()
                              : getXsheetConfigButtonImage();
     break;
+  case UNIFIED_TRANSP_XSHBUTTON:
+    bgColor   = (isTimeline) ? getTimelinePreviewButtonBgOnColor()
+                             : getXsheetPreviewButtonBgOnColor();
+    iconImage = (isTimeline) ? getTimelineUnifiedButtonTranspImage()
+                             : getXsheetUnifiedButtonTranspImage();
+    break;
   default:
     bgColor = grey210;
     static QImage iconignored;
@@ -1266,25 +1272,42 @@ void XsheetViewer::keyPressEvent(QKeyEvent *event) {
   // selection range.
   if (Preferences::instance()->isUseArrowKeyToShiftCellSelectionEnabled() &&
       cellSel && !cellSel->isEmpty()) {
-    int r0, c0, r1, c1;
-    cellSel->getSelectedCells(r0, c0, r1, c1);
+    int rowA, colA, rowB, colB;
+    cellSel->getSelectedCells(rowA, colA, rowB, colB);
     stride.setFrame(cellSel->getSelectedCells().getRowCount());
 
     if (m_cellArea->isControlPressed()) {  // resize
-      if (r0 == r1 && shift.frame() < 0) return;
-      if (c0 == c1 && shift.layer() < firstCol) return;
-      cellSel->selectCells(r0, c0, r1 + shift.frame(), c1 + shift.layer());
+
+      // resize selection of frames/rows forward or backwards
+      assert(cellSel->getResizePivotRow() >= 0);
+      if (rowA < cellSel->getResizePivotRow())
+        rowA += shift.frame();
+      else
+        rowB += shift.frame();
+
+      // resize selection of layers/columns "up" or "down"
+      if (colA < getCurrentColumn())
+        colA += shift.layer();
+      else
+        colB += shift.layer();
+
+      // keep selection inside the xsheet/timeline
+      if (colA < firstCol || colB < firstCol || rowA < 0 || rowB < 0) return;
+
+      // apply new selection rectangle
+      cellSel->selectCells(rowA, colA, rowB, colB);
       updateCells();
       TApp::instance()->getCurrentSelection()->notifySelectionChanged();
       return;
+
     } else {  // shift
       CellPosition offset(shift * stride);
-      int movedR0   = std::max(0, r0 + offset.frame());
-      int movedC0   = std::max(firstCol, c0 + offset.layer());
-      int diffFrame = movedR0 - r0;
-      int diffLayer = movedC0 - c0;
-      cellSel->selectCells(r0 + diffFrame, c0 + diffLayer, r1 + diffFrame,
-                           c1 + diffLayer);
+      int movedRow0 = std::max(0, rowA + offset.frame());
+      int movedCol0 = std::max(firstCol, colA + offset.layer());
+      int diffRow   = movedRow0 - rowA;
+      int diffCol   = movedCol0 - colA;
+      cellSel->selectCells(rowA + diffRow, colA + diffCol, rowB + diffRow,
+                           colB + diffCol);
       TApp::instance()->getCurrentSelection()->notifySelectionChanged();
     }
   }
diff --git a/toonz/sources/toonz/xsheetviewer.h b/toonz/sources/toonz/xsheetviewer.h
index 6e6393d..515148d 100644
--- a/toonz/sources/toonz/xsheetviewer.h
+++ b/toonz/sources/toonz/xsheetviewer.h
@@ -40,7 +40,8 @@ enum TXshButtonType {
   CAMSTAND_TRANSP_XSHBUTTON,
   LOCK_ON_XSHBUTTON,
   LOCK_OFF_XSHBUTTON,
-  CONFIG_XSHBUTTON
+  CONFIG_XSHBUTTON,
+  UNIFIED_TRANSP_XSHBUTTON
 };
 
 namespace XsheetGUI {
@@ -241,9 +242,9 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings {
   Q_PROPERTY(QColor TextColor READ getTextColor WRITE setTextColor)
   Q_PROPERTY(
       QColor ErrorTextColor READ getErrorTextColor WRITE setErrorTextColor)
-  Q_PROPERTY(QColor SelectedTextColor READ getCurrentFrameTextColor WRITE
+  Q_PROPERTY(QColor CurrentFrameTextColor READ getCurrentFrameTextColor WRITE
                  setCurrentFrameTextColor)
-  Q_PROPERTY(QColor CurrentFrameTextColor READ getSelectedTextColor WRITE
+  Q_PROPERTY(QColor SelectedTextColor READ getSelectedTextColor WRITE
                  setSelectedTextColor)
   Q_PROPERTY(QColor PreviewFrameTextColor READ getPreviewFrameTextColor WRITE
                  setPreviewFrameTextColor)
@@ -449,6 +450,7 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings {
   QImage m_xsheetPreviewButtonOnImage;
   QColor m_xsheetPreviewButtonBgOffColor;
   QImage m_xsheetPreviewButtonOffImage;
+  QImage m_xsheetUnifiedButtonTranspImage;
   Q_PROPERTY(
       QColor XsheetPreviewButtonBgOnColor READ getXsheetPreviewButtonBgOnColor
           WRITE setXsheetPreviewButtonBgOnColor)
@@ -461,6 +463,9 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings {
   Q_PROPERTY(
       QImage XsheetPreviewButtonOffImage READ getXsheetPreviewButtonOffImage
           WRITE setXsheetPreviewButtonOffImage)
+  Q_PROPERTY(QImage XsheetUnifiedButtonTranspImage READ
+                 getXsheetUnifiedButtonTranspImage WRITE
+                     setXsheetUnifiedButtonTranspImage)
   // Xsheet Camstand Button
   QColor m_xsheetCamstandButtonBgOnColor;
   QImage m_xsheetCamstandButtonOnImage;
@@ -508,6 +513,7 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings {
   QImage m_timelinePreviewButtonOnImage;
   QColor m_timelinePreviewButtonBgOffColor;
   QImage m_timelinePreviewButtonOffImage;
+  QImage m_timelineUnifiedButtonTranspImage;
   Q_PROPERTY(QColor TimelinePreviewButtonBgOnColor READ
                  getTimelinePreviewButtonBgOnColor WRITE
                      setTimelinePreviewButtonBgOnColor)
@@ -520,6 +526,9 @@ class XsheetViewer final : public QFrame, public SaveLoadQSettings {
   Q_PROPERTY(
       QImage TimelinePreviewButtonOffImage READ getTimelinePreviewButtonOffImage
           WRITE setTimelinePreviewButtonOffImage)
+  Q_PROPERTY(QImage TimelineUnifiedButtonTranspImage READ
+                 getTimelineUnifiedButtonTranspImage WRITE
+                     setTimelineUnifiedButtonTranspImage)
   // Timeline Camstand Button
   QColor m_timelineCamstandButtonBgOnColor;
   QImage m_timelineCamstandButtonOnImage;
@@ -1098,6 +1107,9 @@ public:
   void setXsheetPreviewButtonOffImage(const QImage &image) {
     m_xsheetPreviewButtonOffImage = image;
   }
+  void setXsheetUnifiedButtonTranspImage(const QImage &image) {
+    m_xsheetUnifiedButtonTranspImage = image;
+  }
   QColor getXsheetPreviewButtonBgOnColor() const {
     return m_xsheetPreviewButtonBgOnColor;
   }
@@ -1110,6 +1122,9 @@ public:
   QImage getXsheetPreviewButtonOffImage() const {
     return m_xsheetPreviewButtonOffImage;
   }
+  QImage getXsheetUnifiedButtonTranspImage() const {
+    return m_xsheetUnifiedButtonTranspImage;
+  }
   // Xsheet Camstand Button
   void setXsheetCamstandButtonBgOnColor(const QColor &color) {
     m_xsheetCamstandButtonBgOnColor = color;
@@ -1192,6 +1207,9 @@ public:
   void setTimelinePreviewButtonOffImage(const QImage &image) {
     m_timelinePreviewButtonOffImage = image;
   }
+  void setTimelineUnifiedButtonTranspImage(const QImage &image) {
+    m_timelineUnifiedButtonTranspImage = image;
+  }
   QColor getTimelinePreviewButtonBgOnColor() const {
     return m_timelinePreviewButtonBgOnColor;
   }
@@ -1204,6 +1222,9 @@ public:
   QImage getTimelinePreviewButtonOffImage() const {
     return m_timelinePreviewButtonOffImage;
   }
+  QImage getTimelineUnifiedButtonTranspImage() const {
+    return m_timelineUnifiedButtonTranspImage;
+  }
   // Timeline Camstand Button
   void setTimelineCamstandButtonBgOnColor(const QColor &color) {
     m_timelineCamstandButtonBgOnColor = color;
diff --git a/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp b/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp
index 836266b..28fd4b2 100644
--- a/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp
+++ b/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp
@@ -368,8 +368,8 @@ static QString getExeName(bool isComposer) {
   return name + ".exe ";
 #elif defined(MACOSX)
   TVER::ToonzVersion tver;
-  return "\"./" + QString::fromStdString(tver.getAppName()) +
-         ".app/Contents/MacOS/" + name + "\" ";
+  return QString::fromStdString(tver.getAppName()) + ".app/Contents/MacOS/" +
+         name;
 #else
   return name;
 #endif
@@ -541,6 +541,59 @@ QString TFarmTask::getCommandLineArguments() const {
   return cmdline;
 }
 
+QStringList TFarmTask::getCommandLineArgumentsList() const {
+  QStringList ret;
+
+  if (!m_taskFilePath.isEmpty())
+    ret << QString::fromStdWString(
+        TSystem::toUNC(m_taskFilePath).getWideString());
+
+  if (m_callerMachineName != "") {
+    struct hostent *he = gethostbyname(m_callerMachineName.toLatin1());
+    if (he) {
+      char *ipAddress = inet_ntoa(*(struct in_addr *)*(he->h_addr_list));
+      ret << "-tmsg" << QString::fromUtf8(ipAddress);
+    }
+  }
+
+  if (!m_isComposerTask) {
+    if (m_overwrite == Overwrite_All)
+      ret << "-overwriteAll";
+    else if (m_overwrite == Overwrite_NoPaint)
+      ret << "-overwriteNoPaint";
+    if (m_onlyVisible) ret << "-onlyvisible";
+    return ret;
+  }
+
+  if (!m_outputPath.isEmpty()) {
+    TFilePath outputPath;
+    try {
+      outputPath = TSystem::toUNC(m_outputPath);
+    } catch (TException &) {
+    }
+
+    ret << "-o" << QString::fromStdWString(outputPath.getWideString());
+  }
+
+  ret << "-range" << QString::number(m_from) << QString::number(m_to);
+  ret << "-step" << QString::number(m_step);
+  ret << "-shrink" << QString::number(m_shrink);
+  ret << "-multimedia" << QString::number(m_multimedia);
+
+  const QString threadCounts[3] = {"single", "half", "all"};
+  ret << "-nthreads" << threadCounts[m_threadsIndex];
+
+  const QString maxTileSizes[4] = {
+      "none", QString::number(TOutputProperties::LargeVal),
+      QString::number(TOutputProperties::MediumVal),
+      QString::number(TOutputProperties::SmallVal)};
+  ret << "-maxtilesize" << maxTileSizes[m_maxTileSizeIndex];
+
+  QString appname = QSettings().applicationName();
+
+  return ret;
+}
+
 QString TFarmTask::getCommandLine(bool) const {
   return getCommandLinePrgName() + getCommandLineArguments();
 }
diff --git a/toonz/sources/toonzlib/orientation.cpp b/toonz/sources/toonzlib/orientation.cpp
index c7dea3c..4b9a203 100644
--- a/toonz/sources/toonzlib/orientation.cpp
+++ b/toonz/sources/toonzlib/orientation.cpp
@@ -438,9 +438,9 @@ TopToBottomOrientation::TopToBottomOrientation() {
   static int HDRROW3;
   static int HDRROW4;
   static int HDRROW5;
-  QRect layername, eyeArea, previewArea, lockArea, cameraLockArea, configArea,
-      cameraConfigArea, thumbnailArea, thumbnail, cameraIconArea, pegbarname,
-      volumeArea;
+  QRect layername, eyeArea, previewArea, unifiedViewArea, lockArea,
+      cameraLockArea, configArea, cameraConfigArea, thumbnailArea, thumbnail,
+      cameraIconArea, pegbarname, volumeArea;
   QPoint soundTopLeft;
 
   if (layout == QString("Minimum")) {
@@ -473,6 +473,12 @@ TopToBottomOrientation::TopToBottomOrientation() {
     addRect(PredefinedRect::PREVIEW_LAYER,
             iconRect(previewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1));
 
+    unifiedViewArea = QRect(
+        INDENT, HDRROW2, eyeArea.width() + previewArea.width(), HDRROW_HEIGHT);
+    addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, unifiedViewArea);
+    addRect(PredefinedRect::UNIFIEDVIEW_LAYER,
+            iconRect(unifiedViewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1));
+
     addRect(PredefinedRect::LOCK_AREA, QRect(0, 0, -1, -1));
     addRect(PredefinedRect::LOCK, QRect(0, 0, -1, -1));
     addRect(PredefinedRect::CAMERA_LOCK_AREA, QRect(0, 0, -1, -1));
@@ -559,6 +565,12 @@ TopToBottomOrientation::TopToBottomOrientation() {
     addRect(PredefinedRect::PREVIEW_LAYER,
             iconRect(previewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1));
 
+    unifiedViewArea = QRect(
+        INDENT, HDRROW2, eyeArea.width() + previewArea.width(), HDRROW_HEIGHT);
+    addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, unifiedViewArea);
+    addRect(PredefinedRect::UNIFIEDVIEW_LAYER,
+            iconRect(unifiedViewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1));
+
     lockArea = QRect(INDENT + eyeArea.width() + previewArea.width(), HDRROW2,
                      ICON_WIDTH, HDRROW_HEIGHT);
     addRect(PredefinedRect::LOCK_AREA, lockArea);
@@ -670,6 +682,12 @@ TopToBottomOrientation::TopToBottomOrientation() {
     addRect(PredefinedRect::PREVIEW_LAYER,
             iconRect(previewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1));
 
+    unifiedViewArea =
+        QRect(INDENT, HDRROW2, CELL_WIDTH - ICON_WIDTH, HDRROW_HEIGHT * 2);
+    addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, unifiedViewArea);
+    addRect(PredefinedRect::UNIFIEDVIEW_LAYER,
+            iconRect(unifiedViewArea, ICON_WIDTH, ICON_HEIGHT - 1, 1));
+
     lockArea =
         QRect(INDENT + eyeArea.width(), HDRROW2, ICON_WIDTH, HDRROW_HEIGHT);
     addRect(PredefinedRect::LOCK_AREA, lockArea);
@@ -781,6 +799,13 @@ TopToBottomOrientation::TopToBottomOrientation() {
     addRect(PredefinedRect::PREVIEW_LAYER,
             previewArea.adjusted(previewArea.width() - ICON_WIDTH, 0, 0, 0));
 
+    unifiedViewArea =
+        QRect(INDENT, HDRROW2, CELL_WIDTH - INDENT - 2, HDRROW_HEIGHT - 1);
+    addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, unifiedViewArea);
+    addRect(PredefinedRect::UNIFIEDVIEW_LAYER,
+            unifiedViewArea.adjusted(unifiedViewArea.width() - ICON_WIDTH, 0, 0,
+                                     0));
+
     lockArea = QRect(INDENT, HDRROW2, ICON_WIDTH - 1, HDRROW_HEIGHT - 1);
     addRect(PredefinedRect::LOCK_AREA, lockArea);
     addRect(PredefinedRect::LOCK, lockArea);
@@ -1216,7 +1241,6 @@ LeftToRightOrientation::LeftToRightOrientation() {
                 (FRAME_HEADER_HEIGHT - NAV_TAG_HEIGHT) / 2, NAV_TAG_WIDTH,
                 NAV_TAG_HEIGHT));
 
-
   // Column viewer
   addRect(PredefinedRect::LAYER_HEADER,
           QRect(1, 0, LAYER_HEADER_WIDTH - 2, CELL_HEIGHT));
@@ -1238,6 +1262,10 @@ LeftToRightOrientation::LeftToRightOrientation() {
           eyeArea.translated(ICON_OFFSET, 0));
   addRect(PredefinedRect::PREVIEW_LAYER,
           eye.translated(ICON_OFFSET, 0).adjusted(1, 1, -1, -1));
+
+  addRect(PredefinedRect::UNIFIEDVIEW_LAYER_AREA, eyeArea);
+  addRect(PredefinedRect::UNIFIEDVIEW_LAYER, eye.adjusted(1, 1, -1, -1));
+
   addRect(PredefinedRect::LOCK_AREA, eyeArea.translated(2 * ICON_OFFSET, 0));
   addRect(PredefinedRect::LOCK,
           eye.translated(2 * ICON_OFFSET, 0).adjusted(1, 1, -1, -1));
diff --git a/toonz/sources/toonzlib/preferences.cpp b/toonz/sources/toonzlib/preferences.cpp
index 288a26c..fd28142 100644
--- a/toonz/sources/toonzlib/preferences.cpp
+++ b/toonz/sources/toonzlib/preferences.cpp
@@ -586,6 +586,8 @@ void Preferences::definePreferenceItems() {
   define(showXSheetToolbar, "showXSheetToolbar", QMetaType::Bool, true);
   define(expandFunctionHeader, "expandFunctionHeader", QMetaType::Bool, false);
   define(showColumnNumbers, "showColumnNumbers", QMetaType::Bool, false);
+  define(unifyColumnVisibilityToggles, "unifyColumnVisibilityToggles",
+         QMetaType::Bool, false);
   define(parentColorsInXsheetColumn, "parentColorsInXsheetColumn",
          QMetaType::Bool, false);
   define(highlightLineEverySecond, "highlightLineEverySecond", QMetaType::Bool,
@@ -602,6 +604,14 @@ void Preferences::definePreferenceItems() {
          0);  // default
   define(showFrameNumberWithLetters, "showFrameNumberWithLetters",
          QMetaType::Bool, false);
+  // This option will do the following:
+  // - When setting a cell in the empty column, level name will be copied to the
+  // column name
+  // - Typing the cell without level name in the empty column will try to use a
+  // level with the same name as the column The behavior may be changed in the
+  // future development.
+  define(linkColumnNameWithLevel, "linkColumnNameWithLevel", QMetaType::Bool,
+         false);
 
   // Animation
   define(keyframeType, "keyframeType", QMetaType::Int, 2);  // Linear
diff --git a/toonz/sources/toonzlib/txsheet.cpp b/toonz/sources/toonzlib/txsheet.cpp
index 4484322..79f139e 100644
--- a/toonz/sources/toonzlib/txsheet.cpp
+++ b/toonz/sources/toonzlib/txsheet.cpp
@@ -302,6 +302,13 @@ bool TXsheet::setCell(int row, int col, const TXshCell &cell) {
   else if (row >= m_imp->m_frameCount)
     m_imp->m_frameCount = row + 1;
 
+  // set the level name to the column
+  if (wasColumnEmpty && cellColumn && !cell.isEmpty() &&
+      Preferences::instance()->isLinkColumnNameWithLevelEnabled()) {
+    getStageObject(TStageObjectId::ColumnId(col))
+        ->setName(to_string(cell.m_level->getName()));
+  }
+
   TNotifier::instance()->notify(TXsheetChange());
 
   return true;
@@ -386,6 +393,14 @@ bool TXsheet::setCells(int row, int col, int rowCount, const TXshCell cells[]) {
         newColRowCount < m_imp->m_frameCount)
       updateFrameCount();
   }
+  row + 1;
+
+  // set the level name to the column
+  if (wasColumnEmpty && i < rowCount &&
+      Preferences::instance()->isLinkColumnNameWithLevelEnabled()) {
+    getStageObject(TStageObjectId::ColumnId(col))
+        ->setName(to_string(cells[i].m_level->getName()));
+  }
 
   return true;
 }
diff --git a/toonz/sources/toonzlib/txshlevelcolumn.cpp b/toonz/sources/toonzlib/txshlevelcolumn.cpp
index 7774465..da2a46f 100644
--- a/toonz/sources/toonzlib/txshlevelcolumn.cpp
+++ b/toonz/sources/toonzlib/txshlevelcolumn.cpp
@@ -209,9 +209,12 @@ void TXshLevelColumn::saveData(TOStream &os) {
 
 //-----------------------------------------------------------------------------
 // Used in TCellData::getNumbers
-bool TXshLevelColumn::setNumbers(int row, int rowCount,
-                                 const TXshCell cells[]) {
-  if (m_cells.empty()) return false;
+// reservedLevel can be nonzero if the preferences option
+// "LinkColumnNameWithLevel" is ON and the column name is the same as some level
+// in the scene cast.
+bool TXshLevelColumn::setNumbers(int row, int rowCount, const TXshCell cells[],
+                                 TXshLevel *reservedLevel) {
+  if (m_cells.empty() && !reservedLevel) return false;
   // Check availability.
   // - if source cells are all empty, do nothing
   // - also, if source or target cells contain NO_FRAME, do nothing
@@ -236,16 +239,18 @@ bool TXshLevelColumn::setNumbers(int row, int rowCount,
   // Find a level to input.
   // If the first target cell is empty, search the upper cells, and lower cells
   // and use a level of firsty-found occupied neighbor cell.
-  TXshLevelP currentLevel;
-  int tmpIndex = std::min(row - m_first, (int)m_cells.size() - 1);
+  TXshLevelP currentLevel = reservedLevel;
+  int tmpIndex            = std::min(row - m_first, (int)m_cells.size() - 1);
   // search upper cells
-  while (tmpIndex >= 0) {
-    TXshCell tmpCell = m_cells[tmpIndex];
-    if (!tmpCell.isEmpty() && tmpCell.m_frameId != TFrameId::NO_FRAME) {
-      currentLevel = tmpCell.m_level;
-      break;
+  if (!currentLevel) {
+    while (tmpIndex >= 0) {
+      TXshCell tmpCell = m_cells[tmpIndex];
+      if (!tmpCell.isEmpty() && tmpCell.m_frameId != TFrameId::NO_FRAME) {
+        currentLevel = tmpCell.m_level;
+        break;
+      }
+      tmpIndex--;
     }
-    tmpIndex--;
   }
   // if not found any level in upper cells, then search the lower cells
   if (!currentLevel) {
diff --git a/toonz/sources/toonzlib/txshsoundcolumn.cpp b/toonz/sources/toonzlib/txshsoundcolumn.cpp
index 34b2c73..d84fa3e 100644
--- a/toonz/sources/toonzlib/txshsoundcolumn.cpp
+++ b/toonz/sources/toonzlib/txshsoundcolumn.cpp
@@ -447,7 +447,7 @@ bool TXshSoundColumn::setCell(int row, const TXshCell &cell,
   if (isBeforeLevelInSequence) {
     int oldEndOffset = lBefore->getEndOffset();
     int endOffset    = (lBefore->getVisibleEndFrame() != row) ? oldEndOffset - 1
-                                                           : oldEndOffset;
+                                                              : oldEndOffset;
     if (isNextLevelInSequence) {
       endOffset = lNext->getEndOffset();
       // Se precedente e successivo sono diversi elimino il successivo (caso in
@@ -468,8 +468,8 @@ bool TXshSoundColumn::setCell(int row, const TXshCell &cell,
   if (isNextLevelInSequence) {
     int oldStartOffset = lNext->getStartOffset();
     int startOffset    = (lNext->getVisibleStartFrame() != row)
-                          ? oldStartOffset - 1
-                          : oldStartOffset;
+                             ? oldStartOffset - 1
+                             : oldStartOffset;
     if (l && l != lNext) {
       if (l->getVisibleFrameCount() == 1)
         removeColumnLevel(l);
diff --git a/toonz/sources/toonzqt/dvdialog.cpp b/toonz/sources/toonzqt/dvdialog.cpp
index ee892a1..2d9c19d 100644
--- a/toonz/sources/toonzqt/dvdialog.cpp
+++ b/toonz/sources/toonzqt/dvdialog.cpp
@@ -807,7 +807,7 @@ MessageAndCheckboxDialog::MessageAndCheckboxDialog(
 
 //=============================================================================
 
-void MessageAndCheckboxDialog::onButtonPressed(int id) { done(id); }
+void MessageAndCheckboxDialog::onButtonClicked(int id) { done(id); }
 
 //=============================================================================
 
@@ -849,9 +849,9 @@ RadioButtonDialog::RadioButtonDialog(const QString &labelText,
   endVLayout();
 
   QPushButton *applyButton = new QPushButton(QObject::tr("Apply"));
-  ret = ret && connect(applyButton, SIGNAL(pressed()), this, SLOT(onApply()));
+  ret = ret && connect(applyButton, SIGNAL(clicked()), this, SLOT(onApply()));
   QPushButton *cancelButton = new QPushButton(QObject::tr("Cancel"));
-  ret = ret && connect(cancelButton, SIGNAL(pressed()), this, SLOT(onCancel()));
+  ret = ret && connect(cancelButton, SIGNAL(clicked()), this, SLOT(onCancel()));
 
   addButtonBarWidget(applyButton, cancelButton);
 
@@ -922,9 +922,9 @@ void ProgressDialog::setLabelText(const QString &text) {
 
 void ProgressDialog::setCancelButton(QPushButton *cancelButton) {
   m_cancelButton = cancelButton;
-  bool ret = connect(cancelButton, SIGNAL(pressed()), this, SLOT(onCancel()));
+  bool ret = connect(cancelButton, SIGNAL(clicked()), this, SLOT(onCancel()));
   ret =
-      ret && connect(cancelButton, SIGNAL(pressed()), this, SIGNAL(canceled()));
+      ret && connect(cancelButton, SIGNAL(clicked()), this, SIGNAL(canceled()));
   assert(ret);
   addButtonBarWidget(m_cancelButton);
 }
@@ -1014,7 +1014,7 @@ int DVGui::MsgBox(MsgType type, const QString &text,
     buttonGroup->addButton(button, i + 1);
   }
 
-  QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), &dialog,
+  QObject::connect(buttonGroup, SIGNAL(idClicked(int)), &dialog,
                    SLOT(done(int)));
 
   dialog.raise();
@@ -1064,7 +1064,7 @@ void DVGui::MsgBoxInPopup(MsgType type, const QString &text) {
   button->setDefault(true);
   dialog.addButtonBarWidget(button);
   buttonGroup->addButton(button, 1);
-  QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), &dialog,
+  QObject::connect(buttonGroup, SIGNAL(idClicked(int)), &dialog,
                    SLOT(done(int)));
 
   while (!messageQueue.empty()) {
@@ -1138,7 +1138,7 @@ int DVGui::MsgBox(const QString &text, const QString &button1Text,
   dialog.addButtonBarWidget(button3);
   buttonGroup->addButton(button3, 3);
 
-  QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), &dialog,
+  QObject::connect(buttonGroup, SIGNAL(idClicked(int)), &dialog,
                    SLOT(done(int)));
   dialog.raise();
   return dialog.exec();
@@ -1197,7 +1197,7 @@ int DVGui::MsgBox(const QString &text, const QString &button1Text,
   dialog.addButtonBarWidget(button4);
   buttonGroup->addButton(button4, 4);
 
-  QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), &dialog,
+  QObject::connect(buttonGroup, SIGNAL(idClicked(int)), &dialog,
                    SLOT(done(int)));
   dialog.raise();
   return dialog.exec();
@@ -1258,7 +1258,7 @@ Dialog *DVGui::createMsgBox(MsgType type, const QString &text,
     buttonGroup->addButton(button, i + 1);
   }
 
-  QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), dialog,
+  QObject::connect(buttonGroup, SIGNAL(idClicked(int)), dialog,
                    SLOT(done(int)));
 
   return dialog;
@@ -1317,8 +1317,8 @@ MessageAndCheckboxDialog *DVGui::createMsgandCheckbox(
 
   QObject::connect(dialogCheckBox, SIGNAL(stateChanged(int)), dialog,
                    SLOT(onCheckboxChanged(int)));
-  QObject::connect(buttonGroup, SIGNAL(buttonPressed(int)), dialog,
-                   SLOT(onButtonPressed(int)));
+  QObject::connect(buttonGroup, SIGNAL(idClicked(int)), dialog,
+                   SLOT(onButtonClicked(int)));
 
   return dialog;
 }
diff --git a/toonz/sources/toonzqt/fxschematicnode.cpp b/toonz/sources/toonzqt/fxschematicnode.cpp
index e3b9707..f757fc2 100644
--- a/toonz/sources/toonzqt/fxschematicnode.cpp
+++ b/toonz/sources/toonzqt/fxschematicnode.cpp
@@ -2821,8 +2821,11 @@ FxSchematicZeraryNode::FxSchematicZeraryNode(FxSchematicScene *scene,
   connect(m_nameItem, SIGNAL(focusOut()), this, SLOT(onNameChanged()));
   connect(m_renderToggle, SIGNAL(toggled(bool)), this,
           SLOT(onRenderToggleClicked(bool)));
-  connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this,
-          SLOT(onCameraStandToggleClicked(int)));
+  if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+    m_cameraStandToggle->hide();
+  else
+    connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this,
+            SLOT(onCameraStandToggleClicked(int)));
 
   if (zeraryFx) {
     int i, inputPorts = zeraryFx->getInputPortCount();
@@ -3085,8 +3088,11 @@ FxSchematicColumnNode::FxSchematicColumnNode(FxSchematicScene *scene,
         connect(m_nameItem, SIGNAL(focusOut()), this, SLOT(onNameChanged()));
   ret = ret && connect(m_renderToggle, SIGNAL(toggled(bool)), this,
                        SLOT(onRenderToggleClicked(bool)));
-  ret = ret && connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this,
-                       SLOT(onCameraStandToggleClicked(int)));
+  if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+    m_cameraStandToggle->hide();
+  else
+    ret = ret && connect(m_cameraStandToggle, SIGNAL(stateChanged(int)), this,
+                         SLOT(onCameraStandToggleClicked(int)));
 
   assert(ret);
 
@@ -3122,6 +3128,8 @@ void FxSchematicColumnNode::onRenderToggleClicked(bool toggled) {
   TXshColumn *column = fxScene->getXsheet()->getColumn(m_columnIndex);
   if (column) {
     column->setPreviewVisible(toggled);
+    if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+      column->setCamstandVisible(toggled);
     emit sceneChanged();
     emit xsheetChanged();
   }
diff --git a/toonz/sources/toonzqt/paletteviewergui.cpp b/toonz/sources/toonzqt/paletteviewergui.cpp
index 1a992f6..3c934ab 100644
--- a/toonz/sources/toonzqt/paletteviewergui.cpp
+++ b/toonz/sources/toonzqt/paletteviewergui.cpp
@@ -542,7 +542,10 @@ void PageViewer::drawToggleLink(QPainter &p, QRect &chipRect,
     p.setPen(Qt::black);
     p.drawRect(rect);
 
-    if (globalName[0] == L'+') {
+    if (style->getOriginalName().empty()) {
+      p.setBrush(Qt::black);
+      p.drawRect(rect.adjusted(2, 2, -2, -2));
+    } else if (globalName[0] == L'+') {
       QPointF a(x + 2, y + 2);
       QPointF b(x + 2, y + 5);
       QPointF c(x + 5, y + 2);
@@ -589,6 +592,8 @@ void PageViewer::paintEvent(QPaintEvent *e) {
   TPalette *palette = (m_page) ? m_page->getPalette() : 0;
   if (!palette) return;
 
+  bool isStudioPalette = palette->getGlobalName() != L"";
+
   // [i0,i1] = visible cell range
   QRect visibleRect = e->rect();
   int i0            = posToIndex(visibleRect.topLeft());
@@ -648,7 +653,7 @@ void PageViewer::paintEvent(QPaintEvent *e) {
       }
 
       // toggle link
-      drawToggleLink(p, chipRect, m_page->getStyle(i));
+      drawToggleLink(p, chipRect, style);
     }
     if (ShowNewStyleButton && !m_page->getPalette()->isLocked()) {
       int j      = getChipCount();
@@ -1173,18 +1178,18 @@ void PageViewer::contextMenuEvent(QContextMenuEvent *event) {
   bool isLocked = m_page ? m_page->getPalette()->isLocked() : false;
 
   // remove links from studio palette
-  if (m_viewType == LEVEL_PALETTE && m_styleSelection &&
-      !m_styleSelection->isEmpty() && !isLocked &&
+  if (m_styleSelection && !m_styleSelection->isEmpty() && !isLocked &&
       m_styleSelection->hasLinkedStyle()) {
-    menu.addSeparator();
-    QAction *toggleStyleLink = cmd->getAction("MI_ToggleLinkToStudioPalette");
-    menu.addAction(toggleStyleLink);
-    QAction *removeStyleLink =
-        cmd->getAction("MI_RemoveReferenceToStudioPalette");
-    menu.addAction(removeStyleLink);
-    QAction *getBackOriginalAct =
-        cmd->getAction("MI_GetColorFromStudioPalette");
-    menu.addAction(getBackOriginalAct);
+    if (m_viewType == LEVEL_PALETTE) {
+      menu.addSeparator();
+      menu.addAction(cmd->getAction("MI_ToggleLinkToStudioPalette"));
+      menu.addAction(cmd->getAction("MI_RemoveReferenceToStudioPalette"));
+      menu.addAction(cmd->getAction("MI_GetColorFromStudioPalette"));
+    } else if (m_viewType == STUDIO_PALETTE) {
+      menu.addSeparator();
+      menu.addAction(cmd->getAction("MI_RemoveReferenceToStudioPalette"));
+      menu.addAction(cmd->getAction("MI_GetColorFromStudioPalette"));
+    }
   }
 
   if (((indexPage == 0 && index > 0) || (indexPage > 0 && index >= 0)) &&
diff --git a/toonz/sources/toonzqt/paramfield.cpp b/toonz/sources/toonzqt/paramfield.cpp
index f119c45..d8ae05f 100644
--- a/toonz/sources/toonzqt/paramfield.cpp
+++ b/toonz/sources/toonzqt/paramfield.cpp
@@ -9,6 +9,7 @@
 #include "toonzqt/doublepairfield.h"
 #include "toonzqt/tonecurvefield.h"
 #include "toonzqt/checkbox.h"
+#include "toonzqt/menubarcommand.h"
 
 #include "tdoubleparam.h"
 #include "tnotanimatableparam.h"
@@ -1563,6 +1564,9 @@ void IntParamField::update(int frame) {
 
 namespace component {
 
+MyTextEdit::MyTextEdit(const QString &text, QWidget *parent)
+    : QTextEdit(text, parent) {}
+
 void MyTextEdit::keyPressEvent(QKeyEvent *event) {
   QTextEdit::keyPressEvent(event);
   if (event->key() == Qt::Key_Return) emit edited();
@@ -1572,6 +1576,7 @@ void MyTextEdit::focusOutEvent(QFocusEvent *event) {
   QTextEdit::focusOutEvent(event);
   emit edited();
 }
+
 };  // namespace component
 
 StringParamField::StringParamField(QWidget *parent, QString name,
diff --git a/toonz/sources/toonzqt/stageschematicnode.cpp b/toonz/sources/toonzqt/stageschematicnode.cpp
index 92336be..3eb1a5a 100644
--- a/toonz/sources/toonzqt/stageschematicnode.cpp
+++ b/toonz/sources/toonzqt/stageschematicnode.cpp
@@ -1753,7 +1753,8 @@ StageSchematicColumnNode::StageSchematicColumnNode(StageSchematicScene *scene,
   if (levelType == PLT_XSHLEVEL) {
     m_resizeItem->hide();
     m_cameraStandToggle->hide();
-  }
+  } else if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+    m_cameraStandToggle->hide();
 }
 
 //--------------------------------------------------------
@@ -1961,6 +1962,8 @@ void StageSchematicColumnNode::onRenderToggleClicked(bool isActive) {
       stageScene->getXsheet()->getColumn(m_stageObject->getId().getIndex());
   if (column) {
     column->setPreviewVisible(isActive);
+    if (Preferences::instance()->isUnifyColumnVisibilityTogglesEnabled())
+      column->setCamstandVisible(isActive);
     emit sceneChanged();
     emit xsheetChanged();
   }
diff --git a/toonz/sources/toonzqt/styleselection.cpp b/toonz/sources/toonzqt/styleselection.cpp
index 5930e93..fa6ed8f 100644
--- a/toonz/sources/toonzqt/styleselection.cpp
+++ b/toonz/sources/toonzqt/styleselection.cpp
@@ -499,14 +499,14 @@ void TStyleSelection::enableCommands() {
     enableCommand(this, MI_PasteNames, &TStyleSelection::pasteStylesName);
 
     // available only for level palette
-    if (m_paletteHandle->getPalette()->getGlobalName() == L"") {
-      enableCommand(this, MI_GetColorFromStudioPalette,
-                    &TStyleSelection::getBackOriginalStyle);
+    if (m_paletteHandle->getPalette()->getGlobalName().empty()) {
       enableCommand(this, MI_ToggleLinkToStudioPalette,
                     &TStyleSelection::toggleLink);
-      enableCommand(this, MI_RemoveReferenceToStudioPalette,
-                    &TStyleSelection::removeLink);
     }
+    enableCommand(this, MI_GetColorFromStudioPalette,
+                  &TStyleSelection::getBackOriginalStyle);
+    enableCommand(this, MI_RemoveReferenceToStudioPalette,
+                  &TStyleSelection::removeLink);
   }
   enableCommand(this, MI_Clear, &TStyleSelection::deleteStyles);
   enableCommand(this, MI_EraseUnusedStyles, &TStyleSelection::eraseUnusedStyle);
@@ -1579,11 +1579,13 @@ class UndoRemoveLink final : public TUndo {
     bool m_oldEdittedFlag;
   };
   std::vector<ColorStyleData> m_styles;
+  bool m_isStudioPalette;
 
 public:
   UndoRemoveLink(TPaletteHandle *paletteHandle, int pageIndex)
       : m_paletteHandle(paletteHandle), m_pageIndex(pageIndex) {
-    m_palette = m_paletteHandle->getPalette();
+    m_palette         = m_paletteHandle->getPalette();
+    m_isStudioPalette = !m_palette->getGlobalName().empty();
   }
 
   ~UndoRemoveLink() {}
@@ -1618,7 +1620,13 @@ public:
     for (i = 0; i < (int)m_styles.size(); i++) {
       ColorStyleData data = m_styles[i];
       TColorStyle *cs     = page->getStyle(data.m_indexInPage);
-      cs->setGlobalName(L"");
+      if (m_isStudioPalette) {
+        int styleId = page->getStyleId(m_styles[i].m_indexInPage);
+        std::wstring gname =
+            L"-" + m_palette->getGlobalName() + L"-" + std::to_wstring(styleId);
+        cs->setGlobalName(gname);
+      } else
+        cs->setGlobalName(L"");
       cs->setOriginalName(L"");
       cs->setIsEditedFlag(false);
     }
@@ -1628,7 +1636,7 @@ public:
   int getSize() const override { return sizeof(*this); }
 
   QString getHistoryString() override {
-    return QObject::tr("Remove Reference  in Palette : %1")
+    return QObject::tr("Remove Reference in Palette : %1")
         .arg(QString::fromStdWString(m_palette->getPaletteName()));
   }
   int getHistoryType() override { return HistoryType::Palette; }
@@ -1636,7 +1644,9 @@ public:
 
 //-----------------------------------------------------------------------------
 /*! remove link from studio palette. Delete the global and the original names.
- * return true if something changed
+ * return true if something changed.
+ * If the target palette is the studio palette, set the global name and make
+ * the styles "link parent".
  */
 void TStyleSelection::removeLink() {
   TPalette *palette = getPalette();
@@ -1648,6 +1658,7 @@ void TStyleSelection::removeLink() {
   assert(page);
 
   bool somethingChanged = false;
+  bool isStudioPalette  = !palette->getGlobalName().empty();
 
   UndoRemoveLink *undo = new UndoRemoveLink(m_paletteHandle, m_pageIndex);
 
@@ -1656,7 +1667,17 @@ void TStyleSelection::removeLink() {
     TColorStyle *cs = page->getStyle(*it);
     assert(cs);
 
-    if (cs->getGlobalName() != L"" || cs->getOriginalName() != L"") {
+    if (isStudioPalette && !cs->getOriginalName().empty()) {
+      undo->setColorStyle(*it, cs);
+      int styleId = page->getStyleId(*it);
+      std::wstring gname =
+          L"-" + palette->getGlobalName() + L"-" + std::to_wstring(styleId);
+      cs->setGlobalName(gname);
+      cs->setOriginalName(L"");
+      cs->setIsEditedFlag(false);
+      somethingChanged = true;
+    } else if (!isStudioPalette &&
+               (cs->getGlobalName() != L"" || cs->getOriginalName() != L"")) {
       undo->setColorStyle(*it, cs);
 
       cs->setGlobalName(L"");
@@ -1780,6 +1801,8 @@ void TStyleSelection::getBackOriginalStyle() {
 
     // if the style has no link
     if (gname == L"") continue;
+    // if the style is link parent
+    if (cs->getOriginalName().empty()) continue;
 
     // Find the palette from the table
     int k = gname.find_first_of(L'-', 1);
@@ -1834,7 +1857,8 @@ void TStyleSelection::getBackOriginalStyle() {
 }
 
 //-----------------------------------------------------------------------------
-/*! return true if there is at least one linked style in the selection
+/*! return true if there is at least one linked style in the selection.
+    link parent styles are not counted
  */
 
 bool TStyleSelection::hasLinkedStyle() {
@@ -1845,13 +1869,18 @@ bool TStyleSelection::hasLinkedStyle() {
   TPalette::Page *page = palette->getPage(m_pageIndex);
   assert(page);
 
+  bool isStudioPalette = palette->getGlobalName() != L"";
+
   // for each selected style
   for (std::set<int>::iterator it = m_styleIndicesInPage.begin();
        it != m_styleIndicesInPage.end(); ++it) {
     TColorStyle *cs    = page->getStyle(*it);
     std::wstring gname = cs->getGlobalName();
     // if the style has link, return true
-    if (gname != L"" && (gname[0] == L'-' || gname[0] == L'+')) return true;
+    if (!gname.empty() && (gname[0] == L'+' || gname[0] == L'-') &&
+        !cs->getOriginalName().empty()) {
+      return true;
+    }
   }
   return false;
 }
diff --git a/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml b/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml
index 56e78ed..4f631a7 100644
--- a/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml
+++ b/toonz/sources/xdg-data/io.github.OpenToonz.appdata.xml
@@ -28,6 +28,6 @@
   </screenshots>
   <content_rating type="oars-1.1" />
   <releases>
-    <release version="1.7.0" date="2023-05-01"></release>
+    <release version="1.7.1" date="2023-05-10"></release>
   </releases>
 </component>