--- a/src/file.cpp Mon Jul 01 17:27:37 2013 +0300 +++ b/src/file.cpp Mon Jul 01 19:48:29 2013 +0300 @@ -33,97 +33,107 @@ #include "dialogs.h" #include "gldraw.h" -cfg (str, io_ldpath, ""); -cfg (str, io_recentfiles, ""); +cfg( str, io_ldpath, "" ); +cfg( str, io_recentfiles, "" ); static bool g_loadingMainFile = false; +static const int g_MaxRecentFiles = 5; // ============================================================================= -namespace LDPaths { +namespace LDPaths +{ static str pathError; - struct { + struct + { str LDConfigPath; str partsPath, primsPath; } pathInfo; - void initPaths () { - if (!tryConfigure (io_ldpath)) { + void initPaths () + { + if( !tryConfigure ( io_ldpath )) + { LDrawPathDialog dlg (false); - if (!dlg.exec ()) - exit (0); + if( !dlg.exec () ) + exit( 0 ); - io_ldpath = dlg.filename (); + io_ldpath = dlg.filename(); } } - bool tryConfigure (str path) { + bool tryConfigure( str path ) + { QDir dir; - if (!dir.cd (path)) { + if( !dir.cd( path )) + { pathError = "Directory does not exist."; return false; } - QStringList mustHave = {"LDConfig.ldr", "parts", "p"}; - QStringList contents = dir.entryList (mustHave); + QStringList mustHave = { "LDConfig.ldr", "parts", "p" }; + QStringList contents = dir.entryList( mustHave ); if (contents.size () != mustHave.size ()) { pathError = "Not an LDraw directory! Must<br />have LDConfig.ldr, parts/ and p/."; return false; } - pathInfo.partsPath = fmt ("%1" DIRSLASH "parts", path); - pathInfo.LDConfigPath = fmt ("%1" DIRSLASH "LDConfig.ldr", path); - pathInfo.primsPath = fmt ("%1" DIRSLASH "p", path); + pathInfo.partsPath = fmt( "%1" DIRSLASH "parts", path ); + pathInfo.LDConfigPath = fmt( "%1" DIRSLASH "LDConfig.ldr", path ); + pathInfo.primsPath = fmt( "%1" DIRSLASH "p", path ); return true; } // Accessors - str getError () { return pathError; } - str ldconfig () { return pathInfo.LDConfigPath; } - str prims () { return pathInfo.primsPath; } - str parts () { return pathInfo.partsPath; } + str getError() { return pathError; } + str ldconfig() { return pathInfo.LDConfigPath; } + str prims() { return pathInfo.primsPath; } + str parts() { return pathInfo.partsPath; } } // ============================================================================= -LDOpenFile::LDOpenFile () { - setImplicit (true); - setSavePos (-1); - m_history.setFile (this); +LDOpenFile::LDOpenFile() +{ + setImplicit( true ); + setSavePos( -1 ); + m_history.setFile( this ); } // ============================================================================= -LDOpenFile::~LDOpenFile () { +LDOpenFile::~LDOpenFile() +{ // Clear everything from the model - for (LDObject* obj : m_objs) + for( LDObject* obj : m_objs ) delete obj; // Clear the cache as well - for (LDObject* obj : m_cache) + for( LDObject* obj : m_cache ) delete obj; } // ============================================================================= -LDOpenFile* findLoadedFile (str name) { - for (LDOpenFile* file : g_loadedFiles) - if (file->name () == name) +LDOpenFile* findLoadedFile( str name ) +{ + for( LDOpenFile* file : g_loadedFiles ) + if( file->name () == name ) return file; return null; } // ============================================================================= -str dirname (str path) { - long lastpos = path.lastIndexOf (DIRSLASH); +str dirname( str path ) { + long lastpos = path.lastIndexOf( DIRSLASH ); - if (lastpos > 0) - return path.left (lastpos); + if( lastpos > 0 ) + return path.left( lastpos ); #ifndef _WIN32 - if (path[0] == DIRSLASH_CHAR) + if( path[0] == DIRSLASH_CHAR ) return DIRSLASH; #endif // _WIN32 @@ -132,56 +142,62 @@ // ============================================================================= str basename (str path) { - long lastpos = path.lastIndexOf (DIRSLASH); + long lastpos = path.lastIndexOf( DIRSLASH ); - if (lastpos != -1) - return path.mid (lastpos + 1); + if( lastpos != -1 ) + return path.mid( lastpos + 1 ); return path; } // ============================================================================= File* openLDrawFile (str relpath, bool subdirs) { - print ("%1: Try to open %2\n", __func__, relpath); + print( "%1: Try to open %2\n", __func__, relpath ); File* f = new File; + // LDraw models use Windows-style path separators. If we're not on Windows, + // replace the path separator now before opening any files. #ifndef WIN32 - relpath.replace ("\\", "/"); + relpath.replace( "\\", "/" ); #endif // WIN32 - if (g_curfile != null) { + if( g_curfile ) + { + // First, try find the file in the current model's file path. We want a file + // in the immediate vicinity of the current model to override stock LDraw stuff. str partpath = fmt ("%1" DIRSLASH "%2", dirname (g_curfile->name ()), relpath); - print ("try %1\n", partpath); if (f->open (partpath, File::Read)) return f; } - print ("try %1\n", relpath); if (f->open (relpath, File::Read)) return f; str fullPath; - if (io_ldpath.value.length () > 0) { + if( io_ldpath.value.length() > 0 ) + { // Try with just the LDraw path first fullPath = fmt ("%1" DIRSLASH "%2", io_ldpath, relpath); - print ("try %1\n", fullPath); - if (f->open (fullPath, File::Read)) + if( f->open( fullPath, File::Read )) return f; - if (subdirs) { - for (auto subdir : initlist<const char*> ({"parts", "p"})) { + if( subdirs ) + { + // Look in sub-directories: parts and p + for( auto subdir : initlist<const str>({ "parts", "p" })) + { fullPath = fmt ("%1" DIRSLASH "%2" DIRSLASH "%3", io_ldpath, subdir, relpath); - printf ("try %s\n", qchars (fullPath)); if (f->open (fullPath, File::Read)) return f; } } } + // Did not find the file. delete f; return null; } @@ -189,45 +205,49 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -void FileLoader::work () { +void FileLoader::work() +{ m_progress = 0; abortflag = false; - for (str line : *PROP_NAME (file)) { + for( str line : *PROP_NAME( file )) { // Trim the trailing newline qchar c; - while ((c = line[line.length () - 1]) == '\n' || c == '\r') - line.chop (1); + while(( c = line[line.length () - 1] ) == '\n' || c == '\r' ) + line.chop( 1 ); - LDObject* obj = parseLine (line); - assert (obj != null); + LDObject* obj = parseLine( line ); // Check for parse errors and warn about tthem - if (obj->getType () == LDObject::Gibberish) { - logf (LOG_Warning, "Couldn't parse line #%lu: %s\n", - m_progress + 1, qchars (static_cast<LDGibberish*> (obj)->reason)); + if( obj->getType () == LDObject::Gibberish ) + { +/* + logf( LOG_Warning, "Couldn't parse line #%lu: %s\n", + m_progress + 1, qchars (static_cast<LDGibberish*> (obj)->reason )); logf (LOG_Warning, "- Line was: %s\n", qchars (line)); +*/ - if (m_warningsPointer) - (*m_warningsPointer)++; + if( m_warningsPointer ) + ( *m_warningsPointer )++; } m_objs << obj; m_progress++; - emit progressUpdate (m_progress); + emit progressUpdate( m_progress ); - if (abortflag) { + if( abortflag ) + { // We were flagged for abortion, so abort. - for (LDObject* obj : m_objs) + for( LDObject* obj : m_objs ) delete obj; - m_objs.clear (); + m_objs.clear(); return; } } - emit workDone (); + emit workDone(); m_done = true; } @@ -238,23 +258,22 @@ vector<str> lines; vector<LDObject*> objs; - if (numWarnings) + if( numWarnings ) *numWarnings = 0; FileLoader* loader = new FileLoader; - loader->setFile (f); - loader->setWarningsPointer (numWarnings); + loader->setFile( f ); + loader->setWarningsPointer( numWarnings ); // Calculate the amount of lines ulong numLines = 0; - for (str line : *f) { - (void) line; + for( str line : *f ) numLines++; - } + + f->rewind(); - f->rewind (); - - if (g_loadingMainFile) { + if (g_loadingMainFile) + { // Show a progress dialog if we're loading the main file here and move // the actual work to a separate thread as this can be a rather intensive // operation and if we don't respond quickly enough, the program can be @@ -262,32 +281,32 @@ // Init the thread and move the loader into it QThread* loaderThread = new QThread; - QObject::connect (loaderThread, SIGNAL (started ()), loader, SLOT (work ())); - QObject::connect (loaderThread, SIGNAL (finished ()), loader, SLOT (deleteLater ())); + QObject::connect( loaderThread, SIGNAL( started() ), loader, SLOT( work() )); + QObject::connect( loaderThread, SIGNAL( finished() ), loader, SLOT( deleteLater() )); loader->moveToThread (loaderThread); loaderThread->start (); - // Now create a progress dialog for the operation + // Now create a progress prompt for the operation OpenProgressDialog* dlg = new OpenProgressDialog (g_win); - dlg->setNumLines (numLines); + dlg->setNumLines( numLines ); - // Connect the loader in so we can actually show updates - QObject::connect (loader, SIGNAL (progressUpdate (int)), dlg, SLOT (updateProgress (int))); - QObject::connect (loader, SIGNAL (workDone ()), dlg, SLOT (accept ())); + // Connect the loader in so we can show updates + QObject::connect( loader, SIGNAL( progressUpdate( int )), dlg, SLOT( updateProgress( int ))); + QObject::connect( loader, SIGNAL( workDone() ), dlg, SLOT( accept() )); - // Show the dialog. If the user hits cancel, tell the loader to abort. - if (!dlg->exec ()) + // Show the prompt. If the user hits cancel, tell the loader to abort. + if( !dlg->exec() ) loader->abortflag = true; } else - loader->work (); + loader->work(); // If we wanted the success value, supply that now - if (ok) - *ok = loader->done (); + if( ok ) + *ok = loader->done(); // If the loader was done, return the objects it generated - if (loader->done ()) - objs = loader->objs (); + if( loader->done() ) + objs = loader->objs(); return objs; } @@ -295,39 +314,43 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -LDOpenFile* openDATFile (str path, bool search) { +LDOpenFile* openDATFile( str path, bool search ) +{ // Convert the file name to lowercase since some parts contain uppercase // file names. I'll assume here that the library will always use lowercase // file names for the actual parts.. File* f; - if (search) + if( search ) f = openLDrawFile (path.toLower (), true); else { - f = new File (path, File::Read); + f = new File( path, File::Read ); - if (!*f) { + if( !*f ) + { delete f; f = null; } } - if (!f) + if( !f ) return null; LDOpenFile* oldLoad = g_curfile; LDOpenFile* load = new LDOpenFile; - load->setName (path); + load->setName( path ); - if (g_loadingMainFile) { + if( g_loadingMainFile ) + { g_curfile = load; - g_win->R ()->setFile (load); + g_win->R()->setFile( load ); } ulong numWarnings; bool ok; vector<LDObject*> objs = loadFileContents (f, &numWarnings, &ok); - if (!ok) { + if( !ok ) + { load = oldLoad; return null; } @@ -338,8 +361,10 @@ delete f; g_loadedFiles << load; + /* logf ("File %s parsed successfully (%lu warning%s).\n", qchars (path), numWarnings, plural (numWarnings)); + */ return load; } @@ -347,34 +372,38 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -bool LDOpenFile::safeToClose () { - setlocale (LC_ALL, "C"); +bool LDOpenFile::safeToClose() +{ + typedef QMessageBox msgbox; + setlocale( LC_ALL, "C" ); // If we have unsaved changes, warn and give the option of saving. - if (!implicit () && history ().pos () != savePos ()) { - switch (QMessageBox::question (g_win, "Unsaved Changes", - fmt ("There are unsaved changes to %1. Should it be saved?", - (name ().length () > 0) ? name () : "<anonymous>"), - (QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel), QMessageBox::Cancel)) + if( !implicit() && history().pos() != savePos() ) + { + str message = fmt( "There are unsaved changes to %1. Should it be saved?", + (name().length() > 0) ? name() : "<anonymous>"); + switch( msgbox::question( g_win, "Unsaved Changes", message, + ( msgbox::Yes | msgbox::No | msgbox::Cancel ), msgbox::Cancel )) { - case QMessageBox::Yes: + case msgbox::Yes: // If we don't have a file path yet, we have to ask the user for one. - if (name ().length () == 0) { - str newpath = QFileDialog::getSaveFileName (g_win, "Save As", - g_curfile->name (), "LDraw files (*.dat *.ldr)"); + if( name().length() == 0 ) + { + str newpath = QFileDialog::getSaveFileName( g_win, "Save As", + g_curfile->name(), "LDraw files (*.dat *.ldr)" ); - if (newpath.length () == 0) + if( newpath.length() == 0 ) return false; - setName (newpath); + setName( newpath ); } - if (!save ()) { - str errormsg = fmt ("Failed to save %1: %2\nDo you still want to close?", - name (), strerror (errno)); + if( !save () ) { + message = fmt( "Failed to save %1: %2\nDo you still want to close?", + name(), strerror( errno )); - if (QMessageBox::critical (g_win, "Save Failure", errormsg, - (QMessageBox::Yes | QMessageBox::No), QMessageBox::No) == QMessageBox::No) + if( QMessageBox::critical( g_win, "Save Failure", message, + ( QMessageBox::Yes | QMessageBox::No ), QMessageBox::No ) == QMessageBox::No) { return false; } @@ -382,7 +411,7 @@ break; - case QMessageBox::Cancel: + case msgbox::Cancel: return false; default: @@ -396,180 +425,183 @@ // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -void closeAll () { - if (!g_loadedFiles.size()) +void closeAll() +{ + if( !g_loadedFiles.size() ) return; // Remove all loaded files and the objects they contain - for (LDOpenFile* file : g_loadedFiles) + for( LDOpenFile* file : g_loadedFiles ) delete file; // Clear the array g_loadedFiles.clear(); g_curfile = null; - g_win->R ()->setFile (null); - g_win->fullRefresh (); + g_win->R()->setFile (null); + g_win->fullRefresh(); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -void newFile () { - // Create a new anonymous file and set it to our current - closeAll (); +void newFile () +{ + closeAll(); + // Create a new anonymous file and set it to our current LDOpenFile* f = new LDOpenFile; - f->setName (""); - f->setImplicit (false); + f->setName( "" ); + f->setImplicit( false ); g_loadedFiles << f; g_curfile = f; - g_BBox.reset (); - g_win->R ()->setFile (f); - g_win->fullRefresh (); - g_win->updateTitle (); - f->history ().updateActions (); + g_BBox.reset(); + g_win->R()->setFile( f ); + g_win->fullRefresh(); + g_win->updateTitle(); + f->history().updateActions(); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -void addRecentFile (str path) { - QStringList rfiles = io_recentfiles.value.split ('@'); - - int idx = 0; +void addRecentFile( str path ) +{ + QStringList rfiles = io_recentfiles.value.split( '@' ); - for (str& it : rfiles) { - if (it == path) - break; - - idx++; - } + int idx = rfiles.indexOf( path ); // If this file already is in the list, pop it out. - if (idx != rfiles.size ()) { - if (rfiles.size () == 1) - return; // only recent file - do nothing + if( idx != -1 ) + { + if( rfiles.size () == 1 ) + return; // only recent file - abort and do nothing // Pop it out. - rfiles.removeAt (idx); + rfiles.removeAt( idx ); } // If there's too many recent files, drop one out. - while (rfiles.size () > (5 - 1)) - rfiles.removeAt (0); + while( rfiles.size() > ( g_MaxRecentFiles - 1 )) + rfiles.removeAt( 0 ); // Add the file - rfiles.push_back (path); + rfiles.push_back( path ); // Rebuild the config string - io_recentfiles = rfiles.join ("@"); + io_recentfiles = rfiles.join( "@" ); - config::save (); - g_win->updateRecentFilesMenu (); + config::save(); + g_win->updateRecentFilesMenu(); } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ----------------------------------------------------------------------------- +// Open an LDraw file and set it as the main model // ============================================================================= -void openMainFile (str path) { +void openMainFile( str path ) +{ g_loadingMainFile = true; - closeAll (); + closeAll(); - LDOpenFile* file = openDATFile (path, false); + LDOpenFile* file = openDATFile( path, false ); - if (!file) { + if (!file) + { // Loading failed, thus drop down to a new file since we // closed everything prior. newFile (); // Tell the user loading failed. - setlocale (LC_ALL, "C"); - critical (fmt ("Failed to open %1: %2", path, strerror (errno))); + setlocale( LC_ALL, "C" ); + critical( fmt( "Failed to open %1: %2", path, strerror( errno ))); g_loadingMainFile = false; return; } - file->setImplicit (false); + file->setImplicit( false ); g_curfile = file; // Recalculate the bounding box g_BBox.calculate(); // Rebuild the object tree view now. - g_win->fullRefresh (); - g_win->updateTitle (); - g_win->R ()->setFile (file); - g_win->R ()->resetAngles (); + g_win->fullRefresh(); + g_win->updateTitle(); + g_win->R()->setFile( file ); + g_win->R()->resetAngles(); // Add it to the recent files list. - addRecentFile (path); + addRecentFile( path ); g_loadingMainFile = false; } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -bool LDOpenFile::save (str savepath) { - if (!savepath.length ()) - savepath = name (); +bool LDOpenFile::save( str savepath ) +{ + if( !savepath.length() ) + savepath = name(); - File f (savepath, File::Write); + File f( savepath, File::Write ); - if (!f) + if( !f ) return false; // If the second object in the list holds the file name, update that now. // Only do this if the file is explicitly open. If it's saved into a directory // called "s" or "48", prepend that into the name. LDComment* fpathComment = null; - if (!implicit () && objs ().size () >= 2 && object (1)->getType () == LDObject::Comment) { - fpathComment = static_cast<LDComment*> (object (1)); + LDObject* first = object( 1 ); + if( !implicit() && first != null && first->getType() == LDObject::Comment ) + { + fpathComment = static_cast<LDComment*>( first ); - if (fpathComment->text.left (6) == "Name: ") { - str newfname; - str dir = basename (dirname (savepath)); + if( fpathComment->text.left( 6 ) == "Name: " ) { + str newname; + str dir = basename( dirname( savepath )); - if (dir == "s" || dir == "48") - newfname = dir + "\\"; + if( dir == "s" || dir == "48" ) + newname = dir + "\\"; - newfname += basename (savepath); - fpathComment->text = fmt ("Name: %1", newfname); - g_win->buildObjList (); + newname += basename( savepath ); + fpathComment->text = fmt( "Name: %1", newname ); + g_win->buildObjList(); } } - // Write all entries now - for (LDObject* obj : objs ()) { - // LDraw requires files to have DOS line endings - f.write (obj->raw () + "\r\n"); - } + // File is open, now save the model to it. Note that LDraw requires files to + // have DOS line endings, so we terminate the lines with \r\n. + for( LDObject* obj : objs() ) + f.write( obj->raw () + "\r\n" ); - f.close (); + // File is saved, now clean up. + f.close(); // We have successfully saved, update the save position now. - setSavePos (history ().pos ()); - setName (savepath); + setSavePos( history().pos() ); + setName( savepath ); - g_win->updateTitle (); + g_win->updateTitle(); return true; } -#define CHECK_TOKEN_COUNT(N) \ - if (tokens.size() != N) \ - return new LDGibberish (line, "Bad amount of tokens"); +// ============================================================================= +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ============================================================================= +#define CHECK_TOKEN_COUNT( N ) \ + if( tokens.size() != N ) \ + return new LDGibberish( line, "Bad amount of tokens" ); -#define CHECK_TOKEN_NUMBERS(MIN,MAX) \ +#define CHECK_TOKEN_NUMBERS( MIN, MAX ) \ for (ushort i = MIN; i <= MAX; ++i) \ if (!isNumber (tokens[i])) \ return new LDGibberish (line, fmt ("Token #%1 was `%2`, expected a number", \ (i + 1), tokens[i])); -// ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// ============================================================================= static vertex parseVertex( QStringList& s, const ushort n ) { vertex v; @@ -580,31 +612,35 @@ } // ============================================================================= -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// ----------------------------------------------------------------------------- +// This is the LDraw code parser function. It takes in a string containing LDraw +// code and returns the object parsed from it. parseLine never returns null, +// the object will be LDGibberish if it could not be parsed properly. // ============================================================================= -LDObject* parseLine (str line) { - QStringList tokens = line.split (" ", str::SkipEmptyParts); +LDObject* parseLine( str line ) +{ + QStringList tokens = line.split( " ", str::SkipEmptyParts ); - if (!tokens.size ()) { + if( tokens.size() <= 0 ) + { // Line was empty, or only consisted of whitespace return new LDEmpty; } - if (tokens[0].length () != 1) + if( tokens[0].length() != 1 ) return new LDGibberish (line, "Illogical line code"); - const qchar c = tokens[0][0]; - switch (c.toAscii () - '0') { + int num = tokens[0][0].toAscii() - '0'; + switch( num ) + { case 0: { // Comment - str comm; - for (int i = 1; i < tokens.size(); ++i) { - comm += tokens[i]; - - if (i != tokens.size() - 1) - comm += ' '; - } + str comm = line.mid( line.indexOf( "0" ) + 1 ); + + // Remove any leading whitespace + while( comm[0] == ' ' ) + comm.remove( 0, 1 ); // Handle BFC statements if (tokens.size() > 2 && tokens[1] == "BFC") { @@ -619,10 +655,11 @@ return new LDBFC (LDBFC::InvertNext); } - if (tokens.size() > 2 && tokens[1] == "!LDFORGE") { - // Handle LDForge-specific types, they're embedded into comments - - if (tokens[2] == "VERTEX") { + if( tokens.size() > 2 && tokens[1] == "!LDFORGE" ) + { + // Handle LDForge-specific types, they're embedded into comments too + if( tokens[2] == "VERTEX" ) + { // Vertex (0 !LDFORGE VERTEX) CHECK_TOKEN_COUNT (7) CHECK_TOKEN_NUMBERS (3, 6) @@ -636,40 +673,45 @@ return obj; } - if (tokens[2] == "RADIAL") { + if( tokens[2] == "RADIAL" ) + { CHECK_TOKEN_COUNT (20) CHECK_TOKEN_NUMBERS (4, 19) - LDRadial::Type eType = LDRadial::NumTypes; + LDRadial::Type radtype = LDRadial::NumTypes; - for (int i = 0; i < LDRadial::NumTypes; ++i) { - if (str (LDRadial::radialTypeName ((LDRadial::Type) i)).toUpper ().remove (' ') == tokens[3]) { - eType = (LDRadial::Type) i; + for( int i = 0; i < LDRadial::NumTypes; ++i ) + { + str radname = LDRadial::radialTypeName( (LDRadial::Type) i ); + if( radname.toUpper().remove( ' ' ) == tokens[3] ) + { + radtype = (LDRadial::Type) i; break; } } - if (eType == LDRadial::NumTypes) + if ( radtype == LDRadial::NumTypes) return new LDGibberish (line, fmt ("Unknown radial type %1", tokens[3])); LDRadial* obj = new LDRadial; - obj->setType (eType); - obj->setColor (tokens[4].toLong ()); - obj->setSegments (tokens[5].toLong ()); - obj->setDivisions (tokens[6].toLong ()); - obj->setNumber (tokens[7].toLong ()); - obj->setPosition (parseVertex (tokens, 8)); // 8 - 10 + obj->setType( radtype ); + obj->setColor( tokens[4].toLong() ); + obj->setSegments( tokens[5].toLong() ); + obj->setDivisions( tokens[6].toLong() ); + obj->setNumber( tokens[7].toLong() ); + obj->setPosition( parseVertex( tokens, 8 )); // 8 - 10 matrix transform; - for (short i = 0; i < 9; ++i) - transform[i] = tokens[i + 11].toDouble (); // 11 - 19 + for( short i = 0; i < 9; ++i ) + transform[i] = tokens[i + 11].toDouble(); // 11 - 19 - obj->setTransform (transform); + obj->setTransform( transform ); return obj; } } + // Just a regular comment: LDComment* obj = new LDComment; obj->text = comm; return obj; @@ -678,106 +720,93 @@ case 1: { // Subfile - CHECK_TOKEN_COUNT (15) - CHECK_TOKEN_NUMBERS (1, 13) + CHECK_TOKEN_COUNT( 15 ) + CHECK_TOKEN_NUMBERS( 1, 13 ) // Try open the file. Disable g_loadingMainFile temporarily since we're // not loading the main file now, but the subfile in question. bool tmp = g_loadingMainFile; g_loadingMainFile = false; - LDOpenFile* load = getFile (tokens[14]); + LDOpenFile* load = getFile( tokens[14] ); g_loadingMainFile = tmp; // If we cannot open the file, mark it an error - if (!load) - return new LDGibberish (line, "Could not open referred file"); + if( !load ) + return new LDGibberish( line, "Could not open referred file" ); LDSubfile* obj = new LDSubfile; - obj->setColor (tokens[1].toLong ()); - obj->setPosition (parseVertex (tokens, 2)); // 2 - 4 + obj->setColor( tokens[1].toLong() ); + obj->setPosition( parseVertex(tokens, 2 )); // 2 - 4 matrix transform; - for (short i = 0; i < 9; ++i) - transform[i] = tokens[i + 5].toDouble (); // 5 - 13 + for( short i = 0; i < 9; ++i ) + transform[i] = tokens[i + 5].toDouble(); // 5 - 13 - obj->setTransform (transform); - obj->setFileInfo (load); + obj->setTransform( transform ); + obj->setFileInfo( load ); return obj; } case 2: { - CHECK_TOKEN_COUNT (8) - CHECK_TOKEN_NUMBERS (1, 7) + CHECK_TOKEN_COUNT( 8 ) + CHECK_TOKEN_NUMBERS( 1, 7 ) // Line LDLine* obj = new LDLine; - obj->setColor (tokens[1].toLong ()); - for (short i = 0; i < 2; ++i) - obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 7 + obj->setColor( tokens[1].toLong() ); + for( short i = 0; i < 2; ++i ) + obj->setVertex( i, parseVertex( tokens, 2 + ( i * 3 ))); // 2 - 7 return obj; } case 3: { - CHECK_TOKEN_COUNT (11) - CHECK_TOKEN_NUMBERS (1, 10) + CHECK_TOKEN_COUNT( 11 ) + CHECK_TOKEN_NUMBERS( 1, 10 ) // Triangle LDTriangle* obj = new LDTriangle; - obj->setColor (tokens[1].toLong ()); + obj->setColor( tokens[1].toLong() ); - for (short i = 0; i < 3; ++i) - obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 10 + for( short i = 0; i < 3; ++i ) + obj->setVertex( i, parseVertex( tokens, 2 + ( i * 3 ))); // 2 - 10 return obj; } case 4: - { - CHECK_TOKEN_COUNT (14) - CHECK_TOKEN_NUMBERS (1, 13) - - // Quadrilateral - LDQuad* obj = new LDQuad; - obj->setColor (tokens[1].toLong ()); - - for (short i = 0; i < 4; ++i) - obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 13 - - return obj; - } - case 5: { - CHECK_TOKEN_COUNT (14) - CHECK_TOKEN_NUMBERS (1, 13) + CHECK_TOKEN_COUNT( 14 ) + CHECK_TOKEN_NUMBERS( 1, 13 ) - // Conditional line - LDCondLine* obj = new LDCondLine; - obj->setColor (tokens[1].toLong ()); + // Quadrilateral / Conditional line + LDObject* obj = ( num == 4 ) ? ( (LDObject*) new LDQuad ) : ( (LDObject*) new LDCondLine ); + obj->setColor( tokens[1].toLong() ); - for (short i = 0; i < 4; ++i) - obj->setVertex (i, parseVertex (tokens, 2 + (i * 3))); // 2 - 13 + for( short i = 0; i < 4; ++i ) + obj->setVertex( i, parseVertex( tokens, 2 + ( i * 3 ))); // 2 - 13 return obj; } default: // Strange line we couldn't parse - return new LDGibberish (line, "Unknown line code number"); + return new LDGibberish( line, "Unknown line code number" ); } } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -LDOpenFile* getFile (str fname) { +LDOpenFile* getFile( str fname ) +{ // Try find the file in the list of loaded files - LDOpenFile* load = findLoadedFile (fname); + LDOpenFile* load = findLoadedFile( fname ); // If it's not loaded, try open it - if (!load) - load = openDATFile (fname, true); + if( !load ) + load = openDATFile( fname, true ); return load; } @@ -786,80 +815,81 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void reloadAllSubfiles () { - if (!g_curfile) + if( !g_curfile ) return; - g_loadedFiles.clear (); + g_loadedFiles.clear(); g_loadedFiles << g_curfile; // Go through all objects in the current file and reload the subfiles - for (LDObject* obj : g_curfile->objs ()) { - if (obj->getType() == LDObject::Subfile) { - LDSubfile* ref = static_cast<LDSubfile*> (obj); - LDOpenFile* fileInfo = getFile (ref->fileInfo ()->name ()); + for( LDObject* obj : g_curfile->objs() ) + { + if( obj->getType() == LDObject::Subfile ) + { + LDSubfile* ref = static_cast<LDSubfile*>( obj ); + LDOpenFile* fileInfo = getFile( ref->fileInfo()->name() ); if (fileInfo) - ref->setFileInfo (fileInfo); - else { - // Couldn't load the file, mark it an error - ref->replace (new LDGibberish (ref->raw (), "Could not open referred file")); - } + ref->setFileInfo( fileInfo ); + else + ref->replace( new LDGibberish( ref->raw(), "Could not open referred file" )); } // Reparse gibberish files. It could be that they are invalid because // of loading errors. Circumstances may be different now. - if (obj->getType () == LDObject::Gibberish) - obj->replace (parseLine (static_cast<LDGibberish*> (obj)->contents)); + if( obj->getType() == LDObject::Gibberish ) + obj->replace( parseLine( static_cast<LDGibberish*>( obj )->contents )); } // Close all files left unused - LDOpenFile::closeUnused (); + LDOpenFile::closeUnused(); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -ulong LDOpenFile::addObject (LDObject* obj) { - PROP_NAME (history).add (new AddHistory (PROP_NAME (objs).size (), obj)); - PROP_NAME (objs) << obj; +ulong LDOpenFile::addObject (LDObject* obj) +{ + PROP_NAME( history ).add( new AddHistory( PROP_NAME( objs ).size(), obj )); + PROP_NAME( objs ) << obj; - if (obj->getType () == LDObject::Vertex) - PROP_NAME (vertices) << obj; + if( obj->getType() == LDObject::Vertex ) + PROP_NAME( vertices ) << obj; - if (this == g_curfile) - g_BBox.calcObject (obj); + if( this == g_curfile ) + g_BBox.calcObject( obj ); - return numObjs () - 1; + return numObjs() - 1; } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= void LDOpenFile::insertObj (const ulong pos, LDObject* obj) { - m_history.add (new AddHistory (pos, obj)); - m_objs.insert (pos, obj); + m_history.add( new AddHistory( pos, obj )); + m_objs.insert( pos, obj ); - if (this == g_curfile) - g_BBox.calcObject (obj); + if( this == g_curfile ) + g_BBox.calcObject( obj ); } // ============================================================================= // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // ============================================================================= -void LDOpenFile::forgetObject (LDObject* obj) { - ulong idx = obj->getIndex (this); - m_history.add (new DelHistory (idx, obj)); - m_objs.erase (idx); +void LDOpenFile::forgetObject( LDObject* obj ) { + ulong idx = obj->getIndex( this ); + m_history.add( new DelHistory( idx, obj )); + m_objs.erase( idx ); // Update the bounding box - if (this == g_curfile) + if( this == g_curfile ) g_BBox.calculate (); } // ============================================================================= bool safeToCloseAll () { - for (LDOpenFile* f : g_loadedFiles) - if (!f->safeToClose ()) + for( LDOpenFile* f : g_loadedFiles ) + if( !f->safeToClose() ) return false; return true; @@ -867,11 +897,12 @@ // ============================================================================= void LDOpenFile::setObject (ulong idx, LDObject* obj) { - assert (idx < numObjs ()); + assert( idx < numObjs() ); - str oldcode = m_objs[idx]->raw (); - str newcode = obj->raw (); - m_history << new EditHistory (idx, oldcode, newcode); + // Mark this change to history + str oldcode = object( idx )->raw (); + str newcode = obj->raw(); + m_history << new EditHistory( idx, oldcode, newcode ); m_objs[idx] = obj; } @@ -879,13 +910,14 @@ static vector<LDOpenFile*> getFilesUsed (LDOpenFile* node) { vector<LDOpenFile*> filesUsed; - for (LDObject* obj : *node) { - if (obj->getType () != LDObject::Subfile) + for (LDObject* obj : *node) + { + if( obj->getType() != LDObject::Subfile ) continue; - LDSubfile* ref = static_cast<LDSubfile*> (obj); - filesUsed << ref->fileInfo (); - filesUsed << getFilesUsed (ref->fileInfo ()); + LDSubfile* ref = static_cast<LDSubfile*>( obj ); + filesUsed << ref->fileInfo(); + filesUsed << getFilesUsed( ref->fileInfo() ); } return filesUsed; @@ -893,32 +925,44 @@ // ============================================================================= // Find out which files are unused and close them. -void LDOpenFile::closeUnused () { +void LDOpenFile::closeUnused () +{ vector<LDOpenFile*> filesUsed = getFilesUsed (g_curfile); - // Also, anything that's explicitly opened must not be closed - for (LDOpenFile* file : g_loadedFiles) - if (file->implicit () == false) + // Anything that's explicitly opened must not be closed + for( LDOpenFile* file : g_loadedFiles ) + if( !file->implicit() ) filesUsed << file; // Remove duplicated entries - filesUsed.makeUnique (); + filesUsed.makeUnique(); // Close all open files that aren't in filesUsed - for (LDOpenFile* file : g_loadedFiles) { + for( LDOpenFile* file : g_loadedFiles ) + { bool isused = false; - for (LDOpenFile* usedFile : filesUsed) { - if (file == usedFile) { + for( LDOpenFile* usedFile : filesUsed ) + { + if( file == usedFile ) + { isused = true; break; } } - if (!isused) + if( !isused ) delete file; } - g_loadedFiles.clear (); + g_loadedFiles.clear(); g_loadedFiles << filesUsed; +} + +LDObject* LDOpenFile::object( ulong pos ) const +{ + if( m_objs.size() <= pos ) + return null; + + return m_objs[pos]; } \ No newline at end of file