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;
|
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 ()
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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) {
|
|
||||||
|
if (backupCounter == 0) {
|
||||||
|
if (optionsWindow) {
|
||||||
BackupList * backupList = optionsWindow->getBackupList();
|
BackupList * backupList = optionsWindow->getBackupList();
|
||||||
if (backupList) {
|
if (backupList) {
|
||||||
backupList->updateSilently();
|
backupList->updateSilently();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (searchWindow) {
|
||||||
|
searchWindow->onTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,6 +89,8 @@ SearchWindow :: SearchWindow (Ptr<GLiveSupport>::Ref gLiveSupport,
|
||||||
WidgetConstants::searchWindowTitleImage,
|
WidgetConstants::searchWindowTitleImage,
|
||||||
windowOpenerButton)
|
windowOpenerButton)
|
||||||
{
|
{
|
||||||
|
Gtk::Box * searchWhereBox = constructSearchWhereBox();
|
||||||
|
|
||||||
Gtk::Box * simpleSearchView = constructSimpleSearchView();
|
Gtk::Box * simpleSearchView = constructSimpleSearchView();
|
||||||
Gtk::Box * advancedSearchView = constructAdvancedSearchView();
|
Gtk::Box * advancedSearchView = constructAdvancedSearchView();
|
||||||
Gtk::Box * browseView = constructBrowseView();
|
Gtk::Box * browseView = constructBrowseView();
|
||||||
|
@ -95,20 +110,17 @@ SearchWindow :: SearchWindow (Ptr<GLiveSupport>::Ref gLiveSupport,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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(*searchWhereBox, Gtk::PACK_SHRINK);
|
||||||
bigBox->pack_start(*searchInput, Gtk::PACK_SHRINK);
|
bigBox->pack_start(*searchInput, Gtk::PACK_SHRINK);
|
||||||
bigBox->pack_start(*searchResults);
|
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,23 +289,30 @@ 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(
|
||||||
|
*getResourceUstring("typeColumnLabel"),
|
||||||
modelColumns.typeColumn, 20);
|
modelColumns.typeColumn, 20);
|
||||||
searchResults->appendColumn(*getResourceUstring("titleColumnLabel"),
|
searchResultsTreeView->appendColumn(
|
||||||
|
*getResourceUstring("titleColumnLabel"),
|
||||||
modelColumns.titleColumn, 360);
|
modelColumns.titleColumn, 360);
|
||||||
searchResults->appendColumn(*getResourceUstring("creatorColumnLabel"),
|
searchResultsTreeView->appendColumn(
|
||||||
|
*getResourceUstring("creatorColumnLabel"),
|
||||||
modelColumns.creatorColumn, 260);
|
modelColumns.creatorColumn, 260);
|
||||||
searchResults->appendColumn(*getResourceUstring("lengthColumnLabel"),
|
searchResultsTreeView->appendColumn(
|
||||||
|
*getResourceUstring("lengthColumnLabel"),
|
||||||
modelColumns.lengthColumn, 50);
|
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;
|
||||||
|
@ -255,9 +320,10 @@ SearchWindow :: constructSearchResultsView(void) throw ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -358,10 +448,25 @@ SearchWindow :: onSearch(Ptr<SearchCriteria>::Ref criteria)
|
||||||
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 )) {
|
||||||
|
@ -432,6 +657,7 @@ SearchWindow :: onEntryClicked (GdkEventButton * event) throw ()
|
||||||
Ptr<Playable>::Ref playable =
|
Ptr<Playable>::Ref playable =
|
||||||
(*iter)[modelColumns.playableColumn];
|
(*iter)[modelColumns.playableColumn];
|
||||||
|
|
||||||
|
if (playable) {
|
||||||
switch (playable->getType()) {
|
switch (playable->getType()) {
|
||||||
case Playable::AudioClipType:
|
case Playable::AudioClipType:
|
||||||
contextMenu->popup(event->button, event->time);
|
contextMenu->popup(event->button, event->time);
|
||||||
|
@ -448,6 +674,7 @@ SearchWindow :: onEntryClicked (GdkEventButton * event) throw ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
|
@ -457,13 +684,16 @@ 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];
|
||||||
|
if (playable) {
|
||||||
gLiveSupport->addToScratchpad(playable);
|
gLiveSupport->addToScratchpad(playable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
|
@ -473,14 +703,17 @@ 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];
|
||||||
|
if (playable) {
|
||||||
gLiveSupport->addToLiveMode(playable);
|
gLiveSupport->addToLiveMode(playable);
|
||||||
gLiveSupport->addToScratchpad(playable);
|
gLiveSupport->addToScratchpad(playable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
|
@ -490,11 +723,13 @@ 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];
|
||||||
|
if (playable) {
|
||||||
Ptr<Playlist>::Ref playlist = playable->getPlaylist();
|
Ptr<Playlist>::Ref playlist = playable->getPlaylist();
|
||||||
if (playlist) {
|
if (playlist) {
|
||||||
exportPlaylistWindow.reset(new ExportPlaylistWindow(
|
exportPlaylistWindow.reset(new ExportPlaylistWindow(
|
||||||
|
@ -506,6 +741,7 @@ SearchWindow :: onExportPlaylist(void) throw ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------------
|
/*------------------------------------------------------------------------------
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,10 +174,52 @@ 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,14 +316,24 @@ 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.
|
||||||
|
@ -273,6 +341,17 @@ class SearchWindow : public GuiWindow
|
||||||
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 */
|
||||||
|
|
|
@ -185,6 +185,10 @@ root: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" }
|
||||||
browseTab:string { "Browse" }
|
browseTab:string { "Browse" }
|
||||||
|
@ -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 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue