Parent: [1d3ef3] (diff)

Download this file

cdbrowser.h    308 lines (257 with data), 10.0 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* Copyright (C) 2014-2018 J.F.Dockes
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _CDBROWSER_H_INCLUDED_
#define _CDBROWSER_H_INCLUDED_
#include "libupnpp/config.h"
/** CDBrowser displays Content Directory data inside a DirBrowser Tab */
#include <time.h>
#include <vector>
#include <iostream>
#include <unordered_set>
#include <unordered_map>
#ifdef USING_WEBENGINE
#include <QWebEngineView>
#define QWEBVIEW QWebEngineView
#define QWEBPAGE QWebEnginePage
#define QWEBSETTINGS QWebEngineSettings
#else
#include <QWebView>
#define QWEBVIEW QWebView
#define QWEBPAGE QWebPage
#define QWEBSETTINGS QWebSettings
#endif
#include <QVariant>
#include <QTimer>
#include <QPoint>
#include <QMouseEvent>
#include "libupnpp/control/description.hxx"
#include "libupnpp/control/mediaserver.hxx"
#include "libupnpp/control/cdirectory.hxx"
#include "libupnpp/control/cdircontent.hxx"
#include "HelperStructs/MetaData.h"
#include "HelperStructs/globals.h"
#include "randplayer.h"
class CDBrowseQO;
class RecursiveReaper;
class DirBrowser;
class QProgressDialog;
class ContentDirectoryQO;
class CDBrowser : public QWEBVIEW
{
Q_OBJECT;
public:
CDBrowser(QWidget* parent = 0);
virtual ~CDBrowser();
void setDirBrowser(DirBrowser *db) {m_browsers = db;}
void getSearchCaps(std::set<std::string>& caps) {caps = m_searchcaps;}
void search(const std::string& iss);
// Entry for path inside current server: for going back later
struct CtPathElt {
CtPathElt() {}
CtPathElt(const std::string& id, const std::string& tt,
bool ispl, const std::string ss = std::string())
: objid(id), title(tt), isPlaylist(ispl), searchStr(ss) {}
std::string objid;
std::string title;
bool isPlaylist;
std::string searchStr;
QPoint scrollpos{0,0};
};
// Browse specified container in newly created tab.
// We have no server link yet.
void browseInNewTab(QString UDN, std::vector<CtPathElt> path);
std::string getServerUDN();
const std::vector<CtPathElt>& getcurpath() {
return m_curpath;
}
QPoint scrollpos();
public slots:
virtual void initialPage(bool redisplay = false);
void onBrowseDone(int);
void onSliceAvailable(UPnPClient::UPnPDirContent *);
void onReaperSliceAvailable(UPnPClient::UPnPDirContent *);
void setStyleSheet(bool dark, bool redisplay=true);
void refresh();
void onSysUpdIdChanged(int id);
virtual void appendHtml(const QString&, const QString& html);
virtual void onLinkClicked(const QUrl &);
virtual void createPopupMenu(const QPoint&);
virtual void simpleAdd(QAction *);
virtual void recursiveAdd(QAction *);
virtual void back(QAction *);
virtual void rreaperDone(int);
virtual void onContentsSizeChanged(const QSize&);
#ifdef USING_WEBENGINE
virtual void onPopupJsDone(const QVariant&);
virtual void onJSRan(const QVariant&);
#else
virtual void mouseReleaseEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *e);
#endif
signals:
void sig_tracks_to_playlist(const MetaDataList&);
void sig_tracks_to_randplay(RandPlayer::PlayMode,
const std::vector<UPnPClient::UPnPDirObject>&);
void sig_now_in(QWidget *, const QString&);
void sig_searchcaps_changed();
void sig_browse_in_new_tab(QString UDN,
std::vector<CDBrowser::CtPathElt>);
void sig_rand_stop();
void sig_sort_order();
private:
virtual void processOnLinkClicked(const QUrl &);
bool popupOther(QAction *act);
void initContainerHtml(const std::string& ss = std::string());
void browseContainer(std::string ctid, std::string title, bool ispl,
QPoint scrollpos = QPoint());
void search(const std::string& objid, const std::string& iss,
QPoint scrollpos = QPoint());
void curpathClicked(unsigned int i);
void waitForPage();
void mySetHtml(const QString&);
void doCreatePopupMenu();
void runJS(const QString&);
void updateAlphamap(char& curinitial, const std::string& tt);
void maybeShowAlphamap(unsigned int nct);
QString alphalinks(const std::string& initials);
int serverFromUDN(const std::string& udn);
static const std::string CTTitleStartMarker;
static const std::string plContainerClass;
void init_HTML();
static QString CTToHtml(unsigned int idx,
const UPnPClient::UPnPDirObject& e);
static QString ItemToHtml(unsigned int idx,
const UPnPClient::UPnPDirObject&, int maxartlen);
static QString DSToHtml(unsigned int idx,
const UPnPClient::UPnPDeviceDesc& dev);
static QString initialServersPage();
static QString emptyServersPage();
// This is used to limit our automatic descent further down when a
// container has a unique container entry. To defend against some
// pathological trees
int m_autoclickcnt{0};
// When displaying the servers list, we periodically check the
// server pool state. The last seen Media Server descriptions are
// stored in m_msdescs for diffing with the new ones and deciding
// if we need to redraw. Timer and servers list are only used
// while we are displaying the servers page, the timer is stopped
// as soon as a link is clicked.
QTimer m_timer;
std::vector<UPnPClient::UPnPDeviceDesc> m_msdescs;
// Handle for the currently active media server
std::shared_ptr<ContentDirectoryQO> m_cds;
// Search caps of current server
std::set<std::string> m_searchcaps;
std::vector<CtPathElt> m_curpath;
std::map<char, std::string> m_alphamap;
// Threaded objects to perform directory reads and recursive walks
CDBrowseQO *m_reader;
RecursiveReaper *m_reaper;
void deleteReaders(const QString& from);
bool newCds(int cdsidx);
// Busy dialog for lengthy ops
QProgressDialog *m_progressD;
time_t m_progstart;
// Content of the currently visited container or search
std::vector<UPnPClient::UPnPDirObject> m_entries;
// Scroll position to be restored when we're done reading. This is
// so that the user can scroll while we insert?
QPoint m_savedscrollpos;
// Recursive explore contents, for possible sorting before sending to pl
std::vector<UPnPClient::UPnPDirObject> m_recwalkentries;
// URL hashes for deduplication while walking the tree
std::unordered_set<std::string> m_recwalkdedup;
// Pointer to parent tabbed object for access to shared state (insertActive)
DirBrowser *m_browsers;
// Attributes for the popup menu click:
std::string m_popupobjid;
std::string m_popupobjtitle;
std::string m_popupotype;
int m_popupidx{-1};
bool m_popupispl{false};
QPoint m_popupos;
int m_popupmode; // now, next, at end
#ifdef USING_WEBENGINE
// No use trying to insert stuff before the initial page insert ran
bool m_somethingran{false};
#endif
// Remember last click kind for detecting midclick
Qt::MouseButton m_lastbutton;
// State for init browsing in subdir instead of servers page (middle-click)
QString m_initUDN;
// SystemUpdateID for the connected content directory server
int m_sysUpdId;
};
// A QObject to hold a QString. Maybe there would be a simpler way to
// do this but anyway... We use javascript to append html to the
// window content when new directory entries arrive. We could include
// the html in a javascript statement:
// innerhtml += "html text"
// But then we'd have to escape all the double quotes. Instead we store
// the text inside the QObject text property and make the QObject
// available to javascript. The javascript statement becomes
// innerhtml += newtext.text
class StringObj : public QObject {
Q_OBJECT;
Q_PROPERTY(QString text READ text);
public:
StringObj(const QString& s)
: m_s(s)
{ }
QString text()
{
return m_s;
}
QString m_s;
};
#ifdef USING_WEBENGINE
class CDWebPage: public QWebEnginePage {
Q_OBJECT
public:
CDWebPage(CDBrowser *parent)
: QWebEnginePage((QWidget *)parent), m_browser(parent) {
}
protected:
virtual bool acceptNavigationRequest(const QUrl& url,
NavigationType,
bool) {
m_browser->onLinkClicked(url);
return false;
}
virtual void javaScriptConsoleMessage(
JavaScriptConsoleMessageLevel level,
const QString& msg, int lineNum, const QString & sourceID);
private:
CDBrowser *m_browser;
};
#else // Using Qt Webkit
// We only subclass QWebPage in order to display the JS error messages
class CDWebPage: public QWebPage {
Q_OBJECT;
public:
CDWebPage(QWidget* parent = 0) : QWebPage(parent) {
}
virtual void javaScriptConsoleMessage(const QString& msg, int lineNum,
const QString & sourceID);
};
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#define SCRIPTOWNERSHIP QWebFrame::ScriptOwnership
#else
#define SCRIPTOWNERSHIP QScriptEngine::ScriptOwnership
#endif
#endif
#endif /* _CDBROWSER_H_INCLUDED_ */