MixxxLibraryFeature::MixxxLibraryFeature(Library* pLibrary, TrackCollection* pTrackCollection, ConfigObject<ConfigValue>* pConfig) : LibraryFeature(pLibrary), kMissingTitle(tr("Missing Tracks")), kHiddenTitle(tr("Hidden Tracks")), m_pLibrary(pLibrary), m_pMissingView(NULL), m_pHiddenView(NULL), m_trackDao(pTrackCollection->getTrackDAO()), m_pConfig(pConfig), m_pTrackCollection(pTrackCollection) { QStringList columns; columns << "library." + LIBRARYTABLE_ID << "library." + LIBRARYTABLE_PLAYED << "library." + LIBRARYTABLE_TIMESPLAYED //has to be up here otherwise Played and TimesPlayed are not show << "library." + LIBRARYTABLE_ALBUMARTIST << "library." + LIBRARYTABLE_ALBUM << "library." + LIBRARYTABLE_ARTIST << "library." + LIBRARYTABLE_TITLE << "library." + LIBRARYTABLE_YEAR << "library." + LIBRARYTABLE_RATING << "library." + LIBRARYTABLE_GENRE << "library." + LIBRARYTABLE_COMPOSER << "library." + LIBRARYTABLE_GROUPING << "library." + LIBRARYTABLE_TRACKNUMBER << "library." + LIBRARYTABLE_KEY << "library." + LIBRARYTABLE_KEY_ID << "library." + LIBRARYTABLE_BPM << "library." + LIBRARYTABLE_BPM_LOCK << "library." + LIBRARYTABLE_DURATION << "library." + LIBRARYTABLE_BITRATE << "library." + LIBRARYTABLE_FILETYPE << "library." + LIBRARYTABLE_DATETIMEADDED << "track_locations.location" << "track_locations.fs_deleted" << "library." + LIBRARYTABLE_COMMENT << "library." + LIBRARYTABLE_MIXXXDELETED << "library." + LIBRARYTABLE_COVERART_SOURCE << "library." + LIBRARYTABLE_COVERART_TYPE << "library." + LIBRARYTABLE_COVERART_LOCATION << "library." + LIBRARYTABLE_COVERART_HASH; QSqlQuery query(pTrackCollection->getDatabase()); QString tableName = "library_cache_view"; QString queryString = QString( "CREATE TEMPORARY VIEW IF NOT EXISTS %1 AS " "SELECT %2 FROM library " "INNER JOIN track_locations ON library.location = track_locations.id") .arg(tableName, columns.join(",")); query.prepare(queryString); if (!query.exec()) { LOG_FAILED_QUERY(query); } // Strip out library. and track_locations. for (QStringList::iterator it = columns.begin(); it != columns.end(); ++it) { if (it->startsWith("library.")) { *it = it->replace("library.", ""); } else if (it->startsWith("track_locations.")) { *it = it->replace("track_locations.", ""); } } BaseTrackCache* pBaseTrackCache = new BaseTrackCache( pTrackCollection, tableName, LIBRARYTABLE_ID, columns, true); connect(&m_trackDao, SIGNAL(trackDirty(int)), pBaseTrackCache, SLOT(slotTrackDirty(int))); connect(&m_trackDao, SIGNAL(trackClean(int)), pBaseTrackCache, SLOT(slotTrackClean(int))); connect(&m_trackDao, SIGNAL(trackChanged(int)), pBaseTrackCache, SLOT(slotTrackChanged(int))); connect(&m_trackDao, SIGNAL(tracksAdded(QSet<int>)), pBaseTrackCache, SLOT(slotTracksAdded(QSet<int>))); connect(&m_trackDao, SIGNAL(tracksRemoved(QSet<int>)), pBaseTrackCache, SLOT(slotTracksRemoved(QSet<int>))); connect(&m_trackDao, SIGNAL(dbTrackAdded(TrackPointer)), pBaseTrackCache, SLOT(slotDbTrackAdded(TrackPointer))); m_pBaseTrackCache = QSharedPointer<BaseTrackCache>(pBaseTrackCache); pTrackCollection->setTrackSource(m_pBaseTrackCache); // These rely on the 'default' track source being present. m_pLibraryTableModel = new LibraryTableModel(this, pTrackCollection, "mixxx.db.model.library"); TreeItem* pRootItem = new TreeItem(); TreeItem* pmissingChildItem = new TreeItem(kMissingTitle, kMissingTitle, this, pRootItem); TreeItem* phiddenChildItem = new TreeItem(kHiddenTitle, kHiddenTitle, this, pRootItem); pRootItem->appendChild(pmissingChildItem); pRootItem->appendChild(phiddenChildItem); m_childModel.setRootItem(pRootItem); }
/** @short Take the initial text and mark it as a quotation */ QStringList quoteText(QStringList inputLines) { QStringList quote; for (QStringList::iterator line = inputLines.begin(); line != inputLines.end(); ++line) { if (UiUtils::signatureSeparator().match(*line).hasMatch()) { // This is the signature separator, we should not include anything below that in the quote break; } // rewrap - we need to keep the quotes at < 79 chars, yet the grow with every level if (line->length() < 79-2) { // this line is short enough, prepend quote mark and continue if (line->isEmpty() || line->at(0) == QLatin1Char('>')) line->prepend(QLatin1Char('>')); else line->prepend(QLatin1String("> ")); quote << *line; continue; } // long line -> needs to be wrapped // 1st, detect the quote depth and eventually stript the quotes from the line int quoteLevel = 0; int contentStart = 0; if (line->at(0) == QLatin1Char('>')) { quoteLevel = 1; while (quoteLevel < line->length() && line->at(quoteLevel) == QLatin1Char('>')) ++quoteLevel; contentStart = quoteLevel; if (quoteLevel < line->length() && line->at(quoteLevel) == QLatin1Char(' ')) ++contentStart; } // 2nd, build a quote string QString quotemarks; for (int i = 0; i < quoteLevel; ++i) quotemarks += QLatin1Char('>'); quotemarks += QLatin1String("> "); // 3rd, wrap the line, prepend the quotemarks to each line and add it to the quote text int space(contentStart), lastSpace(contentStart), pos(contentStart), length(0); while (pos < line->length()) { if (line->at(pos) == QLatin1Char(' ')) space = pos+1; ++length; if (length > 65-quotemarks.length() && space != lastSpace) { // wrap quote << quotemarks + line->mid(lastSpace, space - lastSpace); lastSpace = space; length = pos - space; } ++pos; } quote << quotemarks + line->mid(lastSpace); } return quote; }
QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri ) : QgsVectorDataProvider( uri ), mXFieldIndex( -1 ), mYFieldIndex( -1 ), mShowInvalidLines( true ) { // Get the file name and mDelimiter out of the uri mFileName = uri.left( uri.indexOf( "?" ) ); // split the string up on & to get the individual parameters QStringList parameters = uri.mid( uri.indexOf( "?" ) ).split( "&", QString::SkipEmptyParts ); QgsDebugMsg( "Parameter count after split on &" + QString::number( parameters.size() ) ); // get the individual parameters and assign values QStringList temp = parameters.filter( "delimiter=" ); mDelimiter = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; temp = parameters.filter( "delimiterType=" ); mDelimiterType = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; temp = parameters.filter( "xField=" ); QString xField = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; temp = parameters.filter( "yField=" ); QString yField = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; // Decode the parts of the uri. Good if someone entered '=' as a delimiter, for instance. mFileName = QUrl::fromPercentEncoding( mFileName.toUtf8() ); mDelimiter = QUrl::fromPercentEncoding( mDelimiter.toUtf8() ); mDelimiterType = QUrl::fromPercentEncoding( mDelimiterType.toUtf8() ); xField = QUrl::fromPercentEncoding( xField.toUtf8() ); yField = QUrl::fromPercentEncoding( yField.toUtf8() ); QgsDebugMsg( "Data source uri is " + uri ); QgsDebugMsg( "Delimited text file is: " + mFileName ); QgsDebugMsg( "Delimiter is: " + mDelimiter ); QgsDebugMsg( "Delimiter type is: " + mDelimiterType ); QgsDebugMsg( "xField is: " + xField ); QgsDebugMsg( "yField is: " + yField ); // if delimiter contains some special characters, convert them if ( mDelimiterType == "regexp" ) mDelimiterRegexp = QRegExp( mDelimiter ); else mDelimiter.replace( "\\t", "\t" ); // replace "\t" with a real tabulator // Set the selection rectangle to null mSelectionRectangle = QgsRectangle(); // assume the layer is invalid until proven otherwise mValid = false; if ( mFileName.isEmpty() || mDelimiter.isEmpty() || xField.isEmpty() || yField.isEmpty() ) { // uri is invalid so the layer must be too... QString( "Data source is invalid" ); return; } // check to see that the file exists and perform some sanity checks if ( !QFile::exists( mFileName ) ) { QgsDebugMsg( "Data source " + dataSourceUri() + " doesn't exist" ); return; } // Open the file and get number of rows, etc. We assume that the // file has a header row and process accordingly. Caller should make // sure the the delimited file is properly formed. mFile = new QFile( mFileName ); if ( !mFile->open( QIODevice::ReadOnly ) ) { QgsDebugMsg( "Data source " + dataSourceUri() + " could not be opened" ); delete mFile; return; } // now we have the file opened and ready for parsing // set the initial extent mExtent = QgsRectangle(); QMap<int, bool> couldBeInt; QMap<int, bool> couldBeDouble; mStream = new QTextStream( mFile ); QString line; mNumberFeatures = 0; int lineNumber = 0; bool firstPoint = true; bool hasFields = false; while ( !mStream->atEnd() ) { lineNumber++; line = mStream->readLine(); // line of text excluding '\n', default local 8 bit encoding. if ( !hasFields ) { // Get the fields from the header row and store them in the // fields vector QgsDebugMsg( "Attempting to split the input line: " + line + " using delimiter " + mDelimiter ); QStringList fieldList; if ( mDelimiterType == "regexp" ) fieldList = line.split( mDelimiterRegexp ); else fieldList = line.split( mDelimiter ); QgsDebugMsg( "Split line into " + QString::number( fieldList.size() ) + " parts" ); // We don't know anything about a text based field other // than its name. All fields are assumed to be text int fieldPos = 0; for ( QStringList::Iterator it = fieldList.begin(); it != fieldList.end(); ++it ) { QString field = *it; if ( field.length() > 0 ) { // for now, let's set field type as text attributeFields[fieldPos] = QgsField( *it, QVariant::String, "Text" ); // check to see if this field matches either the x or y field if ( xField == *it ) { QgsDebugMsg( "Found x field: " + ( *it ) ); mXFieldIndex = fieldPos; } else if ( yField == *it ) { QgsDebugMsg( "Found y field: " + ( *it ) ); mYFieldIndex = fieldPos; } QgsDebugMsg( "Adding field: " + ( *it ) ); // assume that the field could be integer or double couldBeInt.insert( fieldPos, true ); couldBeDouble.insert( fieldPos, true ); fieldPos++; } } QgsDebugMsg( "Field count for the delimited text file is " + QString::number( attributeFields.size() ) ); hasFields = true; } else if ( mXFieldIndex != -1 && mYFieldIndex != -1 ) { mNumberFeatures++; // split the line on the delimiter QStringList parts; if ( mDelimiterType == "regexp" ) parts = line.split( mDelimiterRegexp ); else parts = line.split( mDelimiter ); // Skip malformed lines silently. Report line number with nextFeature() if ( attributeFields.size() != parts.size() ) { continue; } // Get the x and y values, first checking to make sure they // aren't null. QString sX = parts[mXFieldIndex]; QString sY = parts[mYFieldIndex]; bool xOk = true; bool yOk = true; double x = sX.toDouble( &xOk ); double y = sY.toDouble( &yOk ); if ( xOk && yOk ) { if ( !firstPoint ) { mExtent.combineExtentWith( x, y ); } else { // Extent for the first point is just the first point mExtent.set( x, y, x, y ); firstPoint = false; } } int i = 0; for ( QStringList::iterator it = parts.begin(); it != parts.end(); ++it, ++i ) { // try to convert attribute values to integer and double if ( couldBeInt[i] ) { it->toInt( &couldBeInt[i] ); } if ( couldBeDouble[i] ) { it->toDouble( &couldBeDouble[i] ); } } } } // now it's time to decide the types for the fields for ( QgsFieldMap::iterator it = attributeFields.begin(); it != attributeFields.end(); ++it ) { if ( couldBeInt[it.key()] ) { it->setType( QVariant::Int ); it->setTypeName( "integer" ); } else if ( couldBeDouble[it.key()] ) { it->setType( QVariant::Double ); it->setTypeName( "double" ); } } if ( mXFieldIndex != -1 && mYFieldIndex != -1 ) { QgsDebugMsg( "Data store is valid" ); QgsDebugMsg( "Number of features " + QString::number( mNumberFeatures ) ); QgsDebugMsg( "Extents " + mExtent.toString() ); mValid = true; } else { QgsDebugMsg( "Data store is invalid. Specified x,y fields do not match those in the database" ); } QgsDebugMsg( "Done checking validity" ); }
int main( int argc, char ** argv ) { #if defined (FC_OS_LINUX) || defined(FC_OS_BSD) // Make sure to setup the Qt locale system before setting LANG and LC_ALL to C. // which is needed to use the system locale settings. (void)QLocale::system(); // http://www.freecadweb.org/tracker/view.php?id=399 // Because of setting LANG=C the Qt automagic to use the correct encoding // for file names is broken. This is a workaround to force the use of UTF-8 encoding QFile::setEncodingFunction(myEncoderFunc); QFile::setDecodingFunction(myDecoderFunc); // Make sure that we use '.' as decimal point. See also // http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=559846 putenv("LC_NUMERIC=C"); putenv("PYTHONPATH="); #elif defined(FC_OS_MACOSX) (void)QLocale::system(); putenv("LC_NUMERIC=C"); putenv("PYTHONPATH="); #else setlocale(LC_NUMERIC, "C"); _putenv("PYTHONPATH="); #endif #if defined (FC_OS_WIN32) int argc_ = argc; QVector<QByteArray> data; QVector<char *> argv_; // get the command line arguments as unicode string { QCoreApplication app(argc, argv); QStringList args = app.arguments(); for (QStringList::iterator it = args.begin(); it != args.end(); ++it) { data.push_back(it->toUtf8()); argv_.push_back(data.back().data()); } argv_.push_back(0); // 0-terminated string } #endif // Name and Version of the Application App::Application::Config()["ExeName"] = "FreeCAD"; App::Application::Config()["ExeVendor"] = "FreeCAD"; App::Application::Config()["AppDataSkipVendor"] = "true"; App::Application::Config()["MaintainerUrl"] = "http://www.freecadweb.org/wiki/index.php?title=Main_Page"; // set the banner (for logging and console) App::Application::Config()["CopyrightInfo"] = sBanner; App::Application::Config()["AppIcon"] = "freecad"; App::Application::Config()["SplashScreen"] = "freecadsplash"; App::Application::Config()["StartWorkbench"] = "StartWorkbench"; //App::Application::Config()["HiddenDockWindow"] = "Property editor"; App::Application::Config()["SplashAlignment" ] = "Bottom|Left"; App::Application::Config()["SplashTextColor" ] = "#ffffff"; // white App::Application::Config()["SplashInfoColor" ] = "#c8c8c8"; // light grey try { // Init phase =========================================================== // sets the default run mode for FC, starts with gui if not overridden in InitConfig... App::Application::Config()["RunMode"] = "Gui"; // Inits the Application #if defined (FC_OS_WIN32) App::Application::init(argc_, argv_.data()); #else App::Application::init(argc, argv); #endif #if defined(_MSC_VER) // create a dump file when the application crashes std::string dmpfile = App::Application::getUserAppDataDir(); dmpfile += "crash.dmp"; InitMiniDumpWriter(dmpfile); #endif std::map<std::string, std::string>::iterator it = App::Application::Config().find("NavigationStyle"); if (it != App::Application::Config().end()) { ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View"); // if not already defined do it now (for the very first start) std::string style = hGrp->GetASCII("NavigationStyle", it->second.c_str()); hGrp->SetASCII("NavigationStyle", style.c_str()); } Gui::Application::initApplication(); // Only if 'RunMode' is set to 'Gui' do the replacement if (App::Application::Config()["RunMode"] == "Gui") Base::Interpreter().replaceStdOutput(); } catch (const Base::UnknownProgramOption& e) { QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromLatin1(e.what()); QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>"); QMessageBox::critical(0, appName, s); exit(1); } catch (const Base::ProgramInformation& e) { QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QString::fromLatin1(e.what()); QString s = QLatin1String("<pre>") + msg + QLatin1String("</pre>"); QMessageBox::information(0, appName, s); exit(0); } catch (const Base::Exception& e) { // Popup an own dialog box instead of that one of Windows QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg; msg = QObject::tr("While initializing %1 the following exception occurred: '%2'\n\n" "Python is searching for its files in the following directories:\n%3\n\n" "Python version information:\n%4\n") .arg(appName).arg(QString::fromUtf8(e.what())) .arg(QString::fromUtf8(Py_GetPath())).arg(QString::fromLatin1(Py_GetVersion())); const char* pythonhome = getenv("PYTHONHOME"); if (pythonhome) { msg += QObject::tr("\nThe environment variable PYTHONHOME is set to '%1'.") .arg(QString::fromUtf8(pythonhome)); msg += QObject::tr("\nSetting this environment variable might cause Python to fail. " "Please contact your administrator to unset it on your system.\n\n"); } else { msg += QObject::tr("\nPlease contact the application's support team for more information.\n\n"); } QMessageBox::critical(0, QObject::tr("Initialization of %1 failed").arg(appName), msg); exit(100); } catch (...) { // Popup an own dialog box instead of that one of Windows QApplication app(argc,argv); QString appName = QString::fromLatin1(App::Application::Config()["ExeName"].c_str()); QString msg = QObject::tr("Unknown runtime error occurred while initializing %1.\n\n" "Please contact the application's support team for more information.\n\n").arg(appName); QMessageBox::critical(0, QObject::tr("Initialization of %1 failed").arg(appName), msg); exit(101); } // Run phase =========================================================== Base::RedirectStdOutput stdcout; Base::RedirectStdLog stdclog; Base::RedirectStdError stdcerr; std::streambuf* oldcout = std::cout.rdbuf(&stdcout); std::streambuf* oldclog = std::clog.rdbuf(&stdclog); std::streambuf* oldcerr = std::cerr.rdbuf(&stdcerr); try { if (App::Application::Config()["RunMode"] == "Gui") Gui::Application::runApplication(); else App::Application::runApplication(); } catch (const Base::SystemExitException& e) { exit(e.getExitCode()); } catch (const Base::Exception& e) { e.ReportException(); } catch (...) { Base::Console().Error("Application unexpectedly terminated\n"); } std::cout.rdbuf(oldcout); std::clog.rdbuf(oldclog); std::cerr.rdbuf(oldcerr); // Destruction phase =========================================================== Base::Console().Log("%s terminating...\n",App::Application::Config()["ExeName"].c_str()); // cleans up App::Application::destruct(); Base::Console().Log("%s completely terminated\n",App::Application::Config()["ExeName"].c_str()); return 0; }