Beispiel #1
0
bool
Project::HasLibrary(const char *path)
{
	if (!path)
		return false;
	
	for (int32 i = 0; i < fLibraryList.CountItems(); i++)
	{
		SourceFile *file = (SourceFile*)fLibraryList.ItemAt(i);
		if (file && strcmp(file->GetPath().GetFullPath(),path) == 0)
			return true;
	}
	return false;
}
Beispiel #2
0
void
FindWindow::SetProject(Project *proj)
{
	fFileList.MakeEmpty();
	if (!proj)
		return;
	
	for (int32 i = 0; i < proj->CountGroups(); i++)
	{
		SourceGroup *group = proj->GroupAt(i);
		for (int32 j = 0; j < group->filelist.CountItems(); j++)
		{
			SourceFile *file = group->filelist.ItemAt(j);
			fFileList.AddItem(new BString(file->GetPath().GetFullPath()));
			
			entry_ref partnerRef = GetPartnerRef(file->GetPath().GetRef());
			if (partnerRef.name)
			{
				DPath partnerPath(partnerRef);
				fFileList.AddItem(new BString(partnerPath.GetFullPath()));
			}
		}
	}
}
Beispiel #3
0
SourceFile *
Project::FindFile(const char *path)
{
	if (!path)
		return NULL;
	
	for (int32 i = 0; i < CountGroups(); i++)
	{
		SourceGroup *group = GroupAt(i);
		
		for (int32 j = 0; j < group->filelist.CountItems(); j++)
		{
			SourceFile *src = group->filelist.ItemAt(j);
			if (src && strcmp(src->GetPath().GetFullPath(),path) == 0)
				return src;
		}
	}
	return NULL;
}
Beispiel #4
0
void
Project::RemoveLibrary(const char *path)
{
	if (!path)
		return;
	
	STRACE(1,("%s: Attempting to remove %s\n",GetName(),path));
	for (int32 i = 0; i < fLibraryList.CountItems(); i++)
	{
		SourceFile *file = (SourceFile*)fLibraryList.ItemAt(i);
		if (file && strcmp(file->GetPath().GetFullPath(),path) == 0)
		{
			STRACE(1,("%s: Removed %s\n",GetName(),path));
			fLibraryList.RemoveItemAt(i);
			delete file;
			return;
		}
	}
}
Beispiel #5
0
bool
Project::HasFileName(const char *name)
{
	if (!name)
		return false;
	
	DPath newfile(name);
	
	for (int32 i = 0; i < CountGroups(); i++)
	{
		SourceGroup *group = GroupAt(i);
		
		for (int32 j = 0; j < group->filelist.CountItems(); j++)
		{
			SourceFile *src = group->filelist.ItemAt(j);
			if (src && strcmp(src->GetPath().GetFileName(),newfile.GetFileName()) == 0)
				return true;
		}
	}
	return false;
}
Beispiel #6
0
void
App::MessageReceived(BMessage *msg)
{
	switch (msg->what)
	{
		case M_MAKE_PROJECT:
		case M_RUN_PROJECT:
		case M_RUN_IN_TERMINAL:
		case M_RUN_IN_DEBUGGER:
		case M_RUN_WITH_ARGS:
		case M_FORCE_REBUILD:
		case M_SHOW_ADD_NEW_PANEL:
		case M_SHOW_FIND_AND_OPEN_PANEL:
		case M_SHOW_FIND_IN_PROJECT_FILES:
		case M_SHOW_ERROR_WINDOW:
		case M_TOGGLE_ERROR_WINDOW:
		{
			entry_ref ref;
			if (msg->FindRef("refs",&ref) == B_OK)
				PostToProjectWindow(msg,&ref);
			else
				PostToProjectWindow(msg,NULL);
			
			break;
		}

		case M_OPEN_PARTNER:
		{
			entry_ref ref;
			if (msg->FindRef("refs",&ref) == B_OK)
				OpenPartner(ref);
			break;
		}

		case M_NEW_PROJECT:
		{
			TemplateWindow *win = new TemplateWindow(BRect(100, 100, 400, 300));
			win->Show();
			break;
		}

		case M_SHOW_OPEN_PROJECT:
		{
			CheckCreateOpenPanel();
			fOpenPanel->Show();
			break;
		}

		case M_CREATE_PROJECT:
		{
			CreateNewProject(*msg);
			break;
		}

		case M_QUICK_IMPORT:
		{
			entry_ref ref;
			if (msg->FindRef("refs",&ref) != B_OK || !QuickImportProject(DPath(ref)))
			{
				StartWindow *startwin = new StartWindow();
				startwin->Show();
				break;
			}
			break;
		}
		
		// These are for quit determination. We have to use our own counter variable
		// (sWindowCount) because BFilePanels throw the count off. Using a variable
		// is much preferable to subclassing just for this reason.
		case M_REGISTER_WINDOW:
		{
			sWindowCount++;
			break;
		}

		case M_DEREGISTER_WINDOW:
		{
			sWindowCount--;
			if (sWindowCount <= 1)
				PostMessage(B_QUIT_REQUESTED);
			break;
		}

		case EDIT_OPEN_FILE:
		{
			int32 index = 0;
			entry_ref ref;
			while (msg->FindRef("refs",index,&ref) == B_OK)
			{
				int32 line;
				if (msg->FindInt32("line",index,&line) != B_OK)
					line = -1;
				int32 column;
				if (msg->FindInt32("column",index,&column) != B_OK)
					column = -1;
				
				OpenFile(ref,line,column);
				
				index++;
			}
			
			CheckCreateOpenPanel();
			fOpenPanel->GetPanelDirectory(&ref);
			gLastProjectPath.SetTo(ref);
			BWindow* openWindow = fOpenPanel->Window();
			break;
		}

		case M_FIND_AND_OPEN_FILE:
		{
			FindAndOpenFile(msg);
			break;
		}

		case M_BUILDING_FILE:
		{
			SourceFile *file;
			if (msg->FindPointer("sourcefile",(void**)&file) == B_OK)
				printf(B_TRANSLATE("Building %s\n"),file->GetPath().GetFileName());
			else
				printf(B_TRANSLATE("NULL pointer in M_BUILDING_FILE\n"));
			break;
		}

		case M_LINKING_PROJECT:
		{
			printf(B_TRANSLATE("Linking\n"));
			break;
		}

		case M_UPDATING_RESOURCES:
		{
			printf(B_TRANSLATE("Updating resources\n"));
			break;
		}

		case M_BUILD_FAILURE:
		{
			BString errstr;
			if (msg->FindString("errstr",&errstr) == B_OK)
				printf("%s\n",errstr.String());
			else
			{
				ErrorList errors;
				errors.Unflatten(*msg);
				printf(B_TRANSLATE("Build failure\n%s"), errors.AsString().String());
			}
			sReturnCode = -1;
			PostMessage(B_QUIT_REQUESTED);
			break;
		}

		case M_BUILD_WARNINGS:
		{
			BString errstr;
			if (msg->FindString("errstr",&errstr) == B_OK)
				printf("%s\n",errstr.String());
			break;
		}

		case M_BUILD_SUCCESS:
		{
			printf(B_TRANSLATE("Success\n"));
			PostMessage(B_QUIT_REQUESTED);
			break;
		}

		default:
			BApplication::MessageReceived(msg);
	}
}
Beispiel #7
0
void
Project::Link(void)
{
	BString linkString;
	
	if (TargetType() == TARGET_STATIC_LIB)
	{
		linkString = "ar rcs '";
		linkString << GetPath().GetFolder() << "/" << GetTargetName() << "' ";
		for (int32 i = 0; i < CountGroups(); i++)
		{
			SourceGroup *group = GroupAt(i);
			
			for (int32 j = 0; j < group->filelist.CountItems(); j++)
			{
				SourceFile *file = group->filelist.ItemAt(j);
				if (file->GetObjectPath(fBuildInfo).GetFullPath())
					linkString << "'" << file->GetObjectPath(fBuildInfo).GetFullPath() << "' ";
			}
		}
	
	}
	else
	{
		linkString = "gcc -o '";
		linkString << GetPath().GetFolder() << "/" << GetTargetName() << "' ";
			
		for (int32 i = 0; i < CountGroups(); i++)
		{
			SourceGroup *group = GroupAt(i);
			
			for (int32 j = 0; j < group->filelist.CountItems(); j++)
			{
				SourceFile *file = group->filelist.ItemAt(j);
				if (file->GetObjectPath(fBuildInfo).GetFullPath())
					linkString << "'" << file->GetObjectPath(fBuildInfo).GetFullPath() << "' ";
			}
		}
	
		for (int32 i = 0; i < CountGroups(); i++)
		{
			SourceGroup *group = GroupAt(i);
			
			for (int32 j = 0; j < group->filelist.CountItems(); j++)
			{
				SourceFile *file = group->filelist.ItemAt(j);
				if (file->GetLibraryPath(fBuildInfo).GetFullPath())
					linkString << "'" << file->GetLibraryPath(fBuildInfo).GetFullPath() << "' ";
			}
		}
	
		for (int32 i = 0; i < CountLibraries(); i++)
		{
			SourceFile *file = LibraryAt(i);
			if (!file)
				continue;
			
			BString filenamebase;
			filenamebase = file->GetPath().GetBaseName();
			if (filenamebase.FindFirst("lib") == 0)
				filenamebase.RemoveFirst("lib");
			
			linkString << "-l" << filenamebase << " ";
		}
		
		if (TargetType() == TARGET_DRIVER)
			linkString << "/boot/develop/lib/x86/_KERNEL_ ";
		
		linkString << "-L/boot/home/config/lib ";
		
		switch (TargetType())
		{
			case TARGET_DRIVER:
			{
				linkString << "-Xlinker -nostdlib ";
				break;
			}
			case TARGET_SHARED_LIB:
			{
				linkString << "-nostart -Xlinker -soname=" << GetTargetName() << " ";
				break;
			}
			default:
			{
				// Application
				linkString << "-Xlinker -soname=_APP_ ";
				break;
			}
		}
	}
	
	linkString << " 2>&1";
	
	BString errmsg;
	PipeCommand(linkString.String(),errmsg);

	STRACE(1,("Linking %s:\n%s\nErrors:\n%s\n",GetName(),linkString.String(),errmsg.String()));
	
	if (errmsg.CountChars() > 0)
		ParseLDErrors(errmsg.String(),fBuildInfo.errorList);
}
Beispiel #8
0
void
Project::Save(const char *path)
{
	BString projectPath = fPath.GetFolder();
	projectPath << "/";
	
	BString data;
	data << "NAME=" << fName << "\nTARGETNAME=" << fTargetName << "\n";
	data << "PLATFORM=" << sPlatformArray[fPlatform] << "\n";
	
	switch (fSCMType)
	{
		case SCM_HG:
		{
			data << "SCM=hg\n";
			break;
		}
		case SCM_GIT:
		{
			data << "SCM=git\n";
			break;
		}
		case SCM_SVN:
		{
			data << "SCM=svn\n";
			break;
		}
		case SCM_NONE:
		{
			data << "SCM=none\n";
			break;
		}
		default:
		{
			break;
		}
	}
	
	for (int32 i = 0; i < CountGroups(); i++)
	{
		SourceGroup *group = GroupAt(i);
		data << "GROUP=" << group->name << "\n";
		data << "EXPANDGROUP=" << (group->expanded ? "yes" : "no") << "\n";
		
		for (int32 j = 0; j < group->filelist.CountItems(); j++)
		{
			SourceFile *file = group->filelist.ItemAt(j);
			
			BString temppath(file->GetPath().GetFullPath());
			if (temppath.FindFirst(projectPath.String()) == 0)
			{
				// Absolute paths which include the project folder are stripped
				// down into relative paths
				temppath.RemoveFirst(projectPath.String());
			}
			
			data << "SOURCEFILE=" << temppath << "\n";
			if (file->GetDependencies() && strlen(file->GetDependencies()) > 0)
				data << "DEPENDENCY=" << file->GetDependencies() << "\n";
		}
	}
	
	for (int32 i = 0; i < fLocalIncludeList.CountItems(); i++)
		data << "LOCALINCLUDE=" << fLocalIncludeList.ItemAt(i)->Relative() << "\n";
	
	for (int32 i = 0; i < fSystemIncludeList.CountItems(); i++)
	{
		BString *string = fSystemIncludeList.ItemAt(i);
		BString include = *string;
		if (include[0] == '/')
			include.RemoveFirst(projectPath.String());
		data << "SYSTEMINCLUDE=" << include << "\n";
	}
	
	for (int32 i = 0; i < fLibraryList.CountItems(); i++)
	{
		SourceFile *file = (SourceFile*)fLibraryList.ItemAt(i);
		if (!file)
			continue;
		
		BString strpath(file->GetPath().GetFullPath());
		if (gPlatform == PLATFORM_ZETA)
		{
			if (strpath.FindFirst("/boot/beos/etc/develop/zeta-r1-gcc2-x86/") == 0)
				strpath.ReplaceFirst("/boot/beos/etc/develop/zeta-r1-gcc2-x86/",
										"/boot/develop/");
		}
		
		if (strpath.FindFirst(projectPath.String()) == 0)
			strpath.RemoveFirst(projectPath.String());
		data << "LIBRARY=" << strpath.String() << "\n";
	}
	
	data << "RUNARGS=" << fRunArgs << "\n";
	data << "CCDEBUG=" << (fDebug ? "yes" : "no") << "\n";
	data << "CCPROFILE=" << (fProfile ? "yes" : "no") << "\n";
	data << "CCOPSIZE=" << (fOpSize ? "yes" : "no") << "\n";
	data << "CCOPLEVEL=" << (int)fOpLevel << "\n";
	data << "CCTARGETTYPE=" << fTargetType << "\n";
	data << "CCEXTRA=" << fExtraCompilerOptions << "\n";
	data << "LDEXTRA=" << fExtraLinkerOptions << "\n";
	
	BFile file(path,B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
	if (file.InitCheck() != B_OK)
	{
		STRACE(2,("Couldn't create project file %s. Bailing out\n",path));
		return;
	}
	
	STRACE(2,("Saved Project %s. Data as follows:\n%s\n",path,data.String()));
	
	file.Write(data.String(),data.Length());
	
	fPath = path;
	fObjectPath = fPath.GetFolder();
	
	BString objfolder("(Objects.");
	objfolder << GetName() << ")";
	fObjectPath.Append(objfolder.String());
	
	BNodeInfo nodeInfo(&file);
	nodeInfo.SetType(PROJECT_MIME_TYPE);
	
	UpdateBuildInfo();
}
Beispiel #9
0
status_t
BeIDE2Paladin(const char *path, BString &outpath)
{
	status_t returnVal = BEntry(path).InitCheck();
	if (returnVal != B_OK)
		return returnVal;
	
	BeIDEProject beide(path);
	if (beide.InitCheck() != B_OK)
		return beide.InitCheck();
	
	DPath dpath(path);
	Project proj(dpath.GetBaseName(), beide.TargetName());
	proj.SetPlatform(PLATFORM_R5);

	// NOTE: TARGET_* from Project.h & TARGET_* from BeIDEPRoject.h
	// map perfectly, so no explicit conversion required
	proj.SetTargetType(beide.TargetType());
	
	BString savepath(dpath.GetFolder());
	savepath << "/" << dpath.GetBaseName() << ".pld";
	proj.Save(savepath.String());
	
	for (int32 i = 0; i < beide.CountLocalIncludes(); i++)
	{
		BString include = beide.LocalIncludeAt(i);
		
		if (include.ICompare("{project}") == 0)
			continue;
		
		include.RemoveFirst("{project}/");
		proj.AddLocalInclude(include.String());
	}

	for (int32 i = 0; i < beide.CountSystemIncludes(); i++)
	{
		BString include = beide.SystemIncludeAt(i);
		
		if (include.ICompare("{project}") == 0)
			continue;
		
		include.RemoveFirst("{project}/");
		proj.AddSystemInclude(include.String());
	}
	
	SourceGroup *currentGroup = NULL;
	for (int32 i = 0; i < beide.CountFiles(); i++)
	{
		ProjectFile file = beide.FileAt(i);

		if (file.path.FindFirst("/_KERNEL_") > 0)
			continue;

		SourceFile *srcFile = gFileFactory.CreateSourceFileItem(file.path.String());
		
		if (!srcFile)
			continue;
		
		if (dynamic_cast<SourceFileLib*>(srcFile))
		{
			proj.AddLibrary(srcFile->GetPath().GetFileName());
			delete srcFile;
			continue;
		}
		
		if (!proj.HasGroup(file.group.String()))
			currentGroup = proj.AddGroup(file.group.String());

		BPath newPath;
		if (proj.LocateFile(srcFile->GetPath().GetFullPath(), newPath))
			srcFile->SetPath(newPath.Path());

		proj.AddFile(srcFile, currentGroup);
	}
	
	uint32 codeFlags = beide.CodeGenerationFlags();
	if (codeFlags & CODEGEN_DEBUGGING)
		proj.SetDebug(true);
	
	if (codeFlags & CODEGEN_OPTIMIZE_SIZE)
		proj.SetOpForSize(true);
	
	proj.SetOpLevel(beide.OptimizationMode());
	
	// Because Paladin doesn't currently support the seemingly 50,000 warning
	// types, we'll put them in the compiler options for the ones not commonly
	// used
	BString options;
	
	uint32 warnings = beide.Warnings();
	if (warnings & WARN_STRICT_ANSI)
		options << "-pedantic ";
	
	if (warnings & WARN_LOCAL_SHADOW)
		options << "-Wshadow ";
	
	if (warnings & WARN_INCOMPATIBLE_CAST)
		options << "-Wbad-function-cast ";
	
	if (warnings & WARN_CAST_QUALIFIERS)
		options << "-Wcast-qual ";
	
	if (warnings & WARN_CONFUSING_CAST)
		options << "-Wconversion ";
	
	if (warnings & WARN_CANT_INLINE)
		options << "-Winline ";
	
	if (warnings & WARN_EXTERN_TO_INLINE)
		options << "-Wextern-inline ";
	
	if (warnings & WARN_OVERLOADED_VIRTUALS)
		options << "-Woverloaded-virtual ";
	
	if (warnings & WARN_C_CASTS)
		options << "-Wold-style-cast ";
	
	if (warnings & WARN_EFFECTIVE_CPP)
		options << "-Weffc++ ";
	
	if (warnings & WARN_MISSING_PARENTHESES)
		options << "-Wparentheses ";
	
	if (warnings & WARN_INCONSISTENT_RETURN)
		options << "-Wreturn-type ";
	
	if (warnings & WARN_MISSING_ENUM_CASES)
		options << "-Wswitch ";
	
	if (warnings & WARN_UNUSED_VARS)
		options << "-Wunusued ";
	
	if (warnings & WARN_UNINIT_AUTO_VARS)
		options << "-Wuninitialized ";
	
	if (warnings & WARN_INIT_REORDERING)
		options << "-Wreorder ";
	
	if (warnings & WARN_NONVIRTUAL_DESTRUCTORS)
		options << "-Wnon-virtual-dtor ";
	
	if (warnings & WARN_UNRECOGNIZED_PRAGMAS)
		options << "-Wunknown-pragmas ";
	
	if (warnings & WARN_SIGNED_UNSIGNED_COMP)
		options << "-Wsign-compare ";
	
	if (warnings & WARN_CHAR_SUBSCRIPTS)
		options << "-Wchar-subscripts ";
	
	if (warnings & WARN_PRINTF_FORMATTING)
		options << "-Wformat ";
	
	if (warnings & WARN_TRIGRAPHS_USED)
		options << "-Wtrigraphs ";
	
	uint32 langopts = beide.LanguageOptions();
	if (langopts & LANGOPTS_ANSI_C_MODE)
		options << "-ansi ";
	
	if (langopts & LANGOPTS_SUPPORT_TRIGRAPHS)
		options << "-trigraphs ";
	
	if (langopts & LANGOPTS_SIGNED_CHAR)
		options << "-fsigned-char ";
	
	if (langopts & LANGOPTS_UNSIGNED_BITFIELDS)
		options << "-funsigned-bitfields ";
	
	if (langopts & LANGOPTS_CONST_CHAR_LITERALS)
		options << "-Wwrite-strings ";
	
	options << beide.ExtraCompilerOptions();
	proj.SetExtraCompilerOptions(options.String());
	proj.SetExtraLinkerOptions(beide.ExtraLinkerOptions());
	
	proj.Save();
	
	outpath = savepath;
	
	return B_OK;
}
Beispiel #10
0
ProjectWindow::ProjectWindow(BRect frame, Project *project)
	:	DWindow(frame, "Paladin", B_DOCUMENT_WINDOW, B_NOT_ZOOMABLE |
													B_WILL_ACCEPT_FIRST_CLICK),
		fErrorWindow(NULL),
		fFilePanel(NULL),
		fProject(project),
		fSourceControl(NULL),
		fShowingLibs(false),
		fMenusLocked(false),
		fBuilder(BMessenger(this))
{
	AddCommonFilter(new AltTabFilter());
	SetSizeLimits(200,30000,200,30000);
	RegisterWindow();
	
	// This is for our in-program debug menu which comes in handy now and then.
	// Paladin -d doesn't always get the job done
	AddShortcut('9', B_COMMAND_KEY | B_SHIFT_KEY | B_CONTROL_KEY,
				new BMessage(M_TOGGLE_DEBUG_MENU));
	
	if (fProject)
	{
		fSourceControl = GetSCM(fProject->SourceControl());
		if (fSourceControl)
		{
			if (gPrintDebugMode > 0)
				fSourceControl->SetDebugMode(true);
			
			fSourceControl->SetUpdateCallback(SCMOutputCallback);
			fSourceControl->SetWorkingDirectory(fProject->GetPath().GetFolder());
			
			if (fSourceControl->NeedsInit(fProject->GetPath().GetFolder()))
				fSourceControl->CreateRepository(fProject->GetPath().GetFolder());
		}
	}
	
	BView *top = GetBackgroundView();
	
	BRect bounds(Bounds());
	BRect r(bounds);
	
	r.bottom = 16;
	fMenuBar = new BMenuBar(r,"documentbar");
	top->AddChild(fMenuBar);
	
	r = bounds;
	r.top = fMenuBar->Frame().bottom + 1;
	r.right -= B_V_SCROLL_BAR_WIDTH;
	r.bottom -= B_H_SCROLL_BAR_HEIGHT;
	
	fProjectList = new ProjectList(fProject, r,"filelist",B_FOLLOW_ALL);
	fProjectList->SetInvocationMessage(new BMessage(M_EDIT_FILE));
	
	BScrollView *scrollView = new BScrollView("scrollView",fProjectList,
											B_FOLLOW_ALL,0,false,true);
	top->AddChild(scrollView);
	fProjectList->SetTarget(this);
	
	r.top = r.bottom + 1;
	r.bottom = Bounds().bottom;
	fStatusBar = new BStringView(r,"statusbar", NULL, B_FOLLOW_LEFT_RIGHT |
														B_FOLLOW_BOTTOM);
	top->AddChild(fStatusBar);
	
	fStatusBar->SetViewColor(235,235,235);
	fStatusBar->SetFontSize(10.0);
	
	SetupMenus();
	
	if (project)
	{
		BString title("Paladin: ");
		title << project->GetName();
		SetTitle(title.String());
		
		for (int32 i = 0; i < project->CountGroups(); i++)
		{
			SourceGroup *group = project->GroupAt(i);
			SourceGroupItem *groupitem = new SourceGroupItem(group);
			fProjectList->AddItem(groupitem);
			groupitem->SetExpanded(group->expanded);
			
			for (int32 j = 0; j < group->filelist.CountItems(); j++)
			{
				SourceFile *file = group->filelist.ItemAt(j);
				SourceFileItem *fileitem = new SourceFileItem(file,1);
				
//				fProjectList->AddUnder(fileitem,groupitem);
				fProjectList->AddItem(fileitem);
				
				BString abspath = file->GetPath().GetFullPath();
				if (abspath[0] != '/')
				{
					abspath.Prepend("/");
					abspath.Prepend(project->GetPath().GetFolder());
				}
				BEntry entry(abspath.String());
				if (entry.Exists())
				{
					if (project->CheckNeedsBuild(file,false))
					{
						fileitem->SetDisplayState(SFITEM_NEEDS_BUILD);
						fProjectList->InvalidateItem(fProjectList->IndexOf(fileitem));
					}
					else
						file->SetBuildFlag(BUILD_NO);
				}
				else
				{
					fileitem->SetDisplayState(SFITEM_MISSING);
					fProjectList->InvalidateItem(fProjectList->IndexOf(fileitem));
				}
			}
		}
	}
	
	BNode node(fProject->GetPath().GetFullPath());
	if (node.ReadAttr("project_frame",B_RECT_TYPE,0,&r,sizeof(BRect)) == sizeof(BRect))
	{
		if (r.Width() < 200)
			r.right = r.left + 200;
		if (r.Height() < 200)
			r.top = r.bottom + 200;
		MoveTo(r.left,r.top);
		ResizeTo(r.Width(),r.Height());
	}
	
	fProjectList->MakeFocus(true);
	
	if (gShowFolderOnOpen)
	{
		// Duplicated code from MessageReceived::M_SHOW_PROJECT_FOLDER. Doing
		// it here in combo with snooze() makes it much more likely that the
		// opened project window is frontmost instead of the project folder's window
		entry_ref ref;
		BEntry(fProject->GetPath().GetFolder()).GetRef(&ref);
		BMessenger msgr("application/x-vnd.Be-TRAK");
		
		BMessage reply;
		BMessage openmsg(B_REFS_RECEIVED);
		openmsg.AddRef("refs",&ref);
		msgr.SendMessage(&openmsg);
		snooze(50000);
	}
	
	if (gAutoSyncModules)
		PostMessage(M_SYNC_MODULES);
}
Beispiel #11
0
void
ProjectWindow::MessageReceived(BMessage *msg)
{
	status_t status;
	
	if ( (msg->WasDropped() && msg->what == B_SIMPLE_DATA) || msg->what == M_ADD_FILES)
	{
		fAddFileStruct.refmsg = *msg;
		fAddFileStruct.parent = this;
		
		uint32 buttons;
		fProjectList->GetMouse(&fAddFileStruct.droppt,&buttons);
		
		thread_id addThread = spawn_thread(AddFileThread,"file adding thread",
											B_NORMAL_PRIORITY, &fAddFileStruct);
		if (addThread >= 0)
			resume_thread(addThread);
	}
	switch (msg->what)
	{
		case M_IMPORT_REFS:
		{
			fImportStruct.refmsg = *msg;
			fImportStruct.parent = this;
			
			thread_id importThread = spawn_thread(ImportFileThread,"file import thread",
												B_NORMAL_PRIORITY, &fImportStruct);
			if (importThread >= 0)
				resume_thread(importThread);
			break;
		}
		case M_BACKUP_PROJECT:
		{
			thread_id backupThread = spawn_thread(BackupThread,"project backup thread",
												B_NORMAL_PRIORITY, this);
			if (backupThread >= 0)
			{
				fStatusBar->SetText(TR("Backing up project"));
				UpdateIfNeeded();
				
				SetMenuLock(true);
				resume_thread(backupThread);
			}
			break;
		}
		case M_GET_CHECK_IN_MSG:
		{
			if (!fSourceControl)
			{
				printf("NULL source control\n");
				break;
			}
			
			BString out;
			fSourceControl->GetCheckinHeader(out);
			
			bool select = false;
			if (out.CountChars() > 1)
				out.Prepend("\n\n");
			else
			{
				out = TR("Enter the description for the changes in this revision.");
				select = true;
			}
			
			GetTextWindow *gtw = new GetTextWindow("Paladin", out.String(),
													BMessage(M_CHECK_IN_PROJECT),
													BMessenger(this));
			if (!select)
				gtw->GetTextView()->Select(0,0);
			gtw->Show();
			break;
		}
		case M_CHECK_IN_PROJECT:
		{
			BString commitstr;
			if (msg->FindString("text", &commitstr) == B_OK && fSourceControl)
			{
				SCMOutputWindow *win = new SCMOutputWindow(TR("Commit"));
				win->Show();
				fSourceControl->Commit(commitstr.String());
			}
			break;
		}
		case M_REVERT_PROJECT:
		{
			if (!fSourceControl)
				break;
			
			int32 result = ShowAlert(TR("This will undo all changes since the last commit. "
										"Continue?"), "Don't Revert", "Revert");
			if (result == 1)
			{
				SCMOutputWindow *win = new SCMOutputWindow(TR("Revert"));
				win->Show();
				fSourceControl->Revert(NULL);
			}
			break;
		}
		case M_REBUILD_FILE:
		case M_ADD_SELECTION_TO_REPO:
		case M_REMOVE_SELECTION_FROM_REPO:
		case M_REVERT_SELECTION:
		case M_DIFF_SELECTION:
		{
			ActOnSelectedFiles(msg->what);
			break;
		}
		case M_DIFF_PROJECT:
		{
			if (fSourceControl)
			{
				SCMOutputWindow *win = new SCMOutputWindow(TR("Differences"));
				win->Show();
				fSourceControl->Diff(NULL);
			}
			break;
		}
		case M_PROJECT_SCM_STATUS:
		{
			if (fSourceControl)
			{
				SCMOutputWindow *win = new SCMOutputWindow(TR("Project Status"));
				BString strstatus;
				fSourceControl->GetChangeStatus(strstatus);
				win->GetTextView()->SetText(strstatus.String());
				win->Show();
			}
			break;
		}
		case M_PUSH_PROJECT:
		{
			if (fSourceControl)
			{
				SCMOutputWindow *win = new SCMOutputWindow(TR("Push"));
				win->Show();
				fSourceControl->Push(NULL);
			}
			break;
		}
		case M_PULL_PROJECT:
		{
			if (fSourceControl)
			{
				SCMOutputWindow *win = new SCMOutputWindow(TR("Pull"));
				win->Show();
				status = fSourceControl->Pull(NULL);
				
				if (!status)
					ShowAlert("Unable to pull from the remote repository. If it "
							"uses a secure connection, please set up the appropriate "
							"SSH keys on the remote server.", "OK");
			}
			break;
		}
		case M_CULL_EMPTY_GROUPS:
		{
			CullEmptyGroups();
			break;
		}
		case M_RUN_FILE_TYPES:
		{
			int32 selection = fProjectList->FullListCurrentSelection();
			if (selection < 0)
				break;
			
			SourceFileItem *item = dynamic_cast<SourceFileItem*>(fProjectList->FullListItemAt(selection));
			if (!item)
				break;
			SpawnFileTypes(item->GetData()->GetPath());
			break;
		}
		case M_OPEN_PARENT_FOLDER:
		{
			BMessage openmsg(B_REFS_RECEIVED);
			int32 selindex = 0;
			int32 selection = fProjectList->FullListCurrentSelection();
			selindex++;
			if (selection >= 0)
			{
				while (selection >= 0)
				{
					SourceFileItem *item = dynamic_cast<SourceFileItem*>(fProjectList->FullListItemAt(selection));
					if (!item)
						break;
					
					SourceFile *file = item->GetData();
					BString abspath = file->GetPath().GetFullPath();
					if (abspath[0] != '/')
					{
						abspath.Prepend("/");
						abspath.Prepend(fProject->GetPath().GetFolder());
					}
					DPath filepath(abspath);
					
					entry_ref ref;
					BEntry(filepath.GetFolder()).GetRef(&ref);
					
					openmsg.AddRef("refs",&ref);
					selection = fProjectList->FullListCurrentSelection(selindex++);
				}
				
				BMessenger msgr("application/x-vnd.Be-TRAK");
				msgr.SendMessage(&openmsg);
			}
			
			break;
		}
		case M_SHOW_PROJECT_FOLDER:
		{
			entry_ref ref;
			BEntry(fProject->GetPath().GetFolder()).GetRef(&ref);
			BMessenger msgr("application/x-vnd.Be-TRAK");
			
			BMessage openmsg(B_REFS_RECEIVED);
			openmsg.AddRef("refs",&ref);
			msgr.SendMessage(&openmsg);
			break;
		}
		case M_SHOW_ASCII_TABLE:
		{
			AsciiWindow *ascwin = new AsciiWindow();
			ascwin->Show();
			break;
		}
		case M_SHOW_VREGEX:
		{
			VRegWindow *vregwin = new VRegWindow();
			vregwin->Show();
			break;
		}
		case M_SHOW_LICENSES:
		{
			LicenseManager *man = new LicenseManager(fProject->GetPath().GetFolder());
			man->Show();
			break;
		}
		case M_RUN_TOOL:
		{
			BString sig;
			if (msg->FindString("signature", &sig) == B_OK)
			{
				LaunchHelper launcher(sig.String());
				launcher.Launch();
			}
			break;
		}
		case M_MAKE_MAKE:
		{
			DPath out(fProject->GetPath().GetFolder());
			out.Append("Makefile");
			if (MakeMake(fProject,out) == B_OK);
			{
				BEntry entry(out.GetFullPath());
				entry_ref ref;
				if (entry.InitCheck() == B_OK)
				{
					entry.GetRef(&ref);
					BMessage refmsg(B_REFS_RECEIVED);
					refmsg.AddRef("refs",&ref);
					be_app->PostMessage(&refmsg);
				}
			}
			break;
		}
		case M_SHOW_CODE_LIBRARY:
		{
			#ifdef BUILD_CODE_LIBRARY
			CodeLibWindow *libwin = CodeLibWindow::GetInstance(BRect(100,100,500,350));
			libwin->Show();
			#endif
			
			break;
		}
		case M_OPEN_PARTNER:
		{
			int32 selection = fProjectList->FullListCurrentSelection();
			if (selection < 0)
				break;
			
			SourceFileItem *item = dynamic_cast<SourceFileItem*>(
									fProjectList->FullListItemAt(selection));
			if (!item)
				break;
			entry_ref ref;
			BEntry(fProject->GetPathForFile(item->GetData()).GetFullPath()).GetRef(&ref);
			BMessage refmsg(M_OPEN_PARTNER);
			refmsg.AddRef("refs",&ref);
			be_app->PostMessage(&refmsg);
			break;
		}
		case M_NEW_GROUP:
		{
			MakeGroup(fProjectList->FullListCurrentSelection());
			PostMessage(M_SHOW_RENAME_GROUP);
			break;
		}
		case M_SHOW_RENAME_GROUP:
		{
			int32 selection = fProjectList->FullListCurrentSelection();
			SourceGroupItem *groupItem = NULL;
			if (selection < 0)
			{
				// Don't need a selection if there is only one group in the project
				if (fProject->CountGroups() == 1)
					groupItem = fProjectList->ItemForGroup(fProject->GroupAt(0));
			}
			else
			{
				BStringItem *strItem = (BStringItem*)fProjectList->FullListItemAt(selection);
				groupItem = fProjectList->GroupForItem(strItem);
			}
			
			if (!groupItem)
				break;
			
			GroupRenameWindow *grwin = new GroupRenameWindow(groupItem->GetData(),
															BMessage(M_RENAME_GROUP),
															BMessenger(this));
			grwin->Show();
			break;
		}
		case M_RENAME_GROUP:
		{
			SourceGroup *group;
			BString newname;
			if (msg->FindPointer("group",(void**)&group) != B_OK ||
				msg->FindString("newname",&newname) != B_OK)
				break;
			
			group->name = newname;
			SourceGroupItem *groupItem = fProjectList->ItemForGroup(group);
			if (!groupItem)
				break;
			
			groupItem->SetText(newname.String());
			fProjectList->InvalidateItem(fProjectList->IndexOf(groupItem));
			
			fProject->Save();
			break;
		}
		case M_SORT_GROUP:
		{
			int32 selection = fProjectList->FullListCurrentSelection();
			
			SourceGroupItem *groupItem = NULL;
			if (selection < 0)
			{
				// Don't need a selection if there is only one group in the project
				if (fProject->CountGroups() == 1)
					groupItem = fProjectList->ItemForGroup(fProject->GroupAt(0));
			}
			else
			{
				BStringItem *strItem = (BStringItem*)fProjectList->FullListItemAt(selection);
				groupItem = fProjectList->GroupForItem(strItem);
			}
			
			if (!groupItem)
				break;
			
			fProjectList->SortItemsUnder(groupItem,true,compare_source_file_items);
			groupItem->GetData()->Sort();
			fProject->Save();
			
			break;
		}
		case M_TOGGLE_ERROR_WINDOW:
		{
			ToggleErrorWindow(fProject->GetErrorList());
			break;
		}
		case M_SHOW_ERROR_WINDOW:
		{
			ShowErrorWindow(fProject->GetErrorList());
			break;
		}
		case M_SHOW_PROJECT_SETTINGS:
		{
			BRect r(0,0,350,300);
			BRect screen(BScreen().Frame());
			
			r.OffsetTo((screen.Width() - r.Width()) / 2.0,
						(screen.Height() - r.Height()) / 2.0);
			
			ProjectSettingsWindow *win = new ProjectSettingsWindow(r,fProject);
			win->Show();
			break;
		}
		case M_SHOW_RUN_ARGS:
		{
			RunArgsWindow *argwin = new RunArgsWindow(fProject);
			argwin->Show();
			break;
		}
		case M_JUMP_TO_MSG:
		{
			entry_ref ref;
			if (msg->FindRef("refs",&ref) == B_OK)
			{
				msg->what = B_REFS_RECEIVED;
				be_app->PostMessage(msg);
			}
			break;
		}
		case B_ABOUT_REQUESTED:
		{
			be_app->PostMessage(B_ABOUT_REQUESTED);
			break;
		}
		case M_SHOW_OPEN_PROJECT:
		{
			be_app->PostMessage(msg);
			break;
		}
		case M_NEW_WINDOW:
		{
			be_app->PostMessage(M_NEW_PROJECT);
			break;
		}
		case M_SHOW_PROGRAM_SETTINGS:
		{
			PrefsWindow *prefwin = new PrefsWindow(BRect(0,0,500,400));
			prefwin->Show();
			break;
		}
		case M_SHOW_FIND_AND_OPEN_PANEL:
		{
			BString text;
			msg->FindString("name",&text);
			
			// Passing a NULL string to this is OK
			FindOpenFileWindow *findwin = new FindOpenFileWindow(text.String());
			findwin->Show();
			break;
		}
		case M_FILE_NEEDS_BUILD:
		{
			SourceFile *file;
			if (msg->FindPointer("file",(void**)&file) == B_OK)
			{
				SourceFileItem *item = fProjectList->ItemForFile(file);
				if (item)
				{
					item->SetDisplayState(SFITEM_NEEDS_BUILD);
					fProjectList->InvalidateItem(fProjectList->IndexOf(item));
				}
			}
			break;
		}
		case M_EDIT_FILE:
		{
			int32 i = 0;
			int32 selection = fProjectList->FullListCurrentSelection(i);
			i++;
			
			BMessage refmsg(B_REFS_RECEIVED);
			while (selection >= 0)
			{
				SourceFileItem *item = dynamic_cast<SourceFileItem*>
										(fProjectList->FullListItemAt(selection));
				if (item && item->GetData())
				{
					BString abspath = item->GetData()->GetPath().GetFullPath();
					if (abspath[0] != '/')
					{
						abspath.Prepend("/");
						abspath.Prepend(fProject->GetPath().GetFolder());
					}
					
					BEntry entry(abspath.String());
					if (entry.InitCheck() == B_OK)
					{
						entry_ref ref;
						entry.GetRef(&ref);
						refmsg.AddRef("refs",&ref);
					}
					else
					{
						if (!entry.Exists())
						{
							BString errmsg = TR("Couldn't find XXXXX. It may have been moved or renamed.");
							errmsg.ReplaceFirst("XXXXX",abspath.String());
							ShowAlert(errmsg.String());
						}
					}
				}
				else
				{
					SourceGroupItem *groupItem = dynamic_cast<SourceGroupItem*>
											(fProjectList->FullListItemAt(selection));
					if (groupItem)
					{
						if (groupItem->IsExpanded())
							fProjectList->Collapse(groupItem);
						else
							fProjectList->Expand(groupItem);
						groupItem->GetData()->expanded = groupItem->IsExpanded();
					}
					
				}
				
				selection = fProjectList->CurrentSelection(i);
				i++;
			}
			be_app->PostMessage(&refmsg);
			break;
		}
		case M_LIBWIN_CLOSED:
		{
			fShowingLibs = false;
			break;
		}
		case M_SHOW_LIBRARIES:
		{
			fShowingLibs = true;
			LibraryWindow *libwin = new LibraryWindow(Frame().OffsetByCopy(15,15),
														BMessenger(this), fProject);
			libwin->Show();
			break;
		}
		case M_SHOW_ADD_NEW_PANEL:
		{
			AddNewFileWindow *anfwin = new AddNewFileWindow(BMessage(M_ADD_NEW_FILE),
														BMessenger(this));
			anfwin->Show();
			break;
		}
		case M_SHOW_FIND_IN_PROJECT_FILES:
		{
			if (!gLuaAvailable)
			{
				ShowAlert("Paladin's multi-file Find window depends on Lua. It will "
						"need to be installed if you wish to use this feature.", "OK",
						NULL, NULL, B_STOP_ALERT);
				break;
			}
			
			FindWindow *findwin = new FindWindow();
			findwin->Show();
			break;
		}
		case M_ADD_NEW_FILE:
		{
			BString name;
			bool makepair;
			if (msg->FindString("name",&name) == B_OK && msg->FindBool("makepair",&makepair) == B_OK)
				AddNewFile(name,makepair);
			break;
		}
		case M_SHOW_ADD_PANEL:
		{
			if (!fFilePanel)
			{
				BMessenger msgr(this);
				BEntry entry(fProject->GetPath().GetFolder());
				entry_ref ref;
				entry.GetRef(&ref);
				fFilePanel = new BFilePanel(B_OPEN_PANEL,&msgr,&ref,B_FILE_NODE,true,
											new BMessage(M_ADD_FILES));
			}
			fFilePanel->Show();
			break;
		}
		case M_REMOVE_FILES:
		{
			bool save = false;
			
			for (int32 i = 0; i < fProjectList->CountItems(); i++)
			{
				SourceFileItem *item = dynamic_cast<SourceFileItem*>(fProjectList->ItemAt(i));
				if (item && item->IsSelected())
				{
					fProjectList->RemoveItem(item);
					fProject->RemoveFile(item->GetData());
					delete item;
					save = true;
					i--;
				}
			}
			CullEmptyGroups();
			if (save)
				fProject->Save();
			break;
		}
		case M_EMPTY_CCACHE:
		{
			// We don't do this when forcing a rebuild of the sources because sometimes it
			// can take quite a while
			if (gUseCCache && gCCacheAvailable)
			{
				fStatusBar->SetText(TR("Emptying build cache"));
				UpdateIfNeeded();
				system("ccache -c > /dev/null");
				fStatusBar->SetText("");
				UpdateIfNeeded();
			}
			break;
		}
		case M_FORCE_REBUILD:
		{
			fProject->ForceRebuild();
			
			for (int32 i = 0; i < fProjectList->FullListCountItems(); i++)
			{
				SourceFileItem *item = dynamic_cast<SourceFileItem*>(fProjectList->FullListItemAt(i));
				if (!item)
					continue;
				
				SourceFile *file = item->GetData();
				if (file->UsesBuild())
				{
					item->SetDisplayState(SFITEM_NEEDS_BUILD);
					fProjectList->InvalidateItem(i);
				}
			}
			// This is necessary because InvalidateItem() uses indices from ItemAt(),
			// not FullListItemAt
			fProjectList->Invalidate();
			break;
		}
		case M_UPDATE_DEPENDENCIES:
		{
			UpdateDependencies();
			break;
		}
		case M_MAKE_PROJECT:
		case M_BUILD_PROJECT:
		{
			fBuildingFile = 0;
			DoBuild(POSTBUILD_NOTHING);
			break;
		}
		case M_RUN_PROJECT:
		{
			DoBuild(POSTBUILD_RUN);
			break;
		}
		case M_RUN_IN_TERMINAL:
		{
			DoBuild(POSTBUILD_RUN_IN_TERMINAL);
			break;
		}
		case M_DEBUG_PROJECT:
		{
			if (!fProject->Debug())
			{
				BString errmsg = TR("Your project does not have debugging information compiled ");
				errmsg << TR("in and will need to be rebuilt to debug. Do you wish to rebuild and ")
					<< TR("run the debugger?");
				int32 result = ShowAlert("Debugging information needs to compiled into "
										"your project. This may take some time for large "
										"projects. Do you wish to rebuild and run "
										"the debugger?",
										"Rebuild","Cancel");
				if (result == 1)
					break;
				
				fProject->SetDebug(true);
				fProject->Save();
				fProject->ForceRebuild();
			}
			
			DoBuild(POSTBUILD_DEBUG);
			break;
		}
		case M_EXAMINING_FILE:
		{
			SourceFile *file;
			if (msg->FindPointer("file",(void**)&file) == B_OK)
			{
				BString out;
				out << TR("Examining ") << file->GetPath().GetFileName();
				fStatusBar->SetText(out.String());
			}
			break;
		}
		case M_BUILDING_FILE:
		{
			SourceFile *file;
			if (msg->FindPointer("sourcefile",(void**)&file) == B_OK)
			{
				SourceFileItem *item = fProjectList->ItemForFile(file);
				if (item)
				{
					item->SetDisplayState(SFITEM_BUILDING);
					fProjectList->InvalidateItem(fProjectList->IndexOf(item));
					
					BString out;
					
					int32 count,total;
					if (msg->FindInt32("count",&count) == B_OK &&
						msg->FindInt32("total",&total) == B_OK)
					{
						fBuildingFile = MAX(fBuildingFile, count);
						out << "(" << fBuildingFile << "/" << total << ") ";
					}
					
					out << TR("Building ") << item->Text();
					fStatusBar->SetText(out.String());
				}
			}
			break;
		}
		case M_BUILDING_DONE:
		{
			SourceFile *file;
			if (msg->FindPointer("sourcefile",(void**)&file) == B_OK)
			{
				SourceFileItem *item = fProjectList->ItemForFile(file);
				if (item)
				{
					item->SetDisplayState(SFITEM_NORMAL);
					fProjectList->InvalidateItem(fProjectList->IndexOf(item));
				}
			}
			break;
		}
		case M_LINKING_PROJECT:
		{
			fStatusBar->SetText(TR("Linking"));
			break;
		}
		case M_UPDATING_RESOURCES:
		{
			fStatusBar->SetText(TR("Updating Resources"));
			break;
		}
		case M_DOING_POSTBUILD:
		{
			fStatusBar->SetText(TR("Performing Post-build tasks"));
			break;
		}
		case M_BUILD_FAILURE:
		{
			SetMenuLock(false);
			
			// fall through
		}
		case M_BUILD_MESSAGES:
		case M_BUILD_WARNINGS:
		{
			if (!fErrorWindow)
			{
				BRect screen(BScreen().Frame());
				BRect r(screen);
				r.left = r.right / 4.0;
				r.right *= .75;
				r.top = r.bottom - 200;
				
				BDeskbar deskbar;
				if (deskbar.Location() == B_DESKBAR_BOTTOM)
					r.OffsetBy(0,-deskbar.Frame().Height());
				
				fErrorWindow = new ErrorWindow(r,this);
				fErrorWindow->Show();
			}
			else
			{
				if (!fErrorWindow->IsFront())
					fErrorWindow->Activate();
			}
			fStatusBar->SetText("");
			
			// Should this be an Unflatten or an Append?
			ErrorList *errorList = fProject->GetErrorList();
			errorList->Unflatten(*msg);
			fErrorWindow->PostMessage(msg);
			break;
		}
		case M_BUILD_SUCCESS:
		{
			SetMenuLock(false);
			fStatusBar->SetText("");
			break;
		}
		case M_ERRORWIN_CLOSED:
		{
			fErrorWindow = NULL;
			break;
		}
		case M_SYNC_MODULES:
		{
			#ifdef BUILD_CODE_LIBRARY
			thread_id syncID = spawn_thread(SyncThread,"module update thread",
												B_NORMAL_PRIORITY, this);
			if (syncID >= 0)
				resume_thread(syncID);
			#endif
			break;
		}
		case M_TOGGLE_DEBUG_MENU:
		{
			ToggleDebugMenu();
			break;
		}
		case M_DEBUG_DUMP_DEPENDENCIES:
		{
			DumpDependencies(fProject);
			break;
		}
		case M_DEBUG_DUMP_INCLUDES:
		{
			DumpIncludes(fProject);
			break;
		}
		default:
		{
			DWindow::MessageReceived(msg);
			break;
		}
	}
}
Beispiel #12
0
void
ProjectWindow::ActOnSelectedFiles(const int32 &command)
{
	SCMOutputWindow *win = NULL;
	switch (command)
	{
		case M_ADD_SELECTION_TO_REPO:
		{
			if (!fSourceControl)
				return;
				
			win = new SCMOutputWindow(TR("Add to Repository"));
			win->Show();
			break;
		}
		case M_REMOVE_SELECTION_FROM_REPO:
		{
			if (!fSourceControl)
				return;
				
			win = new SCMOutputWindow(TR("Remove from Repository"));
			win->Show();
			break;
		}
		case M_REVERT_SELECTION:
		{
			if (!fSourceControl)
				return;
				
			win = new SCMOutputWindow(TR("Revert"));
			win->Show();
			break;
		}
		case M_DIFF_SELECTION:
		{
			if (!fSourceControl)
				return;
				
			win = new SCMOutputWindow(TR("Show Differences"));
			win->Show();
			break;
		}
		default:
			break;
	}
	
	for (int32 i = 0; i < fProjectList->CountItems(); i++)
	{
		SourceFileItem *item = dynamic_cast<SourceFileItem*>(fProjectList->ItemAt(i));
		if (item && item->IsSelected())
		{
			SourceFile *file = item->GetData();
			
			BString relPath = file->GetPath().GetFullPath();
			if (relPath.FindFirst(fProject->GetPath().GetFolder()) == 0)
			{
				relPath.RemoveFirst(fProject->GetPath().GetFolder());
				relPath.RemoveFirst("/");
			}
			
			BString relPartnerPath;
			entry_ref partnerRef = GetPartnerRef(file->GetPath().GetRef());
			if (partnerRef.name)
			{
				DPath partnerPath(partnerRef);
				relPartnerPath = partnerPath.GetFullPath();
				if (relPartnerPath.FindFirst(fProject->GetPath().GetFolder()) == 0)
				{
					relPartnerPath.RemoveFirst(fProject->GetPath().GetFolder());
					relPartnerPath.RemoveFirst("/");
				}
			}
			switch (command)
			{
				case M_REBUILD_FILE:
				{
					if (file->UsesBuild())
					{
						file->RemoveObjects(*fProject->GetBuildInfo());
						item->SetDisplayState(SFITEM_NEEDS_BUILD);
						fProjectList->InvalidateItem(fProjectList->IndexOf(item));
					}
					break;
				}
				case M_ADD_SELECTION_TO_REPO:
				{
					fSourceControl->AddToRepository(relPath.String());
					if (relPartnerPath.CountChars() > 0)
						fSourceControl->AddToRepository(relPartnerPath.String());
					break;
				}
				case M_REMOVE_SELECTION_FROM_REPO:
				{
					fSourceControl->RemoveFromRepository(relPath.String());
					if (relPartnerPath.CountChars() > 0)
						fSourceControl->RemoveFromRepository(relPartnerPath.String());
					break;
				}
				case M_REVERT_SELECTION:
				{
					fSourceControl->Revert(relPath.String());
					break;
				}
				case M_DIFF_SELECTION:
				{
					fSourceControl->Diff(relPath.String());
					break;
				}
				default:
				{
					return;
				}
			}
		}
	}
}