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; 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 () throw ()
: Gtk::TreeView(treeModel) : Gtk::TreeView(treeModel)
{ {
treeModel->signal_row_inserted().connect(sigc::mem_fun(*this, connectModelSignals(treeModel);
&ZebraTreeView::onRowInserted));
treeModel->signal_row_deleted().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowDeleted));
treeModel->signal_rows_reordered().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowsReordered));
this->signal_row_expanded().connect(sigc::mem_fun(*this, this->signal_row_expanded().connect(sigc::mem_fun(*this,
&ZebraTreeView::onRowExpanded)); &ZebraTreeView::onRowExpanded));
this->signal_row_collapsed().connect(sigc::mem_fun(*this, 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 :: LiveSupport :: GLiveSupport ::
GLiveSupport :: search(Ptr<SearchCriteria>::Ref criteria) GLiveSupport :: search(Ptr<SearchCriteria>::Ref criteria)
throw (XmlRpcException) 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 Ptr<LiveSupport::GLiveSupport::GLiveSupport::PlayableList>::Ref
results(new PlayableList); results(new PlayableList);
storage->search(sessionId, criteria);
Ptr<std::vector<Ptr<UniqueId>::Ref> >::Ref audioClipIds = getAudioClipIds(); Ptr<std::vector<Ptr<UniqueId>::Ref> >::Ref audioClipIds = getAudioClipIds();
std::vector<Ptr<UniqueId>::Ref>::const_iterator it; std::vector<Ptr<UniqueId>::Ref>::const_iterator it;
for (it = audioClipIds->begin(); it != audioClipIds->end(); ++it) { for (it = audioClipIds->begin(); it != audioClipIds->end(); ++it) {

View file

@ -945,6 +945,16 @@ class GLiveSupport : public LocalizedConfigurable,
search(Ptr<SearchCriteria>::Ref criteria) search(Ptr<SearchCriteria>::Ref criteria)
throw (XmlRpcException); 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. * Browse in the local storage.
* *

View file

@ -65,6 +65,12 @@ const Glib::ustring windowName = "masterPanelWindow";
*/ */
const int updateTimeConstant = 20; 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 */ /* =============================================== local function prototypes */
@ -382,17 +388,25 @@ MasterPanelWindow :: onUpdateTime(int dummy) throw ()
nowPlayingWidget->onUpdateTime(); nowPlayingWidget->onUpdateTime();
// check on the progress of the async methods
static int backupCounter = 0; static int backupCounter = 0;
if (backupCounter++ == updateTimeConstant * 10) { if (backupCounter++ == updateTimeConstant * asyncUpdateFrequency) {
backupCounter = 0; backupCounter = 0;
} }
if (backupCounter == 0 && optionsWindow) {
BackupList * backupList = optionsWindow->getBackupList(); if (backupCounter == 0) {
if (backupList) { if (optionsWindow) {
backupList->updateSilently(); BackupList * backupList = optionsWindow->getBackupList();
if (backupList) {
backupList->updateSilently();
}
}
if (searchWindow) {
searchWindow->onTimer();
} }
} }
return true; return true;
} }

View file

@ -58,6 +58,19 @@ using namespace LiveSupport::GLiveSupport;
/* ================================================ local constants & macros */ /* ================================================ 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 */ /* =============================================== local function prototypes */
@ -76,9 +89,11 @@ SearchWindow :: SearchWindow (Ptr<GLiveSupport>::Ref gLiveSupport,
WidgetConstants::searchWindowTitleImage, WidgetConstants::searchWindowTitleImage,
windowOpenerButton) windowOpenerButton)
{ {
Gtk::Box * simpleSearchView = constructSimpleSearchView(); Gtk::Box * searchWhereBox = constructSearchWhereBox();
Gtk::Box * simpleSearchView = constructSimpleSearchView();
Gtk::Box * advancedSearchView = constructAdvancedSearchView(); Gtk::Box * advancedSearchView = constructAdvancedSearchView();
Gtk::Box * browseView = constructBrowseView(); Gtk::Box * browseView = constructBrowseView();
ScrolledNotebook * searchInput = Gtk::manage(new ScrolledNotebook); ScrolledNotebook * searchInput = Gtk::manage(new ScrolledNotebook);
try { try {
@ -94,21 +109,18 @@ SearchWindow :: SearchWindow (Ptr<GLiveSupport>::Ref gLiveSupport,
std::exit(1); std::exit(1);
} }
// set up the search results box // set up the search results box
ZebraTreeView * searchResultsView = constructSearchResultsView(); ScrolledWindow * searchResultsView = constructSearchResultsView();
Gtk::ScrolledWindow * searchResults = Gtk::manage(
new Gtk::ScrolledWindow);
searchResults->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
searchResults->add(*searchResultsView);
// set the sizes of the two parts of the window // set the sizes of the two parts of the window
searchInput ->set_size_request(750, 240); searchInput ->set_size_request(750, 240);
searchResults->set_size_request(750, 300); searchResultsView->set_size_request(750, 300);
// put them in one big box // put them in one big box
Gtk::VBox * bigBox = Gtk::manage(new Gtk::VBox); Gtk::VBox * bigBox = Gtk::manage(new Gtk::VBox);
bigBox->pack_start(*searchInput, Gtk::PACK_SHRINK); bigBox->pack_start(*searchWhereBox, Gtk::PACK_SHRINK);
bigBox->pack_start(*searchResults); bigBox->pack_start(*searchInput, Gtk::PACK_SHRINK);
bigBox->pack_start(*searchResultsView);
add(*bigBox); add(*bigBox);
// show // 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. * Construct the simple search view.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@ -231,33 +289,41 @@ SearchWindow :: constructBrowseView(void) throw ()
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Construct the search results display. * Construct the search results display.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
ZebraTreeView * ScrolledWindow *
SearchWindow :: constructSearchResultsView(void) throw () SearchWindow :: constructSearchResultsView(void) throw ()
{ {
Ptr<WidgetFactory>::Ref wf = WidgetFactory::getInstance(); Ptr<WidgetFactory>::Ref wf = WidgetFactory::getInstance();
treeModel = Gtk::ListStore::create(modelColumns); localSearchResults = Gtk::ListStore::create(modelColumns);
searchResults = Gtk::manage(wf->createTreeView(treeModel)); remoteSearchResults = Gtk::ListStore::create(modelColumns);
searchResultsTreeView = Gtk::manage(wf->createTreeView(localSearchResults));
searchResultsTreeView->connectModelSignals(remoteSearchResults);
// add the TreeView's view columns // add the TreeView's view columns
try { try {
searchResults->appendColumn(*getResourceUstring("typeColumnLabel"), searchResultsTreeView->appendColumn(
modelColumns.typeColumn, 20); *getResourceUstring("typeColumnLabel"),
searchResults->appendColumn(*getResourceUstring("titleColumnLabel"), modelColumns.typeColumn, 20);
modelColumns.titleColumn, 360); searchResultsTreeView->appendColumn(
searchResults->appendColumn(*getResourceUstring("creatorColumnLabel"), *getResourceUstring("titleColumnLabel"),
modelColumns.creatorColumn, 260); modelColumns.titleColumn, 360);
searchResults->appendColumn(*getResourceUstring("lengthColumnLabel"), searchResultsTreeView->appendColumn(
modelColumns.lengthColumn, 50); *getResourceUstring("creatorColumnLabel"),
modelColumns.creatorColumn, 260);
searchResultsTreeView->appendColumn(
*getResourceUstring("lengthColumnLabel"),
modelColumns.lengthColumn, 50);
} catch (std::invalid_argument &e) { } catch (std::invalid_argument &e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
std::exit(1); std::exit(1);
} }
// register the signal handler for treeview entries being clicked // 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)); *this, &SearchWindow::onEntryClicked));
searchResults->signal_row_activated().connect(sigc::mem_fun( searchResultsTreeView->signal_row_activated().connect(sigc::mem_fun(
*this, &SearchWindow::onDoubleClick)); *this, &SearchWindow::onDoubleClick));
// create the right-click entry context menu // create the right-click entry context menu
@ -284,7 +350,13 @@ SearchWindow :: constructSearchResultsView(void) throw ()
} }
contextMenu->accelerate(*this); 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;
} }
@ -301,7 +373,7 @@ SearchWindow :: onSimpleSearch(void) throw ()
MetadataTypeContainer::Vector::const_iterator MetadataTypeContainer::Vector::const_iterator
it = metadataTypes->begin(); it = metadataTypes->begin();
Ptr<SearchCriteria>::Ref criteria(new SearchCriteria("all", "or")); Ptr<SearchCriteria>::Ref criteria(new SearchCriteria("all", "or"));
Ptr<const MetadataType>::Ref metadata; Ptr<const MetadataType>::Ref metadata;
if (it != metadataTypes->end()) { if (it != metadataTypes->end()) {
@ -349,6 +421,24 @@ SearchWindow :: onBrowse(void) throw ()
void void
SearchWindow :: onSearch(Ptr<SearchCriteria>::Ref criteria) SearchWindow :: onSearch(Ptr<SearchCriteria>::Ref criteria)
throw () 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; Ptr<std::list<Ptr<Playable>::Ref> >::Ref searchResults;
try { try {
@ -357,11 +447,26 @@ SearchWindow :: onSearch(Ptr<SearchCriteria>::Ref criteria)
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return; 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(); Ptr<WidgetFactory>::Ref widgetFactory = WidgetFactory::getInstance();
std::list<Ptr<Playable>::Ref>::const_iterator it; std::list<Ptr<Playable>::Ref>::const_iterator it;
treeModel->clear();
for (it = searchResults->begin(); it != searchResults->end(); ++it) { for (it = searchResults->begin(); it != searchResults->end(); ++it) {
Ptr<Playable>::Ref playable = *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 * 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) { if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
Glib::RefPtr<Gtk::TreeView::Selection> refSelection = Glib::RefPtr<Gtk::TreeView::Selection> refSelection =
searchResults->get_selection(); searchResultsTreeView->get_selection();
if (refSelection) { if (refSelection) {
Gtk::TreeModel::iterator iter = refSelection->get_selected(); Gtk::TreeModel::iterator iter = refSelection->get_selected();
@ -419,7 +644,7 @@ SearchWindow :: onEntryClicked (GdkEventButton * event) throw ()
Gtk::TreeViewColumn * column; Gtk::TreeViewColumn * column;
int cell_x, int cell_x,
cell_y; cell_y;
if (searchResults->get_path_at_pos( if (searchResultsTreeView->get_path_at_pos(
int(event->x), int(event->y), int(event->x), int(event->y),
path, column, path, column,
cell_x, cell_y )) { cell_x, cell_y )) {
@ -431,18 +656,20 @@ SearchWindow :: onEntryClicked (GdkEventButton * event) throw ()
if (iter) { if (iter) {
Ptr<Playable>::Ref playable = Ptr<Playable>::Ref playable =
(*iter)[modelColumns.playableColumn]; (*iter)[modelColumns.playableColumn];
if (playable) {
switch (playable->getType()) {
case Playable::AudioClipType:
contextMenu->popup(event->button, event->time);
break;
case Playable::PlaylistType:
contextMenu->popup(event->button, event->time);
break;
switch (playable->getType()) { default:
case Playable::AudioClipType: break;
contextMenu->popup(event->button, event->time); }
break;
case Playable::PlaylistType:
contextMenu->popup(event->button, event->time);
break;
default:
break;
} }
} }
} }
@ -457,11 +684,14 @@ void
SearchWindow :: onAddToScratchpad(void) throw () SearchWindow :: onAddToScratchpad(void) throw ()
{ {
Glib::RefPtr<Gtk::TreeView::Selection> refSelection = Glib::RefPtr<Gtk::TreeView::Selection> refSelection =
searchResults->get_selection(); searchResultsTreeView->get_selection();
Gtk::TreeModel::iterator iter = refSelection->get_selected(); Gtk::TreeModel::iterator iter = refSelection->get_selected();
if (iter) { if (iter) {
Ptr<Playable>::Ref playable = (*iter)[modelColumns.playableColumn]; Ptr<Playable>::Ref playable = (*iter)[modelColumns.playableColumn];
gLiveSupport->addToScratchpad(playable); if (playable) {
gLiveSupport->addToScratchpad(playable);
}
} }
} }
@ -473,12 +703,15 @@ void
SearchWindow :: onAddToLiveMode(void) throw () SearchWindow :: onAddToLiveMode(void) throw ()
{ {
Glib::RefPtr<Gtk::TreeView::Selection> refSelection = Glib::RefPtr<Gtk::TreeView::Selection> refSelection =
searchResults->get_selection(); searchResultsTreeView->get_selection();
Gtk::TreeModel::iterator iter = refSelection->get_selected(); Gtk::TreeModel::iterator iter = refSelection->get_selected();
if (iter) { if (iter) {
Ptr<Playable>::Ref playable = (*iter)[modelColumns.playableColumn]; Ptr<Playable>::Ref playable = (*iter)[modelColumns.playableColumn];
gLiveSupport->addToLiveMode(playable); if (playable) {
gLiveSupport->addToScratchpad(playable); gLiveSupport->addToLiveMode(playable);
gLiveSupport->addToScratchpad(playable);
}
} }
} }
@ -490,19 +723,22 @@ void
SearchWindow :: onExportPlaylist(void) throw () SearchWindow :: onExportPlaylist(void) throw ()
{ {
Glib::RefPtr<Gtk::TreeView::Selection> Glib::RefPtr<Gtk::TreeView::Selection>
refSelection = searchResults->get_selection(); refSelection = searchResultsTreeView->get_selection();
Gtk::TreeModel::iterator iter = refSelection->get_selected(); Gtk::TreeModel::iterator
iter = refSelection->get_selected();
if (iter) { if (iter) {
Ptr<Playable>::Ref playable = (*iter)[modelColumns.playableColumn]; Ptr<Playable>::Ref playable = (*iter)[modelColumns.playableColumn];
Ptr<Playlist>::Ref playlist = playable->getPlaylist(); if (playable) {
if (playlist) { Ptr<Playlist>::Ref playlist = playable->getPlaylist();
exportPlaylistWindow.reset(new ExportPlaylistWindow( if (playlist) {
exportPlaylistWindow.reset(new ExportPlaylistWindow(
gLiveSupport, gLiveSupport,
gLiveSupport->getBundle("exportPlaylistWindow"), gLiveSupport->getBundle("exportPlaylistWindow"),
playlist)); playlist));
exportPlaylistWindow->set_transient_for(*this); exportPlaylistWindow->set_transient_for(*this);
Gtk::Main::run(*exportPlaylistWindow); Gtk::Main::run(*exportPlaylistWindow);
}
} }
} }
} }
@ -533,3 +769,30 @@ SearchWindow :: on_hide(void) throw ()
GuiWindow::on_hide(); 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/Core/LocalizedObject.h"
#include "LiveSupport/Widgets/Button.h" #include "LiveSupport/Widgets/Button.h"
#include "LiveSupport/Widgets/PlayableTreeModelColumnRecord.h" #include "LiveSupport/Widgets/PlayableTreeModelColumnRecord.h"
#include "LiveSupport/Widgets/ScrolledWindow.h"
#include "GuiWindow.h" #include "GuiWindow.h"
#include "AdvancedSearchEntry.h" #include "AdvancedSearchEntry.h"
#include "BrowseEntry.h" #include "BrowseEntry.h"
@ -80,6 +81,11 @@ class SearchWindow : public GuiWindow
{ {
private: private:
/**
* The "search where" input field.
*/
ComboBoxText * searchWhereEntry;
/** /**
* The simple search input field. * The simple search input field.
*/ */
@ -100,6 +106,16 @@ class SearchWindow : public GuiWindow
*/ */
Ptr<ExportPlaylistWindow>::Ref exportPlaylistWindow; 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. * Construct the simple search view.
* If you enter a string in theGtk::VBox simple search view and * 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) * @return a pointer to the new tree view (already Gtk::manage()'ed)
*/ */
ZebraTreeView * ScrolledWindow *
constructSearchResultsView(void) throw (); constructSearchResultsView(void) throw ();
/** /**
@ -158,9 +174,51 @@ class SearchWindow : public GuiWindow
/** /**
* Do the searching. * Do the searching.
* Calls either localSearch() or remoteSearch().
*
* @param criteria the search criteria.
*/ */
void void
onSearch(Ptr<SearchCriteria>::Ref criteria) throw (); 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. * Signal handler for the mouse clicked on one of the entries.
@ -258,21 +316,42 @@ class SearchWindow : public GuiWindow
ModelColumns modelColumns; 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. * 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. * The pop-up context menu for found items.
*/ */
Gtk::Menu * contextMenu; 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: public:
/** /**
@ -295,6 +374,14 @@ class SearchWindow : public GuiWindow
*/ */
virtual virtual
~SearchWindow(void) throw (); ~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 */ /* ================================================= external data structures */

View file

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