|
|
|
/***************************************************************************
|
|
|
|
copyright : (C) 2003-2006 by Robby Stephenson
|
|
|
|
email : robby@periapsis.org
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of version 2 of the GNU General Public License as *
|
|
|
|
* published by the Free Software Foundation; *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "imagewidget.h"
|
|
|
|
#include "../imagefactory.h"
|
|
|
|
#include "../image.h"
|
|
|
|
#include "../filehandler.h"
|
|
|
|
#include "../tellico_debug.h"
|
|
|
|
#include "../tellico_utils.h"
|
|
|
|
|
|
|
|
#include <kfiledialog.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kbuttonbox.h>
|
|
|
|
#include <kurldrag.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
|
|
|
|
#include <tqwmatrix.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqcheckbox.h>
|
|
|
|
#include <tqdragobject.h>
|
|
|
|
#include <tqapplication.h> // needed for drag distance
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
static const uint IMAGE_WIDGET_BUTTON_MARGIN = 8;
|
|
|
|
static const uint IMAGE_WIDGET_IMAGE_MARGIN = 4;
|
|
|
|
static const uint MAX_UNSCALED_WIDTH = 640;
|
|
|
|
static const uint MAX_UNSCALED_HEIGHT = 640;
|
|
|
|
}
|
|
|
|
|
|
|
|
using Tellico::GUI::ImageWidget;
|
|
|
|
|
|
|
|
ImageWidget::ImageWidget(TQWidget* tqparent_, const char* name_) : TQWidget(tqparent_, name_) {
|
|
|
|
TQHBoxLayout* l = new TQHBoxLayout(this);
|
|
|
|
l->setMargin(IMAGE_WIDGET_BUTTON_MARGIN);
|
|
|
|
m_label = new TQLabel(this);
|
|
|
|
m_label->tqsetSizePolicy(TQSizePolicy(TQSizePolicy::Ignored, TQSizePolicy::Ignored));
|
|
|
|
m_label->setFrameStyle(TQFrame::Panel | TQFrame::Sunken);
|
|
|
|
m_label->tqsetAlignment(TQt::AlignHCenter | TQt::AlignVCenter);
|
|
|
|
l->addWidget(m_label, 1);
|
|
|
|
l->addSpacing(IMAGE_WIDGET_BUTTON_MARGIN);
|
|
|
|
|
|
|
|
TQVBoxLayout* boxLayout = new TQVBoxLayout(l);
|
|
|
|
boxLayout->addStretch(1);
|
|
|
|
|
|
|
|
KButtonBox* box = new KButtonBox(this,Qt::Vertical);
|
|
|
|
box->addButton(i18n("Select Image..."), TQT_TQOBJECT(this), TQT_SLOT(slotGetImage()));
|
|
|
|
box->addButton(i18n("Clear"), TQT_TQOBJECT(this), TQT_SLOT(slotClear()));
|
|
|
|
box->tqlayout();
|
|
|
|
boxLayout->addWidget(box);
|
|
|
|
|
|
|
|
boxLayout->addSpacing(8);
|
|
|
|
m_cbLinkOnly = new TQCheckBox(i18n("Save link only"), this);
|
|
|
|
connect(m_cbLinkOnly, TQT_SIGNAL(clicked()), TQT_SLOT(slotLinkOnlyClicked()));
|
|
|
|
boxLayout->addWidget(m_cbLinkOnly);
|
|
|
|
|
|
|
|
boxLayout->addStretch(1);
|
|
|
|
slotClear();
|
|
|
|
|
|
|
|
// accept image drops
|
|
|
|
setAcceptDrops(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::setImage(const TQString& id_) {
|
|
|
|
if(id_.isEmpty()) {
|
|
|
|
slotClear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_imageID = id_;
|
|
|
|
m_pixmap = ImageFactory::pixmap(id_, MAX_UNSCALED_WIDTH, MAX_UNSCALED_HEIGHT);
|
|
|
|
const bool link = ImageFactory::imageInfo(id_).linkOnly;
|
|
|
|
m_cbLinkOnly->setChecked(link);
|
|
|
|
m_cbLinkOnly->setEnabled(link);
|
|
|
|
// if we're using a link, then the original URL _is_ the id
|
|
|
|
m_originalURL = link ? id_ : KURL();
|
|
|
|
m_scaled = TQPixmap();
|
|
|
|
scale();
|
|
|
|
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::setLinkOnlyChecked(bool link_) {
|
|
|
|
m_cbLinkOnly->setChecked(link_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::slotClear() {
|
|
|
|
// m_image = Data::Image();
|
|
|
|
m_imageID = TQString();
|
|
|
|
m_pixmap = TQPixmap();
|
|
|
|
m_scaled = m_pixmap;
|
|
|
|
m_originalURL = KURL();
|
|
|
|
|
|
|
|
m_label->setPixmap(m_scaled);
|
|
|
|
m_cbLinkOnly->setChecked(false);
|
|
|
|
m_cbLinkOnly->setEnabled(true);
|
|
|
|
update();
|
|
|
|
emit signalModified();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::scale() {
|
|
|
|
int ww = m_label->width() - 2*IMAGE_WIDGET_IMAGE_MARGIN;
|
|
|
|
int wh = m_label->height() - 2*IMAGE_WIDGET_IMAGE_MARGIN;
|
|
|
|
int pw = m_pixmap.width();
|
|
|
|
int ph = m_pixmap.height();
|
|
|
|
|
|
|
|
if(ww < pw || wh < ph) {
|
|
|
|
int newWidth, newHeight;
|
|
|
|
if(pw*wh < ph*ww) {
|
|
|
|
newWidth = static_cast<int>(static_cast<double>(pw)*wh/static_cast<double>(ph));
|
|
|
|
newHeight = wh;
|
|
|
|
} else {
|
|
|
|
newWidth = ww;
|
|
|
|
newHeight = static_cast<int>(static_cast<double>(ph)*ww/static_cast<double>(pw));
|
|
|
|
}
|
|
|
|
|
|
|
|
TQWMatrix wm;
|
|
|
|
wm.scale(static_cast<double>(newWidth)/pw, static_cast<double>(newHeight)/ph);
|
|
|
|
m_scaled = m_pixmap.xForm(wm);
|
|
|
|
} else {
|
|
|
|
m_scaled = m_pixmap;
|
|
|
|
}
|
|
|
|
m_label->setPixmap(m_scaled);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::resizeEvent(TQResizeEvent *) {
|
|
|
|
if(m_pixmap.isNull()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
scale();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::slotGetImage() {
|
|
|
|
KURL url = KFileDialog::getImageOpenURL(TQString(), this);
|
|
|
|
if(url.isEmpty() || !url.isValid()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
loadImage(url);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::slotLinkOnlyClicked() {
|
|
|
|
if(m_imageID.isEmpty()) {
|
|
|
|
// nothing to do, it has an empty image;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool link = m_cbLinkOnly->isChecked();
|
|
|
|
// if the user is trying to link and can't before there's no information about the url
|
|
|
|
// the let him know that
|
|
|
|
if(link && m_originalURL.isEmpty()) {
|
|
|
|
KMessageBox::sorry(this, i18n("Saving a link is only possible for newly added images."));
|
|
|
|
m_cbLinkOnly->setChecked(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// need to reset image id to be the original url
|
|
|
|
// if we're linking only, then we want the image id to be the same as the url
|
|
|
|
// so it needs to be added to the cache all over again
|
|
|
|
// probably could do this without downloading the image all over again,
|
|
|
|
// but I'm not going to do that right now
|
|
|
|
const TQString& id = ImageFactory::addImage(m_originalURL, false, KURL(), link);
|
|
|
|
// same image, so no need to call setImage
|
|
|
|
m_imageID = id;
|
|
|
|
emit signalModified();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::mousePressEvent(TQMouseEvent* event_) {
|
|
|
|
// Only interested in LMB
|
|
|
|
if(event_->button() == Qt::LeftButton) {
|
|
|
|
// Store the position of the mouse press.
|
|
|
|
// check if position is inside the label
|
|
|
|
if(m_label->tqgeometry().tqcontains(event_->pos())) {
|
|
|
|
m_dragStart = event_->pos();
|
|
|
|
} else {
|
|
|
|
m_dragStart = TQPoint();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::mouseMoveEvent(TQMouseEvent* event_) {
|
|
|
|
int delay = TQApplication::startDragDistance();
|
|
|
|
// Only interested in LMB
|
|
|
|
if(event_->state() & Qt::LeftButton) {
|
|
|
|
// only allow drag is the image is non-null, and the drag start point isn't null and the user dragged far enough
|
|
|
|
if(!m_imageID.isEmpty() && !m_dragStart.isNull() && (m_dragStart - event_->pos()).manhattanLength() > delay) {
|
|
|
|
const Data::Image& img = ImageFactory::imageById(m_imageID);
|
|
|
|
if(!img.isNull()) {
|
|
|
|
TQImageDrag* drag = new TQImageDrag(img, this);
|
|
|
|
drag->dragCopy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::dragEnterEvent(TQDragEnterEvent* event_) {
|
|
|
|
event_->accept(KURLDrag::canDecode(event_) || TQImageDrag::canDecode(event_) || TQTextDrag::canDecode(event_));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::dropEvent(TQDropEvent* event_) {
|
|
|
|
TQImage image;
|
|
|
|
KURL::List urls;
|
|
|
|
TQString text;
|
|
|
|
|
|
|
|
GUI::CursorSaver cs(TQt::busyCursor);
|
|
|
|
if(TQImageDrag::decode(event_, image)) {
|
|
|
|
// TQt reads PNG data by default
|
|
|
|
const TQString& id = ImageFactory::addImage(image, TQString::tqfromLatin1("PNG"));
|
|
|
|
if(!id.isEmpty() && id != m_imageID) {
|
|
|
|
setImage(id);
|
|
|
|
emit signalModified();
|
|
|
|
}
|
|
|
|
} else if(KURLDrag::decode(event_, urls)) {
|
|
|
|
if(urls.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// only care about the first one
|
|
|
|
const KURL& url = urls[0];
|
|
|
|
if(url.isEmpty() || !url.isValid()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// kdDebug() << "ImageWidget::dropEvent() - " << url.prettyURL() << endl;
|
|
|
|
loadImage(url);
|
|
|
|
} else if(TQTextDrag::decode(event_, text)) {
|
|
|
|
KURL url(text);
|
|
|
|
if(url.isEmpty() || !url.isValid()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
loadImage(url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ImageWidget::loadImage(const KURL& url_) {
|
|
|
|
const bool link = m_cbLinkOnly->isChecked();
|
|
|
|
|
|
|
|
GUI::CursorSaver cs;
|
|
|
|
// if we're linking only, then we want the image id to be the same as the url
|
|
|
|
const TQString& id = ImageFactory::addImage(url_, false, KURL(), link);
|
|
|
|
if(id != m_imageID) {
|
|
|
|
setImage(id);
|
|
|
|
emit signalModified();
|
|
|
|
}
|
|
|
|
// at the end, cause setImage() resets it
|
|
|
|
m_originalURL = url_;
|
|
|
|
m_cbLinkOnly->setEnabled(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "imagewidget.moc"
|