Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vmj-qt
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kulya
vmj-qt
Commits
ae271926
Commit
ae271926
authored
Feb 11, 2016
by
Dan Pascu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented call transfer
parent
71ffd6d9
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
791 additions
and
13 deletions
+791
-13
contacts.py
blink/contacts.py
+135
-0
mainwindow.py
blink/mainwindow.py
+5
-0
sessions.py
blink/sessions.py
+264
-13
incoming_calltransfer_dialog.ui
resources/incoming_calltransfer_dialog.ui
+387
-0
No files found.
blink/contacts.py
View file @
ae271926
...
...
@@ -3030,6 +3030,8 @@ class ContactDetailModel(QAbstractListModel):
class
ContactListView
(
QListView
):
implements
(
IObserver
)
def
__init__
(
self
,
parent
=
None
):
super
(
ContactListView
,
self
)
.
__init__
(
parent
)
self
.
setItemDelegate
(
ContactDelegate
(
self
))
...
...
@@ -3053,9 +3055,14 @@ class ContactListView(QListView):
self
.
actions
.
send_files
=
QAction
(
"Send File(s)..."
,
self
,
triggered
=
self
.
_AH_SendFiles
)
self
.
actions
.
request_screen
=
QAction
(
"Request Screen"
,
self
,
triggered
=
self
.
_AH_RequestScreen
)
self
.
actions
.
share_my_screen
=
QAction
(
"Share My Screen"
,
self
,
triggered
=
self
.
_AH_ShareMyScreen
)
self
.
actions
.
transfer_call
=
QAction
(
"Transfer Active Call"
,
self
,
triggered
=
self
.
_AH_TransferCall
)
self
.
drop_indicator_index
=
QModelIndex
()
self
.
needs_restore
=
False
self
.
doubleClicked
.
connect
(
self
.
_SH_DoubleClicked
)
# activated is emitted on single click
notification_center
=
NotificationCenter
()
notification_center
.
add_observer
(
self
,
'BlinkSessionDidChangeState'
)
notification_center
.
add_observer
(
self
,
'BlinkSessionDidRemoveStream'
)
notification_center
.
add_observer
(
self
,
'BlinkActiveSessionDidChange'
)
def
selectionChanged
(
self
,
selected
,
deselected
):
super
(
ContactListView
,
self
)
.
selectionChanged
(
selected
,
deselected
)
...
...
@@ -3125,6 +3132,7 @@ class ContactListView(QListView):
menu
.
addAction
(
self
.
actions
.
send_files
)
menu
.
addAction
(
self
.
actions
.
request_screen
)
menu
.
addAction
(
self
.
actions
.
share_my_screen
)
menu
.
addAction
(
self
.
actions
.
transfer_call
)
menu
.
addSeparator
()
menu
.
addAction
(
self
.
actions
.
add_group
)
menu
.
addAction
(
self
.
actions
.
add_contact
)
...
...
@@ -3133,7 +3141,9 @@ class ContactListView(QListView):
menu
.
addAction
(
self
.
actions
.
undo_last_delete
)
self
.
actions
.
undo_last_delete
.
setText
(
undo_delete_text
)
account_manager
=
AccountManager
()
session_manager
=
SessionManager
()
can_call
=
account_manager
.
default_account
is
not
None
and
contact
.
uri
is
not
None
can_transfer
=
contact
.
uri
is
not
None
and
session_manager
.
active_session
is
not
None
and
session_manager
.
active_session
.
state
==
'connected'
self
.
actions
.
start_audio_call
.
setEnabled
(
can_call
)
self
.
actions
.
start_video_call
.
setEnabled
(
can_call
)
self
.
actions
.
start_chat_session
.
setEnabled
(
can_call
)
...
...
@@ -3141,6 +3151,7 @@ class ContactListView(QListView):
self
.
actions
.
send_files
.
setEnabled
(
can_call
)
self
.
actions
.
request_screen
.
setEnabled
(
can_call
)
self
.
actions
.
share_my_screen
.
setEnabled
(
can_call
)
self
.
actions
.
transfer_call
.
setEnabled
(
can_transfer
)
self
.
actions
.
edit_item
.
setEnabled
(
contact
.
editable
)
self
.
actions
.
delete_item
.
setEnabled
(
contact
.
deletable
)
self
.
actions
.
undo_last_delete
.
setEnabled
(
len
(
model
.
deleted_items
)
>
0
)
...
...
@@ -3385,6 +3396,11 @@ class ContactListView(QListView):
session_manager
=
SessionManager
()
session_manager
.
create_session
(
contact
,
contact
.
uri
,
[
StreamDescription
(
'screen-sharing'
,
mode
=
'server'
),
StreamDescription
(
'audio'
)])
def
_AH_TransferCall
(
self
):
contact
=
self
.
selectionModel
()
.
selectedIndexes
()[
0
]
.
data
(
Qt
.
UserRole
)
session_manager
=
SessionManager
()
session_manager
.
active_session
.
transfer
(
contact
.
uri
)
def
_DH_ApplicationXBlinkGroupList
(
self
,
event
,
index
,
rect
,
item
):
model
=
self
.
model
()
groups
=
model
.
items
[
GroupList
]
...
...
@@ -3455,8 +3471,39 @@ class ContactListView(QListView):
session_manager
=
SessionManager
()
session_manager
.
create_session
(
item
,
item
.
uri
,
item
.
preferred_media
.
stream_descriptions
,
connect
=
item
.
preferred_media
.
autoconnect
)
@
run_in_gui_thread
def
handle_notification
(
self
,
notification
):
handler
=
getattr
(
self
,
'_NH_
%
s'
%
notification
.
name
,
Null
)
handler
(
notification
)
def
_NH_BlinkSessionDidChangeState
(
self
,
notification
):
session_manager
=
SessionManager
()
if
notification
.
sender
is
session_manager
.
active_session
and
self
.
context_menu
.
isVisible
():
selected_items
=
[
index
.
data
(
Qt
.
UserRole
)
for
index
in
self
.
selectionModel
()
.
selectedIndexes
()]
if
len
(
selected_items
)
==
1
and
isinstance
(
selected_items
[
0
],
Contact
):
contact
=
selected_items
[
0
]
self
.
actions
.
transfer_call
.
setEnabled
(
contact
.
uri
is
not
None
and
notification
.
sender
.
state
==
'connected'
)
def
_NH_BlinkSessionDidRemoveStream
(
self
,
notification
):
session_manager
=
SessionManager
()
if
notification
.
sender
is
session_manager
.
active_session
and
self
.
context_menu
.
isVisible
():
selected_items
=
[
index
.
data
(
Qt
.
UserRole
)
for
index
in
self
.
selectionModel
()
.
selectedIndexes
()]
if
len
(
selected_items
)
==
1
and
isinstance
(
selected_items
[
0
],
Contact
):
contact
=
selected_items
[
0
]
self
.
actions
.
transfer_call
.
setEnabled
(
contact
.
uri
is
not
None
and
'audio'
in
notification
.
sender
.
streams
)
def
_NH_BlinkActiveSessionDidChange
(
self
,
notification
):
if
self
.
context_menu
.
isVisible
():
selected_items
=
[
index
.
data
(
Qt
.
UserRole
)
for
index
in
self
.
selectionModel
()
.
selectedIndexes
()]
if
len
(
selected_items
)
==
1
and
isinstance
(
selected_items
[
0
],
Contact
):
contact
=
selected_items
[
0
]
active_session
=
notification
.
data
.
active_session
self
.
actions
.
transfer_call
.
setEnabled
(
contact
.
uri
is
not
None
and
active_session
is
not
None
and
active_session
.
state
==
'connected'
)
class
ContactSearchListView
(
QListView
):
implements
(
IObserver
)
def
__init__
(
self
,
parent
=
None
):
super
(
ContactSearchListView
,
self
)
.
__init__
(
parent
)
self
.
setItemDelegate
(
ContactDelegate
(
self
))
...
...
@@ -3478,8 +3525,13 @@ class ContactSearchListView(QListView):
self
.
actions
.
send_files
=
QAction
(
"Send File(s)..."
,
self
,
triggered
=
self
.
_AH_SendFiles
)
self
.
actions
.
request_screen
=
QAction
(
"Request Screen"
,
self
,
triggered
=
self
.
_AH_RequestScreen
)
self
.
actions
.
share_my_screen
=
QAction
(
"Share My Screen"
,
self
,
triggered
=
self
.
_AH_ShareMyScreen
)
self
.
actions
.
transfer_call
=
QAction
(
"Transfer Active Call"
,
self
,
triggered
=
self
.
_AH_TransferCall
)
self
.
drop_indicator_index
=
QModelIndex
()
self
.
doubleClicked
.
connect
(
self
.
_SH_DoubleClicked
)
# activated is emitted on single click
notification_center
=
NotificationCenter
()
notification_center
.
add_observer
(
self
,
'BlinkSessionDidChangeState'
)
notification_center
.
add_observer
(
self
,
'BlinkSessionDidRemoveStream'
)
notification_center
.
add_observer
(
self
,
'BlinkActiveSessionDidChange'
)
def
selectionChanged
(
self
,
selected
,
deselected
):
super
(
ContactSearchListView
,
self
)
.
selectionChanged
(
selected
,
deselected
)
...
...
@@ -3536,13 +3588,16 @@ class ContactSearchListView(QListView):
menu
.
addAction
(
self
.
actions
.
send_files
)
menu
.
addAction
(
self
.
actions
.
request_screen
)
menu
.
addAction
(
self
.
actions
.
share_my_screen
)
menu
.
addAction
(
self
.
actions
.
transfer_call
)
menu
.
addSeparator
()
menu
.
addAction
(
self
.
actions
.
edit_item
)
menu
.
addAction
(
self
.
actions
.
delete_item
)
menu
.
addAction
(
self
.
actions
.
undo_last_delete
)
self
.
actions
.
undo_last_delete
.
setText
(
undo_delete_text
)
account_manager
=
AccountManager
()
session_manager
=
SessionManager
()
can_call
=
account_manager
.
default_account
is
not
None
and
contact
.
uri
is
not
None
can_transfer
=
contact
.
uri
is
not
None
and
session_manager
.
active_session
is
not
None
and
session_manager
.
active_session
.
state
==
'connected'
self
.
actions
.
start_audio_call
.
setEnabled
(
can_call
)
self
.
actions
.
start_video_call
.
setEnabled
(
can_call
)
self
.
actions
.
start_chat_session
.
setEnabled
(
can_call
)
...
...
@@ -3550,6 +3605,7 @@ class ContactSearchListView(QListView):
self
.
actions
.
send_files
.
setEnabled
(
can_call
)
self
.
actions
.
request_screen
.
setEnabled
(
can_call
)
self
.
actions
.
share_my_screen
.
setEnabled
(
can_call
)
self
.
actions
.
transfer_call
.
setEnabled
(
can_transfer
)
self
.
actions
.
edit_item
.
setEnabled
(
contact
.
editable
)
self
.
actions
.
delete_item
.
setEnabled
(
contact
.
deletable
)
self
.
actions
.
undo_last_delete
.
setEnabled
(
len
(
source_model
.
deleted_items
)
>
0
)
...
...
@@ -3730,6 +3786,11 @@ class ContactSearchListView(QListView):
session_manager
=
SessionManager
()
session_manager
.
create_session
(
contact
,
contact
.
uri
,
[
StreamDescription
(
'screen-sharing'
,
mode
=
'server'
),
StreamDescription
(
'audio'
)])
def
_AH_TransferCall
(
self
):
contact
=
self
.
selectionModel
()
.
selectedIndexes
()[
0
]
.
data
(
Qt
.
UserRole
)
session_manager
=
SessionManager
()
session_manager
.
active_session
.
transfer
(
contact
.
uri
)
def
_DH_TextUriList
(
self
,
event
,
index
,
rect
,
item
):
if
index
.
isValid
():
event
.
accept
(
rect
)
...
...
@@ -3746,8 +3807,39 @@ class ContactSearchListView(QListView):
session_manager
=
SessionManager
()
session_manager
.
create_session
(
item
,
item
.
uri
,
item
.
preferred_media
.
stream_descriptions
,
connect
=
item
.
preferred_media
.
autoconnect
)
@
run_in_gui_thread
def
handle_notification
(
self
,
notification
):
handler
=
getattr
(
self
,
'_NH_
%
s'
%
notification
.
name
,
Null
)
handler
(
notification
)
def
_NH_BlinkSessionDidChangeState
(
self
,
notification
):
session_manager
=
SessionManager
()
if
notification
.
sender
is
session_manager
.
active_session
and
self
.
context_menu
.
isVisible
():
selected_items
=
[
index
.
data
(
Qt
.
UserRole
)
for
index
in
self
.
selectionModel
()
.
selectedIndexes
()]
if
len
(
selected_items
)
==
1
and
isinstance
(
selected_items
[
0
],
Contact
):
contact
=
selected_items
[
0
]
self
.
actions
.
transfer_call
.
setEnabled
(
contact
.
uri
is
not
None
and
notification
.
sender
.
state
==
'connected'
)
def
_NH_BlinkSessionDidRemoveStream
(
self
,
notification
):
session_manager
=
SessionManager
()
if
notification
.
sender
is
session_manager
.
active_session
and
self
.
context_menu
.
isVisible
():
selected_items
=
[
index
.
data
(
Qt
.
UserRole
)
for
index
in
self
.
selectionModel
()
.
selectedIndexes
()]
if
len
(
selected_items
)
==
1
and
isinstance
(
selected_items
[
0
],
Contact
):
contact
=
selected_items
[
0
]
self
.
actions
.
transfer_call
.
setEnabled
(
contact
.
uri
is
not
None
and
'audio'
in
notification
.
sender
.
streams
)
def
_NH_BlinkActiveSessionDidChange
(
self
,
notification
):
if
self
.
context_menu
.
isVisible
():
selected_items
=
[
index
.
data
(
Qt
.
UserRole
)
for
index
in
self
.
selectionModel
()
.
selectedIndexes
()]
if
len
(
selected_items
)
==
1
and
isinstance
(
selected_items
[
0
],
Contact
):
contact
=
selected_items
[
0
]
active_session
=
notification
.
data
.
active_session
self
.
actions
.
transfer_call
.
setEnabled
(
contact
.
uri
is
not
None
and
active_session
is
not
None
and
active_session
.
state
==
'connected'
)
class
ContactDetailView
(
QListView
):
implements
(
IObserver
)
def
__init__
(
self
,
contact_list
):
super
(
ContactDetailView
,
self
)
.
__init__
(
contact_list
.
parent
())
palette
=
self
.
palette
()
...
...
@@ -3778,9 +3870,14 @@ class ContactDetailView(QListView):
self
.
actions
.
send_files
=
QAction
(
"Send File(s)..."
,
self
,
triggered
=
self
.
_AH_SendFiles
)
self
.
actions
.
request_screen
=
QAction
(
"Request Screen"
,
self
,
triggered
=
self
.
_AH_RequestScreen
)
self
.
actions
.
share_my_screen
=
QAction
(
"Share My Screen"
,
self
,
triggered
=
self
.
_AH_ShareMyScreen
)
self
.
actions
.
transfer_call
=
QAction
(
"Transfer Active Call"
,
self
,
triggered
=
self
.
_AH_TransferCall
)
self
.
drop_indicator_index
=
QModelIndex
()
self
.
doubleClicked
.
connect
(
self
.
_SH_DoubleClicked
)
# activated is emitted on single click
contact_list
.
installEventFilter
(
self
)
notification_center
=
NotificationCenter
()
notification_center
.
add_observer
(
self
,
'BlinkSessionDidChangeState'
)
notification_center
.
add_observer
(
self
,
'BlinkSessionDidRemoveStream'
)
notification_center
.
add_observer
(
self
,
'BlinkActiveSessionDidChange'
)
def
setModel
(
self
,
model
):
old_model
=
self
.
model
()
or
Null
...
...
@@ -3812,6 +3909,7 @@ class ContactDetailView(QListView):
def
contextMenuEvent
(
self
,
event
):
account_manager
=
AccountManager
()
session_manager
=
SessionManager
()
model
=
self
.
model
()
selected_indexes
=
self
.
selectionModel
()
.
selectedIndexes
()
selected_item
=
selected_indexes
[
0
]
.
data
(
Qt
.
UserRole
)
if
selected_indexes
else
None
...
...
@@ -3825,6 +3923,7 @@ class ContactDetailView(QListView):
menu
.
addAction
(
self
.
actions
.
send_files
)
menu
.
addAction
(
self
.
actions
.
request_screen
)
menu
.
addAction
(
self
.
actions
.
share_my_screen
)
menu
.
addAction
(
self
.
actions
.
transfer_call
)
menu
.
addSeparator
()
if
isinstance
(
selected_item
,
ContactURI
)
and
model
.
contact_detail
.
editable
:
menu
.
addAction
(
self
.
actions
.
make_uri_default
)
...
...
@@ -3832,6 +3931,7 @@ class ContactDetailView(QListView):
menu
.
addAction
(
self
.
actions
.
edit_contact
)
menu
.
addAction
(
self
.
actions
.
delete_contact
)
can_call
=
account_manager
.
default_account
is
not
None
and
contact_has_uris
can_transfer
=
contact_has_uris
and
session_manager
.
active_session
is
not
None
and
session_manager
.
active_session
.
state
==
'connected'
self
.
actions
.
start_audio_call
.
setEnabled
(
can_call
)
self
.
actions
.
start_video_call
.
setEnabled
(
can_call
)
self
.
actions
.
start_chat_session
.
setEnabled
(
can_call
)
...
...
@@ -3839,6 +3939,7 @@ class ContactDetailView(QListView):
self
.
actions
.
send_files
.
setEnabled
(
can_call
)
self
.
actions
.
request_screen
.
setEnabled
(
can_call
)
self
.
actions
.
share_my_screen
.
setEnabled
(
can_call
)
self
.
actions
.
transfer_call
.
setEnabled
(
can_transfer
)
self
.
actions
.
edit_contact
.
setEnabled
(
model
.
contact_detail
.
editable
)
self
.
actions
.
delete_contact
.
setEnabled
(
model
.
contact_detail
.
deletable
)
menu
.
exec_
(
event
.
globalPos
())
...
...
@@ -4004,6 +4105,17 @@ class ContactDetailView(QListView):
session_manager
=
SessionManager
()
session_manager
.
create_session
(
contact
,
selected_uri
,
[
StreamDescription
(
'screen-sharing'
,
mode
=
'server'
),
StreamDescription
(
'audio'
)])
def
_AH_TransferCall
(
self
):
contact
=
self
.
contact_list
.
selectionModel
()
.
selectedIndexes
()[
0
]
.
data
(
Qt
.
UserRole
)
selected_indexes
=
self
.
selectionModel
()
.
selectedIndexes
()
item
=
selected_indexes
[
0
]
.
data
(
Qt
.
UserRole
)
if
selected_indexes
else
None
if
isinstance
(
item
,
ContactURI
):
selected_uri
=
item
.
uri
else
:
selected_uri
=
contact
.
uri
session_manager
=
SessionManager
()
session_manager
.
active_session
.
transfer
(
selected_uri
)
def
_DH_ApplicationXBlinkSession
(
self
,
event
,
index
,
rect
,
item
):
event
.
ignore
(
rect
)
...
...
@@ -4044,6 +4156,29 @@ class ContactDetailView(QListView):
session_manager
=
SessionManager
()
session_manager
.
create_session
(
contact
,
selected_uri
,
contact
.
preferred_media
.
stream_descriptions
,
connect
=
contact
.
preferred_media
.
autoconnect
)
@
run_in_gui_thread
def
handle_notification
(
self
,
notification
):
handler
=
getattr
(
self
,
'_NH_
%
s'
%
notification
.
name
,
Null
)
handler
(
notification
)
def
_NH_BlinkSessionDidChangeState
(
self
,
notification
):
session_manager
=
SessionManager
()
if
notification
.
sender
is
session_manager
.
active_session
and
self
.
context_menu
.
isVisible
():
contact_has_uris
=
self
.
model
()
.
rowCount
()
>
1
self
.
actions
.
transfer_call
.
setEnabled
(
contact_has_uris
and
notification
.
sender
.
state
==
'connected'
)
def
_NH_BlinkSessionDidRemoveStream
(
self
,
notification
):
session_manager
=
SessionManager
()
if
notification
.
sender
is
session_manager
.
active_session
and
self
.
context_menu
.
isVisible
():
contact_has_uris
=
self
.
model
()
.
rowCount
()
>
1
self
.
actions
.
transfer_call
.
setEnabled
(
contact_has_uris
and
'audio'
in
notification
.
sender
.
streams
)
def
_NH_BlinkActiveSessionDidChange
(
self
,
notification
):
if
self
.
context_menu
.
isVisible
():
contact_has_uris
=
self
.
model
()
.
rowCount
()
>
1
active_session
=
notification
.
data
.
active_session
self
.
actions
.
transfer_call
.
setEnabled
(
contact_has_uris
and
active_session
is
not
None
and
active_session
.
state
==
'connected'
)
# The contact editor dialog
#
...
...
blink/mainwindow.py
View file @
ae271926
...
...
@@ -54,6 +54,7 @@ class MainWindow(base_class, ui_class):
notification_center
.
add_observer
(
self
,
name
=
'SIPAccountGotPendingWatcher'
)
notification_center
.
add_observer
(
self
,
name
=
'BlinkSessionNewOutgoing'
)
notification_center
.
add_observer
(
self
,
name
=
'BlinkSessionDidReinitializeForOutgoing'
)
notification_center
.
add_observer
(
self
,
name
=
'BlinkSessionTransferNewOutgoing'
)
notification_center
.
add_observer
(
self
,
name
=
'BlinkFileTransferNewIncoming'
)
notification_center
.
add_observer
(
self
,
name
=
'BlinkFileTransferNewOutgoing'
)
notification_center
.
add_observer
(
self
,
sender
=
AccountManager
())
...
...
@@ -907,6 +908,10 @@ class MainWindow(base_class, ui_class):
def
_NH_BlinkSessionDidReinitializeForOutgoing
(
self
,
notification
):
self
.
search_box
.
clear
()
def
_NH_BlinkSessionTransferNewOutgoing
(
self
,
notification
):
self
.
search_box
.
clear
()
self
.
switch_view_button
.
view
=
SwitchViewButton
.
SessionView
def
_NH_BlinkFileTransferNewIncoming
(
self
,
notification
):
self
.
filetransfer_window
.
show
(
activate
=
QApplication
.
activeWindow
()
is
not
None
)
...
...
blink/sessions.py
View file @
ae271926
...
...
@@ -37,7 +37,7 @@ from sipsimple.configuration.datatypes import Path
from
sipsimple.configuration.settings
import
SIPSimpleSettings
from
sipsimple.core
import
SIPCoreError
,
SIPURI
,
ToHeader
from
sipsimple.lookup
import
DNSLookup
from
sipsimple.session
import
Session
from
sipsimple.session
import
Session
,
IllegalStateError
from
sipsimple.streams
import
MediaStreamRegistry
from
sipsimple.streams.msrp.filetransfer
import
FileSelector
from
sipsimple.streams.msrp.screensharing
import
ExternalVNCServerHandler
,
ExternalVNCViewerHandler
,
ScreenSharingStream
...
...
@@ -470,6 +470,9 @@ class BlinkSession(BlinkSessionBase):
self
.
remote_hold
=
False
self
.
recording
=
False
self
.
transfer_state
=
None
self
.
transfer_direction
=
None
self
.
info
=
SessionInfo
()
self
.
_sibling
=
None
...
...
@@ -655,6 +658,43 @@ class BlinkSession(BlinkSessionBase):
notification_center
.
post_notification
(
'BlinkSessionNewOutgoing'
,
sender
=
self
)
notification_center
.
post_notification
(
'BlinkSessionInfoUpdated'
,
sender
=
self
,
data
=
NotificationData
(
elements
=
{
'session'
,
'media'
,
'statistics'
}))
def
init_transfer
(
self
,
sip_session
,
streams
,
contact
,
contact_uri
,
reinitialize
=
False
):
assert
self
.
state
in
(
None
,
'initialized'
,
'ended'
)
assert
self
.
contact
is
None
or
contact
.
settings
is
self
.
contact
.
settings
notification_center
=
NotificationCenter
()
if
reinitialize
:
notification_center
.
post_notification
(
'BlinkSessionWillReinitialize'
,
sender
=
self
)
self
.
_initialize
(
reinitialize
=
True
)
else
:
self
.
_delete_when_done
=
len
(
streams
)
==
1
and
streams
[
0
]
.
type
==
'audio'
self
.
direction
=
'outgoing'
self
.
sip_session
=
sip_session
self
.
account
=
sip_session
.
account
self
.
contact
=
contact
self
.
contact_uri
=
contact_uri
self
.
uri
=
self
.
_normalize_uri
(
contact_uri
.
uri
)
self
.
stream_descriptions
=
StreamSet
(
StreamDescription
(
stream
.
type
)
for
stream
in
streams
)
self
.
state
=
'initialized'
if
reinitialize
:
notification_center
.
post_notification
(
'BlinkSessionDidReinitializeForOutgoing'
,
sender
=
self
)
else
:
notification_center
.
post_notification
(
'BlinkSessionNewOutgoing'
,
sender
=
self
)
self
.
streams
.
extend
(
streams
)
self
.
info
.
_update
(
self
)
notification_center
.
post_notification
(
'BlinkSessionInfoUpdated'
,
sender
=
self
,
data
=
NotificationData
(
elements
=
{
'session'
,
'media'
,
'statistics'
}))
self
.
state
=
'connecting/dns_lookup'
notification_center
.
post_notification
(
'BlinkSessionWillConnect'
,
sender
=
self
,
data
=
NotificationData
(
sibling
=
None
))
notification_center
.
post_notification
(
'BlinkSessionConnectionProgress'
,
sender
=
self
,
data
=
NotificationData
(
stage
=
'dns_lookup'
))
self
.
stream_descriptions
=
None
self
.
state
=
'connecting'
notification_center
.
post_notification
(
'BlinkSessionConnectionProgress'
,
sender
=
self
,
data
=
NotificationData
(
stage
=
'connecting'
))
def
connect
(
self
):
assert
self
.
direction
==
'outgoing'
and
self
.
state
==
'initialized'
notification_center
=
NotificationCenter
()
...
...
@@ -768,6 +808,15 @@ class BlinkSession(BlinkSessionBase):
self
.
recording
=
False
audio_stream
.
stop_recording
()
def
transfer
(
self
,
contact_uri
,
replaced_session
=
None
):
if
self
.
state
!=
'connected'
:
return
replaced_sip_session
=
None
if
replaced_session
is
None
else
replaced_session
.
sip_session
try
:
self
.
sip_session
.
transfer
(
self
.
_parse_uri
(
contact_uri
.
uri
),
replaced_session
=
replaced_sip_session
)
except
IllegalStateError
:
pass
def
end
(
self
,
delete
=
False
):
if
self
.
state
==
'ending'
:
self
.
_delete_requested
=
delete
...
...
@@ -981,6 +1030,30 @@ class BlinkSession(BlinkSessionBase):
elif
self
.
streams
.
types
.
isdisjoint
({
'audio'
,
'video'
}):
self
.
unhold
()
def
_NH_SIPSessionTransferNewIncoming
(
self
,
notification
):
self
.
transfer_state
=
'active'
self
.
transfer_direction
=
'incoming'
notification
.
center
.
post_notification
(
'BlinkSessionTransferNewIncoming'
,
sender
=
self
,
data
=
notification
.
data
)
def
_NH_SIPSessionTransferNewOutgoing
(
self
,
notification
):
self
.
transfer_state
=
'active'
self
.
transfer_direction
=
'outgoing'
notification
.
center
.
post_notification
(
'BlinkSessionTransferNewOutgoing'
,
sender
=
self
,
data
=
notification
.
data
)
def
_NH_SIPSessionTransferDidStart
(
self
,
notification
):
notification
.
center
.
post_notification
(
'BlinkSessionTransferDidStart'
,
sender
=
self
,
data
=
notification
.
data
)
def
_NH_SIPSessionTransferDidEnd
(
self
,
notification
):
self
.
transfer_state
=
'completed'
notification
.
center
.
post_notification
(
'BlinkSessionTransferDidEnd'
,
sender
=
self
,
data
=
notification
.
data
)
def
_NH_SIPSessionTransferDidFail
(
self
,
notification
):
self
.
transfer_state
=
'failed'
notification
.
center
.
post_notification
(
'BlinkSessionTransferDidFail'
,
sender
=
self
,
data
=
notification
.
data
)
def
_NH_SIPSessionTransferGotProgress
(
self
,
notification
):
notification
.
center
.
post_notification
(
'BlinkSessionTransferGotProgress'
,
sender
=
self
,
data
=
notification
.
data
)
def
_NH_MediaStreamDidStart
(
self
,
notification
):
stream
=
notification
.
sender
audio_stream
=
self
.
streams
.
get
(
'audio'
)
...
...
@@ -1558,7 +1631,7 @@ class DraggedAudioSessionWidget(base_class, ui_class):
if
self
.
in_conference
:
self
.
note_label
.
setText
(
u'Drop outside the conference to detach'
)
else
:
self
.
note_label
.
setText
(
u'
Drop on a session to conference them
'
)
self
.
note_label
.
setText
(
u'
<p><b>Drop</b>: Conference <b>Alt+Drop</b>: Transfer</p>
'
)
def
paintEvent
(
self
,
event
):
painter
=
QPainter
(
self
)
...
...
@@ -1602,6 +1675,9 @@ class AudioSessionItem(object):
self
.
blink_session
=
session
self
.
blink_session
.
items
.
audio
=
self
self
.
status_context
=
None
self
.
__saved_status
=
None
# to store skipped status messages during a context change
self
.
widget
=
Null
self
.
status
=
None
self
.
type
=
'Audio'
...
...
@@ -1676,8 +1752,17 @@ class AudioSessionItem(object):
return
self
.
__dict__
[
'status'
]
def
_set_status
(
self
,
value
):
if
self
.
__dict__
.
get
(
'status'
,
Null
)
==
value
:
old_status
=
self
.
__dict__
.
get
(
'status'
,
Null
)
new_status
=
value
if
old_status
==
new_status
:
return
if
old_status
is
not
None
and
old_status
is
not
Null
:
context
=
None
if
new_status
is
None
else
new_status
.
context
if
self
.
status_context
==
old_status
.
context
!=
context
:
self
.
__saved_status
=
value
# preserve the status that is skipped because of context mismatch
return
elif
old_status
.
context
!=
context
and
context
is
not
None
:
self
.
__saved_status
=
old_status
# preserve the status that was there prior to switching the context
self
.
__dict__
[
'status'
]
=
value
self
.
widget
.
status_label
.
value
=
value
...
...
@@ -1796,7 +1881,8 @@ class AudioSessionItem(object):
def
_reset_status
(
self
,
expected_status
):
if
self
.
status
==
expected_status
:
self
.
status
=
None
self
.
status
=
self
.
__saved_status
self
.
__saved_status
=
None
def
_SH_HangupButtonClicked
(
self
):
self
.
end
()
...
...
@@ -1928,6 +2014,26 @@ class AudioSessionItem(object):
self
.
status
=
Status
(
notification
.
data
.
reason
)
self
.
_cleanup
()
def
_NH_BlinkSessionTransferNewOutgoing
(
self
,
notification
):
if
self
.
blink_session
.
state
==
'connected'
:
self
.
status_context
=
'transfer'
self
.
status
=
Status
(
'Transfer: Trying'
,
context
=
'transfer'
)
def
_NH_BlinkSessionTransferDidEnd
(
self
,
notification
):
if
self
.
blink_session
.
transfer_direction
==
'outgoing'
:
self
.
status
=
Status
(
'Transfer: Succeeded'
,
context
=
'transfer'
)
def
_NH_BlinkSessionTransferDidFail
(
self
,
notification
):
if
self
.
blink_session
.
state
==
'connected'
and
self
.
blink_session
.
transfer_direction
==
'outgoing'
:
reason
=
'Decline'
if
notification
.
data
.
code
==
603
else
notification
.
data
.
reason
self
.
status
=
Status
(
"Transfer: {}"
.
format
(
reason
),
context
=
'transfer'
)
call_later
(
3
,
self
.
_reset_status
,
self
.
status
)
self
.
status_context
=
None
def
_NH_BlinkSessionTransferGotProgress
(
self
,
notification
):
if
self
.
blink_session
.
state
==
'connected'
and
notification
.
data
.
code
<
200
:
# final answers are handled in DidEnd and DiDFail
self
.
status
=
Status
(
"Transfer: {}"
.
format
(
notification
.
data
.
reason
),
context
=
'transfer'
)
def
_NH_MediaStreamWillEnd
(
self
,
notification
):
stream
=
notification
.
sender
if
stream
.
type
==
'audio'
and
stream
.
blink_session
.
items
.
audio
is
self
:
...
...
@@ -2022,7 +2128,7 @@ class AudioSessionModel(QAbstractListModel):
return
None
def
supportedDropActions
(
self
):
return
Qt
.
CopyAction
|
Qt
.
MoveAction
return
Qt
.
CopyAction
|
Qt
.
MoveAction
|
Qt
.
LinkAction
def
mimeTypes
(
self
):
return
[
'application/x-blink-session-list'
]
...
...
@@ -2057,7 +2163,10 @@ class AudioSessionModel(QAbstractListModel):
selection_model
=
session_list
.
selectionModel
()
source
=
session_list
.
dragged_session
target
=
self
.
sessions
[
index
.
row
()]
if
index
.
isValid
()
else
None
if
source
.
client_conference
is
None
:
# the dragged session is not in a conference yet
if
action
==
Qt
.
LinkAction
:
# call transfer
source
.
blink_session
.
transfer
(
target
.
blink_session
.
contact_uri
,
replaced_session
=
target
.
blink_session
)
elif
source
.
client_conference
is
None
:
# the dragged session is not in a conference yet
if
target
.
client_conference
is
not
None
:
source_row
=
self
.
sessions
.
index
(
source
)
target_row
=
self
.
sessions
.
index
(
target
.
client_conference
.
sessions
[
-
1
]
.
items
.
audio
)
+
1
...
...
@@ -2088,6 +2197,7 @@ class AudioSessionModel(QAbstractListModel):
session
.
active
=
source
.
active
or
target
.
active
if
source
.
active
:
source
.
client_conference
.
unhold
()
self
.
structureChanged
.
emit
()
else
:
# the dragged session is in a conference
dragged
=
source
sibling
=
next
(
session
.
items
.
audio
for
session
in
dragged
.
client_conference
.
sessions
if
session
.
items
.
audio
is
not
dragged
)
...
...
@@ -2127,7 +2237,7 @@ class AudioSessionModel(QAbstractListModel):
session_list
.
scrollTo
(
self
.
index
(
self
.
sessions
.
index
(
sibling
)),
session_list
.
PositionAtCenter
)
dragged
.
widget
.
selected
=
False
dragged
.
active
=
False
self
.
structureChanged
.
emit
()
self
.
structureChanged
.
emit
()
return
True
def
_DH_ApplicationXBlinkContactList
(
self
,
mime_data
,
action
,
index
):
...
...
@@ -2515,10 +2625,8 @@ class AudioSessionListView(QListView):
if
not
acceptable_mime_types
:
event
.
ignore
()
elif
event_source
is
not
self
and
'application/x-blink-session-list'
in
provided_mime_types
:
event
.
ignore
()
# we don't handle drops for blink sessions from other sources
event
.
ignore
()
# we don't handle drops for blink sessions from other sources
else
:
if
event_source
is
self
:
event
.
setDropAction
(
Qt
.
MoveAction
)
event
.
accept
()
def
dragLeaveEvent
(
self
,
event
):
...
...
@@ -2528,8 +2636,6 @@ class AudioSessionListView(QListView):
def
dragMoveEvent
(
self
,
event
):
super
(
AudioSessionListView
,
self
)
.
dragMoveEvent
(
event
)
if
event
.
source
()
is
self
:
event
.
setDropAction
(
Qt
.
MoveAction
)
model
=
self
.
model
()
...
...
@@ -2551,7 +2657,10 @@ class AudioSessionListView(QListView):
def
dropEvent
(
self
,
event
):
model
=
self
.
model
()
if
event
.
source
()
is
self
:
event
.
setDropAction
(
Qt
.
MoveAction
)
if
event
.
keyboardModifiers
()
&
Qt
.
AltModifier
:
event
.
setDropAction
(
Qt
.
LinkAction
)
else
:
event
.
setDropAction
(
Qt
.
MoveAction
)
for
session
in
self
.
model
()
.
sessions
:
session
.
widget
.
drop_indicator
=
False
if
model
.
handleDroppedData
(
event
.
mimeData
(),
event
.
dropAction
(),
self
.
indexAt
(
event
.
pos
())):
...
...
@@ -2565,9 +2674,19 @@ class AudioSessionListView(QListView):
rect
=
self
.
viewport
()
.
rect
()
rect
.
setTop
(
self
.
visualRect
(
model
.
index
(
len
(
model
.
sessions
)
-
1
))
.
bottom
())
if
dragged_session
.
client_conference
is
not
None
:
event
.
setDropAction
(
Qt
.
MoveAction
)
event
.
accept
(
rect
)
else
:
event
.
ignore
(
rect
)
elif
event
.
keyboardModifiers
()
&
Qt
.
AltModifier
and
dragged_session
.
client_conference
is
None
:
if
dragged_session
is
session
or
session
.
client_conference
is
not
None
or
session
.
blink_session
.
state
!=
'connected'
:
event
.
ignore
(
rect
)
elif
dragged_session
.
blink_session
.
transfer_state
in
(
'active'
,
'completed'
)
or
session
.
blink_session
.
transfer_state
in
(
'active'
,
'completed'
):
event
.
ignore
(
rect
)
else
:
session
.
widget
.
drop_indicator
=
True
event
.
setDropAction
(
Qt
.
LinkAction
)
# it might not be LinkAction if other keyboard modifiers are active
event
.
accept
(
rect
)
else
:
conference
=
dragged_session
.
client_conference
or
Null
if
dragged_session
is
session
or
session
.
blink_session
in
conference
.
sessions
:
...
...
@@ -2579,6 +2698,7 @@ class AudioSessionListView(QListView):
sibling
.
items
.
audio
.
widget
.
drop_indicator
=
True
else
:
session
.
widget
.
drop_indicator
=
True
event
.
setDropAction
(
Qt
.
MoveAction
)
event
.
accept
(
rect
)
def
_DH_ApplicationXBlinkContactList
(
self
,
event
,
index
,
rect
,
session
):
...
...
@@ -5091,6 +5211,88 @@ class IncomingFileTransferRequest(QObject):
self
.
rejected
.
emit
(
self
,
self
.
dialog
.
reject_mode
)
ui_class
,
base_class
=
uic
.
loadUiType
(
Resources
.
get
(
'incoming_calltransfer_dialog.ui'
))
class
IncomingCallTransferDialog
(
IncomingDialogBase
,
ui_class
):
def
__init__
(
self
,
parent
=
None
):
super
(
IncomingCallTransferDialog
,
self
)
.
__init__
(
parent
)
self
.
setWindowFlags
(
Qt
.
WindowStaysOnTopHint
)
self
.
setAttribute
(
Qt
.
WA_DeleteOnClose
)
with
Resources
.
directory
:
self
.
setupUi
(
self
)
font
=
self
.
username_label
.
font
()
font
.
setPointSizeF
(
self
.
uri_label
.
fontInfo
()
.
pointSizeF
()
+
3
)
font
.
setFamily
(
"Sans Serif"
)
self
.
username_label
.
setFont
(
font
)
font
=
self
.
transfer_label
.
font
()
font
.
setPointSizeF
(
self
.
uri_label
.
fontInfo
()
.
pointSizeF
()
-
1
)
self
.
transfer_label
.
setFont
(
font
)
self
.
slot
=
None
self
.
reject_mode
=
'reject'
def
show
(
self
,
activate
=
True
):
self
.
setAttribute
(
Qt
.
WA_ShowWithoutActivating
,
not
activate
)
super
(
IncomingCallTransferDialog
,
self
)
.
show
()
del
ui_class
,
base_class
class
IncomingCallTransferRequest
(
QObject
):
finished
=
pyqtSignal
(
object
)
accepted
=
pyqtSignal
(
object
)
rejected
=
pyqtSignal
(
object
,
str
)
priority
=
0
stream_types
=
{
'audio'
}
def
__init__
(
self
,
dialog
,
contact
,
contact_uri
,
session
):
super
(
IncomingCallTransferRequest
,
self
)
.
__init__
()
self
.
dialog
=
dialog
self
.
contact
=
contact
self
.
contact_uri
=
contact_uri
self
.
session
=
session
self
.
dialog
.
setWindowTitle
(
u'Incoming Call Transfer'
)
self
.
dialog
.
setWindowIconText
(
u'Incoming Call Transfer'
)
self
.
dialog
.
uri_label
.
setText
(
contact_uri
.
uri
)
self
.
dialog
.
username_label
.
setText
(
contact
.
name
)
if
contact
.
pixmap
:
self
.
dialog
.
user_icon
.
setPixmap
(
contact
.
pixmap
)
self
.
dialog
.
transfer_label
.
setText
(
u'would like to transfer you to {.uri}'
.
format
(
contact_uri
))
self
.
dialog
.
finished
.
connect
(
self
.
_SH_DialogFinished
)
self
.
dialog
.
accepted
.
connect
(
self
.
_SH_DialogAccepted
)
self
.
dialog
.
rejected
.
connect
(
self
.
_SH_DialogRejected
)
def
__eq__
(
self
,
other
):
return
self
is
other
def
__ne__
(
self
,
other
):
return
self
is
not
other
def
__lt__
(
self
,
other
):
return
self
.
priority
<
other
.
priority
def
__le__
(
self
,
other
):
return
self
.
priority
<=
other
.
priority
def
__gt__
(
self
,
other
):
return
self
.
priority
>
other
.
priority
def
__ge__
(
self
,
other
):
return
self
.
priority
>=
other
.
priority
def
_SH_DialogFinished
(
self
):
self
.
finished
.
emit
(
self
)
def
_SH_DialogAccepted
(
self
):
self
.
accepted
.
emit
(
self
)
def
_SH_DialogRejected
(
self
):
self
.
rejected
.
emit
(
self
,
self
.
dialog
.
reject_mode
)
ui_class
,
base_class
=
uic
.
loadUiType
(
Resources
.
get
(
'conference_dialog.ui'
))
class
ConferenceDialog
(
base_class
,
ui_class
):
...
...
@@ -5210,6 +5412,7 @@ class SessionManager(object):
self
.
_filetransfer_tone_timer
.
setSingleShot
(
True
)
notification_center
=
NotificationCenter
()
notification_center
.
add_observer
(
self
,
name
=
'SIPSessionNewOutgoing'
)
notification_center
.
add_observer
(
self
,
name
=
'SIPSessionNewIncoming'
)
notification_center
.
add_observer
(
self
,
name
=
'SIPSessionDidFail'
)
...
...
@@ -5395,6 +5598,18 @@ class SessionManager(object):
if
mode
==
'reject'
:
incoming_request
.
session
.
reject
(
603
)
def
_SH_IncomingCallTransferRequestAccepted
(
self
,
incoming_request
):
try
:
incoming_request
.
session
.
accept_transfer
()
except
IllegalStateError
:
pass
def
_SH_IncomingCallTransferRequestRejected
(
self
,
incoming_request
,
mode
):
try
:
incoming_request
.
session
.
reject_transfer
()
except
IllegalStateError
:
pass
@
run_in_gui_thread
def
handle_notification
(
self
,
notification
):
handler
=
getattr
(
self
,
'_NH_
%
s'
%
notification
.
name
,
Null
)
...
...
@@ -5457,6 +5672,20 @@ class SessionManager(object):
incoming_request
.
dialog
.
show
(
activate
=
QApplication
.
activeWindow
()
is
not
None
and
self
.
incoming_requests
.
index
(
incoming_request
)
==
0
)
self
.
update_ringtone
()
def
_NH_SIPSessionNewOutgoing
(
self
,
notification
):
sip_session
=
notification
.
sender
if
sip_session
.
transfer_info
is
not
None
:
from
blink.contacts
import
URIUtils
contact
,
contact_uri
=
URIUtils
.
find_contact
(
sip_session
.
remote_identity
.
uri
)
try
:
blink_session
=
next
(
session
for
session
in
self
.
sessions
if
session
.
reusable
and
session
.
contact
.
settings
is
contact
.
settings
)
reinitialize
=
True
except
StopIteration
:
blink_session
=
BlinkSession
()
reinitialize
=
False
blink_session
.
init_transfer
(
sip_session
,
notification
.
data
.
streams
,
contact
,
contact_uri
,
reinitialize
=
reinitialize
)
def
_NH_SIPSessionDidFail
(
self
,
notification
):
if
notification
.
sender
.
direction
==
'incoming'
:
for
incoming_request
in
self
.
incoming_requests
[
notification
.
sender
]:
...
...
@@ -5510,6 +5739,28 @@ class SessionManager(object):
self
.
sessions
.
remove
(
notification
.
sender
)
notification
.
center
.
remove_observer
(
self
,
sender
=
notification
.
sender
)
def
_NH_BlinkSessionTransferNewIncoming
(
self
,
notification
):
from
blink.contacts
import
URIUtils
session
=
notification
.
sender
.
sip_session
contact
,
contact_uri
=
URIUtils
.
find_contact
(
notification
.
data
.
transfer_destination
)
dialog
=
IncomingCallTransferDialog
()
# Build the dialog without a parent in order to be displayed on the current workspace on Linux.
incoming_request
=
IncomingCallTransferRequest
(
dialog
,
contact
,
contact_uri
,
session
)
incoming_request
.
finished
.
connect
(
self
.
_SH_IncomingRequestFinished
)
incoming_request
.
accepted
.
connect
(
self
.
_SH_IncomingCallTransferRequestAccepted
)
incoming_request
.
rejected
.
connect
(
self
.
_SH_IncomingCallTransferRequestRejected
)
bisect
.
insort_right
(
self
.
incoming_requests
,
incoming_request
)
incoming_request
.
dialog
.
show
(
activate
=
QApplication
.
activeWindow
()
is
not
None
and
self
.
incoming_requests
.
index
(
incoming_request
)
==
0
)
self
.
update_ringtone
()
def
_NH_BlinkSessionTransferDidFail
(
self
,
notification
):
for
request
in
self
.
incoming_requests
[
notification
.
sender
.
sip_session
,
IncomingCallTransferRequest
]:
request
.
dialog
.
hide
()
self
.
incoming_requests
.
remove
(
request
)
self
.
update_ringtone
()
def
_NH_BlinkFileTransferWasCreated
(
self
,
notification
):
self
.
file_transfers
.
append
(
notification
.
sender
)
notification
.
center
.
add_observer
(
self
,
sender
=
notification
.
sender
)
...
...
resources/incoming_calltransfer_dialog.ui
0 → 100644
View file @
ae271926
<?xml version="1.0" encoding="UTF-8"?>
<ui
version=
"4.0"
>
<class>
Dialog
</class>
<widget
class=
"QDialog"
name=
"Dialog"
>
<property
name=
"geometry"
>
<rect>
<x>
0
</x>
<y>
0
</y>
<width>
480
</width>
<height>
165
</height>
</rect>
</property>
<property
name=
"minimumSize"
>
<size>
<width>
480
</width>
<height>
165
</height>
</size>
</property>
<property
name=
"maximumSize"
>
<size>
<width>
16777215
</width>
<height>
165
</height>
</size>
</property>
<property
name=
"windowTitle"
>
<string>
Incoming Call Transfer
</string>
</property>
<property
name=
"windowIcon"
>
<iconset>
<normaloff>
icons/blink48.png
</normaloff>
icons/blink48.png
</iconset>
</property>
<layout
class=
"QVBoxLayout"
name=
"dialog_layout"
>
<property
name=
"spacing"
>
<number>
34
</number>
</property>
<property
name=
"margin"
>
<number>
8
</number>
</property>
<item>
<widget
class=
"QFrame"
name=
"frame"
>
<property
name=
"styleSheet"
>
<string>
QFrame#frame {
background-color: #f8f8f8;
border-color: #545454;
border-radius: 4px;
border-width: 2px;
border-style: solid;
}
</string>
</property>
<property
name=
"frameShape"
>
<enum>
QFrame::StyledPanel
</enum>
</property>
<property
name=
"frameShadow"
>
<enum>
QFrame::Sunken
</enum>
</property>
<layout
class=
"QGridLayout"
name=
"frame_layout"
>
<property
name=
"topMargin"
>
<number>
7
</number>
</property>
<property
name=
"bottomMargin"
>
<number>
7
</number>
</property>
<property
name=
"verticalSpacing"
>
<number>
0
</number>
</property>
<item
row=
"0"
column=
"1"
>
<widget
class=
"QLabel"
name=
"username_label"
>
<property
name=
"sizePolicy"
>
<sizepolicy
hsizetype=
"Expanding"
vsizetype=
"Fixed"
>
<horstretch>
0
</horstretch>
<verstretch>
0
</verstretch>
</sizepolicy>
</property>
<property
name=
"font"
>
<font>
<family>
Sans Serif
</family>
<pointsize>
12
</pointsize>
<weight>
75
</weight>
<bold>
true
</bold>
</font>
</property>
<property
name=
"text"
>
<string>
Caller name
</string>
</property>
<property
name=
"alignment"
>
<set>
Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
</set>
</property>
</widget>
</item>
<item
row=
"1"
column=
"1"
>
<widget
class=
"QLabel"
name=
"uri_label"
>
<property
name=
"sizePolicy"
>
<sizepolicy
hsizetype=
"Expanding"
vsizetype=
"Fixed"
>
<horstretch>
0
</horstretch>
<verstretch>
0
</verstretch>
</sizepolicy>
</property>
<property
name=
"palette"
>
<palette>
<active>
<colorrole
role=
"WindowText"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
68
</red>
<green>
68
</green>
<blue>
68
</blue>
</color>
</brush>
</colorrole>
<colorrole
role=
"Text"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
68
</red>
<green>
68
</green>
<blue>
68
</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole
role=
"WindowText"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
68
</red>
<green>
68
</green>
<blue>
68
</blue>
</color>
</brush>
</colorrole>
<colorrole
role=
"Text"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
68
</red>
<green>
68
</green>
<blue>
68
</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole
role=
"WindowText"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
118
</red>
<green>
118
</green>
<blue>
117
</blue>
</color>
</brush>
</colorrole>
<colorrole
role=
"Text"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
118
</red>
<green>
118
</green>
<blue>
117
</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property
name=
"text"
>
<string>
Caller URI
</string>
</property>
<property
name=
"indent"
>
<number>
1
</number>
</property>
</widget>
</item>
<item
row=
"0"
column=
"0"
rowspan=
"2"
>
<widget
class=
"QLabel"
name=
"user_icon"
>
<property
name=
"minimumSize"
>
<size>
<width>
36
</width>
<height>
36
</height>
</size>
</property>
<property
name=
"maximumSize"
>
<size>
<width>
36
</width>
<height>
36
</height>
</size>
</property>
<property
name=
"pixmap"
>
<pixmap>
icons/default-avatar.png
</pixmap>
</property>
<property
name=
"alignment"
>
<set>
Qt::AlignCenter
</set>
</property>
</widget>
</item>
<item
row=
"2"
column=
"0"
colspan=
"2"
>
<spacer
name=
"frame_spacer"
>
<property
name=
"orientation"
>
<enum>
Qt::Vertical
</enum>
</property>
<property
name=
"sizeHint"
stdset=
"0"
>
<size>
<width>
0
</width>
<height>
0
</height>
</size>
</property>
</spacer>
</item>
<item
row=
"3"
column=
"0"
colspan=
"2"
>
<widget
class=
"QLabel"
name=
"transfer_label"
>
<property
name=
"palette"
>
<palette>
<active>
<colorrole
role=
"WindowText"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
68
</red>
<green>
68
</green>
<blue>
68
</blue>
</color>
</brush>
</colorrole>
<colorrole
role=
"Text"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
68
</red>
<green>
68
</green>
<blue>
68
</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole
role=
"WindowText"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
68
</red>
<green>
68
</green>
<blue>
68
</blue>
</color>
</brush>
</colorrole>
<colorrole
role=
"Text"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
68
</red>
<green>
68
</green>
<blue>
68
</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole
role=
"WindowText"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
118
</red>
<green>
118
</green>
<blue>
117
</blue>
</color>
</brush>
</colorrole>
<colorrole
role=
"Text"
>
<brush
brushstyle=
"SolidPattern"
>
<color
alpha=
"255"
>
<red>
118
</red>
<green>
118
</green>
<blue>
117
</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property
name=
"text"
>
<string
extracomment=
"is offering to share his screen"
>
would like to transfer you to user@domain
</string>
</property>
<property
name=
"indent"
>
<number>
3
</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout
class=
"QHBoxLayout"
name=
"button_layout"
>
<property
name=
"spacing"
>
<number>
5
</number>
</property>
<item>
<widget
class=
"QPushButton"
name=
"reject_button"
>
<property
name=
"minimumSize"
>
<size>
<width>
85
</width>
<height>
24
</height>
</size>
</property>
<property
name=
"maximumSize"
>
<size>
<width>
16777215
</width>
<height>
24
</height>
</size>
</property>
<property
name=
"text"
>
<string>
Reject
</string>
</property>
</widget>
</item>
<item>
<spacer
name=
"button_spacer"
>
<property
name=
"orientation"
>
<enum>
Qt::Horizontal
</enum>
</property>
<property
name=
"sizeHint"
stdset=
"0"
>
<size>
<width>
40
</width>
<height>
20
</height>
</size>
</property>
</spacer>
</item>
<item>
<widget
class=
"QPushButton"
name=
"accept_button"
>
<property
name=
"minimumSize"
>
<size>
<width>
85
</width>
<height>
24
</height>
</size>
</property>
<property
name=
"maximumSize"
>
<size>
<width>
16777215
</width>
<height>
24
</height>
</size>
</property>
<property
name=
"text"
>
<string>
Accept
</string>
</property>
<property
name=
"default"
>
<bool>
true
</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>
accept_button
</tabstop>
<tabstop>
reject_button
</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>
accept_button
</sender>
<signal>
clicked()
</signal>
<receiver>
Dialog
</receiver>
<slot>
accept()
</slot>
<hints>
<hint
type=
"sourcelabel"
>
<x>
345
</x>
<y>
117
</y>
</hint>
<hint
type=
"destinationlabel"
>
<x>
196
</x>
<y>
67
</y>
</hint>
</hints>
</connection>
<connection>
<sender>
reject_button
</sender>
<signal>
clicked()
</signal>
<receiver>
Dialog
</receiver>
<slot>
reject()
</slot>
<hints>
<hint
type=
"sourcelabel"
>
<x>
48
</x>
<y>
117
</y>
</hint>
<hint
type=
"destinationlabel"
>
<x>
196
</x>
<y>
67
</y>
</hint>
</hints>
</connection>
</connections>
</ui>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment