]> git.sur5r.net Git - minitube/blob - src/channelsview.cpp
Upload 3.9.3-2 to unstable
[minitube] / src / channelsview.cpp
1 #include "channelsview.h"
2 #include "ytuser.h"
3 #include "ytsearch.h"
4 #include "searchparams.h"
5 #include "channelmodel.h"
6 #include "channelsitemdelegate.h"
7 #include "database.h"
8 #include "ytsearch.h"
9 #include "channelaggregator.h"
10 #include "aggregatevideosource.h"
11 #include "painterutils.h"
12 #include "mainwindow.h"
13 #include "utils.h"
14 #ifndef Q_WS_X11
15 #include "extra.h"
16 #endif
17
18 static const char *sortByKey = "subscriptionsSortBy";
19 static const char *showUpdatedKey = "subscriptionsShowUpdated";
20
21 ChannelsView::ChannelsView(QWidget *parent) : QListView(parent),
22     showUpdated(false),
23     sortBy(SortByName) {
24
25     setItemDelegate(new ChannelsItemDelegate(this));
26     setSelectionMode(QAbstractItemView::ExtendedSelection);
27
28     // layout
29     setSpacing(15);
30     setFlow(QListView::LeftToRight);
31     setWrapping(true);
32     setResizeMode(QListView::Adjust);
33     setMovement(QListView::Static);
34     setUniformItemSizes(true);
35
36     // cosmetics
37     setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
38     setFrameShape(QFrame::NoFrame);
39     setAttribute(Qt::WA_MacShowFocusRect, false);
40
41     QPalette p = palette();
42     p.setColor(QPalette::Disabled, QPalette::Base, p.base().color());
43     p.setColor(QPalette::Disabled, QPalette::Text, p.text().color());
44     setPalette(p);
45
46     verticalScrollBar()->setPageStep(3);
47     verticalScrollBar()->setSingleStep(1);
48
49     setMouseTracking(true);
50
51     connect(this, SIGNAL(clicked(const QModelIndex &)),
52             SLOT(itemActivated(const QModelIndex &)));
53     connect(this, SIGNAL(entered(const QModelIndex &)),
54             SLOT(itemEntered(const QModelIndex &)));
55
56     channelsModel = new ChannelsModel(this);
57     setModel(channelsModel);
58     connect(this, SIGNAL(viewportEntered()),
59             channelsModel, SLOT(clearHover()));
60
61     setupActions();
62
63     connect(ChannelAggregator::instance(), SIGNAL(channelChanged(YTUser*)),
64             channelsModel, SLOT(updateChannel(YTUser*)));
65     connect(ChannelAggregator::instance(), SIGNAL(unwatchedCountChanged(int)),
66             SLOT(unwatchedCountChanged(int)));
67
68     unwatchedCountChanged(ChannelAggregator::instance()->getUnwatchedCount());
69 }
70
71 void ChannelsView::setupActions() {
72     QSettings settings;
73
74     markAsWatchedAction = new QAction(
75                 Utils::icon("mark-watched"), tr("Mark all as watched"), this);
76     markAsWatchedAction->setEnabled(false);
77     markAsWatchedAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_W));
78     connect(markAsWatchedAction, SIGNAL(triggered()), SLOT(markAllAsWatched()));
79     statusActions << markAsWatchedAction;
80
81     showUpdated = settings.value(showUpdatedKey, false).toBool();
82     QAction *showUpdatedAction = new QAction(
83                 Utils::icon("show-updated"), tr("Show Updated"), this);
84     showUpdatedAction->setCheckable(true);
85     showUpdatedAction->setChecked(showUpdated);
86     showUpdatedAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_U));
87     connect(showUpdatedAction, SIGNAL(toggled(bool)), SLOT(toggleShowUpdated(bool)));
88     statusActions << showUpdatedAction;
89
90     SortBy sortBy = static_cast<SortBy>(settings.value(sortByKey, SortByName).toInt());
91
92     QMenu *sortMenu = new QMenu(this);
93     QActionGroup *sortGroup = new QActionGroup(this);
94
95     QAction *sortByNameAction = new QAction(tr("Name"), this);
96     sortByNameAction->setActionGroup(sortGroup);
97     sortByNameAction->setCheckable(true);
98     if (sortBy == SortByName) sortByNameAction->setChecked(true);
99     connect(sortByNameAction, SIGNAL(triggered()), SLOT(setSortByName()));
100     sortMenu->addAction(sortByNameAction);
101
102     QAction *sortByUpdatedAction = new QAction(tr("Last Updated"), this);
103     sortByUpdatedAction->setActionGroup(sortGroup);
104     sortByUpdatedAction->setCheckable(true);
105     if (sortBy == SortByUpdated) sortByUpdatedAction->setChecked(true);
106     connect(sortByUpdatedAction, SIGNAL(triggered()), SLOT(setSortByUpdated()));
107     sortMenu->addAction(sortByUpdatedAction);
108
109     QAction *sortByAddedAction = new QAction(tr("Last Added"), this);
110     sortByAddedAction->setActionGroup(sortGroup);
111     sortByAddedAction->setCheckable(true);
112     if (sortBy == SortByAdded) sortByAddedAction->setChecked(true);
113     connect(sortByAddedAction, SIGNAL(triggered()), SLOT(setSortByAdded()));
114     sortMenu->addAction(sortByAddedAction);
115
116     QAction *sortByLastWatched = new QAction(tr("Last Watched"), this);
117     sortByLastWatched->setActionGroup(sortGroup);
118     sortByLastWatched->setCheckable(true);
119     if (sortBy == SortByLastWatched) sortByLastWatched->setChecked(true);
120     connect(sortByLastWatched, SIGNAL(triggered()), SLOT(setSortByLastWatched()));
121     sortMenu->addAction(sortByLastWatched);
122
123     QAction *sortByMostWatched = new QAction(tr("Most Watched"), this);
124     sortByMostWatched->setActionGroup(sortGroup);
125     sortByMostWatched->setCheckable(true);
126     if (sortBy == SortByMostWatched) sortByMostWatched->setChecked(true);
127     connect(sortByMostWatched, SIGNAL(triggered()), SLOT(setSortByMostWatched()));
128     sortMenu->addAction(sortByMostWatched);
129
130     QToolButton *sortButton = new QToolButton(this);
131     sortButton->setText(tr("Sort by"));
132     sortButton->setIcon(Utils::icon("sort"));
133     sortButton->setIconSize(QSize(16, 16));
134     sortButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
135     sortButton->setPopupMode(QToolButton::InstantPopup);
136     sortButton->setMenu(sortMenu);
137     QWidgetAction *widgetAction = new QWidgetAction(this);
138     widgetAction->setDefaultWidget(sortButton);
139     widgetAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_O));
140     statusActions << widgetAction;
141
142     foreach (QAction *action, statusActions)
143         Utils::setupAction(action);
144 }
145
146 void ChannelsView::appear() {
147     updateQuery();
148     foreach (QAction* action, statusActions)
149         MainWindow::instance()->showActionInStatusBar(action, true);
150     setFocus();
151     ChannelAggregator::instance()->run();
152 }
153
154 void ChannelsView::disappear() {
155     foreach (QAction* action, statusActions)
156         MainWindow::instance()->showActionInStatusBar(action, false);
157 }
158
159 void ChannelsView::mouseMoveEvent(QMouseEvent *event) {
160     QListView::mouseMoveEvent(event);
161     const QModelIndex index = indexAt(event->pos());
162     if (index.isValid()) setCursor(Qt::PointingHandCursor);
163     else unsetCursor();
164 }
165
166 void ChannelsView::leaveEvent(QEvent *event) {
167     QListView::leaveEvent(event);
168     channelsModel->clearHover();
169 }
170
171 void ChannelsView::itemEntered(const QModelIndex &index) {
172     // channelsModel->setHoveredRow(index.row());
173 }
174
175 void ChannelsView::itemActivated(const QModelIndex &index) {
176     ChannelsModel::ItemTypes itemType = channelsModel->typeForIndex(index);
177     if (itemType == ChannelsModel::ItemChannel) {
178         YTUser *user = channelsModel->userForIndex(index);
179         SearchParams *params = new SearchParams();
180         params->setAuthor(user->getUserId());
181         params->setSortBy(SearchParams::SortByNewest);
182         params->setTransient(true);
183         YTSearch *videoSource = new YTSearch(params, this);
184         emit activated(videoSource);
185         user->updateWatched();
186     } else if (itemType == ChannelsModel::ItemAggregate) {
187         AggregateVideoSource *videoSource = new AggregateVideoSource(this);
188         videoSource->setName(tr("All Videos"));
189         emit activated(videoSource);
190     } else if (itemType == ChannelsModel::ItemUnwatched) {
191         AggregateVideoSource *videoSource = new AggregateVideoSource(this);
192         videoSource->setName(tr("Unwatched Videos"));
193         videoSource->setUnwatched(true);
194         emit activated(videoSource);
195     }
196 }
197
198 void ChannelsView::paintEvent(QPaintEvent *event) {
199     if (model()->rowCount() < 3) {
200         QString msg;
201         if (!errorMessage.isEmpty())
202             msg = errorMessage;
203         else if (showUpdated)
204             msg = tr("There are no updated subscriptions at this time.");
205         else
206             msg = tr("You have no subscriptions. "
207                      "Use the star symbol to subscribe to channels.");
208         PainterUtils::centeredMessage(msg, viewport());
209     } else QListView::paintEvent(event);
210     PainterUtils::topShadow(viewport());
211 }
212
213 void ChannelsView::toggleShowUpdated(bool enable) {
214     showUpdated = enable;
215     updateQuery(true);
216     QSettings settings;
217     settings.setValue(showUpdatedKey, showUpdated);
218 }
219
220 void ChannelsView::updateQuery(bool transition) {
221     errorMessage.clear();
222     if (!Database::exists()) return;
223
224     QString sql = "select user_id from subscriptions";
225     if (showUpdated)
226         sql += " where notify_count>0";
227
228     switch (sortBy) {
229     case SortByUpdated:
230         sql += " order by updated desc";
231         break;
232     case SortByAdded:
233         sql += " order by added desc";
234         break;
235     case SortByLastWatched:
236         sql += " order by watched desc";
237         break;
238     case SortByMostWatched:
239         sql += " order by views desc";
240         break;
241     default:
242         sql += " order by name collate nocase";
243         break;
244     }
245
246 #ifndef Q_WS_X11
247     if (transition)
248         Extra::fadeInWidget(this, this);
249 #endif
250
251     channelsModel->setQuery(sql, Database::instance().getConnection());
252     if (channelsModel->lastError().isValid()) {
253         qWarning() << channelsModel->lastError().text();
254         errorMessage = channelsModel->lastError().text();
255     }
256 }
257
258 void ChannelsView::setSortBy(SortBy sortBy) {
259     this->sortBy = sortBy;
260     updateQuery(true);
261     QSettings settings;
262     settings.setValue(sortByKey, (int)sortBy);
263 }
264
265 void ChannelsView::markAllAsWatched() {
266     ChannelAggregator::instance()->markAllAsWatched();
267     updateQuery();
268     markAsWatchedAction->setEnabled(false);
269 }
270
271 void ChannelsView::unwatchedCountChanged(int count) {
272     markAsWatchedAction->setEnabled(count > 0);
273     channelsModel->updateUnwatched();
274     updateQuery();
275 }