#include "project.h" #include "editor.h" #include "mainwindow.h" #include "utils.h" #include "systemconsts.h" #include "editorlist.h" #include #include "utils.h" #include #include #include #include #include "settings.h" Project::Project(const QString &filename, const QString &name, QObject *parent) : QObject(parent) { mFilename = filename; mIniFile = std::make_shared(filename,QSettings::IniFormat); mParser = std::make_shared(); mParser->setOnGetFileStream( std::bind( &EditorList::getContentFromOpenedEditor,pMainWindow->editorList(), std::placeholders::_1, std::placeholders::_2)); resetCppParser(mParser); if (name == DEV_INTERNAL_OPEN) open(); else { mName = name; mIniFile->beginGroup("Project"); mIniFile->setValue("filename", mFilename); mIniFile->setValue("name", mName); mIniFile->endGroup(); mNode = makeProjectNode(); } } QString Project::directory() const { QFileInfo fileInfo(mFilename); return fileInfo.absolutePath(); } QString Project::executable() const { QString exeFileName; if (mOptions.overrideOutput && !mOptions.overridenOutput.isEmpty()) { exeFileName = mOptions.overridenOutput; } else { switch(mOptions.type) { case ProjectType::StaticLib: exeFileName = changeFileExt(extractFileName(mFilename),STATIC_LIB_EXT); break; case ProjectType::DynamicLib: exeFileName = changeFileExt(extractFileName(mFilename),DYNAMIC_LIB_EXT); break; default: exeFileName = changeFileExt(extractFileName(mFilename),EXECUTABLE_EXT); } } QString exePath; if (!mOptions.exeOutput.isEmpty()) { QDir baseDir(directory()); exePath = baseDir.filePath(mOptions.exeOutput); } else { exePath = directory(); } QDir exeDir(exePath); return exeDir.filePath(exeFileName); } QString Project::makeFileName() { if (mOptions.useCustomMakefile) return mOptions.customMakefile; else return QDir(directory()).filePath(MAKEFILE_NAME); } bool Project::modified() const { // Project file modified? Done if (mModified) return true;// quick exit avoids loop over all units // Otherwise, check all units foreach (const PProjectUnit& unit, mUnits){ if (unit->modified()) return true; } return false; } void Project::open() { QFile fileInfo(mFilename); if (fileInfo.exists() && !fileInfo.isWritable()) { if (QMessageBox::question(pMainWindow, tr("Remove Readonly Attribute"), tr("Project file '%1' is readonly.
Remove the readonly attribute?") .arg(mFilename), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) { fileInfo.setPermissions( QFileDevice::WriteOwner | QFileDevice::WriteGroup | QFileDevice::WriteUser ); } } loadOptions(); mNode = makeProjectNode(); checkProjectFileForUpdate(); mIniFile->beginGroup("Project"); int uCount = mIniFile->value("UnitCount",0).toInt(); mIniFile->endGroup(); //createFolderNodes; QDir dir(directory()); for (int i=0;i(); mIniFile->beginGroup(QString("Unit%1").arg(i)); newUnit->setFileName(dir.filePath(mIniFile->value("FileName","").toString())); if (!QFileInfo(newUnit->fileName()).exists()) { QMessageBox::critical(pMainWindow, tr("File Not Found"), tr("Project file '%1' can't be found!") .arg(newUnit->fileName()), QMessageBox::Ok); newUnit->setModified(true); } else { newUnit->setFolder(mIniFile->value("Folder","").toString()); newUnit->setCompile(mIniFile->value("Compile", true).toBool()); newUnit->setCompileCpp( mIniFile->value("CompileCpp",mOptions.useGPP).toBool()); newUnit->setLink(mIniFile->value("Link", true).toBool()); newUnit->setPriority(mIniFile->value("Priority", 1000).toInt()); newUnit->setOverrideBuildCmd(mIniFile->value("OverrideBuildCmd", false).toInt()); newUnit->setBuildCmd(mIniFile->value("BuildCmd", "").toString()); newUnit->setDetectEncoding(mIniFile->value("DetectEncoding", mOptions.useUTF8).toBool()); newUnit->setEncoding(mIniFile->value("Encoding",ENCODING_SYSTEM_DEFAULT).toByteArray()); newUnit->setEditor(nullptr); newUnit->setNew(false); newUnit->setParent(this); newUnit->setNode(makeNewFileNode(extractFileName(newUnit->fileName()), false, folderNodeFromName(newUnit->folder()))); newUnit->node()->unitIndex = mUnits.count(); mUnits.append(newUnit); } mIniFile->endGroup(); } rebuildNodes(); } void Project::setFileName(const QString &value) { if (mFilename!=value) { mIniFile->sync(); mIniFile.reset(); QFile::copy(mFilename,value); mFilename = value; setModified(true); mIniFile = std::make_shared(mFilename, QSettings::IniFormat); } } void Project::setModified(bool value) { QFile file(mFilename); // only mark modified if *not* read-only if (!file.exists() || (file.exists() && file.isWritable())) { mModified=value; emit modifyChanged(mModified); } } PFolderNode Project::makeNewFileNode(const QString &s, bool isFolder, PFolderNode newParent) { PFolderNode node = std::make_shared(); node->parent = newParent; node->text = s; if (newParent) { node->level = newParent->level+1; } if (isFolder) node->unitIndex = -1; } PFolderNode Project::makeProjectNode() { PFolderNode node = std::make_shared(); node->text = mName; node->level = 0; } int Project::newUnit(PFolderNode parentNode, const QString customFileName) { PProjectUnit newUnit = std::make_shared(); // Select folder to add unit to if (!parentNode) parentNode = mNode; // project root node if (parentNode->unitIndex>=0) { //it's a file parentNode = mNode; } QString s; QDir dir(directory()); // Find unused 'new' filename if (customFileName.isEmpty()) { do { s = dir.absoluteFilePath(tr("untitled")+QString("%1").arg(getNewFileNumber())); } while (fileExists(s)); } else { s = dir.absoluteFilePath(customFileName); } // Add int result = mUnits.count(); mUnits.append(newUnit); // Set all properties newUnit->setFileName(s); newUnit->setNew(true); newUnit->setEditor(nullptr); newUnit->setFolder(getFolderPath(parentNode)); newUnit->setNode(makeNewFileNode(extractFileName(newUnit->fileName()), false, parentNode)); newUnit->node()->unitIndex = result; //parentNode.Expand(True); newUnit->setCompile(true); newUnit->setCompileCpp(mOptions.useGPP); newUnit->setLink(true); newUnit->setPriority(1000); newUnit->setOverrideBuildCmd(false); newUnit->setBuildCmd(""); newUnit->setModified(true); return result; } Editor *Project::openUnit(int index) { if ((index < 0) || (index >= mUnits.count())) return nullptr; PProjectUnit unit = mUnits[index]; if (!unit->fileName().isEmpty()) { QDir dir(directory()); QString fullPath = dir.absoluteFilePath(unit->fileName()); Editor * editor = pMainWindow->editorList()->getOpenedEditorByFilename(fullPath); if (editor) {//already opened in the editors editor->setInProject(true); return editor; } QByteArray encoding; if (mOptions.useUTF8) { encoding = ENCODING_UTF8; } else encoding = mOptions.encoding.toLocal8Bit(); editor = pMainWindow->editorList()->newEditor(fullPath, encoding, true, false); editor->setInProject(true); unit->setEditor(editor); unit->setEncoding(encoding); loadUnitLayout(editor,index); return editor; } } void Project::rebuildNodes() { // Remember if folder nodes were expanded or collapsed // Create a list of expanded folder nodes // QStringList oldPaths := TStringList.Create; // with MainForm.ProjectView do // for idx := 0 to Items.Count - 1 do begin // tempnode := Items[idx]; // if tempnode.Expanded and (tempnode.Data = Pointer(-1)) then // data=pointer(-1) - it's folder // oldPaths.Add(GetFolderPath(tempnode)); // end; // Delete everything mNode->children.clear(); // Recreate everything createFolderNodes(); for (int idx=0;idxsetNode( makeNewFileNode( extractRelativePath(filename(),mUnits[idx]->fileName()), false, folderNodeFromName(mUnits[idx]->folder()) ) ); mUnits[idx]->node()->unitIndex = idx; } // // expand nodes expanded before recreating the project tree // fNode.Collapse(True); // with MainForm.ProjectView do // for idx := 0 to Items.Count - 1 do begin // tempnode := Items[idx]; // if (tempnode.Data = Pointer(-1)) then //it's a folder // if oldPaths.IndexOf(GetFolderPath(tempnode)) >= 0 then // tempnode.Expand(False); // end; // FreeAndNil(oldPaths); // fNode.Expand(False); emit nodesChanged(); } bool Project::removeEditor(int index, bool doClose) { if (index<0 || index>=mUnits.count()) return false; PProjectUnit unit = mUnits[index]; // Attempt to close it if (doClose && (unit->editor())) { if (!pMainWindow->editorList()->closeEditor(unit->editor())) return false; } //if not fUnits.GetItem(index).fNew then mIniFile->remove("Unit"+QString("%1").arg(index+1)); PFolderNode node = unit->node(); PFolderNode parent = node->parent.lock(); if (parent) { parent->children.removeAll(node); } mUnits.removeAt(index); updateNodeIndexes(); setModified(true); return true; } bool Project::removeFolder(PFolderNode node) { return false; // Sanity check if (!node) return false; // Check if this is actually a folder if (node->unitIndex>=0 || node->level<1) return false; // Let this function call itself removeFolderRecurse(node); // Update list of folders (sets modified) updateFolders(); return true; } void Project::saveAll() { if (!saveUnits()) return; saveOptions(); // update other data, and save to disk saveLayout(); // save current opened files, and which is "active". // We have saved everything to disk, so mark unmodified setModified(false); } void Project::saveLayout() { QString s = changeFileExt(mFilename, "layout"); QSettings layIni(mFilename,QSettings::IniFormat); QStringList sl; // Write list of open project files for (int i=0;ieditorList()->pageCount();i++) { Editor* e= (*(pMainWindow->editorList()))[i]; if (e && e->inProject()) sl.append(QString("%1").arg(indexInUnits(e))); } layIni.beginGroup("Editors"); layIni.setValue("Order",sl.join(",")); Editor *e, *e2; // Remember what files were visible pMainWindow->editorList()->getVisibleEditors(e, e2); if (e) layIni.setValue("Focused", indexInUnits(e)); layIni.endGroup(); // save editor info for (int i=0;ieditor(); if (editor) { layIni.setValue("CursorCol", editor->caretX()); layIni.setValue("CursorRow", editor->caretY()); layIni.setValue("TopLine", editor->topLine()); layIni.setValue("LeftChar", editor->leftChar()); } layIni.endGroup(); // remove old data from project file mIniFile->beginGroup(QString("Unit%1").arg(i+1)); mIniFile->remove("Open"); mIniFile->remove("Top"); mIniFile->remove("CursorCol"); mIniFile->remove("CursorRow"); mIniFile->remove("TopLine"); mIniFile->remove("LeftChar"); mIniFile->endGroup(); } } void Project::saveOptions() { with finiFile do begin WriteString('Project', 'FileName', ExtractRelativePath(Directory, fFileName)); WriteString('Project', 'Name', fName); WriteInteger('Project', 'Type', fOptions.typ); WriteInteger('Project', 'Ver', 2); // Is 2 as of Dev-C++ 5.2.0.3 WriteString('Project', 'ObjFiles', fOptions.ObjFiles.DelimitedText); WriteString('Project', 'Includes', fOptions.Includes.DelimitedText); WriteString('Project', 'Libs', fOptions.Libs.DelimitedText); WriteString('Project', 'PrivateResource', fOptions.PrivateResource); WriteString('Project', 'ResourceIncludes', fOptions.ResourceIncludes.DelimitedText); WriteString('Project', 'MakeIncludes', fOptions.MakeIncludes.DelimitedText); WriteString('Project', 'Compiler', fOptions.CompilerCmd); WriteString('Project', 'CppCompiler', fOptions.CppCompilerCmd); WriteString('Project', 'Linker', fOptions.LinkerCmd); WriteBool('Project', 'IsCpp', fOptions.UseGpp); WriteString('Project', 'Icon', ExtractRelativePath(Directory, fOptions.Icon)); WriteString('Project', 'ExeOutput', fOptions.ExeOutput); WriteString('Project', 'ObjectOutput', fOptions.ObjectOutput); WriteString('Project', 'LogOutput', fOptions.LogOutput); WriteBool('Project', 'LogOutputEnabled', fOptions.LogOutputEnabled); WriteBool('Project', 'OverrideOutput', fOptions.OverrideOutput); WriteString('Project', 'OverrideOutputName', fOptions.OverridenOutput); WriteString('Project', 'HostApplication', fOptions.HostApplication); WriteBool('Project', 'UseCustomMakefile', fOptions.UseCustomMakefile); WriteString('Project', 'CustomMakefile', fOptions.CustomMakefile); WriteBool('Project', 'UsePrecompiledHeader', fOptions.UsePrecompiledHeader); WriteString('Project', 'PrecompiledHeader', fOptions.PrecompiledHeader); WriteString('Project', 'CommandLine', fOptions.CmdLineArgs); WriteString('Project', 'Folders', fFolders.CommaText); WriteBool('Project', 'IncludeVersionInfo', fOptions.IncludeVersionInfo); WriteBool('Project', 'SupportXPThemes', fOptions.SupportXPThemes); WriteInteger('Project', 'CompilerSet', fOptions.CompilerSet); WriteString('Project', 'CompilerSettings', fOptions.CompilerOptions); WriteBool('Project','StaticLink', fOptions.StaticLink); WriteBool('Project','AddCharset', fOptions.AddCharset); WriteBool('Project', 'UseUTF8', fOptions.UseUTF8); WriteInteger('VersionInfo', 'Major', fOptions.VersionInfo.Major); WriteInteger('VersionInfo', 'Minor', fOptions.VersionInfo.Minor); WriteInteger('VersionInfo', 'Release', fOptions.VersionInfo.Release); WriteInteger('VersionInfo', 'Build', fOptions.VersionInfo.Build); WriteInteger('VersionInfo', 'LanguageID', fOptions.VersionInfo.LanguageID); WriteInteger('VersionInfo', 'CharsetID', fOptions.VersionInfo.CharsetID); WriteString('VersionInfo', 'CompanyName', fOptions.VersionInfo.CompanyName); WriteString('VersionInfo', 'FileVersion', fOptions.VersionInfo.FileVersion); WriteString('VersionInfo', 'FileDescription', fOptions.VersionInfo.FileDescription); WriteString('VersionInfo', 'InternalName', fOptions.VersionInfo.InternalName); WriteString('VersionInfo', 'LegalCopyright', fOptions.VersionInfo.LegalCopyright); WriteString('VersionInfo', 'LegalTrademarks', fOptions.VersionInfo.LegalTrademarks); WriteString('VersionInfo', 'OriginalFilename', fOptions.VersionInfo.OriginalFilename); WriteString('VersionInfo', 'ProductName', fOptions.VersionInfo.ProductName); WriteString('VersionInfo', 'ProductVersion', fOptions.VersionInfo.ProductVersion); WriteBool('VersionInfo', 'AutoIncBuildNr', fOptions.VersionInfo.AutoIncBuildNr); WriteBool('VersionInfo', 'SyncProduct', fOptions.VersionInfo.SyncProduct); if fOptions.Ver <= 0 then begin //delete outdated dev4 project options DeleteKey('Project', 'NoConsole'); DeleteKey('Project', 'IsDLL'); DeleteKey('Project', 'ResFiles'); DeleteKey('Project', 'IncludeDirs'); DeleteKey('Project', 'CompilerOptions'); DeleteKey('Project', 'StaticLink'); DeleteKey('Project', 'StaticLink'); DeleteKey('Project', 'UseUTF8'); DeleteKey('Project', 'Use_GPP'); end; end; fINIFile.UpdateFile; // force flush } void Project::addFolder(const QString &s) { if (mFolders.indexOf(s)<0) { mFolders.append(s); rebuildNodes(); //todo: MainForm.ProjectView.Select(FolderNodeFromName(s)); //folderNodeFromName(s)->makeVisible(); setModified(true); } } PProjectUnit Project::addUnit(const QString &inFileName, PFolderNode parentNode, bool rebuild) { PProjectUnit newUnit; // Don't add if it already exists if (fileAlreadyExists(inFileName)) { QMessageBox::critical(pMainWindow, tr("File Exists"), tr("File '%1' is already in the project"), QMessageBox::Ok); return newUnit; } newUnit = std::make_shared(this); // Set all properties newUnit->setFileName(QDir(directory()).filePath(inFileName)); newUnit->setNew(false); newUnit->setEditor(nullptr); newUnit->setFolder(getFolderPath(parentNode)); newUnit->setNode(makeNewFileNode(extractFileName(newUnit->fileName()), false, parentNode)); newUnit->node()->unitIndex = mUnits.count(); mUnits.append(newUnit); // Determine compilation flags switch(getFileType(inFileName)) { case FileType::CSource: newUnit->setCompile(true); newUnit->setCompileCpp(mOptions.useGPP); newUnit->setLink(true); break; case FileType::CppSource: newUnit->setCompile(true); newUnit->setCompileCpp(true); newUnit->setLink(true); break; case FileType::WindowsResourceSource: newUnit->setCompile(true); newUnit->setCompileCpp(mOptions.useGPP); newUnit->setLink(false); break; default: newUnit->setCompile(false); newUnit->setCompileCpp(false); newUnit->setLink(false); } newUnit->setPriority(1000); newUnit->setOverrideBuildCmd(false); newUnit->setBuildCmd(""); if (rebuild) rebuildNodes(); setModified(true); return newUnit; } void Project::buildPrivateResource(bool forceSave) { int comp = 0; foreach (const PProjectUnit& unit,mUnits) { if ( (getFileType(unit->fileName()) == FileType::WindowsResourceSource) && unit->compile() ) comp++; } // if project has no other resources included // and does not have an icon // and does not include the XP style manifest // and does not include version info // then do not create a private resource file if ((comp == 0) && (! mOptions.supportXPThemes) && (! mOptions.includeVersionInfo) && (mOptions.icon == "")) { mOptions.privateResource=""; return; } // change private resource from .res // to _private.res // // in many cases (like in importing a MSVC project) // the project's resource file has already the // .res filename. QString rcFile; if (!mOptions.privateResource.isEmpty()) { rcFile = QDir(directory()).filePath(mOptions.privateResource); if (changeFileExt(rcFile, DEV_PROJECT_EXT) == mFilename) rcFile = changeFileExt(mFilename,QString("_private") + RC_EXT); } else rcFile = changeFileExt(mFilename,QString("_private") + RC_EXT); rcFile = extractRelativePath(mFilename, rcFile); rcFile.replace(' ','_'); // don't run the private resource file and header if not modified, // unless ForceSave is true if (!forceSave && fileExists(rcFile) && fileExists(changeFileExt(rcFile, H_EXT)) && !mModified) return; QStringList contents; contents.append("/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */"); contents.append("/* DO NOT EDIT! */"); contents.append(""); if (mOptions.includeVersionInfo) { contents.append("#include // include for version info constants"); contents.append(""); } foreach (const PProjectUnit& unit, mUnits) { if ( (getFileType(unit->fileName()) == FileType::WindowsResourceSource) && unit->compile() ) contents.append("#include \"" + genMakePath( extractRelativePath(directory(), unit->fileName()), false, false) + "\""); } if (!mOptions.icon.isEmpty()) { contents.append(""); QString icon = QDir(directory()).absoluteFilePath(mOptions.icon); if (fileExists(icon)) { icon = extractRelativePath(mFilename, icon); icon.replace('\\', '/'); contents.append("A ICON \"" + icon + '"'); } else mOptions.icon = ""; } if (mOptions.supportXPThemes) { contents.append(""); contents.append("//"); contents.append("// SUPPORT FOR WINDOWS XP THEMES:"); contents.append("// THIS WILL MAKE THE PROGRAM USE THE COMMON CONTROLS"); contents.append("// LIBRARY VERSION 6.0 (IF IT IS AVAILABLE)"); contents.append("//"); if (!mOptions.exeOutput.isEmpty()) contents.append( "1 24 \"" + genMakePath2( includeTrailingPathDelimiter(mOptions.exeOutput) + extractFileName(executable())) + ".Manifest\""); else contents.append("1 24 \"" + extractFileName(executable()) + ".Manifest\""); } if (mOptions.includeVersionInfo) { contents.append(""); contents.append("//"); contents.append("// TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS..."); contents.append("//"); contents.append("1 VERSIONINFO"); contents.append("FILEVERSION " + QString("%1,%2,%3,%4") .arg(mOptions.versionInfo.major) .arg(mOptions.versionInfo.minor) .arg(mOptions.versionInfo.release) .arg(mOptions.versionInfo.build)); contents.append("PRODUCTVERSION " + QString("%1,%2,%3,%4") .arg(mOptions.versionInfo.major) .arg(mOptions.versionInfo.minor) .arg(mOptions.versionInfo.release) .arg(mOptions.versionInfo.build)); switch(mOptions.type) { case ProjectType::GUI: case ProjectType::Console: contents.append("FILETYPE VFT_APP"); break; case ProjectType::StaticLib: contents.append("FILETYPE VFT_STATIC_LIB"); break; case ProjectType::DynamicLib: contents.append("FILETYPE VFT_DLL"); break; } contents.append("{"); contents.append(" BLOCK \"StringFileInfo\""); contents.append(" {"); contents.append(" BLOCK \"" + QString("%1%2") .arg(mOptions.versionInfo.languageID,4,16,QChar('0')) .arg(mOptions.versionInfo.charsetID,4,16,QChar('0')) + '"'); contents.append(" {"); contents.append(" VALUE \"CompanyName\", \"" + mOptions.versionInfo.companyName + "\""); contents.append(" VALUE \"FileVersion\", \"" + mOptions.versionInfo.fileVersion + "\""); contents.append(" VALUE \"FileDescription\", \"" + mOptions.versionInfo.fileDescription + "\""); contents.append(" VALUE \"InternalName\", \"" + mOptions.versionInfo.internalName + "\""); contents.append(" VALUE \"LegalCopyright\", \"" + mOptions.versionInfo.legalCopyright + '"'); contents.append(" VALUE \"LegalTrademarks\", \"" + mOptions.versionInfo.legalTrademarks + "\""); contents.append(" VALUE \"OriginalFilename\", \"" + mOptions.versionInfo.originalFilename + "\""); contents.append(" VALUE \"ProductName\", \"" + mOptions.versionInfo.productName + "\""); contents.append(" VALUE \"ProductVersion\", \"" + mOptions.versionInfo.productVersion + "\""); contents.append(" }"); contents.append(" }"); // additional block for windows 95->NT contents.append(" BLOCK \"VarFileInfo\""); contents.append(" {"); contents.append(" VALUE \"Translation\", " + QString("0x%1, %2") .arg(mOptions.versionInfo.languageID,4,16,QChar('0')) .arg(mOptions.versionInfo.charsetID)); contents.append(" }"); contents.append("}"); } rcFile = QDir(directory()).absoluteFilePath(rcFile); if (contents.count() > 3) { StringsToFile(contents,rcFile); mOptions.privateResource = extractRelativePath(directory(), rcFile); } else { if (fileExists(rcFile)) QFile::remove(rcFile); QString resFile = changeFileExt(rcFile, RES_EXT); if (fileExists(resFile)) QFile::remove(resFile); mOptions.privateResource = ""; } // if fileExists(Res) then // FileSetDate(Res, DateTimeToFileDate(Now)); // fix the "Clock skew detected" warning ;) // create XP manifest if (mOptions.supportXPThemes) { QStringList content; content.append(""); content.append(""); content.append(""); content.append("" + name + ""); content.append(""); content.append(" "); content.append(" "); content.append(" "); content.append(""); content.append(""); StringsToFile(content,executable() + ".Manifest"); } else if (fileExists(executable() + ".Manifest")) QFile::remove(executable() + ".Manifest"); // create private header file QString hFile = changeFileExt(rcFile, H_EXT); contents.clear(); QString def = extractFileName(rcFile); def.replace(".","_"); contents.append("/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */"); contents.append("/* DO NOT EDIT ! */"); contents.append(""); contents.append("#ifndef " + def); contents.append("#define " + def); contents.append(""); contents.append("/* VERSION DEFINITIONS */"); contents.append("#define VER_STRING\t" + QString("\"%d.%d.%d.%d\"") .arg(mOptions.versionInfo.major) .arg(mOptions.versionInfo.minor) .arg(mOptions.versionInfo.release) .arg(mOptions.versionInfo.build)); contents.append(QString("#define VER_MAJOR\t%1").arg(mOptions.versionInfo.major)); contents.append(QString("#define VER_MINOR\t%1").arg(mOptions.versionInfo.minor)); contents.append(QString("#define VER_RELEASE\t").arg(mOptions.versionInfo.release)); contents.append(QString("#define VER_BUILD\t").arg(mOptions.versionInfo.build)); contents.append(QString("#define COMPANY_NAME\t\"%1\"") .arg(mOptions.versionInfo.companyName)); contents.append(QString("#define FILE_VERSION\t\"%1\"") .arg(mOptions.versionInfo.fileVersion)); contents.append(QString("#define FILE_DESCRIPTION\t\"%1\"") .arg(mOptions.versionInfo.fileDescription)); contents.append(QString("#define INTERNAL_NAME\t\"%1\"") .arg(mOptions.versionInfo.internalName)); contents.append(QString("#define LEGAL_COPYRIGHT\t\"%1\"") .arg(mOptions.versionInfo.legalCopyright)); contents.append(QString("#define LEGAL_TRADEMARKS\t\"%1\"") .arg(mOptions.versionInfo.legalTrademarks)); contents.append(QString("#define ORIGINAL_FILENAME\t\"%1\"") .arg(mOptions.versionInfo.originalFilename)); contents.append(QString("#define PRODUCT_NAME\t\"%1\"") .arg(mOptions.versionInfo.productName)); contents.append(QString("#define PRODUCT_VERSION\t\"%1\"") .arg(mOptions.versionInfo.productVersion)); contents.append(""); contents.append("#endif /*" + def + "*/"); StringsToFile(contents,hFile); } void Project::checkProjectFileForUpdate() { bool cnvt = false; mIniFile->beginGroup("Project"); int uCount = mIniFile->value("UnitCount", 0).toInt(); mIniFile->endGroup(); // check if using old way to store resources and fix it QString oldRes = mIniFile->value("Resources", "").toString(); if (!oldRes.isEmpty()) { QFile::copy(mFilename,mFilename+".bak"); QStringList sl; sl = oldRes.split(';'); for (int i=0;ibeginGroup(QString("Unit%1").arg(uCount+i)); mIniFile->setValue("Filename", s); mIniFile->setValue("Folder", "Resources"); mIniFile->setValue("Compile",true); mIniFile->endGroup(); } mIniFile->beginGroup("Project"); mIniFile->setValue("UnitCount",uCount+sl.count()); QString folders = mIniFile->value("Folders","").toString(); if (!folders.isEmpty()) folders += ",Resources"; else folders = "Resources"; mIniFile->setValue("Folders",folders); mIniFile->endGroup(); } mIniFile->beginGroup("Project"); mIniFile->remove("Resources"); mIniFile->remove("Focused"); mIniFile->remove("Order"); mIniFile->remove("DebugInfo"); mIniFile->remove("ProfileInfo"); if (cnvt) QMessageBox::information( pMainWindow, tr("Project Updated"), tr("Your project was succesfully updated to a newer file format!") +"
" +tr("If something has gone wrong, we kept a backup-file: '%1'...") .arg(mFilename+".bak"), QMessageBox::Ok); } void Project::closeUnit(int index) { PProjectUnit unit = mUnits[index]; if (unit->editor()) { saveUnitLayout(unit->editor(),index); pMainWindow->editorList()->forceCloseEditor(unit->editor()); unit->setEditor(nullptr); } } void Project::createFolderNodes() { mFolderNodes.clear(); for (int idx=0;idx=0) { PFolderNode findnode; for (int c=0;cchildren.count();c++) { if (node->children[c]->text == s.mid(0,i)) findnode = node->children[c]; } if (!findnode) node = makeNewFileNode(s.mid(0,i),true,node); else node = findnode; node->unitIndex = -1; s.remove(0,i); i = s.indexOf('/'); } node = makeNewFileNode(s, true, node); node->unitIndex = -1; mFolderNodes.append(node); } } void Project::doAutoOpen() { //todo: // case devData.AutoOpen of // 0: begin // for i := 0 to pred(fUnits.Count) do // OpenUnit(i); // Open all // if fUnits.Count > 0 then // fUnits[0].Editor.Activate; // Show first // end; // 1: // if fUnits.Count > 0 then // OpenUnit(0).Activate; // Open and show first // 2: // LoadLayout; // Open previous selection // end; } bool Project::fileAlreadyExists(const QString &s) { foreach (const PProjectUnit& unit, mUnits) { if (unit->fileName() == s) return true; } return false; } PFolderNode Project::folderNodeFromName(const QString &name) { int index = mFolders.indexOf(name); if (index>=0) { return mFolderNodes[index]; } return mNode; } QChar Project::getCompilerOption(const QString &optionString) { // Does the option exist? Settings::PCompilerSet compilerSet = pSettings->compilerSets().getSet(mOptions.compilerSet); if (!compilerSet) return '0'; int index = compilerSet->findOptionIndex(optionString); if (index>=0 && indexunitIndex>=0) // not a folder return result; PFolderNode p = node; while (p && p->unitIndex==-1) { if (!result.isEmpty()) result = p->text + "/" + result; p = p->parent.lock(); } return result; } int Project::getUnitFromString(const QString &s) { return indexInUnits(s); } void Project::incrementBuildNumber() { mOptions.versionInfo.build++; mOptions.versionInfo.fileVersion = QString("%1.%2.%3.%3") .arg(mOptions.versionInfo.major) .arg(mOptions.versionInfo.minor) .arg(mOptions.versionInfo.release) .arg(mOptions.versionInfo.build); if (mOptions.versionInfo.syncProduct) mOptions.versionInfo.productVersion = mOptions.versionInfo.fileVersion; setModified(true); } QString Project::listUnitStr(const QChar &separator) { QStringList units; foreach (const PProjectUnit& unit, mUnits) { units.append('"'+unit->fileName()+'"'); } return units.join(separator); } void Project::loadLayout() { QSettings layIni = QSettings(changeFileExt(filename(), "layout"),QSettings::IniFormat); layIni.beginGroup("Editors"); int topLeft = layIni.value("Focused", -1).toInt(); //TopRight := layIni.ReadInteger('Editors', 'FocusedRight', -1); QString temp =layIni.value("Order", "").toString(); layIni.endGroup(); QStringList sl = temp.split(","); foreach (const QString& s,sl) { bool ok; int currIdx = s.toInt(&ok); if (ok) { openUnit(currIdx); } } if (topLeft>=0 && topLefteditor()) { mUnits[topLeft]->editor()->activate(); } } void Project::loadOptions() { mIniFile->beginGroup("Project"); mName = mIniFile->value("name", "").toString(); mOptions.icon = mIniFile->value("icon", "").toString(); mOptions.version = mIniFile->value("Ver", 0).toInt(); if (mOptions.version > 0) { // ver > 0 is at least a v5 project if (mOptions.version < 2) { mOptions.version = 2; QMessageBox::information(pMainWindow, tr("Settings need update"), tr("The compiler settings format of Dev-C++ has changed.") +"

" +tr("Please update your settings at Project >> Project Options >> Compiler and save your project."), QMessageBox::Ok); } mOptions.type = static_cast(mIniFile->value("type", 0).toInt()); mOptions.compilerCmd = mIniFile->value("Compiler", "").toString(); mOptions.cppCompilerCmd = mIniFile->value("CppCompiler", "").toString(); mOptions.linkerCmd = mIniFile->value("Linker", "").toString(); mOptions.objFiles = mIniFile->value("ObjFiles", "").toString().split(";"); mOptions.libs = mIniFile->value("Libs", "").toString().split(";"); mOptions.includes = mIniFile->value("Includes", "").toString().split(";"); mOptions.privateResource = mIniFile->value("PrivateResource", "").toString(); mOptions.resourceIncludes = mIniFile->value("ResourceIncludes", "").toString().split(";"); mOptions.makeIncludes = mIniFile->value("MakeIncludes","").toString().split(";"); mOptions.useGPP = mIniFile->value("IsCpp", false).toBool(); mOptions.exeOutput = mIniFile->value("ExeOutput", "").toString(); mOptions.objectOutput = mIniFile->value("ObjectOutput", "").toString(); mOptions.logOutput = mIniFile->value("LogOutput","").toString(); mOptions.logOutputEnabled = mIniFile->value("LogOutputEnabled", false).toBool(); mOptions.overrideOutput = mIniFile->value("OverrideOutput", false).toBool(); mOptions.overridenOutput = mIniFile->value("OverrideOutputName","").toString(); mOptions.hostApplication = mIniFile->value("HostApplication","").toString(); mOptions.useCustomMakefile = mIniFile->value("UseCustomMakefile", false).toBool(); mOptions.customMakefile = mIniFile->value("CustomMakefile","").toString(); mOptions.usePrecompiledHeader = mIniFile->value("UsePrecompiledHeader", false).toBool(); mOptions.precompiledHeader = mIniFile->value("PrecompiledHeader","").toString(); mOptions.cmdLineArgs = mIniFile->value("CommandLine","").toString(); mFolders = mIniFile->value("Folders","").toString().split(";"); mOptions.includeVersionInfo = mIniFile->value("IncludeVersionInfo", false).toBool(); mOptions.supportXPThemes = mIniFile->value("SupportXPThemes", false).toBool(); mOptions.compilerSet = mIniFile->value("CompilerSet", pSettings->compilerSets().defaultIndex()).toInt(); if (mOptions.compilerSet >= pSettings->compilerSets().size() || mOptions.compilerSet < 0) { // TODO: change from indices to names QMessageBox::critical( pMainWindow, tr("Compiler not found"), tr("The compiler set you have selected for this project, no longer exists.") +"
" +tr("It will be substituted by the global compiler set."), QMessageBox::Ok ); mOptions.compilerSet = pSettings->compilerSets().defaultIndex(); setModified(true); } mOptions.compilerOptions = mIniFile->value("CompilerSettings","").toString(); mOptions.staticLink = mIniFile->value("StaticLink", true).toBool(); mOptions.addCharset = mIniFile->value("AddCharset", true).toBool(); mOptions.useUTF8 = mIniFile->value("UseUTF8", false).toBool(); mOptions.encoding = mIniFile->value("Encoding", ENCODING_SYSTEM_DEFAULT).toString(); mOptions.versionInfo.major = mIniFile->value("Major", 0).toInt(); mOptions.versionInfo.minor = mIniFile->value("Minor", 1).toInt(); mOptions.versionInfo.release = mIniFile->value("Release", 1).toInt(); mOptions.versionInfo.build = mIniFile->value("Build", 1).toInt(); mOptions.versionInfo.languageID = mIniFile->value("LanguageID", 0x0409).toInt(); mOptions.versionInfo.charsetID = mIniFile->value("CharsetID", 0x04E4).toInt(); mOptions.versionInfo.companyName = mIniFile->value("CompanyName","").toString(); mOptions.versionInfo.fileVersion = mIniFile->value("FileVersion", "0.1").toString(); mOptions.versionInfo.fileDescription = mIniFile->value("FileDescription", tr("Developed using the Red Panda Dev-C++ IDE")).toString(); mOptions.versionInfo.internalName = mIniFile->value("InternalName","").toString(); mOptions.versionInfo.legalCopyright = mIniFile->value("LegalCopyright","").toString(); mOptions.versionInfo.legalTrademarks = mIniFile->value("LegalTrademarks","").toString(); mOptions.versionInfo.originalFilename = mIniFile->value("OriginalFilename", extractFileName(executable())).toString(); mOptions.versionInfo.productName = mIniFile->value("ProductName", mName).toString(); mOptions.versionInfo.productVersion = mIniFile->value("ProductVersion", "0.1.1.1").toString(); mOptions.versionInfo.autoIncBuildNr = mIniFile->value("AutoIncBuildNr", false).toBool(); mOptions.versionInfo.syncProduct = mIniFile->value("SyncProduct", false).toBool(); } else { // dev-c < 4 mOptions.version = -1; if (!mIniFile->value("NoConsole", true).toBool()) mOptions.type = ProjectType::Console; else if (mIniFile->value("IsDLL", false).toBool()) mOptions.type = ProjectType::DynamicLib; else mOptions.type = ProjectType::GUI; mOptions.privateResource = mIniFile->value("PrivateResource","").toString(); mOptions.resourceIncludes = mIniFile->value("ResourceIncludes","").toString().split(";"); mOptions.objFiles = mIniFile->value("ObjFiles","").toString().split(";"); mOptions.includes = mIniFile->value("IncludeDirs","").toString().split(";"); mOptions.compilerCmd = mIniFile->value("CompilerOptions","").toString(); mOptions.useGPP = mIniFile->value("Use_GPP", false).toBool(); mOptions.exeOutput = mIniFile->value("ExeOutput","").toString(); mOptions.objectOutput = mIniFile->value("ObjectOutput","").toString(); mOptions.overrideOutput = mIniFile->value("OverrideOutput", false).toBool(); mOptions.overridenOutput = mIniFile->value("OverrideOutputName","").toString(); mOptions.hostApplication = mIniFile->value("HostApplication","").toString(); } } void Project::loadUnitLayout(Editor *e, int index) { if (!e) return; QSettings layIni(changeFileExt(filename(), "layout"), QSettings::IniFormat); layIni.beginGroup(QString("Editor_%1").arg(index)); e->setCaretY(layIni.value("CursorRow",1).toInt()); e->setCaretX(layIni.value("CursorCol",1).toInt()); e->setTopLine(layIni.value("TopLine",1).toInt()); e->setLeftChar(layIni.value("LeftChar",1).toInt()); layIni.endGroup(); } PCppParser Project::cppParser() { return mParser; } void Project::sortUnitsByPriority() { std::sort(mUnits.begin(),mUnits.end(),[](const PProjectUnit& u1, const PProjectUnit& u2)->bool{ return (u1->priority()>u2->priority()); }); } int Project::indexInUnits(const QString &fileName) const { QDir dir(directory()); for (int i=0;ifileName())) return i; } return -1; } int Project::indexInUnits(const Editor *editor) const { if (!editor) return -1; return indexInUnits(editor->filename()); } void Project::removeFolderRecurse(PFolderNode node) { if (!node) return ; // Recursively remove folders for (int i=node->children.count()-1;i>=0;i++) { PFolderNode childNode = node->children[i]; // Remove folder inside folder if (childNode->unitIndex<0 && childNode->level>0) { removeFolderRecurse(childNode); // Or remove editors at this level } else if (childNode->unitIndex >= 0 && childNode->level > 0) { // Remove editor in folder from project int editorIndex = childNode->unitIndex; if (!removeEditor(editorIndex,true)) return; } } PFolderNode parent = node->parent.lock(); if (parent) { parent->children.removeAll(node); } } const ProjectOptions &Project::options() const { return mOptions; } void Project::setOptions(const ProjectOptions &newOptions) { mOptions = newOptions; } const PFolderNode &Project::node() const { return mNode; } void Project::setNode(const PFolderNode &newNode) { mNode = newNode; } const QString &Project::name() const { return mName; } void Project::setName(const QString &newName) { mName = newName; } std::shared_ptr &Project::iniFile() { return mIniFile; } void Project::setIniFile(const std::shared_ptr &newIniFile) { mIniFile = newIniFile; } const QString &Project::filename() const { return mFilename; } ProjectUnit::ProjectUnit(Project* parent) { mEditor = nullptr; mNode = nullptr; mParent = parent; } Project *ProjectUnit::parent() const { return mParent; } void ProjectUnit::setParent(Project* newParent) { mParent = newParent; } Editor *ProjectUnit::editor() const { return mEditor; } void ProjectUnit::setEditor(Editor *newEditor) { mEditor = newEditor; } const QString &ProjectUnit::fileName() const { return mFileName; } void ProjectUnit::setFileName(const QString &newFileName) { mFileName = newFileName; } bool ProjectUnit::isNew() const { return mNew; } void ProjectUnit::setNew(bool newNew) { mNew = newNew; } const QString &ProjectUnit::folder() const { return mFolder; } void ProjectUnit::setFolder(const QString &newFolder) { mFolder = newFolder; } bool ProjectUnit::compile() const { return mCompile; } void ProjectUnit::setCompile(bool newCompile) { mCompile = newCompile; } bool ProjectUnit::compileCpp() const { return mCompileCpp; } void ProjectUnit::setCompileCpp(bool newCompileCpp) { mCompileCpp = newCompileCpp; } bool ProjectUnit::overrideBuildCmd() const { return mOverrideBuildCmd; } void ProjectUnit::setOverrideBuildCmd(bool newOverrideBuildCmd) { mOverrideBuildCmd = newOverrideBuildCmd; } const QString &ProjectUnit::buildCmd() const { return mBuildCmd; } void ProjectUnit::setBuildCmd(const QString &newBuildCmd) { mBuildCmd = newBuildCmd; } bool ProjectUnit::link() const { return mLink; } void ProjectUnit::setLink(bool newLink) { mLink = newLink; } int ProjectUnit::priority() const { return mPriority; } void ProjectUnit::setPriority(int newPriority) { mPriority = newPriority; } bool ProjectUnit::detectEncoding() const { return mDetectEncoding; } void ProjectUnit::setDetectEncoding(bool newDetectEncoding) { mDetectEncoding = newDetectEncoding; } const QByteArray &ProjectUnit::encoding() const { return mEncoding; } void ProjectUnit::setEncoding(const QByteArray &newEncoding) { mEncoding = newEncoding; } bool ProjectUnit::modified() const { if (mEditor) { return mEditor->modified(); } else { return false; } } void ProjectUnit::setModified(bool value) { // Mark the change in the coupled editor if (mEditor) { return mEditor->setModified(value); } // If modified is set to true, mark project as modified too if (value) { mParent->setModified(true); } } bool ProjectUnit::save() { bool previous=pMainWindow->fileSystemWatcher()->blockSignals(true); auto action = finally([&previous](){ pMainWindow->fileSystemWatcher()->blockSignals(previous); }); bool result=true; if (!mEditor && !fileExists(mFileName)) { // file is neither open, nor saved QStringList temp; StringsToFile(temp,mFileName); } else if (mEditor and modified()) { result = mEditor->save(); } if (mNode) { mNode->text = extractFileName(mFileName); } return result; } PFolderNode &ProjectUnit::node() { return mNode; } void ProjectUnit::setNode(const PFolderNode &newNode) { mNode = newNode; }