progress towards #1595 ([2027] and [2029] were that, too)
This commit is contained in:
parent
a577df91bd
commit
06e190c27d
8 changed files with 489 additions and 73 deletions
|
@ -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 ();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue