Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: andrew.k от Май 03, 2012, 13:01



Название: [Решено] Буфер обмена и Google Chrome
Отправлено: andrew.k от Май 03, 2012, 13:01
Код
C++ (Qt)
       QClipboard *clipboard = QApplication::clipboard();
       QMimeData * mimeData = new QMimeData();
 
       QTextDocumentFragment fragment = textEdit->textCursor().selection();
       QTextDocument docFrag;
       QTextCursor cur(&docFrag);
       cur.insertFragment(fragment);
...
       mimeData->setHtml(docFrag.toHtml());
       mimeData->setText(docFrag.toPlainText());
       clipboard->setMimeData(mimeData);
 
Вот кусок кода, который помещает в текст в буфер (форматированный и плейнтекст).
В результате опера, эксплорер, ворд и блокнот успешно могут вставить текст из буфера.
А хром почему-то не может вставить форматированный текст.
Проверял на gmail. Хотя из ворда в гмейл форматированный текст вставляется.

Что не хватает в коде? Почему так?


Название: Re: Буфер обмена и Google Chrome
Отправлено: V1KT0P от Май 03, 2012, 15:23
Что не хватает в коде? Почему так?
Скопируй в буфер обмена из ворда и своей программы один и тот-же текст с одним и тем-же форматированием. И сравни в чем между ними разница.
Например скопированный текст Test жирный из ворда и вставленный в папку создал зип архив на 23 килобайта. Там внутри куча файлов. Это вроде один и тот-же текст в разных форматах. Вот и сравни пофайлово.


Название: Re: Буфер обмена и Google Chrome
Отправлено: andrew.k от Май 03, 2012, 15:44
Что не хватает в коде? Почему так?
Скопируй в буфер обмена из ворда и своей программы один и тот-же текст с одним и тем-же форматированием. И сравни в чем между ними разница.
Например скопированный текст Test жирный из ворда и вставленный в папку создал зип архив на 23 килобайта. Там внутри куча файлов. Это вроде один и тот-же текст в разных форматах. Вот и сравни пофайлово.
Вообще ничего не понял. Что пофайлово сравнивать? какой зип-архив? как из текста архив получился?  ???


Сравнил содержимое буфера обмена (программой InsideClipboard) скопированное из программы и из другого места.
Отличие в наличии формата CF_FORMAT, который определяет кодировку данных в буфере.
Причина проблемы qt-шная реализация буфера обмена не добавляет этот формат.
Видимо поэтому хром не зная какая кодировка не хочет вставлять.

Очевидно решением является добавление этого формата.
Средствами qt похоже это сделать невозможно или я не нашел.

Использовать Win API для добавления недостающей детали? как-то не хочется.


Название: Re: Буфер обмена и Google Chrome
Отправлено: andrew.k от Май 03, 2012, 22:18
Получается, что под виндой некорректно реализовано помещение html текста в буфер обмена.


Название: Re: Буфер обмена и Google Chrome
Отправлено: Bepec от Май 03, 2012, 22:36
Текст в архив - всё просто. docx ворда, это архив, содержищий файлы о стилях, тексте, форматировании и прочих прелестях.

Скорее всего проблема в типе. Насколько я помню, при помещении в буфер задаётся тип данных (не в Qt, а в браузерах), исходя из которого собственно и происходит преобразование. Советую просто посмотреть в эту сторону.


Название: Re: Буфер обмена и Google Chrome
Отправлено: andrew.k от Май 03, 2012, 23:52
Текст в архив - всё просто. docx ворда, это архив, содержищий файлы о стилях, тексте, форматировании и прочих прелестях.
но при чем тут все это?
Скорее всего проблема в типе. Насколько я помню, при помещении в буфер задаётся тип данных (не в Qt, а в браузерах), исходя из которого собственно и происходит преобразование. Советую просто посмотреть в эту сторону.
Я уже понял, в чем проблема, как пойму как её решить отпишу сюда.


Название: Re: Буфер обмена и Google Chrome
Отправлено: andrew.k от Май 04, 2012, 01:27
Эпиграф.
- Вот за это я и ненавижу кошек.
- Ты просто не умеешь их готовить.

Глава 1.
Если посмотреть внимательно на приведенный фрагмент кода, то видно, что там происходит копирование документа и его обработка.
И уже потом из него получается html. В этом и была проблема.

Вот (http://msdn.microsoft.com/en-us/library/windows/desktop/ms649015(v=vs.85).aspx) описание формата HTML в буфере обмена windows.

Из описания видно, что в формате есть два поля в заголовке формата
Код
HTML
   StartFragment:140
   EndFragment:160

И маркеры внутри хтмл
Код
HTML
   <!--StartFragment -->
   <LI> The Fragment </LI>
   <!--EndFragment -->

Обе пары имеют одинаковое назначение: указать начало и конец необходимого фрагмента.
Т.к. выдрать кусок из хтмл нельзя из-за тегов, поэтому до начала фрагментов могут присутствовать другие теги (контекст фрагмента).

Глава 2.
Суть проблемы: получая html из объекта QTextDocument, в результате отсутствуют маркеры начала и конца фрагмента (т.к. это целый документ).
Что логично и нельзя воспринимать как баг. А получая html из QTextDocumentFragment, в результирующем html выставлены эти теги (маркеры <!-- -->). Они обрамляют фрагмент. Что тоже логично.
Теперь когда через QClipboard мы помещаем в буфер html полученный из документа, а не из фрагмента (как нужно делать), кто-то умный видя, что маркеры отсутствуют тупо добавляет их по краям, т.е. в начале и в конце.
При этом не обновляя значения в полях заголовка.
И итоге получается, что положение маркеров в html не соответствует значениям заданным в заголовке формата.

Видя такую картину Google Chrome как истинно кошерная программа отказывается принимать такой фрагмент, хотя всем другим это глубоко фиолетово  ;D

Глава 3.
Решение:
Оно очень простое. Необходимо в документе выделить весь текст и получить выделенный фрагмент, а уже из него получать html.

Т.е. вот таким образом:
Код
C++ (Qt)
       cur.setPosition(0);
       cur.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
       fragment = cur.selection();
       mimeData->setData("text/html", fragDoc.toHtml("utf-8").toUtf8());

А вот пациент (видно, что значения в шапке не валидны, хотя скорее это маркеры неправильно расположены):
Код
HTML
Version:1.0
StartHTML:0000000105
EndHTML:0000001323
StartFragment:0000000127
EndFragment:0000001305
 
<!--StartFragment--><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Andrew</span> 12:33:48 demo text handId=92034024 </p></body></html><!--EndFragment-->

Занавес.