blob: cb3388e380d0c38049c5d6a5ad1fbfbc6f9dc7a2 [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 "accountaudiotab.h"
32
33#include <gtk/gtk.h>
34#include <account.h>
35#include <audio/codecmodel.h>
36#include "models/gtkqsortfiltertreemodel.h"
37
38struct _AccountAudioTab
39{
40 GtkBox parent;
41};
42
43struct _AccountAudioTabClass
44{
45 GtkBoxClass parent_class;
46};
47
48typedef struct _AccountAudioTabPrivate AccountAudioTabPrivate;
49
50struct _AccountAudioTabPrivate
51{
52 Account *account;
53 GtkWidget *treeview_codecs;
54 GtkWidget *button_moveup;
55 GtkWidget *button_movedown;
56};
57
58G_DEFINE_TYPE_WITH_PRIVATE(AccountAudioTab, account_audio_tab, GTK_TYPE_BOX);
59
60#define ACCOUNT_AUDIO_TAB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_AUDIO_TAB_TYPE, AccountAudioTabPrivate))
61
62static void
63account_audio_tab_dispose(GObject *object)
64{
65 G_OBJECT_CLASS(account_audio_tab_parent_class)->dispose(object);
66}
67
68static void
69account_audio_tab_init(AccountAudioTab *view)
70{
71 gtk_widget_init_template(GTK_WIDGET(view));
72}
73
74static void
75account_audio_tab_class_init(AccountAudioTabClass *klass)
76{
77 G_OBJECT_CLASS(klass)->dispose = account_audio_tab_dispose;
78
79 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
80 "/cx/ring/RingGnome/accountaudiotab.ui");
81
82 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAudioTab, treeview_codecs);
83 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAudioTab, button_moveup);
84 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountAudioTab, button_movedown);
85}
86
87static void
88codec_active_toggled(GtkCellRendererToggle *renderer, gchar *path, AccountAudioTab *view)
89{
90 g_return_if_fail(IS_ACCOUNT_AUDIO_TAB(view));
91 AccountAudioTabPrivate *priv = ACCOUNT_AUDIO_TAB_GET_PRIVATE(view);
92
93 /* we want to set it to the opposite of the current value */
94 gboolean toggle = !gtk_cell_renderer_toggle_get_active(renderer);
95
96 /* get iter which was clicked */
97 GtkTreePath *tree_path = gtk_tree_path_new_from_string(path);
98 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_codecs));
99 GtkTreeIter iter;
100 gtk_tree_model_get_iter(model, &iter, tree_path);
101
102 /* get qmodelindex from iter and set the model data */
103 QModelIndex idx = gtk_q_sort_filter_tree_model_get_source_idx(GTK_Q_SORT_FILTER_TREE_MODEL(model), &iter);
104 if (idx.isValid()) {
105 priv->account->codecModel()->audioCodecs()->setData(idx, QVariant(toggle), Qt::CheckStateRole);
106 priv->account->codecModel()->save();
107 }
108}
109
110static QModelIndex
111get_index_from_selection(GtkTreeSelection *selection)
112{
113 GtkTreeIter iter;
114 GtkTreeModel *model = NULL;
115
116 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
117 return gtk_q_sort_filter_tree_model_get_source_idx(GTK_Q_SORT_FILTER_TREE_MODEL(model), &iter);
118 } else {
119 return QModelIndex();
120 }
121}
122
123static void
124move_selected_codec(AccountAudioTab *view, int position_diff)
125{
126 g_return_if_fail(IS_ACCOUNT_AUDIO_TAB(view));
127 AccountAudioTabPrivate *priv = ACCOUNT_AUDIO_TAB_GET_PRIVATE(view);
128
129 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview_codecs));
130 QModelIndex idx = get_index_from_selection(selection);
131
132 if(!idx.isValid())
133 return;
134
135 QMimeData* mime = priv->account->codecModel()->audioCodecs()->mimeData(QModelIndexList() << idx);
136 priv->account->codecModel()->audioCodecs()->dropMimeData(
137 mime,
138 Qt::MoveAction,
139 idx.row() + position_diff,
140 0,
141 QModelIndex());
142 priv->account->saveCodecs();
143
144 /* now make sure to select the same codec which was moved
145 * TODO: UGLY! this should be somehow done in the qt modle bindings,
146 * or via a selection model, not here
147 */
148 int new_row = idx.row() + position_diff;
149 int row_count = priv->account->codecModel()->audioCodecs()->rowCount(idx.parent());
150 if (new_row < 0)
151 new_row = row_count - 1;
152 else if (new_row >= row_count)
153 new_row = 0;
154
155 idx = idx.sibling(new_row, idx.column());
156 GtkTreeIter iter;
157 if (gtk_q_sort_filter_tree_model_source_index_to_iter(
158 GTK_Q_SORT_FILTER_TREE_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_codecs))),
159 idx,
160 &iter)) {
161 gtk_tree_selection_select_iter(selection, &iter);
162 }
163}
164
165static void
166move_codec_up(G_GNUC_UNUSED GtkButton *button, AccountAudioTab *view)
167{
168 move_selected_codec(view, -1);
169}
170
171static void
172move_codec_down(G_GNUC_UNUSED GtkButton *button, AccountAudioTab *view)
173{
174 move_selected_codec(view, +1);
175}
176
177static void
178build_tab_view(AccountAudioTab *view)
179{
180 g_return_if_fail(IS_ACCOUNT_AUDIO_TAB(view));
181 AccountAudioTabPrivate *priv = ACCOUNT_AUDIO_TAB_GET_PRIVATE(view);
182
183 /* codec model */
184 GtkQSortFilterTreeModel *codec_model;
185 GtkCellRenderer *renderer;
186 GtkTreeViewColumn *column;
187
188 codec_model = gtk_q_sort_filter_tree_model_new(
189 priv->account->codecModel()->audioCodecs(),
190 4,
191 Qt::CheckStateRole, G_TYPE_BOOLEAN,
192 CodecModel::Role::NAME, G_TYPE_STRING,
193 CodecModel::Role::BITRATE, G_TYPE_STRING,
194 CodecModel::Role::SAMPLERATE, G_TYPE_STRING);
195 gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_codecs), GTK_TREE_MODEL(codec_model));
196
197 renderer = gtk_cell_renderer_toggle_new();
198 column = gtk_tree_view_column_new_with_attributes("Enabled", renderer, "active", 0, NULL);
199 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
200
201 g_signal_connect(renderer, "toggled", G_CALLBACK(codec_active_toggled), view);
202
203 renderer = gtk_cell_renderer_text_new();
204 column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", 1, NULL);
205 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
206
207 renderer = gtk_cell_renderer_text_new();
208 column = gtk_tree_view_column_new_with_attributes("Bitrate", renderer, "text", 2, NULL);
209 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
210
211 renderer = gtk_cell_renderer_text_new();
212 column = gtk_tree_view_column_new_with_attributes("Samplerate", renderer, "text", 3, NULL);
213 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
214
215 /* connect move codecs up/down signals */
216 g_signal_connect(priv->button_moveup, "clicked", G_CALLBACK(move_codec_up), view);
217 g_signal_connect(priv->button_movedown, "clicked", G_CALLBACK(move_codec_down), view);
218}
219
220GtkWidget *
221account_audio_tab_new(Account *account)
222{
223 g_return_val_if_fail(account != NULL, NULL);
224
225 gpointer view = g_object_new(ACCOUNT_AUDIO_TAB_TYPE, NULL);
226
227 AccountAudioTabPrivate *priv = ACCOUNT_AUDIO_TAB_GET_PRIVATE(view);
228 priv->account = account;
229
230 build_tab_view(ACCOUNT_AUDIO_TAB(view));
231
232 return (GtkWidget *)view;
233}