void HTMLConstructionSite::flushPendingText() { if (m_pendingText.isEmpty()) return; PendingText pendingText; // Hold onto the current pending text on the stack so that queueTask doesn't recurse infinitely. m_pendingText.swap(pendingText); ASSERT(m_pendingText.isEmpty()); // Splitting text nodes into smaller chunks contradicts HTML5 spec, but is necessary // for performance, see: https://bugs.webkit.org/show_bug.cgi?id=55898 unsigned lengthLimit = textLengthLimitForContainer(*pendingText.parent); unsigned currentPosition = 0; const StringBuilder& string = pendingText.stringBuilder; while (currentPosition < string.length()) { unsigned proposedBreakIndex = std::min(currentPosition + lengthLimit, string.length()); unsigned breakIndex = findBreakIndexBetween(string, currentPosition, proposedBreakIndex); ASSERT(breakIndex <= string.length()); String substring = string.substring(currentPosition, breakIndex - currentPosition); substring = atomizeIfAllWhitespace(substring, pendingText.whitespaceMode); HTMLConstructionSiteTask task(HTMLConstructionSiteTask::InsertText); task.parent = pendingText.parent; task.child = Text::create(task.parent->document(), substring); queueTask(task); ASSERT(breakIndex > currentPosition); ASSERT(breakIndex - currentPosition == substring.length()); ASSERT(toText(task.child.get())->length() == substring.length()); currentPosition = breakIndex; } }
void HTMLConstructionSite::attachLater(ContainerNode* parent, PassRefPtr<Node> prpChild, bool selfClosing) { HTMLConstructionSiteTask task(HTMLConstructionSiteTask::Insert); task.parent = parent; task.child = prpChild; task.selfClosing = selfClosing; // Add as a sibling of the parent if we have reached the maximum depth allowed. if (m_openElements.stackDepth() > maximumHTMLParserDOMTreeDepth && task.parent->parentNode()) task.parent = task.parent->parentNode(); ASSERT(task.parent); queueTask(task); }
void HTMLConstructionSite::flushPendingText() { if (m_pendingText.isEmpty()) return; PendingText pendingText; // Hold onto the current pending text on the stack so that queueTask doesn't recurse infinitely. m_pendingText.swap(pendingText); ASSERT(m_pendingText.isEmpty()); // Splitting text nodes into smaller chunks contradicts HTML5 spec, but is necessary // for performance, see: https://bugs.webkit.org/show_bug.cgi?id=55898 unsigned lengthLimit = textLengthLimitForContainer(*pendingText.parent); unsigned currentPosition = 0; const StringBuilder& string = pendingText.stringBuilder; while (currentPosition < string.length()) { unsigned proposedBreakIndex = std::min(currentPosition + lengthLimit, string.length()); unsigned breakIndex = findBreakIndexBetween(string, currentPosition, proposedBreakIndex); ASSERT(breakIndex <= string.length()); String substring = string.substring(currentPosition, breakIndex - currentPosition); ASSERT(breakIndex > currentPosition); ASSERT(breakIndex - currentPosition == substring.length()); currentPosition = breakIndex; if (isAllWhitespace(substring)) { // Ignore whitespace nodes not inside inside a <t>. If we're splitting // a text node this isn't really a whitespace node and we can't ignore // it either. if (!m_openElements.preserveWhiteSpace() && string.length() == substring.length()) continue; // Strings composed entirely of whitespace are likely to be repeated. // Turn them into AtomicString so we share a single string for each. substring = AtomicString(substring).string(); } HTMLConstructionSiteTask task(HTMLConstructionSiteTask::InsertText); task.parent = pendingText.parent; task.child = Text::create(task.parent->document(), substring); queueTask(task); ASSERT(toText(task.child.get())->length() == substring.length()); } }
void LibraryScanner::slotStartScan() { qDebug() << "LibraryScanner::slotStartScan"; QSet<QString> trackLocations = m_trackDao.getTrackLocations(); QHash<QString, int> directoryHashes = m_libraryHashDao.getDirectoryHashes(); QRegExp extensionFilter = QRegExp(SoundSourceProxy::supportedFileExtensionsRegex(), Qt::CaseInsensitive); QRegExp coverExtensionFilter = QRegExp(CoverArtUtils::supportedCoverArtExtensionsRegex(), Qt::CaseInsensitive); QStringList directoryBlacklist = ScannerUtil::getDirectoryBlacklist(); m_scannerGlobal = ScannerGlobalPointer( new ScannerGlobal(trackLocations, directoryHashes, extensionFilter, coverExtensionFilter, directoryBlacklist)); m_scannerGlobal->startTimer(); emit(scanStarted()); // Try to upgrade the library from 1.7 (XML) to 1.8+ (DB) if needed. If the // upgrade_filename already exists, then do not try to upgrade since we have // already done it. // TODO(XXX) SETTINGS_PATH may change in new Mixxx Versions. Here we need // the SETTINGS_PATH from Mixxx V <= 1.7 QString upgrade_filename = QDir::homePath().append("/").append(SETTINGS_PATH).append("DBUPGRADED"); qDebug() << "upgrade filename is " << upgrade_filename; QFile upgradefile(upgrade_filename); if (!upgradefile.exists()) { QTime t2; t2.start(); LegacyLibraryImporter libImport(m_trackDao, m_playlistDao); connect(&libImport, SIGNAL(progress(QString)), this, SIGNAL(progressLoading(QString))); ScopedTransaction transaction(m_database); libImport.import(); transaction.commit(); qDebug("Legacy importer took %d ms", t2.elapsed()); } // First, we're going to mark all the directories that we've previously // hashed as needing verification. As we search through the directory tree // when we rescan, we'll mark any directory that does still exist as // verified. m_libraryHashDao.invalidateAllDirectories(); // Mark all the tracks in the library as needing verification of their // existence. (ie. we want to check they're still on your hard drive where // we think they are) m_trackDao.invalidateTrackLocationsInLibrary(); qDebug() << "Recursively scanning library."; // Start scanning the library. This prepares insertion queries in TrackDAO // (must be called before calling addTracksAdd) and begins a transaction. m_trackDao.addTracksPrepare(); // Recursivly scan each directory in the directories table. QStringList dirs = m_directoryDao.getDirs(); // If there are no directories then we have nothing to do. Cleanup and // finish the scan immediately. if (dirs.isEmpty()) { slotFinishScan(); return; } // Queue up recursive scan tasks for every directory. When all tasks are // done, TaskWatcher will signal slotFinishScan. TaskWatcher* pWatcher = &m_scannerGlobal->getTaskWatcher(); connect(pWatcher, SIGNAL(allTasksDone()), this, SLOT(slotFinishScan())); foreach (const QString& dirPath, dirs) { // Acquire a security bookmark for this directory if we are in a // sandbox. For speed we avoid opening security bookmarks when recursive // scanning so that relies on having an open bookmark for the containing // directory. MDir dir(dirPath); queueTask(new RecursiveScanDirectoryTask(this, m_scannerGlobal, dir.dir(), dir.token())); }
void LibraryScanner::slotStartScan() { qDebug() << "LibraryScanner::slotStartScan"; DEBUG_ASSERT(m_state == STARTING); // Recursively scan each directory in the directories table. m_libraryRootDirs = m_directoryDao.getDirs(); // If there are no directories then we have nothing to do. Cleanup and // finish the scan immediately. if (m_libraryRootDirs.isEmpty()) { changeScannerState(IDLE); return; } changeScannerState(SCANNING); QSet<QString> trackLocations = m_trackDao.getTrackLocations(); QHash<QString, int> directoryHashes = m_libraryHashDao.getDirectoryHashes(); QRegExp extensionFilter(SoundSourceProxy::getSupportedFileNamesRegex()); QRegExp coverExtensionFilter = QRegExp(CoverArtUtils::supportedCoverArtExtensionsRegex(), Qt::CaseInsensitive); QStringList directoryBlacklist = ScannerUtil::getDirectoryBlacklist(); m_scannerGlobal = ScannerGlobalPointer( new ScannerGlobal(trackLocations, directoryHashes, extensionFilter, coverExtensionFilter, directoryBlacklist)); m_scannerGlobal->startTimer(); emit(scanStarted()); // First, we're going to mark all the directories that we've previously // hashed as needing verification. As we search through the directory tree // when we rescan, we'll mark any directory that does still exist as // verified. m_libraryHashDao.invalidateAllDirectories(); // Mark all the tracks in the library as needing verification of their // existence. (ie. we want to check they're still on your hard drive where // we think they are) m_trackDao.invalidateTrackLocationsInLibrary(); qDebug() << "Recursively scanning library."; // Start scanning the library. This prepares insertion queries in TrackDAO // (must be called before calling addTracksAdd) and begins a transaction. m_trackDao.addTracksPrepare(); // First Scan all known directories we have a hash for. // In a second stage, we scan all new directories. This guarantees, // that we discover always the same folder, in case of duplicated folders // by symlinks // Queue up recursive scan tasks for every hashed directory. When all tasks // are done, TaskWatcher will signal slotFinishHashedScan. TaskWatcher* pWatcher = &m_scannerGlobal->getTaskWatcher(); pWatcher->watchTask(); connect(pWatcher, SIGNAL(allTasksDone()), this, SLOT(slotFinishHashedScan())); foreach (const QString& dirPath, m_libraryRootDirs) { // Acquire a security bookmark for this directory if we are in a // sandbox. For speed we avoid opening security bookmarks when recursive // scanning so that relies on having an open bookmark for the containing // directory. MDir dir(dirPath); if (!m_scannerGlobal->testAndMarkDirectoryScanned(dir.dir())) { queueTask(new RecursiveScanDirectoryTask(this, m_scannerGlobal, dir.dir(), dir.token(), false)); } }