Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
savoirfairelinux
jami-client-gnome
Commits
f903d1be
Commit
f903d1be
authored
Mar 25, 2015
by
Stepan Salenikovich
Browse files
gnome: add video settings
Refs #69020 Change-Id: I9c99d96b785fc2c106faab87dea4d4cf9c4f7d0c
parent
12fee941
Changes
10
Hide whitespace changes
Inline
Side-by-side
CMakeLists.txt
View file @
f903d1be
...
...
@@ -179,6 +179,8 @@ SET( SRC_FILES
src/video/xrectsel.c
src/dialogs.h
src/dialogs.c
src/videosettingsview.h
src/videosettingsview.cpp
)
# compile glib resource files to c code
...
...
src/accountview.cpp
View file @
f903d1be
...
...
@@ -389,7 +389,7 @@ account_view_init(AccountView *view)
if
(
gtk_q_tree_model_source_index_to_iter
(
account_model
,
current
,
&
new_iter
))
{
gtk_tree_selection_select_iter
(
selection
,
&
new_iter
);
}
else
{
g_warning
(
"SelectionModel of
Call
Model changed to invalid QModelIndex?"
);
g_warning
(
"SelectionModel of
Account
Model changed to invalid QModelIndex?"
);
}
}
}
...
...
src/models/gtkqsortfiltertreemodel.cpp
View file @
f903d1be
...
...
@@ -310,7 +310,7 @@ gtk_q_sort_filter_tree_model_new(QSortFilterProxyModel *model, size_t n_columns,
retval
->
priv
->
given_model
,
&
QAbstractItemModel
::
rowsInserted
,
[
=
](
const
QModelIndex
&
parent
,
int
first
,
int
last
)
{
for
(
int
row
=
first
;
row
<=
last
;
row
++
)
{
for
(
int
row
=
first
;
row
<=
last
;
++
row
)
{
// g_debug("inserted row %d", row);
GtkTreeIter
*
iter
=
g_new0
(
GtkTreeIter
,
1
);
QModelIndex
idx_given
=
retval
->
priv
->
given_model
->
index
(
row
,
0
,
parent
);
...
...
@@ -331,7 +331,7 @@ gtk_q_sort_filter_tree_model_new(QSortFilterProxyModel *model, size_t n_columns,
G_GNUC_UNUSED
const
QModelIndex
&
destinationParent
,
G_GNUC_UNUSED
int
destinationRow
)
{
/* first remove the row from old location
* then insert them at the new location on the "rowsMoved signal */
for
(
int
row
=
source
Start
;
row
<
=
source
End
;
row
++
)
{
for
(
int
row
=
source
End
;
row
>
=
source
Start
;
--
row
)
{
// g_debug("row about to be moved: %d", row);
QModelIndex
idx_given
=
retval
->
priv
->
given_model
->
index
(
row
,
0
,
sourceParent
);
QModelIndex
idx_original
=
retval
->
priv
->
given_model
->
mapToSource
(
idx_given
);
...
...
@@ -351,7 +351,7 @@ gtk_q_sort_filter_tree_model_new(QSortFilterProxyModel *model, size_t n_columns,
const
QModelIndex
&
destinationParent
,
int
destinationRow
)
{
/* these rows should have been removed in the "rowsAboutToBeMoved" handler
* now insert them in the new location */
for
(
int
row
=
sourceStart
;
row
<=
sourceEnd
;
row
++
)
{
for
(
int
row
=
sourceStart
;
row
<=
sourceEnd
;
++
row
)
{
// g_debug("row moved %d", row);
GtkTreeIter
*
iter_new
=
g_new0
(
GtkTreeIter
,
1
);
QModelIndex
idx_given
=
retval
->
priv
->
given_model
->
index
(
destinationRow
,
0
,
destinationParent
);
...
...
@@ -370,7 +370,7 @@ gtk_q_sort_filter_tree_model_new(QSortFilterProxyModel *model, size_t n_columns,
retval
->
priv
->
given_model
,
&
QAbstractItemModel
::
rowsAboutToBeRemoved
,
[
=
](
const
QModelIndex
&
parent
,
int
first
,
int
last
)
{
for
(
int
row
=
fir
st
;
row
<
=
la
st
;
row
++
)
{
for
(
int
row
=
la
st
;
row
>
=
fir
st
;
--
row
)
{
// g_debug("row about to be deleted %d", row);
QModelIndex
idx_given
=
retval
->
priv
->
given_model
->
index
(
row
,
0
,
parent
);
QModelIndex
idx_original
=
retval
->
priv
->
given_model
->
mapToSource
(
idx_given
);
...
...
@@ -419,6 +419,50 @@ gtk_q_sort_filter_tree_model_new(QSortFilterProxyModel *model, size_t n_columns,
}
);
QObject
::
connect
(
retval
->
priv
->
given_model
,
&
QAbstractItemModel
::
modelAboutToBeReset
,
[
=
]
()
{
// g_debug("model about to be reset");
/* nothing equvivalent eixists in GtkTreeModel, so simply delete all
* rows, and add all rows when the model is reset;
* we must delete the rows in ascending order */
int
row_count
=
retval
->
priv
->
given_model
->
rowCount
();
for
(
int
row
=
row_count
;
row
>
0
;
--
row
)
{
// g_debug("deleting row %d", row -1);
QModelIndex
idx_given
=
retval
->
priv
->
given_model
->
index
(
row
-
1
,
0
);
QModelIndex
idx_original
=
retval
->
priv
->
given_model
->
mapToSource
(
idx_given
);
QModelIndex
idx_access
=
retval
->
priv
->
access_model
->
mapFromSource
(
idx_original
);
GtkTreeIter
iter
;
iter
.
stamp
=
stamp
;
qmodelindex_to_iter
(
idx_access
,
&
iter
);
GtkTreePath
*
path
=
gtk_q_sort_filter_tree_model_get_path
(
GTK_TREE_MODEL
(
retval
),
&
iter
);
gtk_tree_model_row_deleted
(
GTK_TREE_MODEL
(
retval
),
path
);
}
}
);
QObject
::
connect
(
retval
->
priv
->
given_model
,
&
QAbstractItemModel
::
modelReset
,
[
=
]
()
{
// g_debug("model reset");
/* now add all the (new) rows */
int
row_count
=
retval
->
priv
->
given_model
->
rowCount
();
for
(
int
row
=
0
;
row
<
row_count
;
++
row
)
{
// g_debug("adding row %d", row);
GtkTreeIter
*
iter_new
=
g_new0
(
GtkTreeIter
,
1
);
QModelIndex
idx_given
=
retval
->
priv
->
given_model
->
index
(
row
,
0
);
QModelIndex
idx_original
=
retval
->
priv
->
given_model
->
mapToSource
(
idx_given
);
QModelIndex
idx_access
=
retval
->
priv
->
access_model
->
mapFromSource
(
idx_original
);
iter_new
->
stamp
=
stamp
;
qmodelindex_to_iter
(
idx_access
,
iter_new
);
GtkTreePath
*
path_new
=
gtk_q_sort_filter_tree_model_get_path
(
GTK_TREE_MODEL
(
retval
),
iter_new
);
gtk_tree_model_row_inserted
(
GTK_TREE_MODEL
(
retval
),
path_new
,
iter_new
);
}
}
);
return
retval
;
}
...
...
src/models/gtkqtreemodel.cpp
View file @
f903d1be
...
...
@@ -284,12 +284,12 @@ gtk_q_tree_model_new(QAbstractItemModel *model, size_t n_columns, ...)
/* connect signals */
QObject
::
connect
(
model
,
proxy_
model
,
&
QAbstractItemModel
::
rowsInserted
,
[
=
](
const
QModelIndex
&
parent
,
int
first
,
int
last
)
{
for
(
int
row
=
first
;
row
<=
last
;
row
++
)
{
GtkTreeIter
*
iter
=
g_new0
(
GtkTreeIter
,
1
);
QModelIndex
idx
=
retval
->
priv
->
model
->
index
(
row
,
0
,
parent
);
QModelIndex
idx
=
proxy_
model
->
index
(
row
,
0
,
parent
);
iter
->
stamp
=
stamp
;
qmodelindex_to_iter
(
idx
,
iter
);
GtkTreePath
*
path
=
gtk_q_tree_model_get_path
(
GTK_TREE_MODEL
(
retval
),
iter
);
...
...
@@ -299,14 +299,14 @@ gtk_q_tree_model_new(QAbstractItemModel *model, size_t n_columns, ...)
);
QObject
::
connect
(
model
,
proxy_
model
,
&
QAbstractItemModel
::
rowsAboutToBeMoved
,
[
=
](
const
QModelIndex
&
sourceParent
,
int
sourceStart
,
int
sourceEnd
,
G_GNUC_UNUSED
const
QModelIndex
&
destinationParent
,
G_GNUC_UNUSED
int
destinationRow
)
{
/* first remove the row from old location
* then insert them at the new location on the "rowsMoved signal */
for
(
int
row
=
sourceStart
;
row
<=
sourceEnd
;
row
++
)
{
QModelIndex
idx
=
retval
->
priv
->
model
->
index
(
row
,
0
,
sourceParent
);
QModelIndex
idx
=
proxy_
model
->
index
(
row
,
0
,
sourceParent
);
GtkTreeIter
iter_old
;
qmodelindex_to_iter
(
idx
,
&
iter_old
);
GtkTreePath
*
path_old
=
gtk_q_tree_model_get_path
(
GTK_TREE_MODEL
(
retval
),
&
iter_old
);
...
...
@@ -316,7 +316,7 @@ gtk_q_tree_model_new(QAbstractItemModel *model, size_t n_columns, ...)
);
QObject
::
connect
(
model
,
proxy_
model
,
&
QAbstractItemModel
::
rowsMoved
,
[
=
](
G_GNUC_UNUSED
const
QModelIndex
&
sourceParent
,
int
sourceStart
,
int
sourceEnd
,
const
QModelIndex
&
destinationParent
,
int
destinationRow
)
{
...
...
@@ -324,7 +324,7 @@ gtk_q_tree_model_new(QAbstractItemModel *model, size_t n_columns, ...)
* now insert them in the new location */
for
(
int
row
=
sourceStart
;
row
<=
sourceEnd
;
row
++
)
{
GtkTreeIter
*
iter_new
=
g_new0
(
GtkTreeIter
,
1
);
QModelIndex
idx
=
retval
->
priv
->
model
->
index
(
destinationRow
,
0
,
destinationParent
);
QModelIndex
idx
=
proxy_
model
->
index
(
destinationRow
,
0
,
destinationParent
);
iter_new
->
stamp
=
stamp
;
qmodelindex_to_iter
(
idx
,
iter_new
);
GtkTreePath
*
path_new
=
gtk_q_tree_model_get_path
(
GTK_TREE_MODEL
(
retval
),
iter_new
);
...
...
@@ -335,11 +335,13 @@ gtk_q_tree_model_new(QAbstractItemModel *model, size_t n_columns, ...)
);
QObject
::
connect
(
model
,
proxy_
model
,
&
QAbstractItemModel
::
rowsAboutToBeRemoved
,
[
=
](
const
QModelIndex
&
parent
,
int
first
,
int
last
)
{
for
(
int
row
=
first
;
row
<=
last
;
row
++
)
{
QModelIndex
idx
=
retval
->
priv
->
model
->
index
(
row
,
0
,
parent
);
/* go last to first, since the rows are being deleted */
for
(
int
row
=
last
;
row
>=
first
;
--
row
)
{
// g_debug("deleting row: %d", row);
QModelIndex
idx
=
proxy_model
->
index
(
row
,
0
,
parent
);
GtkTreeIter
iter
;
iter
.
stamp
=
stamp
;
qmodelindex_to_iter
(
idx
,
&
iter
);
...
...
@@ -350,7 +352,7 @@ gtk_q_tree_model_new(QAbstractItemModel *model, size_t n_columns, ...)
);
QObject
::
connect
(
model
,
proxy_
model
,
&
QAbstractItemModel
::
dataChanged
,
[
=
](
const
QModelIndex
&
topLeft
,
const
QModelIndex
&
bottomRight
,
G_GNUC_UNUSED
const
QVector
<
int
>
&
roles
=
QVector
<
int
>
())
{
...
...
@@ -378,6 +380,46 @@ gtk_q_tree_model_new(QAbstractItemModel *model, size_t n_columns, ...)
}
);
QObject
::
connect
(
proxy_model
,
&
QAbstractItemModel
::
modelAboutToBeReset
,
[
=
]
()
{
// g_debug("model about to be reset");
/* nothing equvivalent eixists in GtkTreeModel, so simply delete all
* rows, and add all rows when the model is reset;
* we must delete the rows in ascending order */
int
row_count
=
proxy_model
->
rowCount
();
for
(
int
row
=
row_count
;
row
>
0
;
--
row
)
{
// g_debug("deleting row %d", row -1);
QModelIndex
idx
=
proxy_model
->
index
(
row
-
1
,
0
);
GtkTreeIter
iter
;
iter
.
stamp
=
stamp
;
qmodelindex_to_iter
(
idx
,
&
iter
);
GtkTreePath
*
path
=
gtk_q_tree_model_get_path
(
GTK_TREE_MODEL
(
retval
),
&
iter
);
gtk_tree_model_row_deleted
(
GTK_TREE_MODEL
(
retval
),
path
);
}
}
);
QObject
::
connect
(
proxy_model
,
&
QAbstractItemModel
::
modelReset
,
[
=
]
()
{
// g_debug("model reset");
/* now add all the (new) rows */
int
row_count
=
proxy_model
->
rowCount
();
for
(
int
row
=
0
;
row
<
row_count
;
row
++
)
{
// g_debug("adding row %d", row);
GtkTreeIter
*
iter_new
=
g_new0
(
GtkTreeIter
,
1
);
QModelIndex
idx
=
proxy_model
->
index
(
row
,
0
);
iter_new
->
stamp
=
stamp
;
qmodelindex_to_iter
(
idx
,
iter_new
);
GtkTreePath
*
path_new
=
gtk_q_tree_model_get_path
(
GTK_TREE_MODEL
(
retval
),
iter_new
);
gtk_tree_model_row_inserted
(
GTK_TREE_MODEL
(
retval
),
path_new
,
iter_new
);
}
}
);
return
retval
;
}
...
...
src/ringmainwindow.cpp
View file @
f903d1be
...
...
@@ -46,7 +46,8 @@
#include
<accountmodel.h>
#include
<audio/codecmodel.h>
#include
"dialogs.h"
#include
"videosettingsview.h"
#include
<video/previewmanager.h>
#define CALL_VIEW_NAME "calls"
#define GENERAL_SETTINGS_VIEW_NAME "general"
#define AUDIO_SETTINGS_VIEW_NAME "audio"
...
...
@@ -88,6 +89,8 @@ struct _RingMainWindowPrivate
GtkWidget
*
stack_call_view
;
GtkWidget
*
button_placecall
;
GtkWidget
*
account_settings_view
;
GtkWidget
*
video_settings_view
;
GtkWidget
*
last_settings_view
;
GtkWidget
*
radiobutton_audio_settings
;
GtkWidget
*
radiobutton_general_settings
;
GtkWidget
*
radiobutton_video_settings
;
...
...
@@ -402,7 +405,7 @@ settings_clicked(G_GNUC_UNUSED GtkButton *button, RingMainWindow *win)
gtk_widget_show
(
priv
->
hbox_settings
);
gtk_stack_set_transition_type
(
GTK_STACK
(
priv
->
stack_main_view
),
GTK_STACK_TRANSITION_TYPE_SLIDE_UP
);
gtk_stack_set_visible_child
_name
(
GTK_STACK
(
priv
->
stack_main_view
),
ACCOUNT_SETTINGS_VIEW_NAME
);
gtk_stack_set_visible_child
(
GTK_STACK
(
priv
->
stack_main_view
),
priv
->
last_settings_view
);
}
else
{
/* show working dialog in case save operation takes time */
GtkWidget
*
working
=
ring_dialog_working
(
GTK_WIDGET
(
win
),
NULL
);
...
...
@@ -422,6 +425,35 @@ settings_clicked(G_GNUC_UNUSED GtkButton *button, RingMainWindow *win)
gtk_stack_set_transition_type
(
GTK_STACK
(
priv
->
stack_main_view
),
GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN
);
gtk_stack_set_visible_child_name
(
GTK_STACK
(
priv
->
stack_main_view
),
CALL_VIEW_NAME
);
/* make sure video preview is stopped, in case it was started */
Video
::
PreviewManager
::
instance
()
->
stopPreview
();
}
}
static
void
show_video_settings
(
GtkToggleButton
*
navbutton
,
RingMainWindow
*
win
)
{
g_return_if_fail
(
IS_RING_MAIN_WINDOW
(
win
));
RingMainWindowPrivate
*
priv
=
RING_MAIN_WINDOW_GET_PRIVATE
(
win
);
if
(
gtk_toggle_button_get_active
(
navbutton
))
{
gtk_stack_set_transition_type
(
GTK_STACK
(
priv
->
stack_main_view
),
GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT
);
gtk_stack_set_visible_child_name
(
GTK_STACK
(
priv
->
stack_main_view
),
VIDEO_SETTINGS_VIEW_NAME
);
priv
->
last_settings_view
=
priv
->
video_settings_view
;
}
}
static
void
show_account_settings
(
GtkToggleButton
*
navbutton
,
RingMainWindow
*
win
)
{
g_return_if_fail
(
IS_RING_MAIN_WINDOW
(
win
));
RingMainWindowPrivate
*
priv
=
RING_MAIN_WINDOW_GET_PRIVATE
(
win
);
if
(
gtk_toggle_button_get_active
(
navbutton
))
{
gtk_stack_set_transition_type
(
GTK_STACK
(
priv
->
stack_main_view
),
GTK_STACK_TRANSITION_TYPE_SLIDE_RIGHT
);
gtk_stack_set_visible_child_name
(
GTK_STACK
(
priv
->
stack_main_view
),
ACCOUNT_SETTINGS_VIEW_NAME
);
priv
->
last_settings_view
=
priv
->
account_settings_view
;
}
}
...
...
@@ -469,12 +501,20 @@ ring_main_window_init(RingMainWindow *win)
gtk_stack_set_visible_child
(
GTK_STACK
(
priv
->
stack_main_view
),
priv
->
vbox_call_view
);
/* init the settings views */
/* make the setting we will show first the active one */
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
priv
->
radiobutton_account_settings
),
TRUE
);
priv
->
account_settings_view
=
account_view_new
();
gtk_stack_add_named
(
GTK_STACK
(
priv
->
stack_main_view
),
priv
->
account_settings_view
,
ACCOUNT_SETTINGS_VIEW_NAME
);
priv
->
video_settings_view
=
video_settings_view_new
();
gtk_stack_add_named
(
GTK_STACK
(
priv
->
stack_main_view
),
priv
->
video_settings_view
,
VIDEO_SETTINGS_VIEW_NAME
);
/* make the setting we will show first the active one */
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
priv
->
radiobutton_video_settings
),
TRUE
);
priv
->
last_settings_view
=
priv
->
video_settings_view
;
/* connect the settings button signals to switch settings views */
g_signal_connect
(
priv
->
radiobutton_video_settings
,
"toggled"
,
G_CALLBACK
(
show_video_settings
),
win
);
g_signal_connect
(
priv
->
radiobutton_account_settings
,
"toggled"
,
G_CALLBACK
(
show_account_settings
),
win
);
/* call model */
GtkQTreeModel
*
call_model
;
GtkCellRenderer
*
renderer
;
...
...
src/videosettingsview.cpp
0 → 100644
View file @
f903d1be
/*
* Copyright (C) 2015 Savoir-Faire Linux Inc.
* Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#include
"videosettingsview.h"
#include
<gtk/gtk.h>
#include
"models/gtkqtreemodel.h"
#include
"video/video_widget.h"
#include
<video/previewmanager.h>
#include
<video/configurationproxy.h>
#include
<QtCore/QItemSelectionModel>
struct
_VideoSettingsView
{
GtkBox
parent
;
};
struct
_VideoSettingsViewClass
{
GtkBoxClass
parent_class
;
};
typedef
struct
_VideoSettingsViewPrivate
VideoSettingsViewPrivate
;
struct
_VideoSettingsViewPrivate
{
GtkWidget
*
combobox_device
;
GtkWidget
*
combobox_channel
;
GtkWidget
*
combobox_resolution
;
GtkWidget
*
combobox_framerate
;
GtkWidget
*
button_startstop
;
GtkWidget
*
vbox_camera_preview
;
GtkWidget
*
video_widget
;
/* new renderers should be put into the queue for processing by a g_idle
* functions whose id should be saved into renderer_idle_source;
* this way when the CurrentCallView object is destroyed, we do not try
* to process any new renderers by stoping the g_idle function.
*/
guint
renderer_idle_source
;
GAsyncQueue
*
new_renderer_queue
;
QMetaObject
::
Connection
local_renderer_connection
;
QMetaObject
::
Connection
device_selection
;
QMetaObject
::
Connection
channel_selection
;
QMetaObject
::
Connection
resolution_selection
;
QMetaObject
::
Connection
rate_selection
;
};
G_DEFINE_TYPE_WITH_PRIVATE
(
VideoSettingsView
,
video_settings_view
,
GTK_TYPE_BOX
);
#define VIDEO_SETTINGS_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), VIDEO_SETTINGS_VIEW_TYPE, VideoSettingsViewPrivate))
static
void
video_settings_view_dispose
(
GObject
*
object
)
{
VideoSettingsView
*
view
=
VIDEO_SETTINGS_VIEW
(
object
);
VideoSettingsViewPrivate
*
priv
=
VIDEO_SETTINGS_VIEW_GET_PRIVATE
(
view
);
QObject
::
disconnect
(
priv
->
local_renderer_connection
);
QObject
::
disconnect
(
priv
->
device_selection
);
QObject
::
disconnect
(
priv
->
channel_selection
);
QObject
::
disconnect
(
priv
->
resolution_selection
);
QObject
::
disconnect
(
priv
->
rate_selection
);
/* dispose may be called multiple times, make sure
* not to call g_source_remove more than once */
if
(
priv
->
renderer_idle_source
)
{
g_source_remove
(
priv
->
renderer_idle_source
);
priv
->
renderer_idle_source
=
0
;
}
if
(
priv
->
new_renderer_queue
)
{
g_async_queue_unref
(
priv
->
new_renderer_queue
);
priv
->
new_renderer_queue
=
NULL
;
}
G_OBJECT_CLASS
(
video_settings_view_parent_class
)
->
dispose
(
object
);
}
static
void
preview_toggled
(
GtkToggleButton
*
togglebutton
,
G_GNUC_UNUSED
gpointer
user_data
)
{
if
(
gtk_toggle_button_get_active
(
togglebutton
))
{
Video
::
PreviewManager
::
instance
()
->
startPreview
();
gtk_button_set_label
(
GTK_BUTTON
(
togglebutton
),
"stop"
);
}
else
{
Video
::
PreviewManager
::
instance
()
->
stopPreview
();
gtk_button_set_label
(
GTK_BUTTON
(
togglebutton
),
"start"
);
}
}
static
void
push_new_renderer
(
VideoSettingsView
*
self
,
Video
::
Renderer
*
renderer
,
VideoRendererType
type
)
{
g_return_if_fail
(
IS_VIDEO_SETTINGS_VIEW
(
self
));
VideoSettingsViewPrivate
*
priv
=
VIDEO_SETTINGS_VIEW_GET_PRIVATE
(
self
);
VideoRenderer
*
new_video_renderer
=
g_new0
(
VideoRenderer
,
1
);
new_video_renderer
->
renderer
=
renderer
;
new_video_renderer
->
type
=
type
;
g_async_queue_push
(
priv
->
new_renderer_queue
,
new_video_renderer
);
}
static
gboolean
check_renderer_queue
(
VideoSettingsView
*
self
)
{
g_return_val_if_fail
(
IS_VIDEO_SETTINGS_VIEW
(
self
),
FALSE
);
VideoSettingsViewPrivate
*
priv
=
VIDEO_SETTINGS_VIEW_GET_PRIVATE
(
self
);
/* get all the renderers in the queue */
gpointer
new_video_renderer
=
g_async_queue_try_pop
(
priv
->
new_renderer_queue
);
while
(
new_video_renderer
)
{
video_widget_add_renderer
(
VIDEO_WIDGET
(
priv
->
video_widget
),
(
const
VideoRenderer
*
)
new_video_renderer
);
g_free
(
new_video_renderer
);
new_video_renderer
=
g_async_queue_try_pop
(
priv
->
new_renderer_queue
);
}
return
G_SOURCE_CONTINUE
;
}
static
QModelIndex
get_index_from_combobox
(
GtkComboBox
*
box
)
{
GtkTreeIter
iter
;
GtkTreeModel
*
model
=
gtk_combo_box_get_model
(
box
);
if
(
gtk_combo_box_get_active_iter
(
box
,
&
iter
))
{
return
gtk_q_tree_model_get_source_idx
(
GTK_Q_TREE_MODEL
(
model
),
&
iter
);
}
else
{
return
QModelIndex
();
}
}
static
void
update_selection
(
GtkComboBox
*
box
,
QItemSelectionModel
*
selection_model
)
{
QModelIndex
idx
=
get_index_from_combobox
(
box
);
if
(
idx
.
isValid
())
selection_model
->
setCurrentIndex
(
idx
,
QItemSelectionModel
::
ClearAndSelect
);
}
static
QMetaObject
::
Connection
connect_combo_box_qmodel
(
GtkComboBox
*
box
,
QAbstractItemModel
*
qmodel
,
QItemSelectionModel
*
selection_model
)
{
QMetaObject
::
Connection
connection
;
GtkCellRenderer
*
renderer
;
GtkQTreeModel
*
model
=
gtk_q_tree_model_new
(
qmodel
,
1
,
Qt
::
DisplayRole
,
G_TYPE_STRING
);
gtk_combo_box_set_model
(
box
,
GTK_TREE_MODEL
(
model
));
renderer
=
gtk_cell_renderer_text_new
();
gtk_cell_layout_pack_start
(
GTK_CELL_LAYOUT
(
box
),
renderer
,
FALSE
);
gtk_cell_layout_set_attributes
(
GTK_CELL_LAYOUT
(
box
),
renderer
,
"text"
,
0
,
NULL
);
/* connect signals to and from the selection model */
connection
=
QObject
::
connect
(
selection_model
,
&
QItemSelectionModel
::
currentChanged
,
[
=
](
const
QModelIndex
&
current
,
G_GNUC_UNUSED
const
QModelIndex
&
previous
)
{
/* select the current */
if
(
current
.
isValid
())
{
GtkTreeIter
new_iter
;
GtkTreeModel
*
model
=
gtk_combo_box_get_model
(
box
);
g_return_if_fail
(
model
!=
NULL
);
if
(
gtk_q_tree_model_source_index_to_iter
(
GTK_Q_TREE_MODEL
(
model
),
current
,
&
new_iter
))
{
gtk_combo_box_set_active_iter
(
box
,
&
new_iter
);
}
else
{
g_warning
(
"SelectionModel changed to invalid QModelIndex?"
);
}
}
}
);
g_signal_connect
(
box
,
"changed"
,
G_CALLBACK
(
update_selection
),
selection_model
);
/* sync the initial selection */
QModelIndex
idx
=
selection_model
->
currentIndex
();
if
(
idx
.
isValid
())
{
GtkTreeIter
iter
;
if
(
gtk_q_tree_model_source_index_to_iter
(
model
,
idx
,
&
iter
))
gtk_combo_box_set_active_iter
(
box
,
&
iter
);
}
return
connection
;
}
static
void
video_settings_view_init
(
VideoSettingsView
*
view
)
{
gtk_widget_init_template
(
GTK_WIDGET
(
view
));
VideoSettingsViewPrivate
*
priv
=
VIDEO_SETTINGS_VIEW_GET_PRIVATE
(
view
);
/* put video widget in */
priv
->
video_widget
=
video_widget_new
();
gtk_widget_show_all
(
priv
->
video_widget
);
gtk_box_pack_start
(
GTK_BOX
(
priv
->
vbox_camera_preview
),
priv
->
video_widget
,
TRUE
,
TRUE
,
0
);
/* if preview is already started, toggle start/stop button */
if
(
Video
::
PreviewManager
::
instance
()
->
isPreviewing
())
{
gtk_button_set_label
(
GTK_BUTTON
(
priv
->
button_startstop
),
"stop"
);
gtk_toggle_button_set_active
(
GTK_TOGGLE_BUTTON
(
priv
->
button_startstop
),
TRUE
);
}
g_signal_connect
(
priv
->
button_startstop
,
"toggled"
,
G_CALLBACK
(
preview_toggled
),
NULL
);
/* init new renderer queue */
priv
->
new_renderer_queue
=
g_async_queue_new_full
((
GDestroyNotify
)
g_free
);
/* check new render queue when idle */
priv
->
renderer_idle_source
=
g_idle_add_full
(
G_PRIORITY_DEFAULT_IDLE
,
(
GSourceFunc
)
check_renderer_queue
,
view
,
NULL
);
/* local renderer, but set as "remote" so that it takes up the whole screen */
/* check to see if the renderere is running first */
if
(
Video
::
PreviewManager
::
instance
()
->
isPreviewing
())
push_new_renderer
(
view
,
Video
::
PreviewManager
::
instance
()
->
previewRenderer
(),
VIDEO_RENDERER_REMOTE
);
priv
->
local_renderer_connection
=
QObject
::
connect
(
Video
::
PreviewManager
::
instance
(),
&
Video
::
PreviewManager
::
previewStarted
,
[
=
](
Video
::
Renderer
*
renderer
)
{
push_new_renderer
(
view
,
renderer
,
VIDEO_RENDERER_REMOTE
);
}
);
priv
->
device_selection
=
connect_combo_box_qmodel
(
GTK_COMBO_BOX
(
priv
->
combobox_device
),
Video
::
ConfigurationProxy
::
deviceModel
(),
Video
::
ConfigurationProxy
::
deviceSelectionModel
());
priv
->
channel_selection
=
connect_combo_box_qmodel
(
GTK_COMBO_BOX
(
priv
->
combobox_channel
),
Video
::
ConfigurationProxy
::
channelModel
(),
Video
::
ConfigurationProxy
::
channelSelectionModel
());
priv
->
resolution_selection
=
connect_combo_box_qmodel
(
GTK_COMBO_BOX
(
priv
->
combobox_resolution
),
Video
::
ConfigurationProxy
::
resolutionModel
(),
Video
::
ConfigurationProxy
::
resolutionSelectionModel
());
priv
->
rate_selection
=
connect_combo_box_qmodel
(
GTK_COMBO_BOX
(
priv
->
combobox_framerate
),
Video
::
ConfigurationProxy
::
rateModel
(),
Video
::
ConfigurationProxy
::
rateSelectionModel
());
}
static
void
video_settings_view_class_init
(
VideoSettingsViewClass
*
klass
)
{
G_OBJECT_CLASS
(
klass
)
->
dispose
=
video_settings_view_dispose
;
gtk_widget_class_set_template_from_resource
(
GTK_WIDGET_CLASS
(
klass
),
"/cx/ring/RingGnome/videosettingsview.ui"
);
gtk_widget_class_bind_template_child_private
(
GTK_WIDGET_CLASS
(
klass
),
VideoSettingsView
,
combobox_device
);
gtk_widget_class_bind_template_child_private
(
GTK_WIDGET_CLASS
(
klass
),
VideoSettingsView
,
combobox_channel
);
gtk_widget_class_bind_template_child_private
(
GTK_WIDGET_CLASS
(
klass
),
VideoSettingsView
,
combobox_resolution
);
gtk_widget_class_bind_template_child_private
(
GTK_WIDGET_CLASS
(
klass
),
VideoSettingsView
,
combobox_framerate
);
gtk_widget_class_bind_template_child_private
(
GTK_WIDGET_CLASS
(
klass
),
VideoSettingsView
,
button_startstop
);
gtk_widget_class_bind_template_child_private
(
GTK_WIDGET_CLASS
(
klass
),
VideoSettingsView
,
vbox_camera_preview
);
}
GtkWidget
*
video_settings_view_new
()
{
gpointer
view
=
g_object_new
(
VIDEO_SETTINGS_VIEW_TYPE
,
NULL
);