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