From: Ed Page Date: Tue, 8 Jun 2010 22:47:05 +0000 (-0500) Subject: Pulling in things from Gonvert work X-Git-Url: http://git.maemo.org/git/?p=gc-dialer;a=commitdiff_plain;h=c6654b4c289b2b3e05795cff8e4accc3a32b8bca Pulling in things from Gonvert work --- diff --git a/Makefile b/Makefile index 389b948..6b80980 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,6 @@ package: $(OBJ) cp $(SOURCE_PATH)/$(PROJECT_NAME).py $(BUILD_PATH)/generic $(foreach file, $(DATA), cp $(file) $(BUILD_PATH)/generic/$(subst /,-,$(file)) ; ) $(foreach file, $(SOURCE), cp $(file) $(BUILD_PATH)/generic/$(subst /,-,$(file)) ; ) - #$(foreach file, $(OBJ), cp $(file) $(BUILD_PATH)/generic/$(subst /,-,$(file)) ; ) cp support/$(PROJECT_NAME).desktop $(BUILD_PATH)/generic cp support/icons/hicolor/26x26/hildon/$(PROJECT_NAME).png $(BUILD_PATH)/generic/26x26-$(PROJECT_NAME).png cp support/icons/hicolor/64x64/hildon/$(PROJECT_NAME).png $(BUILD_PATH)/generic/64x64-$(PROJECT_NAME).png diff --git a/src/REPLACEME_qt.py b/src/REPLACEME_qt.py new file mode 100755 index 0000000..a66596e --- /dev/null +++ b/src/REPLACEME_qt.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python +# -*- coding: UTF8 -*- + +from __future__ import with_statement + +import sys +import os +import simplejson +import logging + +from PyQt4 import QtGui +from PyQt4 import QtCore + +import constants +import maeqt +from util import misc as misc_utils +import unit_data + + +_moduleLogger = logging.getLogger(__name__) + + +IS_MAEMO = True + + +class REPLACEME(object): + + _DATA_PATHS = [ + os.path.dirname(__file__), + os.path.join(os.path.dirname(__file__), "../data"), + os.path.join(os.path.dirname(__file__), "../lib"), + '/usr/share/%s' % constants.__app_name__, + '/usr/lib/%s' % constants.__app_name__, + ] + + def __init__(self, app): + self._dataPath = "" + for dataPath in self._DATA_PATHS: + appIconPath = os.path.join(dataPath, "pixmaps", "%s.png" % constants.__app_name__) + if os.path.isfile(appIconPath): + self._dataPath = dataPath + break + else: + raise RuntimeError("UI Descriptor not found!") + self._app = app + self._appIconPath = appIconPath + self._recent = [] + self._hiddenCategories = set() + self._hiddenUnits = {} + self._clipboard = QtGui.QApplication.clipboard() + + self._mainWindow = None + + self._fullscreenAction = QtGui.QAction(None) + self._fullscreenAction.setText("Fullscreen") + self._fullscreenAction.setCheckable(True) + self._fullscreenAction.setShortcut(QtGui.QKeySequence("CTRL+Enter")) + self._fullscreenAction.toggled.connect(self._on_toggle_fullscreen) + + self._logAction = QtGui.QAction(None) + self._logAction.setText("Log") + self._logAction.setShortcut(QtGui.QKeySequence("CTRL+l")) + self._logAction.triggered.connect(self._on_log) + + self._quitAction = QtGui.QAction(None) + self._quitAction.setText("Quit") + self._quitAction.setShortcut(QtGui.QKeySequence("CTRL+q")) + self._quitAction.triggered.connect(self._on_quit) + + self._app.lastWindowClosed.connect(self._on_app_quit) + self.load_settings() + + def load_settings(self): + try: + with open(constants._user_settings_, "r") as settingsFile: + settings = simplejson.load(settingsFile) + except IOError, e: + _moduleLogger.info("No settings") + settings = {} + except ValueError: + _moduleLogger.info("Settings were corrupt") + settings = {} + + self._fullscreenAction.setChecked(settings.get("isFullScreen", False)) + + def save_settings(self): + settings = { + "isFullScreen": self._fullscreenAction.isChecked(), + } + with open(constants._user_settings_, "w") as settingsFile: + simplejson.dump(settings, settingsFile) + + @property + def appIconPath(self): + return self._appIconPath + + @property + def fullscreenAction(self): + return self._fullscreenAction + + @property + def logAction(self): + return self._logAction + + @property + def quitAction(self): + return self._quitAction + + def _close_windows(self): + if self._mainWindow is not None: + self._mainWindow.window.destroyed.disconnect(self._on_child_close) + self._mainWindow.close() + self._mainWindow = None + + @misc_utils.log_exception(_moduleLogger) + def _on_app_quit(self, checked = False): + self.save_settings() + + @misc_utils.log_exception(_moduleLogger) + def _on_child_close(self, obj = None): + self._mainWindow = None + + @misc_utils.log_exception(_moduleLogger) + def _on_toggle_fullscreen(self, checked = False): + for window in self._walk_children(): + window.set_fullscreen(checked) + + @misc_utils.log_exception(_moduleLogger) + def _on_log(self, checked = False): + with open(constants._user_logpath_, "r") as f: + logLines = f.xreadlines() + log = "".join(logLines) + self._clipboard.setText(log) + + @misc_utils.log_exception(_moduleLogger) + def _on_quit(self, checked = False): + self._close_windows() + + +class MainWindow(object): + + def __init__(self, parent, app): + self._app = app + + self._layout = QtGui.QVBoxLayout() + + centralWidget = QtGui.QWidget() + centralWidget.setLayout(self._layout) + + self._window = QtGui.QMainWindow(parent) + self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True) + maeqt.set_autorient(self._window, True) + maeqt.set_stackable(self._window, True) + self._window.setWindowTitle("%s" % constants.__pretty_app_name__) + self._window.setWindowIcon(QtGui.QIcon(self._app.appIconPath)) + self._window.setCentralWidget(centralWidget) + + self._closeWindowAction = QtGui.QAction(None) + self._closeWindowAction.setText("Close") + self._closeWindowAction.setShortcut(QtGui.QKeySequence("CTRL+w")) + self._closeWindowAction.triggered.connect(self._on_close_window) + + if IS_MAEMO: + fileMenu = self._window.menuBar().addMenu("&File") + + viewMenu = self._window.menuBar().addMenu("&View") + + self._window.addAction(self._closeWindowAction) + self._window.addAction(self._app.quitAction) + self._window.addAction(self._app.fullscreenAction) + else: + fileMenu = self._window.menuBar().addMenu("&Units") + fileMenu.addAction(self._closeWindowAction) + fileMenu.addAction(self._app.quitAction) + + viewMenu = self._window.menuBar().addMenu("&View") + viewMenu.addAction(self._app.fullscreenAction) + + self._window.addAction(self._app.logAction) + + self.set_fullscreen(self._app.fullscreenAction.isChecked()) + self._window.show() + + @property + def window(self): + return self._window + + def walk_children(self): + return () + + def show(self): + self._window.show() + for child in self.walk_children(): + child.show() + + def hide(self): + for child in self.walk_children(): + child.hide() + self._window.hide() + + def close(self): + for child in self.walk_children(): + child.window.destroyed.disconnect(self._on_child_close) + child.close() + self._window.close() + + def set_fullscreen(self, isFullscreen): + if isFullscreen: + self._window.showFullScreen() + else: + self._window.showNormal() + for child in self.walk_children(): + child.set_fullscreen(isFullscreen) + + @misc_utils.log_exception(_moduleLogger) + def _on_close_window(self, checked = True): + self.close() + + +def run(): + app = QtGui.QApplication([]) + handle = REPLACEME(app) + return app.exec_() + + +if __name__ == "__main__": + logging.basicConfig(level = logging.DEBUG) + try: + os.makedirs(constants._data_path_) + except OSError, e: + if e.errno != 17: + raise + + val = run() + sys.exit(val) diff --git a/src/gtk_toolbox.py b/src/gtk_toolbox.py index 784c871..f687e6b 100644 --- a/src/gtk_toolbox.py +++ b/src/gtk_toolbox.py @@ -567,7 +567,202 @@ class PopupCalendar(object): _moduleLogger.exception(e) +class QuickAddView(object): + + def __init__(self, widgetTree, errorDisplay, signalSink, prefix): + self._errorDisplay = errorDisplay + self._manager = None + self._signalSink = signalSink + + self._clipboard = gtk.clipboard_get() + + self._taskNameEntry = widgetTree.get_widget(prefix+"-nameEntry") + self._addTaskButton = widgetTree.get_widget(prefix+"-addButton") + self._pasteTaskNameButton = widgetTree.get_widget(prefix+"-pasteNameButton") + self._clearTaskNameButton = widgetTree.get_widget(prefix+"-clearNameButton") + self._onAddId = None + self._onAddClickedId = None + self._onAddReleasedId = None + self._addToEditTimerId = None + self._onClearId = None + self._onPasteId = None + + def enable(self, manager): + self._manager = manager + + self._onAddId = self._addTaskButton.connect("clicked", self._on_add) + self._onAddClickedId = self._addTaskButton.connect("pressed", self._on_add_pressed) + self._onAddReleasedId = self._addTaskButton.connect("released", self._on_add_released) + self._onPasteId = self._pasteTaskNameButton.connect("clicked", self._on_paste) + self._onClearId = self._clearTaskNameButton.connect("clicked", self._on_clear) + + def disable(self): + self._manager = None + + self._addTaskButton.disconnect(self._onAddId) + self._addTaskButton.disconnect(self._onAddClickedId) + self._addTaskButton.disconnect(self._onAddReleasedId) + self._pasteTaskNameButton.disconnect(self._onPasteId) + self._clearTaskNameButton.disconnect(self._onClearId) + + def set_addability(self, addability): + self._addTaskButton.set_sensitive(addability) + + def _on_add(self, *args): + try: + name = self._taskNameEntry.get_text() + self._taskNameEntry.set_text("") + + self._signalSink.stage.send(("add", name)) + except Exception, e: + self._errorDisplay.push_exception() + + def _on_add_edit(self, *args): + try: + name = self._taskNameEntry.get_text() + self._taskNameEntry.set_text("") + + self._signalSink.stage.send(("add-edit", name)) + except Exception, e: + self._errorDisplay.push_exception() + + def _on_add_pressed(self, widget): + try: + self._addToEditTimerId = gobject.timeout_add(1000, self._on_add_edit) + except Exception, e: + self._errorDisplay.push_exception() + + def _on_add_released(self, widget): + try: + if self._addToEditTimerId is not None: + gobject.source_remove(self._addToEditTimerId) + self._addToEditTimerId = None + except Exception, e: + self._errorDisplay.push_exception() + + def _on_paste(self, *args): + try: + entry = self._taskNameEntry.get_text() + addedText = self._clipboard.wait_for_text() + if addedText: + entry += addedText + self._taskNameEntry.set_text(entry) + except Exception, e: + self._errorDisplay.push_exception() + + def _on_clear(self, *args): + try: + self._taskNameEntry.set_text("") + except Exception, e: + self._errorDisplay.push_exception() + + +class TapOrHold(object): + + def __init__(self, widget): + self._widget = widget + self._isTap = True + self._isPointerInside = True + self._holdTimeoutId = None + self._tapTimeoutId = None + self._taps = 0 + + self._bpeId = None + self._breId = None + self._eneId = None + self._lneId = None + + def enable(self): + self._bpeId = self._widget.connect("button-press-event", self._on_button_press) + self._breId = self._widget.connect("button-release-event", self._on_button_release) + self._eneId = self._widget.connect("enter-notify-event", self._on_enter) + self._lneId = self._widget.connect("leave-notify-event", self._on_leave) + + def disable(self): + self._widget.disconnect(self._bpeId) + self._widget.disconnect(self._breId) + self._widget.disconnect(self._eneId) + self._widget.disconnect(self._lneId) + + def on_tap(self, taps): + print "TAP", taps + + def on_hold(self, taps): + print "HOLD", taps + + def on_holding(self): + print "HOLDING" + + def on_cancel(self): + print "CANCEL" + + def _on_button_press(self, *args): + # Hack to handle weird notebook behavior + self._isPointerInside = True + self._isTap = True + + if self._tapTimeoutId is not None: + gobject.source_remove(self._tapTimeoutId) + self._tapTimeoutId = None + + # Handle double taps + if self._holdTimeoutId is None: + self._tapTimeoutId = None + + self._taps = 1 + self._holdTimeoutId = gobject.timeout_add(1000, self._on_hold_timeout) + else: + self._taps = 2 + + def _on_button_release(self, *args): + assert self._tapTimeoutId is None + # Handle release after timeout if user hasn't double-clicked + self._tapTimeoutId = gobject.timeout_add(100, self._on_tap_timeout) + + def _on_actual_press(self, *args): + if self._holdTimeoutId is not None: + gobject.source_remove(self._holdTimeoutId) + self._holdTimeoutId = None + + if self._isPointerInside: + if self._isTap: + self.on_tap(self._taps) + else: + self.on_hold(self._taps) + else: + self.on_cancel() + + def _on_tap_timeout(self, *args): + self._tapTimeoutId = None + self._on_actual_press() + return False + + def _on_hold_timeout(self, *args): + self._holdTimeoutId = None + self._isTap = False + self.on_holding() + return False + + def _on_enter(self, *args): + self._isPointerInside = True + + def _on_leave(self, *args): + self._isPointerInside = False + + if __name__ == "__main__": + if True: + win = gtk.Window() + win.set_title("Tap'N'Hold") + eventBox = gtk.EventBox() + win.add(eventBox) + + context = ContextHandler(eventBox, coroutines.printer_sink()) + context.enable() + win.connect("destroy", lambda w: gtk.main_quit()) + + win.show_all() + if False: import datetime cal = PopupCalendar(None, datetime.datetime.now()) diff --git a/src/maeqt.py b/src/maeqt.py new file mode 100644 index 0000000..d61c669 --- /dev/null +++ b/src/maeqt.py @@ -0,0 +1,91 @@ +from PyQt4 import QtCore + + +def _null_set_stackable(window, isStackable): + pass + + +def _maemo_set_stackable(window, isStackable): + window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable) + + +try: + QtCore.Qt.WA_Maemo5StackedWindow + set_stackable = _maemo_set_stackable +except AttributeError: + set_stackable = _null_set_stackable + + +def _null_set_autorient(window, isStackable): + pass + + +def _maemo_set_autorient(window, isStackable): + window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable) + + +try: + QtCore.Qt.WA_Maemo5AutoOrientation + set_autorient = _maemo_set_autorient +except AttributeError: + set_autorient = _null_set_autorient + + +def _null_set_landscape(window, isStackable): + pass + + +def _maemo_set_landscape(window, isStackable): + window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable) + + +try: + QtCore.Qt.WA_Maemo5LandscapeOrientation + set_landscape = _maemo_set_landscape +except AttributeError: + set_landscape = _null_set_landscape + + +def _null_set_portrait(window, isStackable): + pass + + +def _maemo_set_portrait(window, isStackable): + window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable) + + +try: + QtCore.Qt.WA_Maemo5PortraitOrientation + set_portrait = _maemo_set_portrait +except AttributeError: + set_portrait = _null_set_portrait + + +def _null_show_progress_indicator(window, isStackable): + pass + + +def _maemo_show_progress_indicator(window, isStackable): + window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable) + + +try: + QtCore.Qt.WA_Maemo5ShowProgressIndicator + show_progress_indicator = _maemo_show_progress_indicator +except AttributeError: + show_progress_indicator = _null_show_progress_indicator + + +def _null_mark_numbers_preferred(widget): + pass + + +def _newqt_mark_numbers_preferred(widget): + widget.setInputMethodHints(QtCore.Qt.ImhPreferNumbers) + + +try: + QtCore.Qt.ImhPreferNumbers + mark_numbers_preferred = _newqt_mark_numbers_preferred +except AttributeError: + mark_numbers_preferred = _null_mark_numbers_preferred diff --git a/support/builddeb.py b/support/builddeb.py index 84c17d3..04fd6e2 100755 --- a/support/builddeb.py +++ b/support/builddeb.py @@ -29,6 +29,10 @@ REPLACEME __postinstall__ = """#!/bin/sh -e gtk-update-icon-cache -f /usr/share/icons/hicolor +rm -f ~/.REPLACEME/REPLACEME.log +""" + +__preremove__ = """#!/bin/sh -e """ @@ -62,8 +66,7 @@ def build_package(distribution): p = py2deb.Py2deb(__appname__) p.prettyName = constants.__pretty_app_name__ p.description = __description__ - p.bugTracker = "" - p.upgradeDescription = __changelog__.split("\n\n", 1)[0] + p.bugTracker = "REPLACEME" p.author = __author__ p.mail = __email__ p.license = "lgpl" @@ -92,14 +95,15 @@ def build_package(distribution): p.repository = "extras" p.changelog = __changelog__ p.postinstall = __postinstall__ + p.preremove = __preremove__ p.icon = { "debian": "REPLACEME", "diablo": "REPLACEME", "fremantle": "REPLACEME", # Fremantle natively uses 48x48 }[distribution] - p["/usr/bin"] = [ "REPLACEME" ] - for relPath, files in unflatten_files(find_files(".")).iteritems(): - fullPath = "" + p["/opt/REPLACEME/bin"] = [ "REPLACEME" ] + for relPath, files in unflatten_files(find_files("src", ".")).iteritems(): + fullPath = "/opt/REPLACEME/lib" if relPath: fullPath += os.sep+relPath p[fullPath] = list(