progress towards #1595 ([2027] and [2029] were that, too)

This commit is contained in:
fgerlits 2006-05-02 17:38:31 +00:00
parent a577df91bd
commit 06e190c27d
8 changed files with 489 additions and 73 deletions

View file

@ -396,6 +396,19 @@ class ZebraTreeView : public Gtk::TreeView
{
return signalCellEditedObject;
}
/**
* Manually connect the 'model has changed' signals to the tree view.
* This is useful if you want to use the same ZebraTreeView object
* to alternately display two (or more) different tree models.
*
* @param treeModel the tree model whose changes should trigger
* a redraw of the tree view object
*/
void
connectModelSignals(Glib::RefPtr<Gtk::TreeModel> treeModel)
throw ();
};

View file

@ -63,12 +63,7 @@ ZebraTreeView :: ZebraTreeView(Glib::RefPtr<Gtk::TreeModel> treeModel)
throw ()
: Gtk::TreeView(treeModel)
{
treeModel->signal_row_inserted().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowInserted));
treeModel->signal_row_deleted().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowDeleted));
treeModel->signal_rows_reordered().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowsReordered));
connectModelSignals(treeModel);
this->signal_row_expanded().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowExpanded));
this->signal_row_collapsed().connect(sigc::mem_fun(*this,
@ -565,3 +560,19 @@ ZebraTreeView :: renumberRows(void) throw ()
}
}
/*------------------------------------------------------------------------------
* Manually connect the 'model has changed' signals to the tree view.
*----------------------------------------------------------------------------*/
void
ZebraTreeView :: connectModelSignals(Glib::RefPtr<Gtk::TreeModel> treeModel)
throw ()
{
treeModel->signal_row_inserted().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowInserted));
treeModel->signal_row_deleted().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowDeleted));
treeModel->signal_rows_reordered().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowsReordered));
}

View file

@ -1310,12 +1310,23 @@ Ptr<LiveSupport::GLiveSupport::GLiveSupport::PlayableList>::Ref
LiveSupport :: GLiveSupport ::
GLiveSupport :: search(Ptr<SearchCriteria>::Ref criteria)
throw (XmlRpcException)
{
storage->search(sessionId, criteria);
return readSearchResults();
}
/*------------------------------------------------------------------------------
* Return the Playable items found by the latest search (local or remote).
*----------------------------------------------------------------------------*/
Ptr<LiveSupport::GLiveSupport::GLiveSupport::PlayableList>::Ref
LiveSupport :: GLiveSupport ::
GLiveSupport :: readSearchResults(void) throw (XmlRpcException)
{
Ptr<LiveSupport::GLiveSupport::GLiveSupport::PlayableList>::Ref
results(new PlayableList);
storage->search(sessionId, criteria);
Ptr<std::vector<Ptr<UniqueId>::Ref> >::Ref audioClipIds = getAudioClipIds();
std::vector<Ptr<UniqueId>::Ref>::const_iterator it;
for (it = audioClipIds->begin(); it != audioClipIds->end(); ++it) {

View file

@ -945,6 +945,16 @@ class GLiveSupport : public LocalizedConfigurable,
search(Ptr<SearchCriteria>::Ref criteria)
throw (XmlRpcException);
/**
* Return the Playable items found by the latest search.
*
* @return the list of audio clips and playlists found.
* @exception XmlRpcException passed on from getAudioClip() or
* getPlaylist().
*/
Ptr<PlayableList>::Ref
readSearchResults(void) throw (XmlRpcException);
/**
* Browse in the local storage.
*

View file

@ -65,6 +65,12 @@ const Glib::ustring windowName = "masterPanelWindow";
*/
const int updateTimeConstant = 20;
/**
* The delay between two checks on the progress of an asynchronous method
* (in seconds).
*/
const int asyncUpdateFrequency = 10;
}
/* =============================================== local function prototypes */
@ -382,17 +388,25 @@ MasterPanelWindow :: onUpdateTime(int dummy) throw ()
nowPlayingWidget->onUpdateTime();
// check on the progress of the async methods
static int backupCounter = 0;
if (backupCounter++ == updateTimeConstant * 10) {
if (backupCounter++ == updateTimeConstant * asyncUpdateFrequency) {
backupCounter = 0;
}
if (backupCounter == 0 && optionsWindow) {
if (backupCounter == 0) {
if (optionsWindow) {
BackupList * backupList = optionsWindow->getBackupList();
if (backupList) {
backupList->updateSilently();
}
}
if (searchWindow) {
searchWindow->onTimer();
}
}
return true;
}

View file

@ -58,6 +58,19 @@ using namespace LiveSupport::GLiveSupport;
/* ================================================ local constants & macros */
namespace {
/*------------------------------------------------------------------------------
* The 'search where' combo box key for local searches.
*----------------------------------------------------------------------------*/
const std::string searchWhereLocalKey = "searchWhereLocal";
/*------------------------------------------------------------------------------
* The 'search where' combo box key for remote searches.
*----------------------------------------------------------------------------*/
const std::string searchWhereRemoteKey = "searchWhereRemote";
}
/* =============================================== local function prototypes */
@ -76,6 +89,8 @@ SearchWindow :: SearchWindow (Ptr<GLiveSupport>::Ref gLiveSupport,
WidgetConstants::searchWindowTitleImage,
windowOpenerButton)
{
Gtk::Box * searchWhereBox = constructSearchWhereBox();
Gtk::Box * simpleSearchView = constructSimpleSearchView();
Gtk::Box * advancedSearchView = constructAdvancedSearchView();
Gtk::Box * browseView = constructBrowseView();
@ -95,20 +110,17 @@ SearchWindow :: SearchWindow (Ptr<GLiveSupport>::Ref gLiveSupport,
}
// set up the search results box
ZebraTreeView * searchResultsView = constructSearchResultsView();
Gtk::ScrolledWindow * searchResults = Gtk::manage(
new Gtk::ScrolledWindow);
searchResults->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
searchResults->add(*searchResultsView);
ScrolledWindow * searchResultsView = constructSearchResultsView();
// set the sizes of the two parts of the window
searchInput ->set_size_request(750, 240);
searchResults->set_size_request(750, 300);
searchResultsView->set_size_request(750, 300);
// put them in one big box
Gtk::VBox * bigBox = Gtk::manage(new Gtk::VBox);
bigBox->pack_start(*searchWhereBox, Gtk::PACK_SHRINK);
bigBox->pack_start(*searchInput, Gtk::PACK_SHRINK);
bigBox->pack_start(*searchResults);
bigBox->pack_start(*searchResultsView);
add(*bigBox);
// show
@ -128,6 +140,52 @@ SearchWindow :: ~SearchWindow (void) throw ()
}
/*------------------------------------------------------------------------------
* Construct the transport type selection box.
*----------------------------------------------------------------------------*/
Gtk::VBox*
SearchWindow :: constructSearchWhereBox(void) throw ()
{
Ptr<WidgetFactory>::Ref wf = WidgetFactory::getInstance();
Gtk::Label * searchWhereLabel;
try {
searchWhereLabel = Gtk::manage(new Gtk::Label(
*getResourceUstring("searchWhereLabel") ));
searchWhereEntry = Gtk::manage(wf->createComboBoxText());
Ptr<Glib::ustring>::Ref localKey(new Glib::ustring(
searchWhereLocalKey));
Ptr<Glib::ustring>::Ref remoteKey(new Glib::ustring(
searchWhereRemoteKey));
searchWhereEntry->appendPair(getResourceUstring(searchWhereLocalKey),
localKey);
searchWhereEntry->appendPair(getResourceUstring(searchWhereRemoteKey),
remoteKey);
} catch (std::invalid_argument &e) {
std::cerr << e.what() << std::endl;
std::exit(1);
}
searchWhereEntry->set_active(0);
searchWhereEntry->signalSelectionChanged().connect(sigc::mem_fun(
*this, &SearchWindow::onSearchWhereChanged ));
Gtk::HBox * hBox = Gtk::manage(new Gtk::HBox);
hBox->pack_start(*searchWhereLabel, Gtk::PACK_SHRINK, 5);
hBox->pack_start(*searchWhereEntry, Gtk::PACK_SHRINK);
Gtk::HBox * padding = Gtk::manage(new Gtk::HBox);
Gtk::VBox * vBox = Gtk::manage(new Gtk::VBox);
vBox->pack_start(*hBox, Gtk::PACK_SHRINK, 5);
vBox->pack_start(*padding, Gtk::PACK_SHRINK, 5);
return vBox;
}
/*------------------------------------------------------------------------------
* Construct the simple search view.
*----------------------------------------------------------------------------*/
@ -231,23 +289,30 @@ SearchWindow :: constructBrowseView(void) throw ()
/*------------------------------------------------------------------------------
* Construct the search results display.
*----------------------------------------------------------------------------*/
ZebraTreeView *
ScrolledWindow *
SearchWindow :: constructSearchResultsView(void) throw ()
{
Ptr<WidgetFactory>::Ref wf = WidgetFactory::getInstance();
treeModel = Gtk::ListStore::create(modelColumns);
searchResults = Gtk::manage(wf->createTreeView(treeModel));
localSearchResults = Gtk::ListStore::create(modelColumns);
remoteSearchResults = Gtk::ListStore::create(modelColumns);
searchResultsTreeView = Gtk::manage(wf->createTreeView(localSearchResults));
searchResultsTreeView->connectModelSignals(remoteSearchResults);
// add the TreeView's view columns
try {
searchResults->appendColumn(*getResourceUstring("typeColumnLabel"),
searchResultsTreeView->appendColumn(
*getResourceUstring("typeColumnLabel"),
modelColumns.typeColumn, 20);
searchResults->appendColumn(*getResourceUstring("titleColumnLabel"),
searchResultsTreeView->appendColumn(
*getResourceUstring("titleColumnLabel"),
modelColumns.titleColumn, 360);
searchResults->appendColumn(*getResourceUstring("creatorColumnLabel"),
searchResultsTreeView->appendColumn(
*getResourceUstring("creatorColumnLabel"),
modelColumns.creatorColumn, 260);
searchResults->appendColumn(*getResourceUstring("lengthColumnLabel"),
searchResultsTreeView->appendColumn(
*getResourceUstring("lengthColumnLabel"),
modelColumns.lengthColumn, 50);
} catch (std::invalid_argument &e) {
std::cerr << e.what() << std::endl;
@ -255,9 +320,10 @@ SearchWindow :: constructSearchResultsView(void) throw ()
}
// register the signal handler for treeview entries being clicked
searchResults->signal_button_press_event().connect_notify(sigc::mem_fun(
searchResultsTreeView->signal_button_press_event().connect_notify(
sigc::mem_fun(
*this, &SearchWindow::onEntryClicked));
searchResults->signal_row_activated().connect(sigc::mem_fun(
searchResultsTreeView->signal_row_activated().connect(sigc::mem_fun(
*this, &SearchWindow::onDoubleClick));
// create the right-click entry context menu
@ -284,7 +350,13 @@ SearchWindow :: constructSearchResultsView(void) throw ()
}
contextMenu->accelerate(*this);
return searchResults;
// put the tree view inside a scrolled window
ScrolledWindow * view = Gtk::manage(new ScrolledWindow);
view->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
view->add(*searchResultsTreeView);
return view;
}
@ -349,6 +421,24 @@ SearchWindow :: onBrowse(void) throw ()
void
SearchWindow :: onSearch(Ptr<SearchCriteria>::Ref criteria)
throw ()
{
Ptr<const Glib::ustring>::Ref searchWhere
= searchWhereEntry->getActiveKey();
if (*searchWhere == searchWhereLocalKey) {
localSearch(criteria);
} else {
remoteSearchOpen(criteria);
}
}
/*------------------------------------------------------------------------------
* Search in the local storage.
*----------------------------------------------------------------------------*/
void
SearchWindow :: localSearch(Ptr<SearchCriteria>::Ref criteria)
throw ()
{
Ptr<std::list<Ptr<Playable>::Ref> >::Ref searchResults;
try {
@ -358,10 +448,25 @@ SearchWindow :: onSearch(Ptr<SearchCriteria>::Ref criteria)
return;
}
displaySearchResults(searchResults, localSearchResults);
}
/*------------------------------------------------------------------------------
* Display the search results.
*----------------------------------------------------------------------------*/
void
SearchWindow :: displaySearchResults(
Ptr<std::list<Ptr<Playable>::Ref> >::Ref searchResults,
Glib::RefPtr<Gtk::ListStore> treeModel)
throw ()
{
treeModel->clear();
searchResultsTreeView->set_model(treeModel);
Ptr<WidgetFactory>::Ref widgetFactory = WidgetFactory::getInstance();
std::list<Ptr<Playable>::Ref>::const_iterator it;
treeModel->clear();
for (it = searchResults->begin(); it != searchResults->end(); ++it) {
Ptr<Playable>::Ref playable = *it;
@ -401,6 +506,126 @@ SearchWindow :: onSearch(Ptr<SearchCriteria>::Ref criteria)
}
/*------------------------------------------------------------------------------
* Search on the network hub (initiate the async operation).
*----------------------------------------------------------------------------*/
void
SearchWindow :: remoteSearchOpen(Ptr<SearchCriteria>::Ref criteria)
throw ()
{
displayMessage("pleaseWaitMsg", remoteSearchResults);
Ptr<StorageClientInterface>::Ref
storage = gLiveSupport->getStorageClient();
Ptr<SessionId>::Ref sessionId = gLiveSupport->getSessionId();
if (remoteSearchToken) {
try {
storage->cancelTransport(sessionId, remoteSearchToken);
} catch (XmlRpcException &e) {
gLiveSupport->displayMessageWindow(formatMessage(
"remoteSearchErrorMsg",
e.what() ));
return;
}
}
try {
remoteSearchToken = storage->remoteSearchOpen(sessionId, criteria);
} catch (XmlRpcException &e) {
gLiveSupport->displayMessageWindow(formatMessage(
"remoteSearchErrorMsg",
e.what() ));
}
}
/*------------------------------------------------------------------------------
* Search on the network hub (finish the async operation).
*----------------------------------------------------------------------------*/
void
SearchWindow :: remoteSearchClose(void)
throw ()
{
if (remoteSearchToken) {
Ptr<StorageClientInterface>::Ref
storage = gLiveSupport->getStorageClient();
Ptr<SessionId>::Ref sessionId = gLiveSupport->getSessionId();
StorageClientInterface::TransportState state;
Ptr<Glib::ustring>::Ref errorMessage;
try {
state = storage->checkTransport(remoteSearchToken, errorMessage);
} catch (XmlRpcException &e) {
gLiveSupport->displayMessageWindow(formatMessage(
"remoteSearchErrorMsg",
e.what() ));
return;
}
Ptr<std::list<Ptr<Playable>::Ref> >::Ref results;
switch (state) {
case StorageClientInterface::initState :
break;
case StorageClientInterface::pendingState :
break;
case StorageClientInterface::finishedState :
try {
storage->remoteSearchClose(remoteSearchToken);
} catch (XmlRpcException &e) {
gLiveSupport->displayMessageWindow(formatMessage(
"remoteSearchErrorMsg",
e.what() ));
return;
}
remoteSearchToken.reset();
try {
results = gLiveSupport->readSearchResults();
} catch (XmlRpcException &e) {
gLiveSupport->displayMessageWindow(formatMessage(
"remoteSearchErrorMsg",
e.what() ));
return;
}
displaySearchResults(results, remoteSearchResults);
break;
case StorageClientInterface::closedState :
remoteSearchToken.reset();
displayMessage("remoteSearchErrorMsg", remoteSearchResults);
break;
case StorageClientInterface::failedState :
remoteSearchToken.reset();
displayMessage(*errorMessage, remoteSearchResults);
break;
}
}
}
/*------------------------------------------------------------------------------
* Display a (usually error) message in the search results tree view.
*----------------------------------------------------------------------------*/
void
SearchWindow :: displayMessage(const Glib::ustring & messageKey,
Glib::RefPtr<Gtk::ListStore> treeModel)
throw ()
{
treeModel->clear();
Gtk::TreeModel::Row row = *treeModel->append();
row[modelColumns.titleColumn] = *getResourceUstring(messageKey);
searchResultsTreeView->set_model(treeModel);
}
/*------------------------------------------------------------------------------
* Event handler for an entry being clicked in the list
*----------------------------------------------------------------------------*/
@ -409,7 +634,7 @@ SearchWindow :: onEntryClicked (GdkEventButton * event) throw ()
{
if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
Glib::RefPtr<Gtk::TreeView::Selection> refSelection =
searchResults->get_selection();
searchResultsTreeView->get_selection();
if (refSelection) {
Gtk::TreeModel::iterator iter = refSelection->get_selected();
@ -419,7 +644,7 @@ SearchWindow :: onEntryClicked (GdkEventButton * event) throw ()
Gtk::TreeViewColumn * column;
int cell_x,
cell_y;
if (searchResults->get_path_at_pos(
if (searchResultsTreeView->get_path_at_pos(
int(event->x), int(event->y),
path, column,
cell_x, cell_y )) {
@ -432,6 +657,7 @@ SearchWindow :: onEntryClicked (GdkEventButton * event) throw ()
Ptr<Playable>::Ref playable =
(*iter)[modelColumns.playableColumn];
if (playable) {
switch (playable->getType()) {
case Playable::AudioClipType:
contextMenu->popup(event->button, event->time);
@ -448,6 +674,7 @@ SearchWindow :: onEntryClicked (GdkEventButton * event) throw ()
}
}
}
}
/*------------------------------------------------------------------------------
@ -457,13 +684,16 @@ void
SearchWindow :: onAddToScratchpad(void) throw ()
{
Glib::RefPtr<Gtk::TreeView::Selection> refSelection =
searchResults->get_selection();
searchResultsTreeView->get_selection();
Gtk::TreeModel::iterator iter = refSelection->get_selected();
if (iter) {
Ptr<Playable>::Ref playable = (*iter)[modelColumns.playableColumn];
if (playable) {
gLiveSupport->addToScratchpad(playable);
}
}
}
/*------------------------------------------------------------------------------
@ -473,14 +703,17 @@ void
SearchWindow :: onAddToLiveMode(void) throw ()
{
Glib::RefPtr<Gtk::TreeView::Selection> refSelection =
searchResults->get_selection();
searchResultsTreeView->get_selection();
Gtk::TreeModel::iterator iter = refSelection->get_selected();
if (iter) {
Ptr<Playable>::Ref playable = (*iter)[modelColumns.playableColumn];
if (playable) {
gLiveSupport->addToLiveMode(playable);
gLiveSupport->addToScratchpad(playable);
}
}
}
/*------------------------------------------------------------------------------
@ -490,11 +723,13 @@ void
SearchWindow :: onExportPlaylist(void) throw ()
{
Glib::RefPtr<Gtk::TreeView::Selection>
refSelection = searchResults->get_selection();
Gtk::TreeModel::iterator iter = refSelection->get_selected();
refSelection = searchResultsTreeView->get_selection();
Gtk::TreeModel::iterator
iter = refSelection->get_selected();
if (iter) {
Ptr<Playable>::Ref playable = (*iter)[modelColumns.playableColumn];
if (playable) {
Ptr<Playlist>::Ref playlist = playable->getPlaylist();
if (playlist) {
exportPlaylistWindow.reset(new ExportPlaylistWindow(
@ -506,6 +741,7 @@ SearchWindow :: onExportPlaylist(void) throw ()
}
}
}
}
/*------------------------------------------------------------------------------
@ -533,3 +769,30 @@ SearchWindow :: on_hide(void) throw ()
GuiWindow::on_hide();
}
/*------------------------------------------------------------------------------
* Change the displayed search results (local or remote).
*----------------------------------------------------------------------------*/
void
SearchWindow :: onSearchWhereChanged(void) throw ()
{
Ptr<const Glib::ustring>::Ref searchWhere
= searchWhereEntry->getActiveKey();
if (*searchWhere == searchWhereLocalKey) {
searchResultsTreeView->set_model(localSearchResults);
} else {
searchResultsTreeView->set_model(remoteSearchResults);
}
}
/*------------------------------------------------------------------------------
* Perform the periodic checks on the asynchronous methods.
*----------------------------------------------------------------------------*/
void
SearchWindow :: onTimer(void) throw ()
{
remoteSearchClose();
}

View file

@ -49,6 +49,7 @@
#include "LiveSupport/Core/LocalizedObject.h"
#include "LiveSupport/Widgets/Button.h"
#include "LiveSupport/Widgets/PlayableTreeModelColumnRecord.h"
#include "LiveSupport/Widgets/ScrolledWindow.h"
#include "GuiWindow.h"
#include "AdvancedSearchEntry.h"
#include "BrowseEntry.h"
@ -80,6 +81,11 @@ class SearchWindow : public GuiWindow
{
private:
/**
* The "search where" input field.
*/
ComboBoxText * searchWhereEntry;
/**
* The simple search input field.
*/
@ -100,6 +106,16 @@ class SearchWindow : public GuiWindow
*/
Ptr<ExportPlaylistWindow>::Ref exportPlaylistWindow;
/**
* Construct the "search where" box.
* This contains a combo box, where the user can choose between
* local search or hub search.
*
* @return a pointer to the new box (already Gtk::manage()'ed)
*/
Gtk::VBox*
constructSearchWhereBox(void) throw ();
/**
* Construct the simple search view.
* If you enter a string in theGtk::VBox simple search view and
@ -135,7 +151,7 @@ class SearchWindow : public GuiWindow
*
* @return a pointer to the new tree view (already Gtk::manage()'ed)
*/
ZebraTreeView *
ScrolledWindow *
constructSearchResultsView(void) throw ();
/**
@ -158,10 +174,52 @@ class SearchWindow : public GuiWindow
/**
* Do the searching.
* Calls either localSearch() or remoteSearch().
*
* @param criteria the search criteria.
*/
void
onSearch(Ptr<SearchCriteria>::Ref criteria) throw ();
/**
* Change the displayed search results (local or remote).
*/
void
onSearchWhereChanged(void) throw ();
/**
* Search in the local storage.
*
* @param criteria the search criteria.
*/
void
localSearch(Ptr<SearchCriteria>::Ref criteria) throw ();
/**
* Search on the network hub (initiate the async operation).
*
* @param criteria the search criteria.
*/
void
remoteSearchOpen(Ptr<SearchCriteria>::Ref criteria) throw ();
/**
* Search on the network hub (finish the async operation).
*/
void
remoteSearchClose(void) throw ();
/**
* Display the search results.
* The most important metadata are shown in the rows of the given
* tree model.
*/
void
displaySearchResults(
Ptr<std::list<Ptr<Playable>::Ref> >::Ref searchResults,
Glib::RefPtr<Gtk::ListStore> treeModel)
throw ();
/**
* Signal handler for the mouse clicked on one of the entries.
*
@ -258,14 +316,24 @@ class SearchWindow : public GuiWindow
ModelColumns modelColumns;
/**
* The tree model, as a GTK reference.
* The tree model, as a GTK reference, for the local search results.
*/
Glib::RefPtr<Gtk::ListStore> treeModel;
Glib::RefPtr<Gtk::ListStore> localSearchResults;
/**
* The tree model, as a GTK reference, for the remote search results.
*/
Glib::RefPtr<Gtk::ListStore> remoteSearchResults;
/**
* The tree view showing the search results.
*/
ZebraTreeView * searchResults;
ZebraTreeView * searchResultsTreeView;
/**
* The transport token used when a remote search is pending.
*/
Ptr<const Glib::ustring>::Ref remoteSearchToken;
/**
* The pop-up context menu for found items.
@ -273,6 +341,17 @@ class SearchWindow : public GuiWindow
Gtk::Menu * contextMenu;
/**
* Display a (usually error) message in the search results tree view.
*
* @param messageKey the localization key for the message.
* @param treeModel the tree model to display the message in.
*/
void
displayMessage(const Glib::ustring & messageKey,
Glib::RefPtr<Gtk::ListStore> treeModel)
throw ();
public:
/**
@ -295,6 +374,14 @@ class SearchWindow : public GuiWindow
*/
virtual
~SearchWindow(void) throw ();
/**
* Perform the periodic checks on the asynchronous methods.
* This is called every few seconds by the onUpdateTime() function
* in the MasterPanelWindow.
*/
void
onTimer(void) throw ();
};
/* ================================================= external data structures */

View file

@ -185,6 +185,10 @@ root:table
{
windowTitle:string { "Search/Browse" }
searchWhereLabel:string { "Search or browse on: " }
searchWhereLocal:string { "local storage" }
searchWhereRemote:string { "network hub" }
simpleSearchTab:string { "Search" }
advancedSearchTab:string { "Advanced Search" }
browseTab:string { "Browse" }
@ -201,6 +205,9 @@ root:table
addToScratchpadMenuItem:string { "_Add To Scratchpad" }
addToLiveModeMenuItem:string { "Add To _Live Mode" }
exportPlaylistMenuItem:string { "E_xport Playlist" }
pleaseWaitMsg:string { "Please wait..." }
remoteSearchErrorMsg:string { "Search failed: {0}." }
}
advancedSearchEntry:table {