diff options
-rw-r--r-- | README.md | 30 | ||||
-rw-r--r-- | scudcloud-1.0/debian/changelog | 12 | ||||
-rw-r--r-- | scudcloud-1.0/debian/control | 1 | ||||
-rw-r--r-- | scudcloud-1.0/lib/resources.py | 3 | ||||
-rwxr-xr-x | scudcloud-1.0/lib/scudcloud.py | 9 | ||||
-rw-r--r-- | scudcloud-1.0/lib/speller.py | 90 | ||||
-rw-r--r-- | scudcloud-1.0/lib/wrapper.py | 17 | ||||
-rwxr-xr-x | scudcloud-1.0/scudcloud | 2 | ||||
-rw-r--r-- | scudcloud-1.0/scudcloud.spec | 9 |
9 files changed, 156 insertions, 17 deletions
@@ -2,7 +2,7 @@ ![ScudCloud Logo](/scudcloud-1.0/resources/scudcloud.png?raw=true "Scud clouds are low, ragged and wind-torn cloud fragments, usually not attached to the thunderstorm base. With the 'mother' cloud, the form of them together is like a chat balloon") -ScudCloud is a **non official** open-source Linux (Debian, Ubuntu, Kubuntu, Mint, Arch, Fedora) desktop client for [Slack©](http://slack.com). +ScudCloud is a **non official** open-source Linux (Debian, Ubuntu, Kubuntu, Mint, Arch, Fedora) desktop client for [Slack](http://slack.com). ScudCloud uses the [QT](http://qt-project.org) library + [Webkit](http://www.webkit.org/) to render the web version of Slack, but using the [QWebkit-Native bridge](http://qt-project.org/doc/qt-4.8/qtwebkit-bridge.html) to improve desktop integration with: @@ -27,7 +27,7 @@ sudo apt-get update sudo apt-get install scudcloud ``` -If you want **spell checking** (it'll only mark wrong words in red, but no suggestions), add the `hunspell` dictionary for your language. For `en-us`: +If you want **spell checking**, add the `hunspell` dictionary for your language. For `en-us`: sudo apt-get install hunspell-en-us @@ -76,9 +76,9 @@ First, you'll need to install at least packages for `python3`, `python-qt4` (`qt Then run the below script: it'll download the code and install it: ```bash -wget https://github.com/raelgc/scudcloud/archive/v1.0.67.tar.gz -tar -xvf v1.0.67.tar.gz -cd scudcloud-1.0.67 +wget https://github.com/raelgc/scudcloud/archive/v1.0.69.tar.gz +tar -xvf v1.0.69.tar.gz +cd scudcloud-1.0.69 SOURCE="scudcloud-1.0" INSTALL="/opt/scudcloud" sudo mkdir -p $INSTALL/lib @@ -96,35 +96,43 @@ sudo ln -sf $INSTALL/scudcloud /usr/bin/scudcloud # Troubleshooting -## 1. Default domain +#### 1. Default domain You can change the default domain editing or just deleting the config file: ~/.config/scudcloud/scudcloud.cfg -## 2. Where is the package for my distro? +#### 2. Where is the package for my distro? If not listed above, you're welcome [to contribute](/CONTRIBUTING.md). In this meanwhile, try the [Manual Install](#manual-install) instructions. -## 3. `Keep me signed in` is not working +#### 3. Spell checking is not working + +Make sure you have the following packages installed: + +* `libqtwebkit-qupzillaplugins` +* `python3-hunspell` +* `hunspell-en-us` + +#### 4. `Keep me signed in` is not working For some reason, ScudCloud was not able to create the configuration folder. Please, manually create this folder: ~/.config/scudcloud/ -## 4. How to disable Flash? +#### 5. How to disable Flash? Flash is required to display embedded videos, but if you don't care, disable it starting with: scudcloud --no_plugins=True -## 5. How to start ScudCloud minimized? +#### 6. How to start ScudCloud minimized? You can start ScudCloud minized to tray with: scudcloud --minimized=True -## 6. High DPI Support +#### 7. High DPI Support ScudCloud offers zoom support. The zoom level will be persisted between sessions. diff --git a/scudcloud-1.0/debian/changelog b/scudcloud-1.0/debian/changelog index 64777ff..3fa6298 100644 --- a/scudcloud-1.0/debian/changelog +++ b/scudcloud-1.0/debian/changelog @@ -1,3 +1,15 @@ +scudcloud (1.0-69) trusty; urgency=medium + + * Fixing crash when python3-hunspell is not present (#237) + + -- Rael Gugelmin Cunha <rael.gc@gmail.com> Tue, 22 Sep 2015 19:54:47 -0300 + +scudcloud (1.0-68) trusty; urgency=medium + + * Adding HunSpell suggestions (#55) + + -- Rael Gugelmin Cunha <rael.gc@gmail.com> Tue, 22 Sep 2015 16:30:14 -0300 + scudcloud (1.0-67) trusty; urgency=medium * Fixing QuickList diff --git a/scudcloud-1.0/debian/control b/scudcloud-1.0/debian/control index 9ae96d2..d25cae5 100644 --- a/scudcloud-1.0/debian/control +++ b/scudcloud-1.0/debian/control @@ -18,6 +18,7 @@ Recommends: sni-qt, fonts-lato, gir1.2-unity-5.0, libqtwebkit-qupzillaplugins, + python3-hunspell, python3-gi, ttf-mscorefonts-installer Description: ScudCloud is a non official desktop client for Slack diff --git a/scudcloud-1.0/lib/resources.py b/scudcloud-1.0/lib/resources.py index 6e60bd8..f9835d8 100644 --- a/scudcloud-1.0/lib/resources.py +++ b/scudcloud-1.0/lib/resources.py @@ -9,6 +9,9 @@ class Resources: SSO_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/sso/saml/start$') SERVICES_URL_RE = re.compile(r'^http[s]://[a-zA-Z0-9_\-]+.slack.com/services/.*') + SPELL_DICT_PATH = "/usr/share/hunspell/" + SPELL_LIMIT = 6 + # It's initialized in /scudcloud script INSTALL_DIR = None diff --git a/scudcloud-1.0/lib/scudcloud.py b/scudcloud-1.0/lib/scudcloud.py index fcf98fe..debc808 100755 --- a/scudcloud-1.0/lib/scudcloud.py +++ b/scudcloud-1.0/lib/scudcloud.py @@ -4,6 +4,7 @@ from cookiejar import PersistentCookieJar from leftpane import LeftPane from notifier import Notifier from resources import Resources +from speller import Speller from systray import Systray from wrapper import Wrapper from threading import Thread @@ -19,7 +20,7 @@ try: except ImportError: Unity = None Dbusmenu = None - from launcher import DummyLauncher + from launcher import DummyLauncher class ScudCloud(QtGui.QMainWindow): @@ -27,6 +28,7 @@ class ScudCloud(QtGui.QMainWindow): debug = False forceClose = False messages = 0 + speller = Speller() def __init__(self, parent = None, settings_path = ""): super(ScudCloud, self).__init__(parent) @@ -258,11 +260,10 @@ class ScudCloud(QtGui.QMainWindow): for i in range(0, self.stackedWidget.count()): if self.stackedWidget.widget(i).url().toString().startswith(url): self.stackedWidget.setCurrentIndex(i) + self.quicklist(self.current().listChannels()) exists = True break - if exists: - self.quicklist(self.current().listChannels()) - else: + if not exists: self.addWrapper(url) self.enableMenus(self.current().isConnected()) diff --git a/scudcloud-1.0/lib/speller.py b/scudcloud-1.0/lib/speller.py new file mode 100644 index 0000000..6fd34df --- /dev/null +++ b/scudcloud-1.0/lib/speller.py @@ -0,0 +1,90 @@ +import os +from resources import Resources +from PyQt4 import QtGui +from PyQt4.QtCore import QObject +from PyQt4.QtCore import QLocale, QFile, QTextBoundaryFinder + +# Checking if python-hunspell is present +try: + import hunspell +except ImportError: + class hunspell: + HunSpell = None + +# Simplified version of QupZilla Speller (https://github.com/QupZilla/qupzilla/blob/v1.8/src/lib/plugins/qtwebkit/spellcheck/speller.cpp) +class Speller(QObject): + + hunspell = None + initialized = False + startPos = 0 + + def __init__(self): + super(Speller, self).__init__() + if self.initialized or hunspell.HunSpell is None: + return + dictionaryPath = self.getDictionaryPath() + language = self.parseLanguage(dictionaryPath) + if dictionaryPath is None or language is None: + return + self.hunspell = hunspell.HunSpell(dictionaryPath + ".dic", dictionaryPath + ".aff") + self.initialized = True + + def isMisspelled(self, s): + return not self.hunspell.spell(s) + + def suggest(self, s): + return self.hunspell.suggest(s) + + def parseLanguage(self, path): + if '/' in path: + pos = path.rfind('/') + return path[-int(pos + 1):] + return path + + def dictionaryExists(self, path): + return QFile(path + ".dic").exists() and QFile(path + ".aff").exists(); + + def getDictionaryPath(self): + dicPath = Resources.SPELL_DICT_PATH + QLocale.system().name() + if self.dictionaryExists(dicPath): + return dicPath + return '' + + def replaceWord(self, element, word): + action = self.sender() + new = action.data() + text = str(element.evaluateJavaScript("this.value")) + cursorPos = int(element.evaluateJavaScript("this.selectionStart")) + text = text[:self.startPos] + new + text[self.startPos+len(word):] + text = text.replace('\\', "\\\\") + text = text.replace('\n', "\\n") + text = text.replace('\'', "\\'") + element.evaluateJavaScript("this.value='{}'".format(text)) + element.evaluateJavaScript("this.selectionStart=this.selectionEnd={}".format(cursorPos)) + + def getWord(self, element): + text = str(element.evaluateJavaScript("this.value")) + pos = int(int(element.evaluateJavaScript("this.selectionStart")) + int(1)) + finder = QTextBoundaryFinder(QTextBoundaryFinder.Word, text) + finder.setPosition(pos) + self.startPos = finder.toPreviousBoundary() + return text[self.startPos:finder.toNextBoundary()].strip() + + def populateContextMenu(self, menu, element): + word = self.getWord(element) + if self.isMisspelled(word): + suggests = self.suggest(word) + count = Resources.SPELL_LIMIT + if len(suggests) < count: + count = len(suggests) + boldFont = menu.font() + boldFont.setBold(True) + for i in range(0, count): + action = QtGui.QAction(suggests[i], self) + action.triggered.connect(lambda:self.replaceWord(element, word)) + action.setData(suggests[i]) + action.setFont(boldFont) + menu.addAction(action) + if count == 0: + menu.addAction(menu.tr("No suggestions")).setEnabled(False) + menu.addSeparator(); diff --git a/scudcloud-1.0/lib/wrapper.py b/scudcloud-1.0/lib/wrapper.py index 994d0d7..44a8cda 100644 --- a/scudcloud-1.0/lib/wrapper.py +++ b/scudcloud-1.0/lib/wrapper.py @@ -49,6 +49,23 @@ class Wrapper(QWebView): 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+"'" diff --git a/scudcloud-1.0/scudcloud b/scudcloud-1.0/scudcloud index 9af00db..919467c 100755 --- a/scudcloud-1.0/scudcloud +++ b/scudcloud-1.0/scudcloud @@ -14,7 +14,7 @@ from qsingleapplication import QSingleApplication # The ScudCloud QMainWindow win = None -VERSION = '1.0.67' +VERSION = '1.0.69' def main(): global win; diff --git a/scudcloud-1.0/scudcloud.spec b/scudcloud-1.0/scudcloud.spec index 22b39a2..9042a36 100644 --- a/scudcloud-1.0/scudcloud.spec +++ b/scudcloud-1.0/scudcloud.spec @@ -1,7 +1,7 @@ # # spec file for package scudcloud # -# Copyright (c) 2015 Marcin Trendota (moonwolf@techsterowniki.pl) +# Copyright (c) 2015 Marcin Trendota (moonwolf@poczta.onet.pl) # Copyright (c) 2015 Marcin Bajor (marcin.bajor@gmail.com) # # All modifications and additions to the file contributed by third parties @@ -43,6 +43,11 @@ Url: https://github.com/raelgc/scudcloud/ Source: %{name}-%{version}.tar.gz Requires: python3 Requires: python3-qt4 +%if 0%{?suse_version} +Requires: google-lato-fonts +%else +Requires: lato-fonts +%endif BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch @@ -142,6 +147,8 @@ fi %{_bindir}/scudcloud %changelog +* Mon Sep 21 2015 Marcin Trendota <moonwolf@poczta.onet.pl> +- Add lato-fonts dependency * Mon Aug 10 2015 Marcin Bajor <marcin.bajor@gmail.com> - Now build for CentOS, Red Hat Enterprise Linux, openSUSE, SUSE Linux Enterprise Server and others is possible * Mon May 18 2015 Marcin Trendota <moonwolf@poczta.onet.pl> |