Browse Source

New Export Finished notification showing path and opening containing folder. Fix of #4917. Fixed wrongly grayed eject button in File menu. Hopefully fix of ctrl shortcut of tooltips at sidebar.

David Kocik 4 years ago
parent
commit
3ca3a544a8

+ 75 - 0
resources/icons/notification_eject_sd.svg

@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   viewBox="0 0 800 800"
+   style="enable-background:new 0 0 800 800;"
+   xml:space="preserve"
+   sodipodi:docname="notification_eject_sd_hover.svg"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"><metadata
+   id="metadata15"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+   id="defs13" /><sodipodi:namedview
+   inkscape:document-rotation="0"
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="3840"
+   inkscape:window-height="2066"
+   id="namedview11"
+   showgrid="false"
+   inkscape:zoom="1.26"
+   inkscape:cx="400"
+   inkscape:cy="396.42857"
+   inkscape:window-x="-11"
+   inkscape:window-y="-11"
+   inkscape:window-maximized="1"
+   inkscape:current-layer="Layer_1" />
+<style
+   type="text/css"
+   id="style2">
+	.st0{fill:#ED6B21;}
+</style>
+<path
+   style="stroke-width:0.85"
+   class="st0"
+   d="m 565.50264,534.98775 v 60.775 h -330.565 v -60.775 h 330.565 m 27.88,-48.195 h -386.24 c -11.22,0 -20.315,9.095 -20.315,20.315 v 116.535 c 0,11.22 9.095,20.315 20.315,20.315 h 386.24 c 11.22,0 20.315,-9.095 20.315,-20.315 v -116.45 c 0,-11.22 -9.095,-20.4 -20.315,-20.4 z"
+   id="path4" />
+<path
+   style="stroke-width:0.85"
+   class="st0"
+   d="m 400.09264,235.70275 116.96,155.295 h -233.75 l 116.79,-155.295 m 0,-66.64 c -6.12,0 -12.155,2.72 -16.235,8.16 l -172.635,229.5 c -10.115,13.43 -0.51,32.555 16.235,32.555 h 345.355 c 16.745,0 26.35,-19.125 16.235,-32.555 l -172.805,-229.5 c -3.995,-5.44 -10.03,-8.16 -16.15,-8.16 z"
+   id="path6" />
+<g
+   id="g4"
+   transform="matrix(0.9775,0,0,0.9775,53.547,53.54775)">
+	<path
+   id="path2"
+   class="st0"
+   d="M 597.2,701.3 H 110.6 C 53.2,701.3 6.5,654.6 6.5,597.2 V 110.6 C 6.5,53.2 53.2,6.5 110.6,6.5 h 486.6 c 57.4,0 104.1,46.7 104.1,104.1 v 486.6 c 0,57.4 -46.7,104.1 -104.1,104.1 z M 110.6,52.4 c -32,0 -58.2,26 -58.2,58.2 v 486.6 c 0,32 26,58.2 58.2,58.2 h 486.6 c 32,0 58.2,-26 58.2,-58.2 V 110.6 c 0,-32 -26,-58.2 -58.2,-58.2 z" />
+</g>
+<path
+   style="fill:#ed6b21;fill-opacity:1;stroke-width:0.674603"
+   d="m 150.65676,738.12999 c -12.4717,-1.39663 -26.66772,-5.94192 -37.84321,-12.11671 -17.754551,-9.80992 -33.768844,-26.68981 -42.418124,-44.71089 -5.985061,-12.4701 -8.760227,-23.35456 -9.821918,-38.52249 -0.48061,-6.8663 -0.640464,-87.42616 -0.497289,-250.61508 0.195544,-222.88027 0.294923,-240.94223 1.356742,-246.58759 4.2349,-22.51562 13.68014,-40.62012 29.200931,-55.97194 14.237938,-14.082924 31.958648,-23.427941 52.602238,-27.739791 5.87892,-1.227937 14.00696,-1.268146 256.3492,-1.268146 h 250.27778 l 7.08334,1.561512 c 21.30688,4.697075 36.90336,13.216072 51.96052,28.381502 14.67865,14.784203 23.1932,30.350373 27.76125,50.752683 l 1.56791,7.00271 v 250.95239 c 0,242.72256 -0.0418,251.15149 -1.26428,257.0238 -9.30592,44.69034 -45.18963,77.43352 -89.75566,81.90028 -9.17898,0.92002 -488.33076,0.87927 -496.55943,-0.0425 z M 652.87275,692.49 c 19.93824,-6.17834 34.6922,-21.42493 40.00111,-41.33675 l 1.51306,-5.67494 V 399.58544 153.69259 l -1.52571,-5.73412 c -5.66288,-21.28292 -21.4158,-36.89778 -42.2051,-41.83523 -5.63965,-1.33941 -7.66026,-1.3488 -253.17948,-1.17613 l -247.49447,0.17405 -4.72222,1.5953 c -18.05932,6.10093 -31.7315,19.23923 -37.4918,36.0278 -1.04762,3.05333 -2.22128,7.52472 -2.60813,9.93642 -0.47859,2.9836 -0.705,81.91876 -0.70847,246.99889 -0.005,218.14117 0.10226,243.1829 1.05916,248.25397 4.27172,22.63802 22.24346,40.86392 44.80877,45.4425 3.58848,0.72811 49.16893,0.87009 250.95237,0.78171 l 246.56747,-0.10801 z"
+   id="path17" /><path
+   style="fill:#ed6b21;fill-opacity:1;stroke-width:0.674603"
+   d="m 218.59688,436.65333 c -4.13129,-2.06443 -6.86895,-4.83026 -9.31331,-9.40915 -1.8345,-3.43648 -1.79343,-12.82008 0.0723,-16.52778 1.6224,-3.22405 174.17376,-232.72362 177.28101,-235.79015 3.40221,-3.35765 7.0012,-4.88322 12.34326,-5.23218 4.15899,-0.27168 5.32913,-0.0718 8.86231,1.51379 2.23886,1.00474 4.97342,2.78734 6.07682,3.96132 4.02813,4.28582 175.25817,232.2757 176.9048,235.54571 2.34584,4.65861 2.38759,12.10251 0.0927,16.52929 -2.00877,3.87485 -5.74351,7.80536 -9.18863,9.67026 l -2.69841,1.4607 -178.1462,0.17362 -178.14619,0.17362 z m 298.67589,-45.66907 c -0.0611,-1.0035 -116.48775,-154.99008 -117.18534,-154.99008 -0.71184,0 -116.84805,154.02591 -116.8632,154.99008 -0.004,0.27827 52.6617,0.50595 117.03571,0.50595 64.374,0 117.02978,-0.22768 117.01283,-0.50595 z"
+   id="path19" /><path
+   style="fill:#ed6b21;fill-opacity:1;stroke-width:0.674603"
+   d="m 202.23056,642.87591 c -4.08272,-1.10499 -7.53117,-3.30912 -10.37477,-6.63124 -4.63948,-5.42019 -4.43387,-2.10678 -4.42657,-71.33297 l 0.007,-62.44927 1.60268,-3.44194 c 1.88877,-4.05635 5.3977,-7.75734 9.36436,-9.8769 l 2.84915,-1.52243 h 199.00794 199.00793 l 2.84915,1.52243 c 3.96665,2.11956 7.47559,5.82055 9.36436,9.8769 l 1.60267,3.44194 0.007,62.44927 c 0.008,69.78764 0.26152,65.98231 -4.79028,71.72146 -1.4904,1.69319 -4.37627,3.87229 -6.52672,4.9283 l -3.85513,1.89304 -196.30953,0.12602 c -153.67069,0.0987 -196.97613,-0.0544 -199.37859,-0.70461 z M 565.87502,565.20052 V 534.50608 H 400.25994 234.64486 v 30.69444 30.69446 h 165.61508 165.61508 z"
+   id="path21" /></svg>

+ 76 - 0
resources/icons/notification_eject_sd_hover.svg

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Layer_1"
+   x="0px"
+   y="0px"
+   viewBox="0 0 800 800"
+   style="enable-background:new 0 0 800 800;"
+   xml:space="preserve"
+   sodipodi:docname="notification_eject_sd.svg"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"><metadata
+   id="metadata15"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+   id="defs13" /><sodipodi:namedview
+   inkscape:document-rotation="0"
+   pagecolor="#ffffff"
+   bordercolor="#666666"
+   borderopacity="1"
+   objecttolerance="10"
+   gridtolerance="10"
+   guidetolerance="10"
+   inkscape:pageopacity="0"
+   inkscape:pageshadow="2"
+   inkscape:window-width="1918"
+   inkscape:window-height="2054"
+   id="namedview11"
+   showgrid="false"
+   inkscape:zoom="1.26"
+   inkscape:cx="400"
+   inkscape:cy="401.5873"
+   inkscape:window-x="0"
+   inkscape:window-y="0"
+   inkscape:window-maximized="0"
+   inkscape:current-layer="Layer_1" />
+<style
+   type="text/css"
+   id="style2">
+	.st0{fill:#ED6B21;}
+</style>
+<path
+   class="st0"
+   d="M594.8,558.9v71.5H205.9v-71.5H594.8 M627.6,502.2H173.2c-13.2,0-23.9,10.7-23.9,23.9v137.1  c0,13.2,10.7,23.9,23.9,23.9h454.4c13.2,0,23.9-10.7,23.9-23.9V526.2C651.5,513,640.8,502.2,627.6,502.2L627.6,502.2z"
+   id="path4" />
+<path
+   class="st0"
+   d="M400.2,206.8l137.6,182.7h-275L400.2,206.8 M400.2,128.4c-7.2,0-14.3,3.2-19.1,9.6l-203.1,270  c-11.9,15.8-0.6,38.3,19.1,38.3h406.3c19.7,0,31-22.5,19.1-38.3l-203.3-270C414.5,131.6,407.4,128.4,400.2,128.4L400.2,128.4z"
+   id="path6" />
+<g
+   id="g4"
+   transform="matrix(1.15,0,0,1.15,-7.50075,-7.5)">
+	<path
+   id="path2"
+   class="st0"
+   d="M597.2,701.3H110.6c-57.4,0-104.1-46.7-104.1-104.1V110.6C6.5,53.2,53.2,6.5,110.6,6.5h486.6   c57.4,0,104.1,46.7,104.1,104.1v486.6C701.3,654.6,654.6,701.3,597.2,701.3z M110.6,52.4c-32,0-58.2,26-58.2,58.2v486.6   c0,32,26,58.2,58.2,58.2h486.6c32,0,58.2-26,58.2-58.2V110.6c0-32-26-58.2-58.2-58.2L110.6,52.4z" />
+</g>
+<path
+   style="fill:#ed6b21;fill-opacity:1;stroke-width:0.793651"
+   d="M 107.81901,798.00119 C 77.966509,794.83135 49.146122,779.90354 30.060545,757.72544 16.219297,741.64143 7.2605087,723.64471 2.5844311,702.53048 L 0.79365079,694.44444 V 399.60317 104.7619 L 2.5707889,96.74281 C 8.1200484,71.702533 18.222321,53.056007 35.651802,35.682695 53.220959,18.170156 71.802034,8.0954675 96.708127,2.5778576 L 104.7619,0.79365079 h 294.44445 c 281.74132,0 294.75136,0.0623952 301.55851,1.44626191 16.67428,3.3898194 30.80854,9.2277743 44.45639,18.3620833 30.56319,20.455498 49.17772,51.734599 52.83931,88.789134 0.52246,5.28681 0.71992,107.13501 0.57277,295.37077 -0.21452,274.44189 -0.28952,287.63907 -1.67476,294.84127 -9.63677,50.10325 -47.25156,87.71807 -97.3554,97.35548 -7.21079,1.38698 -20.15876,1.45445 -296.82539,1.54754 -159.10715,0.0532 -291.83859,-0.17373 -294.95877,-0.505 z m 582.70983,-52.40653 c 14.11333,-2.49918 25.86756,-8.65506 36.13916,-18.92666 10.4238,-10.4238 16.61917,-22.37735 18.96341,-36.58863 0.59763,-3.62296 0.78014,-91.16224 0.61306,-294.04762 -0.2267,-275.2812 -0.30507,-289.11319 -1.66353,-293.6508 -2.29132,-7.653498 -8.052,-18.790275 -12.80623,-24.757484 -7.93878,-9.964272 -18.57499,-17.346949 -31.48512,-21.854079 l -7.43245,-2.594784 -291.12328,-0.20372 C 142.50327,52.78948 110.02937,52.90047 105.30529,53.98405 79.968659,59.795581 61.031339,78.238321 54.164726,103.78898 l -1.754497,6.52848 -0.240323,282.14286 c -0.151001,177.27655 0.04527,285.53516 0.528069,291.26984 2.318854,27.5434 19.073236,49.76542 44.524247,59.05433 10.087718,3.68173 -4.026285,3.51395 301.243128,3.58099 197.57151,0.0434 288.82563,-0.19746 292.06349,-0.77082 z"
+   id="path19" /><path
+   id="path12"
+   d="M 107.81901,798.00119 C 71.793616,794.17587 39.726024,774.51428 19.725029,743.98814 11.604149,731.59381 6.0410683,718.13847 2.5844311,702.53048 L 0.79365079,694.44444 V 399.20635 103.96825 L 3.035741,94.554887 C 8.7824143,70.427608 18.557382,52.794942 35.676163,35.676161 52.78713,18.565194 70.514246,8.724096 94.444444,3.0513179 l 9.523806,-2.25766869 h 294.84127 c 282.12524,0 295.14809,0.0623746 301.95534,1.44626189 16.66109,3.3871391 30.79289,9.2216269 44.45639,18.3543829 30.53954,20.412782 49.17677,51.732756 52.83931,88.796836 0.52246,5.28681 0.71992,107.13501 0.57277,295.37077 -0.21452,274.44188 -0.28952,287.63907 -1.67476,294.84127 -8.48938,44.13777 -38.62564,78.86883 -80.59962,92.88841 -19.37815,6.47239 11.16453,5.88739 -313.58117,6.0062 -159.10715,0.0579 -291.83859,-0.16532 -294.95877,-0.49659 z m 583.84766,-52.6969 c 13.48971,-2.42242 24.94716,-8.60413 35.32488,-19.05909 10.25229,-10.3286 16.66154,-22.92711 18.61985,-36.60068 0.66689,-4.65647 0.83196,-81.74243 0.62956,-294.0096 C 745.9846,126.77174 745.87745,107.60752 744.6044,102.9114 738.42079,80.100871 721.07257,62.283764 697.9879,55.03493 l -5.92441,-1.860328 H 399.20635 106.34921 L 98.809524,55.78721 C 75.623265,63.821579 59.178748,82.101475 53.902861,105.70593 52.59901,111.53938 52.514615,128.88593 52.47105,400 l -0.04629,288.09524 2.080286,7.60155 c 6.270993,22.91476 22.15377,39.95711 44.384633,47.62505 3.584011,1.23621 7.998091,1.91356 14.999211,2.30168 5.45635,0.30249 136.34921,0.59491 290.87301,0.64982 232.38849,0.0826 281.98128,-0.0849 286.90477,-0.96905 z"
+   style="fill:#ed6b21;fill-opacity:1;stroke-width:0.793651" /><path
+   id="path14"
+   d="m 188.74939,444.33528 c -4.767,-1.68913 -10.12828,-6.7592 -12.71276,-12.02223 -2.90908,-5.92405 -3.07868,-13.78271 -0.41474,-19.21781 1.59087,-3.24578 204.04455,-273.05533 208.24079,-277.52202 0.98764,-1.05129 4.03672,-3.01468 6.77574,-4.3631 4.52929,-2.22976 5.50158,-2.41761 10.74224,-2.07541 6.86047,0.44798 10.76603,2.25377 15.37601,7.10932 3.73681,3.93587 203.30677,268.8636 207.0044,274.79691 2.05716,3.30097 2.4722,4.84315 2.70946,10.06767 0.23771,5.23447 -0.0137,6.8089 -1.6588,10.38763 -2.76417,6.01319 -5.53229,8.93875 -11.0814,11.71167 l -4.85687,2.42701 -208.40498,-0.0627 c -181.84257,-0.0547 -208.82739,-0.21233 -211.71909,-1.23698 z m 348.94902,-54.98925 c 0,-0.9027 -136.36908,-182.10669 -137.30528,-182.44799 -0.54415,-0.19837 -135.36926,178.28524 -137.53574,182.07198 -0.54249,0.9482 19.37332,1.10934 137.10317,1.10934 83.74346,0 137.73785,-0.28747 137.73785,-0.73333 z"
+   style="fill:#ed6b21;fill-opacity:1;stroke-width:0.793651" /><path
+   id="path16"
+   d="m 168.25397,686.16973 c -7.05465,-1.71645 -13.06577,-6.58064 -16.33102,-13.21504 L 150,669.04762 v -74.20635 -74.20635 l 1.8935,-4.19003 c 1.12593,-2.49152 3.46026,-5.59868 5.75857,-7.66505 7.33695,-6.59655 -16.73947,-6.00214 243.08455,-6.00144 l 231.80306,6.3e-4 4.76912,2.2562 c 5.31341,2.5137 9.30333,6.56248 11.81369,11.98794 1.66145,3.59075 1.67116,4.0432 1.67116,77.8181 v 74.20635 l -1.92294,3.90707 c -2.44721,4.97227 -6.5951,9.12016 -11.60261,11.6026 l -3.93477,1.95064 -231.3492,0.12055 c -127.24207,0.0663 -232.42064,-0.14013 -233.73016,-0.45875 z m 426.5873,-91.72529 V 558.33333 H 400 205.15873 v 36.11111 36.11111 H 400 594.84127 Z"
+   style="fill:#ed6b21;fill-opacity:1;stroke-width:0.793651" /></svg>

+ 2 - 0
src/imgui/imconfig.h

@@ -121,6 +121,8 @@ namespace ImGui
     const char MinimalizeHoverMarker   = 0xF;
 	const char WarningMarker           = 0x10;
 	const char ErrorMarker             = 0x11;
+    const char EjectMarker             = 0x12;
+    const char EjectHoverMarker        = 0x13;
 //    void MyFunction(const char* name, const MyMatrix44& v);
 
 }

+ 1 - 0
src/libslic3r/Exception.hpp

@@ -20,6 +20,7 @@ SLIC3R_DERIVE_EXCEPTION(OutOfRange,         LogicError);
 SLIC3R_DERIVE_EXCEPTION(IOError,            CriticalException);
 SLIC3R_DERIVE_EXCEPTION(FileIOError,        IOError);
 SLIC3R_DERIVE_EXCEPTION(HostNetworkError,   IOError);
+SLIC3R_DERIVE_EXCEPTION(ExportError,      CriticalException);
 // Runtime exception produced by Slicer. Such exception cancels the slicing process and it shall be shown in notifications.
 SLIC3R_DERIVE_EXCEPTION(SlicingError,       Exception);
 #undef SLIC3R_DERIVE_EXCEPTION

+ 2 - 2
src/libslic3r/Zipper.cpp

@@ -25,12 +25,12 @@ public:
     std::string formatted_errorstr() const
     {
         return L("Error with zip archive") + " " + m_zipname + ": " +
-               get_errorstr() + "!";
+               get_errorstr();
     }
 
     SLIC3R_NORETURN void blow_up() const
     {
-        throw Slic3r::RuntimeError(formatted_errorstr());
+        throw Slic3r::ExportError(formatted_errorstr());
     }
 
     bool is_alive()

+ 5 - 9
src/libslic3r/utils.cpp

@@ -429,24 +429,20 @@ CopyFileResult copy_file_inner(const std::string& from, const std::string& to, s
 	// the copy_file() function will fail appropriately and we don't want the permission()
 	// calls to cause needless failures on permissionless filesystems (ie. FATs on SD cards etc.)
 	// or when the target file doesn't exist.
-	
-	//This error code is ignored
 	boost::system::error_code ec;
-	
 	boost::filesystem::permissions(target, perms, ec);
-	//if (ec)
-	//	BOOST_LOG_TRIVIAL(error) << "Copy file permisions before copy error message: " << ec.message();
-	// This error code is passed up
+	if (ec)
+		BOOST_LOG_TRIVIAL(error) << "boost::filesystem::permisions before copy error message (this could be irrelevant message based on file system): " << ec.message();
 	ec.clear();
 	boost::filesystem::copy_file(source, target, boost::filesystem::copy_option::overwrite_if_exists, ec);
 	if (ec) {
 		error_message = ec.message();
 		return FAIL_COPY_FILE;
 	}
-	//ec.clear();
+	ec.clear();
 	boost::filesystem::permissions(target, perms, ec);
-	//if (ec)
-	//	BOOST_LOG_TRIVIAL(error) << "Copy file permisions after copy error message: " << ec.message();
+	if (ec)
+		BOOST_LOG_TRIVIAL(error) << "boost::filesystem::permisions after copy error message (this could be irrelevant message based on file system): " << ec.message();
 	return SUCCESS;
 }
 

+ 23 - 5
src/slic3r/GUI/BackgroundSlicingProcess.cpp

@@ -53,6 +53,24 @@ bool SlicingProcessCompletedEvent::critical_error() const
 	return true;
 }
 
+bool SlicingProcessCompletedEvent::invalidate_plater() const
+{
+	if (critical_error())
+	{
+		try {
+			this->rethrow_exception();
+		}
+		catch (const Slic3r::ExportError&) {
+			// Exception thrown by copying file does not ivalidate plater
+			return false;
+		}
+		catch (...) {
+		}
+		return true;
+	}
+	return false;
+}
+
 std::string SlicingProcessCompletedEvent::format_error_message() const
 {
 	std::string error;
@@ -142,19 +160,19 @@ void BackgroundSlicingProcess::process_fff()
 			switch (copy_ret_val) {
 			case SUCCESS: break; // no error
 			case FAIL_COPY_FILE:
-				throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?\nError message: %1%"))) % error_message).str());
+				throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?\nError message: %1%"))) % error_message).str());
 				break;
 			case FAIL_FILES_DIFFERENT: 
-				throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at %1%.tmp."))) % export_path).str());
+				throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at %1%.tmp."))) % export_path).str());
 				break;
 			case FAIL_RENAMING: 
-				throw Slic3r::RuntimeError((boost::format(_utf8(L("Renaming of the G-code after copying to the selected destination folder has failed. Current path is %1%.tmp. Please try exporting again."))) % export_path).str()); 
+				throw Slic3r::ExportError((boost::format(_utf8(L("Renaming of the G-code after copying to the selected destination folder has failed. Current path is %1%.tmp. Please try exporting again."))) % export_path).str());
 				break;
 			case FAIL_CHECK_ORIGIN_NOT_OPENED: 
-				throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the original code at %1% couldn't be opened during copy check. The output G-code is at %2%.tmp."))) % m_temp_output_path % export_path).str());
+				throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the original code at %1% couldn't be opened during copy check. The output G-code is at %2%.tmp."))) % m_temp_output_path % export_path).str());
 				break;
 			case FAIL_CHECK_TARGET_NOT_OPENED: 
-				throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the exported code couldn't be opened during copy check. The output G-code is at %1%.tmp."))) % export_path).str()); 
+				throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the exported code couldn't be opened during copy check. The output G-code is at %1%.tmp."))) % export_path).str());
 				break;
 			default:
 				throw Slic3r::RuntimeError(_utf8(L("Unknown error occured during exporting G-code.")));

+ 2 - 0
src/slic3r/GUI/BackgroundSlicingProcess.hpp

@@ -57,6 +57,8 @@ public:
 	bool		error() 	const { return m_status == Error; }
 	// Unhandled error produced by stdlib or a Win32 structured exception, or unhandled Slic3r's own critical exception.
 	bool 		critical_error() const;
+	// Critical errors does invalidate plater except CopyFileError.
+	bool        invalidate_plater() const;
 	// Only valid if error()
 	void 		rethrow_exception() const { assert(this->error()); assert(m_exception); std::rethrow_exception(m_exception); }
 	// Produce a human readable message to be displayed by a notification or a message box.

+ 3 - 1
src/slic3r/GUI/ImGuiWrapper.cpp

@@ -49,7 +49,9 @@ static const std::map<const char, std::string> font_icons = {
     {ImGui::MinimalizeMarker      , "notification_minimalize"       },
     {ImGui::MinimalizeHoverMarker , "notification_minimalize_hover" },
 	{ImGui::WarningMarker         , "notification_warning"          },
-    {ImGui::ErrorMarker           , "notification_error"            }
+    {ImGui::ErrorMarker           , "notification_error"            },
+    {ImGui::EjectMarker           , "notification_eject_sd"         },
+    {ImGui::EjectHoverMarker      , "notification_eject_sd_hover"   },
 };
 
 const ImVec4 ImGuiWrapper::COL_GREY_DARK         = { 0.333f, 0.333f, 0.333f, 1.0f };

+ 247 - 28
src/slic3r/GUI/NotificationManager.cpp

@@ -1,6 +1,7 @@
 #include "NotificationManager.hpp"
 
 #include "GUI_App.hpp"
+#include "GUI.hpp"
 #include "Plater.hpp"
 #include "GLCanvas3D.hpp"
 #include "ImGuiWrapper.hpp"
@@ -33,6 +34,56 @@ namespace Notifications_Internal{
 		else
 			ImGui::PushStyleColor(idx, col);
 	}
+
+	void open_folder(const std::string& path)
+	{
+		// Code taken from desktop_open_datadir_folder()
+
+		// Execute command to open a file explorer, platform dependent.
+		// FIXME: The const_casts aren't needed in wxWidgets 3.1, remove them when we upgrade.
+
+#ifdef _WIN32
+		const wxString widepath = from_u8(path);
+		const wchar_t* argv[] = { L"explorer", widepath.GetData(), nullptr };
+		::wxExecute(const_cast<wchar_t**>(argv), wxEXEC_ASYNC, nullptr);
+#elif __APPLE__
+		const char* argv[] = { "open", path.data(), nullptr };
+		::wxExecute(const_cast<char**>(argv), wxEXEC_ASYNC, nullptr);
+#else
+		const char* argv[] = { "xdg-open", path.data(), nullptr };
+
+		// Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars,
+		// because they may mess up the environment expected by the file manager.
+		// Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure.
+		if (wxGetEnv("APPIMAGE", nullptr)) {
+			// We're running from AppImage
+			wxEnvVariableHashMap env_vars;
+			wxGetEnvMap(&env_vars);
+
+			env_vars.erase("APPIMAGE");
+			env_vars.erase("APPDIR");
+			env_vars.erase("LD_LIBRARY_PATH");
+			env_vars.erase("LD_PRELOAD");
+			env_vars.erase("UNION_PRELOAD");
+
+			wxExecuteEnv exec_env;
+			exec_env.env = std::move(env_vars);
+
+			wxString owd;
+			if (wxGetEnv("OWD", &owd)) {
+				// This is the original work directory from which the AppImage image was run,
+				// set it as CWD for the child process:
+				exec_env.cwd = std::move(owd);
+			}
+
+			::wxExecute(const_cast<char**>(argv), wxEXEC_ASYNC, nullptr, &exec_env);
+		}
+		else {
+			// Looks like we're NOT running from AppImage, we'll make no changes to the environment.
+			::wxExecute(const_cast<char**>(argv), wxEXEC_ASYNC, nullptr, nullptr);
+		}
+#endif
+	}
 }
 
 #if 1
@@ -183,6 +234,7 @@ NotificationManager::PopNotification::RenderResult NotificationManager::PopNotif
 			render_left_sign(imgui);
 			render_text(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
 			render_close_button(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
+			m_minimize_b_visible = false;
 			if (m_multiline && m_lines_count > 3)
 				render_minimize_button(imgui, win_pos.x, win_pos.y);
 		} else {
@@ -205,12 +257,8 @@ NotificationManager::PopNotification::RenderResult NotificationManager::PopNotif
 		ImGui::PopStyleColor();
 	return ret_val;
 }
-void NotificationManager::PopNotification::init()
+void NotificationManager::PopNotification::count_spaces()
 {
-	std::string text          = m_text1 + " " + m_hypertext;
-	int         last_end      = 0;
-	            m_lines_count = 0;
-
 	//determine line width 
 	m_line_height = ImGui::CalcTextSize("A").y;
 
@@ -221,8 +269,16 @@ void NotificationManager::PopNotification::init()
 		float picture_width = ImGui::CalcTextSize(text.c_str()).x;
 		m_left_indentation = picture_width + m_line_height / 2;
 	}
-	m_window_width_offset = m_left_indentation + m_line_height * 2;
+	m_window_width_offset = m_left_indentation + m_line_height * 3.f;
 	m_window_width = m_line_height * 25;
+}
+void NotificationManager::PopNotification::init()
+{
+	std::string text          = m_text1 + " " + m_hypertext;
+	int         last_end      = 0;
+	            m_lines_count = 0;
+
+	count_spaces();
 	
 	// count lines
 	m_endlines.clear();
@@ -233,10 +289,9 @@ void NotificationManager::PopNotification::init()
 			//next line is ended by '/n'
 			m_endlines.push_back(next_hard_end);
 			last_end = next_hard_end + 1;
-		}
-		else {
+		} else {
 			// find next suitable endline
-			if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - 3.5f * m_line_height) {// m_window_width_offset) {
+			if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset) {
 				// more than one line till end
 				int next_space = text.find_first_of(' ', last_end);
 				if (next_space > 0) {
@@ -245,8 +300,19 @@ void NotificationManager::PopNotification::init()
 						next_space = next_space_candidate;
 						next_space_candidate = text.find_first_of(' ', next_space + 1);
 					}
-					m_endlines.push_back(next_space);
-					last_end = next_space + 1;
+					// when one word longer than line.
+					if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset) {
+						float width_of_a = ImGui::CalcTextSize("a").x;
+						int letter_count = (int)((m_window_width - m_window_width_offset) / width_of_a);
+						while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset) {
+							letter_count++;
+						}
+						m_endlines.push_back(last_end + letter_count);
+						last_end += letter_count;
+					} else {
+						m_endlines.push_back(next_space);
+						last_end = next_space + 1;
+					}
 				}
 			}
 			else {
@@ -257,6 +323,8 @@ void NotificationManager::PopNotification::init()
 		}
 		m_lines_count++;
 	}
+	if (m_lines_count == 3)
+		m_multiline = true;
 	m_initialized = true;
 }
 void NotificationManager::PopNotification::set_next_window_size(ImGuiWrapper& imgui)
@@ -285,7 +353,8 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
 			float shift_y = m_line_height;// -m_line_height / 20;
 			for (size_t i = 0; i < m_lines_count; i++) {
 			    std::string line = m_text1.substr(last_end , m_endlines[i] - last_end);
-				last_end = m_endlines[i] + 1;
+				if(i < m_lines_count - 1)
+					last_end = m_endlines[i] + (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
 				ImGui::SetCursorPosX(x_offset);
 				ImGui::SetCursorPosY(starting_y + i * shift_y);
 				imgui.text(line.c_str());
@@ -303,7 +372,7 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
 			ImGui::SetCursorPosY(win_size.y / 2 - win_size.y / 6 - m_line_height / 2);
 			imgui.text(m_text1.substr(0, m_endlines[0]).c_str());
 			// line2
-			std::string line = m_text1.substr(m_endlines[0] + 1, m_endlines[1] - m_endlines[0] - 1);
+			std::string line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0), m_endlines[1] - m_endlines[0] - (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
 			if (ImGui::CalcTextSize(line.c_str()).x > m_window_width - m_window_width_offset - ImGui::CalcTextSize((".." + _u8L("More")).c_str()).x)
 			{
 				line = line.substr(0, line.length() - 6);
@@ -326,7 +395,7 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons
 			ImGui::SetCursorPosY(win_size.y / 2 - win_size.y / 6 - m_line_height / 2);
 			imgui.text(m_text1.substr(0, m_endlines[0]).c_str());
 			// line2
-			std::string line = m_text1.substr(m_endlines[0] + 1);
+			std::string line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
 			cursor_y = win_size.y / 2 + win_size.y / 6 - m_line_height / 2;
 			ImGui::SetCursorPosX(x_offset);
 			ImGui::SetCursorPosY(cursor_y);
@@ -375,8 +444,7 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
 			set_next_window_size(imgui);
 		}
 		else {
-			on_text_click();
-			m_close_pending = true;
+			m_close_pending = on_text_click();
 		}
 	}
 	ImGui::PopStyleColor();
@@ -407,7 +475,7 @@ void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui,
 void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
 {
 	ImVec2 win_size(win_size_x, win_size_y);
-	ImVec2 win_pos(win_pos_x, win_pos_y);
+	ImVec2 win_pos(win_pos_x, win_pos_y); 
 	ImVec4 orange_color = ImGui::GetStyleColorVec4(ImGuiCol_Button);
 	orange_color.w = 0.8f;
 	ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
@@ -422,7 +490,7 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
 	button_text = ImGui::CloseIconMarker;
 	
 	if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y),
-		                           ImVec2(win_pos.x, win_pos.y + win_size.y - (m_multiline? 2 * m_line_height : 0)),
+		                           ImVec2(win_pos.x, win_pos.y + win_size.y - ( m_minimize_b_visible ? 2 * m_line_height : 0)),
 		                           true))
 	{
 		button_text = ImGui::CloseIconHoverMarker;
@@ -435,11 +503,10 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
 	{
 		m_close_pending = true;
 	}
-
 	//invisible large button
-	ImGui::SetCursorPosX(win_size.x - win_size.x / 10.f);
+	ImGui::SetCursorPosX(win_size.x - m_line_height * 2.125);
 	ImGui::SetCursorPosY(0);
-	if (imgui.button(" ", win_size.x / 10.f, win_size.y - (m_multiline ? 2 * m_line_height : 0)))
+	if (imgui.button(" ", m_line_height * 2.125, win_size.y - ( m_minimize_b_visible ? 2 * m_line_height : 0)))
 	{
 		m_close_pending = true;
 	}
@@ -540,15 +607,12 @@ void NotificationManager::PopNotification::render_minimize_button(ImGuiWrapper&
 	ImGui::PopStyleColor();
 	ImGui::PopStyleColor();
 	ImGui::PopStyleColor();
+	m_minimize_b_visible = true;
 }
-void NotificationManager::PopNotification::on_text_click()
+bool NotificationManager::PopNotification::on_text_click()
 {
+	bool ret = true;
 	switch (m_data.type) {
-	case NotificationType::ExportToRemovableFinished :
-		assert(m_evt_handler != nullptr);
-		if (m_evt_handler != nullptr)
-			wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED));
-		break;
 	case NotificationType::SlicingComplete :
 		//wxGetApp().plater()->export_gcode(false);
 		assert(m_evt_handler != nullptr);
@@ -567,6 +631,7 @@ void NotificationManager::PopNotification::on_text_click()
 	default:
 		break;
 	}
+	return ret;
 }
 void NotificationManager::PopNotification::update(const NotificationData& n)
 {
@@ -633,6 +698,127 @@ void NotificationManager::SlicingCompleteLargeNotification::set_large(bool l)
 	m_hypertext = l ? _u8L("Export G-Code.") : std::string();
 	m_hidden = !l;
 }
+//---------------ExportFinishedNotification-----------
+void NotificationManager::ExportFinishedNotification::count_spaces()
+{
+	//determine line width 
+	m_line_height = ImGui::CalcTextSize("A").y;
+
+	m_left_indentation = m_line_height;
+	if (m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) {
+		std::string text;
+		text = (m_data.level == NotificationLevel::ErrorNotification ? ImGui::ErrorMarker : ImGui::WarningMarker);
+		float picture_width = ImGui::CalcTextSize(text.c_str()).x;
+		m_left_indentation = picture_width + m_line_height / 2;
+	}
+	//TODO count this properly
+	m_window_width_offset = m_left_indentation + m_line_height * (m_to_removable ? 5.f : 3.f);
+	m_window_width = m_line_height * 25;
+}
+
+void NotificationManager::ExportFinishedNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
+{
+	
+	ImVec2      win_size(win_size_x, win_size_y);
+	ImVec2      win_pos(win_pos_x, win_pos_y);
+	float       x_offset = m_left_indentation;
+	std::string fulltext = m_text1 + m_hypertext; //+ m_text2;
+	ImVec2      text_size = ImGui::CalcTextSize(fulltext.c_str());
+	// Lines are always at least two and m_multiline is always true for ExportFinishedNotification.
+	// First line has "Export Finished" text and than hyper text open folder.
+	// Following lines are path to gcode.
+	int last_end = 0;
+	float starting_y = m_line_height / 2;//10;
+	float shift_y = m_line_height;// -m_line_height / 20;
+	for (size_t i = 0; i < m_lines_count; i++) {
+		std::string line = m_text1.substr(last_end, m_endlines[i] - last_end);
+		if (i < m_lines_count - 1)
+			last_end = m_endlines[i] + (m_text1[m_endlines[i]] == '\n' || m_text1[m_endlines[i]] == ' ' ? 1 : 0);
+		ImGui::SetCursorPosX(x_offset);
+		ImGui::SetCursorPosY(starting_y + i * shift_y);
+		imgui.text(line.c_str());
+		//hyperlink text
+		if ( i == 0 )  {
+			render_hypertext(imgui, x_offset + ImGui::CalcTextSize(m_text1.substr(0, last_end).c_str()).x + ImGui::CalcTextSize("   ").x, starting_y, _u8L("Open Folder."));
+		}
+	}
+
+}
+
+void NotificationManager::ExportFinishedNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
+{
+	PopNotification::render_close_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
+	if(m_to_removable)
+		render_eject_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
+}
+
+void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
+{
+	ImVec2 win_size(win_size_x, win_size_y);
+	ImVec2 win_pos(win_pos_x, win_pos_y);
+	ImVec4 orange_color = ImGui::GetStyleColorVec4(ImGuiCol_Button);
+	orange_color.w = 0.8f;
+	ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
+	ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
+	Notifications_Internal::push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_fading_out, m_current_fade_opacity);
+	Notifications_Internal::push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_fading_out, m_current_fade_opacity);
+	ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
+
+	std::string button_text;
+	button_text = ImGui::EjectMarker;
+	
+    if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - m_line_height * 4.5f, win_pos.y),
+		ImVec2(win_pos.x - m_line_height * 2.5f, win_pos.y + win_size.y),
+		true))
+	{
+		button_text = ImGui::EjectHoverMarker;
+		// tooltip
+		long time_now = wxGetLocalTime();
+		if (m_hover_time > 0 && m_hover_time < time_now) {
+			ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
+			ImGui::BeginTooltip();
+			imgui.text(_u8L("Eject drive"));
+			ImGui::EndTooltip();
+			ImGui::PopStyleColor();
+		} 
+		if (m_hover_time == 0)
+			m_hover_time = time_now;
+	} else 
+		m_hover_time = 0;
+
+	ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
+	ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
+	ImGui::SetCursorPosX(win_size.x - m_line_height * 4.f);
+	ImGui::SetCursorPosY(win_size.y / 2 - button_size.y / 2);
+	if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
+	{
+		assert(m_evt_handler != nullptr);
+		if (m_evt_handler != nullptr)
+			wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED));
+		m_close_pending = true;
+	}
+
+	//invisible large button
+	ImGui::SetCursorPosX(win_size.x - m_line_height * 4.625f);
+	ImGui::SetCursorPosY(0);
+	if (imgui.button("  ", m_line_height * 2.f, win_size.y))
+	{
+		assert(m_evt_handler != nullptr);
+		if (m_evt_handler != nullptr)
+			wxPostEvent(m_evt_handler, EjectDriveNotificationClickedEvent(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED));
+		m_close_pending = true;
+	}
+	ImGui::PopStyleColor();
+	ImGui::PopStyleColor();
+	ImGui::PopStyleColor();
+	ImGui::PopStyleColor();
+	ImGui::PopStyleColor();
+}
+bool NotificationManager::ExportFinishedNotification::on_text_click()
+{
+	Notifications_Internal::open_folder(m_export_dir_path);
+	return false;
+}
 //------NotificationManager--------
 NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
 	m_evt_handler(evt_handler)
@@ -789,6 +975,13 @@ void NotificationManager::remove_slicing_warnings_of_released_objects(const std:
 				notification->close();
 		}
 }
+void NotificationManager::push_exporting_finished_notification(GLCanvas3D& canvas, std::string path, std::string dir_path, bool on_removable)
+{
+	close_notification_of_type(NotificationType::ExportFinished);
+	NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotification, 0,  _u8L("Exporting finished.") +"\n"+ path };
+	push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path),
+		canvas, 0);
+}
 bool NotificationManager::push_notification_data(const NotificationData &notification_data,  GLCanvas3D& canvas, int timestamp)
 {
 	return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), canvas, timestamp);
@@ -822,7 +1015,7 @@ void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay
 	bool     hovered = false;
 	sort_notifications();
 	// iterate thru notifications and render them / erease them
-	for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
+	for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) { 
 		if ((*it)->get_finished()) {
 			it = m_pop_notifications.erase(it);
 		} else {
@@ -931,5 +1124,31 @@ bool NotificationManager::has_slicing_error_notification()
     });
 }
 
+void NotificationManager::new_export_began(bool on_removable)
+{
+	close_notification_of_type(NotificationType::ExportFinished);
+	// If we want to hold information of ejecting removable on later export finished notifications
+	/*
+	for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
+		if (notification->get_type() == NotificationType::ExportToRemovableFinished) {
+			if (!on_removable) {
+				const NotificationData old_data = notification->get_data();
+				notification->update( {old_data.type, old_data.level ,old_data.duration, std::string(), old_data.hypertext} );
+			} else {
+				notification->close();
+			}
+			return;
+		}
+	}
+	*/
+}
+void NotificationManager::device_ejected()
+{
+	for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
+		if (notification->get_type() == NotificationType::ExportFinished && dynamic_cast<ExportFinishedNotification*>(notification.get())->m_to_removable)
+			notification->close();
+	}
+}
+
 }//namespace GUI
 }//namespace Slic3r

Some files were not shown because too many files changed in this diff