1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
import sys, subprocess, os, json, tempfile
from urllib import request
from urllib.parse import urlparse
from resources import Resources
from PyQt4 import QtWebKit, QtGui, QtCore
from PyQt4.Qt import QApplication, QKeySequence, QTimer
from PyQt4.QtCore import QBuffer, QByteArray, QUrl
from PyQt4.QtWebKit import QWebView, QWebPage, QWebSettings
from PyQt4.QtNetwork import QNetworkProxy
class Wrapper(QWebView):
highlights = 0
icon = None
name = ''
def __init__(self, window):
self.configure_proxy()
QWebView.__init__(self)
self.window = window
with open(Resources.get_path("scudcloud.js"), "r") as f:
self.js = f.read()
self.setZoomFactor(self.window.zoom)
self.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks)
self.urlChanged.connect(self._urlChanged)
self.loadStarted.connect(self._loadStarted)
self.loadFinished.connect(self._loadFinished)
self.linkClicked.connect(self._linkClicked)
self.page().featurePermissionRequested.connect(self.permissionRequested)
self.addActions()
def permissionRequested(self, frame, feature):
self.page().setFeaturePermission(frame, feature, QWebPage.PermissionGrantedByUser)
self.overrideNotifications()
def configure_proxy(self):
proxy = urlparse(os.environ.get('http_proxy') or os.environ.get('HTTP_PROXY'))
if proxy.hostname is not None and proxy.port is not None:
q_network_proxy = QNetworkProxy(QNetworkProxy.HttpProxy, proxy.hostname, proxy.port)
if proxy.username is not None:
q_network_proxy.setUser(proxy.username)
if proxy.password is not None:
q_network_proxy.setPassword(proxy.password)
QNetworkProxy.setApplicationProxy(q_network_proxy)
def addActions(self):
self.pageAction(QWebPage.SetTextDirectionDefault).setVisible(False)
self.pageAction(QWebPage.SetTextDirectionLeftToRight).setVisible(False)
self.pageAction(QWebPage.SetTextDirectionRightToLeft).setVisible(False)
self.pageAction(QWebPage.Undo).setShortcuts(QKeySequence.Undo)
self.pageAction(QWebPage.Redo).setShortcuts(QKeySequence.Redo)
self.pageAction(QWebPage.Cut).setShortcuts(QKeySequence.Cut)
self.pageAction(QWebPage.Copy).setShortcuts(QKeySequence.Copy)
self.pageAction(QWebPage.Paste).setShortcuts(QKeySequence.Paste)
self.pageAction(QWebPage.Back).setShortcuts(QKeySequence.Back)
self.pageAction(QWebPage.Forward).setShortcuts(QKeySequence.Forward)
self.pageAction(QWebPage.Reload).setShortcuts(QKeySequence.Refresh)
def contextMenuEvent(self, event):
menu = QtGui.QMenu(self)
if self.window.speller.initialized:
hit = self.page().currentFrame().hitTestContent(event.pos())
element = hit.element()
if hit.isContentEditable() and not hit.isContentSelected() and element.attribute("type") != "password":
self.window.speller.populateContextMenu(menu, element)
pageMenu = self.page().createStandardContextMenu()
if pageMenu is not None:
for a in pageMenu.actions():
if a.isSeparator():
menu.addSeparator()
elif a.isVisible():
menu.addAction(a)
del pageMenu
menu.exec_(event.globalPos())
def call(self, function, arg=None):
if isinstance(arg, str):
arg = "'"+arg+"'"
if arg is None:
arg = ""
return self.page().currentFrame().evaluateJavaScript("ScudCloud."+function+"("+arg+");")
def _loadStarted(self):
# Some custom CSS to clean/fix UX
self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(Resources.get_path("resources.css")))
def _urlChanged(self, qUrl):
url = qUrl.toString()
# Some integrations/auth will get back to /services with no way to get back to chat
if Resources.SERVICES_URL_RE.match(url):
self.systemOpen(url)
self.load(QUrl("https://"+qUrl.host()+"/messages/general"))
def _loadFinished(self, ok=True):
# Starting the webkit-JS bridge
self.page().currentFrame().addToJavaScriptWindowObject("desktop", self)
# Loading ScudCloud JS client
self.page().currentFrame().evaluateJavaScript(self.js)
self.window.statusBar().hide()
def systemOpen(self, url):
subprocess.call(('xdg-open', url))
def _linkClicked(self, qUrl):
url = qUrl.toString()
handle_link = (
Resources.SIGNIN_URL == url or
Resources.MAINPAGE_URL_RE.match(url) or
Resources.MESSAGES_URL_RE.match(url) or
Resources.SSO_URL_RE.match(url) or
url.startswith("https://accounts.google.com/o/oauth"))
if handle_link:
self.load(qUrl)
else:
self.systemOpen(url)
def preferences(self):
self.window.show()
self.call("preferences")
def createSnippet(self):
self.call("createSnippet")
def team(self):
return self.call("getCurrentTeam")
def logout(self):
self.call("logout")
def help(self):
self.call("help")
def helpCenter(self):
subprocess.call(('xdg-open', "https://slack.zendesk.com/hc/en-us"))
def about(self):
subprocess.call(('xdg-open', "https://github.com/raelgc/scudcloud"))
def listChannels(self):
return self.call("listChannels")
def openChannel(self, menuitem, timestamp):
self.call("join", menuitem.property_get("id"))
self.window.show()
@QtCore.pyqtSlot(int, int)
def count(self, highlight, unread):
self.highlights = highlight
self.window.count()
@QtCore.pyqtSlot(str)
def populate(self, serialized):
data = json.loads(serialized)
self.window.teams(data['teams'])
if self.window.current() == self:
self.window.quicklist(data['channels'])
self.name = data['teams'][0]['team_name']
filename, headers = request.urlretrieve(data['icon'], tempfile.gettempdir()+'/'+self.name+'.png')
self.icon = filename
@QtCore.pyqtSlot(bool)
def enableMenus(self, enabled):
self.window.enableMenus(enabled)
@QtCore.pyqtSlot(bool)
def pasted(self, checked):
clipboard = QApplication.clipboard()
mime = clipboard.mimeData()
if mime.hasImage():
pixmap = clipboard.pixmap()
byteArray = QByteArray()
buffer = QBuffer(byteArray)
pixmap.save(buffer, "PNG")
self.call("setClipboard", str(byteArray.toBase64(), sys.stdout.encoding))
@QtCore.pyqtSlot(str, str)
def sendMessage(self, title, message):
erase = ['['+self.name.lower()+'] in ', '['+self.name.lower()+'] from ']
for s in erase:
title = str(title).replace(s, '', 1)
self.window.notify(title, str(message), self.icon)
|