Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: xintrea от Сентябрь 12, 2010, 14:43



Название: [Решено] [QTextEdit] Как получить картинку из ресурсов документа?
Отправлено: xintrea от Сентябрь 12, 2010, 14:43
Здравствуйте!


Делаю я сейчас несложный WYSIWYG-редактор текста. И возникла необходимость сохранять картинки, которые были вставлены в текст из буфера обмена.

В момент вставки картинки из буфера, ресурсу катринки присваивается уникальное имя, в формате "imageXXXXX", где XXXXX-случайное число (о коллизиях пока не думаем):

Код:
// Вставка MIME данных
void EditorTextArea::insertFromMimeData(const QMimeData *source)
{
 QTextCursor cursor = this->textCursor();
 QTextDocument *document = this->document();

 // Вставка картинки
 if(source->hasImage())
  {
   // Принятые данные преобразуются в тип QImage
   QImage image=qvariant_cast<QImage>(source->imageData());

   // Генерируется имя ресурса
   QString image_name="image"+QString::number(qrand());

   // Ресурс добавляется в хранилище ресурсов документа
   document->addResource(QTextDocument::ImageResource, QUrl(image_name), image);

   // Картинка вставляется в текст
   cursor.insertImage(image_name);

   return;
  }
}

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

Я делаю так:
(textarea - это объект класса QTextEdit)

Код:
void Editor::save_textarea_images(QString dirname)
{
 qDebug() << "Save images, blocks count " << textarea->document()->blockCount() << "\n";

 // Перебираются блоки документа и находятся блоки с картинками
 QTextBlock bl = textarea->document()->begin();
 while(bl.isValid())
  {
   QTextBlock::iterator it;

   for(it = bl.begin(); !(it.atEnd()); ++it)
    {
     QTextFragment currentFragment = it.fragment();
     if(currentFragment.isValid())
      {
       if(currentFragment.charFormat().isImageFormat())
        {
         // Найден блок с картинкой

         // Выясняется формат картинки
         QTextImageFormat imgFmt = currentFragment.charFormat().toImageFormat();

         // Из формата выясняется имя картинки
         QString image_name=imgFmt.name();
         qDebug() << "Image " << image_name << "\n"; // имя файла

         QString image_file_name=dirname+"/"+image_name;
         qDebug() << "Save image data to file " << image_file_name;

         // Из ресурсов вытягивается картинка
         QVariant image_data=textarea->document()->resource(QTextDocument::ImageResource, image_name);
         qDebug() << "Data length " << image_data.toByteArray().length();
         qDebug() << "Image data as string" << image_data.toString();

         // Картинка записывается в файл
         QFile imgfile(image_file_name);
         QTextStream out(&imgfile);
         out << image_data.toByteArray();
        }
      }
    }
   bl = bl.next();
  }
}

Результат получается вот такой (файлы картинок не создаются, видимо из-за того, что поток нуливой длины):

Код:
Save images, blocks count 27

Image  "image476707713"
Save image data to file  "./base/0000000842/image476707713"
Data length  0
Image data as string ""

Image  "image1186278907"
Save image data to file  "./base/0000000842/image1186278907"
Data length  0
Image data  as string ""

То есть, вызов textarea->document()->resource(...) либо не возвращает данные и ресурсов, либо я неправильно преобразую эти данные. А как правильно преобразовать, я не знаю.

Вопрос - как вытянуть данные картинок из ресурсов документа, чтобы их можно было сохранить?


Название: Re: [QTextEdit] Как получить картинку из ресурсов документа?
Отправлено: crossly от Сентябрь 12, 2010, 15:40
а если
Код:
QVariant image_data=textarea->document()->resource(QTextDocument::ImageResource, QUrl(image_name));
??
Цитировать
Результат получается вот такой (файлы картинок не создаются, видимо из-за того, что поток нуливой длины):
не создается потому как вы его не открываете...


Название: Re: [QTextEdit] Как получить картинку из ресурсов документа?
Отправлено: xintrea от Сентябрь 12, 2010, 16:00
а если
Код:
QVariant image_data=textarea->document()->resource(QTextDocument::ImageResource, QUrl(image_name));
??

Попробовал и через QUrl - толку нет.

Цитировать
Результат получается вот такой (файлы картинок не создаются, видимо из-за того, что поток нуливой длины):
не создается потому как вы его не открываете...

Да, вы правы. Добавил после строки "QFile imgfile(image_file_name);" код:

Код:
if (!imgfile.open(QIODevice::WriteOnly))
 {
  qDebug() << "Cant open file " << image_file_name << " for write.";
  exit(1);
 }

теперь создаются пустые файлы.

Какие еще будут варианты вытягивания картинок?


Название: Re: [QTextEdit] Как получить картинку из ресурсов документа?
Отправлено: xintrea от Сентябрь 12, 2010, 18:56
У меня есть подозрение, что каким-то хитрым образом надо формировать QUrl к картинке.

Потому что, если выполнить код с указанием несуществущего ресурса картинки:

QVariant image_data=textarea->document()->resource(QTextDocument::ImageResource, QUrl("unavailable_resource"));

- результат будет тот же.

Вопрос, наверно, в том, как правильно написать QUrl зная имя картинки в ресурсах.




Название: Re: [QTextEdit] Как получить картинку из ресурсов документа?
Отправлено: Makss от Сентябрь 12, 2010, 20:48
Код:
            QVariant var = doc->resource(QTextDocument::ImageResource, QUrl(<имя ресурса>));
            if(var.isValid()) {
                QImage img = var.value<QImage>(); //вашь рисунок
            }

но это точно будет работать если изображения вы добавляли в ресурсы через QImage, другие варианты не проверял, в моём проекте все именно так и сделано и всё работает


Название: Re: [QTextEdit] Как получить картинку из ресурсов документа?
Отправлено: xintrea от Сентябрь 12, 2010, 21:43
Код:
            QVariant var = doc->resource(QTextDocument::ImageResource, QUrl(<имя ресурса>));
            if(var.isValid()) {
                QImage img = var.value<QImage>(); //вашь рисунок
            }

но это точно будет работать если изображения вы добавляли в ресурсы через QImage, другие варианты не проверял, в моём проекте все именно так и сделано и всё работает

Ага, спасибо, я уже так и сделал.

Как сказали знающие люди, в QVariant не работает метод toByteArray(), если внутри содержится значение типа QImage. Точнее, он будет возвращать пустой массив.

А так как метода перевода в QImage у QVariant нет, нужно преобразовывать тип через variant_variable.value<QImage>(). Ну а потом можно с QImage что угодно делать, например сохранить через метод save().