Example #1
0
void UniversalUpdates::PerformUniversalUpdates( bool resources_already_loaded,
                                                const QList< Resource* > &resources,
                                                const QHash< QString, QString > &updates )
{
    QHash< QString, QString > html_updates;
    QHash< QString, QString > css_updates;
    QHash< QString, QString > xml_updates;
    tie( html_updates, css_updates, xml_updates ) = SeparateHtmlCssXmlUpdates( updates );

    QList< HTMLResource* > html_resources;
    QList< CSSResource* > css_resources;
    OPFResource *opf_resource = NULL;
    NCXResource *ncx_resource = NULL;

    int num_files = resources.count();

    for ( int i = 0; i < num_files; ++i )
    {
        Resource *resource = resources.at( i );

        if ( resource->Type() == Resource::HTMLResourceType )

            html_resources.append( qobject_cast< HTMLResource* >( resource ) );

        else if ( resource->Type() == Resource::CSSResourceType )

            css_resources.append( qobject_cast< CSSResource* >( resource ) );

        else if ( resource->Type() == Resource::OPFResourceType )
        
            opf_resource = qobject_cast< OPFResource* >( resource );
        
        else if ( resource->Type() == Resource::NCXResourceType )
        
            ncx_resource = qobject_cast< NCXResource* >( resource );      
    }

    QFutureSynchronizer<void> sync;

    if ( resources_already_loaded )
    {
        sync.addFuture( QtConcurrent::map( html_resources, boost::bind( UpdateOneHTMLFile, _1, html_updates, css_updates ) ) );
        sync.addFuture( QtConcurrent::map( css_resources,  boost::bind( UpdateOneCSSFile,  _1, css_updates ) ) );
    }

    else
    {
        sync.addFuture( QtConcurrent::map( html_resources, boost::bind( LoadAndUpdateOneHTMLFile, _1, html_updates, css_updates ) ) );
        sync.addFuture( QtConcurrent::map( css_resources,  boost::bind( LoadAndUpdateOneCSSFile,  _1, css_updates ) ) );
    }

    // We can't schedule these with QtConcurrent because they
    // will (indirectly) call QTextDocument::setPlainText, and if
    // a tab is open for the ncx/opf, then an event needs to be sent
    // to the tab widget. Events can't cross threads, and we crash.
    UpdateNCXFile( ncx_resource, xml_updates );
    UpdateOPFFile( opf_resource, xml_updates );

    sync.waitForFinished();
}
Example #2
0
void ImportHTML::UpdateFiles(HTMLResource &html_resource,
                             QString & source, 
                             const QHash<QString, QString> &updates)
{
    Q_ASSERT(&html_resource != NULL);
    QHash<QString, QString> html_updates;
    QHash<QString, QString> css_updates;
    QString newsource = source;
    QString currentpath = html_resource.GetCurrentBookRelPath();
    std::tie(html_updates, css_updates, std::ignore) =
        UniversalUpdates::SeparateHtmlCssXmlUpdates(updates);
    QList<Resource *> all_files = m_Book->GetFolderKeeper().GetResourceList();
    int num_files = all_files.count();
    QList<CSSResource *> css_resources;

    for (int i = 0; i < num_files; ++i) {
        Resource *resource = all_files.at(i);

        if (resource->Type() == Resource::CSSResourceType) {
            css_resources.append(qobject_cast<CSSResource *>(resource));
        }
    }
    
    QFutureSynchronizer<void> sync;
    sync.addFuture(QtConcurrent::map(css_resources,
                                     std::bind(UniversalUpdates::LoadAndUpdateOneCSSFile, std::placeholders::_1, css_updates)));
    html_resource.SetText(PerformHTMLUpdates(newsource, html_updates, css_updates, currentpath)());
    html_resource.SetCurrentBookRelPath("");
    sync.waitForFinished();
}
QStringList UniversalUpdates::PerformUniversalUpdates(bool resources_already_loaded,
        const QList<Resource *> &resources,
        const QHash<QString, QString> &updates,
        const QList<XMLResource *> &non_well_formed)
{
    QStringList updatekeys = updates.keys();
    QHash<QString, QString> html_updates;
    QHash<QString, QString> css_updates;
    QHash<QString, QString> xml_updates;
    std::tie(html_updates, css_updates, xml_updates) = SeparateHtmlCssXmlUpdates(updates);
    QList<HTMLResource *> html_resources;
    QList<CSSResource *> css_resources;
    OPFResource *opf_resource = NULL;
    NCXResource *ncx_resource = NULL;
    int num_files = resources.count();

    for (int i = 0; i < num_files; ++i) {
        Resource *resource = resources.at(i);

        if (resource->Type() == Resource::HTMLResourceType) {
            html_resources.append(qobject_cast<HTMLResource *>(resource));
        } else if (resource->Type() == Resource::CSSResourceType) {
            css_resources.append(qobject_cast<CSSResource *>(resource));
        } else if (resource->Type() == Resource::OPFResourceType) {
            opf_resource = qobject_cast<OPFResource *>(resource);
        } else if (resource->Type() == Resource::NCXResourceType) {
            ncx_resource = qobject_cast<NCXResource *>(resource);
        }
    }

    QFutureSynchronizer<void> sync;
    QFuture<QString> html_future;
    QFuture<void> css_future;

    if (resources_already_loaded) {
        html_future = QtConcurrent::mapped(html_resources, std::bind(UpdateOneHTMLFile, std::placeholders::_1, html_updates, css_updates));
        css_future = QtConcurrent::map(css_resources,  std::bind(UpdateOneCSSFile,  std::placeholders::_1, css_updates));
    } else {
        html_future = QtConcurrent::mapped(html_resources, std::bind(LoadAndUpdateOneHTMLFile, std::placeholders::_1, html_updates, css_updates, non_well_formed));
        css_future = QtConcurrent::map(css_resources,  std::bind(LoadAndUpdateOneCSSFile,  std::placeholders::_1, css_updates));
    }

    sync.addFuture(html_future);
    sync.addFuture(css_future);
    // We can't schedule these with QtConcurrent because they
    // will (indirectly) call QTextDocument::setPlainText, and if
    // a tab is open for the ncx/opf, then an event needs to be sent
    // to the tab widget. Events can't cross threads, and we crash.
    const QString ncx_result = UpdateNCXFile(ncx_resource, xml_updates);
    const QString opf_result = UpdateOPFFile(opf_resource, xml_updates);
    sync.waitForFinished();
    // Now assemble our list of errors if any.
    QStringList load_update_errors;

    for (int i = 0; i < html_future.results().count(); i++) {
        const QString html_error = html_future.resultAt(i);

        if (!html_error.isEmpty()) {
            load_update_errors.append(html_error);
        }
    }

    if (!ncx_result.isEmpty()) {
        load_update_errors.append(ncx_result);
    }

    if (!opf_result.isEmpty()) {
        load_update_errors.append(opf_result);
    }

    return load_update_errors;
}