void SettingsTest::testMerge_data(){ // Key names state which file(s) a key is set in (master, foo or bar). Value // is always in form "<file>-value" based on which file it is taken from. const QScopedPointer<QTemporaryFile> masterFile( QTemporaryFile::createLocalFile(":/testdata/merge/settings.ini")); QSettings master(masterFile->fileName(), QSettings::IniFormat); const QStringList settingsFiles = QStringList() << ":/testdata/merge/settings.d/bar.ini" << ":/testdata/merge/settings.d/foo.ini"; SsuSettings::merge(&master, settingsFiles); QSettings expected(":/testdata/merge/merged.ini", QSettings::IniFormat); const QSet<QString> masterKeys = master.allKeys().toSet(); const QSet<QString> expectedKeys = expected.allKeys().toSet(); QTest::addColumn<bool>("keyIsMerged"); QTest::addColumn<bool>("keyShouldBeMerged"); QTest::addColumn<QString>("actualValue"); QTest::addColumn<QString>("expectedValue"); foreach (const QString &key, masterKeys + expectedKeys){ QTest::newRow(qPrintable(key)) << masterKeys.contains(key) << expectedKeys.contains(key) << master.value(key).toString() << expected.value(key).toString(); } }
void StateListener::slotStateChanged() { // Get the current file. Are we on a temporary submit editor indicated by // temporary path prefix or does the file contains a hash, indicating a project // folder? State state; IDocument *currentDocument = EditorManager::currentDocument(); if (!currentDocument) { state.currentFile.clear(); } else { state.currentFile = currentDocument->filePath().toString(); if (state.currentFile.isEmpty() || currentDocument->isTemporary()) state.currentFile = VcsBasePlugin::source(currentDocument); } QScopedPointer<QFileInfo> currentFileInfo; // Instantiate QFileInfo only once if required. if (!state.currentFile.isEmpty()) { const bool isTempFile = state.currentFile.startsWith(QDir::tempPath()); // Quick check: Does it look like a patch? const bool isPatch = state.currentFile.endsWith(QLatin1String(".patch")) || state.currentFile.endsWith(QLatin1String(".diff")); if (isPatch) { // Patch: Figure out a name to display. If it is a temp file, it could be // Codepaster. Use the display name of the editor. state.currentPatchFile = state.currentFile; if (isTempFile) state.currentPatchFileDisplayName = displayNameOfEditor(state.currentPatchFile); if (state.currentPatchFileDisplayName.isEmpty()) { currentFileInfo.reset(new QFileInfo(state.currentFile)); state.currentPatchFileDisplayName = currentFileInfo->fileName(); } } // For actual version control operations on it: // Do not show temporary files and project folders ('#') if (isTempFile || state.currentFile.contains(QLatin1Char('#'))) state.currentFile.clear(); } // Get the file and its control. Do not use the file unless we find one IVersionControl *fileControl = 0; if (!state.currentFile.isEmpty()) { if (currentFileInfo.isNull()) currentFileInfo.reset(new QFileInfo(state.currentFile)); if (currentFileInfo->isDir()) { state.currentFile.clear(); state.currentFileDirectory = currentFileInfo->absoluteFilePath(); } else { state.currentFileDirectory = currentFileInfo->absolutePath(); state.currentFileName = currentFileInfo->fileName(); } fileControl = VcsManager::findVersionControlForDirectory( state.currentFileDirectory, &state.currentFileTopLevel); if (!fileControl) state.clearFile(); } // Check for project, find the control IVersionControl *projectControl = 0; Project *currentProject = ProjectTree::currentProject(); if (!currentProject) currentProject = SessionManager::startupProject(); if (currentProject) { state.currentProjectPath = currentProject->projectDirectory().toString(); state.currentProjectName = currentProject->displayName(); projectControl = VcsManager::findVersionControlForDirectory(state.currentProjectPath, &state.currentProjectTopLevel); if (projectControl) { // If we have both, let the file's one take preference if (fileControl && projectControl != fileControl) state.clearProject(); } else { state.clearProject(); // No control found } } // Assemble state and emit signal. IVersionControl *vc = fileControl; if (!vc) vc = projectControl; if (!vc) state.clearPatchFile(); // Need a repository to patch if (debug) qDebug() << state << (vc ? vc->displayName() : QLatin1String("No version control")); EditorManager::updateWindowTitles(); emit stateChanged(state, vc); }
bool KexiCSVExport::exportData(KDbTableOrQuerySchema *tableOrQuery, const Options& options, int recordCount, QTextStream *predefinedTextStream) { KDbConnection* conn = tableOrQuery->connection(); if (!conn) return false; KDbQuerySchema* query = tableOrQuery->query(); QList<QVariant> queryParams; if (!query) { query = tableOrQuery->table()->query(); } else { queryParams = KexiMainWindowIface::global()->currentParametersForQuery(query->id()); } if (recordCount == -1) recordCount = KDb::recordCount(tableOrQuery, queryParams); if (recordCount == -1) return false; //! @todo move this to non-GUI location so it can be also used via command line //! @todo add a "finish" page with a progressbar. //! @todo look at recordCount whether the data is really large; //! if so: avoid copying to clipboard (or ask user) because of system memory //! @todo OPTIMIZATION: use fieldsExpanded(true /*UNIQUE*/) //! @todo OPTIMIZATION? (avoid multiple data retrieving) look for already fetched data within KexiProject.. KDbQueryColumnInfo::Vector fields(query->fieldsExpanded(KDbQuerySchema::WithInternalFields)); QString buffer; QScopedPointer<QSaveFile> kSaveFile; QTextStream *stream = 0; QScopedPointer<QTextStream> kSaveFileTextStream; const bool copyToClipboard = options.mode == Clipboard; if (copyToClipboard) { //! @todo (during exporting): enlarge bufSize by factor of 2 when it became too small int bufSize = qMin((recordCount < 0 ? 10 : recordCount) * fields.count() * 20, 128000); buffer.reserve(bufSize); if (buffer.capacity() < bufSize) { qWarning() << "Cannot allocate memory for " << bufSize << " characters"; return false; } } else { if (predefinedTextStream) { stream = predefinedTextStream; } else { if (options.fileName.isEmpty()) {//sanity qWarning() << "Fname is empty"; return false; } kSaveFile.reset(new QSaveFile(options.fileName)); qDebug() << "QSaveFile Filename:" << kSaveFile->fileName(); if (kSaveFile->open(QIODevice::WriteOnly)) { kSaveFileTextStream.reset(new QTextStream(kSaveFile.data())); stream = kSaveFileTextStream.data(); qDebug() << "have a stream"; } if (QFileDevice::NoError != kSaveFile->error() || !stream) {//sanity qWarning() << "Status != 0 or stream == 0"; //! @todo show error return false; } } } //! @todo escape strings #define _ERR \ if (kSaveFile) { kSaveFile->cancelWriting(); } \ return false #define APPEND(what) \ if (copyToClipboard) buffer.append(what); else (*stream) << (what) // use native line ending for copying, RFC 4180 one for saving to file #define APPEND_EOLN \ if (copyToClipboard) { APPEND('\n'); } else { APPEND("\r\n"); } qDebug() << 0 << "Columns: " << query->fieldsExpanded().count(); // 0. Cache information const int fieldsCount = query->fieldsExpanded().count(); //real fields count without internals const QByteArray delimiter(options.delimiter.left(1).toLatin1()); const bool hasTextQuote = !options.textQuote.isEmpty(); const QString textQuote(options.textQuote.left(1)); const QByteArray escapedTextQuote((textQuote + textQuote).toLatin1()); //ok? //cache for faster checks QScopedArrayPointer<bool> isText(new bool[fieldsCount]); QScopedArrayPointer<bool> isDateTime(new bool[fieldsCount]); QScopedArrayPointer<bool> isTime(new bool[fieldsCount]); QScopedArrayPointer<bool> isBLOB(new bool[fieldsCount]); QScopedArrayPointer<int> visibleFieldIndex(new int[fieldsCount]); // bool isInteger[fieldsCount]; //cache for faster checks // bool isFloatingPoint[fieldsCount]; //cache for faster checks for (int i = 0; i < fieldsCount; i++) { KDbQueryColumnInfo* ci; const int indexForVisibleLookupValue = fields[i]->indexForVisibleLookupValue(); if (-1 != indexForVisibleLookupValue) { ci = query->expandedOrInternalField(indexForVisibleLookupValue); visibleFieldIndex[i] = indexForVisibleLookupValue; } else { ci = fields[i]; visibleFieldIndex[i] = i; } const KDbField::Type t = ci->field->type(); // cache: evaluating type of expressions can be expensive isText[i] = KDbField::isTextType(t); isDateTime[i] = t == KDbField::DateTime; isTime[i] = t == KDbField::Time; isBLOB[i] = t == KDbField::BLOB; // isInteger[i] = KDbField::isIntegerType(t) // || t == KDbField::Boolean; // isFloatingPoint[i] = KDbField::isFPNumericType(t); } // 1. Output column names if (options.addColumnNames) { for (int i = 0; i < fieldsCount; i++) { //qDebug() << "Adding column names"; if (i > 0) { APPEND(delimiter); } if (hasTextQuote) { APPEND(textQuote + fields[i]->captionOrAliasOrName().replace(textQuote, escapedTextQuote) + textQuote); } else { APPEND(fields[i]->captionOrAliasOrName()); } } APPEND_EOLN } KexiGUIMessageHandler handler; KDbCursor *cursor = conn->executeQuery(query, queryParams); if (!cursor) { handler.showErrorMessage(conn->result()); _ERR; } for (cursor->moveFirst(); !cursor->eof() && !cursor->result().isError(); cursor->moveNext()) { //qDebug() << "Adding records"; const int realFieldCount = qMin(cursor->fieldCount(), fieldsCount); for (int i = 0; i < realFieldCount; i++) { const int real_i = visibleFieldIndex[i]; if (i > 0) { APPEND(delimiter); } if (cursor->value(real_i).isNull()) { continue; } if (isText[real_i]) { if (hasTextQuote) APPEND(textQuote + QString(cursor->value(real_i).toString()).replace(textQuote, escapedTextQuote) + textQuote); else APPEND(cursor->value(real_i).toString()); } else if (isDateTime[real_i]) { //avoid "T" in ISO DateTime APPEND(cursor->value(real_i).toDateTime().date().toString(Qt::ISODate) + " " + cursor->value(real_i).toDateTime().time().toString(Qt::ISODate)); } else if (isTime[real_i]) { //time is temporarily stored as null date + time... APPEND(cursor->value(real_i).toTime().toString(Qt::ISODate)); } else if (isBLOB[real_i]) { //BLOB is escaped in a special way if (hasTextQuote) //! @todo add options to suppport other types from KDbBLOBEscapingType enum... APPEND(textQuote + KDb::escapeBLOB(cursor->value(real_i).toByteArray(), KDb::BLOBEscapeHex) + textQuote); else APPEND(KDb::escapeBLOB(cursor->value(real_i).toByteArray(), KDb::BLOBEscapeHex)); } else {//other types APPEND(cursor->value(real_i).toString()); } } APPEND_EOLN } if (copyToClipboard) buffer.squeeze(); if (!conn->deleteCursor(cursor)) { handler.showErrorMessage(conn->result()); _ERR; } if (copyToClipboard) QApplication::clipboard()->setText(buffer, QClipboard::Clipboard); qDebug() << "Done"; if (kSaveFile) { stream->flush(); if (!kSaveFile->commit()) { qWarning() << "Error commiting the file" << kSaveFile->fileName(); } } return true; }