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