From: Flavio Date: Wed, 26 Jan 2011 00:09:30 +0000 (+0100) Subject: Channels! X-Git-Tag: 1.4~38 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=a9c9cbc53ba0a8923a0189db69abab18d362304f;p=minitube Channels! --- diff --git a/minitube.pro b/minitube.pro index 94ac55e..f78cd09 100644 --- a/minitube.pro +++ b/minitube.pro @@ -1,6 +1,6 @@ CONFIG += release TEMPLATE = app -VERSION = 1.3 +VERSION = 1.4 DEFINES += APP_VERSION="$$VERSION" INCLUDEPATH += /usr/include/phonon @@ -36,7 +36,7 @@ HEADERS += src/MainWindow.h \ src/minisplitter.h \ src/loadingwidget.h \ src/videoareawidget.h \ - src/googlesuggest.h \ + src/autocomplete.h \ src/videowidget.h \ src/videodefinition.h \ src/fontutils.h \ @@ -48,7 +48,10 @@ HEADERS += src/MainWindow.h \ src/downloadview.h \ src/downloadmodel.h \ src/downloadlistview.h \ - src/downloadsettings.h + src/downloadsettings.h \ + src/youtubesuggest.h \ + src/suggester.h \ + src/channelsuggest.h SOURCES += src/main.cpp \ src/MainWindow.cpp \ src/SearchView.cpp \ @@ -72,7 +75,7 @@ SOURCES += src/main.cpp \ src/minisplitter.cpp \ src/loadingwidget.cpp \ src/videoareawidget.cpp \ - src/googlesuggest.cpp \ + src/autocomplete.cpp \ src/videowidget.cpp \ src/videodefinition.cpp \ src/constants.cpp \ @@ -85,7 +88,9 @@ SOURCES += src/main.cpp \ src/downloadview.cpp \ src/downloadmodel.cpp \ src/downloadlistview.cpp \ - src/downloadsettings.cpp + src/downloadsettings.cpp \ + src/youtubesuggest.cpp \ + src/channelsuggest.cpp RESOURCES += resources.qrc DESTDIR = build/target/ OBJECTS_DIR = build/obj/ diff --git a/src/ListModel.cpp b/src/ListModel.cpp index 1c146ee..8fff12a 100644 --- a/src/ListModel.cpp +++ b/src/ListModel.cpp @@ -3,6 +3,7 @@ #define MAX_ITEMS 10 static const QString recentKeywordsKey = "recentKeywords"; +static const QString recentChannelsKey = "recentChannels"; ListModel::ListModel(QWidget *parent) : QAbstractListModel(parent) { youtubeSearch = 0; @@ -202,17 +203,32 @@ void ListModel::addVideo(Video* video) { // save keyword QString query = searchParams->keywords(); - if (query.startsWith("http://")) { - // Save the video title - query += "|" + videos.first()->title(); + if (!query.isEmpty()) { + if (query.startsWith("http://")) { + // Save the video title + query += "|" + videos.first()->title(); + } + QSettings settings; + QStringList keywords = settings.value(recentKeywordsKey).toStringList(); + keywords.removeAll(query); + keywords.prepend(query); + while (keywords.size() > 10) + keywords.removeLast(); + settings.setValue(recentKeywordsKey, keywords); } - QSettings settings; - QStringList keywords = settings.value(recentKeywordsKey).toStringList(); - keywords.removeAll(query); - keywords.prepend(query); - while (keywords.size() > 10) - keywords.removeLast(); - settings.setValue(recentKeywordsKey, keywords); + + // save channel + QString channel = searchParams->author(); + if (!channel.isEmpty()) { + QSettings settings; + QStringList channels = settings.value(recentChannelsKey).toStringList(); + channels.removeAll(channel); + channels.prepend(channel); + while (channels.size() > 10) + channels.removeLast(); + settings.setValue(recentChannelsKey, channels); + } + } } diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index d52cbfd..b405a82 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -13,6 +13,7 @@ // #include "local/mac/mac_startup.h" #endif #include "downloadmanager.h" +#include "youtubesuggest.h" MainWindow::MainWindow() : aboutView(0), @@ -28,7 +29,7 @@ MainWindow::MainWindow() : // views searchView = new SearchView(this); - connect(searchView, SIGNAL(search(QString)), this, SLOT(showMedia(QString))); + connect(searchView, SIGNAL(search(SearchParams*)), this, SLOT(showMedia(SearchParams*))); views->addWidget(searchView); mediaView = new MediaView(this); @@ -36,7 +37,8 @@ MainWindow::MainWindow() : toolbarSearch = new SearchLineEdit(this); toolbarSearch->setMinimumWidth(toolbarSearch->fontInfo().pixelSize()*15); - connect(toolbarSearch, SIGNAL(search(const QString&)), searchView, SLOT(watch(const QString&))); + toolbarSearch->setSuggester(new YouTubeSuggest(this)); + connect(toolbarSearch, SIGNAL(search(const QString&)), this, SLOT(startToolbarSearch(const QString&))); // build ui createActions(); @@ -620,9 +622,7 @@ void MainWindow::showSearch() { totalTime->clear(); } -void MainWindow::showMedia(QString query) { - SearchParams *searchParams = new SearchParams(); - searchParams->setKeywords(query); +void MainWindow::showMedia(SearchParams *searchParams) { mediaView->search(searchParams); showWidget(mediaView); } @@ -981,3 +981,19 @@ void MainWindow::toggleDownloads(bool show) { if (show) showWidget(downloadView); else goBack(); } + +void MainWindow::startToolbarSearch(QString query) { + + query = query.trimmed(); + + // check for empty query + if (query.length() == 0) { + return; + } + + SearchParams *searchParams = new SearchParams(); + searchParams->setKeywords(query); + + // go! + showMedia(searchParams); +} diff --git a/src/MainWindow.h b/src/MainWindow.h index 203a214..5034df8 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -31,7 +31,7 @@ private slots: void fadeInWidget(QWidget *oldWidget, QWidget *newWidget); void goBack(); void showSearch(); - void showMedia(QString query); + void showMedia(SearchParams *params); void visitSite(); void donate(); void about(); @@ -63,6 +63,8 @@ private slots: void downloadsFinished(); void toggleDownloads(bool show); + void startToolbarSearch(QString query); + private: void initPhonon(); void createActions(); diff --git a/src/SearchView.cpp b/src/SearchView.cpp index 0e6deb3..ce1cd85 100644 --- a/src/SearchView.cpp +++ b/src/SearchView.cpp @@ -1,12 +1,16 @@ #include "SearchView.h" #include "constants.h" #include "fontutils.h" +#include "searchparams.h" +#include "youtubesuggest.h" +#include "channelsuggest.h" namespace The { QMap* globalActions(); } static const QString recentKeywordsKey = "recentKeywords"; +static const QString recentChannelsKey = "recentChannels"; static const int PADDING = 30; SearchView::SearchView(QWidget *parent) : QWidget(parent) { @@ -77,9 +81,24 @@ SearchView::SearchView(QWidget *parent) : QWidget(parent) { layout->addSpacing(PADDING / 2); - QLabel *tipLabel = new QLabel(tr("Enter a keyword to start watching videos."), this); + QBoxLayout *tipLayout = new QHBoxLayout(); + tipLayout->setSpacing(10); + + QLabel *tipLabel = new QLabel(tr("Enter"), this); + tipLabel->setFont(biggerFont); + tipLayout->addWidget(tipLabel); + + typeCombo = new QComboBox(this); + typeCombo->addItem(tr("a keyword")); + typeCombo->addItem(tr("a channel")); + typeCombo->setFont(biggerFont); + connect(typeCombo, SIGNAL(currentIndexChanged(int)), SLOT(searchTypeChanged(int))); + tipLayout->addWidget(typeCombo); + + tipLabel = new QLabel(tr("to start watching videos."), this); tipLabel->setFont(biggerFont); - layout->addWidget(tipLabel); + tipLayout->addWidget(tipLabel); + layout->addLayout(tipLayout); layout->addSpacing(PADDING / 2); @@ -93,8 +112,12 @@ SearchView::SearchView(QWidget *parent) : QWidget(parent) { queryEdit->setFocus(Qt::OtherFocusReason); connect(queryEdit, SIGNAL(search(const QString&)), this, SLOT(watch(const QString&))); connect(queryEdit, SIGNAL(textChanged(const QString &)), this, SLOT(textChanged(const QString &))); - searchLayout->addWidget(queryEdit); + youtubeSuggest = new YouTubeSuggest(this); + channelSuggest = new ChannelSuggest(this); + searchTypeChanged(0); + + searchLayout->addWidget(queryEdit); searchLayout->addSpacing(10); watchButton = new QPushButton(tr("Watch"), this); @@ -113,7 +136,7 @@ SearchView::SearchView(QWidget *parent) : QWidget(parent) { recentKeywordsLayout = new QVBoxLayout(); recentKeywordsLayout->setSpacing(5); - recentKeywordsLayout->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); + recentKeywordsLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft); recentKeywordsLabel = new QLabel(tr("Recent keywords").toUpper(), this); #if defined(APP_MAC) | defined(APP_WIN) QPalette palette = recentKeywordsLabel->palette(); @@ -128,6 +151,24 @@ SearchView::SearchView(QWidget *parent) : QWidget(parent) { otherLayout->addLayout(recentKeywordsLayout); + // recent channels + recentChannelsLayout = new QVBoxLayout(); + recentChannelsLayout->setSpacing(5); + recentChannelsLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft); + recentChannelsLabel = new QLabel(tr("Recent channels").toUpper(), this); +#if defined(APP_MAC) | defined(APP_WIN) + palette = recentChannelsLabel->palette(); + palette.setColor(QPalette::WindowText, QColor(0x65, 0x71, 0x80)); + recentChannelsLabel->setPalette(palette); +#else + recentChannelsLabel->setForegroundRole(QPalette::Dark); +#endif + recentChannelsLabel->hide(); + recentChannelsLabel->setFont(smallerFont); + recentChannelsLayout->addWidget(recentChannelsLabel); + + otherLayout->addLayout(recentChannelsLayout); + layout->addLayout(otherLayout); mainLayout->addSpacing(PADDING); @@ -179,10 +220,48 @@ void SearchView::updateRecentKeywords() { } +void SearchView::updateRecentChannels() { + + // cleanup + QLayoutItem *item; + while ((item = recentChannelsLayout->takeAt(1)) != 0) { + item->widget()->close(); + delete item; + } + // load + QSettings settings; + QStringList keywords = settings.value(recentChannelsKey).toStringList(); + recentChannelsLabel->setVisible(!keywords.isEmpty()); + // TODO The::globalActions()->value("clearRecentKeywords")->setEnabled(!keywords.isEmpty()); + + foreach (QString keyword, keywords) { + QString link = keyword; + QString display = keyword; + if (keyword.startsWith("http://")) { + int separator = keyword.indexOf("|"); + if (separator > 0 && separator + 1 < keyword.length()) { + link = keyword.left(separator); + display = keyword.mid(separator+1); + } + } + QLabel *itemLabel = new QLabel("" + + display + "", this); + + itemLabel->setMaximumWidth(queryEdit->width() + watchButton->width()); + // itemLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + // Make links navigable with the keyboard too + itemLabel->setTextInteractionFlags(Qt::LinksAccessibleByKeyboard | Qt::LinksAccessibleByMouse); + + connect(itemLabel, SIGNAL(linkActivated(QString)), this, SLOT(watchChannel(QString))); + recentChannelsLayout->addWidget(itemLabel); + } + +} void SearchView::watch() { - QString query = queryEdit->text().simplified(); + QString query = queryEdit->text(); watch(query); } @@ -192,14 +271,47 @@ void SearchView::textChanged(const QString &text) { void SearchView::watch(QString query) { + query = query.simplified(); + // check for empty query if (query.length() == 0) { queryEdit->setFocus(Qt::OtherFocusReason); return; } + SearchParams *searchParams = new SearchParams(); + if (typeCombo->currentIndex() == 0) + searchParams->setKeywords(query); + else { + // remove spaces from channel name + query = query.replace(" ", ""); + searchParams->setAuthor(query); + searchParams->setSortBy(SearchParams::SortByNewest); + } + // go! - emit search(query); + emit search(searchParams); +} + +void SearchView::watchChannel(QString channel) { + + channel = channel.simplified(); + + // check for empty query + if (channel.length() == 0) { + queryEdit->setFocus(Qt::OtherFocusReason); + return; + } + + // remove spaces from channel name + channel = channel.replace(" ", ""); + + SearchParams *searchParams = new SearchParams(); + searchParams->setAuthor(channel); + searchParams->setSortBy(SearchParams::SortByNewest); + + // go! + emit search(searchParams); } void SearchView::checkForUpdate() { @@ -255,3 +367,11 @@ void SearchView::paintEvent(QPaintEvent * /*event*/) { painter.fillRect(0, 0, width(), height(), brush); #endif } + +void SearchView::searchTypeChanged(int index) { + if (index == 0) { + queryEdit->setSuggester(youtubeSuggest); + } else { + queryEdit->setSuggester(channelSuggest); + } +} diff --git a/src/SearchView.h b/src/SearchView.h index c32db4b..dfdfee9 100644 --- a/src/SearchView.h +++ b/src/SearchView.h @@ -6,6 +6,10 @@ #include "searchlineedit.h" #include "updatechecker.h" +class SearchParams; +class YouTubeSuggest; +class ChannelSuggest; + class SearchView : public QWidget, public View { Q_OBJECT @@ -13,9 +17,11 @@ class SearchView : public QWidget, public View { public: SearchView(QWidget *parent); void updateRecentKeywords(); + void updateRecentChannels(); void appear() { updateRecentKeywords(); + updateRecentChannels(); queryEdit->clear(); queryEdit->setFocus(Qt::OtherFocusReason); queryEdit->enableSuggest(); @@ -32,10 +38,11 @@ public: public slots: void watch(QString query); + void watchChannel(QString channel); void gotNewVersion(QString version); signals: - void search(QString query); + void search(SearchParams*); protected: void paintEvent(QPaintEvent *); @@ -43,13 +50,20 @@ protected: private slots: void watch(); void textChanged(const QString &text); + void searchTypeChanged(int index); private: void checkForUpdate(); + YouTubeSuggest *youtubeSuggest; + ChannelSuggest *channelSuggest; + + QComboBox *typeCombo; SearchLineEdit *queryEdit; QLabel *recentKeywordsLabel; - QVBoxLayout *recentKeywordsLayout; + QBoxLayout *recentKeywordsLayout; + QLabel *recentChannelsLabel; + QBoxLayout *recentChannelsLayout; QLabel *message; QPushButton *watchButton; diff --git a/src/autocomplete.cpp b/src/autocomplete.cpp index 656c651..1db03ee 100644 --- a/src/autocomplete.cpp +++ b/src/autocomplete.cpp @@ -1,14 +1,8 @@ -#include "googlesuggest.h" -#include "networkaccess.h" +#include "autocomplete.h" +#include "suggester.h" -#define GSUGGEST_URL "http://suggestqueries.google.com/complete/search?ds=yt&output=toolbar&hl=%1&q=%2" - -namespace The { - NetworkAccess* http(); -} - -GSuggestCompletion::GSuggestCompletion(QWidget *parent, QLineEdit *editor): - QObject(parent), buddy(parent), editor(editor) { +AutoComplete::AutoComplete(QWidget *parent, QLineEdit *editor): + QObject(parent), buddy(parent), editor(editor), suggester(0) { enabled = true; @@ -40,11 +34,11 @@ GSuggestCompletion::GSuggestCompletion(QWidget *parent, QLineEdit *editor): } -GSuggestCompletion::~GSuggestCompletion() { +AutoComplete::~AutoComplete() { delete popup; } -bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) { +bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) { if (obj != popup) return false; @@ -104,7 +98,7 @@ bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) { return false; } -void GSuggestCompletion::showCompletion(const QStringList &choices) { +void AutoComplete::showCompletion(const QStringList &choices) { if (choices.isEmpty()) return; @@ -129,7 +123,7 @@ void GSuggestCompletion::showCompletion(const QStringList &choices) { popup->show(); } -void GSuggestCompletion::doneCompletion() { +void AutoComplete::doneCompletion() { timer->stop(); popup->hide(); editor->setFocus(); @@ -144,19 +138,25 @@ void GSuggestCompletion::doneCompletion() { } } -void GSuggestCompletion::preventSuggest() { +void AutoComplete::preventSuggest() { // qDebug() << "preventSuggest"; timer->stop(); enabled = false; popup->hide(); } -void GSuggestCompletion::enableSuggest() { +void AutoComplete::enableSuggest() { // qDebug() << "enableSuggest"; enabled = true; } -void GSuggestCompletion::autoSuggest() { +void AutoComplete::setSuggester(Suggester* suggester) { + if (this->suggester) this->suggester->disconnect(); + this->suggester = suggester; + connect(suggester, SIGNAL(ready(QStringList)), SLOT(suggestionsReady(QStringList))); +} + +void AutoComplete::autoSuggest() { if (!enabled) return; QString query = editor->text(); @@ -164,38 +164,16 @@ void GSuggestCompletion::autoSuggest() { // qDebug() << "originalText" << originalText; if (query.isEmpty()) return; - QString locale = QLocale::system().name().replace("_", "-"); - // case for system locales such as "C" - if (locale.length() < 2) { - locale = "en-US"; - } - - QString url = QString(GSUGGEST_URL).arg(locale, query); - - QObject *reply = The::http()->get(url); - connect(reply, SIGNAL(data(QByteArray)), SLOT(handleNetworkData(QByteArray))); + if (suggester) + suggester->suggest(query); } -void GSuggestCompletion::handleNetworkData(QByteArray response) { +void AutoComplete::suggestionsReady(QStringList suggestions) { if (!enabled) return; - - QStringList choices; - - QXmlStreamReader xml(response); - while (!xml.atEnd()) { - xml.readNext(); - if (xml.tokenType() == QXmlStreamReader::StartElement) - if (xml.name() == "suggestion") { - QStringRef str = xml.attributes().value("data"); - choices << str.toString(); - } - } - - showCompletion(choices); - + showCompletion(suggestions); } -void GSuggestCompletion::currentItemChanged(QListWidgetItem *current) { +void AutoComplete::currentItemChanged(QListWidgetItem *current) { if (current) { // qDebug() << "current" << current->text(); current->setSelected(true); diff --git a/src/autocomplete.h b/src/autocomplete.h index 9773380..9a6e8b3 100644 --- a/src/autocomplete.h +++ b/src/autocomplete.h @@ -1,24 +1,27 @@ -#ifndef GOOGLESUGGEST_H -#define GOOGLESUGGEST_H +#ifndef SUGGESTCOMPLETION_H +#define SUGGESTCOMPLETION_H #include -class GSuggestCompletion : public QObject { +class Suggester; + +class AutoComplete : public QObject { Q_OBJECT public: - GSuggestCompletion(QWidget *parent, QLineEdit *editor); - ~GSuggestCompletion(); + AutoComplete(QWidget *parent, QLineEdit *editor); + ~AutoComplete(); bool eventFilter(QObject *obj, QEvent *ev); void showCompletion(const QStringList &choices); + void setSuggester(Suggester* suggester); public slots: void doneCompletion(); void preventSuggest(); void enableSuggest(); void autoSuggest(); - void handleNetworkData(QByteArray response); void currentItemChanged(QListWidgetItem *current); + void suggestionsReady(QStringList suggestions); private: QWidget *buddy; @@ -27,7 +30,8 @@ private: QListWidget *popup; QTimer *timer; bool enabled; + Suggester* suggester; }; -#endif // GOOGLESUGGEST_H +#endif // SUGGESTCOMPLETION_H diff --git a/src/searchlineedit.cpp b/src/searchlineedit.cpp index 42c2aee..e63fbd9 100644 --- a/src/searchlineedit.cpp +++ b/src/searchlineedit.cpp @@ -47,7 +47,7 @@ #include #include -#include "googlesuggest.h" +#include "autocomplete.h" ClearButton::ClearButton(QWidget *parent) : QAbstractButton(parent) @@ -180,7 +180,7 @@ m_searchButton(new SearchButton(this)) setSizePolicy(QSizePolicy::Preferred, policy.verticalPolicy()); // completion - completion = new GSuggestCompletion(this, m_lineEdit); + completion = new AutoComplete(this, m_lineEdit); } diff --git a/src/searchlineedit.h b/src/searchlineedit.h index a1d71c4..f56ca80 100644 --- a/src/searchlineedit.h +++ b/src/searchlineedit.h @@ -43,6 +43,7 @@ #define SEARCHLINEEDIT_H #include "urllineedit.h" +#include "autocomplete.h" #include #include @@ -52,7 +53,7 @@ class QMenu; QT_END_NAMESPACE class SearchButton; -class GSuggestCompletion; +class Suggester; /* Clear button on the right hand side of the search widget. @@ -93,6 +94,7 @@ public: void enableSuggest(); void preventSuggest(); void selectAll() { lineEdit()->selectAll(); }; + void setSuggester(Suggester *suggester) { completion->setSuggester(suggester); } protected: void resizeEvent(QResizeEvent *event); @@ -107,7 +109,7 @@ private: SearchButton *m_searchButton; QString m_inactiveText; - GSuggestCompletion *completion; + AutoComplete *completion; }; #endif // SEARCHLINEEDIT_H