blob: 1e21167e21bbf9f3c51036948f262da524d06e2b [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);
Stepan Salenikovich61cbab02015-03-16 18:35:10 -0400106 }
107}
108
109static QModelIndex
110get_index_from_selection(GtkTreeSelection *selection)
111{
112 GtkTreeIter iter;
113 GtkTreeModel *model = NULL;
114
115 if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
116 return gtk_q_sort_filter_tree_model_get_source_idx(GTK_Q_SORT_FILTER_TREE_MODEL(model), &iter);
117 } else {
118 return QModelIndex();
119 }
120}
121
122static void
123move_selected_codec(AccountAudioTab *view, int position_diff)
124{
125 g_return_if_fail(IS_ACCOUNT_AUDIO_TAB(view));
126 AccountAudioTabPrivate *priv = ACCOUNT_AUDIO_TAB_GET_PRIVATE(view);
127
128 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->treeview_codecs));
129 QModelIndex idx = get_index_from_selection(selection);
130
131 if(!idx.isValid())
132 return;
133
134 QMimeData* mime = priv->account->codecModel()->audioCodecs()->mimeData(QModelIndexList() << idx);
135 priv->account->codecModel()->audioCodecs()->dropMimeData(
136 mime,
137 Qt::MoveAction,
138 idx.row() + position_diff,
139 0,
140 QModelIndex());
Stepan Salenikovich61cbab02015-03-16 18:35:10 -0400141
142 /* now make sure to select the same codec which was moved
143 * TODO: UGLY! this should be somehow done in the qt modle bindings,
144 * or via a selection model, not here
145 */
146 int new_row = idx.row() + position_diff;
147 int row_count = priv->account->codecModel()->audioCodecs()->rowCount(idx.parent());
148 if (new_row < 0)
149 new_row = row_count - 1;
150 else if (new_row >= row_count)
151 new_row = 0;
152
153 idx = idx.sibling(new_row, idx.column());
154 GtkTreeIter iter;
155 if (gtk_q_sort_filter_tree_model_source_index_to_iter(
156 GTK_Q_SORT_FILTER_TREE_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_codecs))),
157 idx,
158 &iter)) {
159 gtk_tree_selection_select_iter(selection, &iter);
160 }
161}
162
163static void
164move_codec_up(G_GNUC_UNUSED GtkButton *button, AccountAudioTab *view)
165{
166 move_selected_codec(view, -1);
167}
168
169static void
170move_codec_down(G_GNUC_UNUSED GtkButton *button, AccountAudioTab *view)
171{
172 move_selected_codec(view, +1);
173}
174
175static void
176build_tab_view(AccountAudioTab *view)
177{
178 g_return_if_fail(IS_ACCOUNT_AUDIO_TAB(view));
179 AccountAudioTabPrivate *priv = ACCOUNT_AUDIO_TAB_GET_PRIVATE(view);
180
181 /* codec model */
182 GtkQSortFilterTreeModel *codec_model;
183 GtkCellRenderer *renderer;
184 GtkTreeViewColumn *column;
185
186 codec_model = gtk_q_sort_filter_tree_model_new(
187 priv->account->codecModel()->audioCodecs(),
188 4,
189 Qt::CheckStateRole, G_TYPE_BOOLEAN,
190 CodecModel::Role::NAME, G_TYPE_STRING,
191 CodecModel::Role::BITRATE, G_TYPE_STRING,
192 CodecModel::Role::SAMPLERATE, G_TYPE_STRING);
193 gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_codecs), GTK_TREE_MODEL(codec_model));
194
195 renderer = gtk_cell_renderer_toggle_new();
196 column = gtk_tree_view_column_new_with_attributes("Enabled", renderer, "active", 0, NULL);
197 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
198
199 g_signal_connect(renderer, "toggled", G_CALLBACK(codec_active_toggled), view);
200
201 renderer = gtk_cell_renderer_text_new();
202 column = gtk_tree_view_column_new_with_attributes("Name", renderer, "text", 1, NULL);
203 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
204
205 renderer = gtk_cell_renderer_text_new();
206 column = gtk_tree_view_column_new_with_attributes("Bitrate", renderer, "text", 2, NULL);
207 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
208
209 renderer = gtk_cell_renderer_text_new();
210 column = gtk_tree_view_column_new_with_attributes("Samplerate", renderer, "text", 3, NULL);
211 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_codecs), column);
212
213 /* connect move codecs up/down signals */
214 g_signal_connect(priv->button_moveup, "clicked", G_CALLBACK(move_codec_up), view);
215 g_signal_connect(priv->button_movedown, "clicked", G_CALLBACK(move_codec_down), view);
216}
217
218GtkWidget *
219account_audio_tab_new(Account *account)
220{
221 g_return_val_if_fail(account != NULL, NULL);
222
223 gpointer view = g_object_new(ACCOUNT_AUDIO_TAB_TYPE, NULL);
224
225 AccountAudioTabPrivate *priv = ACCOUNT_AUDIO_TAB_GET_PRIVATE(view);
226 priv->account = account;
227
228 build_tab_view(ACCOUNT_AUDIO_TAB(view));
229
230 return (GtkWidget *)view;
231}