void ExtractOneVideoFrame::markShortVideo(const DB::FileName &fileName)
{
    if (s_tokenForShortVideos.isNull()) {
        Utilities::StringSet usedTokens = MainWindow::TokenEditor::tokensInUse().toSet();
        for ( int ch = 'A'; ch <= 'Z'; ++ch ) {
            QString token = QChar::fromLatin1( (char) ch );
            if (!usedTokens.contains(token)) {
                s_tokenForShortVideos = token;
                break;
            }
        }

        if (s_tokenForShortVideos.isNull()) {
            // Hmmm, no free token. OK lets just skip setting tokens.
            return;
        }
        KMessageBox::information(MainWindow::Window::theMainWindow(),
                                 i18n("Unable to extract video thumbnails from some files. "
                                      "Either the file is damaged in some way, or the video is ultra short. "
                                      "For your convenience, the token '%1' "
                                      "has been set on those videos.\n\n"
                                      "(You might need to wait till the video extraction led in your status bar has stopped blinking, "
                                      "to see all affected videos.)",
                                      s_tokenForShortVideos));
    }

    DB::ImageInfoPtr info = DB::ImageDB::instance()->info(fileName);
    DB::CategoryPtr tokensCategory = DB::ImageDB::instance()->categoryCollection()->categoryForSpecial(DB::Category::TokensCategory);
    info->addCategoryInfo(tokensCategory->name(), s_tokenForShortVideos);
    MainWindow::DirtyIndicator::markDirty();
}
void BackgroundJobs::SearchForVideosWithoutVideoThumbnailsJob::execute()
{
    const DB::FileNameList images = DB::ImageDB::instance()->images();

    for( const DB::FileName& image : images ) {
        const DB::ImageInfoPtr info = image.info();
        if ( !info->isVideo() )
            continue;

        // silently ignore videos not (currently) on disk:
        if ( ! info->fileName().exists() )
            continue;

        const DB::FileName thumbnailName = BackgroundJobs::HandleVideoThumbnailRequestJob::frameName(info->fileName(),9);
        if ( thumbnailName.exists() )
            continue;

        BackgroundJobs::ReadVideoLengthJob* readVideoLengthJob = new BackgroundJobs::ReadVideoLengthJob(info->fileName(), BackgroundTaskManager::BackgroundVideoPreviewRequest);

        for (int i=0; i<10; ++i) {
            ExtractOneThumbnailJob* extractJob = new ExtractOneThumbnailJob( info->fileName(), i, BackgroundTaskManager::BackgroundVideoPreviewRequest );
            extractJob->addDependency(readVideoLengthJob);
        }

        BackgroundTaskManager::JobManager::instance()->addJob( readVideoLengthJob);
    }
    emit completed();
}
void ThumbnailView::Delegate::paintVideoInfo(QPainter *painter, const QRect& pixmapRect, const QModelIndex &index) const
{
    DB::ImageInfoPtr imageInfo = model()->imageAt(index.row()).info();
    if (!imageInfo || imageInfo->mediaType() != DB::Video )
        return;

    const QString text = videoLengthText(imageInfo);
    const QRect metricsRect = painter->fontMetrics().boundingRect(text);

    const int margin = 3;
    const QRect textRect = QRect(pixmapRect.right()-metricsRect.width()-margin,
                                 pixmapRect.bottom()-metricsRect.height()-margin,
                                 metricsRect.width(), metricsRect.height());
    const QRect backgroundRect =  textRect.adjusted(-margin,-margin, margin, margin);

    if ( backgroundRect.width() > pixmapRect.width()/2  ) {
        // Don't show the time if the box would fill more than half the thumbnail
        return;
    }

    painter->save();
    painter->fillRect(backgroundRect, QBrush( QColor(0,0,0,128)));
    painter->setPen(Qt::white);
    painter->drawText(textRect, text);
    painter->restore();
}
Beispiel #4
0
ImportExport::ClashInfo ImportExport::MD5CheckPage::clashes(const ImportSettings& settings)
{
    QStringList myCategories;
    Q_FOREACH( const CategoryMatchSetting& matcher, settings.categoryMatchSetting() ) {
        myCategories.append( matcher.DBCategoryName() );
    }

    ClashInfo res( myCategories );
    DB::ImageInfoList list = settings.selectedImages();
    Q_FOREACH( DB::ImageInfoPtr info, list ) {
        if ( !DB::ImageDB::instance()->md5Map()->contains(info->MD5Sum()) )
            continue;

        const DB::FileName name = DB::ImageDB::instance()->md5Map()->lookup(info->MD5Sum());
        DB::ImageInfoPtr other = DB::ImageDB::instance()->info(name);
        if ( info->label() != other->label() )
            res.label = true;
        if ( info->description() != other->description() )
            res.description = true;

        if ( info->angle() != other->angle() )
            res.orientation = true;

        if (info->date() != other->date() )
            res.date = true;

        Q_FOREACH( const CategoryMatchSetting& matcher, settings.categoryMatchSetting() ) {
            const QString XMLFileCategory = matcher.XMLCategoryName();
            const QString DBCategory = matcher.DBCategoryName();
            if ( mapCategoriesToDB( matcher, info->itemsOfCategory( XMLFileCategory ) ) != other->itemsOfCategory( DBCategory ) )
                res.categories[DBCategory] = true;
        }
    }
    return res;
}
void ExtractOneThumbnailJob::execute()
{    
    if ( m_wasCanceled || frameName().exists() )
        emit completed();
    else {
        DB::ImageInfoPtr info = DB::ImageDB::instance()->info(m_fileName);
        const int length = info->videoLength();
        ImageManager::ExtractOneVideoFrame::extract(m_fileName, length*m_index/10.0, this, SLOT(frameLoaded(QImage)));
    }
}
QString ThumbnailView::Delegate::videoLengthText(const DB::ImageInfoPtr &imageInfo) const
{
    const int length = imageInfo->videoLength();
    if ( length < 0 )
        return i18nc("No video length could be determined, so we just display 'video' instead of the video length.","video");

    const int hours = length/60/60;
    const int minutes = (length/60)%60;
    const int secs = length % 60;

    QString res;
    if (hours > 0)
        res = QString::number(hours) + QLatin1String(":");

    if (minutes < 10 && hours > 0)
        res += QLatin1String("0");

    res += QString::number(minutes);
    res += QLatin1String(":");

    if (secs < 10)
        res += QLatin1String("0");

    res += QString::number(secs);

    return res;
}
QDomElement ImportExport::XMLHandler::save( QDomDocument doc, const DB::ImageInfoPtr& info )
{
    QDomElement elm = doc.createElement( QString::fromLatin1("image") );
    elm.setAttribute( QString::fromLatin1("label"),  info->label() );
    elm.setAttribute( QString::fromLatin1("description"), info->description() );

    DB::ImageDate date = info->date();
    QDateTime start = date.start();
    QDateTime end = date.end();

    elm.setAttribute( QString::fromLatin1("yearFrom"), start.date().year() );
    elm.setAttribute( QString::fromLatin1("monthFrom"),  start.date().month() );
    elm.setAttribute( QString::fromLatin1("dayFrom"),  start.date().day() );
    elm.setAttribute( QString::fromLatin1("hourFrom"), start.time().hour() );
    elm.setAttribute( QString::fromLatin1("minuteFrom"), start.time().minute() );
    elm.setAttribute( QString::fromLatin1("secondFrom"), start.time().second() );

    elm.setAttribute( QString::fromLatin1("yearTo"), end.date().year() );
    elm.setAttribute( QString::fromLatin1("monthTo"),  end.date().month() );
    elm.setAttribute( QString::fromLatin1("dayTo"),  end.date().day() );

    elm.setAttribute( QString::fromLatin1( "width" ), info->size().width() );
    elm.setAttribute( QString::fromLatin1( "height" ), info->size().height() );
    elm.setAttribute( QString::fromLatin1( "md5sum" ), info->MD5Sum().toHexString() );
    elm.setAttribute( QString::fromLatin1( "angle" ), info->angle() );

    writeCategories( doc, elm, info );

    return elm;
}
void ImportExport::XMLHandler::writeCategories( QDomDocument doc, QDomElement root, const DB::ImageInfoPtr& info )
{
    QDomElement elm = doc.createElement( QString::fromLatin1("options") );

    bool anyAtAll = false;
    QStringList grps = info->availableCategories();
    Q_FOREACH(const QString &name, grps ) {
        QDomElement opt = doc.createElement( QString::fromLatin1("option") );
        opt.setAttribute( QString::fromLatin1("name"),  name );

        StringSet items = info->itemsOfCategory(name);
        bool any = false;
        Q_FOREACH( const QString &item, items ) {
            QDomElement val = doc.createElement( QString::fromLatin1("value") );
            val.setAttribute( QString::fromLatin1("value"), item );
            opt.appendChild( val );
            any = true;
            anyAtAll = true;
        }
Beispiel #9
0
void ToolTip::requestImage( const DB::FileName& fileName )
{
    int size = Settings::SettingsData::instance()->previewSize();
    DB::ImageInfoPtr info = DB::ImageDB::instance()->info( fileName );
    if ( size != 0 ) {
        ImageManager::ImageRequest* request = new ImageManager::ImageRequest( fileName, QSize( size, size ), info->angle(), this );
        request->setPriority( ImageManager::Viewer );
        ImageManager::AsyncLoader::instance()->load( request );
    }
    else
        renderToolTip();
}
void ThumbnailView::Delegate::paintStackedIndicator( QPainter* painter, const QRect &pixmapRect, const QModelIndex& index ) const
{
    DB::ImageInfoPtr imageInfo = model()->imageAt(index.row()).info();
    if (!imageInfo || !imageInfo->isStacked())
        return;

    const QRect cellRect = widget()->visualRect( index );

    // Calculate the three points for the bottom most/right most lines
    int leftX = cellRect.left();
    int rightX = cellRect.right() + 5; // 5 for the 3D effect

    if ( isFirst( index.row() ) )
        leftX = pixmapRect.left() + pixmapRect.width()/2;

    if ( isLast( index.row() ) )
        rightX = pixmapRect.right();

    QPoint bottomLeftPoint( leftX, pixmapRect.bottom() );
    QPoint bottomRightPoint( rightX, pixmapRect.bottom() );
    QPoint topPoint = isLast( index.row() ) ? QPoint( rightX, pixmapRect.top() + pixmapRect.height()/2 ) : QPoint();

    // Paint the lines.
    painter->save();
    for ( int i=0; i < 8; ++i ) {
        painter->setPen( QPen(i % 2 == 0 ? Qt::black : Qt::white) );

        painter->drawLine(bottomLeftPoint,bottomRightPoint);
        if ( topPoint != QPoint() ) {
            painter->drawLine( bottomRightPoint, topPoint );
            topPoint -= QPoint(1,1);
        }

        bottomLeftPoint -= QPoint( isFirst( index.row()) ? 1 : 0, 1 );
        bottomRightPoint -= QPoint( isLast( index.row()) ? 1 : 0, 1);
    }
    painter->restore();
}
void MainWindow::ExternalPopup::populate( DB::ImageInfoPtr current, const DB::FileNameList& imageList )
{
    _list = imageList;
    _currentInfo = current;
    clear();
    QAction *action;

    QStringList list = QStringList() << i18n("Current Item") << i18n("All Selected Items") << i18n("Copy and Open");
    for ( int which = 0; which < 3; ++which ) {
        if ( which == 0 && !current )
            continue;

        const bool multiple = (_list.count() > 1);
        const bool enabled = (which != 1 && _currentInfo ) || (which == 1 && multiple);

        // Submenu
        QMenu *submenu = addMenu( list[which] );
        submenu->setEnabled(enabled);

        // Fetch set of offers
        OfferType offers;
        if ( which == 0 )
            offers = appInfos( DB::FileNameList() << current->fileName() );
        else
            offers = appInfos( imageList );

        for ( OfferType::const_iterator offerIt = offers.begin(); offerIt != offers.end(); ++offerIt ) {
            action = submenu->addAction( (*offerIt).first );
            action->setObjectName( (*offerIt).first ); // Notice this is needed to find the application later!
            action->setIcon( KIcon((*offerIt).second) );
            action->setData( which );
            action->setEnabled( enabled );
        }

        // A personal command
        action = submenu->addAction( i18n("Open With...") );
        action->setObjectName( i18n("Open With...") ); // Notice this is needed to find the application later!
        // XXX: action->setIcon( KIcon((*offerIt).second) );
        action->setData( which );
        action->setEnabled( enabled );

        // A personal command
        // XXX: see kdialog.h for simple usage
        action = submenu->addAction( i18n("Your Command Line") );
        action->setObjectName( i18n("Your Command Line") ); // Notice this is needed to find the application later!
        // XXX: action->setIcon( KIcon((*offerIt).second) );
        action->setData( which );
        action->setEnabled( enabled );
    }
}