xref: /haiku/src/servers/registrar/RecentApps.cpp (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		RecentApps.cpp
23 //	Author:			Tyler Dauwalder (tyler@dauwalder.net)
24 //	Description:	Recently launched apps list
25 //------------------------------------------------------------------------------
26 /*! \file RecentApps.cpp
27 	\brief RecentApps class implementation
28 */
29 
30 #include "RecentApps.h"
31 
32 #include <AppFileInfo.h>
33 #include <Entry.h>
34 #include <File.h>
35 #include <Message.h>
36 #include <Mime.h>
37 #include <Roster.h>
38 #include <storage_support.h>
39 
40 #define DBG(x) (x)
41 //#define DBG(x)
42 #define OUT printf
43 
44 /*!	\class RecentApps
45 	\brief Manages the roster's list of recently launched applications
46 
47 */
48 
49 /*!	\var std::list<std::string> RecentApps::fAppList
50 	\brief The list of app sigs, most recent first
51 
52 	The signatures are expected to be stored all lowercase, as MIME
53 	signatures are case-independent.
54 */
55 
56 // constructor
57 /*!	\brief Creates a new list.
58 
59 	The list is initially empty.
60 */
61 RecentApps::RecentApps()
62 {
63 }
64 
65 // destructor
66 /*!	\brief Frees all resources associated with the object.
67 
68 	Currently does nothing.
69 */
70 RecentApps::~RecentApps()
71 {
72 }
73 
74 // Add
75 /*! \brief Places the app with the given signature at the front of
76 	the recent apps list.
77 
78 	If the app already exists elsewhere in the list, that item is
79 	removed so only one instance exists in the list at any time.
80 
81 	\param appSig The application's signature
82 	\param appFlags The application's flags. If \a appFlags contains
83 	                either \c B_ARGV_ONLY or \c B_BACKGROUND_APP, the
84 	                application is \b not added to the list (but \c B_OK
85 	                is still returned).
86 	\return
87 	- \c B_OK: success (even if the app was not added due to appFlags)
88 	- error code: failure
89 */
90 status_t
91 RecentApps::Add(const char *appSig, int32 appFlags)
92 {
93 	status_t err = appSig ? B_OK : B_BAD_VALUE;
94 	if (!err && !(appFlags & B_ARGV_ONLY) && !(appFlags & B_BACKGROUND_APP)) {
95 		// Store all sigs as lowercase
96 		std::string sig = BPrivate::Storage::to_lower(appSig);
97 
98 		// Remove any previous instance
99 		std::list<std::string>::iterator i;
100 		for (i = fAppList.begin(); i != fAppList.end(); i++) {
101 			if (*i == sig) {
102 				fAppList.erase(i);
103 				break;
104 			}
105 		}
106 		// Add to the front
107 		fAppList.push_front(sig);
108 	}
109 
110 	return err;
111 }
112 
113 // Add
114 /*! \brief Adds the signature of the application referred to by \a ref at
115 	the front of the recent apps list.
116 
117 	The entry is checked for a BEOS:APP_SIG attribute. If that fails, the
118 	app's resources are checked. If no signature can be found, the call
119 	fails.
120 */
121 status_t
122 RecentApps::Add(const entry_ref *ref, int32 appFlags)
123 {
124 	BFile file;
125 	BAppFileInfo info;
126 	char signature[B_MIME_TYPE_LENGTH];
127 
128 	status_t err = ref ? B_OK : B_BAD_VALUE;
129 	if (!err)
130 		err = file.SetTo(ref, B_READ_ONLY);
131 	if (!err)
132 		err = info.SetTo(&file);
133 	if (!err)
134 		err = info.GetSignature(signature);
135 	if (!err)
136 		err = Add(signature, appFlags);
137 	return err;
138 }
139 
140 // Get
141 /*! \brief Returns the first \a maxCount recent apps in the \c BMessage
142 	pointed to by \a list.
143 
144 	The message is cleared first, and \c entry_refs for the the apps are
145 	stored in the \c "refs" field of the message (\c B_REF_TYPE).
146 
147 	If there are fewer than \a maxCount items in the list, the entire
148 	list is returned.
149 
150 	Since BRoster::GetRecentApps() returns \c void, the message pointed
151 	to by \a list is simply cleared if maxCount is invalid (i.e. <= 0).
152 */
153 status_t
154 RecentApps::Get(int32 maxCount, BMessage *list)
155 {
156 	status_t err = list ? B_OK : B_BAD_VALUE;
157 	if (!err) {
158 		// Clear
159 		list->MakeEmpty();
160 
161 		// Fill
162 		std::list<std::string>::iterator item;
163 		int counter = 0;
164 		for (item = fAppList.begin();
165 		       counter < maxCount && item != fAppList.end();
166 		         counter++, item++)
167 		{
168 			entry_ref ref;
169 			status_t error = GetRefForApp(item->c_str(), &ref);
170 			if (!error)
171 				list->AddRef("refs", &ref);
172 			else
173 				DBG(OUT("WARNING: RecentApps::Get(): No ref found for app '%s'\n", item->c_str()));
174 		}
175 	}
176 
177 	return err;
178 }
179 
180 // Clear
181 /*! \brief Clears the list of recently launched apps
182 */
183 status_t
184 RecentApps::Clear()
185 {
186 	fAppList.clear();
187 	return B_OK;
188 }
189 
190 // Print
191 /*! \brief Dumps the the current list of apps to stdout.
192 */
193 status_t
194 RecentApps::Print()
195 {
196 	std::list<std::string>::iterator item;
197 	int counter = 1;
198 	for (item = fAppList.begin();
199 	       item != fAppList.end();
200 	         item++)
201 	{
202 		printf("%d: '%s'\n", counter++, item->c_str());
203 	}
204 	return B_OK;
205 }
206 
207 // Save
208 /*! \brief Outputs a textual representation of the current recent
209 	apps list to the given file stream.
210 
211 */
212 status_t
213 RecentApps::Save(FILE* file)
214 {
215 	status_t error = file ? B_OK : B_BAD_VALUE;
216 	if (!error) {
217 		fprintf(file, "# Recent applications\n");
218 		std::list<std::string>::iterator item;
219 		for (item = fAppList.begin();
220 		       item != fAppList.end();
221 		         item++)
222 		{
223 			fprintf(file, "RecentApp %s\n", item->c_str());
224 		}
225 		fprintf(file, "\n");
226 	}
227 	return error;
228 }
229 
230 // GetRefForApp
231 /*! \brief Fetches an \c entry_ref for the application with the
232 	given signature.
233 
234 	First the MIME database is checked for a matching application type
235 	with a valid app hint attribute. If that fails, a query is established
236 	to track down such an application, if there is one available.
237 */
238 status_t
239 RecentApps::GetRefForApp(const char *appSig, entry_ref *result)
240 {
241 	status_t err = appSig && result ? B_OK : B_BAD_VALUE;
242 
243 	// We'll use BMimeType to check for the app hint, since I'm lazy
244 	// and Ingo's on vacation :-P :-)
245 	BMimeType mime(appSig);
246 	err = mime.InitCheck();
247 	if (!err)
248 		err = mime.GetAppHint(result);
249 	return err;
250 }
251 
252