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 } 205 206 // Save 207 /*! \brief Outputs a textual representation of the current recent 208 apps list to the given file stream. 209 210 */ 211 status_t 212 RecentApps::Save(FILE* file) 213 { 214 status_t error = file ? B_OK : B_BAD_VALUE; 215 if (!error) { 216 fprintf(file, "# Recent applications\n"); 217 std::list<std::string>::iterator item; 218 for (item = fAppList.begin(); 219 item != fAppList.end(); 220 item++) 221 { 222 fprintf(file, "RecentApp %s\n", item->c_str()); 223 } 224 fprintf(file, "\n"); 225 } 226 return error; 227 } 228 229 // GetRefForApp 230 /*! \brief Fetches an \c entry_ref for the application with the 231 given signature. 232 233 First the MIME database is checked for a matching application type 234 with a valid app hint attribute. If that fails, a query is established 235 to track down such an application, if there is one available. 236 */ 237 status_t 238 RecentApps::GetRefForApp(const char *appSig, entry_ref *result) 239 { 240 status_t err = appSig && result ? B_OK : B_BAD_VALUE; 241 242 // We'll use BMimeType to check for the app hint, since I'm lazy 243 // and Ingo's on vacation :-P :-) 244 BMimeType mime(appSig); 245 err = mime.InitCheck(); 246 if (!err) 247 err = mime.GetAppHint(result); 248 return err; 249 } 250 251