예제 #1
0
void VideoThread::run()
{
    while (!m_quit) {
        m_vcap >> m_image;
        emit imageReady(m_image);
    }
}
예제 #2
0
cVideoLabel::cVideoLabel(QWidget *parent) :
  QLabel(parent)
{
  //Need this to allow the object to track mouse events
  setFocusPolicy(Qt::ClickFocus);

  //JJV DEBUG - hardcoded stuff
  this->moveForwardKey = Qt::Key_E;
  this->moveBackwardKey = Qt::Key_D;
  this->moveLeftKey = Qt::Key_S;
  this->moveRightKey = Qt::Key_F;


  //Setup the OpenCV thread
  this->thread = new QThread;
  this->openCVObj = new OPENCV_HANDLER();
  this->openCVObj->moveToThread(this->thread);
  connect(this->openCVObj, SIGNAL(error(QString)), this, SLOT(videoError(QString)));
  connect(this->thread, SIGNAL(started()), this->openCVObj, SLOT(process()));
  connect(this->openCVObj, SIGNAL(finished()), this->thread, SLOT(quit()));
  connect(this->openCVObj, SIGNAL(finished()), this->openCVObj, SLOT(deleteLater()));
  connect(this->thread, SIGNAL(finished()), this->thread, SLOT(deleteLater()));
  connect(this->openCVObj, SIGNAL(imageReady(QPixmap)), this, SLOT(updateImage(QPixmap)));
  this->thread->start();
}
예제 #3
0
void MainWindow::slot_searchImagesButtonClicked()
{
    ui->searchImagesLineEdit->setText( ui->searchImagesLineEdit->text().simplified() );
    if( ui->searchImagesLineEdit->text() == "" )
    {
        ui->scene->setWebImageTextureId( 0 );
        return;
    }

    ui->searchImagesLineEdit->setEnabled( false );
    ui->searchImagesButton->setEnabled( false );
    ui->searchImagesButton->setText( "Buscando" );


    WebImage *webImage = new WebImage( this );

    if( ui->allImagesButton->isChecked() )
    {
        ui->messagesTextEdit->append( "Buscando imagenes: " + ui->searchImagesLineEdit->text() + "..." );
        webImage->searchForAllImages( ui->searchImagesLineEdit->text() );
    }
    if( ui->streetViewImagesButton->isChecked() )
    {
        ui->messagesTextEdit->append( "Buscando lugar: " + ui->searchImagesLineEdit->text() + "..." );
        webImage->searchForStreetViewImage( ui->searchImagesLineEdit->text() );
    }

    connect( webImage, SIGNAL( notImage() ), SLOT( slot_webImageNotImage() ) );
    connect( webImage, SIGNAL( imageReady( GLuint ) ), SLOT( slot_webImageReady( GLuint ) ) );
}
void Converter::process(cv::Mat frame) {
    //  cv::resize(frame, frame, cv::Size(), 0.3, 0.3, cv::INTER_AREA);
    cv::cvtColor(frame, frame, CV_BGR2RGB);
    const QImage image(frame.data, frame.cols, frame.rows, frame.step,
                       QImage::Format_RGB888, &matDeleter, new cv::Mat(frame));
    Q_ASSERT(image.constBits() == frame.data);
    emit imageReady(image);
}
예제 #5
0
CameraEngine::CameraEngine(QObject *parent) :
    QThread(parent)
{   
    QSettings settings("RobotStation");
    m_camera = settings.value("camera",0).toInt();
    m_stop = false;
    connect(this,SIGNAL(imageReady(Mat)),this,SLOT(updateImage(Mat)));
}
예제 #6
0
LocalImageLoaderPrivate::LocalImageLoaderPrivate(LocalImageLoader *loader, QThread *thread) : QObject(0)
    , loader(loader)
{
	moveToThread(thread);
	connect(loader, SIGNAL(needToPrepare()), this, SLOT(prepareImages()));
	connect(this, SIGNAL(imageReady()), loader, SLOT(onImageReady()));
	connect(this, SIGNAL(imageFailed(quint64)), loader, SLOT(onImageFailed(quint64)));
};
QtBarcodeReader::QtBarcodeReader(QObject *parent,QWidget *viewer) :
    QObject(parent)
{
    qRegisterMetaType<cv::Mat>("cv::Mat");
    converter.setProcessAll(false);    
    cvcapture= new CVCapture();
    converter.connect(cvcapture, SIGNAL(matReady(cv::Mat)), SLOT(processFrame(cv::Mat)));
    BarcodeDecoder.connect(&converter, SIGNAL(imageReady(QImage)), SLOT(decodeImage(QImage)));
    connect(&BarcodeDecoder,SIGNAL(BarcodeDecodeStatus(BARCODESTATUS,QString)),this, SLOT(NewBarcodeDecodeStatus(BARCODESTATUS,QString)));

    if (viewer!=0) {
        viewer->connect(&converter, SIGNAL(imageReady(QImage)), SLOT(setImage(QImage)));
    }



}
예제 #8
0
void VisionGUI::updateFrame(Image<PixRGB<byte> > img, bool isFwdCamera) {

    cleanImage = img;
    if (!ui.actionFreeze_Frame->isChecked()) {
        curImage = convertToQImage4(img);
        emit imageReady();
    }
}
예제 #9
0
MapLayer::MapLayer(MapLayerPrivate &dd, QObject *parent)
    :QObject(parent), d_ptr(&dd)
{
    setObjectName("MapLayer");
    d_ptr->q_ptr = this;
    connect(d_ptr, SIGNAL(needRender(QRect)), this, SIGNAL(imageReady(QRect)));
    d_ptr->uid = QUuid::createUuid().toString();
}
예제 #10
0
void PHIImageRequest::slotFinished()
{
    if ( _reply->error()!=QNetworkReply::NoError ) {
        emit error( _reply->errorString() );
    }
    QImage img=QImage::fromData( _reply->readAll() );
    emit imageReady( img, _num );
    deleteLater();
}
예제 #11
0
void PreviewLoader::Impl::finishedGenerating(pid_t pid, int retval)
{
	// Paranoia check!
	InProgressProcesses::iterator git = in_progress_.find(pid);
	if (git == in_progress_.end()) {
		lyxerr << "PreviewLoader::finishedGenerating(): unable to find "
			"data for PID " << pid << endl;
		return;
	}

	string const command = git->second.command;
	string const status = retval > 0 ? "failed" : "succeeded";
	LYXERR(Debug::GRAPHICS, "PreviewLoader::finishedInProgress("
				<< retval << "): processing " << status
				<< " for " << command);
	if (retval > 0)
		return;

	// Read the metrics file, if it exists
	vector<double> ascent_fractions(git->second.snippets.size());
	setAscentFractions(ascent_fractions, git->second.metrics_file);

	// Add these newly generated bitmap files to the cache and
	// start loading them into LyX.
	BitmapFile::const_iterator it  = git->second.snippets.begin();
	BitmapFile::const_iterator end = git->second.snippets.end();

	list<PreviewImagePtr> newimages;

	int metrics_counter = 0;
	for (; it != end; ++it, ++metrics_counter) {
		string const & snip = it->first;
		FileName const & file = it->second;
		double af = ascent_fractions[metrics_counter];

		// Add the image to the cache only if it's actually present
		if (file.isReadableFile()) {
			PreviewImagePtr ptr(new PreviewImage(parent_, snip, file, af));
			cache_[snip] = ptr;

			newimages.push_back(ptr);
		}

	}

	// Remove the item from the list of still-executing processes.
	in_progress_.erase(git);

	// Tell the outside world
	list<PreviewImagePtr>::const_reverse_iterator
		nit  = newimages.rbegin();
	list<PreviewImagePtr>::const_reverse_iterator
		nend = newimages.rend();
	for (; nit != nend; ++nit) {
		imageReady(*nit->get());
	}
}
예제 #12
0
VisionGUI::VisionGUI(OptionManager &mgr,
                     const std::string &descrName, const std::string &tagName) :
    VisionBrainComponentI(mgr, descrName, tagName) {

    ui.setupUi(this);
    connect (ui.actionExit, SIGNAL(triggered()), this, SLOT(close()));
    connect (this, SIGNAL(imageReady()), this, SLOT(updateImageLabel()));
    connect (ui.actionSave_Frame_as_Image, SIGNAL(triggered()), this, SLOT(saveImage()));
}
예제 #13
0
QIcon RecaptchaPluginConfig::icon() const {
    const QPixmap icon = ImageCache::instance()->image(iconFilePath());

    if (icon.isNull()) {
        connect(ImageCache::instance(), SIGNAL(imageReady(QString)), this, SLOT(onImageReady(QString)));
        return QPixmap(DEFAULT_ICON);
    }

    return icon;
}
예제 #14
0
bool WidgetRenderer::receiveFrame(const VideoFrame &frame)
{
    prepareFrame(frame);
    //update();
    /*
     * workaround for the widget not updated if has parent. don't know why it works and why update() can't
     * Thanks to Vito Covito and Carlo Scarpato
     */
    emit imageReady();
    return true;
}
예제 #15
0
void QCameraDevice::onTimeout()
{
    if (!m_capture->isOpened()) {
        return;
    }
    static cv::Mat frame;
    *m_capture >> frame;
    if (frame.cols) {
        emit imageReady(imageFromMat(frame));
    }
}
예제 #16
0
bool WidgetRenderer::receiveFrame(const VideoFrame &frame)
{
    preparePixmap(frame);
    updateUi();
    /*
     * workaround for the widget not updated if has parent. don't know why it works and why update() can't
     * Thanks to Vito Covito and Carlo Scarpato
     * Now it's fixed by posting a QUpdateLaterEvent
     */
    Q_EMIT imageReady();
    return true;
}
예제 #17
0
void LocalImageLoader::onImageReady() {
	{
		QMutexLocker lock(toPrepareMutex());
		if (toPrepare.isEmpty()) {
			if (priv) priv->deleteLater();
			priv = 0;
			if (thread) thread->deleteLater();
			thread = 0;
		}
	}

	emit imageReady();
}
VimeoPlaylistDialog::VimeoPlaylistDialog(VimeoVideo *video, QWidget *parent) :
    Dialog(parent),
    m_video(video),
    m_playlist(0),
    m_model(new VimeoPlaylistModel(this)),
    m_cache(new ImageCache),
    m_view(new ListView(this)),
    m_tabBar(new QTabBar(this)),
    m_stack(new QStackedWidget(this)),
    m_scrollArea(0),
    m_titleEdit(0),
    m_descriptionEdit(0),
    m_passwordEdit(0),
    m_label(new QLabel(QString("<p align='center'; style='font-size: 40px; color: %1'>%2</p>")
                              .arg(palette().color(QPalette::Mid).name()).arg(tr("No albums found")), this)),
    m_buttonBox(new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Vertical, this)),
    m_layout(new QGridLayout(this))
{
    setWindowTitle(tr("Add to album"));
    setMinimumHeight(340);
    
    m_view->setModel(m_model);
    m_view->setItemDelegate(new PlaylistDelegate(m_cache, VimeoPlaylistModel::DateRole,
                                                 VimeoPlaylistModel::ThumbnailUrlRole, VimeoPlaylistModel::TitleRole,
                                                 VimeoPlaylistModel::UsernameRole, VimeoPlaylistModel::VideoCountRole,
                                                 m_view));
    
    m_tabBar->addTab(tr("Albums"));
    m_tabBar->addTab(tr("New album"));
    m_tabBar->setExpanding(false);
    m_tabBar->setDrawBase(false);
    m_tabBar->setStyleSheet("QTabBar::tab { height: 40px; }");
    
    m_stack->addWidget(m_view);
    m_stack->addWidget(m_label);
    
    m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
    
    m_layout->addWidget(m_tabBar, 0, 0);
    m_layout->addWidget(m_stack, 1, 0);
    m_layout->addWidget(m_buttonBox, 1, 1, 2, 1);
    m_layout->setRowStretch(1, 1);
        
    connect(m_cache, SIGNAL(imageReady()), this, SLOT(onImageReady()));
    connect(m_model, SIGNAL(statusChanged(QVimeo::ResourcesRequest::Status)),
            this, SLOT(onModelStatusChanged(QVimeo::ResourcesRequest::Status)));
    connect(m_view, SIGNAL(activated(QModelIndex)), this, SLOT(addToPlaylist(QModelIndex)));
    connect(m_tabBar, SIGNAL(currentChanged(int)), this, SLOT(onTabIndexChanged(int)));
    connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
    connect(m_buttonBox, SIGNAL(accepted()), this, SLOT(createNewPlaylist()));         
}
예제 #19
0
VimeoUsersWindow::VimeoUsersWindow(StackedWindow *parent) :
    StackedWindow(parent),
    m_model(new VimeoUserModel(this)),
    m_cache(new ImageCache),
    m_view(new ListView(this)),
    m_delegate(new UserDelegate(m_cache, VimeoUserModel::SubscriberCountRole, VimeoUserModel::ThumbnailUrlRole,
                                VimeoUserModel::UsernameRole, m_view)),
    m_viewGroup(new QActionGroup(this)),
    m_listAction(new QAction(tr("List"), this)),
    m_gridAction(new QAction(tr("Grid"), this)),
    m_reloadAction(new QAction(tr("Reload"), this)),
    m_label(new QLabel(QString("<p align='center'; style='font-size: 40px; color: %1'>%2</p>")
                              .arg(palette().color(QPalette::Mid).name()).arg(tr("No users found")), this))
{
    setWindowTitle(tr("Users"));
    setCentralWidget(new QWidget);
    
    m_view->setModel(m_model);
    m_view->setItemDelegate(m_delegate);
    
    m_listAction->setCheckable(true);
    m_listAction->setChecked(true);
    m_gridAction->setCheckable(true);
    m_viewGroup->setExclusive(true);
    m_viewGroup->addAction(m_listAction);
    m_viewGroup->addAction(m_gridAction);
    m_reloadAction->setEnabled(false);
    
    m_label->hide();
    
    m_layout = new QVBoxLayout(centralWidget());
    m_layout->addWidget(m_view);
    m_layout->addWidget(m_label);
    m_layout->setContentsMargins(0, 0, 0, 0);
    
    menuBar()->addAction(m_listAction);
    menuBar()->addAction(m_gridAction);
    menuBar()->addAction(m_reloadAction);
    
    connect(m_model, SIGNAL(statusChanged(QVimeo::ResourcesRequest::Status)), this,
            SLOT(onModelStatusChanged(QVimeo::ResourcesRequest::Status)));
    connect(m_cache, SIGNAL(imageReady()), this, SLOT(onImageReady()));
    connect(m_view, SIGNAL(activated(QModelIndex)), this, SLOT(showUser(QModelIndex)));
    connect(m_listAction, SIGNAL(triggered()), this, SLOT(enableListMode()));
    connect(m_gridAction, SIGNAL(triggered()), this, SLOT(enableGridMode()));
    connect(m_reloadAction, SIGNAL(triggered()), m_model, SLOT(reload()));
    
    if (Settings::instance()->defaultViewMode() == "grid") {
        m_gridAction->trigger();
    }
}
예제 #20
0
파일: JpegServer.cpp 프로젝트: dtbinh/dviz
void JpegServer::incomingConnection(int socketDescriptor)
{
	JpegServerThread *thread = new JpegServerThread(socketDescriptor, m_adaptiveWriteEnabled);
	connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
	connect(this, SIGNAL(frameReady(QImage)), thread, SLOT(imageReady(QImage)), Qt::QueuedConnection);
	thread->start();
	qDebug() << "JpegServer: Client Connected, Socket Descriptor:"<<socketDescriptor;
	
	
	thread->moveToThread(thread);
	
	if(!m_timer.isActive())
		m_timer.start();
}
예제 #21
0
WidgetRenderer::WidgetRenderer(WidgetRendererPrivate &d, QWidget *parent, Qt::WindowFlags f)
    :QWidget(parent, f),QPainterRenderer(d)
{
    d.painter = new QPainter();
    setAcceptDrops(true);
    setFocusPolicy(Qt::StrongFocus);
    setAutoFillBackground(false);
    QPainterFilterContext *ctx = static_cast<QPainterFilterContext*>(d.filter_context);
    if (ctx) {
        ctx->painter = d.painter;
    } else {
        qWarning("FilterContext not available!");
    }
    connect(this, SIGNAL(imageReady()), SLOT(update()));
}
예제 #22
0
void CameraWorker::onTimeout()
{
    if(ros::ok())
        ros::spinOnce();

    QImage qimg((uchar*)imageptr_cv.data, imageptr_cv.cols, imageptr_cv.rows, imageptr_cv.step, QImage::Format_RGB888);
    myMutex->lock();
    if(myPixmap)
        delete myPixmap;
    myPixmap = new QPixmap(QPixmap::fromImage(qimg));
    myMutex->unlock();
    emit imageReady(myPixmap);
    timer->setSingleShot(true);
    timer->start(10);
}
예제 #23
0
void CameraWorker::onTimeout()
{
    if(isCamera)
    {
        displayFrame = displayCamFrame;
        frame = cvQueryFrame(capture);
    }
    else
    {
        displayFrame = displayArenaFrame;
        frame = arenaFrame;
    }
    if(!frame)
        return;
    frame->roi = roi;
    cvResize(frame, calibFrame, CV_INTER_NN);
    cvCopy(calibFrame, displayFrame);
    if(isThreshold)
        colorImage(calibFrame, displayFrame);    
    if(isBlob)
    {
        makeBlobImage(frame, blobImage);
        b->detectBlobs(blobImage, a.getZoneImage());
        blobDataArr = b->getBlobDataArr();
        drawBlobs(displayFrame, blobDataArr);
        myMutex->lock();
        bs->populateFromBlobData(blobDataArr);
        bs->bombDepositPoint = a.getBombDrop();
        bs->resourceDepositPoint = a.getMineDrop();
        bs->startCorner = a.getStartCorner();
        myMutex->unlock();
        emit beliefStateReady(bs);
    }
    if(isArenaCalib)
    {
        a.drawArenaDisplay(displayFrame);
    }
    cvCvtColor(displayFrame, displayFrame,CV_BGR2RGB);
    QImage qimg((uchar*)displayFrame->imageData, displayFrame->width, displayFrame->height, displayFrame->widthStep, QImage::Format_RGB888);
    myMutex->lock();
    if(myPixmap)
        delete myPixmap;
    myPixmap = new QPixmap(QPixmap::fromImage(qimg));
    myMutex->unlock();
    emit imageReady(myPixmap);
    timer->setSingleShot(true);
    timer->start(10);
}
예제 #24
0
void QFrameConverter::timerEvent(QTimerEvent * ev)
{
    if (ev->timerId() != timer.timerId())
    {
        QObject::timerEvent(ev);
    }
    else
    {
        if (!pauseProcessing)
        {
            frameSource->getFrame(frame);

            if (!frame.empty())
            {
                QImage::Format format(QImage::Format_RGB888);
                switch (frame.channels())
                {
                case 1:
                    format = QImage::Format_Grayscale8;
                    break;
                case 3:
                    format = QImage::Format_RGB888;
                    break;
                default:
                    Q_ASSERT(false);
                }

                const QImage image(frame.data, frame.cols, frame.rows, static_cast<int>(frame.step), format);

                Q_ASSERT(image.constBits() == frame.data);

                emit imageReady(image);
            }
        }
    }

    if (stopTimer)
    {
        timer.stop();
        while(timer.isActive())
        {
            QThread::sleep(10);
        }
    }
}
예제 #25
0
void QuaZipImageSource::extractAll()
{
    _archive->open(QuaZip::mdUnzip);
    _archive->goToFirstFile();

    // Keep track of the images that have not been extracted yet.
    auto images = QList<ImageSourceItem>(_images);
    auto index = 0;

    while (!images.isEmpty() && !_extractWatcher.isCanceled()) {

        // If the currently displayed image has changed and has not yet been
        // extracted, change the index to that image.
        if (_currentFileNameChanged) {
            auto i = std::find_if(images.begin(), images.end(), [&](ImageSourceItem a) {
                return a.second->relativeFilePath() == _currentFileName;
            });

            if (i != images.end()) {
                index = i - images.begin();
            }
        }

        // Loop through the list of images.
        if (index >= images.size()) {
            index = 0;
        }

        // Extract the image.
        auto file = images.at(index).second;
        if (!file->exists()) {
            _archive->setCurrentFile(file->relativeFilePath());
            this->extractImage(_archive.get(), file->absoluteFilePath());
            emit imageReady(file->relativeFilePath());
        }

        // Since the image is removed, the index remains the same.
        images.removeAt(index);
    }

    _archive->close();
}
예제 #26
0
파일: webcams.cpp 프로젝트: Fale/qtmoko
void V4L1Still::takeStillImage(unsigned int format, QSize resolution, int count, unsigned int msecs)
{
    Q_UNUSED(count);
    Q_UNUSED(msecs);

    if(format != QtopiaCamera::RGB32 && resolution != wc->current_resolution) return;

    bool wasActivated = false;

    if(!wc->preview->preview_active) {
        wc->preview->start(QtopiaCamera::RGB32, wc->current_resolution, 15);
        if(!wc->preview->preview_active) return;
        wasActivated = true;
    }

    QByteArray ba(reinterpret_cast<char*>(wc->preview->preview_buffer_data), wc->preview->preview_buffer_bytesused);
    emit imageReady(ba, QSize(wc->preview->preview_buffer_width, wc->preview->preview_buffer_height), true);


    if(wasActivated)
        wc->preview->stop();
}
예제 #27
0
WidgetRenderer::WidgetRenderer(QWidget *parent, Qt::WindowFlags f) :
    QWidget(parent, f),QPainterRenderer(*new WidgetRendererPrivate())
{
    DPTR_D(WidgetRenderer);
    d.painter = new QPainter();
    setAcceptDrops(true);
    setFocusPolicy(Qt::StrongFocus);
    /* To rapidly update custom widgets that constantly paint over their entire areas with
     * opaque content, e.g., video streaming widgets, it is better to set the widget's
     * Qt::WA_OpaquePaintEvent, avoiding any unnecessary overhead associated with repainting the
     * widget's background
     */
    setAttribute(Qt::WA_OpaquePaintEvent);
    setAutoFillBackground(false);
    QPainterFilterContext *ctx = static_cast<QPainterFilterContext*>(d.filter_context);
    if (ctx) {
        ctx->painter = d.painter;
    } else {
        qWarning("FilterContext not available!");
    }
    connect(this, SIGNAL(imageReady()), SLOT(update()));
}
예제 #28
0
파일: webcams.cpp 프로젝트: Fale/qtmoko
void Still::takeStillImage(unsigned int format, QSize resolution, int count , unsigned int msecs )
{
    if (count < 1 || !wc->stillFormatMap.keys().contains(format) ||
        !wc->stillFormatMap.value(format).contains(resolution)) return;

    Q_UNUSED(msecs);
    bool previewWasStarted = false;
    bool revert = false;
    QSize saved_res = wc->preview->resolution();
    unsigned int saved_format = wc->preview->format();

    if(!wc->preview->preview_active) {
        wc->preview->start(wc->preview->format(), resolution, wc->preview->framerate());
        if(!wc->preview->preview_active) return;
        previewWasStarted = true;
    } else if (resolution != wc->preview->resolution()) {
        wc->preview->stop();
        Qtopia::msleep(500);
        wc->preview->start(format, resolution, wc->preview->framerate());
        revert = true;
    }
    // give camera time to adjust
    Qtopia::msleep(2000);
    current_resolution = resolution;
    current_format = format;

    int bu = wc->preview->preview_buffer_bytesused;
    QByteArray ba(reinterpret_cast<const char*>(wc->preview->preview_buffer_data), bu);

    emit imageReady(ba, QSize(wc->preview->preview_buffer_width, wc->preview->preview_buffer_height), true);

    if(previewWasStarted) {
        wc->preview->stop();
    } else if (revert) {
        wc->preview->stop();
        wc->preview->start(saved_format, saved_res, wc->preview->framerate());
    }
}
예제 #29
0
QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    const QString & uri = id;

    if (uri.simplified().isEmpty())
        return QImage();

    QMetaObject::invokeMethod(this, "loadImage", Qt::QueuedConnection,
                              Q_ARG(QString, uri));

    QMutexLocker locker(&m_waitMutex);

    while (!imageReady(uri) && !m_cancel)
    {
        m_waitCondition.wait(&m_waitMutex);
    }

    if (m_cancel)
        return QImage();

    QByteArray data = takeImageData(uri);

    // We have the data, release the lock before decoding/scaling
    // (do not access shared data after this point)
    locker.unlock();

    QImage image = QImage::fromData(data);
    *size = image.size();

    if (requestedSize.isValid())
    {
        return image.scaled(requestedSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    }
    else
    {
        return image;
    }
}
SoundCloudPlaylistsWindow::SoundCloudPlaylistsWindow(StackedWindow *parent) :
    StackedWindow(parent),
    m_model(new SoundCloudPlaylistModel(this)),
    m_cache(new ImageCache),
    m_nowPlayingAction(new NowPlayingAction(this)),
    m_view(new ListView(this)),
    m_reloadAction(new QAction(tr("Reload"), this)),
    m_label(new QLabel(QString("<p align='center'; style='font-size: 40px; color: %1'>%2</p>")
                              .arg(palette().color(QPalette::Mid).name()).arg(tr("No sets found")), this))
{
    setWindowTitle(tr("Sets"));
    setCentralWidget(new QWidget);
    
    m_view->setModel(m_model);
    m_view->setItemDelegate(new PlaylistDelegate(m_cache, SoundCloudPlaylistModel::ArtistRole,
                                                 SoundCloudPlaylistModel::DateRole,
                                                 SoundCloudPlaylistModel::ThumbnailUrlRole,
                                                 SoundCloudPlaylistModel::TitleRole,
                                                 SoundCloudPlaylistModel::TrackCountRole, m_view));
    m_reloadAction->setEnabled(false);
    
    m_label->hide();
    
    m_layout = new QVBoxLayout(centralWidget());
    m_layout->addWidget(m_view);
    m_layout->addWidget(m_label);
    m_layout->setContentsMargins(0, 0, 0, 0);
    
    menuBar()->addAction(m_reloadAction);
    menuBar()->addAction(m_nowPlayingAction);
    
    connect(m_model, SIGNAL(statusChanged(QSoundCloud::ResourcesRequest::Status)), this,
            SLOT(onModelStatusChanged(QSoundCloud::ResourcesRequest::Status)));
    connect(m_cache, SIGNAL(imageReady()), this, SLOT(onImageReady()));
    connect(m_view, SIGNAL(activated(QModelIndex)), this, SLOT(showPlaylist(QModelIndex)));
    connect(m_reloadAction, SIGNAL(triggered()), m_model, SLOT(reload()));
}