xref: /haiku/src/servers/registrar/RecentApps.cpp (revision c698a51ee009dcd9509e517f407b4d4b0fb21852)
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 #include <stdio.h>
41 
42 #define DBG(x) (x)
43 //#define DBG(x)
44 #define OUT printf
45 
46 /*!	\class RecentApps
47 	\brief Manages the roster's list of recently launched applications
48 
49 */
50 
51 /*!	\var std::list<std::string> RecentApps::fAppList
52 	\brief The list of app sigs, most recent first
53 
54 	The signatures are expected to be stored all lowercase, as MIME
55 	signatures are case-independent.
56 */
57 
58 // constructor
59 /*!	\brief Creates a new list.
60 
61 	The list is initially empty.
62 */
63 RecentApps::RecentApps()
64 {
65 }
66 
67 // destructor
68 /*!	\brief Frees all resources associated with the object.
69 
70 	Currently does nothing.
71 */
72 RecentApps::~RecentApps()
73 {
74 }
75 
76 // Add
77 /*! \brief Places the app with the given signature at the front of
78 	the recent apps list.
79 
80 	If the app already exists elsewhere in the list, that item is
81 	removed so only one instance exists in the list at any time.
82 
83 	\param appSig The application's signature
84 	\param appFlags The application's flags. If \a appFlags contains
85 	                either \c B_ARGV_ONLY or \c B_BACKGROUND_APP, the
86 	                application is \b not added to the list (but \c B_OK
87 	                is still returned).
88 	\return
89 	- \c B_OK: success (even if the app was not added due to appFlags)
90 	- error code: failure
91 */
92 status_t
93 RecentApps::Add(const char *appSig, int32 appFlags)
94 {
95 	status_t err = appSig ? B_OK : B_BAD_VALUE;
96 	if (!err && !(appFlags & B_ARGV_ONLY) && !(appFlags & B_BACKGROUND_APP)) {
97 		// Store all sigs as lowercase
98 		std::string sig = BPrivate::Storage::to_lower(appSig);
99 
100 		// Remove any previous instance
101 		std::list<std::string>::iterator i;
102 		for (i = fAppList.begin(); i != fAppList.end(); i++) {
103 			if (*i == sig) {
104 				fAppList.erase(i);
105 				break;
106 			}
107 		}
108 		// Add to the front
109 		fAppList.push_front(sig);
110 	}
111 
112 	return err;
113 }
114 
115 // Add
116 /*! \brief Adds the signature of the application referred to by \a ref at
117 	the front of the recent apps list.
118 
119 	The entry is checked for a BEOS:APP_SIG attribute. If that fails, the
120 	app's resources are checked. If no signature can be found, the call
121 	fails.
122 */
123 status_t
124 RecentApps::Add(const entry_ref *ref, int32 appFlags)
125 {
126 	BFile file;
127 	BAppFileInfo info;
128 	char signature[B_MIME_TYPE_LENGTH];
129 
130 	status_t err = ref ? B_OK : B_BAD_VALUE;
131 	if (!err)
132 		err = file.SetTo(ref, B_READ_ONLY);
133 	if (!err)
134 		err = info.SetTo(&file);
135 	if (!err)
136 		err = info.GetSignature(signature);
137 	if (!err)
138 		err = Add(signature, appFlags);
139 	return err;
140 }
141 
142 // Get
143 /*! \brief Returns the first \a maxCount recent apps in the \c BMessage
144 	pointed to by \a list.
145 
146 	The message is cleared first, and \c entry_refs for the the apps are
147 	stored in the \c "refs" field of the message (\c B_REF_TYPE).
148 
149 	If there are fewer than \a maxCount items in the list, the entire
150 	list is returned.
151 
152 	Since BRoster::GetRecentApps() returns \c void, the message pointed
153 	to by \a list is simply cleared if maxCount is invalid (i.e. <= 0).
154 */
155 status_t
156 RecentApps::Get(int32 maxCount, BMessage *list)
157 {
158 	status_t err = list ? B_OK : B_BAD_VALUE;
159 	if (!err) {
160 		// Clear
161 		list->MakeEmpty();
162 
163 		// Fill
164 		std::list<std::string>::iterator item;
165 		int counter = 0;
166 		for (item = fAppList.begin();
167 		       counter < maxCount && item != fAppList.end();
168 		         counter++, item++)
169 		{
170 			entry_ref ref;
171 			status_t error = GetRefForApp(item->c_str(), &ref);
172 			if (!error)
173 				list->AddRef("refs", &ref);
174 			else
175 				DBG(OUT("WARNING: RecentApps::Get(): No ref found for app '%s'\n", item->c_str()));
176 		}
177 	}
178 
179 	return err;
180 }
181 
182 // Clear
183 /*! \brief Clears the list of recently launched apps
184 */
185 status_t
186 RecentApps::Clear()
187 {
188 	fAppList.clear();
189 	return B_OK;
190 }
191 
192 // GetRefForApp
193 /*! \brief Fetches an \c entry_ref for the application with the
194 	given signature.
195 
196 	First the MIME database is checked for a matching application type
197 	with a valid app hint attribute. If that fails, a query is established
198 	to track down such an application, if there is one available.
199 */
200 status_t
201 RecentApps::GetRefForApp(const char *appSig, entry_ref *result)
202 {
203 	status_t err = appSig && result ? B_OK : B_BAD_VALUE;
204 
205 	// We'll use BMimeType to check for the app hint, since I'm lazy
206 	// and Ingo's on vacation :-P :-)
207 	BMimeType mime(appSig);
208 	err = mime.InitCheck();
209 	if (!err)
210 		err = mime.GetAppHint(result);
211 	return err;
212 }
213 
214 // Print
215 /*! \brief Dumps the the current list of apps to stdout.
216 */
217 status_t
218 RecentApps::Print()
219 {
220 	std::list<std::string>::iterator item;
221 	int counter = 1;
222 	for (item = fAppList.begin();
223 	       item != fAppList.end();
224 	         item++)
225 	{
226 		printf("%d: '%s'\n", counter++, item->c_str());
227 	}
228 }
229