/*************************************************************************** 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 #include #include #include #include #include #include #include #include #include #include // 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* parent_, const char* name_) : TQWidget(parent_, name_) { TQHBoxLayout* l = new TQHBoxLayout(this); l->setMargin(IMAGE_WIDGET_BUTTON_MARGIN); m_label = new TQLabel(this); m_label->setSizePolicy(TQSizePolicy(TQSizePolicy::Ignored, TQSizePolicy::Ignored)); m_label->setFrameStyle(TQFrame::Panel | TQFrame::Sunken); m_label->setAlignment(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,TQt::Vertical); box->addButton(i18n("Select Image..."), this, TQ_SLOT(slotGetImage())); box->addButton(i18n("Clear"), this, TQ_SLOT(slotClear())); box->layout(); boxLayout->addWidget(box); boxLayout->addSpacing(8); m_cbLinkOnly = new TQCheckBox(i18n("Save link only"), this); connect(m_cbLinkOnly, TQ_SIGNAL(clicked()), TQ_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(static_cast(pw)*wh/static_cast(ph)); newHeight = wh; } else { newWidth = ww; newHeight = static_cast(static_cast(ph)*ww/static_cast(pw)); } TQWMatrix wm; wm.scale(static_cast(newWidth)/pw, static_cast(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() == TQt::LeftButton) { // Store the position of the mouse press. // check if position is inside the label if(m_label->geometry().contains(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() & TQt::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::fromLatin1("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"