diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2018-10-13 07:37:26 +0000 |
|---|---|---|
| committer | Tavmjong Bah <tavmjong@free.fr> | 2018-10-13 07:37:26 +0000 |
| commit | faf43f2ffa88561acb95909861bb28fcdfaeb858 (patch) | |
| tree | 77f397b880ec970981a754c9549b24842161855b /src/resource-manager.cpp | |
| parent | CI/AppVeyor: increase clone depth (diff) | |
| download | inkscape-faf43f2ffa88561acb95909861bb28fcdfaeb858.tar.gz inkscape-faf43f2ffa88561acb95909861bb28fcdfaeb858.zip | |
Move some files to 'io' directory.
Diffstat (limited to 'src/resource-manager.cpp')
| -rw-r--r-- | src/resource-manager.cpp | 445 |
1 files changed, 0 insertions, 445 deletions
diff --git a/src/resource-manager.cpp b/src/resource-manager.cpp deleted file mode 100644 index 6a455a8cc..000000000 --- a/src/resource-manager.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Inkscape::ResourceManager - tracks external resources such as image and css files. - * - * Copyright 2011 Jon A. Cruz <jon@joncruz.org> - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include <string> -#include <vector> -#include <algorithm> - -#include <gtkmm/recentmanager.h> -#include <glibmm/i18n.h> -#include <glibmm/miscutils.h> -#include <glibmm/fileutils.h> -#include <glibmm/uriutils.h> -#include <glibmm/convert.h> - -#include "resource-manager.h" - -#include "document.h" -#include "document-undo.h" -#include "verbs.h" - -#include "object/sp-object.h" - -#include "xml/node.h" - -namespace Inkscape { - -static std::vector<std::string> splitPath( std::string const &path ) -{ - std::vector<std::string> parts; - - std::string prior; - std::string tmp = path; - while ( !tmp.empty() && (tmp != prior) ) { - prior = tmp; - - parts.push_back( Glib::path_get_basename(tmp) ); - tmp = Glib::path_get_dirname(tmp); - } - if ( !parts.empty() ) { - std::reverse(parts.begin(), parts.end()); - if ( (parts[0] == ".") && (path[0] != '.') ) { - parts.erase(parts.begin()); - } - } - - return parts; -} - -static std::string convertPathToRelative( std::string const &path, std::string const &docbase ) -{ - std::string result = path; - - if ( !path.empty() && Glib::path_is_absolute(path) ) { - // Whack the parts into pieces - - std::vector<std::string> parts = splitPath(path); - std::vector<std::string> baseParts = splitPath(docbase); - - // TODO debug g_message("+++++++++++++++++++++++++"); - for ( std::vector<std::string>::iterator it = parts.begin(); it != parts.end(); ++it ) { - // TODO debug g_message(" [%s]", it->c_str()); - } - // TODO debug g_message(" - - - - - - - - - - - - - - - "); - for ( std::vector<std::string>::iterator it = baseParts.begin(); it != baseParts.end(); ++it ) { - // TODO debug g_message(" [%s]", it->c_str()); - } - // TODO debug g_message("+++++++++++++++++++++++++"); - - if ( !parts.empty() && !baseParts.empty() && (parts[0] == baseParts[0]) ) { - // Both paths have the same root. We can proceed. - while ( !parts.empty() && !baseParts.empty() && (parts[0] == baseParts[0]) ) { - parts.erase( parts.begin() ); - baseParts.erase( baseParts.begin() ); - } - - // TODO debug g_message("+++++++++++++++++++++++++"); - for ( std::vector<std::string>::iterator it = parts.begin(); it != parts.end(); ++it ) { - // TODO debug g_message(" [%s]", it->c_str()); - } - // TODO debug g_message(" - - - - - - - - - - - - - - - "); - for ( std::vector<std::string>::iterator it = baseParts.begin(); it != baseParts.end(); ++it ) { - // TODO debug g_message(" [%s]", it->c_str()); - } - // TODO debug g_message("+++++++++++++++++++++++++"); - - if ( !parts.empty() ) { - result.clear(); - - for ( size_t i = 0; i < baseParts.size(); ++i ) { - parts.insert(parts.begin(), ".."); - } - result = Glib::build_filename( parts ); - // TODO debug g_message("----> [%s]", result.c_str()); - } - } - } - - return result; -} - - -class ResourceManagerImpl : public ResourceManager { -public: - ResourceManagerImpl(); - ~ResourceManagerImpl() override; - - bool fixupBrokenLinks(SPDocument *doc) override; - - - /** - * Walk all links in a document and create a listing of unique broken links. - * - * @return a list of all broken links. - */ - std::vector<Glib::ustring> findBrokenLinks(SPDocument *doc); - - /** - * Resolve broken links as a whole and return a map for those that can be found. - * - * Note: this will allow for future enhancements including relinking to new locations - * with the most broken files found, etc. - * - * @return a map of found links. - */ - std::map<Glib::ustring, Glib::ustring> locateLinks(Glib::ustring const & docbase, std::vector<Glib::ustring> const & brokenLinks); - - - /** - * Try to parse href into a local filename using standard methods. - * - * @return true if successful. - */ - bool extractFilepath( Glib::ustring const &href, std::string &uri ); - - /** - * Try to parse href into a local filename using some non-standard methods. - * This means the href is likely invalid and should be rewritten. - * - * @return true if successful. - */ - bool reconstructFilepath( Glib::ustring const &href, std::string &uri ); - - bool searchUpwards( std::string const &base, std::string const &subpath, std::string &dest ); - -protected: -}; - - -ResourceManagerImpl::ResourceManagerImpl() - : ResourceManager() -{ -} - -ResourceManagerImpl::~ResourceManagerImpl() -= default; - -bool ResourceManagerImpl::extractFilepath( Glib::ustring const &href, std::string &uri ) -{ - bool isFile = false; - - uri.clear(); - - std::string scheme = Glib::uri_parse_scheme(href); - if ( !scheme.empty() ) { - // TODO debug g_message("Scheme is now [%s]", scheme.c_str()); - if ( scheme == "file" ) { - // TODO debug g_message("--- is a file URI [%s]", href.c_str()); - - // throws Glib::ConvertError: - try { - uri = Glib::filename_from_uri(href); - // TODO debug g_message(" [%s]", uri.c_str()); - isFile = true; - } catch(Glib::ConvertError e) { - g_warning("%s", e.what().c_str()); - } - } - } else { - // No scheme. Assuming it is a file path (absolute or relative). - // throws Glib::ConvertError: - uri = Glib::filename_from_utf8( href ); - isFile = true; - } - - return isFile; -} - -bool ResourceManagerImpl::reconstructFilepath( Glib::ustring const &href, std::string &uri ) -{ - bool isFile = false; - - uri.clear(); - - std::string scheme = Glib::uri_parse_scheme(href); - if ( !scheme.empty() ) { - if ( scheme == "file" ) { - // try to build a relative filename for URIs like "file:image.png" - // they're not standard conformant but not uncommon - Glib::ustring href_new = Glib::ustring(href, 5); - uri = Glib::filename_from_utf8(href_new); - // TODO debug g_message("reconstructed path for '%s' into '%s'", href.c_str(), uri.c_str()); - isFile = true; - } - } - return isFile; -} - - -std::vector<Glib::ustring> ResourceManagerImpl::findBrokenLinks( SPDocument *doc ) -{ - std::vector<Glib::ustring> result; - std::set<Glib::ustring> uniques; - - if ( doc ) { - std::vector<SPObject *> images = doc->getResourceList("image"); - for (std::vector<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) { - Inkscape::XML::Node *ir = (*it)->getRepr(); - - gchar const *href = ir->attribute("xlink:href"); - if ( href && ( uniques.find(href) == uniques.end() ) ) { - std::string uri; - if ( extractFilepath( href, uri ) ) { - if ( Glib::path_is_absolute(uri) ) { - if ( !Glib::file_test(uri, Glib::FILE_TEST_EXISTS) ) { - result.emplace_back(href); - uniques.insert(href); - } - } else { - std::string combined = Glib::build_filename(doc->getBase(), uri); - if ( !Glib::file_test(combined, Glib::FILE_TEST_EXISTS) ) { - result.emplace_back(href); - uniques.insert(href); - } - } - } else if ( reconstructFilepath( href, uri ) ) { - result.emplace_back(href); - uniques.insert(href); - } - } - } - } - - return result; -} - - -std::map<Glib::ustring, Glib::ustring> ResourceManagerImpl::locateLinks(Glib::ustring const & docbase, std::vector<Glib::ustring> const & brokenLinks) -{ - std::map<Glib::ustring, Glib::ustring> result; - - - // Note: we use a vector because we want them to stay in order: - std::vector<std::string> priorLocations; - - Glib::RefPtr<Gtk::RecentManager> recentMgr = Gtk::RecentManager::get_default(); - std::vector< Glib::RefPtr<Gtk::RecentInfo> > recentItems = recentMgr->get_items(); - for ( std::vector< Glib::RefPtr<Gtk::RecentInfo> >::iterator it = recentItems.begin(); it != recentItems.end(); ++it ) { - Glib::ustring uri = (*it)->get_uri(); - std::string scheme = Glib::uri_parse_scheme(uri); - if ( scheme == "file" ) { - try { - std::string path = Glib::filename_from_uri(uri); - path = Glib::path_get_dirname(path); - if ( std::find(priorLocations.begin(), priorLocations.end(), path) == priorLocations.end() ) { - // TODO debug g_message(" ==>[%s]", path.c_str()); - priorLocations.push_back(path); - } - } catch (Glib::ConvertError e) { - g_warning("%s", e.what().c_str()); - } - } - } - - // At the moment we expect this list to contain file:// references, or simple relative or absolute paths. - for ( std::vector<Glib::ustring>::const_iterator it = brokenLinks.begin(); it != brokenLinks.end(); ++it ) { - // TODO debug g_message("========{%s}", it->c_str()); - - std::string uri; - if ( extractFilepath( *it, uri ) || reconstructFilepath( *it, uri ) ) { - // We were able to get some path. Check it - std::string origPath = uri; - - if ( !Glib::path_is_absolute(uri) ) { - uri = Glib::build_filename(docbase, uri); - // TODO debug g_message(" not absolute. Fixing up as [%s]", uri.c_str()); - } - - bool exists = Glib::file_test(uri, Glib::FILE_TEST_EXISTS); - - // search in parent folders - if (!exists) { - exists = searchUpwards( docbase, origPath, uri ); - } - - // Check if the MRU bases point us to it. - if ( !exists ) { - if ( !Glib::path_is_absolute(origPath) ) { - for ( std::vector<std::string>::iterator it = priorLocations.begin(); !exists && (it != priorLocations.end()); ++it ) { - exists = searchUpwards( *it, origPath, uri ); - } - } - } - - if ( exists ) { - if ( Glib::path_is_absolute( uri ) ) { - // TODO debug g_message("Need to convert to relative if possible [%s]", uri.c_str()); - uri = convertPathToRelative( uri, docbase ); - } - - bool isAbsolute = Glib::path_is_absolute( uri ); - Glib::ustring replacement = isAbsolute ? Glib::filename_to_uri( uri ) : Glib::filename_to_utf8( uri ); - result[*it] = replacement; - } - } - } - - return result; -} - -bool ResourceManagerImpl::fixupBrokenLinks(SPDocument *doc) -{ - bool changed = false; - if ( doc ) { - // TODO debug g_message("FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP FIXUP"); - // TODO debug g_message(" base is [%s]", doc->getBase()); - - std::vector<Glib::ustring> brokenHrefs = findBrokenLinks(doc); - if ( !brokenHrefs.empty() ) { - // TODO debug g_message(" FOUND SOME LINKS %d", static_cast<int>(brokenHrefs.size())); - for ( std::vector<Glib::ustring>::iterator it = brokenHrefs.begin(); it != brokenHrefs.end(); ++it ) { - // TODO debug g_message(" [%s]", it->c_str()); - } - } - - std::map<Glib::ustring, Glib::ustring> mapping = locateLinks(doc->getBase(), brokenHrefs); - for ( std::map<Glib::ustring, Glib::ustring>::iterator it = mapping.begin(); it != mapping.end(); ++it ) - { - // TODO debug g_message(" [%s] ==> {%s}", it->first.c_str(), it->second.c_str()); - } - - bool savedUndoState = DocumentUndo::getUndoSensitive(doc); - DocumentUndo::setUndoSensitive(doc, true); - - std::vector<SPObject *> images = doc->getResourceList("image"); - for (std::vector<SPObject *>::const_iterator it = images.begin(); it != images.end(); ++it) { - Inkscape::XML::Node *ir = (*it)->getRepr(); - - gchar const *href = ir->attribute("xlink:href"); - if ( href ) { - // TODO debug g_message(" consider [%s]", href); - - if ( mapping.find(href) != mapping.end() ) { - // TODO debug g_message(" Found a replacement"); - - ir->setAttribute( "xlink:href", mapping[href].c_str() ); - if ( ir->attribute( "sodipodi:absref" ) ) { - ir->setAttribute( "sodipodi:absref", nullptr ); // Remove this attribute - } - - SPObject *updated = doc->getObjectByRepr(ir); - if (updated) { - // force immediate update of dependent attributes - updated->updateRepr(); - } - - changed = true; - } - } - } - if ( changed ) { - DocumentUndo::done( doc, SP_VERB_DIALOG_XML_EDITOR, _("Fixup broken links") ); - } - DocumentUndo::setUndoSensitive(doc, savedUndoState); - } - - return changed; -} - - -bool ResourceManagerImpl::searchUpwards( std::string const &base, std::string const &subpath, std::string &dest ) -{ - bool exists = false; - // TODO debug g_message("............"); - - std::vector<std::string> parts = splitPath(subpath); - std::vector<std::string> baseParts = splitPath(base); - - while ( !exists && !baseParts.empty() ) { - std::vector<std::string> current; - current.insert(current.begin(), parts.begin(), parts.end()); - // TODO debug g_message(" ---{%s}", Glib::build_filename( baseParts ).c_str()); - while ( !exists && !current.empty() ) { - std::vector<std::string> combined; - combined.insert( combined.end(), baseParts.begin(), baseParts.end() ); - combined.insert( combined.end(), current.begin(), current.end() ); - std::string filepath = Glib::build_filename( combined ); - exists = Glib::file_test(filepath, Glib::FILE_TEST_EXISTS); - // TODO debug g_message(" ...[%s] %s", filepath.c_str(), (exists ? "XXX" : "")); - if ( exists ) { - dest = filepath; - } - current.erase( current.begin() ); - } - baseParts.pop_back(); - } - - return exists; -} - - -static ResourceManagerImpl* theInstance = nullptr; - -ResourceManager::ResourceManager() - : Glib::Object() -{ -} - -ResourceManager::~ResourceManager() = default; - -ResourceManager& ResourceManager::getManager() { - if ( !theInstance ) { - theInstance = new ResourceManagerImpl(); - } - - return *theInstance; -} - - -} // namespace Inkscape - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : |
