Skip to content

Commit

Permalink
Merge branch 'master' into dev/improved-module-detection
Browse files Browse the repository at this point in the history
  • Loading branch information
ErikBjare committed Jul 25, 2020
2 parents 68314f0 + 20261da commit 0a359bd
Show file tree
Hide file tree
Showing 8 changed files with 983 additions and 1,011 deletions.
59 changes: 59 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Build

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:
name: Test on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-18.04, windows-latest, macOS-latest]
python_version: [3.6]
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python_version }}
- name: Create virtualenv
shell: bash
run: |
pip install virtualenv
python -m virtualenv venv
- name: Install dependencies
shell: bash
run: |
pip install poetry
source venv/bin/activate || source venv/Scripts/activate
poetry install
- name: Build
shell: bash
run: |
source venv/bin/activate || source venv/Scripts/activate
make build
- name: Run tests
shell: bash
run: |
source venv/bin/activate || source venv/Scripts/activate
make test
make typecheck
- name: Run integration tests
if: runner.os == 'Linux'
run: |
sudo apt-get install -y libdbus-1-3 libxkbcommon-x11-0; # Workaround for issue with Qt integration test on xenial: https://github.com/pytest-dev/pytest-qt/issues/266#issuecomment-510035926
sudo apt-get install xvfb;
source venv/bin/activate || source venv/Scripts/activate
xvfb-run --auto-servernum make test-integration;
- name: Package
shell: bash
run: |
source venv/bin/activate || source venv/Scripts/activate
pip install pyinstaller==3.5
make package
46 changes: 0 additions & 46 deletions .travis.yml

This file was deleted.

12 changes: 3 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
.PHONY: build install test test-integration typecheck package clean

ifdef DEV
installcmd := poetry install
else
installcmd := pip3 install .
endif

build: aw_qt/resources.py
# Workaround for https://github.com/python-poetry/poetry/issues/1338#issuecomment-571618450
cp .gitignore .gitignore.backup
grep -v 'aw_qt/resources.py' .gitignore.backup > .gitignore
$(installcmd)
poetry install
mv .gitignore.backup .gitignore
rm -f .gitignore.backup

install:
bash scripts/config-autostart.sh

test:
python3 -c 'import aw_qt'
python -c 'import aw_qt'

test-integration:
python3 ./tests/integration_tests.py --no-modules
python ./tests/integration_tests.py --no-modules

typecheck:
mypy aw_qt --strict --pretty
Expand Down
1 change: 0 additions & 1 deletion aw_qt/resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@
<qresource>
<file alias="logo.png">../media/logo/logo.png</file>
<file alias="black-monochrome-logo.png">../media/logo/black-monochrome-logo.png</file>
<file alias="white-monochrome-logo.png">../media/logo/white-monochrome-logo.png</file>
</qresource>
</RCC>
102 changes: 76 additions & 26 deletions aw_qt/trayicon.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import sys
import logging
import signal
import webbrowser
import os
import subprocess
from collections import defaultdict
from typing import Any, DefaultDict, List, Optional
import webbrowser

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMessageBox, QMenu, QWidget, QPushButton
from PyQt5.QtWidgets import (
QApplication,
QSystemTrayIcon,
QMessageBox,
QMenu,
QWidget,
QPushButton,
)
from PyQt5.QtGui import QIcon

import aw_core
Expand All @@ -18,30 +25,62 @@
logger = logging.getLogger(__name__)


def get_env():
"""
Necessary for xdg-open to work properly when PyInstaller overrides LD_LIBRARY_PATH
https://github.com/ActivityWatch/activitywatch/issues/208#issuecomment-417346407
"""
env = dict(os.environ) # make a copy of the environment
lp_key = "LD_LIBRARY_PATH" # for GNU/Linux and *BSD.
lp_orig = env.get(lp_key + "_ORIG")
if lp_orig is not None:
env[lp_key] = lp_orig # restore the original, unmodified value
else:
# This happens when LD_LIBRARY_PATH was not set.
# Remove the env var as a last resort:
env.pop(lp_key, None)
return env


def open_url(url):
if sys.platform == "linux":
env = get_env()
subprocess.Popen(["xdg-open", url], env=env)
else:
webbrowser.open(url)


def open_webui(root_url: str) -> None:
print("Opening dashboard")
webbrowser.open(root_url)
open_url(root_url)


def open_apibrowser(root_url: str) -> None:
print("Opening api browser")
webbrowser.open(root_url + "/api")
open_url(root_url + "/api")


def open_dir(d: str)-> None:
def open_dir(d: str) -> None:
"""From: http://stackoverflow.com/a/1795849/965332"""
if sys.platform == 'win32':
if sys.platform == "win32":
os.startfile(d)
elif sys.platform == 'darwin':
subprocess.Popen(['open', d])
elif sys.platform == "darwin":
subprocess.Popen(["open", d])
else:
subprocess.Popen(['xdg-open', d])
subprocess.Popen(["xdg-open", d])


class TrayIcon(QSystemTrayIcon):
def __init__(self, manager: Manager, icon: QIcon, parent: Optional[QWidget]=None, testing: bool=False) -> None:
def __init__(
self,
manager: Manager,
icon: QIcon,
parent: Optional[QWidget] = None,
testing: bool = False,
) -> None:
QSystemTrayIcon.__init__(self, icon, parent)
self._parent = parent # QSystemTrayIcon also tries to save parent info but it screws up the type info
self._parent = parent # QSystemTrayIcon also tries to save parent info but it screws up the type info
self.setToolTip("ActivityWatch" + (" (testing)" if testing else ""))

self.manager = manager
Expand All @@ -68,10 +107,14 @@ def _build_rootmenu(self) -> None:
self._build_modulemenu(modulesMenu)

menu.addSeparator()
menu.addAction("Open log folder", lambda: open_dir(aw_core.dirs.get_log_dir(None)))
menu.addAction(
"Open log folder", lambda: open_dir(aw_core.dirs.get_log_dir(None))
)
menu.addSeparator()

exitIcon = QIcon.fromTheme("application-exit", QIcon("media/application_exit.png"))
exitIcon = QIcon.fromTheme(
"application-exit", QIcon("media/application_exit.png")
)
# This check is an attempted solution to: https://github.com/ActivityWatch/activitywatch/issues/62
# Seems to be in agreement with: https://github.com/OtterBrowser/otter-browser/issues/1313
# "it seems that the bug is also triggered when creating a QIcon with an invalid path"
Expand Down Expand Up @@ -105,6 +148,7 @@ def rebuild_modules_menu() -> None:

# TODO: Do it in a better way, singleShot isn't pretty...
QtCore.QTimer.singleShot(2000, rebuild_modules_menu)

QtCore.QTimer.singleShot(2000, rebuild_modules_menu)

def check_module_status() -> None:
Expand All @@ -116,6 +160,7 @@ def check_module_status() -> None:

# TODO: Do it in a better way, singleShot isn't pretty...
QtCore.QTimer.singleShot(2000, rebuild_modules_menu)

QtCore.QTimer.singleShot(2000, check_module_status)

def _build_modulemenu(self, moduleMenu: QMenu) -> None:
Expand All @@ -130,11 +175,15 @@ def add_module_menuitem(module: Module) -> None:
ac.setChecked(module.is_alive())

# Merged from branch dev/autodetect-modules, still kind of in progress with making this actually work
modules_by_location: DefaultDict[str, List[Module]] = defaultdict(lambda: list())
modules_by_location: DefaultDict[str, List[Module]] = defaultdict(
lambda: list()
)
for module in sorted(self.manager.modules.values(), key=lambda m: m.name):
modules_by_location[module.location].append(module)

for location, modules in sorted(modules_by_location.items(), key=lambda kv: kv[0]):
for location, modules in sorted(
modules_by_location.items(), key=lambda kv: kv[0]
):
header = moduleMenu.addAction(location)
header.setEnabled(False)

Expand All @@ -159,27 +208,28 @@ def run(manager: Manager, testing: bool = False) -> Any:

app = QApplication(sys.argv)

# Ensure cleanup happens on SIGTERM and SIGINT (kill and ctrl+c etc)
# The 2 un-used variables are necessary
signal.signal(signal.SIGINT, lambda _, __: exit(manager))
signal.signal(signal.SIGTERM, lambda _, __: exit(manager))
# Without this, Ctrl+C will have no effect
signal.signal(signal.SIGINT, lambda *args: exit(manager))
# Ensure cleanup happens on SIGTERM
signal.signal(signal.SIGTERM, lambda *args: exit(manager))

timer = QtCore.QTimer()
timer.start(100) # You may change this if you wish.
timer.timeout.connect(lambda: None) # Let the interpreter run each 500 ms.

if not QSystemTrayIcon.isSystemTrayAvailable():
QMessageBox.critical(None, "Systray", "I couldn't detect any system tray on this system. Either get one or run the ActivityWatch modules from the console.")
QMessageBox.critical(
None,
"Systray",
"I couldn't detect any system tray on this system. Either get one or run the ActivityWatch modules from the console.",
)
sys.exit(1)

widget = QWidget()
if sys.platform == "darwin":
from Foundation import NSUserDefaults
style = NSUserDefaults.standardUserDefaults().stringForKey_('AppleInterfaceStyle')
if style == "Dark":
icon = QIcon(":/white-monochrome-logo.png")
else:
icon = QIcon(":/black-monochrome-logo.png")
icon = QIcon(":/black-monochrome-logo.png")
# Allow macOS to use filters for changing the icon's color
icon.setIsMask(True)
else:
icon = QIcon(":/logo.png")

Expand Down
2 changes: 1 addition & 1 deletion media
Loading

0 comments on commit 0a359bd

Please sign in to comment.