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