diff --git a/libretroshare/src/dbase/fistore.cc b/libretroshare/src/dbase/fistore.cc index bd2a345b4..02896c5ab 100644 --- a/libretroshare/src/dbase/fistore.cc +++ b/libretroshare/src/dbase/fistore.cc @@ -405,7 +405,7 @@ int FileIndexStore::SearchHash(std::string hash, std::list &results) } -int FileIndexStore::SearchKeywords(std::list keywords, std::list &results) const +int FileIndexStore::SearchKeywords(std::list keywords, std::list &results,uint32_t flags) const { lockData(); std::map::const_iterator pit; @@ -417,49 +417,52 @@ int FileIndexStore::SearchKeywords(std::list keywords, std::listsecond)->searchTerms(keywords, firesults); - /* translate results */ - for(rit = firesults.begin(); rit != firesults.end(); rit++) + if(flags & DIR_FLAGS_REMOTE) + for(pit = indices.begin(); pit != indices.end(); pit++) { - FileDetail fd; - fd.id = pit->first; - fd.name = (*rit)->name; - fd.hash = (*rit)->hash; - fd.path = ""; /* TODO */ - fd.size = (*rit)->size; - fd.age = now - (*rit)->modtime; - fd.rank = (*rit)->pop; + firesults.clear(); + + (pit->second)->searchTerms(keywords, firesults); + /* translate results */ + for(rit = firesults.begin(); rit != firesults.end(); rit++) + { + FileDetail fd; + fd.id = pit->first; + fd.name = (*rit)->name; + fd.hash = (*rit)->hash; + fd.path = ""; /* TODO */ + fd.size = (*rit)->size; + fd.age = now - (*rit)->modtime; + fd.rank = (*rit)->pop; + + results.push_back(fd); + } - results.push_back(fd); } - } - if (localindex) - { - firesults.clear(); - - localindex->searchTerms(keywords, firesults); - /* translate results */ - for(rit = firesults.begin(); rit != firesults.end(); rit++) + if(flags & DIR_FLAGS_LOCAL) + if (localindex) { - FileDetail fd; - fd.id = "Local"; //localId; - fd.name = (*rit)->name; - fd.hash = (*rit)->hash; - fd.path = ""; /* TODO */ - fd.size = (*rit)->size; - fd.age = now - (*rit)->modtime; - fd.rank = (*rit)->pop; + firesults.clear(); + + localindex->searchTerms(keywords, firesults); + /* translate results */ + for(rit = firesults.begin(); rit != firesults.end(); rit++) + { + FileDetail fd; + fd.id = "Local"; //localId; + fd.name = (*rit)->name; + fd.hash = (*rit)->hash; + fd.path = ""; /* TODO */ + fd.size = (*rit)->size; + fd.age = now - (*rit)->modtime; + fd.rank = (*rit)->pop; + + results.push_back(fd); + } - results.push_back(fd); } - } - unlockData(); return results.size(); } diff --git a/libretroshare/src/dbase/fistore.h b/libretroshare/src/dbase/fistore.h index ad3f6e319..76d0821f9 100644 --- a/libretroshare/src/dbase/fistore.h +++ b/libretroshare/src/dbase/fistore.h @@ -74,7 +74,7 @@ virtual int loadCache(const CacheData &data); /* actual load, once data availa int SearchHash(std::string hash, std::list &results) const; /* Search Interface - For Search Interface */ - int SearchKeywords(std::list terms, std::list &results) const; + int SearchKeywords(std::list terms, std::list &results,uint32_t flags) const; /* Search Interface - for Adv Search Interface */ int searchBoolExp(Expression * exp, std::list &results) const; diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc index 5c13b27ae..5110f7a20 100644 --- a/libretroshare/src/ft/ftserver.cc +++ b/libretroshare/src/ft/ftserver.cc @@ -383,7 +383,7 @@ int ftServer::RequestDirDetails(void *ref, DirDetails &details, uint32_t flags) /***************************************************************/ -int ftServer::SearchKeywords(std::list keywords, std::list &results) +int ftServer::SearchKeywords(std::list keywords, std::list &results,uint32_t flags) { #ifdef SERVER_DEBUG std::cerr << "ftServer::SearchKeywords()"; @@ -396,7 +396,7 @@ int ftServer::SearchKeywords(std::list keywords, std::listSearchKeywords(keywords, results); + return mFiStore->SearchKeywords(keywords, results,flags); } int ftServer::SearchBoolExp(Expression * exp, std::list &results) diff --git a/libretroshare/src/ft/ftserver.h b/libretroshare/src/ft/ftserver.h index 3957e5754..8926ece92 100644 --- a/libretroshare/src/ft/ftserver.h +++ b/libretroshare/src/ft/ftserver.h @@ -140,7 +140,7 @@ virtual bool ExtraFileMove(std::string fname, std::string hash, uint64_t size, virtual int RequestDirDetails(std::string uid, std::string path, DirDetails &details); virtual int RequestDirDetails(void *ref, DirDetails &details, uint32_t flags); -virtual int SearchKeywords(std::list keywords, std::list &results); +virtual int SearchKeywords(std::list keywords, std::list &results,uint32_t flags); virtual int SearchBoolExp(Expression * exp, std::list &results); /*** diff --git a/libretroshare/src/rsiface/rsfiles.h b/libretroshare/src/rsiface/rsfiles.h index 3f8575035..58335ee48 100644 --- a/libretroshare/src/rsiface/rsfiles.h +++ b/libretroshare/src/rsiface/rsfiles.h @@ -130,7 +130,7 @@ virtual bool ExtraFileMove(std::string fname, std::string hash, uint64_t size, virtual int RequestDirDetails(std::string uid, std::string path, DirDetails &details) = 0; virtual int RequestDirDetails(void *ref, DirDetails &details, uint32_t flags) = 0; -virtual int SearchKeywords(std::list keywords, std::list &results) = 0; +virtual int SearchKeywords(std::list keywords, std::list &results,uint32_t flags) = 0; virtual int SearchBoolExp(Expression * exp, std::list &results) = 0; /*** diff --git a/libretroshare/src/rsiface/rsiface.h b/libretroshare/src/rsiface/rsiface.h index 215e54f54..9a58454e5 100644 --- a/libretroshare/src/rsiface/rsiface.h +++ b/libretroshare/src/rsiface/rsiface.h @@ -35,6 +35,9 @@ class NotifyBase; class RsIface; class RsControl; class RsInit; +#ifdef TURTLE_HOPPING +struct TurtleFileInfo ; +#endif /* declare single RsIface for everyone to use! */ @@ -200,6 +203,9 @@ class NotifyBase virtual void notifyErrorMsg(int list, int sev, std::string msg) { (void) list; (void) sev; (void) msg; return; } virtual void notifyChat() { return; } virtual void notifyHashingInfo(std::string fileinfo) { (void)fileinfo; return ; } +#ifdef TURTLE_HOPPING + virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list& files) { (void)files; } +#endif }; const int NOTIFY_LIST_NEIGHBOURS = 1; diff --git a/libretroshare/src/rsiface/rsturtle.h b/libretroshare/src/rsiface/rsturtle.h index 0bfb4937a..abaf4e24e 100644 --- a/libretroshare/src/rsiface/rsturtle.h +++ b/libretroshare/src/rsiface/rsturtle.h @@ -35,6 +35,16 @@ extern RsTurtle *rsTurtle ; typedef uint32_t TurtleRequestId ; +// This is the structure used to send back results of the turtle search +// to the notifyBase class. + +struct TurtleFileInfo +{ + std::string hash ; + std::string name ; + uint64_t size ; +}; + // Interface class for turtle hopping. // // This class mainly interacts with the turtle router, that is responsible diff --git a/libretroshare/src/rsserver/p3files.cc b/libretroshare/src/rsserver/p3files.cc index bdf3a3ae2..6217a44af 100644 --- a/libretroshare/src/rsserver/p3files.cc +++ b/libretroshare/src/rsserver/p3files.cc @@ -252,12 +252,12 @@ int p3Files::RequestDirDetails(void *ref, DirDetails &details, uint32_t flags) } -int p3Files::SearchKeywords(std::list keywords, std::list &results) +int p3Files::SearchKeywords(std::list keywords, std::list &results,uint32_t flags) { lockRsCore(); /* LOCK */ /* call to filedexmServer */ - int val = mServer->SearchKeywords(keywords, results); + int val = mServer->SearchKeywords(keywords, results,flags); unlockRsCore(); /* UNLOCK */ diff --git a/libretroshare/src/server/filedexserver.cc b/libretroshare/src/server/filedexserver.cc index bff863b72..127a90651 100644 --- a/libretroshare/src/server/filedexserver.cc +++ b/libretroshare/src/server/filedexserver.cc @@ -393,10 +393,9 @@ int filedexserver::RequestDirDetails(void *ref, DirDetails &details, uint32_t fl return fiStore->RequestDirDetails(ref, details, flags); } -int filedexserver::SearchKeywords(std::list keywords, - std::list &results) +int filedexserver::SearchKeywords(std::list keywords,std::list &results,uint32_t flags) { - return fiStore->SearchKeywords(keywords, results); + return fiStore->SearchKeywords(keywords, results,flags); } int filedexserver::SearchBoolExp(Expression * exp, std::list &results) diff --git a/libretroshare/src/services/p3turtle.cc b/libretroshare/src/services/p3turtle.cc index 6518945b7..63cf9cc81 100644 --- a/libretroshare/src/services/p3turtle.cc +++ b/libretroshare/src/services/p3turtle.cc @@ -27,6 +27,7 @@ #include "rsiface/rsiface.h" #include "rsiface/rspeers.h" +#include "rsiface/rsfiles.h" #include "pqi/p3authmgr.h" #include "pqi/p3connmgr.h" @@ -54,6 +55,7 @@ p3turtle::p3turtle(p3ConnectMgr *cm) :p3Service(RS_SERVICE_TYPE_TURTLE), mConnMg { RsStackMutex stack(mTurtleMtx); /********** STACK LOCKED MTX ******/ + srand48(time(NULL)) ; addSerialType(new RsTurtleSerialiser()); } @@ -94,10 +96,20 @@ TurtleRequestId p3turtle::turtleSearch(const std::string& string_to_match) TurtleRequestId id = generateRandomRequestId() ; - // form a request packet + // Form a request packet that simulates a request from us. // RsTurtleSearchRequestItem *item = new RsTurtleSearchRequestItem ; +#ifdef P3TURTLE_DEBUG + std::cerr << "performing search. OwnId = " << mConnMgr->getOwnId() << std::endl ; +#endif + while(mConnMgr->getOwnId() == "") + { + std::cerr << "... waitting for connect manager to form own id." << std::endl ; + sleep(1) ; + } + + item->PeerId(mConnMgr->getOwnId()) ; item->match_string = string_to_match ; item->request_id = id ; item->depth = 0 ; @@ -122,8 +134,8 @@ void p3turtle::turtleDownload(const std::string& file_hash) int p3turtle::handleIncoming() { #ifdef P3TURTLE_DEBUG - std::cerr << "p3turtle::handleIncoming()"; - std::cerr << std::endl; +// std::cerr << "p3turtle::handleIncoming()"; +// std::cerr << std::endl; #endif int nhandled = 0; @@ -160,7 +172,7 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item) // - If the item destimation is #ifdef P3TURTLE_DEBUG - std::cerr << "Received search request: " << std::endl ; + std::cerr << "Received search request from peer " << item->PeerId() << ": " << std::endl ; item->print(std::cerr,0) ; #endif // If the item contains an already handled search request, give up. This @@ -186,7 +198,7 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item) #ifdef P3TURTLE_DEBUG std::cerr << " Request not from us. Performing local search" << std::endl ; #endif - std::map result ; + std::list result ; performLocalSearch(item->match_string,result) ; if(!result.empty()) @@ -203,7 +215,7 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item) res_item->PeerId(item->PeerId()) ; // send back to the same guy #ifdef P3TURTLE_DEBUG - std::cerr << " " << result.size() << " matches found. Sending back to origin." << std::endl ; + std::cerr << " " << result.size() << " matches found. Sending back to origin (" << res_item->PeerId() << ")." << std::endl ; #endif sendItem(res_item) ; } @@ -215,6 +227,9 @@ void p3turtle::handleSearchRequest(RsTurtleSearchRequestItem *item) { std::list onlineIds ; mConnMgr->getOnlineList(onlineIds); +#ifdef P3TURTLE_DEBUG + std::cerr << " Looking for online peers" << std::endl ; +#endif for(std::list::const_iterator it(onlineIds.begin());it!=onlineIds.end();++it) if(*it != item->PeerId()) @@ -259,6 +274,8 @@ void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item) // Is this result's target actually ours ? + ++(item->depth) ; // increase depth + if(it->second == mConnMgr->getOwnId()) returnSearchResult(item) ; // Yes, so send upward. else @@ -268,8 +285,6 @@ void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item) #endif RsTurtleSearchResultItem *fwd_item = new RsTurtleSearchResultItem(*item) ; // copy the item - ++(fwd_item->depth) ; // increase depth - // normally here, we should setup the forward adress, so that the owner's of the files found can be further reached by a tunnel. fwd_item->PeerId(it->second) ; @@ -281,6 +296,7 @@ void p3turtle::handleSearchResult(RsTurtleSearchResultItem *item) std::ostream& RsTurtleSearchRequestItem::print(std::ostream& o, uint16_t) { o << "Search request:" << std::endl ; + o << " direct origin: \"" << PeerId() << "\"" << std::endl ; o << " match string: \"" << match_string << "\"" << std::endl ; o << " Req. Id: " << request_id << std::endl ; o << " Depth : " << depth << std::endl ; @@ -292,13 +308,13 @@ std::ostream& RsTurtleSearchResultItem::print(std::ostream& o, uint16_t) { o << "Search result:" << std::endl ; - o << " Peer id: " << peer_id << std::endl ; + o << " Peer id: " << PeerId() << std::endl ; o << " Depth : " << depth << std::endl ; o << " Req. Id: " << request_id << std::endl ; o << " Files:" << std::endl ; - for(std::map::const_iterator it(result.begin());it!=result.end();++it) - o << " " << it->first << " " << it->second << std::endl ; + for(std::list::const_iterator it(result.begin());it!=result.end();++it) + o << " " << it->hash << " " << it->size << " " << it->name << std::endl ; return o ; } @@ -307,8 +323,11 @@ void p3turtle::returnSearchResult(RsTurtleSearchResultItem *item) { // just cout for now, but it should be notified to the gui - std::cerr << "Received result for search request: " << std::endl ; - item->print(std::cerr,0) ; +#ifdef P3TURTLE_DEBUG + std::cerr << " Returning result for search request " << item->request_id << " upwards." << std::endl ; +#endif + + rsicontrol->getNotify().notifyTurtleSearchResult(item->request_id,item->result) ; } /************* from pqiMonitor *******************/ @@ -350,6 +369,61 @@ uint32_t RsTurtleSearchRequestItem::serial_size() return s ; } +uint32_t RsTurtleSearchResultItem::serial_size() +{ + uint32_t s = 0 ; + + s += 8 ; // header + s += 4 ; // search request id + s += 2 ; // depth + s += 4 ; // number of results + + for(std::list::const_iterator it(result.begin());it!=result.end();++it) + { + s += 8 ; // file size + s += GetTlvStringSize(it->hash) ; // file hash + s += GetTlvStringSize(it->name) ; // file name + } + + return s ; +} + +RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size) +{ + // look what we have... + + /* get the type */ + uint32_t rstype = getRsItemId(data); +#ifdef P3TURTLE_DEBUG + std::cerr << "p3turtle: deserialising packet: " << std::endl ; +#endif + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_TURTLE != getRsItemService(rstype))) + { +#ifdef P3TURTLE_DEBUG + std::cerr << " Wrong type !!" << std::endl ; +#endif + return NULL; /* wrong type */ + } + + try + { + switch(getRsItemSubType(rstype)) + { + case RS_TURTLE_SUBTYPE_SEARCH_REQUEST: return new RsTurtleSearchRequestItem(data,*size) ; + case RS_TURTLE_SUBTYPE_SEARCH_RESULT: return new RsTurtleSearchResultItem(data,*size) ; + + default: + std::cerr << "Unknown packet type in RsTurtle!" << std::endl ; + return NULL ; + } + } + catch(std::exception& e) + { + std::cerr << "Exception raised: " << e.what() << std::endl ; + return NULL ; + } +} + bool RsTurtleSearchRequestItem::serialize(void *data,uint32_t& pktsize) { uint32_t tlvsize = serial_size(); @@ -384,21 +458,24 @@ bool RsTurtleSearchRequestItem::serialize(void *data,uint32_t& pktsize) return ok; } -uint32_t RsTurtleSearchResultItem::serial_size() +RsTurtleSearchRequestItem::RsTurtleSearchRequestItem(void *data,uint32_t pktsize) + : RsTurtleItem(RS_TURTLE_SUBTYPE_SEARCH_REQUEST) { - uint32_t s = 0 ; +#ifdef P3TURTLE_DEBUG + std::cerr << " type = search request" << std::endl ; +#endif + uint32_t offset = 8; // skip the header + uint32_t rssize = getRsItemSize(data); + bool ok = true ; - s += 8 ; // header - s += 4 ; // search request id - s += 4 ; // number of results + ok &= GetTlvString(data, pktsize, &offset, TLV_TYPE_STR_VALUE, match_string); // file hash + ok &= getRawUInt32(data, pktsize, &offset, &request_id); + ok &= getRawUInt16(data, pktsize, &offset, &depth); - for(std::map::const_iterator it(result.begin());it!=result.end();++it) - { - s += GetTlvStringSize(it->first) ; // file hash - s += GetTlvStringSize(it->second) ; // file name - } - - return s ; + if (offset != rssize) + throw std::runtime_error("Size error while deserializing.") ; + if (!ok) + throw std::runtime_error("Unknown error while deserializing.") ; } bool RsTurtleSearchResultItem::serialize(void *data,uint32_t& pktsize) @@ -421,12 +498,14 @@ bool RsTurtleSearchResultItem::serialize(void *data,uint32_t& pktsize) /* add mandatory parts first */ ok &= setRawUInt32(data, tlvsize, &offset, request_id); + ok &= setRawUInt16(data, tlvsize, &offset, depth); ok &= setRawUInt32(data, tlvsize, &offset, result.size()); - for(std::map::const_iterator it(result.begin());it!=result.end();++it) + for(std::list::const_iterator it(result.begin());it!=result.end();++it) { - ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_HASH_SHA1, it->first); // file hash - ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, it->second); // file name + ok &= setRawUInt64(data, tlvsize, &offset, it->size); // file size + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_HASH_SHA1, it->hash); // file hash + ok &= SetTlvString(data, tlvsize, &offset, TLV_TYPE_STR_NAME, it->name); // file name } if (offset != tlvsize) @@ -438,35 +517,15 @@ bool RsTurtleSearchResultItem::serialize(void *data,uint32_t& pktsize) } return ok; - } -RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size) -{ - // look what we have... - - /* get the type */ - uint32_t rstype = getRsItemId(data); - - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_TURTLE != getRsItemService(rstype))) - { - return NULL; /* wrong type */ - } - - switch(getRsItemSubType(rstype)) - { - case RS_TURTLE_SUBTYPE_SEARCH_REQUEST: return new RsTurtleSearchResultItem(data,*size) ; - case RS_TURTLE_SUBTYPE_SEARCH_RESULT: return new RsTurtleSearchResultItem(data,*size) ; - - default: - std::cerr << "Unknown packet type in RsTurtle!" << std::endl ; - return NULL ; - } -} RsTurtleSearchResultItem::RsTurtleSearchResultItem(void *data,uint32_t pktsize) : RsTurtleItem(RS_TURTLE_SUBTYPE_SEARCH_RESULT) { +#ifdef P3TURTLE_DEBUG + std::cerr << " type = search result" << std::endl ; +#endif uint32_t offset = 8; // skip the header uint32_t rssize = getRsItemSize(data); @@ -475,18 +534,23 @@ RsTurtleSearchResultItem::RsTurtleSearchResultItem(void *data,uint32_t pktsize) bool ok = true ; uint32_t s ; ok &= getRawUInt32(data, pktsize, &offset, &request_id); + ok &= getRawUInt16(data, pktsize, &offset, &depth); ok &= getRawUInt32(data, pktsize, &offset, &s) ; +#ifdef P3TURTLE_DEBUG + std::cerr << " reuqest_id=" << request_id << ", depth=" << depth << ", s=" << s << std::endl ; +#endif result.clear() ; for(uint i=0;i& result) +{ + /* call to core */ + std::list initialResults; + std::list words ; + + // to do: split search string into words. + words.push_back(s) ; + + // now, search! + rsFiles->SearchKeywords(words, initialResults,DIR_FLAGS_LOCAL); + + result.clear() ; + + for(std::list::const_iterator it(initialResults.begin());it!=initialResults.end();++it) + { + TurtleFileInfo i ; + i.hash = it->hash ; + i.size = it->size ; + i.name = it->name ; + + result.push_back(i) ; + } +} + + diff --git a/libretroshare/src/services/p3turtle.h b/libretroshare/src/services/p3turtle.h index c49e8d259..feb5d1078 100644 --- a/libretroshare/src/services/p3turtle.h +++ b/libretroshare/src/services/p3turtle.h @@ -86,7 +86,7 @@ class RsTurtleSearchResultItem: public RsTurtleItem TurtleRequestId request_id ; // randomly generated request id. - std::map result ; + std::list result ; virtual std::ostream& print(std::ostream& o, uint16_t) ; protected: @@ -175,7 +175,7 @@ class p3turtle: public p3Service, public pqiMonitor, public RsTurtle // int handleOutgoing(); // Performs a search calling local cache and search structure. - void performLocalSearch(const std::string& s,std::map& result) {} + void performLocalSearch(const std::string& s,std::list& result) ; void handleSearchRequest(RsTurtleSearchRequestItem *item); void handleSearchResult(RsTurtleSearchResultItem *item); diff --git a/retroshare-gui/src/RetroShare.pro b/retroshare-gui/src/RetroShare.pro index 86f8cca82..50da73758 100644 --- a/retroshare-gui/src/RetroShare.pro +++ b/retroshare-gui/src/RetroShare.pro @@ -17,7 +17,7 @@ linux-g++ { LIBS += ../../../../lib/linux-g++/libssl.a LIBS += ../../../../lib/linux-g++/libcrypto.a LIBS += -lQtUiTools - LIBS += -lz + LIBS += -lz } linux-g++-64 { OBJECTS_DIR = temp/linux-g++-64/obj @@ -489,6 +489,17 @@ TRANSLATIONS += \ lang/retroshare_sr.ts \ lang/retroshare_se.ts +# To compile for turtle hopping. I'm using this flag to avoid conflict while developping. +# Just do a +# qmake CONFIG=turtle + +turtle { + SOURCES += gui/TurtleSearchDialog.cpp + HEADERS += rsiface/rsturtle.h gui/TurtleSearchDialog.h + FORMS += gui/TurtleSearchDialog.ui + DEFINES *= TURTLE_HOPPING +} + diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index 601a796a0..636c2f034 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -48,6 +48,10 @@ #include "games/qbackgammon/bgwindow.h" //#include "smplayer.h" +#ifdef TURTLE_HOPPING +#include "gui/TurtleSearchDialog.h" +#endif + #include "statusbar/peerstatus.h" #include "Preferences/PreferencesWindow.h" #include "Settings/gsettingswin.h" @@ -75,6 +79,7 @@ #define IMAGE_FILES ":/images/fileshare24.png" #define IMAGE_CHANNELS ":/images/channels.png" #define IMAGE_FORUMS ":/images/konversation.png" +#define IMAGE_TURTLE ":/images/turtle.png" #define IMAGE_PREFERENCES ":/images/kcmsystem24.png" #define IMAGE_CHAT ":/images/groupchat.png" #define IMAGE_RETROSHARE ":/images/rstray3.png" @@ -179,7 +184,10 @@ MainWindow::MainWindow(QWidget* parent, Qt::WFlags flags) //PeersFeed *peersFeed = NULL; //ui.stackPages->add(peersFeed = new PeersFeed(ui.stackPages), // createPageAction(QIcon(IMAGE_PEERS), tr("Peers"), grp)); - +#ifdef TURTLE_HOPPING + ui.stackPages->add(turtleDialog = new TurtleSearchDialog(ui.stackPages), + createPageAction(QIcon(IMAGE_TURTLE), tr("Turtle"), grp)); +#endif ui.stackPages->add(searchDialog = new SearchDialog(ui.stackPages), createPageAction(QIcon(IMAGE_SEARCH), tr("Search"), grp)); diff --git a/retroshare-gui/src/gui/MainWindow.h b/retroshare-gui/src/gui/MainWindow.h index 4fdc2901e..f883fc272 100644 --- a/retroshare-gui/src/gui/MainWindow.h +++ b/retroshare-gui/src/gui/MainWindow.h @@ -39,6 +39,9 @@ #include "MessengerWindow.h" #include "ApplicationWindow.h" #include "PluginsPage.h" +#ifdef TURTLE_HOPPING +#include "TurtleSearchDialog.h" +#endif #include "Preferences/PreferencesWindow.h" #include "Settings/gsettingswin.h" @@ -95,6 +98,9 @@ public: NetworkDialog *networkDialog; PeersDialog *peersDialog; SearchDialog *searchDialog; +#ifdef TURTLE_HOPPING + TurtleSearchDialog *turtleDialog; +#endif TransfersDialog *transfersDialog; ChatDialog *chatDialog; MessagesDialog *messagesDialog; diff --git a/retroshare-gui/src/gui/SearchDialog.cpp b/retroshare-gui/src/gui/SearchDialog.cpp index a01e8960b..c686cca9b 100644 --- a/retroshare-gui/src/gui/SearchDialog.cpp +++ b/retroshare-gui/src/gui/SearchDialog.cpp @@ -26,9 +26,6 @@ #include "rsiface/rsexpr.h" #include "rsiface/rsfiles.h" #include "rsiface/rspeers.h" -#ifdef TURTLE_HOPPING -#include "rsiface/rsturtle.h" -#endif #include "util/misc.h" #include @@ -419,12 +416,6 @@ void SearchDialog::advancedSearch(Expression* expression) void SearchDialog::searchKeywords() { -#ifdef TURTLE_HOPPING - QString qTxt = ui.lineEdit->text(); - std::string txt = qTxt.toStdString(); - - TurtleRequestId id = rsTurtle->turtleSearch(txt) ; -#else QString qTxt = ui.lineEdit->text(); std::string txt = qTxt.toStdString(); @@ -449,7 +440,7 @@ void SearchDialog::searchKeywords() std::list initialResults; std::list * finalResults = 0; - rsFiles -> SearchKeywords(words, initialResults); + rsFiles -> SearchKeywords(words, initialResults,DIR_FLAGS_LOCAL | DIR_FLAGS_REMOTE); /* which extensions do we use? */ QString qExt, qName; int extIndex; @@ -497,7 +488,6 @@ void SearchDialog::searchKeywords() /* abstraction to allow reusee of tree rendering code */ resultsToTree(txt, *finalResults); -#endif } void SearchDialog::resultsToTree(std::string txt, std::list results) diff --git a/retroshare-gui/src/gui/TurtleSearchDialog.cpp b/retroshare-gui/src/gui/TurtleSearchDialog.cpp new file mode 100644 index 000000000..423451f1b --- /dev/null +++ b/retroshare-gui/src/gui/TurtleSearchDialog.cpp @@ -0,0 +1,660 @@ +/**************************************************************** + * RShare is distributed under the following license: + * + * Copyright (C) 2006, crypton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + ****************************************************************/ + +#include + +#include "rshare.h" +#include "TurtleSearchDialog.h" +#include "rsiface/rsiface.h" +#include "rsiface/rsexpr.h" +#include "rsiface/rsfiles.h" +#include "rsiface/rspeers.h" +#ifdef TURTLE_HOPPING +#include "rsiface/rsturtle.h" +#endif +#include "util/misc.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Images for context menu icons */ +#define IMAGE_START ":/images/download.png" +#define IMAGE_REMOVE ":/images/delete.png" +#define IMAGE_REMOVEALL ":/images/deleteall.png" + +/* Key for UI Preferences */ +#define UI_PREF_ADVANCED_SEARCH "UIOptions/AdvancedSearch" + +/* indicies for search results item columns SR_ = Search Result */ +/* indicies for search results item columns SR_ = Search Result */ +#define SR_ICON_COL 0 +#define SR_NAME_COL 1 +#define SR_SIZE_COL 2 +#define SR_ID_COL 3 +#define SR_TYPE_COL 4 +#define SR_HASH_COL 5 +#define SR_SEARCH_ID_COL 6 + +#define SR_UID_COL 7 +#define SR_REALSIZE_COL 8 + +/* indicies for search summary item columns SS_ = Search Summary */ +#define SS_TEXT_COL 0 +#define SS_COUNT_COL 1 +#define SS_SEARCH_ID_COL 2 + +/* static members */ +/* These indices MUST be identical to their equivalent indices in the combobox */ +const int TurtleSearchDialog::FILETYPE_IDX_ANY = 0; +const int TurtleSearchDialog::FILETYPE_IDX_ARCHIVE = 1; +const int TurtleSearchDialog::FILETYPE_IDX_AUDIO = 2; +const int TurtleSearchDialog::FILETYPE_IDX_CDIMAGE = 3; +const int TurtleSearchDialog::FILETYPE_IDX_DOCUMENT = 4; +const int TurtleSearchDialog::FILETYPE_IDX_PICTURE = 5; +const int TurtleSearchDialog::FILETYPE_IDX_PROGRAM = 6; +const int TurtleSearchDialog::FILETYPE_IDX_VIDEO = 7; +QMap * TurtleSearchDialog::FileTypeExtensionMap = new QMap(); +bool TurtleSearchDialog::initialised = false; + +/** Constructor */ +TurtleSearchDialog::TurtleSearchDialog(QWidget *parent) +: MainPage(parent), + advSearchDialog(NULL), + contextMnu(NULL), contextMnu2(NULL), + nextSearchId(1) +{ + /* Invoke the Qt Designer generated object setup routine */ + ui.setupUi(this); + + /* initialise the filetypes mapping */ + if (!TurtleSearchDialog::initialised) + { + initialiseFileTypeMappings(); + } + + /* Advanced search panel specifica */ + RshareSettings rsharesettings; + QString key (UI_PREF_ADVANCED_SEARCH); + bool useAdvanced = rsharesettings.value(key, QVariant(false)).toBool(); + if (useAdvanced) + { + ui.toggleAdvancedSearchBtn->setChecked(true); + ui.SimpleSearchPanel->hide(); + } else { + ui.AdvancedSearchPanel->hide(); + } + + connect(ui.toggleAdvancedSearchBtn, SIGNAL(toggled(bool)), this, SLOT(toggleAdvancedSearchDialog(bool))); + connect(ui.focusAdvSearchDialogBtn, SIGNAL(clicked()), this, SLOT(showAdvSearchDialog())); + + /* End Advanced Search Panel specifics */ + + + connect( ui.searchResultWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( searchtableWidgetCostumPopupMenu( QPoint ) ) ); + + connect( ui.searchSummaryWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( searchtableWidget2CostumPopupMenu( QPoint ) ) ); + + connect( ui.lineEdit, SIGNAL( returnPressed ( void ) ), this, SLOT( searchKeywords( void ) ) ); + connect( ui.pushButtonsearch, SIGNAL( released ( void ) ), this, SLOT( searchKeywords( void ) ) ); + connect( ui.pushButtonDownload, SIGNAL( released ( void ) ), this, SLOT( download( void ) ) ); + //connect( ui.searchSummaryWidget, SIGNAL( itemSelectionChanged ( void ) ), this, SLOT( selectSearchResults( void ) ) ); + + connect ( ui.searchSummaryWidget, SIGNAL( currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem * ) ), + this, SLOT( selectSearchResults( void ) ) ); + + + /* hide the Tree +/- */ + ui.searchResultWidget -> setRootIsDecorated( false ); + ui.searchResultWidget -> setColumnHidden( SR_UID_COL,true ); + ui.searchResultWidget -> setColumnHidden( SR_REALSIZE_COL,true ); + ui.searchSummaryWidget -> setRootIsDecorated( false ); + + /* make it extended selection */ + ui.searchResultWidget -> setSelectionMode(QAbstractItemView::ExtendedSelection); + + + /* Set header resize modes and initial section sizes */ + ui.searchSummaryWidget->setColumnCount(3); + + QHeaderView * _smheader = ui.searchSummaryWidget->header () ; + _smheader->setResizeMode (0, QHeaderView::Interactive); + _smheader->setResizeMode (1, QHeaderView::Interactive); + _smheader->setResizeMode (2, QHeaderView::Interactive); + + _smheader->resizeSection ( 0, 80 ); + _smheader->resizeSection ( 1, 75 ); + _smheader->resizeSection ( 2, 75 ); + + ui.searchResultWidget->setColumnCount(6); + _smheader = ui.searchResultWidget->header () ; + _smheader->setResizeMode (0, QHeaderView::Custom); + _smheader->setResizeMode (1, QHeaderView::Interactive); + _smheader->setResizeMode (2, QHeaderView::Interactive); + _smheader->setResizeMode (3, QHeaderView::Interactive); + + _smheader->resizeSection ( 0, 20 ); + _smheader->resizeSection ( 1, 220 ); + _smheader->resizeSection ( 2, 75 ); + _smheader->resizeSection ( 3, 75 ); + _smheader->resizeSection ( 4, 75 ); + _smheader->resizeSection ( 5, 240 ); + + + // set header text aligment + QTreeWidgetItem * headerItem = ui.searchResultWidget->headerItem(); + headerItem->setTextAlignment(2, Qt::AlignRight | Qt::AlignRight); + headerItem->setTextAlignment(3, Qt::AlignRight | Qt::AlignRight); + + ui.searchResultWidget->sortItems(SR_NAME_COL, Qt::AscendingOrder); + + + +/* Hide platform specific features */ +#ifdef Q_WS_WIN + +#endif +} + +void TurtleSearchDialog::initialiseFileTypeMappings() +{ + /* edit these strings to change the range of extensions recognised by the search */ + TurtleSearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ANY, ""); + TurtleSearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_AUDIO, "aac aif iff m3u mid midi mp3 mpa ogg ra ram wav wma"); + TurtleSearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_ARCHIVE, "7z bz2 gz pkg rar sea sit sitx tar zip"); + TurtleSearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_CDIMAGE, "iso nrg mdf"); + TurtleSearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_DOCUMENT, "doc odt ott rtf pdf ps txt log msg wpd wps" ); + TurtleSearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PICTURE, "3dm 3dmf ai bmp drw dxf eps gif ico indd jpe jpeg jpg mng pcx pcc pct pgm " + "pix png psd psp qxd qxprgb sgi svg tga tif tiff xbm xcf"); + TurtleSearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_PROGRAM, "app bat cgi com bin exe js pif py pl sh vb ws "); + TurtleSearchDialog::FileTypeExtensionMap->insert(FILETYPE_IDX_VIDEO, "3gp asf asx avi mov mp4 mkv flv mpeg mpg qt rm swf vob wmv"); + TurtleSearchDialog::initialised = true; +} + +void TurtleSearchDialog::searchtableWidgetCostumPopupMenu( QPoint point ) +{ + // block the popup if no results available + if ((ui.searchResultWidget->selectedItems()).size() == 0) return; + + // create the menu as required + if (contextMnu == 0) + { + contextMnu = new QMenu(this); + + downloadAct = new QAction(QIcon(IMAGE_START), tr( "Download" ), this ); + connect( downloadAct , SIGNAL( triggered() ), this, SLOT( download() ) ); + + broadcastonchannelAct = new QAction( tr( "Broadcast on Channel" ), this ); + connect( broadcastonchannelAct , SIGNAL( triggered() ), this, SLOT( broadcastonchannel() ) ); + + recommendtofriendsAct = new QAction( tr( "Recommend to Friends" ), this ); + connect( recommendtofriendsAct , SIGNAL( triggered() ), this, SLOT( recommendtofriends() ) ); + + + contextMnu->clear(); + contextMnu->addAction( downloadAct); + contextMnu->addSeparator(); + contextMnu->addAction( broadcastonchannelAct); + contextMnu->addAction( recommendtofriendsAct); + } + + QMouseEvent *mevent = new QMouseEvent( QEvent::MouseButtonPress, point, + Qt::RightButton, Qt::RightButton, Qt::NoModifier ); + contextMnu->exec( mevent->globalPos() ); +} + + +void TurtleSearchDialog::download() +{ + /* should also be able to handle multi-selection */ + QList itemsForDownload = ui.searchResultWidget->selectedItems(); + int numdls = itemsForDownload.size(); + QTreeWidgetItem * item; + bool attemptDownloadLocal = false; + + for (int i = 0; i < numdls; ++i) { + item = itemsForDownload.at(i); + // call the download + if (item->text(SR_ID_COL) != "Local") + { + std::cerr << "TurtleSearchDialog::download() Calling File Request"; + std::cerr << std::endl; + std::list srcIds; + srcIds.push_back(item->text(SR_UID_COL).toStdString()) ; + + rsFiles -> FileRequest((item->text(SR_NAME_COL)).toStdString(), + (item->text(SR_HASH_COL)).toStdString(), + (item->text(SR_REALSIZE_COL)).toInt(), + "", 0, srcIds); + + std::cout << "isuing file request from search dialog: -" << (item->text(SR_NAME_COL)).toStdString() << "-" << (item->text(SR_HASH_COL)).toStdString() << "-" << (item->text(SR_REALSIZE_COL)).toInt() << "-ids=" ; + for(std::list::const_iterator it(srcIds.begin());it!=srcIds.end();++it) + std::cout << *it << "-" << std::endl ; + } + else + { + attemptDownloadLocal = true; + } + } + if (attemptDownloadLocal) + { + QMessageBox::information(0, tr("Download Notice"), tr("Skipping Local Files")); + } +} + + +void TurtleSearchDialog::broadcastonchannel() +{ + + QMessageBox::warning(0, tr("Sorry"), tr("This function is not yet implemented.")); +} + + +void TurtleSearchDialog::recommendtofriends() +{ + QMessageBox::warning(0, tr("Sorry"), tr("This function is not yet implemented.")); + +} + + +/** context menu searchTablewidget2 **/ +void TurtleSearchDialog::searchtableWidget2CostumPopupMenu( QPoint point ) +{ + + // block the popup if no results available + if ((ui.searchSummaryWidget->selectedItems()).size() == 0) return; + + // create the menu as required + if (contextMnu2 == 0) + { + contextMnu2 = new QMenu( this ); + + searchRemoveAct = new QAction(QIcon(IMAGE_REMOVE), tr( "Remove" ), this ); + connect( searchRemoveAct , SIGNAL( triggered() ), this, SLOT( searchRemove() ) ); + + searchRemoveAllAct = new QAction(QIcon(IMAGE_REMOVEALL), tr( "Remove All" ), this ); + connect( searchRemoveAllAct , SIGNAL( triggered() ), this, SLOT( searchRemoveAll() ) ); + + contextMnu2->clear(); + contextMnu2->addAction( searchRemoveAct); + contextMnu2->addAction( searchRemoveAllAct); + } + + QMouseEvent *mevent2 = new QMouseEvent( QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier ); + contextMnu2->exec( mevent2->globalPos() ); +} + +/** remove selected search result **/ +void TurtleSearchDialog::searchRemove() +{ + /* get the current search id from the summary window */ + QTreeWidgetItem *ci = ui.searchSummaryWidget->currentItem(); + if (!ci) + return; + + /* get the searchId text */ + QString searchId = ci->text(SS_SEARCH_ID_COL); + + std::cerr << "TurtleSearchDialog::searchRemove(): searchId: " << searchId.toStdString(); + std::cerr << std::endl; + + /* show only matching searchIds in main window */ + int items = ui.searchResultWidget->topLevelItemCount(); + for(int i = 0; i < items;) + { + /* get item */ + QTreeWidgetItem *ti = ui.searchResultWidget->topLevelItem(i); + if (ti->text(SR_SEARCH_ID_COL) == searchId) + { + /* remove */ + delete (ui.searchResultWidget->takeTopLevelItem(i)); + items--; + } + else + { + /* step to the next */ + i++; + } + } + int sii = ui.searchSummaryWidget->indexOfTopLevelItem(ci); + if (sii != -1) + { + delete (ui.searchSummaryWidget->takeTopLevelItem(sii)); + } + + ui.searchResultWidget->update(); + ui.searchSummaryWidget->update(); +} + +/** remove all search results **/ +void TurtleSearchDialog::searchRemoveAll() +{ + ui.searchResultWidget->clear(); + ui.searchSummaryWidget->clear(); + nextSearchId = 1; +} + +/* ***************************************************************** + Advanced search implementation +*******************************************************************/ +// Event handlers for hide and show events +void TurtleSearchDialog::hideEvent(QHideEvent * event) +{ + showAdvSearchDialog(false); + MainPage::hideEvent(event); +} + +void TurtleSearchDialog::toggleAdvancedSearchDialog(bool toggled) +{ + // record the users preference for future reference + RshareSettings rsharesettings; + QString key (UI_PREF_ADVANCED_SEARCH); + rsharesettings.setValue(key, QVariant(toggled)); + + showAdvSearchDialog(toggled); +} + +void TurtleSearchDialog::showAdvSearchDialog(bool show) +{ + // instantiate if about to show for the first time + if (advSearchDialog == 0 && show) + { + advSearchDialog = new AdvancedSearchDialog(); + connect(advSearchDialog, SIGNAL(search(Expression*)), + this, SLOT(advancedSearch(Expression*))); + } + if (show) { + advSearchDialog->show(); + advSearchDialog->raise(); + advSearchDialog->setFocus(); + } else if (advSearchDialog != 0){ + advSearchDialog->hide(); + } +} + +void TurtleSearchDialog::advancedSearch(Expression* expression) +{ + advSearchDialog->hide(); + + /* call to core */ + std::list results; + rsFiles -> SearchBoolExp(expression, results); + + /* abstraction to allow reusee of tree rendering code */ + resultsToTree((advSearchDialog->getSearchAsString()).toStdString(), results); +} + + + +void TurtleSearchDialog::searchKeywords() +{ + QString qTxt = ui.lineEdit->text(); + std::string txt = qTxt.toStdString(); + + TurtleRequestId id = rsTurtle->turtleSearch(txt) ; +} + +void TurtleSearchDialog::updateFiles(qulonglong search_id,TurtleFileInfo files) +{ + std::cerr << "updating file list for id " << search_id << std::endl ; +#ifdef A_VIRER + QString qTxt = ui.lineEdit->text(); + std::string txt = qTxt.toStdString(); + + std::cerr << "TurtleSearchDialog::searchKeywords() : " << txt << std::endl; + + /* extract keywords from lineEdit */ + QStringList qWords = qTxt.split(" ", QString::SkipEmptyParts); + std::list words; + QStringListIterator qWordsIter(qWords); + while (qWordsIter.hasNext()) + { + words.push_back(qWordsIter.next().toStdString()); + } + + if (words.size() < 1) + { + /* ignore */ + return; + } + + /* call to core */ + std::list initialResults; + std::list * finalResults = 0; + + rsFiles -> SearchKeywords(words, initialResults,DIR_FLAGS_LOCAL | DIR_FLAGS_REMOTE); + /* which extensions do we use? */ + QString qExt, qName; + int extIndex; + bool matched =false; + FileDetail fd; + + if (ui.FileTypeComboBox->currentIndex() == FILETYPE_IDX_ANY) + { + finalResults = &initialResults; + } else { + finalResults = new std::list; + // amend the text description of the search + txt += " (" + ui.FileTypeComboBox->currentText().toStdString() + ")"; + // collect the extensions to use + QString extStr = TurtleSearchDialog::FileTypeExtensionMap->value(ui.FileTypeComboBox->currentIndex()); + QStringList extList = extStr.split(" "); + + // now iterate through the results ignoring those with wrong extensions + std::list::iterator resultsIter; + for (resultsIter = initialResults.begin(); resultsIter != initialResults.end(); resultsIter++) + { + fd = *resultsIter; + // get this file's extension + qName = QString::fromStdString(fd.name); + extIndex = qName.lastIndexOf("."); + if (extIndex >= 0) { + qExt = qName.mid(extIndex+1); + if (qExt != "" ) + { + // does it match? + matched = false; + /* iterate through the requested extensions */ + for (int i = 0; i < extList.size(); ++i) + { + if (qExt.toUpper() == extList.at(i).toUpper()) + { + finalResults->push_back(fd); + matched = true; + } + } + } + } + } + } + + /* abstraction to allow reusee of tree rendering code */ + resultsToTree(txt, *finalResults); +#endif +} + +void TurtleSearchDialog::resultsToTree(std::string txt, std::list results) +{ + /* translate search results */ + int searchId = nextSearchId++; + std::ostringstream out; + out << searchId; + + std::list::iterator it; + for(it = results.begin(); it != results.end(); it++) + { + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(SR_NAME_COL, QString::fromStdString(it->name)); + item->setText(SR_HASH_COL, QString::fromStdString(it->hash)); + item->setText(SR_SEARCH_ID_COL, QString::fromStdString(out.str())); + + QString ext = QFileInfo(QString::fromStdString(it->name)).suffix(); + if (ext == "jpg" || ext == "jpeg" || ext == "png" || ext == "gif" + || ext == "bmp" || ext == "ico" || ext == "svg") + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypePicture.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Picture")); + } + else if (ext == "avi" || ext == "mpg" || ext == "mpeg" || ext == "wmv" + || ext == "mkv" || ext == "mp4" || ext == "flv" || ext == "mov" + || ext == "vob" || ext == "qt" || ext == "rm" || ext == "3gp") + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypeVideo.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Video")); + } + else if (ext == "ogg" || ext == "mp3" || ext == "wav" || ext == "wma") + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypeAudio.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Audio")); + } + else if (ext == "tar" || ext == "bz2" || ext == "zip" || ext == "gz" + || ext == "rar" || ext == "rpm" || ext == "deb") + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypeArchive.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Archive")); + } + else if (ext == "app" || ext == "bat" || ext == "cgi" || ext == "com" + || ext == "bin" || ext == "exe" || ext == "js" || ext == "pif" + || ext == "py" || ext == "pl" || ext == "sh" || ext == "vb" || ext == "ws") + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypeProgram.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Program")); + } + else if (ext == "iso" || ext == "nrg" || ext == "mdf" ) + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypeCDImage.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("CD-Image")); + } + else if (ext == "txt" || ext == "cpp" || ext == "c" || ext == "h") + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypeDocument.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Document")); + } + else if (ext == "doc" || ext == "rtf" || ext == "sxw" || ext == "xls" + || ext == "sxc" || ext == "odt" || ext == "ods") + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypeDocument.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Document")); + } + else if (ext == "html" || ext == "htm" || ext == "php") + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypeDocument.png")); + item->setText(SR_TYPE_COL, QString::fromUtf8("Document")); + } + else + { + item->setIcon(SR_ICON_COL, QIcon(":/images/FileTypeAny.png")); + } + + + + /* + * to facilitate downlaods we need to save the file size too + */ + //QVariant * variant = new QVariant((qulonglong)it->size); + //item->setText(SR_SIZE_COL, QString(variant->toString())); + item->setText(SR_SIZE_COL, misc::friendlyUnit(it->size)); + item->setText(SR_REALSIZE_COL, QString::number(it->size)); + item->setTextAlignment( SR_SIZE_COL, Qt::AlignRight ); + + + // I kept the color code green=online, grey=offline + // Qt::blue is very dark and hardly compatible with the black text on it. + // + if (it->id == "Local") + { + item->setText(SR_ID_COL, QString::fromStdString(it->id)); + item->setText(SR_UID_COL, QString::fromStdString(rsPeers->getOwnId())); + item->setBackground(3, QBrush(Qt::red)); /* colour green? */ + } + else + { + item->setText(SR_ID_COL, QString::fromStdString( rsPeers->getPeerName(it->id))); + item->setText(SR_UID_COL, QString::fromStdString( it->id)); + if(rsPeers->isOnline(it->id)) + item->setBackground(3, QBrush(Qt::green)); + else + item->setBackground(3, QBrush(Qt::lightGray)); + } + + ui.searchResultWidget->addTopLevelItem(item); + } + + /* add to the summary as well */ + + QTreeWidgetItem *item = new QTreeWidgetItem(); + item->setText(SS_TEXT_COL, QString::fromStdString(txt)); + std::ostringstream out2; + out2 << results.size(); + + item->setText(SS_COUNT_COL, QString::fromStdString(out2.str())); + item->setText(SS_SEARCH_ID_COL, QString::fromStdString(out.str())); + + ui.searchSummaryWidget->addTopLevelItem(item); + ui.searchSummaryWidget->setCurrentItem(item); + + /* select this search result */ + selectSearchResults(); +} + + +//void QTreeWidget::currentItemChanged ( QTreeWidgetItem * current, QTreeWidgetItem * previous ) [signal] + + +void TurtleSearchDialog::selectSearchResults() +{ + /* highlight this search in summary window */ + QTreeWidgetItem *ci = ui.searchSummaryWidget->currentItem(); + if (!ci) + return; + + /* get the searchId text */ + QString searchId = ci->text(SS_SEARCH_ID_COL); + + std::cerr << "TurtleSearchDialog::selectSearchResults(): searchId: " << searchId.toStdString(); + std::cerr << std::endl; + + /* show only matching searchIds in main window */ + int items = ui.searchResultWidget->topLevelItemCount(); + for(int i = 0; i < items; i++) + { + /* get item */ + QTreeWidgetItem *ti = ui.searchResultWidget->topLevelItem(i); + if (ti->text(SR_SEARCH_ID_COL) == searchId) + { + ti->setHidden(false); + } + else + { + ti->setHidden(true); + } + } + ui.searchResultWidget->update(); +} + + diff --git a/retroshare-gui/src/gui/TurtleSearchDialog.h b/retroshare-gui/src/gui/TurtleSearchDialog.h new file mode 100644 index 000000000..62f53beb8 --- /dev/null +++ b/retroshare-gui/src/gui/TurtleSearchDialog.h @@ -0,0 +1,133 @@ +/**************************************************************** +* RShare is distributed under the following license: +* +* Copyright (C) 2006, crypton +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +****************************************************************/ + +#ifndef _TURTLESEARCHDIALOG_H +#define _TURTLESEARCHDIALOG_H + +#include +#include + +#include +#include + +//#include + +#include +#include "mainpage.h" +#include "ui_TurtleSearchDialog.h" +#include "advsearch/advancedsearchdialog.h" +#include "Preferences/rsharesettings.h" + +class FileDetail; + +class TurtleSearchDialog : public MainPage +{ + Q_OBJECT + + public: + /** Default Constructor */ + TurtleSearchDialog(QWidget *parent = 0); + /** Default Destructor */ + + + public slots: + void updateFiles(qulonglong request_id,TurtleFileInfo file) ; + + private slots: + + /** Create the context popup menu and it's submenus */ + void searchtableWidgetCostumPopupMenu( QPoint point ); + void searchtableWidget2CostumPopupMenu( QPoint point ); + + void download(); + + void broadcastonchannel(); + + void recommendtofriends(); + + + + void searchRemove(); + + void searchRemoveAll(); + + void searchKeywords(); + + /** management of the adv search dialog object when switching search modes */ + void toggleAdvancedSearchDialog(bool); + void hideEvent(QHideEvent * event); + + /** raises (and if necessary instantiates) the advanced search dialog */ + void showAdvSearchDialog(bool=true); + + /** perform the advanced search */ + void advancedSearch(Expression*); + + void selectSearchResults(); + + private: + /** render the results to the tree widget display */ + void resultsToTree(std::string, std::list); + + /** the advanced search dialog instance */ + AdvancedSearchDialog * advSearchDialog; + + /** Define the popup menus for the Context menu */ + QMenu* contextMnu; + + QMenu* contextMnu2; + + /** Defines the actions for the context menu */ + QAction* downloadAct; + QAction* broadcastonchannelAct; + QAction* recommendtofriendsAct; + + QAction* searchRemoveAct; + QAction* searchRemoveAllAct; + + /** Contains the mapping of filetype combobox to filetype extensions */ + static const int FILETYPE_IDX_ANY; + static const int FILETYPE_IDX_ARCHIVE; + static const int FILETYPE_IDX_AUDIO; + static const int FILETYPE_IDX_CDIMAGE; + static const int FILETYPE_IDX_DOCUMENT; + static const int FILETYPE_IDX_PICTURE; + static const int FILETYPE_IDX_PROGRAM; + static const int FILETYPE_IDX_VIDEO; + + + static QMap * FileTypeExtensionMap; + static bool initialised; + void initialiseFileTypeMappings(); + + /**** + QTreeWidget *searchtableWidget; + QTreeWidget *searchtablewidget2; + ****/ + + int nextSearchId; + + /** Qt Designer generated object */ + Ui::TurtleSearchDialog ui; +}; + +#endif + diff --git a/retroshare-gui/src/gui/TurtleSearchDialog.ui b/retroshare-gui/src/gui/TurtleSearchDialog.ui new file mode 100644 index 000000000..eb7a11796 --- /dev/null +++ b/retroshare-gui/src/gui/TurtleSearchDialog.ui @@ -0,0 +1,1230 @@ + + TurtleSearchDialog + + + + 0 + 0 + 661 + 289 + + + + + 1 + 1 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 0 + 0 + 0 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 192 + 192 + 192 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + 104 + 104 + 104 + + + + + + + 208 + 208 + 208 + + + + + + + 255 + 255 + 255 + + + + + + + 247 + 247 + 247 + + + + + + + 104 + 104 + 104 + + + + + + + 139 + 139 + 139 + + + + + + + 104 + 104 + 104 + + + + + + + 255 + 255 + 255 + + + + + + + 104 + 104 + 104 + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 128 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 255 + + + + + + + 255 + 0 + 255 + + + + + + + 231 + 231 + 231 + + + + + + + + + Arial + 8 + 50 + false + false + false + false + + + + Qt::NoContextMenu + + + + 6 + + + 0 + + + 6 + + + 0 + + + 1 + + + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + + 34 + 34 + + + + + 34 + 34 + + + + Toggle advanced searching on and off. + + + + + + :/images/advsearch_24x24.png + + + + 24 + 24 + + + + true + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + + + 255 + 0 + + + + + 390 + 24 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + QFrame::Plain + + + <h3>Simple Search:</h3> + + + + + + + Qt::Horizontal + + + + 10 + 20 + + + + + + + + + 0 + 0 + + + + Keywords + + + + + + + + 3 + 0 + + + + + 558 + 16777215 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 16 + 32 + + + + + + + + <html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:8pt; font-weight:400; font-style:normal; text-decoration:none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Format</p></body></html> + + + + + + + + Any + + + :/images/FileTypeAny.png + + + + + Archive + + + :/images/FileTypeArchive.png + + + + + Audio + + + :/images/FileTypeAudio.png + + + + + CD-Image + + + :/images/FileTypeCDImage.png + + + + + Document + + + :/images/FileTypeDocument.png + + + + + Picture + + + :/images/FileTypePicture.png + + + + + Program + + + :/images/FileTypeProgram.png + + + + + Video + + + :/images/FileTypeVideo.png + + + + + + + + Qt::Horizontal + + + + 16 + 20 + + + + + + + + + 34 + 34 + + + + + 34 + 34 + + + + Perform simple search + + + + + + :/images/find.png + + + + 24 + 24 + + + + + + + + + + + + + true + + + + 0 + 0 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + <h3>Advanced Search:</h3> + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 50 + 20 + + + + + + + + true + + + + 0 + 0 + + + + Show Advanced Search Tool + + + + + + + + + + + + + + + 6 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + + 34 + 34 + + + + + 34 + 34 + + + + Download + + + + + + :/images/down_24x24.png + + + + 24 + 24 + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + + + + + 0 + 1 + + + + Qt::Horizontal + + + + + 1 + 0 + + + + Qt::CustomContextMenu + + + true + + + QAbstractItemView::DragOnly + + + true + + + + + + + + + Filename + + + + + Size + + + + + Sources + + + + + Type + + + + + Hash + + + + + + + 0 + 1 + + + + + 0 + 0 + + + + + 0 + 0 + + + + true + + + Qt::CustomContextMenu + + + true + + + + KeyWords + + + + + Results + + + + + Search Id + + + + + + + + + + + + SearchTreeWidget + QTreeWidget +
gui/SearchTreeWidget.h
+
+
+ + + + + + toggleAdvancedSearchBtn + toggled(bool) + SimpleSearchPanel + setHidden(bool) + + + 29 + 35 + + + 72 + 43 + + + + + toggleAdvancedSearchBtn + toggled(bool) + AdvancedSearchPanel + setVisible(bool) + + + 28 + 29 + + + 80 + 64 + + + + +
diff --git a/retroshare-gui/src/gui/images.qrc b/retroshare-gui/src/gui/images.qrc index cfbe30004..51ca75060 100644 --- a/retroshare-gui/src/gui/images.qrc +++ b/retroshare-gui/src/gui/images.qrc @@ -17,6 +17,7 @@ images/channels.png images/channeldelete.png images/channelsubscribe.png + images/turtle.png images/channels16.png images/channels24.png images/channels32.png diff --git a/retroshare-gui/src/gui/images/turtle.png b/retroshare-gui/src/gui/images/turtle.png new file mode 100644 index 000000000..84ece2205 Binary files /dev/null and b/retroshare-gui/src/gui/images/turtle.png differ diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index a899cc57c..bc8c71a22 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -153,6 +153,11 @@ int main(int argc, char *argv[]) // avoid clashes between infos from threads. // QObject::connect(notify,SIGNAL(hashingInfoChanged(const QString&)),w ,SLOT(updateHashingInfo(const QString&))) ; +#ifdef TURTLE_HOPPING + qRegisterMetaType("TurtleFileInfo") ; + std::cerr << "connecting signals and slots" << std::endl ; + QObject::connect(notify,SIGNAL(gotTurtleSearchResult(qulonglong,TurtleFileInfo)),w->turtleDialog,SLOT(updateFiles(qulonglong,TurtleFileInfo))) ; +#endif QObject::connect(notify,SIGNAL(filesPreModChanged(bool)) ,w->sharedfilesDialog,SLOT(preModDirectories(bool) )) ; QObject::connect(notify,SIGNAL(filesPostModChanged(bool)) ,w->sharedfilesDialog,SLOT(postModDirectories(bool) )) ; QObject::connect(notify,SIGNAL(transfersChanged()) ,w->transfersDialog ,SLOT(insertTransfers() )) ; diff --git a/retroshare-gui/src/rsiface/notifyqt.cpp b/retroshare-gui/src/rsiface/notifyqt.cpp index 01cb01e62..f7f6909ac 100644 --- a/retroshare-gui/src/rsiface/notifyqt.cpp +++ b/retroshare-gui/src/rsiface/notifyqt.cpp @@ -3,6 +3,9 @@ #include "rsiface/rsnotify.h" #include "rsiface/rspeers.h" #include "rsiface/rsphoto.h" +#ifdef TURTLE_HOPPING +#include +#endif #include "gui/NetworkDialog.h" #include "gui/PeersDialog.h" @@ -36,6 +39,18 @@ void NotifyQt::notifyErrorMsg(int list, int type, std::string msg) return; } +#ifdef TURTLE_HOPPING +void NotifyQt::notifyTurtleSearchResult(uint32_t search_id,const std::list& files) +{ + std::cerr << "in notify search result..." << std::endl ; + +// QList qfiles ; + + for(std::list::const_iterator it(files.begin());it!=files.end();++it) + emit gotTurtleSearchResult(search_id,*it) ; +// qfiles.push_back(*it) ; +} +#endif void NotifyQt::notifyHashingInfo(std::string fileinfo) { emit hashingInfoChanged(QString::fromStdString(fileinfo)) ; @@ -56,12 +71,21 @@ void NotifyQt::notifyListChange(int list, int type) switch(list) { case NOTIFY_LIST_NEIGHBOURS: +#ifdef DEBUG + std::cerr << "received neighbrs changed" << std::endl ; +#endif emit neighborsChanged(); break; case NOTIFY_LIST_FRIENDS: +#ifdef DEBUG + std::cerr << "received friends changed" << std::endl ; +#endif emit friendsChanged() ; break; case NOTIFY_LIST_DIRLIST: +#ifdef DEBUG + std::cerr << "received files changed" << std::endl ; +#endif emit filesPostModChanged(false) ; /* Remote */ emit filesPostModChanged(true) ; /* Local */ break; @@ -69,15 +93,24 @@ void NotifyQt::notifyListChange(int list, int type) //displaySearch(); break; case NOTIFY_LIST_MESSAGELIST: +#ifdef DEBUG + std::cerr << "received msg changed" << std::endl ; +#endif emit messagesChanged() ; break; case NOTIFY_LIST_CHANNELLIST: //displayChannels(); break; case NOTIFY_LIST_TRANSFERLIST: +#ifdef DEBUG + std::cerr << "received transfer changed" << std::endl ; +#endif emit transfersChanged() ; break; case NOTIFY_LIST_CONFIG: +#ifdef DEBUG + std::cerr << "received config changed" << std::endl ; +#endif emit configChanged() ; break ; default: @@ -133,6 +166,8 @@ void NotifyQt::UpdateGUI() /* hack to force updates until we've fixed that part */ static time_t lastTs = 0; +// std::cerr << "Got update signal t=" << lastTs << std::endl ; + if (time(NULL) > lastTs) // always update, every 1 sec. { emit transfersChanged(); diff --git a/retroshare-gui/src/rsiface/notifyqt.h b/retroshare-gui/src/rsiface/notifyqt.h index 39d3c414d..bee6382f1 100644 --- a/retroshare-gui/src/rsiface/notifyqt.h +++ b/retroshare-gui/src/rsiface/notifyqt.h @@ -14,8 +14,12 @@ class ChatDialog; class MessagesDialog; class ChannelsDialog; class MessengerWindow; +#ifdef TURTLE_HOPPING +#include "rsiface/rsturtle.h" +class TurtleSearchDialog ; - +struct TurtleFileInfo ; +#endif //class NotifyQt: public NotifyBase, public QObject class NotifyQt: public QObject, public NotifyBase @@ -46,6 +50,9 @@ class NotifyQt: public QObject, public NotifyBase virtual void notifyErrorMsg(int list, int sev, std::string msg); virtual void notifyChat(); virtual void notifyHashingInfo(std::string fileinfo); +#ifdef TURTLE_HOPPING + virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list& found_files); +#endif signals: // It's beneficial to send info to the GUI using signals, because signals are thread-safe @@ -59,6 +66,7 @@ class NotifyQt: public QObject, public NotifyBase void neighborsChanged() const ; void messagesChanged() const ; void configChanged() const ; + void gotTurtleSearchResult(qulonglong search_id,TurtleFileInfo file) const ; public slots: diff --git a/retroshare-gui/src/rsiface/rsfiles.h b/retroshare-gui/src/rsiface/rsfiles.h index 3f8575035..58335ee48 100644 --- a/retroshare-gui/src/rsiface/rsfiles.h +++ b/retroshare-gui/src/rsiface/rsfiles.h @@ -130,7 +130,7 @@ virtual bool ExtraFileMove(std::string fname, std::string hash, uint64_t size, virtual int RequestDirDetails(std::string uid, std::string path, DirDetails &details) = 0; virtual int RequestDirDetails(void *ref, DirDetails &details, uint32_t flags) = 0; -virtual int SearchKeywords(std::list keywords, std::list &results) = 0; +virtual int SearchKeywords(std::list keywords, std::list &results,uint32_t flags) = 0; virtual int SearchBoolExp(Expression * exp, std::list &results) = 0; /*** diff --git a/retroshare-gui/src/rsiface/rsiface.h b/retroshare-gui/src/rsiface/rsiface.h index 215e54f54..9a58454e5 100644 --- a/retroshare-gui/src/rsiface/rsiface.h +++ b/retroshare-gui/src/rsiface/rsiface.h @@ -35,6 +35,9 @@ class NotifyBase; class RsIface; class RsControl; class RsInit; +#ifdef TURTLE_HOPPING +struct TurtleFileInfo ; +#endif /* declare single RsIface for everyone to use! */ @@ -200,6 +203,9 @@ class NotifyBase virtual void notifyErrorMsg(int list, int sev, std::string msg) { (void) list; (void) sev; (void) msg; return; } virtual void notifyChat() { return; } virtual void notifyHashingInfo(std::string fileinfo) { (void)fileinfo; return ; } +#ifdef TURTLE_HOPPING + virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list& files) { (void)files; } +#endif }; const int NOTIFY_LIST_NEIGHBOURS = 1; diff --git a/retroshare-gui/src/rsiface/rsturtle.h b/retroshare-gui/src/rsiface/rsturtle.h index 0bfb4937a..abaf4e24e 100644 --- a/retroshare-gui/src/rsiface/rsturtle.h +++ b/retroshare-gui/src/rsiface/rsturtle.h @@ -35,6 +35,16 @@ extern RsTurtle *rsTurtle ; typedef uint32_t TurtleRequestId ; +// This is the structure used to send back results of the turtle search +// to the notifyBase class. + +struct TurtleFileInfo +{ + std::string hash ; + std::string name ; + uint64_t size ; +}; + // Interface class for turtle hopping. // // This class mainly interacts with the turtle router, that is responsible