<div dir="ltr"><div class="gmail_extra" style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial"><span class="gmail-im" style="color:rgb(80,0,80)"><div class="gmail_quote">On 16 July 2018 at 19:57, Phil Thompson<span> </span><span dir="ltr"><<a href="mailto:phil@riverbankcomputing.com" target="_blank" style="color:rgb(17,85,204)">phil@riverbankcomputing.com</a>></span><span> </span>wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail-m_7833282403167241560gmail-m_3415079511633522678HOEnZb"><div class="gmail-m_7833282403167241560gmail-m_3415079511633522678h5"><span style="color:rgb(34,34,34)">A small, complete example would help.</span><br></div></div></blockquote></div><div class="gmail_extra"><br></div></span><div class="gmail_extra">Good suggestion. In creating a self-contained example, I actually figured out how</div><div class="gmail_extra">to fix the problem. Here is my code in case others are interested:</div><div class="gmail_extra"><br></div><div class="gmail_extra"><div class="gmail_extra">from PyQt5.QtMacExtras import QMacPasteboardMime</div><div class="gmail_extra"><br></div><div class="gmail_extra">class MacClipboardFix(<wbr>QMacPasteboardMime):</div><div class="gmail_extra"><span style="white-space:pre-wrap">    </span>"""</div><div class="gmail_extra"><span style="white-space:pre-wrap"> </span>Work around QTBUG-61562 on Mac, which can be reproduced as follows:</div><div class="gmail_extra"><br></div><div class="gmail_extra"><span style="white-space:pre-wrap">         </span>from PyQt5.QtWidgets import QApplication</div><div class="gmail_extra"><span style="white-space:pre-wrap">           </span>app = QApplication([])</div><div class="gmail_extra"><span style="white-space:pre-wrap">             </span>app.clipboard().setText('<wbr>Hello')</div><div class="gmail_extra"><br></div><div class="gmail_extra"><span style="white-space:pre-wrap"> </span>Now paste into Excel or Pycharm. The text that gets pasted is not just</div><div class="gmail_extra"><span style="white-space:pre-wrap">     </span>'Hello' but '\uFEFFHello'.</div><span class="gmail-im" style="color:rgb(80,0,80)"><div class="gmail_extra"><span style="white-space:pre-wrap">     </span>"""</div><div class="gmail_extra"><span style="white-space:pre-wrap"> </span>def __init__(self):</div><div class="gmail_extra"><span style="white-space:pre-wrap">                </span>super().__init__(<wbr>QMacPasteboardMime.MIME_CLIP)</div><div class="gmail_extra"><span style="white-space:pre-wrap">  </span>def convertorName(self):</div><div class="gmail_extra"><span style="white-space:pre-wrap">           </span>return 'UnicodeTextUtf8Default'</div><div class="gmail_extra"><span style="white-space:pre-wrap">    </span>def flavorFor(self, mime):</div><div class="gmail_extra"><span style="white-space:pre-wrap">         </span>if mime == 'text/plain':</div><div class="gmail_extra"><span style="white-space:pre-wrap">                   </span>return 'public.utf8-plain-text'</div></span><div class="gmail_extra"><span style="white-space:pre-wrap">               </span>parts = mime.split('charset=', 1)</div><div class="gmail_extra"><span style="white-space:pre-wrap">          </span>if len(parts) > 1:</div><div class="gmail_extra"><span style="white-space:pre-wrap">                      </span>charset = parts[1].split(';', 1)[0]</div><span class="gmail-im" style="color:rgb(80,0,80)"><div class="gmail_extra"><span style="white-space:pre-wrap">                    </span>if charset == 'system':</div><div class="gmail_extra"><span style="white-space:pre-wrap">                            </span>return 'public.utf8-plain-text'</div></span><div class="gmail_extra"><span style="white-space:pre-wrap">                       </span>if charset in ('iso-106464-ucs-2', 'utf16'):</div><span class="gmail-im" style="color:rgb(80,0,80)"><div class="gmail_extra"><span style="white-space:pre-wrap">                           </span>return 'public.utf16-plain-text'</div><div class="gmail_extra"><span style="white-space:pre-wrap">           </span>return None</div><div class="gmail_extra"><span style="white-space:pre-wrap">        </span>def canConvert(self, mime, flav):</div><div class="gmail_extra"><span style="white-space:pre-wrap">          </span>return mime.startswith('text/plain') and \</div><div class="gmail_extra"><span style="white-space:pre-wrap">                 </span>flav in ('public.utf8-plain-text', 'public.utf16-plain-text')</div><div class="gmail_extra"><span style="white-space:pre-wrap">      </span>def mimeFor(self, flavor):</div><div class="gmail_extra"><span style="white-space:pre-wrap">         </span>if flavor == 'public.utf8-plain-text':</div><div class="gmail_extra"><span style="white-space:pre-wrap">                     </span>return 'text/plain'</div><div class="gmail_extra"><span style="white-space:pre-wrap">                </span>if flavor == 'public.utf16-plain-text':</div><div class="gmail_extra"><span style="white-space:pre-wrap">                    </span>return 'text/plain;charset=utf16'</div><div class="gmail_extra"><span style="white-space:pre-wrap">          </span>return None</div></span><div class="gmail_extra"><span style="white-space:pre-wrap">   </span>def convertFromMime(self, mime, data, flavor):</div><div class="gmail_extra"><span style="white-space:pre-wrap">             </span>if flavor == 'public.utf8-plain-text':</div><div class="gmail_extra"><span style="white-space:pre-wrap">                     </span>return [data.encode('utf-8')]</div><div class="gmail_extra"><span style="white-space:pre-wrap">              </span>if flavor == 'public.utf16-plain-text':</div><div class="gmail_extra"><span style="white-space:pre-wrap">                    </span>return [data.encode('utf-16')]</div><div class="gmail_extra"><span style="white-space:pre-wrap">             </span>return []</div><div class="gmail_extra"><span style="white-space:pre-wrap">  </span>def convertToMime(self, mime, data, flavor):</div><div class="gmail_extra"><span style="white-space:pre-wrap">               </span>if len(data) > 1:</div><div class="gmail_extra"><span style="white-space:pre-wrap">                       </span>raise ValueError('Cannot handle multiple data members')</div><div class="gmail_extra"><span style="white-space:pre-wrap">            </span>data, = data</div><div class="gmail_extra"><span style="white-space:pre-wrap">               </span>if flavor == 'public.utf8-plain-text':</div><div class="gmail_extra"><span style="white-space:pre-wrap">                     </span>return data.decode('utf-8')</div><div class="gmail_extra"><span style="white-space:pre-wrap">                </span>if flavor == 'public.utf16-plain-text':</div><div class="gmail_extra"><span style="white-space:pre-wrap">                    </span>return data.decode('utf-16')</div><div class="gmail_extra"><span style="white-space:pre-wrap">               </span>raise ValueError('Unhandled MIME type: ' + mime)</div><div class="gmail_extra"><br></div><div class="gmail_extra">You then need to instantiate this class (and keep the instance around so it isn't</div><div class="gmail_extra">garbage collected) somewhere in your code.</div><div class="gmail_extra"><br></div></div></div><div class="gmail_extra" style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial">Thanks Phil, and sorry for unnecessarily having strained your time.</div><div class="gmail_extra" style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial"><br></div><div class="gmail_extra" style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial">Best,</div><div class="gmail_extra" style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial">Michael</div></div><div class="gmail_extra"><br><div class="gmail_quote">On 16 July 2018 at 19:57, Phil Thompson <span dir="ltr"><<a href="mailto:phil@riverbankcomputing.com" target="_blank">phil@riverbankcomputing.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On 16 Jul 2018, at 5:58 pm, Michael Herrmann <<a href="mailto:michael@herrmann.io">michael@herrmann.io</a>> wrote:<br>
> <br>
> Hi all,<br>
> <br>
> I'm trying to work around QTBUG-61562: On Mac, this bug prepends invisible Unicode characters to the clipboard when copy/pasting.<br>
> <br>
> The class QMacPasteboardMime lets one customize copy/pasting on Mac. I created a subclass of it, which does get picked up by Qt. However, the crucial methods canConvert(...) and convertFromMime(...) aren't called. Only the more preliminary convertorName() and flavorFor(...) of my subclass are invoked.<br>
> <br>
> Does anyone have experience with this? Here is my code, adapted from a solution posted in the discussion of QTBUG-61652:<br>
> <br>
> from PyQt5.QtMacExtras import QMacPasteboardMime<br>
> <br>
> class MyMime(QMacPasteboardMime):<br>
>     def __init__(self):<br>
>         super().__init__(<wbr>QMacPasteboardMime.MIME_CLIP)<br>
>     def convertorName(self):<br>
>         return 'UnicodeTextUtf8Default'<br>
>     def flavorFor(self, mime):<br>
>         if mime == 'text/plain':<br>
>             return 'public.utf8-plain-text'<br>
>         i = mime.find('charset=')<br>
>         if i >= 0:<br>
>             charset = mime[i + len('charset='):]<br>
>             charset = charset.split(';', 1)[0]<br>
>             if charset == 'system':<br>
>                 return 'public.utf8-plain-text'<br>
>             if charset in ('iso-10646-ucs-2', 'ut16'):<br>
>                 return 'public.utf16-plain-text'<br>
>         return None<br>
>     def canConvert(self, mime, flav):<br>
>         return mime.startswith('text/plain') and \<br>
>             flav in ('public.utf8-plain-text', 'public.utf16-plain-text')<br>
>     def mimeFor(self, flavor):<br>
>         if flavor == 'public.utf8-plain-text':<br>
>             return 'text/plain'<br>
>         if flavor == 'public.utf16-plain-text':<br>
>             return 'text/plain;charset=utf16'<br>
>         return None<br>
>     def convertToMime(self, mimetype, data, flavor):<br>
>         if len(data) > 1:<br>
>             raise ValueError('Cannot handle multiple member data')<br>
>         first, = data<br>
>         if flavor == 'public.utf8-plain-text':<br>
>             return first.decode('utf-8')<br>
>         if flavor == 'public.utf16-plain-text':<br>
>             return first.decode('utf-16')<br>
>         raise ValueError('Unhandled MIME type: ' + mimetype)<br>
>     def convertFromMime(self, mime, data, flavor):<br>
>         string = data.toString()<br>
>         if flavor == 'public.utf-8.plain-text':<br>
>             return string.encode('utf-8')<br>
>         if flavor == 'public.utf16-plain-text':<br>
>             return string.encode('utf-16')<br>
>         return b''<br>
> <br>
> As I said, flavorFor(...) gets called with 'text/plain'. And convertorName() gets called. But not canConvert(...) and convertFromMime(...).<br>
<br>
</div></div>A small, complete example would help.<br>
<span class="HOEnZb"><font color="#888888"><br>
Phil</font></span></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div><img src="cid:ii_148f0c6115a835fe" alt="Inline image 1" width="142" height="1"><br></div><div><br></div><div><font color="#999999">Michael Herrmann, MSc</font></div><div><font color="#999999">Vienna, Austria</font></div><div><font color="#999999"><a href="https://twitter.com/m_herrmann" target="_blank">Follow me on Twitter</a></font></div></div></div></div></div></div></div></div></div></div>
</div>