Chapter 12. Añadir más características

Posibilidad de guardar el resultado

Ahora queremos guardar la imagen teñida en un archivo. ¿Qué podemos hacer? En primer lugar añadiremos un método de acceso a CentralView que devuelva el mapa de pixels teñido (el mapa de pixels que se encuentra en m_label):

   QPixmap *tintedPixmap() const { return m_label->pixmap(); };

En TheTinterView, añadiremos un nuevo método junto a openURL(const KURL &url), ¿adivina el nombre? Correcto, saveURL(const KURL &url) :) Este método hace:

void TheTinterView::saveURL(const KURL &url)
{
  QString tmpFile;
  KTempFile *temp=0;
  if (url.isLocalFile())
    tmpFile=url.path();
  else
  {
    temp=new KTempFile;
    tmpFile=temp->name();
  }

  m_view->tintedPixmap()->save( tmpFile, "PNG");

  if (temp)
  {
    KIO::NetAccess::upload(tmpFile, url, this);
    temp->unlink();
    delete temp;
  }
}

En caso de que la URL sea un archivo local, lo utilizaremos como archivo en el que guardar el mapa de pixels teñido en formato PNG. Si no es un archivo local, crearemos un archivo temporal y guardaremos ahí la imagen en formato PNG y, a continuación, cargaremos el archivo temporal en la URL especificada por el usuario, eliminaremos el archivo temporal y destruiremos el objeto que habíamos creado para ello.

Añadir soporte para arratrar y soltar

Aquí no hay mucho que hacer, ya que KDevelop añadió automáticamente desde el principio el código necesario para aceptar operaciones de arrastrar y soltar con URIs (equivalentes, de momento, a URLs), y como hemos utilizado KIO para cargar nuestras imágenes, ya es posible arrastrar una imagen desde Konqueror a TheTinter y será descargada.

Para desarrollar algo sobre arrastrar y soltar, añadiremos soporte para imágenes. La diferencia con las URIs es que los eventos de arrastrar y soltar de una imagen contienen la información de la propia imagen, mientras que en el caso de las URLs, estas únicamente contienen la dirección de la imagen.

El código que utilizaremos es:

void TheTinter::dragEnterEvent(QDragEnterEvent *event)
{
      // accept uri drops only
          event->accept(QUriDrag::canDecode(event) || QImageDrag::canDecode(event));
}
Esto será llamado cada vez que recibamos un evento de arrastrar y soltar en nuestra aplicación. Le dice al subsistema de arrastrar y soltar si se debe aceptar o rechazar la operación.

void TheTinter::dropEvent(QDropEvent *event)
{
  // esta es una implementación muy simple de un evento de soltar. únicamente
  // aceptaremos una URL.  el código de arrastrar y soltar de Qt puede hacer
  // *mucho* más, así que, por favor, consulte la documentación
  QStrList uri;

  // comprobar si se puede decodificar la URI.  si no, ignorarla
  if (QUriDrag::decode(event, uri))
  {
    // correcto, tenemos una URI.  la procesamos
    QString url, target;
    url = uri.first();

    // cargamos el archivo
    load(KURL(url));
    return;
  }

  QPixmap pixmap;
  if (QImageDrag::decode(event, pixmap))
  {
    m_view->openPixmap(pixmap);
  }
}
Este código se ejecutará cada vez que el usuario suelte sobre nuestra ventana cualquier cosa que esté arrastrando. En primero lugar tratamos de comprobar si el evento es un evento URI. Si la primera parte tiene éxito, extraemos la primera URL de la (posible) lista de URIs que contiene el evento, y ejecutamos esa URL.

Si no se trataba de un evento URI, tratamos de decodificarlo como un evento de imagen (utilizando QImageDrag::decode). Si es correcto, abrimos esa imagen. Hay que tener en cuenta que TheTinterView::openPixmap todavía no existe, así que añadimos ese método y lo implementamos de esta forma:

void TheTinterView::openPixmap(const QPixmap& pixmap)
{
    m_view->setPixmap( pixmap );
}

Y esto es s9, nuestra aplicación final. Espero que haya disfrutado del tutorial y haya aprendido con él. También deseo poder ver publicadas muy pronto sus aplicaciones de KDE :).

Un saludo,

Antonio Larrosa Jiménez <larrosa@kde.org>