// determines the icon data; this could be either a path on disk (if we have // a suitable icon locally), base64-encoded icon data (if the icon is embedded // in an R package), or nothing (if we cannot determine an icon at all) std::string iconData(const std::string& iconGroup, const std::string& iconName, const std::string& iconPath) { if (iconPath.empty()) { // convert the icon name into the format of our shipped icons, which is // all lowercase with no whitespace (e.g. "SQL Server" => "sqlserver.png") std::string iconFilename(string_utils::toLower(iconName)); iconFilename = boost::regex_replace(iconFilename, boost::regex("\\s"), "") + ".png"; // the package did not supply an icon; see if there's one baked in FilePath path = options().rResourcesPath().childPath("connections") .childPath(iconGroup) .childPath(iconFilename); if (path.exists()) return std::string("connections/") + iconGroup + "/" + iconFilename; if (iconGroup == "drivers") return std::string("connections/drivers/odbc.png"); // didn't find anything return std::string(); } // expand the path FilePath icon = module_context::resolveAliasedPath(iconPath); std::string iconData; // ensure that the icon file exists and is a small GIF, JPG, or PNG image if (icon.exists() && icon.size() < kMaxIconSize && (icon.hasExtensionLowerCase(".gif") || icon.hasExtensionLowerCase(".png") || icon.hasExtensionLowerCase(".jpg") || icon.hasExtensionLowerCase(".jpeg"))) { Error error = base64::encode(icon, &iconData); if (error) LOG_ERROR(error); else { iconData = "data:" + icon.mimeContentType("image/png") + ";base64," + iconData; } } return iconData; }
Error HunspellCustomDictionaries::add(const FilePath& dicPath) const { // validate .dic extension if (!dicPath.hasExtensionLowerCase(".dic")) { return systemError(boost::system::errc::invalid_argument, ERROR_LOCATION); } // remove existing with same name std::string name = dicPath.stem(); Error error = remove(name); if (error) LOG_ERROR(error); // add it return dicPath.copy(dictionaryPath(name)); }
void onDocSaved(FilePath &path) { Error error; // ignore non-R Markdown saves if (!path.hasExtensionLowerCase(".rmd")) return; // find cache folder (bail out if it doesn't exist) FilePath cache = chunkCacheFolder(path, "", notebookCtxId()); if (!cache.exists()) return; FilePath saved = chunkCacheFolder(path, "", kSavedCtx); if (saved.exists()) { // tidy up: remove any saved chunks that no longer exist error = removeStaleSavedChunks(path, saved); if (error) LOG_ERROR(error); } else { // no saved context yet; ensure we have a place to put it saved.ensureDirectory(); } // move all the chunk definitions over to the saved context std::vector<FilePath> children; error = cache.children(&children); if (error) { LOG_ERROR(error); return; } BOOST_FOREACH(const FilePath source, children) { // compute the target path FilePath target = saved.complete(source.filename()); if (source.filename() == kNotebookChunkDefFilename) { // the definitions should be copied (we always want them in both // contexts) error = target.removeIfExists(); if (!error) error = source.copy(target); } else if (source.isDirectory()) { // library folders should be merged and then removed, so we don't // lose library contents if (source.filename() == kChunkLibDir) { error = mergeLib(source, target); if (!error) error = source.remove(); } else { // the chunk output folders should be moved; destroy the old copy error = target.removeIfExists(); if (!error) error = source.move(target); } } else { // nothing besides the chunks.json and chunk folders should be here, // so ignore other files/content continue; } if (error) LOG_ERROR(error); }