Added Basics of Menu System to retroshare-nogui.

* Menu System basic structure complete.
 * Added functions to NotifyTxt to handle search results.
 * Running from std::cin at the moment.
 * Functional Commands:
	- List Friends, Network.
	- Show Transfers, Cancel Transfers.
	- Basic Search, and Download.
 * Not Connected to SSH server at this point, TODO.
 * Lots of Other Commands to add (e.g. import/add/remove friends, forums, etc)
 * Enable via option in retroshare-nogui.pro, instructions at bottom of file.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-gxs-b1@5390 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2012-08-07 23:55:43 +00:00
parent a715947046
commit db35ae95af
9 changed files with 1970 additions and 4 deletions

View File

@ -0,0 +1,766 @@
#include "menu/menu.h"
#include <retroshare/rsconfig.h>
#include <retroshare/rspeers.h>
#include <retroshare/rsiface.h>
#include <iostream>
/**********************************************************
* Menu Base Interface.
*/
int tailrec_printparents(Menu *m, std::ostream &out)
{
Menu *p = m->parent();
if (p)
{
tailrec_printparents(p, out);
}
out << m->ShortFnDesc() << " => ";
#if 0
MenuList *ml = dynamic_cast<MenuList *>(m);
MenuOpBasicKey *mbk = dynamic_cast<MenuOpBasicKey *>(m);
MenuOpTwoKeys *mtk = dynamic_cast<MenuOpTwoKeys *>(m);
if (ml)
{
out << "MenuList@" << (void *) m << " ";
}
else if (mbk)
{
out << "MenuBasicKey@" << (void *) m << " ";
}
else if (mtk)
{
out << "MenuOpTwoKeys@" << (void *) m << " ";
}
else
{
out << "Menu@" << (void *) m << " ";
}
#endif
return 1;
}
uint32_t MenuInterface::process(char key)
{
#ifdef MENU_DEBUG
std::cerr << "MenuInterface::process(" << key << ")";
std::cerr << std::endl;
#endif // MENU_DEBUG
/* call process on current menu */
uint32_t rt = mCurrentMenu->process(key);
bool doRedraw = true;
bool showError = false;
bool showHelp = false;
#ifdef MENU_DEBUG
std::cerr << "MenuInterface::process() currentMenu says: " << rt;
std::cerr << std::endl;
#endif // MENU_DEBUG
switch(rt)
{
case MENU_PROCESS_NONE:
case MENU_PROCESS_DONE:
/* no changes - operation performed, or noop */
break;
case MENU_PROCESS_NEEDDATA:
/* no redraw, this could be called many times */
doRedraw = false;
break;
case MENU_PROCESS_ERROR:
/* Show Error at top of Page */
showError = true;
break;
case MENU_PROCESS_HELP:
/* Show Help at top of Page */
showHelp = true;
break;
case MENU_PROCESS_MENU:
/* new menu to switch to */
if (mCurrentMenu->selectedMenu())
{
std::cerr << "MenuInterface::process() Switching Menus";
std::cerr << std::endl;
mCurrentMenu = mCurrentMenu->selectedMenu();
}
else
{
std::cerr << "MenuInterface::process() ERROR";
std::cerr << " SelectedMenu == NULL";
std::cerr << std::endl;
}
break;
case MENU_PROCESS_TOP:
/* switch to Base Menu */
mCurrentMenu = mBase;
break;
case MENU_PROCESS_QUIT:
return MENU_PROCESS_QUIT;
break;
}
/* now we redraw, and wait for next data */
if (!doRedraw)
{
return MENU_PROCESS_NEEDDATA;
}
/* HEADER */
for(int i = 0; i < 20; i++)
{
std::cerr << std::endl;
}
/* ERROR */
if (showError)
{
mCurrentMenu->showError();
}
/* HELP */
else if (showHelp)
{
mCurrentMenu->showHelp();
}
/* MENU PAGE */
drawHeader();
mCurrentMenu->drawPage();
return MENU_PROCESS_NEEDDATA;
}
uint32_t MenuInterface::drawHeader()
{
std::cerr << "=======================================================";
std::cerr << std::endl;
std::cerr << "Retroshare Terminal Menu V2.xxxx ======================";
std::cerr << std::endl;
unsigned int nTotal = 0;
unsigned int nConnected = 0;
rsPeers->getPeerCount(&nTotal, &nConnected, false);
uint32_t netState = rsConfig->getNetState();
std::string natState("Unknown");
switch(netState)
{
default:
case RSNET_NETSTATE_BAD_UNKNOWN:
natState = "YELLOW:Unknown";
break;
case RSNET_NETSTATE_BAD_OFFLINE:
natState = "GRAY:Offline";
break;
case RSNET_NETSTATE_BAD_NATSYM:
natState = "RED:Nasty Firewall";
break;
case RSNET_NETSTATE_BAD_NODHT_NAT:
natState = "RED:NoDht & Firewalled";
break;
case RSNET_NETSTATE_WARNING_RESTART:
natState = "YELLOW:Restarting";
break;
case RSNET_NETSTATE_WARNING_NATTED:
natState = "YELLOW:Firewalled";
break;
case RSNET_NETSTATE_WARNING_NODHT:
natState = "YELLOW:DHT Disabled";
break;
case RSNET_NETSTATE_GOOD:
natState = "GREEN:Good!";
break;
case RSNET_NETSTATE_ADV_FORWARD:
natState = "GREEN:Forwarded Port";
break;
}
float downKb = 0;
float upKb = 0;
rsicontrol -> ConfigGetDataRates(downKb, upKb);
std::cerr << "Friends " << nConnected << "/" << nTotal;
std::cerr << " Network: " << natState;
std::cerr << std::endl;
std::cerr << "Down: " << downKb << " (kB/s) ";
std::cerr << " Up: " << upKb << " (kB/s) ";
std::cerr << std::endl;
std::cerr << "Menu State: ";
tailrec_printparents(mCurrentMenu, std::cerr);
std::cerr << std::endl;
std::cerr << "=======================================================";
std::cerr << std::endl;
return 1;
}
/**********************************************************
* Menu (Base)
*/
Menu::~Menu()
{
/* cleanup children */
mParent = NULL;
mSelectedMenu = NULL;
std::map<uint8_t, Menu *>::iterator it;
for(it = mChildren.begin(); it != mChildren.end(); it++)
{
delete (it->second);
}
mChildren.clear();
}
int Menu::addMenuItem(char key, Menu *child)
{
std::map<uint8_t, Menu *>::iterator it;
it = mChildren.find(key);
if (it != mChildren.end())
{
std::cerr << "Menu::addMenuItem() ERROR DUPLICATE MENU ITEM";
std::cerr << std::endl;
return 0;
}
mChildren[key] = child;
child->setParent(this);
return 1;
}
uint32_t Menu::process(char key)
{
/* try standard list ones */
uint32_t rt = std_process(key);
if (rt)
{
return rt;
}
/* now try children */
rt = process_children(key);
if (rt)
{
return rt;
}
return MENU_PROCESS_NONE;
}
uint32_t Menu::std_process(char key)
{
switch(key)
{
case MENU_KEY_QUIT:
return MENU_PROCESS_QUIT;
break;
case MENU_KEY_HELP:
return MENU_PROCESS_HELP;
break;
case MENU_KEY_TOP:
return MENU_PROCESS_TOP;
break;
case MENU_KEY_UP:
setSelectedMenu(parent());
return MENU_PROCESS_MENU;
break;
}
return MENU_PROCESS_NONE;
}
uint32_t Menu::process_children(char key)
{
std::map<uint8_t, Menu *>::iterator it;
it = mChildren.find(key);
if (it == mChildren.end())
{
return MENU_PROCESS_NONE;
}
/* have a child */
/* now return, depending on type */
switch(it->second->op())
{
/* Think I can handle these the same! Both will call DrawPage,
* then Process on New Menu
*/
case MENU_OP_NEEDDATA:
case MENU_OP_SUBMENU:
setSelectedMenu(it->second);
return MENU_PROCESS_MENU;
break;
default:
case MENU_OP_INSTANT:
/* done already! */
setSelectedMenu(NULL);
return MENU_PROCESS_DONE;
break;
case MENU_OP_ERROR:
/* done already! */
setSelectedMenu(NULL);
return MENU_PROCESS_ERROR;
break;
}
}
uint32_t Menu::drawPage()
{
std::cerr << "Universal Commands ( ";
std::cerr << (char) MENU_KEY_QUIT << ":Quit ";
std::cerr << (char) MENU_KEY_HELP << ":Help ";
std::cerr << (char) MENU_KEY_TOP << ":Top ";
std::cerr << (char) MENU_KEY_UP << ":Up ";
std::cerr << ")";
std::cerr << std::endl;
std::cerr << "Specific Commands (";
std::map<uint8_t, Menu *>::iterator it;
for(it = mChildren.begin(); it != mChildren.end(); it++)
{
std::cerr << (char) it->first << ":";
std::cerr << it->second->ShortFnDesc() << " ";
}
std::cerr << ")";
std::cerr << std::endl;
return 1;
}
uint32_t Menu::drawHelpPage()
{
std::cerr << "Menu Help: Universal Commands are:";
std::cerr << std::endl;
std::cerr << "\tKey: " << (char) MENU_KEY_QUIT << " => Quit";
std::cerr << std::endl;
std::cerr << "\tKey: " << (char) MENU_KEY_HELP << " => Help";
std::cerr << std::endl;
std::cerr << "\tKey: " << (char) MENU_KEY_TOP << " => Top Menu";
std::cerr << std::endl;
std::cerr << "\tKey: " << (char) MENU_KEY_UP << " => Up a Menu";
std::cerr << std::endl;
std::cerr << "Specific Commands are:";
std::cerr << std::endl;
std::map<uint8_t, Menu *>::iterator it;
for(it = mChildren.begin(); it != mChildren.end(); it++)
{
std::cerr << "\tKey: " << (char) it->first << " => ";
std::cerr << it->second->ShortFnDesc();
std::cerr << std::endl;
}
return 1;
}
/**********************************************************
* Menu List (Base)
*/
uint32_t MenuList::drawPage()
{
Menu::drawPage();
std::cerr << "Navigation Commands (";
//std::cerr << (char) MENULIST_KEY_LIST << ":List ";
std::cerr << (char) MENULIST_KEY_NEXT << ":Next ";
std::cerr << (char) MENULIST_KEY_PREV << ":Prev ";
std::cerr << ")";
std::cerr << std::endl;
std::cerr << "MenuList::Internals ";
std::cerr << "ListSize: " << getListCount();
std::cerr << " SelectIdx: " << mSelectIdx;
std::cerr << " Cursor: " << mCursor;
std::cerr << std::endl;
int i = 0;
int listCount = getListCount();
int startCount = mCursor + 1;
int endCount = mCursor + 10;
if (endCount > listCount)
{
endCount = listCount;
}
if (mSelectIdx >= 0)
{
std::cerr << "Current Selection Idx: " << mSelectIdx << " : ";
std::string desc;
if (getEntryDesc(mSelectIdx, desc) & (desc != ""))
{
std::cerr << desc;
}
else
{
std::cerr << "Missing Description";
}
std::cerr << std::endl;
}
else
{
std::cerr << "No Current Selection: Use 0 - 9 to choose an Entry";
std::cerr << std::endl;
}
std::cerr << "Showing " << startCount;
std::cerr << " to " << endCount << " of " << listCount << " Entries";
std::cerr << std::endl;
std::list<std::string>::iterator it;
for (it = mList.begin(); it != mList.end(); it++, i++)
{
int curIdx = i - mCursor;
if ((curIdx >= 0) && (curIdx < 10))
{
if (i == mSelectIdx)
{
std::cerr << "SELECTED => (" << curIdx << ") ";
}
else
{
std::cerr << "\t(" << curIdx << ") ";
}
std::string desc;
if (getEntryDesc(i, desc) & (desc != ""))
{
std::cerr << desc;
}
else
{
std::cerr << *it << " => ";
std::cerr << "Missing Description";
}
std::cerr << std::endl;
}
}
return 1;
}
uint32_t MenuList::drawHelpPage()
{
Menu::drawPage();
std::cerr << "MenuList Help: Navigation Commands are:";
std::cerr << std::endl;
//std::cerr << "\tKey: " << (char) MENULIST_KEY_LIST << " => List";
//std::cerr << std::endl;
std::cerr << "\tKey: " << (char) MENULIST_KEY_NEXT << " => Next Page";
std::cerr << std::endl;
std::cerr << "\tKey: " << (char) MENULIST_KEY_PREV << " => Prev Page";
std::cerr << std::endl;
std::cerr << "MenuList::drawPage() Internal Details";
std::cerr << std::endl;
std::cerr << "List Size: " << getListCount();
std::cerr << std::endl;
std::cerr << "SelectIdx: " << mSelectIdx;
std::cerr << std::endl;
std::cerr << "Cursor: " << mCursor;
std::cerr << std::endl;
return 1;
}
uint32_t MenuList::op()
{
/* load friend list*/
mList.clear();
//rsPeers->getGpgAcceptedList(mList);
mSelectIdx = -1;
mCursor = 0;
return MENU_OP_ERROR; // SUBMENU -> only for inherited classes;
}
uint32_t MenuList::getListCount()
{
return mList.size();
}
int MenuList::getCurrentKey(std::string &key)
{
return getListEntry(mSelectIdx, key);
}
int MenuList::getCurrentIdx(int &idx)
{
idx = mSelectIdx;
return 1;
}
int MenuList::getListEntry(int idx, std::string &key)
{
if (idx < 0)
{
return MENU_ENTRY_NONE;
}
std::list<std::string>::iterator it;
int i = 0;
for (it = mList.begin(); (i < idx) && (it != mList.end()); it++, i++) ;
if (it != mList.end())
{
key = *it;
return MENU_ENTRY_OKAY;
}
return MENU_ENTRY_NONE;
}
int MenuList::getEntryDesc(int idx, std::string &desc)
{
desc = "Entry Description";
return MENU_ENTRY_OKAY;
}
uint32_t MenuList::process(char key)
{
/* try standard list ones */
uint32_t rt = Menu::process(key);
if (rt)
{
return rt;
}
rt = list_process(key);
return rt;
}
uint32_t MenuList::list_process(char key)
{
if (((key >= '0') && (key <= '9')) ||
((key >= 'a') && (key <= 'f')))
{
int idx = 0;
/* select index */
if ((key >= '0') && (key <= '9'))
{
idx = key - '0';
}
else
{
idx = key - 'a' + 9;
}
/* now change selection, dependent on pagination */
if (mCursor + idx < getListCount())
{
mSelectIdx = mCursor + idx;
std::cerr << "MenuList::list_process() Selected Idx: " << mSelectIdx;
std::cerr << std::endl;
}
else
{
std::cerr << "MenuList::list_process() Idx Out of Range";
std::cerr << std::endl;
}
return MENU_PROCESS_DONE; /* ready for next key stroke */
}
switch(key)
{
case MENULIST_KEY_LIST:
/* send a list to output */
return MENU_PROCESS_DONE; /* ready for next key stroke */
break;
case MENULIST_KEY_NEXT:
/* shift to next page */
if (mCursor + 10 < getListCount())
{
mCursor += 10;
}
return MENU_PROCESS_DONE;
break;
case MENULIST_KEY_PREV:
/* shift to prev page */
if (((int) mCursor) - 10 >= 0)
{
mCursor -= 10;
}
return MENU_PROCESS_DONE;
break;
}
return MENU_PROCESS_NONE;
}
uint32_t MenuOpBasicKey::op_basic(std::string key)
{
parent()->setErrorMessage("MenuOpBasicKey Not Overloaded Correctly");
return MENU_OP_ERROR;
}
uint32_t MenuOpBasicKey::op()
{
std::string key;
Menu *Parent=parent();
MenuList *p = dynamic_cast<MenuList *>(Parent);
if (!p)
{
if (Parent)
{
Parent->setErrorMessage("Invalid (Basic) Menu Structure");
}
return MENU_OP_ERROR;
}
if (p->getCurrentKey(key))
{
return op_basic(key);
}
if (Parent)
{
Parent->setErrorMessage("Invalid Current Keys");
}
return MENU_OP_ERROR;
}
uint32_t MenuOpTwoKeys::op_twokeys(std::string parentkey, std::string key)
{
parent()->setErrorMessage("MenuOpTwoKeys Not Overloaded Correctly");
return MENU_OP_ERROR;
}
uint32_t MenuOpTwoKeys::op()
{
std::string parentkey;
std::string key;
Menu *Parent=parent();
MenuList *p = dynamic_cast<MenuList *>(Parent);
Menu *grandParent=parent()->parent();
MenuList *gp = dynamic_cast<MenuList *>(grandParent);
if ((!gp) || (!p))
{
if (Parent)
{
Parent->setErrorMessage("Invalid (TwoKeys) Menu Structure");
}
return MENU_OP_ERROR;
}
if ((gp->getCurrentKey(parentkey)) && (p->getCurrentKey(key)))
{
return op_twokeys(parentkey, key);
}
if (Parent)
{
Parent->setErrorMessage("Invalid Current Keys");
}
return MENU_OP_ERROR;
}
/**********************************************************
* Menu Op Line Input (Base)
*/
uint32_t MenuOpLineInput::op()
{
return MENU_OP_NEEDDATA;
}
uint32_t MenuOpLineInput::process_lines(std::string input)
{
std::cerr << "MenuOpLineInput::process_lines() => SHOULD BE OVERLOADED";
std::cerr << "Input Was: ";
std::cerr << std::endl;
std::cerr << "==================================================";
std::cerr << std::endl;
std::cerr << input;
std::cerr << "==================================================";
std::cerr << std::endl;
return MENU_PROCESS_ERROR;
}
uint32_t MenuOpLineInput::process(char key)
{
/* read data in and add to buffer */
mInput += key;
if (key != '\n')
{
return MENU_PROCESS_NEEDDATA;
}
uint32_t rt = process_lines(mInput);
switch(rt)
{
case MENU_PROCESS_NEEDDATA:
break;
case MENU_PROCESS_ERROR:
std::cerr << "MenuOpLineInput::process() => ERROR";
std::cerr << std::endl;
case MENU_PROCESS_DONE:
/* cleanup for next command */
std::cerr << "MenuOpLineInput::process() Clearing Buffer";
std::cerr << std::endl;
mInput.clear();
/* go back to parent menu */
rt = MENU_PROCESS_MENU;
setSelectedMenu(parent());
break;
}
return rt;
}

View File

@ -0,0 +1,178 @@
#ifndef RSNOGUI_MENU_H
#define RSNOGUI_MENU_H
#include <inttypes.h>
#include <string>
#include <map>
#include <list>
#define MENU_PROCESS_NONE 0
#define MENU_PROCESS_TOP 1
#define MENU_PROCESS_MENU 2
#define MENU_PROCESS_NEEDDATA 3
#define MENU_PROCESS_DONE 4
#define MENU_PROCESS_QUIT 5
#define MENU_PROCESS_SHUTDOWN 6
#define MENU_PROCESS_HELP 7
#define MENU_PROCESS_ERROR 8
#define MENU_KEY_QUIT 'Q'
#define MENU_KEY_HELP 'H'
#define MENU_KEY_TOP 'T'
#define MENU_KEY_REPEAT 'R'
#define MENU_KEY_UP 'U'
#define MENULIST_KEY_LIST 'L' // Don't need this.
#define MENULIST_KEY_NEXT 'N'
#define MENULIST_KEY_PREV 'P'
#define MENU_OP_ERROR 0
#define MENU_OP_INSTANT 1
#define MENU_OP_SUBMENU 2
#define MENU_OP_NEEDDATA 3
#define MENU_ENTRY_NONE 0
#define MENU_ENTRY_OKAY 1
class Menu;
class Screen;
class Menu
{
public:
Menu(std::string shortDesc): mParent(NULL), mShortDesc(shortDesc) { return; }
virtual ~Menu();
void setParent(Menu *p) { mParent = p; }
Menu *parent() { return mParent; }
Menu *selectedMenu() { return mSelectedMenu; }
int addMenuItem(char key, Menu *child);
virtual uint32_t op() { return MENU_OP_SUBMENU; } /* what type is it? returns SUBMENU, INSTANT, NEEDINPUT */
virtual uint32_t process(char key);
// THE BIT STILL TO BE DEFINED!
std::string ShortFnDesc() { return mShortDesc; }// Menu Text (for Help).
//virtual std::string menuText() = 0;
//virtual std::string menuHelp() = 0;
virtual void setOpMessage(std::string msg) { return; }
virtual void setErrorMessage(std::string msg) { return; }
virtual uint32_t drawPage(); // { return 1; } //= 0;
virtual uint32_t drawHelpPage(); // { return 1; } //= 0;
virtual uint32_t showError() { return 1; } //= 0;
virtual uint32_t showHelp() { return 1; } //= 0;
protected:
virtual uint32_t std_process(char key); /* for H/T/R/Q */
virtual uint32_t process_children(char key); /* check for children ops */
void setSelectedMenu(Menu *m) { mSelectedMenu = m; }
private:
Menu *mParent;
Menu *mSelectedMenu;
std::string mShortDesc;
std::map<uint8_t, Menu *> mChildren;
};
/**********************************************************
* Generic MenuList... provides a list of KEYS, which
* can be iterated through.
*
* Maintains: List + Current + Next / Previous.
* Single Child, which is called for all.
*/
class MenuList: public Menu
{
public:
MenuList(std::string shortDesc): Menu(shortDesc) { return; }
virtual uint32_t op();
virtual uint32_t process(char key);
// List Info.
uint32_t getListCount();
int getCurrentIdx(int &idx);
int getCurrentKey(std::string &key);
int getListEntry(int idx, std::string &key);
virtual int getEntryDesc(int idx, std::string &desc);
// Output.
virtual uint32_t drawPage();
virtual uint32_t drawHelpPage();
protected:
virtual uint32_t list_process(char key);
int32_t mSelectIdx; /* -1 => none */
uint32_t mCursor; /* offset for list display */
std::list<std::string> mList;
private:
};
class MenuOpBasicKey: public Menu
{
public:
MenuOpBasicKey(std::string shortDesc): Menu(shortDesc) { return; }
virtual uint32_t op();
protected:
virtual uint32_t op_basic(std::string key);
};
class MenuOpTwoKeys: public Menu
{
public:
MenuOpTwoKeys(std::string shortDesc): Menu(shortDesc) { return; }
virtual uint32_t op();
protected:
virtual uint32_t op_twokeys(std::string parentkey, std::string key);
};
/* Read input, line by line...
*/
class MenuOpLineInput: public Menu
{
public:
MenuOpLineInput(std::string shortDesc): Menu(shortDesc) { return; }
virtual uint32_t op();
virtual uint32_t process(char key);
protected:
virtual uint32_t process_lines(std::string input);
std::string mInput;
};
class MenuInterface
{
public:
MenuInterface(Menu *b) :mCurrentMenu(b), mBase(b) { return; }
uint32_t process(char key);
uint32_t drawHeader();
private:
Menu *mCurrentMenu;
Menu *mBase;
};
#endif

View File

@ -0,0 +1,578 @@
#include <retroshare/rspeers.h>
#include <retroshare/rsfiles.h>
#include <retroshare/rsturtle.h>
#include "util/rsstring.h"
#include "menu/menus.h"
// Can't use: Q, H, T, U (universal)
// or L, N, P (list ops).
// or 0-9,a-f (list selection).
#define MENU_FRIENDS_KEY_ADD 'A'
#define MENU_FRIENDS_KEY_VIEW 'V'
#define MENU_FRIENDS_KEY_REMOVE 'D'
#define MENU_FRIENDS_KEY_CHAT 'C'
#define MENU_TRANSFER_KEY_STOP 'S'
#define MENU_TRANSFER_KEY_CANCEL 'C'
#define MENU_SEARCH_KEY_ADD 'A'
#define MENU_SEARCH_KEY_REMOVE 'D'
#define MENU_SEARCH_KEY_VIEW 'V'
#define MENU_SEARCH_KEY_DOWNLOAD 'G'
#define MENU_FRIENDS_KEY_ADD 'A'
#define MENU_FRIENDS_KEY_VIEW 'V'
#define MENU_FRIENDS_KEY_REMOVE 'D'
#define MENU_FRIENDS_KEY_CHAT 'C'
#define MENU_TOPLEVEL_KEY_FRIENDS 'F'
#define MENU_TOPLEVEL_KEY_NETWORK 'W'
#define MENU_TOPLEVEL_KEY_TRANSFER 'D'
#define MENU_TOPLEVEL_KEY_SEARCH 'S'
#define MENU_TOPLEVEL_KEY_FORUMS 'O'
Menu *CreateMenuStructure(NotifyTxt *notify)
{
/* construct Friends Menu */
MenuList *friends = new MenuListFriends();
// No Friends Operations Completed Yet!
//friends->addMenuItem(MENU_FRIENDS_KEY_ADD, new MenuOpFriendsAdd());
//friends->addMenuItem(MENU_FRIENDS_KEY_VIEW, new MenuOpFriendsViewDetail());
//friends->addMenuItem(MENU_FRIENDS_KEY_REMOVE, new MenuOpFriendsRemove());
//friends->addMenuItem(MENU_FRIENDS_KEY_CHAT, new MenuOpFriendsChat());
MenuList *network = new MenuListNetwork();
MenuList *transfers = new MenuListTransfer();
//transfers->addMenuItem(MENU_TRANSFER_KEY_STOP, new MenuOpTransferStop());
transfers->addMenuItem(MENU_TRANSFER_KEY_CANCEL, new MenuOpTransferCancel());
MenuList *search = new MenuListSearch(notify);
MenuList *searchlist = new MenuListSearchList(notify);
search->addMenuItem(MENU_SEARCH_KEY_ADD, new MenuOpSearchNew());
//search->addMenuItem(MENU_SEARCH_KEY_REMOVE, new MenuOpSearchDelete());
search->addMenuItem(MENU_SEARCH_KEY_VIEW, searchlist);
searchlist->addMenuItem(MENU_SEARCH_KEY_DOWNLOAD, new MenuOpSearchListDownload());
// Forums - TODO.
//MenuList *forums = new MenuListForums();
//forums->addMenuItem(MENU_FRIENDS_KEY_ADD, new MenuOpFriendsAdd());
//forums->addMenuItem(MENU_FRIENDS_KEY_VIEW, new MenuOpFriendsViewDetail());
//forums->addMenuItem(MENU_FRIENDS_KEY_REMOVE, new MenuOpFriendsRemove());
//forums->addMenuItem(MENU_FRIENDS_KEY_CHAT, new MenuOpFriendsChat());
/* Top Level Menu */
Menu *tlm = new Menu("Top Level Menu");
tlm->addMenuItem(MENU_TOPLEVEL_KEY_FRIENDS, friends);
tlm->addMenuItem(MENU_TOPLEVEL_KEY_NETWORK, network);
tlm->addMenuItem(MENU_TOPLEVEL_KEY_TRANSFER, transfers);
tlm->addMenuItem(MENU_TOPLEVEL_KEY_SEARCH, search);
//tlm->addMenuItem(MENU_TOPLEVEL_KEY_FORUMS, forums);
return tlm;
}
/************
* Friends Menu
*/
uint32_t MenuListFriends::op()
{
MenuList::op();
rsPeers->getGPGAcceptedList(mList);
//rsPeers->getGPGValidList(mList);
return MENU_OP_SUBMENU;
}
int MenuListFriends::getEntryDesc(int idx, std::string &desc)
{
std::string gpgId;
if (!getListEntry(idx, gpgId))
{
/* error */
return 0;
}
RsPeerDetails details;
if (rsPeers->getPeerDetails(gpgId, details))
{
if (details.accept_connection)
{
desc = "Friend: ";
}
else
{
desc = "Neighbour: ";
}
desc += "<" + gpgId + "> ";
desc += details.name;
}
return 1;
}
uint32_t MenuListNetwork::op()
{
MenuList::op();
rsPeers->getGPGValidList(mList);
//rsPeers->getGPGAcceptedList(mList);
return MENU_OP_SUBMENU;
}
uint32_t MenuOpFriendsAdd::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpFriendsViewDetail::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpFriendsRemove::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpFriendsChat::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
/************
* Transfer Menu
*/
uint32_t MenuListTransfer::op()
{
MenuList::op();
/* load friend list*/
rsFiles->FileDownloads(mList);
return MENU_OP_SUBMENU;
}
int MenuListTransfer::getEntryDesc(int idx, std::string &desc)
{
std::string hash;
if (!getListEntry(idx, hash))
{
std::cerr << "MenuListTransfer::getEntryDesc() No ListEntry";
std::cerr << std::endl;
return 0;
}
FileInfo info;
if (!rsFiles->FileDetails(hash, RS_FILE_HINTS_DOWNLOAD, info))
{
std::cerr << "MenuListTransfer::getEntryDesc() No FileDetails";
std::cerr << std::endl;
return 0;
}
float frac = (float) info.transfered / info.size;
if (frac != 1.0)
{
if (info.tfRate > 0)
{
rs_sprintf(desc, "<%s> Downloading %3.2f%% from %d Peers @%3.1fKB/s. Name: %s",
info.hash.c_str(), frac, info.peers.size(), info.tfRate, info.fname.c_str());
}
else
{
rs_sprintf(desc, "<%s> Stalled %3.2f%% Name: %s",
info.hash.c_str(), frac, info.fname.c_str());
}
}
else
{
rs_sprintf(desc, "<%s> Done! Name: %s", info.hash.c_str(), info.fname.c_str());
}
return MENU_OP_INSTANT;
}
uint32_t MenuOpTransferStop::op_basic(std::string key)
{
rsFiles->FileCancel(key);
parent()->setOpMessage("Stopped Transfer");
return MENU_OP_INSTANT;
}
uint32_t MenuOpTransferCancel::op_basic(std::string key)
{
rsFiles->FileCancel(key);
parent()->setOpMessage("Stopped Transfer");
return MENU_OP_INSTANT;
}
/************
* Search Menu
*/
uint32_t MenuListSearch::op()
{
mSelectIdx = -1;
mCursor = 0;
/* Don't reset List -> done dynamically */
return MENU_OP_SUBMENU;
}
int MenuListSearch::getEntryDesc(int idx, std::string &desc)
{
std::string strSearchId;
if (!getListEntry(idx, strSearchId))
{
/* error */
return 0;
}
std::map<std::string, std::string>::iterator it;
std::map<std::string, uint32_t>::iterator sit;
it = mSearchTerms.find(strSearchId);
sit = mSearchIds.find(strSearchId);
if ((it == mSearchTerms.end()) || (sit == mSearchIds.end()))
{
/* error */
return 0;
}
rs_sprintf(desc, "Search(\"%s\") Found %d matches so far",
it->second.c_str(), mNotify->getSearchResultCount(sit->second));
return 1;
}
int MenuListSearch::getCurrentSearchId(uint32_t &id)
{
std::string strSearchId;
if (!getListEntry(mSelectIdx, strSearchId))
{
/* error */
return 0;
}
std::map<std::string, uint32_t>::iterator sit;
sit = mSearchIds.find(strSearchId);
if (sit == mSearchIds.end())
{
/* error */
return 0;
}
id = sit->second;
return 1;
}
int MenuListSearch::storeSearch(uint32_t searchId, std::string match_string)
{
std::cerr << "MenuListSearch::storeSearch(" << searchId << " => ";
std::cerr << match_string;
std::cerr << std::endl;
std::string strSearchId;
rs_sprintf(strSearchId, "%lu", searchId);
mList.push_back(strSearchId);
mSearchTerms[strSearchId] = match_string;
mSearchIds[strSearchId] = searchId;
return 1;
}
int MenuListSearch::removeSearch(std::string strSearchId)
{
std::cerr << "MenuListSearch::removeSearch(" << strSearchId << ")";
std::cerr << std::endl;
std::map<std::string, uint32_t>::iterator it;
it = mSearchIds.find(strSearchId);
if (it != mSearchIds.end())
{
/* cleanup local maps */
/* cancel search */
/* clear results from Notify Collector */
}
return 1;
}
uint32_t MenuOpSearchNew::process_lines(std::string input)
{
/* launch search */
if (input.size() < 4)
{
std::cerr << "MenuOpSearchNew::process_lines() ERROR Input too small";
std::cerr << std::endl;
return MENU_PROCESS_ERROR;
}
std::string search = input.substr(0, input.size() - 1); // remove \n.
uint32_t searchId = (uint32_t) rsTurtle->turtleSearch(search);
/* store request in parent */
MenuListSearch *ms = dynamic_cast<MenuListSearch *>(parent());
if (ms)
{
ms->storeSearch(searchId, search);
}
return MENU_PROCESS_DONE;
}
uint32_t MenuOpSearchDelete::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuListSearchList::op()
{
MenuList::op();
return refresh();
}
uint32_t MenuListSearchList::refresh()
{
Menu* p = parent();
MenuListSearch *mls = dynamic_cast<MenuListSearch *>(p);
if (!mls)
{
std::cerr << "MenuListSearchList::refresh() mls not there";
std::cerr << std::endl;
return MENU_OP_ERROR;
}
/* load friend list*/
mList.clear();
uint32_t searchId;
if (!mls->getCurrentSearchId(searchId))
{
std::cerr << "MenuListSearchList::refresh() currentIdx invalid";
std::cerr << std::endl;
return MENU_OP_ERROR;
}
std::cerr << "MenuListSearchList::refresh() searchId: " << searchId;
std::cerr << std::endl;
std::list<TurtleFileInfo>::iterator it;
mNotify->getSearchResults(searchId, mSearchResults);
/* convert into useful list */
for(it = mSearchResults.begin(); it != mSearchResults.end(); it++)
{
mList.push_back(it->hash);
}
mSelectIdx = -1;
mCursor = 0;
return MENU_OP_SUBMENU;
}
int MenuListSearchList::getEntryDesc(int idx, std::string &desc)
{
std::list<TurtleFileInfo>::iterator it;
int i = 0;
for (it = mSearchResults.begin();
(i < idx) && (it != mSearchResults.end()); it++, i++) ;
if (it != mSearchResults.end())
{
rs_sprintf(desc, "<%s> Size: %llu Name:%s",
it->hash.c_str(), it->size, it->name.c_str());
return MENU_ENTRY_OKAY;
}
return MENU_ENTRY_NONE;
}
int MenuListSearchList::downloadSelected()
{
if (mSelectIdx < 0)
{
std::cerr << "MenuListSearchList::downloadSelected() Invalid Selection";
std::cerr << std::endl;
return MENU_ENTRY_NONE;
}
std::list<TurtleFileInfo>::iterator it;
int i = 0;
for (it = mSearchResults.begin();
(i < mSelectIdx) && (it != mSearchResults.end()); it++, i++) ;
if (it != mSearchResults.end())
{
std::list<std::string> srcIds;
if (rsFiles -> FileRequest(it->name, it->hash, it->size,
"", RS_FILE_HINTS_NETWORK_WIDE, srcIds))
{
std::cerr << "MenuListSearchList::downloadSelected() Download Started";
std::cerr << std::endl;
}
else
{
std::cerr << "MenuListSearchList::downloadSelected() Error Starting Download";
std::cerr << std::endl;
}
return MENU_ENTRY_OKAY;
}
return MENU_ENTRY_NONE;
}
uint32_t MenuOpSearchListDownload::op_basic(std::string key)
{
Menu* p = parent();
MenuListSearchList *mlsl = dynamic_cast<MenuListSearchList *>(p);
if (!mlsl)
{
std::cerr << "MenuOpSearchListDownload::op_basic() ERROR";
std::cerr << std::endl;
return MENU_OP_ERROR;
}
mlsl->downloadSelected();
return MENU_OP_INSTANT;
}
/************
* Forums Menu
*/
uint32_t MenuListForums::op()
{
/* load friend list*/
mList.clear();
rsPeers->getGPGAcceptedList(mList);
mSelectIdx = 0;
return MENU_OP_SUBMENU;
}
int MenuListForums::getEntryDesc(int idx, std::string &desc)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumDetails::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumSubscribe::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumUnsubscribe::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumCreate::op_basic(std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuListForumMsgs::op()
{
/* load friend list*/
mList.clear();
rsPeers->getGPGAcceptedList(mList);
mSelectIdx = 0;
return MENU_OP_SUBMENU;
}
int MenuListForumMsgs::getEntryDesc(int idx, std::string &desc)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumMsgView::op_twokeys(std::string parentkey, std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumMsgReply::op_twokeys(std::string parentkey, std::string key)
{
return MENU_OP_INSTANT;
}
uint32_t MenuOpForumMsgWrite::op_twokeys(std::string parentkey, std::string key)
{
return MENU_OP_INSTANT;
}

View File

@ -0,0 +1,269 @@
#include "menu/menu.h"
#include <retroshare/rsturtle.h>
#include "notifytxt.h" /* needed to access search results */
#include <map>
Menu *CreateMenuStructure(NotifyTxt *notify);
/************
* Friends Menu
*/
class MenuListFriends: public MenuList
{
public:
MenuListFriends() :MenuList("Friends") { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
protected:
MenuListFriends(std::string name) :MenuList(name) { return; } // For Network.
};
class MenuListNetwork: public MenuListFriends
{
public:
MenuListNetwork() :MenuListFriends("Network") { return; }
virtual uint32_t op();
};
class MenuOpFriendsAdd: public MenuOpBasicKey
{
public:
MenuOpFriendsAdd() :MenuOpBasicKey("Add") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpFriendsViewDetail: public MenuOpBasicKey
{
public:
MenuOpFriendsViewDetail() :MenuOpBasicKey("View") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpFriendsRemove: public MenuOpBasicKey
{
public:
MenuOpFriendsRemove() :MenuOpBasicKey("Remove") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpFriendsChat: public MenuOpBasicKey
{
public:
MenuOpFriendsChat() :MenuOpBasicKey("Chat") { return; }
virtual uint32_t op_basic(std::string hash);
};
/************
* Transfer Menu
*/
class MenuListTransfer: public MenuList
{
public:
MenuListTransfer() :MenuList("Downloads") { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
};
class MenuOpTransferStop: public MenuOpBasicKey
{
public:
MenuOpTransferStop() :MenuOpBasicKey("Stop") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpTransferCancel: public MenuOpBasicKey
{
public:
MenuOpTransferCancel() :MenuOpBasicKey("Cancel") { return; }
virtual uint32_t op_basic(std::string hash);
};
/************
* Search Menu
*/
class MenuListSearch: public MenuList
{
public:
MenuListSearch(NotifyTxt *notify)
:MenuList("Search"), mNotify(notify) { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
/* specific Search Functions */
int getCurrentSearchId(uint32_t &id);
int storeSearch(uint32_t searchId, std::string match_string);
int removeSearch(std::string strSearchId);
private:
std::map<std::string, uint32_t> mSearchIds;
std::map<std::string, std::string> mSearchTerms;
NotifyTxt *mNotify;
};
class MenuOpSearchNew: public MenuOpLineInput
{
public:
MenuOpSearchNew() :MenuOpLineInput("New") { return; }
virtual uint32_t process_lines(std::string input);
};
class MenuOpSearchDelete: public MenuOpBasicKey
{
public:
MenuOpSearchDelete() :MenuOpBasicKey("Delete") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuListSearchList: public MenuList
{
public:
MenuListSearchList(NotifyTxt *notify)
:MenuList("Results"), mNotify(notify) { return; }
virtual uint32_t op();
uint32_t refresh();
int getEntryDesc(int idx, std::string &desc);
int downloadSelected();
private:
NotifyTxt *mNotify;
std::list<TurtleFileInfo> mSearchResults; // local cache for consistency.
};
class MenuOpSearchListDownload: public MenuOpBasicKey
{
public:
MenuOpSearchListDownload() :MenuOpBasicKey("Download") { return; }
virtual uint32_t op_basic(std::string hash);
};
/************
* Forums Menu
*/
class MenuListForums: public MenuList
{
public:
MenuListForums() :MenuList("Forums SubMenu") { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
};
class MenuOpForumDetails: public MenuOpBasicKey
{
public:
MenuOpForumDetails() :MenuOpBasicKey("Show Forum Details") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpForumSubscribe: public MenuOpBasicKey
{
public:
MenuOpForumSubscribe() :MenuOpBasicKey("Subscribe To Forum") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpForumUnsubscribe: public MenuOpBasicKey
{
public:
MenuOpForumUnsubscribe() :MenuOpBasicKey("Unsubscribe To Forum") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuOpForumCreate: public MenuOpBasicKey
{
public:
MenuOpForumCreate() :MenuOpBasicKey("Create Forum") { return; }
virtual uint32_t op_basic(std::string hash);
};
class MenuListForumMsgs: public MenuList
{
public:
MenuListForumMsgs() :MenuList("List Forum Msgs") { return; }
virtual uint32_t op();
int getEntryDesc(int idx, std::string &desc);
};
class MenuOpForumMsgView: public MenuOpTwoKeys
{
public:
MenuOpForumMsgView() :MenuOpTwoKeys("View Message") { return; }
virtual uint32_t op_twokeys(std::string parentkey, std::string key);
};
class MenuOpForumMsgReply: public MenuOpTwoKeys
{
public:
MenuOpForumMsgReply() :MenuOpTwoKeys("Reply to Message") { return; }
virtual uint32_t op_twokeys(std::string parentkey, std::string key);
};
class MenuOpForumMsgWrite: public MenuOpTwoKeys
{
public:
MenuOpForumMsgWrite() :MenuOpTwoKeys("Write Message") { return; }
virtual uint32_t op_twokeys(std::string parentkey, std::string key);
};

View File

@ -0,0 +1,32 @@
#include <iostream>
#include "menu/menu.h"
class MenuTest
{
public:
MenuTest(MenuInterface *i, std::istream &in, std::ostream &out)
:mMenus(i), mIn(in), mOut(out)
{
return;
}
int tick()
{
int c = mIn.get();
uint8_t key = (uint8_t) c;
mMenus->process(key);
return 1;
}
private:
MenuInterface *mMenus;
std::istream &mIn;
std::ostream &mOut;
};

View File

@ -95,7 +95,7 @@ bool NotifyTxt::askForPassword(const std::string& key_details, bool prev_is_bad,
void NotifyTxt::notifyListChange(int list, int type)
{
std::cerr << "NotifyTxt::notifyListChange()" << std::endl;
//std::cerr << "NotifyTxt::notifyListChange()" << std::endl;
switch(list)
{
// case NOTIFY_LIST_NEIGHBOURS:
@ -214,3 +214,94 @@ void NotifyTxt::displayTransfers()
iface->unlockData(); /* UnLock Interface */
}
/******************* Turtle Search Interface **********/
void NotifyTxt::notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& found_files)
{
// std::cerr << "NotifyTxt::notifyTurtleSearchResult() " << found_files.size();
// std::cerr << " new results for Id: " << search_id;
// std::cerr << std::endl;
RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/
std::map<uint32_t, std::list<TurtleFileInfo> >::iterator it;
it = mSearchResults.find(search_id);
if (it == mSearchResults.end())
{
/* new entry */
mSearchResults[search_id] = found_files;
return;
}
/* add to existing entry */
std::list<TurtleFileInfo>::const_iterator fit;
for(fit = found_files.begin(); fit != found_files.end(); fit++)
{
it->second.push_back(*fit);
}
return;
}
/* interface for handling SearchResults */
void NotifyTxt::getSearchIds(std::list<uint32_t> &searchIds)
{
RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/
std::map<uint32_t, std::list<TurtleFileInfo> >::iterator it;
for(it = mSearchResults.begin(); it != mSearchResults.end(); it++)
{
searchIds.push_back(it->first);
}
return;
}
int NotifyTxt::getSearchResults(uint32_t id, std::list<TurtleFileInfo> &searchResults)
{
RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/
std::map<uint32_t, std::list<TurtleFileInfo> >::iterator it;
it = mSearchResults.find(id);
if (it == mSearchResults.end())
{
return 0;
}
searchResults = it->second;
return 1;
}
int NotifyTxt::getSearchResultCount(uint32_t id)
{
RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/
std::map<uint32_t, std::list<TurtleFileInfo> >::iterator it;
it = mSearchResults.find(id);
if (it == mSearchResults.end())
{
return 0;
}
return it->second.size();
}
int NotifyTxt::clearSearchId(uint32_t searchId)
{
RsStackMutex stack(mNotifyMtx); /****** LOCKED *****/
std::map<uint32_t, std::list<TurtleFileInfo> >::iterator it;
it = mSearchResults.find(searchId);
if (it == mSearchResults.end())
{
return 0;
}
mSearchResults.erase(it);
return 1;
}

View File

@ -27,13 +27,15 @@
#include <retroshare/rsiface.h>
#include <retroshare/rsturtle.h>
#include "util/rsthreads.h"
#include <string>
class NotifyTxt: public NotifyBase
{
public:
NotifyTxt() { return; }
NotifyTxt():mNotifyMtx("NotifyMtx") { return; }
virtual ~NotifyTxt() { return; }
void setRsIface(RsIface *i) { iface = i; }
@ -42,6 +44,15 @@ class NotifyTxt: public NotifyBase
virtual void notifyChat();
virtual bool askForPassword(const std::string& key_details, bool prev_is_bad, std::string& password);
virtual void notifyTurtleSearchResult(uint32_t search_id,const std::list<TurtleFileInfo>& found_files);
/* interface for handling SearchResults */
void getSearchIds(std::list<uint32_t> &searchIds);
int getSearchResults(uint32_t id, std::list<TurtleFileInfo> &searchResults);
int clearSearchId(uint32_t searchId);
int getSearchResultCount(uint32_t id);
private:
void displayNeighbours();
@ -53,6 +64,12 @@ class NotifyTxt: public NotifyBase
void displayTransfers();
RsIface *iface; /* so we can get the data */
/* store TurtleSearchResults */
RsMutex mNotifyMtx;
std::map<uint32_t, std::list<TurtleFileInfo> > mSearchResults;
};
#endif

View File

@ -4,6 +4,17 @@ CONFIG += bitdht
#CONFIG += introserver
#CONFIG += sshserver
CONFIG += debug
debug {
QMAKE_CFLAGS -= -O2
QMAKE_CFLAGS += -O0
QMAKE_CFLAGS += -g
QMAKE_CXXFLAGS -= -O2
QMAKE_CXXFLAGS += -O0
QMAKE_CXXFLAGS += -g
}
################################# Linux ##########################################
linux-* {
#CONFIG += version_detail_bash_script
@ -123,12 +134,22 @@ sshserver {
#
# You can connect from a standard ssh, eg: ssh -p 7022 127.0.0.1
#
# The Menu system is available from the command-line now,
# but not over SSH yet...
# if it get covered by debug gunk, just press <return> to refresh.
#
INCLUDEPATH += ../../../lib/libssh-0.5.2/include/
LIBS += ../../../lib/libssh-0.5.2/build/src/libssh.a
LIBS += ../../../lib/libssh-0.5.2/build/src/threads/libssh_threads.a
HEADERS += ssh/rssshd.h
SOURCES += ssh/rssshd.cc
HEADERS += menu/menu.h \
menu/menus.h \
SOURCES += menu/menu.cc \
menu/menus.cc \
DEFINES *= RS_SSH_SERVER
}

View File

@ -42,6 +42,10 @@
#ifdef RS_SSH_SERVER
#include "ssh/rssshd.h"
#include "menu/menus.h"
#include "menu/menutest.h"
#endif
/* Basic instructions for running libretroshare as background thread.
@ -152,12 +156,17 @@ int main(int argc, char **argv)
#ifdef RS_SSH_SERVER
ssh->start();
Menu *baseMenu = CreateMenuStructure(notify);
MenuInterface *menuInterface = new MenuInterface(baseMenu);
MenuTest menuTest(menuInterface, std::cin, std::cout);
#endif
/* pass control to the GUI */
while(1)
{
std::cerr << "GUI Tick()" << std::endl;
//std::cerr << "GUI Tick()" << std::endl;
#ifndef WINDOWS_SYS
sleep(1);
#else
@ -167,6 +176,11 @@ int main(int argc, char **argv)
#ifdef RS_INTRO_SERVER
rsIS.tick();
#endif
#ifdef RS_SSH_SERVER
menuTest.tick();
#endif
}
return 1;
}