favorites.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2004, 2006, 2010 Martin Fuchs
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 
00020  //
00021  // Explorer and Desktop clone
00022  //
00023  // favorites.cpp
00024  //
00025  // Martin Fuchs, 04.04.2004
00026  //
00027 
00028 
00029 #include <precomp.h>
00030 
00031 #include "startmenu.h"
00032 
00033 
00034 String DecodeURLString(const char* s)
00035 {
00036     TCHAR buffer[BUFFER_LEN];
00037     LPTSTR o = buffer;
00038 
00039     for(const char* p=s; *p; ++p)
00040         if (*p == '%') {
00041             if (!strncmp(p+1, "20", 2)) {
00042                 *o++ = ' ';
00043                 p += 2;
00044             } else
00045                 *o++ = *p;
00046         } else
00047             *o++ = *p;
00048 
00049     return String(buffer, o-buffer);
00050 }
00051 
00052 
00053  /// read .URL file
00054 bool Bookmark::read_url(LPCTSTR path)
00055 {
00056     char line[BUFFER_LEN];
00057 
00058     tifstream in(path);
00059 
00060     while(in.good()) {
00061         in.getline(line, BUFFER_LEN);
00062 
00063         const char* p = line;
00064         while(isspace(*p))
00065             ++p;
00066 
00067         const char* keyword = p;
00068         const char* eq = strchr(p, '=');
00069 
00070         if (eq) {
00071             const char* cont = eq + 1;
00072             while(isspace(*cont))
00073                 ++cont;
00074 
00075             if (!_strnicmp(keyword, "URL", 3))
00076                 _url = DecodeURLString(cont);
00077             else if (!_strnicmp(keyword, "IconFile", 8))
00078                 _icon_path = DecodeURLString(cont);
00079         }
00080     }
00081 
00082     return true;
00083 }
00084 
00085  /// convert XBEL bookmark node
00086 bool Bookmark::read(const_XMLPos& pos)
00087 {
00088     _url = pos.get("href").c_str();
00089 
00090     if (pos.go_down("title")) {
00091         _name = pos->get_content();
00092         pos.back();
00093     }
00094 
00095     if (pos.go_down("desc")) {
00096         _description = pos->get_content();
00097         pos.back();
00098     }
00099 
00100     if (pos.go_down("info")) {
00101         const_XMLChildrenFilter metadata(pos, "metadata");
00102 
00103         for(const_XMLChildrenFilter::const_iterator it=metadata.begin(); it!=metadata.end(); ++it) {
00104             const XMLNode& node = **it;
00105             const_XMLPos sub_pos(&node);
00106 
00107             if (node.get("owner") == "ros-explorer") {
00108                 if (sub_pos.go_down("icon")) {
00109                     _icon_path = sub_pos.get("path").c_str();
00110                     _icon_idx = XS_toi(sub_pos.get("index"));
00111 
00112                     sub_pos.back(); // </icon>
00113                 }
00114             }
00115         }
00116 
00117         pos.back(); // </metadata>
00118         pos.back(); // </info>
00119     }
00120 
00121     return !_url.empty();   // _url is mandatory.
00122 }
00123 
00124  /// write XBEL bookmark node
00125 void Bookmark::write(XMLPos& pos) const
00126 {
00127     pos.create("bookmark");
00128 
00129     pos["href"] = _url.c_str();
00130 
00131     if (!_name.empty()) {
00132         pos.create("title");
00133         pos->set_content(_name);
00134         pos.back();
00135     }
00136 
00137     if (!_description.empty()) {
00138         pos.create("desc");
00139         pos->set_content(_description);
00140         pos.back();
00141     }
00142 
00143     if (!_icon_path.empty()) {
00144         pos.create("info");
00145         pos.create("metadata");
00146         pos["owner"] = "ros-explorer";
00147         pos.create("icon");
00148         pos["path"] = _icon_path.c_str();
00149         pos["index"].printf(XS_TEXT("%d"), _icon_idx);
00150         pos.back(); // </icon>
00151         pos.back(); // </metadata>
00152         pos.back(); // </info>
00153     }
00154 
00155     pos.back();
00156 }
00157 
00158 
00159  /// read bookmark folder from XBEL formated XML tree
00160 void BookmarkFolder::read(const_XMLPos& pos)
00161 {
00162     if (pos.go_down("title")) {
00163         _name = pos->get_content();
00164         pos.back();
00165     }
00166 
00167     if (pos.go_down("desc")) {
00168         _description = pos->get_content();
00169         pos.back();
00170     }
00171 
00172     _bookmarks.read(pos);
00173 }
00174 
00175  /// write bookmark folder content from XBEL formated XML tree
00176 void BookmarkFolder::write(XMLPos& pos) const
00177 {
00178     pos.create("folder");
00179 
00180     if (!_name.empty()) {
00181         pos.create("title");
00182         pos->set_content(_name);
00183         pos.back();
00184     }
00185 
00186     if (!_description.empty()) {
00187         pos.create("desc");
00188         pos->set_content(_description);
00189         pos.back();
00190     }
00191 
00192     _bookmarks.write(pos);
00193 }
00194 
00195 
00196 BookmarkNode::BookmarkNode()
00197  :  _type(BMNT_NONE)
00198 {
00199     _pbookmark = NULL;
00200 }
00201 
00202 BookmarkNode::BookmarkNode(const Bookmark& bm)
00203  :  _type(BMNT_BOOKMARK)
00204 {
00205     _pbookmark = new Bookmark(bm);
00206 }
00207 
00208 BookmarkNode::BookmarkNode(const BookmarkFolder& bmf)
00209  :  _type(BMNT_FOLDER)
00210 {
00211     _pfolder = new BookmarkFolder(bmf);
00212 }
00213 
00214 BookmarkNode::BookmarkNode(const BookmarkNode& other)
00215  :  _type(other._type)
00216 {
00217     if (other._type == BMNT_BOOKMARK)
00218         _pbookmark = new Bookmark(*other._pbookmark);
00219     else if (other._type == BMNT_FOLDER)
00220         _pfolder = new BookmarkFolder(*other._pfolder);
00221     else
00222         _pbookmark = NULL;
00223 }
00224 
00225 BookmarkNode::~BookmarkNode()
00226 {
00227     if (_type == BMNT_BOOKMARK)
00228         delete _pbookmark;
00229     else if (_type == BMNT_FOLDER)
00230         delete _pfolder;
00231 }
00232 
00233 BookmarkNode& BookmarkNode::operator=(const Bookmark& bm)
00234 {
00235     clear();
00236 
00237     _pbookmark = new Bookmark(bm);
00238 
00239     return *this;
00240 }
00241 
00242 BookmarkNode& BookmarkNode::operator=(const BookmarkFolder& bmf)
00243 {
00244     clear();
00245 
00246     _pfolder = new BookmarkFolder(bmf);
00247 
00248     return *this;
00249 }
00250 
00251 BookmarkNode& BookmarkNode::operator=(const BookmarkNode& other)
00252 {
00253     clear();
00254 
00255     _type = other._type;
00256 
00257     if (other._type == BMNT_BOOKMARK)
00258         _pbookmark = new Bookmark(*other._pbookmark);
00259     else if (other._type == BMNT_FOLDER)
00260         _pfolder = new BookmarkFolder(*other._pfolder);
00261 
00262     return *this;
00263 }
00264 
00265 void BookmarkNode::clear()
00266 {
00267     if (_type == BMNT_BOOKMARK) {
00268         delete _pbookmark;
00269         _pbookmark = NULL;
00270     }
00271     else if (_type == BMNT_FOLDER) {
00272         delete _pfolder;
00273         _pfolder = NULL;
00274     }
00275 
00276     _type = BMNT_NONE;
00277 }
00278 
00279 
00280  /// read bookmark list from XBEL formated XML tree
00281 void BookmarkList::read(const_XMLPos& pos)
00282 {
00283     const XMLNode::Children& children = pos->get_children();
00284 
00285     for(XMLNode::Children::const_iterator it=children.begin(); it!=children.end(); ++it) {
00286         const XMLNode& node = **it;
00287         const_XMLPos sub_pos(&node);
00288 
00289         if (node == "folder") {
00290             BookmarkFolder folder;
00291 
00292             folder.read(sub_pos);
00293 
00294             push_back(folder);
00295         } else if (node == "bookmark") {
00296             Bookmark bookmark;
00297 
00298             if (bookmark.read(sub_pos))
00299                 push_back(bookmark);
00300         }
00301     }
00302 }
00303 
00304  /// write bookmark list into XBEL formated XML tree
00305 void BookmarkList::write(XMLPos& pos) const
00306 {
00307     for(const_iterator it=begin(); it!=end(); ++it) {
00308         const BookmarkNode& node = *it;
00309 
00310         if (node._type == BookmarkNode::BMNT_FOLDER) {
00311             const BookmarkFolder& folder = *node._pfolder;
00312 
00313             folder.write(pos);
00314 
00315             pos.back();
00316         } else if (node._type == BookmarkNode::BMNT_BOOKMARK) {
00317             const Bookmark& bookmark = *node._pbookmark;
00318 
00319             if (!bookmark._url.empty())
00320                 bookmark.write(pos);
00321         }
00322     }
00323 }
00324 
00325 
00326  /// fill treeview control with bookmark tree content
00327 void BookmarkList::fill_tree(HWND hwnd, HTREEITEM parent, HIMAGELIST himagelist, HDC hdc_wnd) const
00328 {
00329     TV_INSERTSTRUCT tvi;
00330 
00331     tvi.hParent = parent;
00332     tvi.hInsertAfter = TVI_LAST;
00333 
00334     TV_ITEM& tv = tvi.item;
00335     tv.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM;
00336 
00337     for(const_iterator it=begin(); it!=end(); ++it) {
00338         const BookmarkNode& node = *it;
00339 
00340         tv.lParam = (LPARAM)&node;
00341 
00342         if (node._type == BookmarkNode::BMNT_FOLDER) {
00343             const BookmarkFolder& folder = *node._pfolder;
00344 
00345             tv.pszText = (LPTSTR)folder._name.c_str();
00346             tv.iImage = 3;          // folder
00347             tv.iSelectedImage = 4;  // open folder
00348             HTREEITEM hitem = TreeView_InsertItem(hwnd, &tvi);
00349 
00350             folder._bookmarks.fill_tree(hwnd, hitem, himagelist, hdc_wnd);
00351         } else if (node._type == BookmarkNode::BMNT_BOOKMARK) {
00352             const Bookmark& bookmark = *node._pbookmark;
00353 
00354             tv.pszText = (LPTSTR)bookmark._name.c_str();
00355             tv.iImage = 1;          // bookmark
00356             tv.iSelectedImage = 2;  // selected bookmark
00357 
00358             if (!bookmark._icon_path.empty()) {
00359                 const Icon& icon = g_Globals._icon_cache.extract(bookmark._icon_path, bookmark._icon_idx);
00360 
00361                 if ((ICON_ID)icon != ICID_NONE)
00362                     tv.iImage = tv.iSelectedImage = icon.add_to_imagelist(himagelist, hdc_wnd);
00363             }
00364 
00365             (void)TreeView_InsertItem(hwnd, &tvi);
00366         }
00367     }
00368 }
00369 
00370 
00371  /// import Internet Explorer bookmarks from Favorites folder into bookmark list
00372 void BookmarkList::import_IE_favorites(ShellDirectory& dir, HWND hwnd)
00373 {
00374     TCHAR path[MAX_PATH], ext[_MAX_EXT];
00375 
00376     dir.smart_scan(SORT_NAME, SCAN_DONT_EXTRACT_ICONS);
00377 
00378     for(Entry*entry=dir._down; entry; entry=entry->_next) {
00379         if (entry->_shell_attribs & SFGAO_HIDDEN)   // ignore files like "desktop.ini"
00380             continue;
00381 
00382         String name;
00383 
00384         if (entry->_etype == ET_SHELL)
00385             name = dir._folder.get_name(static_cast<ShellEntry*>(entry)->_pidl);
00386         else
00387             name = entry->_display_name;
00388 
00389         if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
00390             BookmarkFolder new_folder;
00391 
00392             new_folder._name = DecodeXMLString(name);
00393 
00394             if (entry->_etype == ET_SHELL) {
00395                 ShellDirectory new_dir(dir._folder, static_cast<ShellEntry*>(entry)->_pidl, hwnd);
00396                 new_folder._bookmarks.import_IE_favorites(new_dir, hwnd);
00397             } else {
00398                 entry->get_path(path, COUNTOF(path));
00399                 ShellDirectory new_dir(GetDesktopFolder(), path, hwnd);
00400                 new_folder._bookmarks.import_IE_favorites(new_dir, hwnd);
00401             }
00402 
00403             push_back(new_folder);
00404         } else {
00405             Bookmark bookmark;
00406 
00407             bookmark._name = DecodeXMLString(name);
00408 
00409             entry->get_path(path, COUNTOF(path));
00410             _tsplitpath_s(path, NULL, 0, NULL, 0, NULL, 0, ext, COUNTOF(ext));
00411 
00412             if (!_tcsicmp(ext, TEXT(".url"))) {
00413                 bookmark.read_url(path);
00414                 push_back(bookmark);
00415             } else {
00416                 ///@todo read shell links
00417                 //assert(0);
00418             }
00419         }
00420     }
00421 }
00422 
00423 
00424  /// read XBEL bookmark file
00425 bool Favorites::read(LPCTSTR path)
00426 {
00427     XMLDoc xbel;
00428 
00429     if (!xbel.read_file(path)) {
00430         if (!xbel._errors.empty())
00431             MessageBox(g_Globals._hwndDesktop, xbel._errors.str(),
00432                         TEXT("ROS Explorer - reading bookmark file"), MB_OK);
00433     }
00434 
00435     const_XMLPos pos(&xbel);
00436 
00437     if (!pos.go_down("xbel"))
00438         return false;
00439 
00440     super::read(pos);
00441 
00442     pos.back();
00443 
00444     return true;
00445 }
00446 
00447  /// write XBEL bookmark file
00448 void Favorites::write(LPCTSTR path) const
00449 {
00450     XMLDoc xbel;
00451 
00452     XMLPos pos(&xbel);
00453     pos.create("xbel");
00454     super::write(pos);
00455     pos.back();
00456 
00457     xbel._format._doctype._name = "xbel";
00458     xbel._format._doctype._public = "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML";
00459     xbel._format._doctype._system = "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd";
00460 
00461     xbel.write_file(path);
00462 }
00463 
00464  /// import Internet Explorer bookmarks from Favorites folder
00465 bool Favorites::import_IE_favorites(HWND hwnd)
00466 {
00467     WaitCursor wait;
00468 
00469     StartMenuShellDirs dirs;
00470 
00471     try {
00472         dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_COMMON_FAVORITES, hwnd), hwnd));
00473         dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_FAVORITES, hwnd), hwnd));
00474     } catch(COMException&) {
00475     }
00476 
00477     for(StartMenuShellDirs::iterator it=dirs.begin(); it!=dirs.end(); ++it) {
00478         StartMenuDirectory& smd = *it;
00479         ShellDirectory& dir = smd._dir;
00480 
00481         try {
00482             super::import_IE_favorites(dir, hwnd);
00483         } catch(COMException&) {
00484         }
00485     }
00486 
00487     return true;
00488 }

ROS Explorer Source Code Documentation
generated on 02.01.2013 by doxygen

ROS Explorer Homepage