webimagefetcherdialog.cpp 8.34 KB
Newer Older
1 2 3
/***************************************************************************
    copyright            : (C) 2004 Nathan Toone
    email                : nathan@toonetown.com
4 5
    copyright            : (C) 2007 Michael Pyne
    email                : michael.pyne@kdemail.net
6 7 8 9 10 11 12 13 14 15 16
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

17
#include "webimagefetcherdialog.h"
18 19
#include "tag.h"

20
#include <kapplication.h>
21
#include <kio/job.h>
Scott Wheeler's avatar
Scott Wheeler committed
22 23
#include <klocale.h>
#include <kdebug.h>
24
#include <kmessagebox.h>
25 26 27
#include <krun.h>
#include <kiconloader.h>
#include <kurllabel.h>
28

29 30
#include <QVBoxLayout>
#include <QHBoxLayout>
31
#include <QPainter>
32
#include <QEventLoop>
33
#include <QListView>
Laurent Montel's avatar
Laurent Montel committed
34
#include <QPixmap>
35

36
WebImageFetcherDialog::WebImageFetcherDialog(const WebImageList &imageList,
37
                                         const FileHandle &file,
38
                                         QWidget *parent) :
Richard Lärkäng's avatar
Richard Lärkäng committed
39
    KDialog(parent),
40
    m_pixmap(QPixmap()),
41
    m_imageList(imageList),
42
    m_file(file)
43
{
Laurent Montel's avatar
Laurent Montel committed
44
    setObjectName( QLatin1String("internet_image_fetcher" ));
Richard Lärkäng's avatar
Richard Lärkäng committed
45 46 47
    setModal(true);
    setButtons(Ok | Cancel | User1);
    setDefaultButton(NoDefault);
Laurent Montel's avatar
Port++  
Laurent Montel committed
48
    showButtonSeparator(true);
Richard Lärkäng's avatar
Richard Lärkäng committed
49

50 51
    QWidget *mainBox = new QWidget(this);
    QBoxLayout *mainLayout = new QVBoxLayout(mainBox);
52 53 54 55 56 57 58 59 60 61 62 63
    mainLayout->setMargin(0); // No extra padding needed.
    mainLayout->setSpacing(spacingHint());

    m_iconWidget = new QListView(mainBox);
    m_iconWidget->setGridSize(QSize(100, 120));
    m_iconWidget->setViewMode(QListView::IconMode);
    m_iconWidget->setResizeMode(QListView::Adjust);
    m_iconWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
    m_iconWidget->setVerticalScrollMode(QListView::ScrollPerItem);
    m_iconWidget->setMovement(QListView::Static);
    m_iconWidget->setSelectionMode(QListView::SingleSelection);
    m_iconWidget->setIconSize(QSize(80, 80));
64 65

    mainLayout->addWidget(m_iconWidget);
66 67
    connect(m_iconWidget, SIGNAL(activated(const QModelIndex &)),
            this, SLOT(slotActivated(const QModelIndex &)));
68

69 70 71 72 73 74 75 76
    // Before changing the code below be sure to check the attribution terms
    // of the Yahoo Image Search API.
    // http://developer.yahoo.com/attribution/
    KUrlLabel *logoLabel = new KUrlLabel(mainBox);
    logoLabel->setUrl("http://developer.yahoo.com/about/");
    logoLabel->setPixmap(UserIcon("yahoo_credit"));
    logoLabel->setMargin(15);    // Allow large margin per attribution terms.
    logoLabel->setUseTips(true); // Show URL in tooltip.
77
    connect(logoLabel, SIGNAL(leftClickedUrl(const QString &)),
78 79 80 81 82 83 84 85
                       SLOT(showCreditURL(const QString &)));

    QBoxLayout *creditLayout = new QHBoxLayout;
    mainLayout->addLayout(creditLayout);

    creditLayout->addStretch(); // Left spacer
    creditLayout->addWidget(logoLabel);
    creditLayout->addStretch(); // Right spacer
Scott Wheeler's avatar
Scott Wheeler committed
86

87 88
    setMainWidget(mainBox);
    setButtonText(User1, i18n("New Search"));
89 90 91 92

    connect(this, SIGNAL(user1Clicked()),  SIGNAL(newSearchRequested()));
    connect(this, SIGNAL(okClicked()),     SLOT(slotOk()));
    connect(this, SIGNAL(cancelClicked()), SLOT(slotCancel()));
93 94

    setInitialSize(QSize(500, 480));
95 96
}

97
WebImageFetcherDialog::~WebImageFetcherDialog()
98
{
99
}
100

101
void WebImageFetcherDialog::showCreditURL(const QString &url)
102 103 104 105
{
    // Don't use static member since I'm sure that someday knowing my luck
    // Yahoo will change their mimetype they serve.
    (void) new KRun(KUrl(url), topLevelWidget());
106 107
}

108
void WebImageFetcherDialog::setLayout()
109
{
110 111 112 113
    setCaption(QString("%1 - %2 (%3)")
              .arg(m_file.tag()->artist())
              .arg(m_file.tag()->album())
              .arg(m_imageList.size()));
114

115 116 117
    QStandardItemModel *model = new QStandardItemModel(m_iconWidget);
    QAbstractItemModel *oldModel = m_iconWidget->model();

Albert Astals Cid's avatar
Albert Astals Cid committed
118
    foreach(const WebImage &image, m_imageList) {
119
        WebCoverIconViewItem *item = new WebCoverIconViewItem(m_iconWidget, image);
120 121 122 123 124
        model->appendRow(item);
    }

    m_iconWidget->setModel(model);
    delete oldModel;
125 126 127 128

    adjustSize();
}

129
void WebImageFetcherDialog::setImageList(const WebImageList &imageList)
130
{
131 132 133
    m_imageList = imageList;
}

134
void WebImageFetcherDialog::setFile(const FileHandle &file)
135 136
{
    m_file = file;
137 138
}

139 140 141 142
////////////////////////////////////////////////////////////////////////////////
// public slots
////////////////////////////////////////////////////////////////////////////////

143
void WebImageFetcherDialog::refreshScreen(WebImageList &imageList)
144 145 146 147 148
{
    setImageList(imageList);
    setLayout();
}

149
int WebImageFetcherDialog::exec()
150 151
{
    setLayout();
Richard Lärkäng's avatar
Richard Lärkäng committed
152
    return KDialog::exec();
153 154
}

155
void WebImageFetcherDialog::slotOk()
156
{
157 158 159
    slotActivated(m_iconWidget->currentIndex());
}

160
void WebImageFetcherDialog::slotActivated(const QModelIndex &index)
161
{
162
    emit coverSelected(m_imageList[index.row()].imageURL());
163 164
}

165
void WebImageFetcherDialog::selectedItemIsBad()
166 167 168 169 170 171 172 173 174 175 176
{
    QModelIndex index = m_iconWidget->currentIndex();

    QStandardItemModel *model = static_cast<QStandardItemModel *>(m_iconWidget->model());
    QStandardItem *item = model->itemFromIndex(index);
    if(!item)
        return;

    item->setIcon(DesktopIcon("dialog-error"));
}

177
void WebImageFetcherDialog::slotCancel()
178 179
{
    m_pixmap = QPixmap();
180
    reject();
181
}
182

183 184 185 186
////////////////////////////////////////////////////////////////////////////////
// CoverIconViewItem
////////////////////////////////////////////////////////////////////////////////

187
WebCoverIconViewItem::WebCoverIconViewItem(QWidget *parent, const WebImage &image) :
188
    QObject(parent), QStandardItem(image.size()), m_job(0)
189
{
Scott Wheeler's avatar
Scott Wheeler committed
190
    // Set up the iconViewItem
191

192
    setIcon(DesktopIcon("system-search"));
193

Scott Wheeler's avatar
Scott Wheeler committed
194
    // Start downloading the image.
195

Michael Pyne's avatar
Michael Pyne committed
196
    m_job = KIO::storedGet(image.thumbURL(), KIO::NoReload, KIO::HideProgressInfo);
197
    connect(m_job, SIGNAL(result(KJob *)), this, SLOT(imageResult(KJob *)));
198 199
}

200
WebCoverIconViewItem::~WebCoverIconViewItem()
201
{
202 203
    if(m_job) {
        m_job->kill();
Scott Wheeler's avatar
Scott Wheeler committed
204

205 206
        // Drain results issued by KIO before being deleted,
        // and before deleting the job.
Scott Wheeler's avatar
Scott Wheeler committed
207
        kapp->processEvents(QEventLoop::ExcludeUserInput);
208 209 210

        delete m_job;
    }
211 212
}

213
void WebCoverIconViewItem::imageResult(KJob *job)
214
{
215 216 217 218 219
    if(job != m_job) {
        kError() << "Wrong slot called.\n";
        setIcon(DesktopIcon("dialog-error"));
        return;
    }
220

221 222 223
    if(job->error()) {
        kError() << "Unable to grab image\n";
        setIcon(DesktopIcon("dialog-error"));
224
        return;
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
    }

    // Create thumbnail to show on icon.  At least by Qt 4.3 the standard
    // item delegate is still retarded when it comes to drawing uneven sized
    // items in a grid, as shorter items (in height) have the corresponding
    // text shoved up below meaning the text doesn't line up.  So, force every
    // icon to be the exact same size manually...

    QPixmap iconImage, realImage(80, 80);
    iconImage.loadFromData(m_job->data());
    realImage.fill(Qt::transparent);

    if(iconImage.isNull()) {
        kError() << "Thumbnail image is not of a supported format\n";
        setIcon(DesktopIcon("dialog-error"));
        return;
    }

    // Scale down if necesssary
    if(iconImage.width() > 80 || iconImage.height() > 80)
        iconImage = iconImage.scaled(80, 80, Qt::KeepAspectRatio, Qt::SmoothTransformation);

    QPainter p;
    QRect targetRect(QPoint(0, 0), iconImage.size());
    p.begin(&realImage);
250
    p.setCompositionMode(QPainter::CompositionMode_Source);
251 252 253 254 255 256 257 258 259

    // Center thumbnail in 80x80 pixmap
    targetRect.setWidth(iconImage.width());
    targetRect.moveLeft((realImage.width() - iconImage.width()) / 2);
    targetRect.setHeight(iconImage.height());
    targetRect.moveTop((realImage.height() - iconImage.height()) / 2);

    p.drawPixmap(targetRect, iconImage, iconImage.rect());
    p.end();
260

261
    setIcon(realImage);
262
}
263

264
#include "webimagefetcherdialog.moc"
265 266

// vim: set et sw=4 tw=0 sta: