1 #include "SearchView.h"
4 #include "searchparams.h"
5 #include "youtubesuggest.h"
6 #include "channelsuggest.h"
8 #include "searchlineedit_mac.h"
10 #include "searchlineedit.h"
17 QMap<QString, QAction*>* globalActions();
20 static const QString recentKeywordsKey = "recentKeywords";
21 static const QString recentChannelsKey = "recentChannels";
22 static const int PADDING = 30;
24 SearchView::SearchView(QWidget *parent) : QWidget(parent) {
26 QFont biggerFont = FontUtils::big();
27 QFont smallerFont = FontUtils::smallBold();
29 #if defined(APP_MAC) | defined(APP_WIN)
30 // speedup painting since we'll paint the whole background
31 // by ourselves anyway in paintEvent()
32 setAttribute(Qt::WA_OpaquePaintEvent);
35 QBoxLayout *mainLayout = new QVBoxLayout();
36 mainLayout->setMargin(0);
37 mainLayout->setSpacing(0);
39 // hidden message widget
40 message = new QLabel(this);
42 mainLayout->addWidget(message);
45 QLabel *buy = new QLabel(this);
46 buy->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
47 buy->setText(QString("<a style='color:palette(text);text-decoration:none' href='%1'>%2</a>").arg(
48 QString(Constants::WEBSITE) + "#download",
49 tr("Get the full version").toUpper()
51 buy->setOpenExternalLinks(true);
53 buy->setAlignment(Qt::AlignRight);
54 buy->setStyleSheet("QLabel {"
55 "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #CCD6E0, stop: 1 #ADBCCC);"
56 "border-bottom-left-radius: 8px;"
57 "border-bottom-right-radius: 8px;"
61 mainLayout->addWidget(buy, 0, Qt::AlignRight);
64 mainLayout->addStretch();
65 mainLayout->addSpacing(PADDING);
67 QBoxLayout *hLayout = new QHBoxLayout();
68 hLayout->setAlignment(Qt::AlignCenter);
69 mainLayout->addLayout(hLayout);
71 QLabel *logo = new QLabel(this);
72 QString resource = "app";
74 resource = Extra::resourceName(resource);
75 logo->setMaximumSize(128, 128);
76 logo->setScaledContents(true);
78 logo->setPixmap(QPixmap(":/images/" + resource + ".png"));
79 hLayout->addWidget(logo, 0, Qt::AlignTop);
80 hLayout->addSpacing(PADDING);
82 QVBoxLayout *layout = new QVBoxLayout();
83 layout->setAlignment(Qt::AlignCenter);
84 hLayout->addLayout(layout);
86 QLabel *welcomeLabel =
87 new QLabel("<h1 style='font-weight:normal'>" +
88 tr("Welcome to <a href='%1'>%2</a>,")
89 // .replace("<a ", "<a style='color:palette(text)'")
90 .replace("<a href", "<a style='text-decoration:none; color:palette(text); font-weight:bold' href")
91 .arg(Constants::WEBSITE, Constants::NAME)
93 welcomeLabel->setOpenExternalLinks(true);
94 layout->addWidget(welcomeLabel);
96 layout->addSpacing(PADDING / 2);
98 QBoxLayout *tipLayout = new QHBoxLayout();
99 tipLayout->setSpacing(10);
101 //: "Enter", as in "type". The whole frase says: "Enter a keyword to start watching videos"
102 QLabel *tipLabel = new QLabel(tr("Enter"), this);
103 tipLabel->setFont(biggerFont);
104 tipLayout->addWidget(tipLabel);
106 typeCombo = new QComboBox(this);
107 typeCombo->addItem(tr("a keyword"));
108 typeCombo->addItem(tr("a channel"));
109 typeCombo->setFont(biggerFont);
110 connect(typeCombo, SIGNAL(currentIndexChanged(int)), SLOT(searchTypeChanged(int)));
111 tipLayout->addWidget(typeCombo);
113 tipLabel = new QLabel(tr("to start watching videos."), this);
114 tipLabel->setFont(biggerFont);
115 tipLayout->addWidget(tipLabel);
116 layout->addLayout(tipLayout);
118 layout->addSpacing(PADDING / 2);
120 QHBoxLayout *searchLayout = new QHBoxLayout();
121 searchLayout->setAlignment(Qt::AlignVCenter);
123 queryEdit = new SearchLineEdit(this);
124 queryEdit->setFont(biggerFont);
125 queryEdit->setMinimumWidth(queryEdit->fontInfo().pixelSize()*15);
126 connect(queryEdit, SIGNAL(search(const QString&)), SLOT(watch(const QString&)));
127 connect(queryEdit, SIGNAL(textChanged(const QString &)), SLOT(textChanged(const QString &)));
128 connect(queryEdit, SIGNAL(suggestionAccepted(const QString&)), SLOT(watch(const QString&)));
130 youtubeSuggest = new YouTubeSuggest(this);
131 channelSuggest = new ChannelSuggest(this);
132 searchTypeChanged(0);
134 searchLayout->addWidget(queryEdit);
135 searchLayout->addSpacing(10);
137 watchButton = new QPushButton(tr("Watch"), this);
138 watchButton->setDefault(true);
139 watchButton->setEnabled(false);
140 watchButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
141 connect(watchButton, SIGNAL(clicked()), this, SLOT(watch()));
142 searchLayout->addWidget(watchButton);
144 layout->addItem(searchLayout);
146 layout->addSpacing(PADDING / 2);
148 QHBoxLayout *otherLayout = new QHBoxLayout();
149 otherLayout->setMargin(0);
150 otherLayout->setSpacing(10);
152 recentKeywordsLayout = new QVBoxLayout();
153 recentKeywordsLayout->setSpacing(5);
154 recentKeywordsLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
155 recentKeywordsLabel = new QLabel(tr("Recent keywords").toUpper(), this);
156 recentKeywordsLabel->setProperty("recentHeader", true);
157 recentKeywordsLabel->setForegroundRole(QPalette::Dark);
158 recentKeywordsLabel->hide();
159 recentKeywordsLabel->setFont(smallerFont);
160 recentKeywordsLayout->addWidget(recentKeywordsLabel);
162 otherLayout->addLayout(recentKeywordsLayout);
165 recentChannelsLayout = new QVBoxLayout();
166 recentChannelsLayout->setSpacing(5);
167 recentChannelsLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
168 recentChannelsLabel = new QLabel(tr("Recent channels").toUpper(), this);
169 recentChannelsLabel->setProperty("recentHeader", true);
170 recentChannelsLabel->setForegroundRole(QPalette::Dark);
171 recentChannelsLabel->hide();
172 recentChannelsLabel->setFont(smallerFont);
173 recentChannelsLayout->addWidget(recentChannelsLabel);
175 otherLayout->addLayout(recentChannelsLayout);
177 layout->addLayout(otherLayout);
179 mainLayout->addSpacing(PADDING);
180 mainLayout->addStretch();
182 setLayout(mainLayout);
186 void SearchView::appear() {
187 updateRecentKeywords();
188 updateRecentChannels();
189 queryEdit->selectAll();
190 queryEdit->enableSuggest();
191 QTimer::singleShot(0, queryEdit, SLOT(setFocus()));
194 void SearchView::updateRecentKeywords() {
198 while ((item = recentKeywordsLayout->takeAt(1)) != 0) {
199 item->widget()->close();
205 QStringList keywords = settings.value(recentKeywordsKey).toStringList();
206 recentKeywordsLabel->setVisible(!keywords.isEmpty());
207 The::globalActions()->value("clearRecentKeywords")->setEnabled(!keywords.isEmpty());
209 foreach (QString keyword, keywords) {
210 QString link = keyword;
211 QString display = keyword;
212 if (keyword.startsWith("http://") || keyword.startsWith("https://")) {
213 int separator = keyword.indexOf("|");
214 if (separator > 0 && separator + 1 < keyword.length()) {
215 link = keyword.left(separator);
216 display = keyword.mid(separator+1);
219 bool needStatusTip = false;
220 if (display.length() > 24) {
221 display.truncate(24);
222 display.append("...");
223 needStatusTip = true;
225 QLabel *itemLabel = new QLabel("<a href=\"" + link
226 + "\" style=\"color:palette(text); text-decoration:none\">"
227 + display + "</a>", this);
228 itemLabel->setAttribute(Qt::WA_DeleteOnClose);
229 itemLabel->setProperty("recentItem", true);
230 itemLabel->setMaximumWidth(queryEdit->width() + watchButton->width());
231 // itemLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
232 // Make links navigable with the keyboard too
233 itemLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard | Qt::LinksAccessibleByMouse);
235 itemLabel->setStatusTip(link);
236 connect(itemLabel, SIGNAL(linkActivated(QString)), this, SLOT(watchKeywords(QString)));
237 recentKeywordsLayout->addWidget(itemLabel);
242 void SearchView::updateRecentChannels() {
246 while ((item = recentChannelsLayout->takeAt(1)) != 0) {
247 item->widget()->close();
253 QStringList keywords = settings.value(recentChannelsKey).toStringList();
254 recentChannelsLabel->setVisible(!keywords.isEmpty());
255 // TODO The::globalActions()->value("clearRecentKeywords")->setEnabled(!keywords.isEmpty());
257 foreach (QString keyword, keywords) {
258 QString link = keyword;
259 QString display = keyword;
260 if (keyword.startsWith("http://") || keyword.startsWith("https://")) {
261 int separator = keyword.indexOf("|");
262 if (separator > 0 && separator + 1 < keyword.length()) {
263 link = keyword.left(separator);
264 display = keyword.mid(separator+1);
267 QLabel *itemLabel = new QLabel("<a href=\"" + link
268 + "\" style=\"color:palette(text); text-decoration:none\">"
269 + display + "</a>", this);
270 itemLabel->setAttribute(Qt::WA_DeleteOnClose);
271 itemLabel->setProperty("recentItem", true);
272 itemLabel->setMaximumWidth(queryEdit->width() + watchButton->width());
273 // itemLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
274 // Make links navigable with the keyboard too
275 itemLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard | Qt::LinksAccessibleByMouse);
277 connect(itemLabel, SIGNAL(linkActivated(QString)), this, SLOT(watchChannel(QString)));
278 recentChannelsLayout->addWidget(itemLabel);
283 void SearchView::watch() {
284 QString query = queryEdit->text();
288 void SearchView::textChanged(const QString &text) {
289 watchButton->setEnabled(!text.simplified().isEmpty());
292 void SearchView::watch(QString query) {
294 query = query.simplified();
296 // check for empty query
297 if (query.length() == 0) {
298 queryEdit->setFocus(Qt::OtherFocusReason);
302 SearchParams *searchParams = new SearchParams();
303 if (typeCombo->currentIndex() == 0)
304 searchParams->setKeywords(query);
306 // remove spaces from channel name
307 query = query.replace(" ", "");
308 searchParams->setAuthor(query);
309 searchParams->setSortBy(SearchParams::SortByNewest);
313 emit search(searchParams);
316 void SearchView::watchChannel(QString channel) {
318 channel = channel.simplified();
320 // check for empty query
321 if (channel.length() == 0) {
322 queryEdit->setFocus(Qt::OtherFocusReason);
326 // remove spaces from channel name
327 channel = channel.remove(" ");
329 SearchParams *searchParams = new SearchParams();
330 searchParams->setAuthor(channel);
331 searchParams->setSortBy(SearchParams::SortByNewest);
334 emit search(searchParams);
337 void SearchView::watchKeywords(QString query) {
339 query = query.simplified();
341 // check for empty query
342 if (query.length() == 0) {
343 queryEdit->setFocus(Qt::OtherFocusReason);
347 if (typeCombo->currentIndex() == 0) {
348 queryEdit->setText(query);
349 watchButton->setEnabled(true);
352 SearchParams *searchParams = new SearchParams();
353 searchParams->setKeywords(query);
356 emit search(searchParams);
359 void SearchView::paintEvent(QPaintEvent * /*event*/) {
360 #if defined(APP_MAC) | defined(APP_WIN)
362 if (window()->isActiveWindow()) {
363 brush = QBrush(QColor(0xdd, 0xe4, 0xeb));
365 brush = palette().window();
367 QPainter painter(this);
368 painter.fillRect(0, 0, width(), height(), brush);
372 void SearchView::searchTypeChanged(int index) {
374 queryEdit->setSuggester(youtubeSuggest);
376 queryEdit->setSuggester(channelSuggest);
378 queryEdit->selectAll();
379 queryEdit->setFocus();