xref: /haiku/src/add-ons/tracker/openterminal/OpenTerminal.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
1 /*
2  * Copyright 2007 - 2009 Chris Roberts. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Chris Roberts, cpr420@gmail.com
7  */
8 
9 #include <StorageKit.h>
10 #include <SupportKit.h>
11 #include <AppKit.h>
12 
13 #include <vector>
14 
15 #include <add-ons/tracker/TrackerAddOn.h>
16 
17 const char* kTerminalSignature = "application/x-vnd.Haiku-Terminal";
18 const directory_which kAppsDirectory = B_SYSTEM_APPS_DIRECTORY;
19 
20 void
21 launch_terminal(BEntry* targetEntry, BPath* terminalPath) {
22 
23 	BPath targetPath;
24 
25 	if (targetEntry->GetPath(&targetPath) != B_OK)
26 		return;
27 
28 	// Escape paths which contain an apostraphe
29 	BString target(targetPath.Path());
30 	target.ReplaceAll("'", "'\\''");
31 
32 	BString terminal(terminalPath->Path());
33 	terminal.ReplaceAll("'", "'\\''");
34 
35 	// Build the command to "cd '/my/target/folder'; '/path/to/Terminal' &"
36 	BString command("cd '");
37 	command << target << "'; '" << terminal << "' &";
38 
39 	// Launch the Terminal.
40 	system(command.String());
41 }
42 
43 
44 void
45 process_refs(entry_ref base_ref, BMessage* message, void* reserved)
46 {
47 	BPath terminalPath;
48 
49 	bool terminalFound = false;
50 
51 	// Search for Terminal path by asking BRoster.
52 	entry_ref terminalRef;
53 	if (be_roster->FindApp(kTerminalSignature, &terminalRef) == B_OK) {
54 		if (terminalPath.SetTo(&terminalRef) == B_OK)
55 			terminalFound = true;
56 	}
57 
58 	// Fall back to manually creating a path if BRoster didn't find it.
59 	if (!terminalFound) {
60 		if (find_directory(kAppsDirectory, &terminalPath) != B_OK)
61 			return;
62 
63 		if (terminalPath.Append("Terminal") != B_OK)
64 			return;
65 	}
66 
67 	BEntry entry;
68 	int32 i;
69 	entry_ref tracker_ref;
70 	std::vector<BEntry> entries;
71 
72 	// Iterate through the refs that Tracker has sent us.
73 	for (i = 0; message->FindRef("refs", i, &tracker_ref) == B_OK; i++) {
74 
75 		// Pass 'true' as the traverse argument below, so that if the ref
76 		// is a symbolic link we get the target of the link to ensure that
77 		// it actually exists.
78 		if (entry.SetTo(&tracker_ref, true) != B_OK)
79 			continue;
80 
81 		// If the entry is a file then look for the parent directory.
82 		if (!entry.IsDirectory()) {
83 			if (entry.GetParent(&entry) != B_OK)
84 				continue;
85 		}
86 
87 		bool duplicate = false;
88 
89 		// Check for duplicates.
90 		for (uint x = 0; x < entries.size(); x++) {
91 			if (entries[x] == entry) {
92 				duplicate = true;
93 				break;
94 			}
95 		}
96 
97 		// This is a duplicate.  Continue to next ref.
98 		if (duplicate)
99 			continue;
100 
101 		// Push entry onto the vector so we can check for duplicates later.
102 		entries.push_back(BEntry(entry));
103 
104 		launch_terminal(&entry, &terminalPath);
105 
106 	}
107 
108 	// If nothing was selected we'll use the base folder.
109 	if (i == 0) {
110 		if (entry.SetTo(&base_ref) == B_OK)
111 			launch_terminal(&entry, &terminalPath);
112 	}
113 }
114