blob: 57dfe4c9cc6a5bc9ecdb7379fa0bb21303b1ff8e [file] [log] [blame]
Stepan Salenikovich61cbab02015-03-16 18:35:10 -04001/*
2 * Copyright (C) 2015 Savoir-Faire Linux Inc.
3 * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Additional permission under GNU GPL version 3 section 7:
20 *
21 * If you modify this program, or any covered work, by linking or
22 * combining it with the OpenSSL project's OpenSSL library (or a
23 * modified version of that library), containing parts covered by the
24 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
25 * grants you additional permission to convey the resulting work.
26 * Corresponding Source for a non-source form of such a combination
27 * shall include the source code for the parts of OpenSSL used as well
28 * as that of the covered work.
29 */
30
31#include "accountvideotab.h"
32
33#include <gtk/gtk.h>
34#include <account.h>
35#include <audio/codecmodel.h>
36#include "models/gtkqsortfiltertreemodel.h"
37
38struct _AccountVideoTab
39{
40 GtkBox parent;
41};
42
43struct _AccountVideoTabClass
44{
45 GtkBoxClass parent_class;
46};
47
48typedef struct _AccountVideoTabPrivate AccountVideoTabPrivate;
49
50struct _AccountVideoTabPrivate
51{
52 Account *account;
53 GtkWidget *treeview_codecs;
54 GtkWidget *checkbutton_enable;
55 GtkWidget *button_moveup;
56 GtkWidget *button_movedown;
57};
58
59G_DEFINE_TYPE_WITH_PRIVATE(AccountVideoTab, account_video_tab, GTK_TYPE_BOX);
60
61#define ACCOUNT_VIDEO_TAB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_VIDEO_TAB_TYPE, AccountVideoTabPrivate))
62
63static void
64account_video_tab_dispose(GObject *object)
65{
66 G_OBJECT_CLASS(account_video_tab_parent_class)->dispose(object);
67}
68
69static void
70account_video_tab_init(AccountVideoTab *view)
71{
72 gtk_widget_init_template(GTK_WIDGET(view));
73}
74
75static void
76account_video_tab_class_init(AccountVideoTabClass *klass)
77{
78 G_OBJECT_CLASS(klass)->dispose = account_video_tab_dispose;
79
80 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
81 "/cx/ring/RingGnome/accountvideotab.ui");
82
83 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountVideoTab, treeview_codecs);
84 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountVideoTab, checkbutton_enable);
85 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountVideoTab, button_moveup);
86 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountVideoTab, button_movedown);
87}
88
89static void
90video_enable(GtkToggleButton *checkbutton, AccountVideoTab *view)
91{
92 g_return_if_fail(IS_ACCOUNT_VIDEO_TAB(view));
93 AccountVideoTabPrivate *priv = ACCOUNT_VIDEO_TAB_GET_PRIVATE(view);
94 priv->account->setVideoEnabled(gtk_toggle_button_get_active(checkbutton));
95}
96
97static void
98codec_active_toggled(GtkCellRendererToggle *renderer, gchar *path, AccountVideoTab *view)
99{
100 g_return_if_fail(IS_ACCOUNT_VIDEO_TAB(view));
101 AccountVideoTabPrivate *priv = ACCOUNT_VIDEO_TAB_GET_PRIVATE(view);
102
103 /* we want to set it to the opposite of the current value */
104 gboolean toggle = !gtk_cell_renderer_toggle_get_active(renderer);
105
106 /* get iter which was clicked */
107 GtkTreePath *tree_path = gtk_tree_path_new_from_string(path);
108 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_codecs));
109 GtkTreeIter iter;
110 gtk_tree_model_get_iter(model, &iter, tree_path);
111
112 /* get qmodelindex from iter and set the model data */
113 QModelIndex idx = gtk_q_sort_filter_tree_model_get_source_idx(GTK_Q_SORT_FILTER_TREE_MODEL(model), &iter);
114 if (idx.isValid()) {
115 priv->account->codecModel()->videoCodecs()->setData(idx, QVariant(toggle), Qt::CheckStateRole);
116 priv->account->codecModel()->save();
117 }
118}
119
120static QModelIndex
121get_index_from_selection(GtkTreeSelection *selection)
122{
123 GtkTreeIter iter;
124 GtkTreeModel *model = NULL;
125
126 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
127 return gtk_q_sort_filter_tree_model_get_source_idx(GTK_Q_SORT_FILTER_TREE_MODEL(model), &iter);
128 } else {
129 return QModelIndex();
130 }
131}
132
133static void
134move_selected_codec(AccountVideoTab *view, int position_diff)
135{
136 g_return_if_fail(IS_ACCOUNT_VIDEO_TAB(view));
137 AccountVideoTabPrivate *priv = ACCOUNT_VIDEO_TAB_GET_PRIVATE(view);
138
139 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview_codecs));
140 QModelIndex idx = get_index_from_selection(selection);
141
142 if(!idx.isValid())
143 return;
144
145 QMimeData* mime = priv->account->codecModel()->videoCodecs()->mimeData(QModelIndexList() << idx);
146 priv->account->codecModel()->videoCodecs()->dropMimeData(
147 mime,
148 Qt::MoveAction,
149 idx.row() + position_diff,
150 0,
151 QModelIndex());
152 priv->account->saveCodecs();
153
154 /* now make sure to select the same codec which was moved
155 * TODO: UGLY! this should be somehow done in the qt modle bindings,
156 * or via a selection model, not here
157 */
158 int new_row = idx.row() + position_diff;
159 int row_count = priv->account->codecModel()->videoCodecs()->rowCount(idx.parent());
160 if (new_row < 0)
161 new_row = row_count - 1;
162 else if (new_row >= row_count)
163 new_row = 0;
164
165 idx = idx.sibling(new_row, idx.column());
166 GtkTreeIter iter;
167 if (gtk_q_sort_filter_tree_model_source_index_to_iter(
168 GTK_Q_SORT_FILTER_TREE_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_codecs))),
169 idx,
170 &iter)) {
171 gtk_tree_selection_select_iter(selection, &iter);
172 }
173}
174
175static void
176move_codec_up(G_GNUC_UNUSED GtkButton *button, AccountVideoTab *view)
177{
178 move_selected_codec(view, -1);
179}
180
181static void
182move_codec_down(G_GNUC_UNUSED GtkButton *button, AccountVideoTab *view)
183{
184 move_selected_codec(view, +1);
185}
186
187static void
188build_tab_view(AccountVideoTab *view)
189{
190 g_return_if_fail(IS_ACCOUNT_VIDEO_TAB(view));
191 AccountVideoTabPrivate *priv = ACCOUNT_VIDEO_TAB_GET_PRIVATE(view);
192
193 /* codec model */
194 GtkQSortFilterTreeModel *codec_model;
195 GtkCellRenderer *renderer;
196 GtkTreeViewColumn *column;
197
198 codec_model = gtk_q_sort_filter_tree_model_new(
199 priv->account->codecModel()->videoCodecs(),
200 3,
201 Qt::CheckStateRole, G_TYPE_BOOLEAN,
202 CodecModel::Role::NAME, G_TYPE_STRING,
203 CodecModel::Role::BITRATE, G_TYPE_STRING);
204 gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_codecs), GTK_TREE_MODEL(codec_model));
205
206 renderer = gtk_cell_renderer_toggle_new();
207 column = gtk_tree_view_column_new_with_attributes("Enabled", renderer, "active", 0, NULL);
208 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
209
210 g_signal_connect(renderer, "toggled", G_CALLBACK(codec_active_toggled), view);
211
212 renderer = gtk_cell_renderer_text_new();
213 column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", 1, NULL);
214 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
215
216 renderer = gtk_cell_renderer_text_new();
217 column = gtk_tree_view_column_new_with_attributes("Bitrate", renderer, "text", 2, NULL);
218 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
219
220 /* enable video checkbutton */
221 gtk_toggle_button_set_active(
222 GTK_TOGGLE_BUTTON(priv->checkbutton_enable), priv->account->isVideoEnabled());
223 g_signal_connect(priv->checkbutton_enable, "toggled", G_CALLBACK(video_enable), view);
224
225 /* connect move codecs up/down signals */
226 g_signal_connect(priv->button_moveup, "clicked", G_CALLBACK(move_codec_up), view);
227 g_signal_connect(priv->button_movedown, "clicked", G_CALLBACK(move_codec_down), view);
228}
229
230GtkWidget *
231account_video_tab_new(Account *account)
232{
233 g_return_val_if_fail(account != NULL, NULL);
234
235 gpointer view = g_object_new(ACCOUNT_VIDEO_TAB_TYPE, NULL);
236
237 AccountVideoTabPrivate *priv = ACCOUNT_VIDEO_TAB_GET_PRIVATE(view);
238 priv->account = account;
239
240 build_tab_view(ACCOUNT_VIDEO_TAB(view));
241
242 return (GtkWidget *)view;
243}