]> git.sur5r.net Git - minitube/blob - src/searchview.cpp
Updated spanish translation
[minitube] / src / searchview.cpp
1 #include "searchview.h"
2 #include "constants.h"
3 #include "fontutils.h"
4 #include "searchparams.h"
5 #include "ytsuggester.h"
6 #include "channelsuggest.h"
7 #ifdef APP_MAC
8 #include "searchlineedit_mac.h"
9 #else
10 #include "searchlineedit.h"
11 #endif
12 #ifndef Q_WS_X11
13 #include "extra.h"
14 #endif
15 #ifdef APP_ACTIVATION
16 #include "activation.h"
17 #endif
18 #include "mainwindow.h"
19
20 namespace The {
21 QHash<QString, QAction*>* globalActions();
22 }
23
24 static const QString recentKeywordsKey = "recentKeywords";
25 static const QString recentChannelsKey = "recentChannels";
26 static const int PADDING = 30;
27
28 SearchView::SearchView(QWidget *parent) : QWidget(parent) {
29
30     QFont biggerFont = FontUtils::big();
31     QFont smallerFont = FontUtils::smallBold();
32
33 #if defined(APP_MAC) | defined(APP_WIN)
34     // speedup painting since we'll paint the whole background
35     // by ourselves anyway in paintEvent()
36     setAttribute(Qt::WA_OpaquePaintEvent);
37 #endif
38
39     QBoxLayout *mainLayout = new QVBoxLayout();
40     mainLayout->setMargin(PADDING);
41     mainLayout->setSpacing(0);
42
43     // hidden message widget
44     message = new QLabel(this);
45     message->hide();
46     mainLayout->addWidget(message);
47
48     mainLayout->addStretch();
49     mainLayout->addSpacing(PADDING);
50
51     QBoxLayout *hLayout = new QHBoxLayout();
52     hLayout->setAlignment(Qt::AlignCenter);
53     mainLayout->addLayout(hLayout);
54
55     QLabel *logo = new QLabel(this);
56     logo->setPixmap(QPixmap(":/images/app.png"));
57     hLayout->addWidget(logo, 0, Qt::AlignTop);
58     hLayout->addSpacing(PADDING);
59
60     QVBoxLayout *layout = new QVBoxLayout();
61     layout->setAlignment(Qt::AlignCenter);
62     hLayout->addLayout(layout);
63
64     QLabel *welcomeLabel =
65             new QLabel("<h1 style='font-weight:normal'>" +
66                        tr("Welcome to <a href='%1'>%2</a>,")
67                        // .replace("<a ", "<a style='color:palette(text)'")
68                        .replace("<a href", "<a style='text-decoration:none; color:palette(text); font-weight:bold' href")
69                        .arg(Constants::WEBSITE, Constants::NAME)
70                        + "</h1>", this);
71     welcomeLabel->setOpenExternalLinks(true);
72     layout->addWidget(welcomeLabel);
73
74     layout->addSpacing(PADDING / 2);
75
76     QBoxLayout *tipLayout = new QHBoxLayout();
77     tipLayout->setSpacing(10);
78
79     //: "Enter", as in "type". The whole phrase says: "Enter a keyword to start watching videos"
80     QLabel *tipLabel = new QLabel(tr("Enter"), this);
81     tipLabel->setFont(biggerFont);
82     tipLayout->addWidget(tipLabel);
83
84     typeCombo = new QComboBox(this);
85     typeCombo->addItem(tr("a keyword"));
86     typeCombo->addItem(tr("a channel"));
87     typeCombo->setFont(biggerFont);
88     connect(typeCombo, SIGNAL(currentIndexChanged(int)), SLOT(searchTypeChanged(int)));
89     tipLayout->addWidget(typeCombo);
90
91     tipLabel = new QLabel(tr("to start watching videos."), this);
92     tipLabel->setFont(biggerFont);
93     tipLayout->addWidget(tipLabel);
94     layout->addLayout(tipLayout);
95
96     layout->addSpacing(PADDING / 2);
97
98     QHBoxLayout *searchLayout = new QHBoxLayout();
99     searchLayout->setAlignment(Qt::AlignVCenter);
100
101     queryEdit = new SearchLineEdit(this);
102     queryEdit->setFont(biggerFont);
103     queryEdit->setMinimumWidth(queryEdit->fontInfo().pixelSize()*15);
104     connect(queryEdit, SIGNAL(search(const QString&)), SLOT(watch(const QString&)));
105     connect(queryEdit, SIGNAL(textChanged(const QString &)), SLOT(textChanged(const QString &)));
106     connect(queryEdit, SIGNAL(suggestionAccepted(const QString&)), SLOT(watch(const QString&)));
107
108     youtubeSuggest = new YTSuggester(this);
109     channelSuggest = new ChannelSuggest(this);
110     searchTypeChanged(0);
111
112     searchLayout->addWidget(queryEdit);
113     searchLayout->addSpacing(10);
114
115     watchButton = new QPushButton(tr("Watch"), this);
116     watchButton->setDefault(true);
117     watchButton->setEnabled(false);
118     watchButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
119     connect(watchButton, SIGNAL(clicked()), this, SLOT(watch()));
120     searchLayout->addWidget(watchButton);
121
122     layout->addItem(searchLayout);
123
124     layout->addSpacing(PADDING / 2);
125
126     QHBoxLayout *otherLayout = new QHBoxLayout();
127     otherLayout->setMargin(0);
128     otherLayout->setSpacing(10);
129
130     recentKeywordsLayout = new QVBoxLayout();
131     recentKeywordsLayout->setSpacing(5);
132     recentKeywordsLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
133     recentKeywordsLabel = new QLabel(tr("Recent keywords").toUpper(), this);
134     recentKeywordsLabel->setProperty("recentHeader", true);
135     recentKeywordsLabel->setForegroundRole(QPalette::Dark);
136     recentKeywordsLabel->hide();
137     recentKeywordsLabel->setFont(smallerFont);
138     recentKeywordsLayout->addWidget(recentKeywordsLabel);
139
140     otherLayout->addLayout(recentKeywordsLayout);
141
142     // recent channels
143     recentChannelsLayout = new QVBoxLayout();
144     recentChannelsLayout->setSpacing(5);
145     recentChannelsLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
146     recentChannelsLabel = new QLabel(tr("Recent channels").toUpper(), this);
147     recentChannelsLabel->setProperty("recentHeader", true);
148     recentChannelsLabel->setForegroundRole(QPalette::Dark);
149     recentChannelsLabel->hide();
150     recentChannelsLabel->setFont(smallerFont);
151     recentChannelsLayout->addWidget(recentChannelsLabel);
152
153     otherLayout->addLayout(recentChannelsLayout);
154
155     layout->addLayout(otherLayout);
156
157     mainLayout->addSpacing(PADDING);
158     mainLayout->addStretch();
159
160 #ifdef APP_ACTIVATION
161     if (!Activation::instance().isActivated())
162         mainLayout->addWidget(Extra::buyButton(tr("Get the full version")), 0, Qt::AlignRight);
163 #endif
164
165     setLayout(mainLayout);
166
167 }
168
169 void SearchView::appear() {
170     updateRecentKeywords();
171     updateRecentChannels();
172     queryEdit->selectAll();
173     queryEdit->enableSuggest();
174     QTimer::singleShot(0, queryEdit, SLOT(setFocus()));
175 }
176
177 void SearchView::updateRecentKeywords() {
178
179     // cleanup
180     QLayoutItem *item;
181     while ((item = recentKeywordsLayout->takeAt(1)) != 0) {
182         item->widget()->close();
183         delete item;
184     }
185
186     // load
187     QSettings settings;
188     QStringList keywords = settings.value(recentKeywordsKey).toStringList();
189     recentKeywordsLabel->setVisible(!keywords.isEmpty());
190     The::globalActions()->value("clearRecentKeywords")->setEnabled(!keywords.isEmpty());
191
192     foreach (QString keyword, keywords) {
193         QString link = keyword;
194         QString display = keyword;
195         if (keyword.startsWith("http://") || keyword.startsWith("https://")) {
196             int separator = keyword.indexOf("|");
197             if (separator > 0 && separator + 1 < keyword.length()) {
198                 link = keyword.left(separator);
199                 display = keyword.mid(separator+1);
200             }
201         }
202         bool needStatusTip = false;
203         if (display.length() > 24) {
204             display.truncate(24);
205             display.append("...");
206             needStatusTip = true;
207         }
208         QLabel *itemLabel = new QLabel("<a href=\"" + link
209                                        + "\" style=\"color:palette(text); text-decoration:none\">"
210                                        + display + "</a>", this);
211         itemLabel->setAttribute(Qt::WA_DeleteOnClose);
212         itemLabel->setProperty("recentItem", true);
213         itemLabel->setMaximumWidth(queryEdit->width() + watchButton->width());
214         // itemLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
215         // Make links navigable with the keyboard too
216         itemLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard | Qt::LinksAccessibleByMouse);
217         if (needStatusTip)
218             itemLabel->setStatusTip(link);
219         connect(itemLabel, SIGNAL(linkActivated(QString)), this, SLOT(watchKeywords(QString)));
220         recentKeywordsLayout->addWidget(itemLabel);
221     }
222
223 }
224
225 void SearchView::updateRecentChannels() {
226
227     // cleanup
228     QLayoutItem *item;
229     while ((item = recentChannelsLayout->takeAt(1)) != 0) {
230         item->widget()->close();
231         delete item;
232     }
233
234     // load
235     QSettings settings;
236     QStringList keywords = settings.value(recentChannelsKey).toStringList();
237     recentChannelsLabel->setVisible(!keywords.isEmpty());
238     // TODO The::globalActions()->value("clearRecentKeywords")->setEnabled(!keywords.isEmpty());
239
240     foreach (QString keyword, keywords) {
241         QString link = keyword;
242         QString display = keyword;
243         int separator = keyword.indexOf('|');
244         if (separator > 0 && separator + 1 < keyword.length()) {
245             link = keyword.left(separator);
246             display = keyword.mid(separator+1);
247         }
248         QLabel *itemLabel = new QLabel("<a href=\"" + link
249                                        + "\" style=\"color:palette(text); text-decoration:none\">"
250                                        + display + "</a>", this);
251         itemLabel->setAttribute(Qt::WA_DeleteOnClose);
252         itemLabel->setProperty("recentItem", true);
253         itemLabel->setMaximumWidth(queryEdit->width() + watchButton->width());
254         // itemLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
255         // Make links navigable with the keyboard too
256         itemLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard | Qt::LinksAccessibleByMouse);
257
258         connect(itemLabel, SIGNAL(linkActivated(QString)), this, SLOT(watchChannel(QString)));
259         recentChannelsLayout->addWidget(itemLabel);
260     }
261
262 }
263
264 void SearchView::watch() {
265     QString query = queryEdit->text();
266     watch(query);
267 }
268
269 void SearchView::textChanged(const QString &text) {
270     watchButton->setEnabled(!text.simplified().isEmpty());
271 }
272
273 void SearchView::watch(QString query) {
274
275     query = query.simplified();
276
277     // check for empty query
278     if (query.length() == 0) {
279         queryEdit->setFocus(Qt::OtherFocusReason);
280         return;
281     }
282
283     SearchParams *searchParams = new SearchParams();
284     if (typeCombo->currentIndex() == 0)
285         searchParams->setKeywords(query);
286     else {
287         // remove spaces from channel name
288         query = query.replace(" ", "");
289         searchParams->setAuthor(query);
290         searchParams->setSortBy(SearchParams::SortByNewest);
291     }
292
293     // go!
294     emit search(searchParams);
295 }
296
297 void SearchView::watchChannel(QString channel) {
298
299     channel = channel.simplified();
300
301     // check for empty query
302     if (channel.length() == 0) {
303         queryEdit->setFocus(Qt::OtherFocusReason);
304         return;
305     }
306
307     // remove spaces from channel name
308     channel = channel.remove(" ");
309
310     SearchParams *searchParams = new SearchParams();
311     searchParams->setAuthor(channel);
312     searchParams->setSortBy(SearchParams::SortByNewest);
313
314     // go!
315     emit search(searchParams);
316 }
317
318 void SearchView::watchKeywords(QString query) {
319
320     query = query.simplified();
321
322     // check for empty query
323     if (query.length() == 0) {
324         queryEdit->setFocus(Qt::OtherFocusReason);
325         return;
326     }
327
328     if (typeCombo->currentIndex() == 0) {
329         queryEdit->setText(query);
330         watchButton->setEnabled(true);
331     }
332
333     SearchParams *searchParams = new SearchParams();
334     searchParams->setKeywords(query);
335
336     // go!
337     emit search(searchParams);
338 }
339
340 void SearchView::paintEvent(QPaintEvent * /*event*/) {
341     QPainter painter(this);
342
343 #if defined(APP_MAC) | defined(APP_WIN)
344     QBrush brush;
345     if (window()->isActiveWindow()) {
346         brush = QBrush(QColor(0xdd, 0xe4, 0xeb));
347     } else {
348         brush = palette().window();
349     }
350     painter.fillRect(0, 0, width(), height(), brush);
351 #endif
352
353     static QLinearGradient shadow;
354     static const int shadowHeight = 10;
355     if (shadow.stops().count() == 2) {
356         shadow.setFinalStop(0, shadowHeight);
357         const qreal initialOpacity = 96;
358         for (qreal i = 0; i <= 1; i += 1.0/shadowHeight) {
359             qreal opacity = qPow(initialOpacity, (1.0 - i)) - 1;
360             shadow.setColorAt(i, QColor(0x00, 0x00, 0x00, opacity));
361         }
362     }
363     QRect r = rect();
364     painter.fillRect(r.x(), r.y(), r.width(), shadowHeight, QBrush(shadow));
365 }
366
367 void SearchView::searchTypeChanged(int index) {
368     if (index == 0) {
369         queryEdit->setSuggester(youtubeSuggest);
370     } else {
371         queryEdit->setSuggester(channelSuggest);
372     }
373     queryEdit->selectAll();
374     queryEdit->setFocus();
375 }