static int preBmGs(unsigned char *x, int m, int bmGs[]) { int *suff, i, j; suff = (int *) calloc(sizeof(int), m); if (suff == NULL) return -1; suffixes(x, m, suff); for (i = 0; i < m; ++i) bmGs[i] = m; j = 0; for (i = m - 1; i >= -1; --i) if (i == -1 || suff[i] == i + 1) for (; j < m - 1 - i; ++j) if (bmGs[j] == m) bmGs[j] = m - 1 - i; for (i = 0; i <= m - 2; ++i) bmGs[m - 1 - suff[i]] = m - 1 - i; free(suff); return 0; }
static int preBmGs(const unsigned char *wanted, int wlen, int bmGs[]) { int i, j, suffix[BM_XSIZE]; if (NULL == wanted || 0 >= wlen || NULL == bmGs) return -1; suffixes(wanted, wlen, suffix); for (i = 0; i < wlen; i++) { bmGs[i] = wlen; } for (j = 0, i = wlen - 1; i >= 0; i--) { if (suffix[i] == i + 1) { for (; j < wlen - 1 - i; j++) { if (bmGs[j] == wlen) { bmGs[j] = wlen - 1 - i; } } } } for (i = 0; i <= wlen - 2; i++) { bmGs[wlen - 1 - suffix[i]] = wlen - 1 - i; } return 0; }
static void preBmGs( unsigned char *x, int m, int bmGs[]) { int i, j; int *suff = safe_malloc(m * sizeof(int)); suffixes(x, m, suff); for (i = 0; i < m; ++i) { bmGs[i] = m; } j = 0; for (i = m - 1; i >= 0; --i) { if (suff[i] == i + 1) { for (; j < m - 1 - i; ++j) { if (bmGs[j] == m) { bmGs[j] = m - 1 - i; } } } } for (i = 0; i <= m - 2; ++i) { bmGs[m - 1 - suff[i]] = m - 1 - i; } free(suff); }
void suffix_s( string &word ) { cout << "suffix_s -- word passed in: " << word << endl; string::size_type spos = 0; string::size_type pos3 = word.size()-3; // "ous", "ss", "is" string suffixes( "oussis" ); if ( ! word.compare( pos3, 3, suffixes, spos, 3 ) || ! word.compare( pos3+1, 2, suffixes, spos+2, 2 ) || ! word.compare( pos3+1, 2, suffixes, spos+4, 2 )) { cout << "suffix_s: found immutable suffix: " << word << endl; return; } string ies( "ies" ); if ( ! word.compare( pos3, 3, ies )) { word.replace( pos3, 3, 1, 'y' ); cout << "suffix_s -- word returned: " << word << endl; return; } // erase ending 's' word.erase( pos3+2 ); cout << "suffix_s -- word returned: " << word << endl; }
const QString RarArchEngine::openFilter() { QStringList filters; QStringList suffs = suffixes(); for (int i=0;i<suffs.count();i++) { filters << "*." + suffs[i]; } return tr("Rar files") + " (" + filters.join(" ") + ")"; }
const QString XzipArchEngine::createFilter() { QStringList filters; filters << "*.tar.xz"; QStringList suffs = suffixes(); for (int i=0;i<suffs.count();i++) { filters << "*." + suffs[i]; } return tr("Xzip files") + " (" + filters.join(" ") + ")"; }
std::vector<std::list<Parameterization> > ParameterizedCommand::ExpandParameters( unsigned int startIndex, const std::vector<IParameter::Pointer>& parameters) { typedef std::vector<std::list<Parameterization> > ReturnType; const unsigned int nextIndex = startIndex + 1; const bool noMoreParameters = (nextIndex >= parameters.size()); const IParameter::Pointer parameter(parameters[startIndex]); ReturnType parameterizations; if (parameter->IsOptional()) { parameterizations.push_back(std::list<Parameterization>()); } IParameter::ParameterValues parameterValues(parameter->GetValues()); for (IParameter::ParameterValues::iterator parameterValueItr = parameterValues.begin(); parameterValueItr != parameterValues.end(); ++parameterValueItr) { std::list<Parameterization> combination; combination.push_back( Parameterization(parameter, parameterValueItr->second)); parameterizations.push_back(combination); } // Check if another iteration will produce any more names. if (noMoreParameters) { // This is it, so just return the current parameterizations. return parameterizations; } // Make recursive call ReturnType suffixes(ExpandParameters(nextIndex, parameters)); if (suffixes.empty()) { // This is it, so just return the current parameterizations. return parameterizations; } ReturnType returnValue; for (ReturnType::iterator suffixItr = suffixes.begin(); suffixItr != suffixes.end(); ++suffixItr) { for (ReturnType::iterator combinationItr = parameterizations.begin(); combinationItr != parameterizations.end(); ++combinationItr) { std::list<Parameterization> newCombination(*combinationItr); newCombination.insert(newCombination.end(), suffixItr->begin(), suffixItr->end()); returnValue.push_back(newCombination); } } return returnValue; }
void preBmGs(const char* x, int m, int* bmGs, int XSIZE) { int i = 0, j = 0, *suffix = NULL; if (!(suffix = (int*) malloc(sizeof(int)*XSIZE))) { fprintf(stderr, "malloc err!\n"); return; } suffixes(x, m, suffix, XSIZE); for (i = 0; i < XSIZE; i ++) { bmGs[i] = m; } // init consider no suffix for (i = m-2; i >= 0; i --) { // a head prefix as suffix if (suffix[i] == i+1) { for (j = m-1-i; j >= 0; j --) { bmGs[j] = (m-1) - i; } } } for (i = 0; i <= m-2; i ++) { // find a good suffix bmGs[(m-1) - suffix[i]] = (m-1) - i; } free(suffix); }
void suffix_s(string word)//处理部分三单问题 { string::size_type spos = 0; string::size_type pos3 = word.size() - 3; // 以"ous", "ss", "is", "ius"结尾的要去掉 string suffixes("oussisius"); if (!word.compare(pos3, 3, suffixes, spos, 3) || // ous !word.compare(pos3, 3, suffixes, spos + 6, 3) || // ius !word.compare(pos3 + 1, 2, suffixes, spos + 2, 2) || // ss !word.compare(pos3 + 1, 2, suffixes, spos + 4, 2)) // es return; else if (word.compare(pos3, 3, suffixes, spos, 3) || // ous word.compare(pos3, 3, suffixes, spos + 6, 3))// ius word.erase(pos3, 3); else word.erase(pos3 + 1, 2); }
void preGS(char *pattern, int patternSize, int bmGs[]) { int i, j, suffix[GSIZE]; _pattern = pattern; _patternSize = patternSize; suffixes(pattern, patternSize, suffix); for (i = 0; i < patternSize; ++i) bmGs[i] = patternSize; j = 0; for (i = patternSize - 1; i >= 0; --i) if (suffix[i] == i + 1) for (; j < patternSize - 1 - i; ++j) if (bmGs[j] == patternSize) bmGs[j] = patternSize - 1 - i; for (i = 0; i <= patternSize - 2; ++i) bmGs[patternSize - 1 - suffix[i]] = patternSize - 1 - i; }
QString BAbstractFileType::createFileDialogFilter() const { QString desc = description(); QStringList sl = suffixes(); if (desc.isEmpty() || sl.isEmpty()) return ""; QString filter; filter += desc + " ("; if (sl.contains("*")) sl.clear(); sl.removeDuplicates(); if (!sl.isEmpty()) { for (int i = 0; i < sl.size(); ++i) filter += "*." + sl.at(i) + (i < sl.size() - 1 ? " " : ""); } else filter += "*"; filter += ")"; return filter; }
void suffix_s( string &word ) { string::size_type spos = 0; string::size_type pos3 = word.size()-3; // "ous", "ss", "is" string suffixes( "oussis" ); if ( ! word.compare( pos3, 3, suffixes, spos, 3 ) || ! word.compare( pos3+1, 2, suffixes, spos+2, 2 ) || ! word.compare( pos3+1, 2, suffixes, spos+4, 2 )) return; string ies( "ies" ); if ( ! word.compare( pos3, 3, ies )) { word.replace( pos3, 3, 1, 'y' ); return; } // erase ending 's' word.erase( pos3+2 ); }
static void preBmGs( const char * needle, HB_ISIZ m, HB_ISIZ bmGs[] ) { HB_ISIZ i, j; HB_ISIZ * suff = ( HB_ISIZ * ) hb_xgrab( m * sizeof( HB_ISIZ ) ); suffixes( needle, m, suff ); for( i = 0; i < m; ++i ) bmGs[ i ] = m; j = 0; for( i = m - 1; i >= 0; --i ) if( suff[ i ] == i + 1 ) for( ; j < m - 1 - i; ++j ) if( bmGs[ j ] == m ) bmGs[ j ] = m - 1 - i; for( i = 0; i <= m - 2; ++i ) bmGs[ m - 1 - suff[ i ] ] = m - 1 - i; hb_xfree( suff ); }
bool PreTeXFileType::matchesFileName(const QString &fileName) const { return suffixes().contains(QFileInfo(fileName).suffix(), Qt::CaseInsensitive); }
std::list< util::istring > FileFormat::getSuffixes()const { std::list<util::istring> ret = util::stringToList<util::istring>( suffixes(), boost::regex( "[[:space:]]" ) ); BOOST_FOREACH( util::istring & ref, ret ) { ref.erase( 0, ref.find_first_not_of( '.' ) ); // remove leading . if there are some }
QList<QList<Parameterization> > ParameterizedCommand::ExpandParameters( unsigned int startIndex, const QList<IParameter::Pointer>& parameters) { typedef QList<QList<Parameterization> > ReturnType; const int nextIndex = startIndex + 1; const bool noMoreParameters = (nextIndex >= parameters.size()); const IParameter::Pointer parameter(parameters[startIndex]); ReturnType parameterizations; if (parameter->IsOptional()) { parameterizations.push_back(QList<Parameterization>()); } IParameterValues* values = NULL; try { values = parameter->GetValues(); } catch (const ParameterValuesException& /*e*/) { if (noMoreParameters) { return parameterizations; } // Make recursive call return ExpandParameters(nextIndex, parameters); } const QHash<QString,QString> parameterValues = values->GetParameterValues(); for (IParameter::ParameterValues::const_iterator parameterValueItr = parameterValues.begin(); parameterValueItr != parameterValues.end(); ++parameterValueItr) { QList<Parameterization> combination; combination.push_back( Parameterization(parameter, parameterValueItr.value())); parameterizations.push_back(combination); } // Check if another iteration will produce any more names. if (noMoreParameters) { // This is it, so just return the current parameterizations. return parameterizations; } // Make recursive call ReturnType suffixes(ExpandParameters(nextIndex, parameters)); if (suffixes.empty()) { // This is it, so just return the current parameterizations. return parameterizations; } ReturnType returnValue; for (ReturnType::iterator suffixItr = suffixes.begin(); suffixItr != suffixes.end(); ++suffixItr) { for (ReturnType::iterator combinationItr = parameterizations.begin(); combinationItr != parameterizations.end(); ++combinationItr) { QList<Parameterization> newCombination(*combinationItr); newCombination.append(*suffixItr); returnValue.push_back(newCombination); } } return returnValue; }
bool QLibraryPrivate::load_sys() { QString attempt; #if !defined(QT_NO_DYNAMIC_LIBRARY) QFileInfo fi(fileName); #if defined(Q_OS_SYMBIAN) QString path; // In Symbian, always resolve with just the filename QString name; // Replace possible ".qtplugin" suffix with ".dll" if (fi.suffix() == QLatin1String("qtplugin")) name = fi.completeBaseName() + QLatin1String(".dll"); else name = fi.fileName(); #else QString path = fi.path(); QString name = fi.fileName(); if (path == QLatin1String(".") && !fileName.startsWith(path)) path.clear(); else path += QLatin1Char('/'); #endif // The first filename we want to attempt to load is the filename as the callee specified. // Thus, the first attempt we do must be with an empty prefix and empty suffix. QStringList suffixes(QLatin1String("")), prefixes(QLatin1String("")); if (pluginState != IsAPlugin) { #if !defined(Q_OS_SYMBIAN) prefixes << QLatin1String("lib"); #endif #if defined(Q_OS_HPUX) // according to // http://docs.hp.com/en/B2355-90968/linkerdifferencesiapa.htm // In PA-RISC (PA-32 and PA-64) shared libraries are suffixed // with .sl. In IPF (32-bit and 64-bit), the shared libraries // are suffixed with .so. For compatibility, the IPF linker // also supports the .sl suffix. // But since we don't know if we are built on HPUX or HPUXi, // we support both .sl (and .<version>) and .so suffixes but // .so is preferred. # if defined(__ia64) if (!fullVersion.isEmpty()) { suffixes << QString::fromLatin1(".so.%1").arg(fullVersion); } else { suffixes << QLatin1String(".so"); } # endif if (!fullVersion.isEmpty()) { suffixes << QString::fromLatin1(".sl.%1").arg(fullVersion); suffixes << QString::fromLatin1(".%1").arg(fullVersion); } else { suffixes << QLatin1String(".sl"); } #elif defined(Q_OS_AIX) suffixes << ".a"; #elif defined(Q_OS_SYMBIAN) suffixes << QLatin1String(".dll"); #else if (!fullVersion.isEmpty()) { suffixes << QString::fromLatin1(".so.%1").arg(fullVersion); } else { suffixes << QLatin1String(".so"); } #endif # ifdef Q_OS_MAC if (!fullVersion.isEmpty()) { suffixes << QString::fromLatin1(".%1.bundle").arg(fullVersion); suffixes << QString::fromLatin1(".%1.dylib").arg(fullVersion); } else { suffixes << QLatin1String(".bundle") << QLatin1String(".dylib"); } #endif } int dlFlags = 0; #if defined(QT_HPUX_LD) dlFlags = DYNAMIC_PATH | BIND_NONFATAL; if (loadHints & QLibrary::ResolveAllSymbolsHint) { dlFlags |= BIND_IMMEDIATE; } else { dlFlags |= BIND_DEFERRED; } #else if (loadHints & QLibrary::ResolveAllSymbolsHint) { dlFlags |= RTLD_NOW; } else { dlFlags |= RTLD_LAZY; } if (loadHints & QLibrary::ExportExternalSymbolsHint) { dlFlags |= RTLD_GLOBAL; } #if !defined(Q_OS_CYGWIN) else { #if defined(Q_OS_MAC) if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) #endif dlFlags |= RTLD_LOCAL; } #endif #if defined(Q_OS_AIX) // Not sure if any other platform actually support this thing. if (loadHints & QLibrary::LoadArchiveMemberHint) { dlFlags |= RTLD_MEMBER; } #endif #endif // QT_HPUX_LD bool retry = true; for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) { for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) { if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix))) continue; if (!suffixes.at(suffix).isEmpty() && name.endsWith(suffixes.at(suffix))) continue; if (loadHints & QLibrary::LoadArchiveMemberHint) { attempt = name; int lparen = attempt.indexOf(QLatin1Char('(')); if (lparen == -1) lparen = attempt.count(); attempt = path + prefixes.at(prefix) + attempt.insert(lparen, suffixes.at(suffix)); } else { attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix); } #if defined(QT_HPUX_LD) pHnd = (void*)shl_load(QFile::encodeName(attempt), dlFlags, 0); #else pHnd = dlopen(QFile::encodeName(attempt), dlFlags); #endif #if defined(Q_OS_SYMBIAN) // Never try again in symbian, dlopen already handles the library search logic, // and there is only one possible suffix. retry = false; #else if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) { // We only want to continue if dlopen failed due to that the shared library did not exist. // However, we are only able to apply this check for absolute filenames (since they are // not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...) // This is all because dlerror is flawed and cannot tell us the reason why it failed. retry = false; } #endif } } #ifdef Q_OS_MAC if (!pHnd) { QByteArray utf8Bundle = fileName.toUtf8(); QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true); QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl); if(bundle) { QCFType<CFURLRef> url = CFBundleCopyExecutableURL(bundle); char executableFile[FILENAME_MAX]; CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX); attempt = QString::fromUtf8(executableFile); pHnd = dlopen(QFile::encodeName(attempt), dlFlags); } } #endif #endif // QT_NO_DYNAMIC_LIBRARY if (!pHnd) { errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qdlerror()); } if (pHnd) { qualifiedFileName = attempt; errorString.clear(); } return (pHnd != 0); }
int RideImportWizard::process() { // set progress bar limits - for each file we // will make 5 passes over the files // 1. checking it is a file ane readable // 2. parsing it with the RideFileReader // 3. [optional] collect date/time information from user // 4. copy file into Library // 5. Process for CPI (not implemented yet) // So, therefore the progress bar runs from 0 to files*4. (since step 5 is not implemented yet) progressBar->setMinimum(0); progressBar->setMaximum(filenames.count()*4); // Pass one - Is it valid? phaseLabel->setText(tr("Step 1 of 4: Check file permissions")); for (int i=0; i < filenames.count(); i++) { // get fullpath name for processing QFileInfo thisfile(filenames[i]); if (thisfile.exists() && thisfile.isFile() && thisfile.isReadable()) { // is it one we understand ? QStringList suffixList = RideFileFactory::instance().suffixes(); QRegExp suffixes(QString("^(%1)$").arg(suffixList.join("|"))); suffixes.setCaseSensitivity(Qt::CaseInsensitive); if (suffixes.exactMatch(thisfile.suffix())) { // Woot. We know how to parse this baby tableWidget->item(i,5)->setText(tr("Queued")); } else { tableWidget->item(i,5)->setText(tr("Error - Unknown file type")); } } else { // Cannot open tableWidget->item(i,5)->setText(tr("Error - Not a valid file")); } progressBar->setValue(progressBar->value()+1); } QApplication::processEvents(); if (aborted) { done(0); } repaint(); // Pass 2 - Read in with the relevant RideFileReader method phaseLabel->setText(tr("Step 2 of 4: Validating Files")); for (int i=0; i< filenames.count(); i++) { // does the status say Queued? if (!tableWidget->item(i,5)->text().startsWith(tr("Error"))) { QStringList errors; QFile thisfile(filenames[i]); tableWidget->item(i,5)->setText(tr("Parsing...")); tableWidget->setCurrentCell(i,5); QApplication::processEvents(); if (aborted) { done(0); } this->repaint(); QList<RideFile*> rides; RideFile *ride = RideFileFactory::instance().openRideFile(mainWindow, thisfile, errors, &rides); // is this an archive of files? if (rides.count() > 1) { int here = i; // remove current filename from state arrays and tableview filenames.removeAt(here); blanks.removeAt(here); tableWidget->removeRow(here); // resize dialog according to the number of rows we expect int willhave = filenames.count() + rides.count(); resize(920 + ((willhave > 16 ? 24 : 0) + (willhave > 9 && willhave < 17) ? 8 : 0), 118 + (willhave > 16 ? 17*20 : (willhave+1) * 20)); // ok so create a temporary file and add to the tableWidget int counter = 0; foreach(RideFile *extracted, rides) { // write as a temporary file, using the original // filename with "-n" appended QString fulltarget = QDir::tempPath() + "/" + QFileInfo(thisfile).baseName() + QString("-%1.tcx").arg(counter+1); TcxFileReader reader; QFile target(fulltarget); reader.writeRideFile(mainWindow, extracted, target); deleteMe.append(fulltarget); delete extracted; // now add each temporary file ... filenames.insert(here, fulltarget); blanks.insert(here, true); // by default editable tableWidget->insertRow(here+counter); QTableWidgetItem *t; // Filename t = new QTableWidgetItem(); t->setText(fulltarget); t->setFlags(t->flags() & (~Qt::ItemIsEditable)); tableWidget->setItem(here+counter,0,t); // Date t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() | Qt::ItemIsEditable); t->setBackgroundColor(Qt::red); tableWidget->setItem(here+counter,1,t); // Time t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() | Qt::ItemIsEditable); tableWidget->setItem(here+counter,2,t); // Duration t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() & (~Qt::ItemIsEditable)); tableWidget->setItem(here+counter,3,t); // Distance t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() & (~Qt::ItemIsEditable)); tableWidget->setItem(here+counter,4,t); // Import Status t = new QTableWidgetItem(); t->setText(tr("")); t->setFlags(t->flags() & (~Qt::ItemIsEditable)); tableWidget->setItem(here+counter,5,t); counter++; tableWidget->adjustSize(); QApplication::processEvents(); } // progress bar needs to adjust... progressBar->setMaximum(filenames.count()*4); // then go back one and re-parse from there rides.clear(); i--; goto next; // buttugly I know, but count em across 100,000 lines of code }
int RideImportWizard::process() { // set progress bar limits - for each file we // will make 5 passes over the files // 1. checking it is a file ane readable // 2. parsing it with the RideFileReader // 3. [optional] collect date/time information from user // 4. copy file into Library // 5. Process for CPI (not implemented yet) // So, therefore the progress bar runs from 0 to files*4. (since step 5 is not implemented yet) progressBar->setMinimum(0); progressBar->setMaximum(filenames.count()*4); // Pass one - Is it valid? phaseLabel->setText(tr("Step 1 of 4: Check file permissions")); for (int i=0; i < filenames.count(); i++) { // get fullpath name for processing QFileInfo thisfile(filenames[i]); if (thisfile.exists() && thisfile.isFile() && thisfile.isReadable()) { // is it one we understand ? QStringList suffixList = RideFileFactory::instance().suffixes(); QRegExp suffixes(QString("^(%1)$").arg(suffixList.join("|"))); suffixes.setCaseSensitivity(Qt::CaseInsensitive); if (suffixes.exactMatch(thisfile.suffix())) { // Woot. We know how to parse this baby tableWidget->item(i,5)->setText(tr("Queued")); } else { tableWidget->item(i,5)->setText(tr("Error - Unknown file type")); } } else { // Cannot open tableWidget->item(i,5)->setText(tr("Error - Not a valid file")); } progressBar->setValue(progressBar->value()+1); } QApplication::processEvents(); if (aborted) { done(0); } repaint(); // Pass 2 - Read in with the relevant RideFileReader method phaseLabel->setText(tr("Step 2 of 4: Validating Files")); for (int i=0; i< filenames.count(); i++) { // does the status say Queued? if (!tableWidget->item(i,5)->text().startsWith(tr("Error"))) { QStringList errors; QFile thisfile(filenames[i]); tableWidget->item(i,5)->setText(tr("Parsing...")); tableWidget->setCurrentCell(i,5); QApplication::processEvents(); if (aborted) { done(0); } this->repaint(); boost::scoped_ptr<RideFile> ride(RideFileFactory::instance().openRideFile(thisfile, errors)); // did it parse ok? if (ride && errors.empty()) { // ITS A KEEPER, LETS GET SOME METADATA ON DISPLAY tableWidget->item(i,5)->setText(tr("Validated")); // Set Date and Time if (ride->startTime().isNull()) { // Poo. The user needs to supply the date/time for this ride blanks[i] = true; tableWidget->item(i,1)->setText(tr("")); tableWidget->item(i,2)->setText(tr("")); } else { // Cool, the date and time was extrcted from the source file blanks[i] = false; tableWidget->item(i,1)->setText(ride->startTime().toString(tr("dd MMM yyyy"))); tableWidget->item(i,2)->setText(ride->startTime().toString(tr("hh:mm:ss ap"))); } tableWidget->item(i,1)->setTextAlignment(Qt::AlignRight); // put in the middle tableWidget->item(i,2)->setTextAlignment(Qt::AlignRight); // put in the middle // show duration by looking at last data point if (ride->dataPoints().last() != NULL) { int secs = ride->dataPoints().last()->secs; QChar zero = QLatin1Char ( '0' ); QString time = QString("%1:%2:%3").arg(secs/3600,2,10,zero) .arg(secs%3600/60,2,10,zero) .arg(secs%60,2,10,zero); tableWidget->item(i,3)->setText(time); tableWidget->item(i,3)->setTextAlignment(Qt::AlignHCenter); // put in the middle // show distance by looking at last data point int km = ride->dataPoints().last()->km; QString dist = QString ("%1 km").arg(km, 1,10,zero); tableWidget->item(i,4)->setText(dist); tableWidget->item(i,4)->setTextAlignment(Qt::AlignRight); // put in the middle } else { tableWidget->item(i,3)->setText(tr("00:00:00")); // duration tableWidget->item(i,3)->setTextAlignment(Qt::AlignHCenter); // put in the middle tableWidget->item(i,4)->setText(tr("0 km")); tableWidget->item(i,4)->setTextAlignment(Qt::AlignRight); // put in the middle } } else { // nope - can't handle this file tableWidget->item(i,5)->setText(tr("Error - ") + errors.join(tr(" "))); } } progressBar->setValue(progressBar->value()+1); QApplication::processEvents(); if (aborted) { done(0); } this->repaint(); } // Pass 3 - get missing date and times for imported files phaseLabel->setText(tr("Step 3 of 4: Confirm Date and Time")); int needdates=0; bool first = true; for (int i=0; i<filenames.count(); i++) { // ignore errors QTableWidgetItem *t = tableWidget->item(i,5); if (t->text().startsWith(tr("Error"))) continue; // date needed? if (blanks[i]) { needdates++; t = tableWidget->item(i,1); t->setFlags(t->flags() | (Qt::ItemIsEditable)); // make editable ONLY if not present - // we cannot override the RideFileReader if (first) { tableWidget->editItem(t); first = false; } t = tableWidget->item(i,2); t->setFlags(t->flags() | (Qt::ItemIsEditable)); // make editable ONLY if not present - // we cannot override the RideFileReader } // does nothing for the moment progressBar->setValue(progressBar->value()+1); progressBar->repaint(); } // Wait for user to press save abortButton->setText(tr("Save")); aborted = false; cancelButton->setHidden(false); todayButton->setHidden(false); overFiles->setHidden(false); if (needdates == 0) { // no need to wait for the user to input dates // nd press save if all the dates are set // (i.e. they got set by the file importers already) // do nothing for now since we need to confirm dates // and confirm overwrite files rather than importing // without user intervention abortButton->setDisabled(false); // abortClicked(); } else { // de-activate Save button until the dates and times are sorted abortButton->setDisabled(true); } connect(tableWidget, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(activateSave())); return 0; }
/** * cactusMerge.cpp: merge two pairs of c2h and FASTA files into one pair. The * files must be star trees with the same root sequence. */ int main( int argc, char** argv ) { // Register ctrl+c handler. See // <http://www.yolinux.com/TUTORIALS/C++Signals.html> signal(SIGINT, stacktraceOnSignal); // Register segfaults with the stack trace handler signal(SIGSEGV, stacktraceOnSignal); // Parse options with boost::programOptions. See // <http://www.radmangames.com/programming/how-to-use-boost-program_options> std::string appDescription = std::string("Merge c2h/FASTA file pairs.\n" "Usage: cactusMerge <c2hOut> <fastaOut> --c2h <c2h files...> " "--fasta <fasta files...> --suffix <suffixes...>"); // Make an options description for our program's options. boost::program_options::options_description description("Options"); // Add all the options description.add_options() ("help", "Print help messages") ("c2h", boost::program_options::value<std::vector<std::string>>(), "List of c2h files to merge") ("fasta", boost::program_options::value<std::vector<std::string>>(), "List of FASTA files for the given c2h files") ("suffix", boost::program_options::value<std::vector<std::string>>(), "List of suffixes to add on to event names") ("mergeOn", boost::program_options::value<std::string>()->required(), "An event on which to merge the files") ("c2hOut", boost::program_options::value<std::string>()->required(), "File to save .c2h-format alignment in") ("fastaOut", boost::program_options::value<std::string>()->required(), "File in which to save FASTA records for building HAL from .c2h"); // And set up our positional arguments boost::program_options::positional_options_description positionals; positionals.add("mergeOn", 1); positionals.add("c2hOut", 1); positionals.add("fastaOut", 1); // Add a variables map to hold option variables. boost::program_options::variables_map options; try { // Parse options into the variable map, or throw an error if there's // something wring with them. boost::program_options::store( // Build the command line parser. boost::program_options::command_line_parser(argc, argv) .options(description) .positional(positionals) .run(), options); boost::program_options::notify(options); if(options.count("help")) { // The help option was given. Print program help. std::cout << appDescription << std::endl; std::cout << description << std::endl; // Don't do the actual program. return 0; } if(!options.count("mergeOn") || !options.count("c2h") || !options.count("fasta")) { // We need both of these throw boost::program_options::error("Missing important arguments!"); } if(options["c2h"].as<std::vector<std::string>>().size() != options["fasta"].as<std::vector<std::string>>().size()) { // Counts need to match up here, because these are pairs throw boost::program_options::error( "c2h/fasta counts don't match!"); } if(options.count("suffix") && options["c2h"].as<std::vector<std::string>>().size() != options["suffix"].as<std::vector<std::string>>().size()) { // If we have any suffixes we must have the right number throw boost::program_options::error( "c2h/suffix counts don't match!"); } } catch(boost::program_options::error& error) { // Something is bad about our options. Complain on stderr std::cerr << "Option parsing error: " << error.what() << std::endl; std::cerr << std::endl; // Talk about our app. std::cerr << appDescription << std::endl; // Show all the actually available options. std::cerr << description << std::endl; // Stop the program. return -1; } // If we get here, we have the right arguments. // Make a list of the c2h files to use std::vector<std::string> c2hFiles( options["c2h"].as<std::vector<std::string>>()); // This holds the suffix applied to all the top sequences and events in each // file. std::vector<std::string> suffixes( options["suffix"].as<std::vector<std::string>>()); // Make a list of the FASTA files to use std::vector<std::string> fastaFiles( options["fasta"].as<std::vector<std::string>>()); // This will hold all of the renames that have to happen for each file. // These are generated when we go through the file by renaming top and // bottom sequences with suffixes. std::vector<std::map<std::string, std::string>> renames; for(size_t i = 0; i < c2hFiles.size(); i++) { // Make sure it has an empty map of renames for each file. renames.push_back(std::map<std::string, std::string>()); } // This will hold the event names for the c2h files in order std::vector<std::string> eventNames; // And this will hold the sequence names std::vector<std::string> sequenceNames; // This will hold bottom (1) and top (0) flags for each sequence. std::vector<bool> isBottom; // And this will hold the sequence lengths std::vector<size_t> sequenceLengths; // This will hold the first sequence number for any event and sequence name std::map<std::pair<std::string, std::string>, size_t> firstSequenceNumber; // Holds Merge structs to be executed later. std::vector<C2hMerge> merges; // We're going to throw out all of the events that are old rootSeqs, and // just keep the actual leaves. This holds the list of renamed event names // we are keeping. std::set<std::string> eventsToKeep; for(size_t fileIndex = 0; fileIndex < c2hFiles.size(); fileIndex++) { // Scan through the c2h files to get the event, sequence, and length of // each thread, and to collect merges. Log::output() << "Reading alignment " << c2hFiles[fileIndex] << std::endl; // Open the file std::ifstream c2h(c2hFiles[fileIndex]); // This maps block name to (sequence number, start location) pairs for // this file. We use it to compose merges for our list in global // sequence number space. std::map<size_t, std::pair<size_t, size_t>> nameMap; for(std::string line; std::getline(c2h, line);) { // This is a new sequence. Split it up on \t. std::vector<std::string> parts; boost::split(parts, line, boost::is_any_of("\t")); if(parts.size() < 1) { // Skip lines that have nothing on them. continue; } // For each line if(parts[0] == "s") { // It's a sequence line. Start a new squence. if(parts.size() != 4) { // Not the right number of fields. throw std::runtime_error( std::string("Invalid field count in ") + line); } // Grab the parts std::string eventName = unquote(parts[1]); std::string sequenceName = unquote(parts[2]); bool bottomFlag = std::stoi(parts[3]); Log::info() << "Read sequence " << eventName << "." << sequenceName << (bottomFlag ? " (bottom)" : " (top)") << std::endl; if(eventName != options["mergeOn"].as<std::string>()) { // We aren't merging on this sequence, so we may have to // apply a suffix. // We need to rename this event (possibly to the same thing) renames[fileIndex][eventName] = eventName + suffixes[fileIndex]; if(bottomFlag) { // All the bottom events (that aren't being merged // on) need to be renamed apart manually since the names // may be reused. renames[fileIndex][eventName] += "-" + std::to_string(fileIndex); } eventName = renames[fileIndex][eventName]; if(!bottomFlag) { // Keep this event when we do our final output. eventsToKeep.insert(eventName); } // And the sequence renames[fileIndex][sequenceName] = sequenceName + suffixes[fileIndex]; if(bottomFlag) { // All the bottom sequences (that aren't being merged // on) need to be renamed apart manually since the names // may be reused. renames[fileIndex][sequenceName] += "-" + std::to_string(fileIndex); } sequenceName = renames[fileIndex][sequenceName]; Log::info() << "Canonical name: " << eventName << "." << sequenceName << std::endl; } else { // If we are going to merge on it, we keep its name the same // and then later we just make one thread for that name. We // do definitely need it in the output though. eventsToKeep.insert(eventName); } // Save the names eventNames.push_back(eventName); sequenceNames.push_back(sequenceName); // Save the bottomness flag. isBottom.push_back(bottomFlag); // Initialize the total length to 0 sequenceLengths.push_back(0); auto namePair = std::make_pair(eventName, sequenceName); if(!firstSequenceNumber.count(namePair)) { // This is the first time we have seen a sequence // for this event and sequence name. Everything should // merge against this one thread and not make more // threads. // If this is the mergeOn event, we'll only make this // once across all the files. // Later instances of this event and sequence name should // redirect here. firstSequenceNumber[namePair] = sequenceNames.size() - 1; Log::info() << "This is the first time we have seen " "this sequence." << std::endl; } } else if(parts[0] == "a") { // This is an alignment block if(sequenceNames.size() == 0) { throw std::runtime_error( "Found alignmet block before sequence"); } // Which sequence are we working on? size_t sequenceNumber = sequenceNames.size() - 1; if(isBottom[sequenceNumber]) { // Parse it as a bottom block: "a" name start length if(parts.size() != 4) { // Not the right number of fields. throw std::runtime_error( std::string("Invalid field count in ") + line); } size_t blockName = std::stoll(parts[1]); size_t blockStart = std::stoll(parts[2]); size_t blockLength = std::stoll(parts[3]); // Look up the sequence number we actually want to merge // against when we come get this block. auto namePair = std::make_pair(eventNames[sequenceNumber], sequenceNames[sequenceNumber]); size_t mergeSequenceNumber = firstSequenceNumber[namePair]; // We need to associate the block name with the thread // number for the sequence we want it to merge into, and the // start location it specifies, for merging later. nameMap[blockName] = std::make_pair(mergeSequenceNumber, blockStart); Log::debug() << "Bottom block " << blockName << " is " << blockStart << " on sequence " << mergeSequenceNumber << std::endl; // Also record the additional length on this sequence sequenceLengths[sequenceNumber] += blockLength; } else { // Parse it as a top block: // "a" start length [name orientation] if(parts.size() < 3) { // Not the right number of fields. throw std::runtime_error( std::string("Invalid field count in ") + line); } // Parse out the start and length size_t segmentStart = std::stoll(parts[1]); size_t segmentLength = std::stoll(parts[2]); // Add in the length sequenceLengths[sequenceNumber] += segmentLength; if(parts.size() == 5) { // If it has a name and orientation, remember a merge. size_t blockName = std::stoll(parts[3]); bool orientation = std::stoi(parts[4]); // Get the sequence number that canonically represents // all sequences with this event/sequence name // combination. auto namePair = std::make_pair( eventNames[sequenceNumber], sequenceNames[sequenceNumber]); size_t mergeSequenceNumber = firstSequenceNumber[ namePair]; // Make a merge and populate it with everything we can // get from this segment. C2hMerge merge; merge.sequence1 = mergeSequenceNumber; merge.start1 = segmentStart; merge.length = segmentLength; // TODO: error-check length merge.orientation = orientation; // Grab the info from the bottom segment we are talking // about earlier in this file. merge.sequence2 = nameMap[blockName].first; merge.start2 = nameMap[blockName].second; Log::debug() << "Going to merge " << segmentStart << " length " << segmentLength << " to " << blockName << " orientation " << orientation << std::endl; // Save the merge for doing later. merges.push_back(merge); } } } } } // Make a thread set with all those threads stPinchThreadSet* threadSet = stPinchThreadSet_construct(); // Make all the threads. Be 1-based internally since the serialization code // wants that. for(size_t i = 0; i < sequenceLengths.size(); i++) { auto namePair = std::make_pair(eventNames[i], sequenceNames[i]); if(firstSequenceNumber[namePair] != i) { // This sequence is not the first; it is getting merged into another // one that is the same length and structure and name (i.e. it // appears in two files). Don't make a thread for it. continue; } // Make threads for all the top sequences and the first bottom sequence // for every event and sequence name pair. stPinchThreadSet_addThread(threadSet, i, 1, sequenceLengths[i]); } for(auto merge : merges) { // Apply all the merges, converting merges to 1-based stPinchThread_pinch( stPinchThreadSet_getThread(threadSet, merge.sequence1), stPinchThreadSet_getThread(threadSet, merge.sequence2), merge.start1 + 1, merge.start2 + 1, merge.length, merge.orientation); Log::trace() << "Applied merge between threads " << merge.sequence1 << ":" << merge.start1 << "-" << merge.start1 + merge.length << " and " << merge.sequence2 << ":" << merge.start2 << "-" << merge.start2 + merge.length << " orientation " << merge.orientation << std::endl; } // Write out a new c2h file, with a new rootSeq. size_t newRootLength = writeAlignment(threadSet, sequenceNames, eventNames, options["c2hOut"].as<std::string>(), &eventsToKeep); // Clean up thread set. stPinchThreadSet_destruct(threadSet); // Merge the FASTAs, applying any renaming that needs to happen. // We'll do the FASTA output ourselves. Open the file. std::ofstream fastaOut(options["fastaOut"].as<std::string>()); // Write the newly synthesized rootSeq. TODO: unify with writeAlignmentFasta // by moving support for renames over there. fastaOut << ">rootSeq" << std::endl; for(size_t i = 0; i < newRootLength; i++) { // Write an n for every base fastaOut << "N"; } fastaOut << std::endl; // This holds the IDs of all the sequences we already wrote. Only write // sequences if they aren't duplicates after renaming (which is how we // deduplicate the shared root) std::unordered_set<std::string> alreadyWritten; for(size_t fileIndex = 0; fileIndex < fastaFiles.size(); fileIndex++) { // Open up the FASTA for reading Fasta fasta(fastaFiles[fileIndex]); Log::info() << "Copying over FASTA records from " << fastaFiles[fileIndex] << std::endl; while(fasta.hasNext()) { // Go through all the FASTA records. // TODO: assumes FASTA headers have nothing but IDs. std::pair<std::string, std::string> record = fasta.getNextRecord(); if(renames[fileIndex].count(record.first)) { // Rename them if necessary record.first = renames[fileIndex][record.first]; } if(!eventsToKeep.count(record.first)) { // This event wasn't on the list of events to actually output, // so don't output it. Log::info() << "Skipped event " << record.first << std::endl; continue; } if(!alreadyWritten.count(record.first)) { // Save the record to the output FASTA file. fastaOut << ">" << record.first << std::endl << record.second << std::endl; // Remember that we have written a record by this name. alreadyWritten.insert(record.first); } } } fastaOut.close(); // Now we're done! return 0; }