?? qsettings.cpp
字號:
if (thePrefix.isEmpty()) { ensureAllSectionsParsed(confFile); } else { ensureSectionParsed(confFile, thePrefix); } j = const_cast<const ParsedSettingsMap *>( &confFile->originalKeys)->lowerBound( thePrefix); while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) { if (!confFile->removedKeys.contains(j.key())) processChild(j.key().originalCaseKey().mid(startPos), spec, result); ++j; } j = const_cast<const ParsedSettingsMap *>( &confFile->addedKeys)->lowerBound(thePrefix); while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) { processChild(j.key().originalCaseKey().mid(startPos), spec, result); ++j; } if (!fallbacks) break; } } return result.keys();}void QConfFileSettingsPrivate::clear(){ QConfFile *confFile = confFiles[spec]; if (!confFile) return; QMutexLocker locker(&confFile->mutex); ensureAllSectionsParsed(confFile); confFile->addedKeys.clear(); confFile->removedKeys = confFile->originalKeys;}void QConfFileSettingsPrivate::sync(){ // people probably won't be checking the status a whole lot, so in case of // error we just try to go on and make the best of it for (int i = 0; i < NumConfFiles; ++i) { QConfFile *confFile = confFiles[i]; if (confFile) { QMutexLocker locker(&confFile->mutex); syncConfFile(i); } }}void QConfFileSettingsPrivate::flush(){ sync();}QString QConfFileSettingsPrivate::fileName() const{ QConfFile *confFile = confFiles[spec]; if (!confFile) return QString(); return confFile->name;}bool QConfFileSettingsPrivate::isWritable() const{ if (format > QSettings::IniFormat && !writeFunc) return false; QConfFile *confFile = confFiles[spec]; if (!confFile) return false; if (QFile::exists(confFile->name)) { QFile file(confFile->name);; return file.open(QFile::ReadWrite); } else { // we use a temporary file to avoid race conditions QTemporaryFile file(confFile->name); return file.open(); }}void QConfFileSettingsPrivate::syncConfFile(int confFileNo){ QConfFile *confFile = confFiles[confFileNo]; bool readOnly = confFile->addedKeys.isEmpty() && confFile->removedKeys.isEmpty(); bool ok; /* We can often optimize the read-only case, if the file on disk hasn't changed. */ if (readOnly) { QFileInfo fileInfo(confFile->name); if (confFile->size == fileInfo.size() && confFile->timeStamp == fileInfo.lastModified()) return; } /* Open the configuration file and try to use it using a named semaphore on Windows and an advisory lock on Unix-based systems. This protect us against other QSettings instances trying to access the same file from other threads or processes. As it stands now, the locking mechanism doesn't work for .plist files. */ QFile file(confFile->name); bool createFile = !file.exists(); if (!readOnly) file.open(QFile::ReadWrite); if (!file.isOpen()) file.open(QFile::ReadOnly);#ifdef Q_OS_WIN HANDLE readSemaphore = 0; HANDLE writeSemaphore = 0; static const int FileLockSemMax = 50; int numReadLocks = readOnly ? 1 : FileLockSemMax; if (file.isOpen()) { // Aquire the write lock if we will be writing if (!readOnly) { QString writeSemName = QLatin1String("QSettingsWriteSem "); writeSemName.append(file.fileName()); QT_WA( { writeSemaphore = CreateSemaphoreW(0, 1, 1, reinterpret_cast<const wchar_t *>(writeSemName.utf16())); } , { writeSemaphore = CreateSemaphoreA(0, 1, 1, writeSemName.toLocal8Bit()); } ); if (writeSemaphore) { WaitForSingleObject(writeSemaphore, INFINITE); } else { setStatus(QSettings::AccessError); return; } } // Aquire all the read locks if we will be writing, to make sure nobody // reads while we're writing. If we are only reading, aquire a single // read lock. QString readSemName = QLatin1String("QSettingsReadSem "); readSemName.append(file.fileName()); QT_WA( { readSemaphore = CreateSemaphoreW(0, FileLockSemMax, FileLockSemMax, reinterpret_cast<const wchar_t *>(readSemName.utf16())); } , { readSemaphore = CreateSemaphoreA(0, FileLockSemMax, FileLockSemMax, readSemName.toLocal8Bit()); } ); if (readSemaphore) { for (int i = 0; i < numReadLocks; ++i) WaitForSingleObject(readSemaphore, INFINITE); } else { setStatus(QSettings::AccessError); if (writeSemaphore != 0) { ReleaseSemaphore(writeSemaphore, 1, 0); CloseHandle(writeSemaphore); } return; } }#else if (file.isOpen()) unixLock(file.handle(), readOnly ? F_RDLCK : F_WRLCK);#endif // If we have created the file, apply the file perms if (file.isOpen()) { if (createFile) { QFile::Permissions perms = QFile::ReadOwner | QFile::WriteOwner; if (!confFile->userPerms) perms |= QFile::ReadGroup|QFile::ReadOther; file.setPermissions(perms); } } /* We hold the lock. Let's reread the file if it has changed since last time we read it. */ QFileInfo fileInfo(confFile->name); bool mustReadFile = true; if (!readOnly) { mustReadFile = (confFile->size != fileInfo.size() || (confFile->size != 0 && confFile->timeStamp != fileInfo.lastModified())); } if (mustReadFile) { confFile->unparsedIniSections.clear(); confFile->originalKeys.clear(); /* Files that we can't read (because of permissions or because they don't exist) are treated as empty files. */ if (file.isReadable() && fileInfo.size() != 0) {#ifdef Q_OS_MAC if (format == QSettings::NativeFormat) { ok = readPlistFile(confFile->name, &confFile->originalKeys); } else#endif { if (format <= QSettings::IniFormat) { QByteArray data = file.readAll(); ok = readIniFile(data, &confFile->unparsedIniSections); } else { if (readFunc) { QSettings::SettingsMap tempNewKeys; ok = readFunc(file, tempNewKeys); if (ok) { QSettings::SettingsMap::const_iterator i = tempNewKeys.constBegin(); while (i != tempNewKeys.constEnd()) { confFile->originalKeys.insert(QSettingsKey(i.key(), caseSensitivity), i.value()); ++i; } } } else { ok = false; } } } if (!ok) setStatus(QSettings::FormatError); } confFile->size = fileInfo.size(); confFile->timeStamp = fileInfo.lastModified(); } /* We also need to save the file. We still hold the file lock, so everything is under control. */ if (!readOnly) { ensureAllSectionsParsed(confFile); ParsedSettingsMap mergedKeys = confFile->mergedKeyMap(); if (file.isWritable()) {#ifdef Q_OS_MAC if (format == QSettings::NativeFormat) { ok = writePlistFile(confFile->name, mergedKeys); } else#endif { file.seek(0); // shouldn't be necessary file.resize(0); if (format <= QSettings::IniFormat) { ok = writeIniFile(file, mergedKeys); } else { if (writeFunc) { QSettings::SettingsMap tempOriginalKeys; ParsedSettingsMap::const_iterator i = mergedKeys.constBegin(); while (i != mergedKeys.constEnd()) { tempOriginalKeys.insert(i.key(), i.value()); ++i; } ok = writeFunc(file, tempOriginalKeys); } else { ok = false; } } } } else { ok = false; } if (ok) { confFile->unparsedIniSections.clear(); confFile->originalKeys = mergedKeys; confFile->addedKeys.clear(); confFile->removedKeys.clear(); QFileInfo fileInfo(confFile->name); confFile->size = fileInfo.size(); confFile->timeStamp = fileInfo.lastModified(); } else { setStatus(QSettings::AccessError); } } /* Release the file lock. */#ifdef Q_OS_WIN if (readSemaphore != 0) { ReleaseSemaphore(readSemaphore, numReadLocks, 0); CloseHandle(readSemaphore); } if (writeSemaphore != 0) { ReleaseSemaphore(writeSemaphore, 1, 0); CloseHandle(writeSemaphore); }#endif}enum { Space = 0x1, Special = 0x2 };static const char charTraits[256] ={ // Space: '\t', '\n', '\r', ' ' // Special: '\n', '\r', '"', ';', '=', '\\' 0, 0, 0, 0, 0, 0, 0, 0, 0, Space, Space | Special, 0, 0, Space | Special, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Space, 0, Special, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Special, 0, Special, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Special, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};bool QConfFileSettingsPrivate::readIniLine(const QByteArray &data, int &dataPos, int &lineStart, int &lineLen, int &equalsPos){ int dataLen = data.length(); bool inQuotes = false; equalsPos = -1; lineStart = dataPos; while (lineStart < dataLen && (charTraits[uint(uchar(data.at(lineStart)))] & Space)) ++lineStart; int i = lineStart; while (i < dataLen) { while (!(charTraits[uint(uchar(data.at(i)))] & Special)) { if (++i == dataLen) goto break_out_of_outer_loop; } char ch = data.at(i++); if (ch == '=') { if (!inQuotes && equalsPos == -1) equalsPos = i - 1; } else if (ch == '\n' || ch == '\r') { if (i == lineStart + 1) { ++lineStart; } else if (!inQuotes) { --i; goto break_out_of_outer_loop; } } else if (ch == '\\') { if (i < dataLen) { char ch = data.at(i++); if (i < dataLen) { char ch2 = data.at(i); // \n, \r, \r\n, and \n\r are legitimate line terminators in INI files if ((ch == '\n' && ch2 == '\r') || (ch == '\r' && ch2 == '\n')) ++i; } } } else if (ch == '"') { inQuotes = !inQuotes; } else { Q_ASSERT(ch == ';'); if (i == lineStart + 1) { char ch; while (i < dataLen && ((ch = data.at(i) != '\n') && ch != '\r')) ++i; lineStart = i; } else if (!inQuotes) { --i; goto break_out_of_outer_loop; } } }break_out_of_outer_loop: dataPos = i; lineLen = i - lineStart; return lineLen > 0;}/* Returns false on parse error. However, as many keys are read as possible, so if the user doesn't check the status he will get the most out of the file anyway.*/bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data, UnparsedSettingsMap *unparsedIniSections){#define FLUSH_CURRENT_SECTION() \ { \ QByteArray §ionData = (*unparsedIniSections)[QSettingsKey(currentSection, \ IniCaseSensitivity)]; \ if (!sectionData.isEmpty()) \ sectionData.append('\n'); \ sectionData += data.mid(currentSectionStart, lineStart - currentSectionStart); \ }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -