Merge branch 'master' of repos.ctdo.de:psychose
|
@ -15,17 +15,17 @@ set -g terminal-overrides 'xterm*:smcup@:rmcup@'
|
||||||
new-session -s 'csession'
|
new-session -s 'csession'
|
||||||
attach-session -t 'csession'
|
attach-session -t 'csession'
|
||||||
|
|
||||||
new-window -n 'socat-ekg-merle' -t 'csession:3' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-merle-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ekg2osc-merle-out,b115200,user=stefan'
|
new-window -n 'socat-ekg-merle' -t 'csession:3' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-merle-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ekg2osc-merle-out,b115200,user=sarah'
|
||||||
new-window -n 'socat-ekg-uwe' -t 'csession:4' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-uwe-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ekg2osc-uwe-out,b115200,user=stefan'
|
new-window -n 'socat-ekg-uwe' -t 'csession:4' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-uwe-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ekg2osc-uwe-out,b115200,user=sarah'
|
||||||
new-window -n 'socat-ekg-bjoern' -t 'csession:2' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-bjoern-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ekg2osc-bjoern-out,b115200,user=stefan'
|
new-window -n 'socat-ekg-bjoern' -t 'csession:2' 'socat -d -d PTY,raw,echo=0,link=/tmp/ekg2osc-bjoern-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ekg2osc-bjoern-out,b115200,user=sarah'
|
||||||
|
|
||||||
new-window -n 'socat-pulse-merle' -t 'csession:6' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-merle-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/pulse2osc-merle-out,b115200,user=stefan'
|
new-window -n 'socat-pulse-merle' -t 'csession:6' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-merle-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/pulse2osc-merle-out,b115200,user=sarah'
|
||||||
new-window -n 'socat-pulse-uwe' -t 'csession:7' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-uwe-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/pulse2osc-uwe-out,b115200,user=stefan'
|
new-window -n 'socat-pulse-uwe' -t 'csession:7' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-uwe-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/pulse2osc-uwe-out,b115200,user=sarah'
|
||||||
new-window -n 'socat-pulse-bjoern' -t 'csession:5' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-bjoern-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/pulse2osc-bjoern-out,b115200,user=stefan'
|
new-window -n 'socat-pulse-bjoern' -t 'csession:5' 'socat -d -d PTY,raw,echo=0,link=/tmp/pulse2osc-bjoern-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/pulse2osc-bjoern-out,b115200,user=sarah'
|
||||||
|
|
||||||
new-window -n 'socat-ehealth-merle' -t 'csession:9' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-merle-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ehealth2osc-merle-out,b115200,user=stefan'
|
new-window -n 'socat-ehealth-merle' -t 'csession:9' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-merle-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ehealth2osc-merle-out,b115200,user=sarah'
|
||||||
new-window -n 'socat-ehealth-uwe' -t 'csession:10' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-uwe-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ehealth2osc-uwe-out,b115200,user=stefan'
|
new-window -n 'socat-ehealth-uwe' -t 'csession:10' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-uwe-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ehealth2osc-uwe-out,b115200,user=sarah'
|
||||||
new-window -n 'socat-ehealth-bjoern' -t 'csession:8' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-bjoern-in,b115200,user=stefan PTY,raw,echo=0,link=/tmp/ehealth2osc-bjoern-out,b115200,user=stefan'
|
new-window -n 'socat-ehealth-bjoern' -t 'csession:8' 'socat -d -d PTY,raw,echo=0,link=/tmp/ehealth2osc-bjoern-in,b115200,user=sarah PTY,raw,echo=0,link=/tmp/ehealth2osc-bjoern-out,b115200,user=sarah'
|
||||||
|
|
||||||
new-window -n 'ekg2osc-merle' -t 'csession:11' 'ekgmerle -D /tmp/ekg2osc-merle-out'
|
new-window -n 'ekg2osc-merle' -t 'csession:11' 'ekgmerle -D /tmp/ekg2osc-merle-out'
|
||||||
new-window -n 'ekg2osc-uwe' -t 'csession:12' 'ekguwe -D /tmp/ekg2osc-uwe-out'
|
new-window -n 'ekg2osc-uwe' -t 'csession:12' 'ekguwe -D /tmp/ekg2osc-uwe-out'
|
||||||
|
@ -39,17 +39,17 @@ new-window -n 'ehealth2osc-merle' -t 'csession:17' 'sleep 1 && ehealthmerle -
|
||||||
new-window -n 'ehealth2osc-uwe' -t 'csession:18' 'sleep 1 && ehealthuwe -D /tmp/ehealth2osc-uwe-out'
|
new-window -n 'ehealth2osc-uwe' -t 'csession:18' 'sleep 1 && ehealthuwe -D /tmp/ehealth2osc-uwe-out'
|
||||||
new-window -n 'ehealth2osc-bjoern' -t 'csession:19' 'sleep 1 && ehealthbjoern -D /tmp/ehealth2osc-bjoern-out'
|
new-window -n 'ehealth2osc-bjoern' -t 'csession:19' 'sleep 1 && ehealthbjoern -D /tmp/ehealth2osc-bjoern-out'
|
||||||
|
|
||||||
new-window -n 'test-ekg-merle' -t 'csession:21' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-merle-in'
|
new-window -n 'test-ekg-merle' -t 'csession:21' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-merle-in'
|
||||||
new-window -n 'test-ekg-uwe' -t 'csession:22' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-uwe-in'
|
new-window -n 'test-ekg-uwe' -t 'csession:22' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-uwe-in'
|
||||||
new-window -n 'test-ekg-bjoern' -t 'csession:20' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-bjoern-in'
|
new-window -n 'test-ekg-bjoern' -t 'csession:20' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ekg_test.py /tmp/ekg2osc-bjoern-in'
|
||||||
|
|
||||||
new-window -n 'test-pulse-merle' -t 'csession:24' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-merle-in'
|
new-window -n 'test-pulse-merle' -t 'csession:24' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-merle-in'
|
||||||
new-window -n 'test-pulse-uwe' -t 'csession:25' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-uwe-in'
|
new-window -n 'test-pulse-uwe' -t 'csession:25' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-uwe-in'
|
||||||
new-window -n 'test-pulse-bjoern' -t 'csession:23' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-bjoern-in'
|
new-window -n 'test-pulse-bjoern' -t 'csession:23' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_pulse_test.py /tmp/pulse2osc-bjoern-in'
|
||||||
|
|
||||||
new-window -n 'test-ehealth-merle' -t 'csession:27' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-merle-in'
|
new-window -n 'test-ehealth-merle' -t 'csession:27' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-merle-in'
|
||||||
new-window -n 'test-ehealth-uwe' -t 'csession:28' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-uwe-in'
|
new-window -n 'test-ehealth-uwe' -t 'csession:28' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-uwe-in'
|
||||||
new-window -n 'test-ehealth-bjoern' -t 'csession:26' 'python /home/stefan/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-bjoern-in'
|
new-window -n 'test-ehealth-bjoern' -t 'csession:26' 'python /home/sarah/dev/psychose/sensors2osc/sensors2osc/socat_ehealth_test.py /tmp/ehealth2osc-bjoern-in'
|
||||||
|
|
||||||
select-window -t 'csession:2'
|
select-window -t 'csession:2'
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,28 @@
|
||||||
<height>606</height>
|
<height>606</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Monospace</family>
|
||||||
|
<pointsize>14</pointsize>
|
||||||
|
<italic>true</italic>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGraphicsView" name="graphics_view">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>785</width>
|
||||||
|
<height>580</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="palette">
|
<property name="palette">
|
||||||
<palette>
|
<palette>
|
||||||
<active>
|
<active>
|
||||||
|
@ -425,61 +447,13 @@
|
||||||
</disabled>
|
</disabled>
|
||||||
</palette>
|
</palette>
|
||||||
</property>
|
</property>
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Monospace</family>
|
|
||||||
<pointsize>14</pointsize>
|
|
||||||
<italic>true</italic>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>MainWindow</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="centralwidget">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QGraphicsView" name="graphics_view">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>785</width>
|
|
||||||
<height>580</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="autoFillBackground">
|
<property name="autoFillBackground">
|
||||||
<bool>true</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>4</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'dump_grabber.ui'
|
# Form implementation generated from reading ui file 'dump_grabber.ui'
|
||||||
#
|
#
|
||||||
# Created: Wed Apr 16 22:18:59 2014
|
# Created: Tue May 13 06:55:09 2014
|
||||||
# by: PyQt4 UI code generator 4.10.3
|
# by: PyQt4 UI code generator 4.10.3
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -27,6 +27,19 @@ class Ui_MainWindow(object):
|
||||||
def setupUi(self, MainWindow):
|
def setupUi(self, MainWindow):
|
||||||
MainWindow.setObjectName(_fromUtf8("MainWindow"))
|
MainWindow.setObjectName(_fromUtf8("MainWindow"))
|
||||||
MainWindow.resize(811, 606)
|
MainWindow.resize(811, 606)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Monospace"))
|
||||||
|
font.setPointSize(14)
|
||||||
|
font.setItalic(True)
|
||||||
|
MainWindow.setFont(font)
|
||||||
|
self.centralwidget = QtGui.QWidget(MainWindow)
|
||||||
|
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
|
||||||
|
self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
|
||||||
|
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
||||||
|
self.horizontalLayout = QtGui.QHBoxLayout()
|
||||||
|
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
||||||
|
self.graphics_view = QtGui.QGraphicsView(self.centralwidget)
|
||||||
|
self.graphics_view.setMinimumSize(QtCore.QSize(785, 580))
|
||||||
palette = QtGui.QPalette()
|
palette = QtGui.QPalette()
|
||||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
|
@ -163,23 +176,11 @@ class Ui_MainWindow(object):
|
||||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText, brush)
|
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText, brush)
|
||||||
MainWindow.setPalette(palette)
|
self.graphics_view.setPalette(palette)
|
||||||
self.centralwidget = QtGui.QWidget(MainWindow)
|
self.graphics_view.setAutoFillBackground(False)
|
||||||
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
|
|
||||||
self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
|
|
||||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
|
||||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
|
||||||
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
|
||||||
self.graphics_view = QtGui.QGraphicsView(self.centralwidget)
|
|
||||||
self.graphics_view.setMinimumSize(QtCore.QSize(785, 580))
|
|
||||||
self.graphics_view.setAutoFillBackground(True)
|
|
||||||
self.graphics_view.setObjectName(_fromUtf8("graphics_view"))
|
self.graphics_view.setObjectName(_fromUtf8("graphics_view"))
|
||||||
self.horizontalLayout.addWidget(self.graphics_view)
|
self.horizontalLayout.addWidget(self.graphics_view)
|
||||||
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
|
|
||||||
self.horizontalLayout.addItem(spacerItem)
|
|
||||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||||
spacerItem1 = QtGui.QSpacerItem(20, 4, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
|
||||||
self.verticalLayout.addItem(spacerItem1)
|
|
||||||
MainWindow.setCentralWidget(self.centralwidget)
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
|
|
||||||
self.retranslateUi(MainWindow)
|
self.retranslateUi(MainWindow)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="icon" type="image/png" href="/icon.png" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="/texter_%d.mjpeg" alt="Smiley face" />
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,7 +1,6 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
# This file is part of chaosc and psychosis
|
# This file is part of chaosc and psychosis
|
||||||
#
|
#
|
||||||
# chaosc is free software: you can redistribute it and/or modify
|
# chaosc is free software: you can redistribute it and/or modify
|
||||||
|
@ -21,116 +20,92 @@
|
||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import Queue
|
|
||||||
import re
|
import re
|
||||||
import select
|
import signal
|
||||||
import socket
|
|
||||||
import sys
|
import sys
|
||||||
import threading
|
from collections import deque
|
||||||
import time
|
|
||||||
|
|
||||||
from datetime import datetime
|
from chaosc.argparser_groups import ArgParser
|
||||||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
|
||||||
from chaosc.argparser_groups import *
|
|
||||||
from chaosc.lib import logger, resolve_host
|
from chaosc.lib import logger, resolve_host
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
|
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
|
||||||
|
from PyQt4.QtGui import QPixmap, QPainter
|
||||||
|
from PyQt4.QtNetwork import QHostAddress
|
||||||
|
|
||||||
from dump_grabber.dump_grabber_ui import Ui_MainWindow
|
from dump_grabber.dump_grabber_ui import Ui_MainWindow
|
||||||
|
from psylib.mjpeg_streaming_server import (MjpegStreamingServer,
|
||||||
|
MjpegStreamingConsumerInterface)
|
||||||
|
from psylib.psyqt_base import PsyQtChaoscClientBase
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from chaosc.c_osc_lib import OSCMessage, decode_osc
|
from chaosc.c_osc_lib import OSCMessage, decode_osc
|
||||||
except ImportError as e:
|
except ImportError:
|
||||||
from chaosc.osc_lib import OSCMessage, decode_osc
|
from chaosc.osc_lib import OSCMessage, decode_osc
|
||||||
|
|
||||||
app = QtGui.QApplication([])
|
QTAPP = QtGui.QApplication([])
|
||||||
|
|
||||||
class TextStorage(object):
|
class ExclusiveTextStorage(object):
|
||||||
def __init__(self, columns):
|
"""Stores the text representation of per actor osc messages"""
|
||||||
super(TextStorage, self).__init__()
|
|
||||||
self.column_count = columns
|
|
||||||
self.colors = (QtCore.Qt.red, QtCore.Qt.green, QtGui.QColor(46, 100, 254))
|
|
||||||
|
|
||||||
def init_columns(self):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def add_text(self, column, text):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
|
|
||||||
class ColumnTextStorage(TextStorage):
|
|
||||||
def __init__(self, columns, default_font, column_width, line_height, scene):
|
def __init__(self, columns, default_font, column_width, line_height, scene):
|
||||||
super(ColumnTextStorage, self).__init__(columns)
|
self.column_count = columns
|
||||||
self.columns = list()
|
self.colors = (
|
||||||
|
QtCore.Qt.red, QtCore.Qt.green, QtGui.QColor(46, 100, 254))
|
||||||
|
self.lines = deque()
|
||||||
self.default_font = default_font
|
self.default_font = default_font
|
||||||
self.column_width = column_width
|
self.column_width = column_width
|
||||||
self.line_height = line_height
|
self.line_height = line_height
|
||||||
self.graphics_scene = scene
|
self.graphics_scene = scene
|
||||||
self.num_lines, self.offset = divmod(775, self.line_height)
|
self.num_lines, self.offset = divmod(576, self.line_height)
|
||||||
|
self.data = deque()
|
||||||
def init_columns(self):
|
|
||||||
for x in range(self.column_count):
|
|
||||||
column = list()
|
|
||||||
color = self.colors[x]
|
|
||||||
for y in range(self.num_lines):
|
|
||||||
text_item = self.graphics_scene.addSimpleText("%d:%d" % (x, y), self.default_font)
|
|
||||||
text_item.setBrush(color)
|
|
||||||
text_item.setPos(x * self.column_width, y * self.line_height)
|
|
||||||
column.append(text_item)
|
|
||||||
self.columns.append(column)
|
|
||||||
|
|
||||||
def add_text(self, column, text):
|
|
||||||
text_item = self.graphics_scene.addSimpleText(text, self.default_font)
|
|
||||||
color = self.colors[column]
|
|
||||||
text_item.setBrush(color)
|
|
||||||
|
|
||||||
old_item = self.columns[column].pop(0)
|
|
||||||
self.graphics_scene.removeItem(old_item)
|
|
||||||
self.columns[column].append(text_item)
|
|
||||||
for iy, text_item in enumerate(self.columns[column]):
|
|
||||||
text_item.setPos(column * self.column_width, iy * self.line_height)
|
|
||||||
|
|
||||||
|
|
||||||
class ExclusiveTextStorage(TextStorage):
|
|
||||||
def __init__(self, columns, default_font, column_width, line_height, scene):
|
|
||||||
super(ExclusiveTextStorage, self).__init__(columns)
|
|
||||||
self.column_count = columns
|
|
||||||
self.lines = list()
|
|
||||||
self.default_font = default_font
|
|
||||||
self.column_width = column_width
|
|
||||||
self.line_height = line_height
|
|
||||||
self.graphics_scene = scene
|
|
||||||
self.num_lines, self.offset = divmod(775, self.line_height)
|
|
||||||
|
|
||||||
def init_columns(self):
|
def init_columns(self):
|
||||||
color = self.colors[0]
|
color = self.colors[0]
|
||||||
for y in range(self.num_lines):
|
for line_index in range(self.num_lines):
|
||||||
text_item = self.graphics_scene.addSimpleText("", self.default_font)
|
text_item = self.graphics_scene.addSimpleText("", self.default_font)
|
||||||
text_item.setBrush(color)
|
text_item.setBrush(color)
|
||||||
text_item.setPos(0, y * self.line_height)
|
text_item.setPos(0, line_index * self.line_height)
|
||||||
self.lines.append(text_item)
|
self.lines.append(text_item)
|
||||||
|
|
||||||
def add_text(self, column, text):
|
def __add_text(self, column, text):
|
||||||
text_item = self.graphics_scene.addSimpleText(text, self.default_font)
|
text_item = self.graphics_scene.addSimpleText(text, self.default_font)
|
||||||
text_item.setX(column * self.column_width)
|
text_item.setX(column * self.column_width)
|
||||||
color = self.colors[column]
|
text_item.setBrush(self.colors[column])
|
||||||
text_item.setBrush(color)
|
old_item = self.lines.popleft()
|
||||||
|
|
||||||
old_item = self.lines.pop(0)
|
|
||||||
self.graphics_scene.removeItem(old_item)
|
self.graphics_scene.removeItem(old_item)
|
||||||
self.lines.append(text_item)
|
self.lines.append(text_item)
|
||||||
for iy, text_item in enumerate(self.lines):
|
|
||||||
text_item.setY(iy * self.line_height)
|
def finish(self):
|
||||||
|
for column, text in self.data:
|
||||||
|
self.__add_text(column, text)
|
||||||
|
self.data.clear()
|
||||||
|
|
||||||
|
for text_index, text_item in enumerate(self.lines):
|
||||||
|
text_item.setY(text_index * self.line_height)
|
||||||
|
|
||||||
|
def add_text(self, column, text):
|
||||||
|
self.data.append((column, text))
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
class MainWindow(QtGui.QMainWindow, Ui_MainWindow,
|
||||||
def __init__(self, parent=None, columns=3, column_exclusive=False):
|
MjpegStreamingConsumerInterface, PsyQtChaoscClientBase):
|
||||||
super(MainWindow, self).__init__(parent)
|
|
||||||
|
"""This app receives per actor osc messages and provides an mjpeg stream
|
||||||
|
with colored text representation arranged in columns"""
|
||||||
|
|
||||||
|
def __init__(self, args, parent=None):
|
||||||
|
self.args = args
|
||||||
|
super(MainWindow, self).__init__()
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.graphics_view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
self.http_server = MjpegStreamingServer(
|
||||||
self.graphics_view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
(args.http_host, args.http_port), self)
|
||||||
|
self.http_server.listen(port=args.http_port)
|
||||||
|
self.graphics_view.setHorizontalScrollBarPolicy(
|
||||||
|
QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
|
self.graphics_view.setVerticalScrollBarPolicy(
|
||||||
|
QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
self.graphics_view.setRenderHint(QtGui.QPainter.Antialiasing, True)
|
self.graphics_view.setRenderHint(QtGui.QPainter.Antialiasing, True)
|
||||||
self.graphics_view.setFrameStyle(QtGui.QFrame.NoFrame)
|
self.graphics_view.setFrameStyle(QtGui.QFrame.NoFrame)
|
||||||
self.graphics_scene = QtGui.QGraphicsScene(self)
|
self.graphics_scene = QtGui.QGraphicsScene(self)
|
||||||
|
@ -140,178 +115,77 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||||
self.default_font.setStyleHint(QtGui.QFont.Monospace)
|
self.default_font.setStyleHint(QtGui.QFont.Monospace)
|
||||||
self.default_font.setBold(True)
|
self.default_font.setBold(True)
|
||||||
self.graphics_scene.setFont(self.default_font)
|
self.graphics_scene.setFont(self.default_font)
|
||||||
|
|
||||||
self.font_metrics = QtGui.QFontMetrics(self.default_font)
|
self.font_metrics = QtGui.QFontMetrics(self.default_font)
|
||||||
self.line_height = self.font_metrics.height()
|
self.line_height = self.font_metrics.height()
|
||||||
|
columns = 3
|
||||||
self.column_width = 775 / columns
|
self.column_width = 775 / columns
|
||||||
|
self.text_storage = ExclusiveTextStorage(columns, self.default_font,
|
||||||
self.text_storage = ExclusiveTextStorage(columns, self.default_font, self.column_width, self.line_height, self.graphics_scene)
|
self.column_width,
|
||||||
#self.text_storage = ColumnTextStorage(columns, self.default_font, self.column_width, self.line_height, self.graphics_scene)
|
self.line_height,
|
||||||
|
self.graphics_scene)
|
||||||
self.text_storage.init_columns()
|
self.text_storage.init_columns()
|
||||||
|
self.regex = re.compile("^/(uwe|merle|bjoern)/(.*?)$")
|
||||||
|
|
||||||
|
def pubdir(self):
|
||||||
|
return os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
msg = OSCMessage("/unsubscribe")
|
||||||
|
msg.appendTypedArg("localhost", "s")
|
||||||
|
msg.appendTypedArg(self.args.client_port, "i")
|
||||||
|
msg.appendTypedArg(self.args.authenticate, "s")
|
||||||
|
self.osc_sock.writeDatagram(
|
||||||
|
QByteArray(msg.encode_osc()), QHostAddress("127.0.0.1"), 7110)
|
||||||
|
|
||||||
|
def handle_osc_error(self, error):
|
||||||
|
logger.info("osc socket error %d", error)
|
||||||
|
|
||||||
def add_text(self, column, text):
|
def add_text(self, column, text):
|
||||||
self.text_storage.add_text(column, text)
|
self.text_storage.add_text(column, text)
|
||||||
|
|
||||||
def render(self):
|
def render_image(self):
|
||||||
image = QtGui.QImage(768, 576, QtGui.QImage.Format_ARGB32_Premultiplied)
|
self.text_storage.finish()
|
||||||
|
image = QPixmap(768, 576)
|
||||||
image.fill(QtCore.Qt.black)
|
image.fill(QtCore.Qt.black)
|
||||||
painter = QtGui.QPainter(image)
|
painter = QPainter(image)
|
||||||
painter.setRenderHints(QtGui.QPainter.RenderHint(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing), True)
|
painter.setRenderHints(QPainter.RenderHint(
|
||||||
|
QPainter.Antialiasing | QPainter.TextAntialiasing), True)
|
||||||
painter.setFont(self.default_font)
|
painter.setFont(self.default_font)
|
||||||
self.graphics_view.render(painter, target=QtCore.QRectF(0,0,768,576),source=QtCore.QRect(0,0,768,576))
|
self.graphics_view.render(
|
||||||
|
painter, target=QtCore.QRectF(0, 0, 768, 576),
|
||||||
|
source=QtCore.QRect(0, 0, 768, 576))
|
||||||
painter.end()
|
painter.end()
|
||||||
return image
|
buf = QBuffer()
|
||||||
|
buf.open(QIODevice.WriteOnly)
|
||||||
|
image.save(buf, "JPG", 100)
|
||||||
|
image_data = buf.data()
|
||||||
|
return image_data
|
||||||
|
|
||||||
|
def got_message(self):
|
||||||
class OSCThread(threading.Thread):
|
while self.osc_sock.hasPendingDatagrams():
|
||||||
def __init__(self, args):
|
data, address, port = self.osc_sock.readDatagram(
|
||||||
super(OSCThread, self).__init__()
|
self.osc_sock.pendingDatagramSize())
|
||||||
self.args = args
|
try:
|
||||||
self.running = True
|
osc_address, typetags, args = decode_osc(data, 0, len(data))
|
||||||
|
except ValueError:
|
||||||
self.client_address = resolve_host(args.client_host, args.client_port, args.address_family)
|
|
||||||
|
|
||||||
self.chaosc_address = chaosc_host, chaosc_port = resolve_host(args.chaosc_host, args.chaosc_port, args.address_family)
|
|
||||||
|
|
||||||
self.osc_sock = socket.socket(args.address_family, 2, 17)
|
|
||||||
self.osc_sock.bind(self.client_address)
|
|
||||||
self.osc_sock.setblocking(0)
|
|
||||||
|
|
||||||
logger.info("starting up osc receiver on '%s:%d'", self.client_address[0], self.client_address[1])
|
|
||||||
|
|
||||||
self.subscribe_me()
|
|
||||||
|
|
||||||
def subscribe_me(self):
|
|
||||||
logger.info("%s: subscribing to '%s:%d' with label %r", datetime.now().strftime("%x %X"), self.chaosc_address[0], self.chaosc_address[1], self.args.subscriber_label)
|
|
||||||
msg = OSCMessage("/subscribe")
|
|
||||||
msg.appendTypedArg(self.client_address[0], "s")
|
|
||||||
msg.appendTypedArg(self.client_address[1], "i")
|
|
||||||
msg.appendTypedArg(self.args.authenticate, "s")
|
|
||||||
if self.args.subscriber_label is not None:
|
|
||||||
msg.appendTypedArg(self.args.subscriber_label, "s")
|
|
||||||
self.osc_sock.sendto(msg.encode_osc(), self.chaosc_address)
|
|
||||||
|
|
||||||
|
|
||||||
def unsubscribe_me(self):
|
|
||||||
if self.args.keep_subscribed:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.info("unsubscribing from '%s:%d'", self.chaosc_address[0], self.chaosc_address[1])
|
|
||||||
msg = OSCMessage("/unsubscribe")
|
|
||||||
msg.appendTypedArg(self.client_address[0], "s")
|
|
||||||
msg.appendTypedArg(self.client_address[1], "i")
|
|
||||||
msg.appendTypedArg(self.args.authenticate, "s")
|
|
||||||
self.osc_sock.sendto(msg.encode_osc(), self.chaosc_address)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
|
|
||||||
while self.running:
|
|
||||||
try:
|
try:
|
||||||
reads, writes, errs = select.select([self.osc_sock], [], [], 0.01)
|
actor, text = self.regex.match(osc_address).groups()
|
||||||
except Exception, e:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if reads:
|
|
||||||
try:
|
|
||||||
osc_input, address = self.osc_sock.recvfrom(8192)
|
|
||||||
osc_address, typetags, messages = decode_osc(osc_input, 0, len(osc_input))
|
|
||||||
queue.put_nowait((osc_address, messages))
|
|
||||||
except Exception, e:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.unsubscribe_me()
|
|
||||||
logger.info("OSCThread is going down")
|
|
||||||
|
|
||||||
|
|
||||||
queue = Queue.Queue()
|
|
||||||
|
|
||||||
class MyHandler(BaseHTTPRequestHandler):
|
|
||||||
|
|
||||||
def do_GET(self):
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.path=re.sub('[^.a-zA-Z0-9]', "",str(self.path))
|
|
||||||
if self.path=="" or self.path==None or self.path[:1]==".":
|
|
||||||
self.send_error(403,'Forbidden')
|
|
||||||
|
|
||||||
if self.path.endswith(".html"):
|
|
||||||
directory = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
data = open(os.path.join(directory, self.path), "rb").read()
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header('Content-type', 'text/html')
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write(data)
|
|
||||||
elif self.path.endswith(".mjpeg"):
|
|
||||||
self.thread = thread = OSCThread(self.server.args)
|
|
||||||
thread.daemon = True
|
|
||||||
thread.start()
|
|
||||||
window = MainWindow()
|
|
||||||
window.hide()
|
|
||||||
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-Type", "multipart/x-mixed-replace; boundary=--aaboundary")
|
|
||||||
self.end_headers()
|
|
||||||
|
|
||||||
event_loop = QtCore.QEventLoop()
|
|
||||||
last_frame = time.time() - 1.
|
|
||||||
frame_rate = 16.0
|
|
||||||
frame_length = 1. / frame_rate
|
|
||||||
regex = re.compile("^/(uwe|merle|bjoern)/(.*?)$")
|
|
||||||
while 1:
|
|
||||||
event_loop.processEvents()
|
|
||||||
app.sendPostedEvents(None, 0)
|
|
||||||
while 1:
|
|
||||||
try:
|
|
||||||
osc_address, args = queue.get_nowait()
|
|
||||||
print osc_address
|
|
||||||
except Queue.Empty:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
actor, text = regex.match(osc_address).groups()
|
|
||||||
if actor == "merle":
|
|
||||||
window.add_text(0, "%s = %s" % (text, ", ".join([str(i) for i in args])))
|
|
||||||
if actor == "uwe":
|
|
||||||
window.add_text(1, "%s = %s" % (text, ", ".join([str(i) for i in args])))
|
|
||||||
if actor == "bjoern":
|
|
||||||
window.add_text(2, "%s = %s" % (text, ", ".join([str(i) for i in args])))
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
now = time.time()
|
|
||||||
delta = now - last_frame
|
|
||||||
if delta > frame_length:
|
|
||||||
last_frame = now
|
|
||||||
img = window.render()
|
|
||||||
buffer = QBuffer()
|
|
||||||
buffer.open(QIODevice.WriteOnly)
|
|
||||||
img.save(buffer, "JPG")
|
|
||||||
JpegData = buffer.data()
|
|
||||||
self.wfile.write("--aaboundary\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len(JpegData), JpegData))
|
|
||||||
JpegData = None
|
|
||||||
buffer = None
|
|
||||||
img = None
|
|
||||||
time.sleep(0.01)
|
|
||||||
return
|
|
||||||
except (KeyboardInterrupt, SystemError):
|
|
||||||
if hasattr(self, "thread") and self.thread is not None:
|
|
||||||
self.thread.running = False
|
|
||||||
self.thread.join()
|
|
||||||
self.thread = None
|
|
||||||
except IOError, e:
|
|
||||||
if e[0] in (32, 104):
|
|
||||||
if hasattr(self, "thread") and self.thread is not None:
|
|
||||||
self.thread.running = False
|
|
||||||
self.thread.join()
|
|
||||||
self.thread = None
|
|
||||||
else:
|
else:
|
||||||
pass
|
if text == "temperatur":
|
||||||
|
text += "e"
|
||||||
|
if actor == "merle":
|
||||||
class JustAHTTPServer(HTTPServer):
|
self.add_text(0, "%s = %s" % (
|
||||||
pass
|
text, ", ".join([str(i) for i in args])))
|
||||||
|
elif actor == "uwe":
|
||||||
|
self.add_text(1, "%s = %s" % (
|
||||||
|
text, ", ".join([str(i) for i in args])))
|
||||||
|
elif actor == "bjoern":
|
||||||
|
self.add_text(2, "%s = %s" % (
|
||||||
|
text, ", ".join([str(i) for i in args])))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -326,14 +200,16 @@ def main():
|
||||||
arg_parser.add_subscriber_group()
|
arg_parser.add_subscriber_group()
|
||||||
args = arg_parser.finalize()
|
args = arg_parser.finalize()
|
||||||
|
|
||||||
http_host, http_port = resolve_host(args.http_host, args.http_port, args.address_family)
|
args.http_host, args.http_port = resolve_host(
|
||||||
|
args.http_host, args.http_port, args.address_family)
|
||||||
|
args.chaosc_host, args.chaosc_port = resolve_host(
|
||||||
|
args.chaosc_host, args.chaosc_port, args.address_family)
|
||||||
|
|
||||||
server = JustAHTTPServer((http_host, http_port), MyHandler)
|
window = MainWindow(args)
|
||||||
server.address_family = args.address_family
|
sys.excepthook = window.sigint_handler
|
||||||
server.args = args
|
signal.signal(signal.SIGTERM, window.sigterm_handler)
|
||||||
logger.info("starting up http server on '%s:%d'", http_host, http_port)
|
QTAPP.exec_()
|
||||||
|
|
||||||
server.serve_forever()
|
|
||||||
|
|
||||||
if ( __name__ == '__main__' ):
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from distribute_setup import use_setuptools
|
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
@ -12,13 +9,15 @@ if sys.version_info >= (3,):
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='dump_grabber',
|
name='dump_grabber',
|
||||||
version="0.1",
|
version="0.2",
|
||||||
packages=find_packages(exclude=["scripts",]),
|
packages=find_packages(exclude=["scripts",]),
|
||||||
|
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
|
|
||||||
exclude_package_data = {'': ['.gitignore']},
|
exclude_package_data = {'': ['.gitignore']},
|
||||||
|
|
||||||
|
install_requires = ["psylib"],
|
||||||
|
|
||||||
# installing unzipped
|
# installing unzipped
|
||||||
zip_safe = False,
|
zip_safe = False,
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,556 @@
|
||||||
|
#!python
|
||||||
|
"""Bootstrap distribute installation
|
||||||
|
|
||||||
|
If you want to use setuptools in your package's setup.py, just include this
|
||||||
|
file in the same directory with it, and add this to the top of your setup.py::
|
||||||
|
|
||||||
|
from distribute_setup import use_setuptools
|
||||||
|
use_setuptools()
|
||||||
|
|
||||||
|
If you want to require a specific version of setuptools, set a download
|
||||||
|
mirror, or use an alternate download directory, you can do so by supplying
|
||||||
|
the appropriate options to ``use_setuptools()``.
|
||||||
|
|
||||||
|
This file can also be run as a script to install or upgrade setuptools.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import fnmatch
|
||||||
|
import tempfile
|
||||||
|
import tarfile
|
||||||
|
import optparse
|
||||||
|
|
||||||
|
from distutils import log
|
||||||
|
|
||||||
|
try:
|
||||||
|
from site import USER_SITE
|
||||||
|
except ImportError:
|
||||||
|
USER_SITE = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
return subprocess.call(args) == 0
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# will be used for python 2.3
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
# quoting arguments if windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
def quote(arg):
|
||||||
|
if ' ' in arg:
|
||||||
|
return '"%s"' % arg
|
||||||
|
return arg
|
||||||
|
args = [quote(arg) for arg in args]
|
||||||
|
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||||
|
|
||||||
|
DEFAULT_VERSION = "0.6.49"
|
||||||
|
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||||
|
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||||
|
|
||||||
|
SETUPTOOLS_PKG_INFO = """\
|
||||||
|
Metadata-Version: 1.0
|
||||||
|
Name: setuptools
|
||||||
|
Version: %s
|
||||||
|
Summary: xxxx
|
||||||
|
Home-page: xxx
|
||||||
|
Author: xxx
|
||||||
|
Author-email: xxx
|
||||||
|
License: xxx
|
||||||
|
Description: xxx
|
||||||
|
""" % SETUPTOOLS_FAKED_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def _install(tarball, install_args=()):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# installing
|
||||||
|
log.warn('Installing Distribute')
|
||||||
|
if not _python_cmd('setup.py', 'install', *install_args):
|
||||||
|
log.warn('Something went wrong during the installation.')
|
||||||
|
log.warn('See the error message above.')
|
||||||
|
# exitcode will be 2
|
||||||
|
return 2
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_egg(egg, tarball, to_dir):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# building an egg
|
||||||
|
log.warn('Building a Distribute egg in %s', to_dir)
|
||||||
|
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
# returning the result
|
||||||
|
log.warn(egg)
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
raise IOError('Could not build the egg.')
|
||||||
|
|
||||||
|
|
||||||
|
def _do_download(version, download_base, to_dir, download_delay):
|
||||||
|
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||||
|
% (version, sys.version_info[0], sys.version_info[1]))
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
tarball = download_setuptools(version, download_base,
|
||||||
|
to_dir, download_delay)
|
||||||
|
_build_egg(egg, tarball, to_dir)
|
||||||
|
sys.path.insert(0, egg)
|
||||||
|
import setuptools
|
||||||
|
setuptools.bootstrap_install_from = egg
|
||||||
|
|
||||||
|
|
||||||
|
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
was_imported = 'pkg_resources' in sys.modules or \
|
||||||
|
'setuptools' in sys.modules
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
# Setuptools 0.7b and later is a suitable (and preferable)
|
||||||
|
# substitute for any Distribute version.
|
||||||
|
try:
|
||||||
|
pkg_resources.require("setuptools>=0.7b")
|
||||||
|
return
|
||||||
|
except (pkg_resources.DistributionNotFound,
|
||||||
|
pkg_resources.VersionConflict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not hasattr(pkg_resources, '_distribute'):
|
||||||
|
if not no_fake:
|
||||||
|
_fake_setuptools()
|
||||||
|
raise ImportError
|
||||||
|
except ImportError:
|
||||||
|
return _do_download(version, download_base, to_dir, download_delay)
|
||||||
|
try:
|
||||||
|
pkg_resources.require("distribute>=" + version)
|
||||||
|
return
|
||||||
|
except pkg_resources.VersionConflict:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if was_imported:
|
||||||
|
sys.stderr.write(
|
||||||
|
"The required version of distribute (>=%s) is not available,\n"
|
||||||
|
"and can't be installed while this script is running. Please\n"
|
||||||
|
"install a more recent version first, using\n"
|
||||||
|
"'easy_install -U distribute'."
|
||||||
|
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
except pkg_resources.DistributionNotFound:
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
finally:
|
||||||
|
if not no_fake:
|
||||||
|
_create_fake_setuptools_pkg_info(to_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, delay=15):
|
||||||
|
"""Download distribute from a specified location and return its filename
|
||||||
|
|
||||||
|
`version` should be a valid distribute version number that is available
|
||||||
|
as an egg for download under the `download_base` URL (which should end
|
||||||
|
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||||
|
`delay` is the number of seconds to pause before an actual download
|
||||||
|
attempt.
|
||||||
|
"""
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
try:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
except ImportError:
|
||||||
|
from urllib2 import urlopen
|
||||||
|
tgz_name = "distribute-%s.tar.gz" % version
|
||||||
|
url = download_base + tgz_name
|
||||||
|
saveto = os.path.join(to_dir, tgz_name)
|
||||||
|
src = dst = None
|
||||||
|
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||||
|
try:
|
||||||
|
log.warn("Downloading %s", url)
|
||||||
|
src = urlopen(url)
|
||||||
|
# Read/write all in one block, so we don't create a corrupt file
|
||||||
|
# if the download is interrupted.
|
||||||
|
data = src.read()
|
||||||
|
dst = open(saveto, "wb")
|
||||||
|
dst.write(data)
|
||||||
|
finally:
|
||||||
|
if src:
|
||||||
|
src.close()
|
||||||
|
if dst:
|
||||||
|
dst.close()
|
||||||
|
return os.path.realpath(saveto)
|
||||||
|
|
||||||
|
|
||||||
|
def _no_sandbox(function):
|
||||||
|
def __no_sandbox(*args, **kw):
|
||||||
|
try:
|
||||||
|
from setuptools.sandbox import DirectorySandbox
|
||||||
|
if not hasattr(DirectorySandbox, '_old'):
|
||||||
|
def violation(*args):
|
||||||
|
pass
|
||||||
|
DirectorySandbox._old = DirectorySandbox._violation
|
||||||
|
DirectorySandbox._violation = violation
|
||||||
|
patched = True
|
||||||
|
else:
|
||||||
|
patched = False
|
||||||
|
except ImportError:
|
||||||
|
patched = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
return function(*args, **kw)
|
||||||
|
finally:
|
||||||
|
if patched:
|
||||||
|
DirectorySandbox._violation = DirectorySandbox._old
|
||||||
|
del DirectorySandbox._old
|
||||||
|
|
||||||
|
return __no_sandbox
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_file(path, content):
|
||||||
|
"""Will backup the file then patch it"""
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
if existing_content == content:
|
||||||
|
# already patched
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return False
|
||||||
|
log.warn('Patching...')
|
||||||
|
_rename_path(path)
|
||||||
|
f = open(path, 'w')
|
||||||
|
try:
|
||||||
|
f.write(content)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_file = _no_sandbox(_patch_file)
|
||||||
|
|
||||||
|
|
||||||
|
def _same_content(path, content):
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
return existing_content == content
|
||||||
|
|
||||||
|
|
||||||
|
def _rename_path(path):
|
||||||
|
new_name = path + '.OLD.%s' % time.time()
|
||||||
|
log.warn('Renaming %s to %s', path, new_name)
|
||||||
|
os.rename(path, new_name)
|
||||||
|
return new_name
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_flat_installation(placeholder):
|
||||||
|
if not os.path.isdir(placeholder):
|
||||||
|
log.warn('Unkown installation at %s', placeholder)
|
||||||
|
return False
|
||||||
|
found = False
|
||||||
|
for file in os.listdir(placeholder):
|
||||||
|
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
log.warn('Could not locate setuptools*.egg-info')
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Moving elements out of the way...')
|
||||||
|
pkg_info = os.path.join(placeholder, file)
|
||||||
|
if os.path.isdir(pkg_info):
|
||||||
|
patched = _patch_egg_dir(pkg_info)
|
||||||
|
else:
|
||||||
|
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||||
|
|
||||||
|
if not patched:
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
# now let's move the files out of the way
|
||||||
|
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||||
|
element = os.path.join(placeholder, element)
|
||||||
|
if os.path.exists(element):
|
||||||
|
_rename_path(element)
|
||||||
|
else:
|
||||||
|
log.warn('Could not find the %s element of the '
|
||||||
|
'Setuptools distribution', element)
|
||||||
|
return True
|
||||||
|
|
||||||
|
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||||
|
|
||||||
|
|
||||||
|
def _after_install(dist):
|
||||||
|
log.warn('After install bootstrap.')
|
||||||
|
placeholder = dist.get_command_obj('install').install_purelib
|
||||||
|
_create_fake_setuptools_pkg_info(placeholder)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_fake_setuptools_pkg_info(placeholder):
|
||||||
|
if not placeholder or not os.path.exists(placeholder):
|
||||||
|
log.warn('Could not find the install location')
|
||||||
|
return
|
||||||
|
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||||
|
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||||
|
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||||
|
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
log.warn('%s already exists', pkg_info)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Creating %s', pkg_info)
|
||||||
|
try:
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
except EnvironmentError:
|
||||||
|
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||||
|
log.warn('Creating %s', pth_file)
|
||||||
|
f = open(pth_file, 'w')
|
||||||
|
try:
|
||||||
|
f.write(os.path.join(os.curdir, setuptools_file))
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||||
|
_create_fake_setuptools_pkg_info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_egg_dir(path):
|
||||||
|
# let's check if it's already patched
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
_rename_path(path)
|
||||||
|
os.mkdir(path)
|
||||||
|
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def _before_install():
|
||||||
|
log.warn('Before install bootstrap.')
|
||||||
|
_fake_setuptools()
|
||||||
|
|
||||||
|
|
||||||
|
def _under_prefix(location):
|
||||||
|
if 'install' not in sys.argv:
|
||||||
|
return True
|
||||||
|
args = sys.argv[sys.argv.index('install') + 1:]
|
||||||
|
for index, arg in enumerate(args):
|
||||||
|
for option in ('--root', '--prefix'):
|
||||||
|
if arg.startswith('%s=' % option):
|
||||||
|
top_dir = arg.split('root=')[-1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
elif arg == option:
|
||||||
|
if len(args) > index:
|
||||||
|
top_dir = args[index + 1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
if arg == '--user' and USER_SITE is not None:
|
||||||
|
return location.startswith(USER_SITE)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _fake_setuptools():
|
||||||
|
log.warn('Scanning installed packages')
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
except ImportError:
|
||||||
|
# we're cool
|
||||||
|
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||||
|
return
|
||||||
|
ws = pkg_resources.working_set
|
||||||
|
try:
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||||
|
)
|
||||||
|
except TypeError:
|
||||||
|
# old distribute API
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools')
|
||||||
|
)
|
||||||
|
|
||||||
|
if setuptools_dist is None:
|
||||||
|
log.warn('No setuptools distribution found')
|
||||||
|
return
|
||||||
|
# detecting if it was already faked
|
||||||
|
setuptools_location = setuptools_dist.location
|
||||||
|
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||||
|
|
||||||
|
# if --root or --preix was provided, and if
|
||||||
|
# setuptools is not located in them, we don't patch it
|
||||||
|
if not _under_prefix(setuptools_location):
|
||||||
|
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||||
|
' in another location')
|
||||||
|
return
|
||||||
|
|
||||||
|
# let's see if its an egg
|
||||||
|
if not setuptools_location.endswith('.egg'):
|
||||||
|
log.warn('Non-egg installation')
|
||||||
|
res = _remove_flat_installation(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log.warn('Egg installation')
|
||||||
|
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if (os.path.exists(pkg_info) and
|
||||||
|
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return
|
||||||
|
log.warn('Patching...')
|
||||||
|
# let's create a fake egg replacing setuptools one
|
||||||
|
res = _patch_egg_dir(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
log.warn('Patching complete.')
|
||||||
|
_relaunch()
|
||||||
|
|
||||||
|
|
||||||
|
def _relaunch():
|
||||||
|
log.warn('Relaunching...')
|
||||||
|
# we have to relaunch the process
|
||||||
|
# pip marker to avoid a relaunch bug
|
||||||
|
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||||
|
_cmd2 = ['-c', 'install', '--record']
|
||||||
|
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||||
|
sys.argv[0] = 'setup.py'
|
||||||
|
args = [sys.executable] + sys.argv
|
||||||
|
sys.exit(subprocess.call(args))
|
||||||
|
|
||||||
|
|
||||||
|
def _extractall(self, path=".", members=None):
|
||||||
|
"""Extract all members from the archive to the current working
|
||||||
|
directory and set owner, modification time and permissions on
|
||||||
|
directories afterwards. `path' specifies a different directory
|
||||||
|
to extract to. `members' is optional and must be a subset of the
|
||||||
|
list returned by getmembers().
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
import operator
|
||||||
|
from tarfile import ExtractError
|
||||||
|
directories = []
|
||||||
|
|
||||||
|
if members is None:
|
||||||
|
members = self
|
||||||
|
|
||||||
|
for tarinfo in members:
|
||||||
|
if tarinfo.isdir():
|
||||||
|
# Extract directories with a safe mode.
|
||||||
|
directories.append(tarinfo)
|
||||||
|
tarinfo = copy.copy(tarinfo)
|
||||||
|
tarinfo.mode = 448 # decimal for oct 0700
|
||||||
|
self.extract(tarinfo, path)
|
||||||
|
|
||||||
|
# Reverse sort directories.
|
||||||
|
if sys.version_info < (2, 4):
|
||||||
|
def sorter(dir1, dir2):
|
||||||
|
return cmp(dir1.name, dir2.name)
|
||||||
|
directories.sort(sorter)
|
||||||
|
directories.reverse()
|
||||||
|
else:
|
||||||
|
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||||
|
|
||||||
|
# Set correct owner, mtime and filemode on directories.
|
||||||
|
for tarinfo in directories:
|
||||||
|
dirpath = os.path.join(path, tarinfo.name)
|
||||||
|
try:
|
||||||
|
self.chown(tarinfo, dirpath)
|
||||||
|
self.utime(tarinfo, dirpath)
|
||||||
|
self.chmod(tarinfo, dirpath)
|
||||||
|
except ExtractError:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if self.errorlevel > 1:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self._dbg(1, "tarfile: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_install_args(options):
|
||||||
|
"""
|
||||||
|
Build the arguments to 'python setup.py install' on the distribute package
|
||||||
|
"""
|
||||||
|
install_args = []
|
||||||
|
if options.user_install:
|
||||||
|
if sys.version_info < (2, 6):
|
||||||
|
log.warn("--user requires Python 2.6 or later")
|
||||||
|
raise SystemExit(1)
|
||||||
|
install_args.append('--user')
|
||||||
|
return install_args
|
||||||
|
|
||||||
|
def _parse_args():
|
||||||
|
"""
|
||||||
|
Parse the command line for options
|
||||||
|
"""
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'--user', dest='user_install', action='store_true', default=False,
|
||||||
|
help='install in user site package (requires Python 2.6 or later)')
|
||||||
|
parser.add_option(
|
||||||
|
'--download-base', dest='download_base', metavar="URL",
|
||||||
|
default=DEFAULT_URL,
|
||||||
|
help='alternative URL from where to download the distribute package')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
# positional arguments are ignored
|
||||||
|
return options
|
||||||
|
|
||||||
|
def main(version=DEFAULT_VERSION):
|
||||||
|
"""Install or upgrade setuptools and EasyInstall"""
|
||||||
|
options = _parse_args()
|
||||||
|
tarball = download_setuptools(download_base=options.download_base)
|
||||||
|
return _install(tarball, _build_install_args(options))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
|
@ -1,7 +1,7 @@
|
||||||
<HTML>
|
<HTML>
|
||||||
<BODY>
|
<BODY>
|
||||||
|
|
||||||
<img src="/camera.mjpeg" alt="Smiley face">
|
<img src="/camera_%d.mjpeg" alt="Smiley face">
|
||||||
|
|
||||||
</BODY>
|
</BODY>
|
||||||
</HTML>
|
</HTML>
|
||||||
|
|
|
@ -0,0 +1,282 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of psychose/ekgplotter package
|
||||||
|
#
|
||||||
|
# psychose/ekgplotter is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# psychose/ekgplotter is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with psychose/ekgplotter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 Stefan Kögl
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import random
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
import signal
|
||||||
|
import sys
|
||||||
|
import exceptions
|
||||||
|
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
from PyQt4.QtGui import QImage, QPixmap, QMainWindow
|
||||||
|
from PyQt4.QtCore import QBuffer, QIODevice
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import pyqtgraph as pg
|
||||||
|
from pyqtgraph.widgets.PlotWidget import PlotWidget
|
||||||
|
from pyqtgraph.graphicsItems.PlotCurveItem import PlotCurveItem
|
||||||
|
from pyqtgraph.graphicsItems.ScatterPlotItem import ScatterPlotItem
|
||||||
|
|
||||||
|
from chaosc.argparser_groups import ArgParser
|
||||||
|
from chaosc.lib import logger, resolve_host
|
||||||
|
from psylib.mjpeg_streaming_server import *
|
||||||
|
from psylib.psyqt_base import PsyQtChaoscClientBase
|
||||||
|
|
||||||
|
try:
|
||||||
|
from chaosc.c_osc_lib import decode_osc
|
||||||
|
except ImportError as e:
|
||||||
|
from chaosc.osc_lib import decode_osc
|
||||||
|
|
||||||
|
qtapp = QtGui.QApplication([])
|
||||||
|
|
||||||
|
|
||||||
|
def get_steps(pulse, delta_ms):
|
||||||
|
beat_length = 60000. / pulse
|
||||||
|
steps_pre = int(beat_length / delta_ms) + 1
|
||||||
|
used_sleep_time = beat_length / steps_pre
|
||||||
|
steps = int(beat_length / used_sleep_time)
|
||||||
|
return steps, used_sleep_time
|
||||||
|
|
||||||
|
|
||||||
|
class Generator(object):
|
||||||
|
def __init__(self, pulse=92, delta=80):
|
||||||
|
self.count = 0
|
||||||
|
self.pulse = random.randint(85, 105)
|
||||||
|
self.delta = delta
|
||||||
|
self.finished = False
|
||||||
|
self.steps, _ = get_steps(self.pulse, delta / 4)
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
while 1:
|
||||||
|
if self.count < int(self.steps / 100. * 30):
|
||||||
|
value = random.randint(30, 35)
|
||||||
|
elif self.count == int(self.steps / 100. * 30):
|
||||||
|
value = random.randint(55, 66)
|
||||||
|
elif self.count < int(self.steps / 100. * 45):
|
||||||
|
value = random.randint(30, 35)
|
||||||
|
elif self.count < int(self.steps / 2.):
|
||||||
|
value = random.randint(0, 15)
|
||||||
|
elif self.count == int(self.steps / 2.):
|
||||||
|
value = 255
|
||||||
|
elif self.count < int(self.steps / 100. * 60):
|
||||||
|
value = random.randint(25, 35)
|
||||||
|
elif self.count < int(self.steps / 100. * 70):
|
||||||
|
value = random.randint(10, 30)
|
||||||
|
elif self.count < self.steps:
|
||||||
|
value = random.randint(15, 30)
|
||||||
|
else:
|
||||||
|
self.finished = True
|
||||||
|
self.count = 0
|
||||||
|
value = 30
|
||||||
|
|
||||||
|
self.count += 1
|
||||||
|
yield value
|
||||||
|
|
||||||
|
def set_pulse(self, pulse):
|
||||||
|
self.pulse = pulse
|
||||||
|
self.steps, _ = get_steps(pulse, self.delta)
|
||||||
|
|
||||||
|
def retrigger(self):
|
||||||
|
self.count = self.steps / 2
|
||||||
|
|
||||||
|
|
||||||
|
class Actor(object):
|
||||||
|
def __init__(self, name, num_data, color, ix, max_actors, actor_height):
|
||||||
|
self.name = name
|
||||||
|
self.num_data = num_data
|
||||||
|
self.color = color
|
||||||
|
self.ix = ix
|
||||||
|
self.max_actors = max_actors
|
||||||
|
self.actor_height = actor_height
|
||||||
|
self.offset = ix * actor_height
|
||||||
|
self.data = np.array([self.offset + 30] * num_data)
|
||||||
|
self.head = 0
|
||||||
|
self.pre_head = 0
|
||||||
|
self.plotItem = PlotCurveItem(pen=pg.mkPen(color, width=3), width=4, name=name)
|
||||||
|
self.plotPoint = ScatterPlotItem(pen=pg.mkPen("w", width=5), brush=pg.mkBrush(color), size=5)
|
||||||
|
self.osci = None
|
||||||
|
self.osci_obj = None
|
||||||
|
self.render()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "<Actor name:%r, position=%r>" % (self.name, self.head)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "Actor(%r, %r, %r, %r, %r, %r)" % (self.name, self.num_data,
|
||||||
|
self.color, self.ix, self.max_actors, self.actor_height)
|
||||||
|
|
||||||
|
def add_value(self, value):
|
||||||
|
self.pre_head = self.head
|
||||||
|
self.data[self.pre_head] = value / self.max_actors + self.offset
|
||||||
|
self.head = (self.pre_head + 1) % self.num_data
|
||||||
|
|
||||||
|
def fill_missing(self, count):
|
||||||
|
dp = self.head
|
||||||
|
for i in range(count):
|
||||||
|
self.data[dp] = self.offset
|
||||||
|
dp = (dp + 1) % self.num_data
|
||||||
|
|
||||||
|
self.pre_head = (dp - 1) % self.num_data
|
||||||
|
self.head = dp
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
self.plotItem.setData(y=self.data, clear=True)
|
||||||
|
self.plotPoint.setData(x=[self.pre_head], y=[self.data[self.pre_head]])
|
||||||
|
|
||||||
|
class PlotWindow(PlotWidget):
|
||||||
|
def __init__(self, title=None, **kargs):
|
||||||
|
self.win = QtGui.QMainWindow()
|
||||||
|
self.win.resize(768, 576)
|
||||||
|
PlotWidget.__init__(self, **kargs)
|
||||||
|
self.win.setCentralWidget(self)
|
||||||
|
for m in ['resize']:
|
||||||
|
setattr(self, m, getattr(self.win, m))
|
||||||
|
if title is not None:
|
||||||
|
self.win.setWindowTitle(title)
|
||||||
|
self.win.show()
|
||||||
|
|
||||||
|
|
||||||
|
class EkgPlotWidget(QMainWindow, PsyQtChaoscClientBase, MjpegStreamingConsumerInterface):
|
||||||
|
def __init__(self, args, parent=None):
|
||||||
|
self.args = args
|
||||||
|
super(EkgPlotWidget, self).__init__()
|
||||||
|
PsyQtChaoscClientBase.__init__(self)
|
||||||
|
self.plot_widget = PlotWidget(title="Psychose - EkgPlotter")
|
||||||
|
colors = ["r", "g", "b"]
|
||||||
|
self.active_actors = list()
|
||||||
|
self.actors = dict()
|
||||||
|
self.max_value = 255
|
||||||
|
actor_names = ["merle", "uwe", "bjoern"]
|
||||||
|
self.max_actors = len(actor_names)
|
||||||
|
self.actor_height = self.max_value / self.max_actors
|
||||||
|
self.fps = 12.5
|
||||||
|
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self, self.fps)
|
||||||
|
self.http_server.listen(port=args.http_port)
|
||||||
|
self.num_data = 100
|
||||||
|
self.plot_widget.showGrid(False, False)
|
||||||
|
self.plot_widget.setYRange(0, 255)
|
||||||
|
self.plot_widget.setXRange(0, self.num_data)
|
||||||
|
self.plot_widget.resize(768, 576)
|
||||||
|
|
||||||
|
bottom_axis = self.plot_widget.getAxis("bottom")
|
||||||
|
left_axis = self.plot_widget.getAxis("left")
|
||||||
|
bottom_axis.setTicks([])
|
||||||
|
left_axis.setTicks([])
|
||||||
|
bottom_axis.hide()
|
||||||
|
left_axis.hide()
|
||||||
|
|
||||||
|
for ix, (actor_name, color) in enumerate(zip(actor_names, colors)):
|
||||||
|
self.add_actor(actor_name, self.num_data, color, ix, self.max_actors, self.actor_height)
|
||||||
|
|
||||||
|
self.set_positions()
|
||||||
|
self.heartbeat_regex = re.compile("^/(.*?)/heartbeat$")
|
||||||
|
|
||||||
|
def pubdir(self):
|
||||||
|
return os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
def add_actor(self, actor_name, num_data, color, ix, max_actors, actor_height):
|
||||||
|
actor_obj = Actor(actor_name, num_data, color, ix, max_actors, actor_height)
|
||||||
|
self.actors[actor_name] = actor_obj
|
||||||
|
self.plot_widget.addItem(actor_obj.plotItem)
|
||||||
|
self.plot_widget.addItem(actor_obj.plotPoint)
|
||||||
|
self.active_actors.append(actor_obj)
|
||||||
|
actor_obj.osci_obj = Generator(pulse=random.randint(88, 104), delta=self.http_server.timer_delta)
|
||||||
|
actor_obj.osci = actor_obj.osci_obj()
|
||||||
|
|
||||||
|
def set_positions(self):
|
||||||
|
for ix, actor_obj in enumerate(self.active_actors):
|
||||||
|
actor_obj.plotItem.setPos(0, ix * 2)
|
||||||
|
actor_obj.plotPoint.setPos(0, ix * 2)
|
||||||
|
|
||||||
|
def active_actor_count(self):
|
||||||
|
return self.max_actors
|
||||||
|
|
||||||
|
def update(self, osc_address, args):
|
||||||
|
res = self.heartbeat_regex.match(osc_address)
|
||||||
|
if res:
|
||||||
|
actor_name = res.group(1)
|
||||||
|
actor_obj = self.actors[actor_name]
|
||||||
|
#logger.info("actor: %r, %r", actor_name, args)
|
||||||
|
if args[0] == 1:
|
||||||
|
actor_obj.osci_obj.retrigger()
|
||||||
|
actor_obj.osci_obj.set_pulse(args[1])
|
||||||
|
|
||||||
|
def render_image(self):
|
||||||
|
for actor_obj in self.active_actors:
|
||||||
|
actor_obj.add_value(actor_obj.osci.next())
|
||||||
|
actor_obj.add_value(actor_obj.osci.next())
|
||||||
|
actor_obj.add_value(actor_obj.osci.next())
|
||||||
|
actor_obj.add_value(actor_obj.osci.next())
|
||||||
|
actor_obj.render()
|
||||||
|
image = QPixmap(768, 576)
|
||||||
|
image.fill(QtCore.Qt.white)
|
||||||
|
painter = QtGui.QPainter(image)
|
||||||
|
painter.setRenderHints(QtGui.QPainter.RenderHint(
|
||||||
|
QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing),
|
||||||
|
True)
|
||||||
|
scene = self.plot_widget.plotItem.scene()
|
||||||
|
scene.render(painter, QtCore.QRectF(0, 0, 768, 576), QtCore.QRectF(0, 0, 768, 576))
|
||||||
|
painter.end()
|
||||||
|
buf = QBuffer()
|
||||||
|
buf.open(QIODevice.WriteOnly)
|
||||||
|
image.save(buf, "JPG", 80)
|
||||||
|
JpegData = buf.data()
|
||||||
|
return JpegData
|
||||||
|
|
||||||
|
def got_message(self):
|
||||||
|
while self.osc_sock.hasPendingDatagrams():
|
||||||
|
data, address, port = self.osc_sock.readDatagram(self.osc_sock.pendingDatagramSize())
|
||||||
|
try:
|
||||||
|
osc_address, typetags, args = decode_osc(data, 0, len(data))
|
||||||
|
except ValueError, error:
|
||||||
|
logger.exception(error)
|
||||||
|
else:
|
||||||
|
self.update(osc_address, args)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
arg_parser = ArgParser("ekgplotter")
|
||||||
|
arg_parser.add_global_group()
|
||||||
|
client_group = arg_parser.add_client_group()
|
||||||
|
arg_parser.add_argument(client_group, '-x', "--http_host", default='::',
|
||||||
|
help='my host, defaults to "::"')
|
||||||
|
arg_parser.add_argument(client_group, '-X', '--http_port', default=9000,
|
||||||
|
type=int, help='my port, defaults to 9000')
|
||||||
|
arg_parser.add_chaosc_group()
|
||||||
|
arg_parser.add_subscriber_group()
|
||||||
|
args = arg_parser.finalize()
|
||||||
|
|
||||||
|
args.http_host, args.http_port = resolve_host(args.http_host, args.http_port, args.address_family)
|
||||||
|
args.chaosc_host, args.chaosc_port = resolve_host(args.chaosc_host, args.chaosc_port, args.address_family)
|
||||||
|
|
||||||
|
window = EkgPlotWidget(args)
|
||||||
|
logger.info("foooooooo")
|
||||||
|
window.hide()
|
||||||
|
#sys.excepthook = window.sigint_handler
|
||||||
|
#signal.signal(signal.SIGTERM, window.sigterm_handler)
|
||||||
|
qtapp.exec_()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -1,9 +1,6 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from distribute_setup import use_setuptools
|
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
@ -12,7 +9,7 @@ if sys.version_info >= (3,):
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='ekgplotter',
|
name='ekgplotter',
|
||||||
version="0.1",
|
version="0.2",
|
||||||
packages=find_packages(exclude=["scripts",]),
|
packages=find_packages(exclude=["scripts",]),
|
||||||
|
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
|
@ -22,7 +19,7 @@ setup(
|
||||||
|
|
||||||
exclude_package_data = {'': ['.gitignore']},
|
exclude_package_data = {'': ['.gitignore']},
|
||||||
|
|
||||||
install_requires=["pyqtgraph"],
|
install_requires=["psylib", "pyqtgraph"],
|
||||||
|
|
||||||
# installing unzipped
|
# installing unzipped
|
||||||
zip_safe = False,
|
zip_safe = False,
|
||||||
|
@ -30,7 +27,7 @@ setup(
|
||||||
# predefined extension points, e.g. for plugins
|
# predefined extension points, e.g. for plugins
|
||||||
entry_points = """
|
entry_points = """
|
||||||
[console_scripts]
|
[console_scripts]
|
||||||
ekgplotter = ekgplotter.main:main
|
ekgplotter = ekgplotter.main_qt:main
|
||||||
""",
|
""",
|
||||||
# pypi metadata
|
# pypi metadata
|
||||||
author = "Stefan Kögl",
|
author = "Stefan Kögl",
|
||||||
|
|
|
@ -0,0 +1,556 @@
|
||||||
|
#!python
|
||||||
|
"""Bootstrap distribute installation
|
||||||
|
|
||||||
|
If you want to use setuptools in your package's setup.py, just include this
|
||||||
|
file in the same directory with it, and add this to the top of your setup.py::
|
||||||
|
|
||||||
|
from distribute_setup import use_setuptools
|
||||||
|
use_setuptools()
|
||||||
|
|
||||||
|
If you want to require a specific version of setuptools, set a download
|
||||||
|
mirror, or use an alternate download directory, you can do so by supplying
|
||||||
|
the appropriate options to ``use_setuptools()``.
|
||||||
|
|
||||||
|
This file can also be run as a script to install or upgrade setuptools.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import fnmatch
|
||||||
|
import tempfile
|
||||||
|
import tarfile
|
||||||
|
import optparse
|
||||||
|
|
||||||
|
from distutils import log
|
||||||
|
|
||||||
|
try:
|
||||||
|
from site import USER_SITE
|
||||||
|
except ImportError:
|
||||||
|
USER_SITE = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
return subprocess.call(args) == 0
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# will be used for python 2.3
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
# quoting arguments if windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
def quote(arg):
|
||||||
|
if ' ' in arg:
|
||||||
|
return '"%s"' % arg
|
||||||
|
return arg
|
||||||
|
args = [quote(arg) for arg in args]
|
||||||
|
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||||
|
|
||||||
|
DEFAULT_VERSION = "0.6.49"
|
||||||
|
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||||
|
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||||
|
|
||||||
|
SETUPTOOLS_PKG_INFO = """\
|
||||||
|
Metadata-Version: 1.0
|
||||||
|
Name: setuptools
|
||||||
|
Version: %s
|
||||||
|
Summary: xxxx
|
||||||
|
Home-page: xxx
|
||||||
|
Author: xxx
|
||||||
|
Author-email: xxx
|
||||||
|
License: xxx
|
||||||
|
Description: xxx
|
||||||
|
""" % SETUPTOOLS_FAKED_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def _install(tarball, install_args=()):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# installing
|
||||||
|
log.warn('Installing Distribute')
|
||||||
|
if not _python_cmd('setup.py', 'install', *install_args):
|
||||||
|
log.warn('Something went wrong during the installation.')
|
||||||
|
log.warn('See the error message above.')
|
||||||
|
# exitcode will be 2
|
||||||
|
return 2
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_egg(egg, tarball, to_dir):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# building an egg
|
||||||
|
log.warn('Building a Distribute egg in %s', to_dir)
|
||||||
|
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
# returning the result
|
||||||
|
log.warn(egg)
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
raise IOError('Could not build the egg.')
|
||||||
|
|
||||||
|
|
||||||
|
def _do_download(version, download_base, to_dir, download_delay):
|
||||||
|
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||||
|
% (version, sys.version_info[0], sys.version_info[1]))
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
tarball = download_setuptools(version, download_base,
|
||||||
|
to_dir, download_delay)
|
||||||
|
_build_egg(egg, tarball, to_dir)
|
||||||
|
sys.path.insert(0, egg)
|
||||||
|
import setuptools
|
||||||
|
setuptools.bootstrap_install_from = egg
|
||||||
|
|
||||||
|
|
||||||
|
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
was_imported = 'pkg_resources' in sys.modules or \
|
||||||
|
'setuptools' in sys.modules
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
# Setuptools 0.7b and later is a suitable (and preferable)
|
||||||
|
# substitute for any Distribute version.
|
||||||
|
try:
|
||||||
|
pkg_resources.require("setuptools>=0.7b")
|
||||||
|
return
|
||||||
|
except (pkg_resources.DistributionNotFound,
|
||||||
|
pkg_resources.VersionConflict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not hasattr(pkg_resources, '_distribute'):
|
||||||
|
if not no_fake:
|
||||||
|
_fake_setuptools()
|
||||||
|
raise ImportError
|
||||||
|
except ImportError:
|
||||||
|
return _do_download(version, download_base, to_dir, download_delay)
|
||||||
|
try:
|
||||||
|
pkg_resources.require("distribute>=" + version)
|
||||||
|
return
|
||||||
|
except pkg_resources.VersionConflict:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if was_imported:
|
||||||
|
sys.stderr.write(
|
||||||
|
"The required version of distribute (>=%s) is not available,\n"
|
||||||
|
"and can't be installed while this script is running. Please\n"
|
||||||
|
"install a more recent version first, using\n"
|
||||||
|
"'easy_install -U distribute'."
|
||||||
|
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
except pkg_resources.DistributionNotFound:
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
finally:
|
||||||
|
if not no_fake:
|
||||||
|
_create_fake_setuptools_pkg_info(to_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, delay=15):
|
||||||
|
"""Download distribute from a specified location and return its filename
|
||||||
|
|
||||||
|
`version` should be a valid distribute version number that is available
|
||||||
|
as an egg for download under the `download_base` URL (which should end
|
||||||
|
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||||
|
`delay` is the number of seconds to pause before an actual download
|
||||||
|
attempt.
|
||||||
|
"""
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
try:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
except ImportError:
|
||||||
|
from urllib2 import urlopen
|
||||||
|
tgz_name = "distribute-%s.tar.gz" % version
|
||||||
|
url = download_base + tgz_name
|
||||||
|
saveto = os.path.join(to_dir, tgz_name)
|
||||||
|
src = dst = None
|
||||||
|
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||||
|
try:
|
||||||
|
log.warn("Downloading %s", url)
|
||||||
|
src = urlopen(url)
|
||||||
|
# Read/write all in one block, so we don't create a corrupt file
|
||||||
|
# if the download is interrupted.
|
||||||
|
data = src.read()
|
||||||
|
dst = open(saveto, "wb")
|
||||||
|
dst.write(data)
|
||||||
|
finally:
|
||||||
|
if src:
|
||||||
|
src.close()
|
||||||
|
if dst:
|
||||||
|
dst.close()
|
||||||
|
return os.path.realpath(saveto)
|
||||||
|
|
||||||
|
|
||||||
|
def _no_sandbox(function):
|
||||||
|
def __no_sandbox(*args, **kw):
|
||||||
|
try:
|
||||||
|
from setuptools.sandbox import DirectorySandbox
|
||||||
|
if not hasattr(DirectorySandbox, '_old'):
|
||||||
|
def violation(*args):
|
||||||
|
pass
|
||||||
|
DirectorySandbox._old = DirectorySandbox._violation
|
||||||
|
DirectorySandbox._violation = violation
|
||||||
|
patched = True
|
||||||
|
else:
|
||||||
|
patched = False
|
||||||
|
except ImportError:
|
||||||
|
patched = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
return function(*args, **kw)
|
||||||
|
finally:
|
||||||
|
if patched:
|
||||||
|
DirectorySandbox._violation = DirectorySandbox._old
|
||||||
|
del DirectorySandbox._old
|
||||||
|
|
||||||
|
return __no_sandbox
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_file(path, content):
|
||||||
|
"""Will backup the file then patch it"""
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
if existing_content == content:
|
||||||
|
# already patched
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return False
|
||||||
|
log.warn('Patching...')
|
||||||
|
_rename_path(path)
|
||||||
|
f = open(path, 'w')
|
||||||
|
try:
|
||||||
|
f.write(content)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_file = _no_sandbox(_patch_file)
|
||||||
|
|
||||||
|
|
||||||
|
def _same_content(path, content):
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
return existing_content == content
|
||||||
|
|
||||||
|
|
||||||
|
def _rename_path(path):
|
||||||
|
new_name = path + '.OLD.%s' % time.time()
|
||||||
|
log.warn('Renaming %s to %s', path, new_name)
|
||||||
|
os.rename(path, new_name)
|
||||||
|
return new_name
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_flat_installation(placeholder):
|
||||||
|
if not os.path.isdir(placeholder):
|
||||||
|
log.warn('Unkown installation at %s', placeholder)
|
||||||
|
return False
|
||||||
|
found = False
|
||||||
|
for file in os.listdir(placeholder):
|
||||||
|
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
log.warn('Could not locate setuptools*.egg-info')
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Moving elements out of the way...')
|
||||||
|
pkg_info = os.path.join(placeholder, file)
|
||||||
|
if os.path.isdir(pkg_info):
|
||||||
|
patched = _patch_egg_dir(pkg_info)
|
||||||
|
else:
|
||||||
|
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||||
|
|
||||||
|
if not patched:
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
# now let's move the files out of the way
|
||||||
|
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||||
|
element = os.path.join(placeholder, element)
|
||||||
|
if os.path.exists(element):
|
||||||
|
_rename_path(element)
|
||||||
|
else:
|
||||||
|
log.warn('Could not find the %s element of the '
|
||||||
|
'Setuptools distribution', element)
|
||||||
|
return True
|
||||||
|
|
||||||
|
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||||
|
|
||||||
|
|
||||||
|
def _after_install(dist):
|
||||||
|
log.warn('After install bootstrap.')
|
||||||
|
placeholder = dist.get_command_obj('install').install_purelib
|
||||||
|
_create_fake_setuptools_pkg_info(placeholder)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_fake_setuptools_pkg_info(placeholder):
|
||||||
|
if not placeholder or not os.path.exists(placeholder):
|
||||||
|
log.warn('Could not find the install location')
|
||||||
|
return
|
||||||
|
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||||
|
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||||
|
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||||
|
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
log.warn('%s already exists', pkg_info)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Creating %s', pkg_info)
|
||||||
|
try:
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
except EnvironmentError:
|
||||||
|
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||||
|
log.warn('Creating %s', pth_file)
|
||||||
|
f = open(pth_file, 'w')
|
||||||
|
try:
|
||||||
|
f.write(os.path.join(os.curdir, setuptools_file))
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||||
|
_create_fake_setuptools_pkg_info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_egg_dir(path):
|
||||||
|
# let's check if it's already patched
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
_rename_path(path)
|
||||||
|
os.mkdir(path)
|
||||||
|
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def _before_install():
|
||||||
|
log.warn('Before install bootstrap.')
|
||||||
|
_fake_setuptools()
|
||||||
|
|
||||||
|
|
||||||
|
def _under_prefix(location):
|
||||||
|
if 'install' not in sys.argv:
|
||||||
|
return True
|
||||||
|
args = sys.argv[sys.argv.index('install') + 1:]
|
||||||
|
for index, arg in enumerate(args):
|
||||||
|
for option in ('--root', '--prefix'):
|
||||||
|
if arg.startswith('%s=' % option):
|
||||||
|
top_dir = arg.split('root=')[-1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
elif arg == option:
|
||||||
|
if len(args) > index:
|
||||||
|
top_dir = args[index + 1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
if arg == '--user' and USER_SITE is not None:
|
||||||
|
return location.startswith(USER_SITE)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _fake_setuptools():
|
||||||
|
log.warn('Scanning installed packages')
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
except ImportError:
|
||||||
|
# we're cool
|
||||||
|
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||||
|
return
|
||||||
|
ws = pkg_resources.working_set
|
||||||
|
try:
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||||
|
)
|
||||||
|
except TypeError:
|
||||||
|
# old distribute API
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools')
|
||||||
|
)
|
||||||
|
|
||||||
|
if setuptools_dist is None:
|
||||||
|
log.warn('No setuptools distribution found')
|
||||||
|
return
|
||||||
|
# detecting if it was already faked
|
||||||
|
setuptools_location = setuptools_dist.location
|
||||||
|
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||||
|
|
||||||
|
# if --root or --preix was provided, and if
|
||||||
|
# setuptools is not located in them, we don't patch it
|
||||||
|
if not _under_prefix(setuptools_location):
|
||||||
|
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||||
|
' in another location')
|
||||||
|
return
|
||||||
|
|
||||||
|
# let's see if its an egg
|
||||||
|
if not setuptools_location.endswith('.egg'):
|
||||||
|
log.warn('Non-egg installation')
|
||||||
|
res = _remove_flat_installation(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log.warn('Egg installation')
|
||||||
|
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if (os.path.exists(pkg_info) and
|
||||||
|
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return
|
||||||
|
log.warn('Patching...')
|
||||||
|
# let's create a fake egg replacing setuptools one
|
||||||
|
res = _patch_egg_dir(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
log.warn('Patching complete.')
|
||||||
|
_relaunch()
|
||||||
|
|
||||||
|
|
||||||
|
def _relaunch():
|
||||||
|
log.warn('Relaunching...')
|
||||||
|
# we have to relaunch the process
|
||||||
|
# pip marker to avoid a relaunch bug
|
||||||
|
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||||
|
_cmd2 = ['-c', 'install', '--record']
|
||||||
|
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||||
|
sys.argv[0] = 'setup.py'
|
||||||
|
args = [sys.executable] + sys.argv
|
||||||
|
sys.exit(subprocess.call(args))
|
||||||
|
|
||||||
|
|
||||||
|
def _extractall(self, path=".", members=None):
|
||||||
|
"""Extract all members from the archive to the current working
|
||||||
|
directory and set owner, modification time and permissions on
|
||||||
|
directories afterwards. `path' specifies a different directory
|
||||||
|
to extract to. `members' is optional and must be a subset of the
|
||||||
|
list returned by getmembers().
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
import operator
|
||||||
|
from tarfile import ExtractError
|
||||||
|
directories = []
|
||||||
|
|
||||||
|
if members is None:
|
||||||
|
members = self
|
||||||
|
|
||||||
|
for tarinfo in members:
|
||||||
|
if tarinfo.isdir():
|
||||||
|
# Extract directories with a safe mode.
|
||||||
|
directories.append(tarinfo)
|
||||||
|
tarinfo = copy.copy(tarinfo)
|
||||||
|
tarinfo.mode = 448 # decimal for oct 0700
|
||||||
|
self.extract(tarinfo, path)
|
||||||
|
|
||||||
|
# Reverse sort directories.
|
||||||
|
if sys.version_info < (2, 4):
|
||||||
|
def sorter(dir1, dir2):
|
||||||
|
return cmp(dir1.name, dir2.name)
|
||||||
|
directories.sort(sorter)
|
||||||
|
directories.reverse()
|
||||||
|
else:
|
||||||
|
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||||
|
|
||||||
|
# Set correct owner, mtime and filemode on directories.
|
||||||
|
for tarinfo in directories:
|
||||||
|
dirpath = os.path.join(path, tarinfo.name)
|
||||||
|
try:
|
||||||
|
self.chown(tarinfo, dirpath)
|
||||||
|
self.utime(tarinfo, dirpath)
|
||||||
|
self.chmod(tarinfo, dirpath)
|
||||||
|
except ExtractError:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if self.errorlevel > 1:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self._dbg(1, "tarfile: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_install_args(options):
|
||||||
|
"""
|
||||||
|
Build the arguments to 'python setup.py install' on the distribute package
|
||||||
|
"""
|
||||||
|
install_args = []
|
||||||
|
if options.user_install:
|
||||||
|
if sys.version_info < (2, 6):
|
||||||
|
log.warn("--user requires Python 2.6 or later")
|
||||||
|
raise SystemExit(1)
|
||||||
|
install_args.append('--user')
|
||||||
|
return install_args
|
||||||
|
|
||||||
|
def _parse_args():
|
||||||
|
"""
|
||||||
|
Parse the command line for options
|
||||||
|
"""
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'--user', dest='user_install', action='store_true', default=False,
|
||||||
|
help='install in user site package (requires Python 2.6 or later)')
|
||||||
|
parser.add_option(
|
||||||
|
'--download-base', dest='download_base', metavar="URL",
|
||||||
|
default=DEFAULT_URL,
|
||||||
|
help='alternative URL from where to download the distribute package')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
# positional arguments are ignored
|
||||||
|
return options
|
||||||
|
|
||||||
|
def main(version=DEFAULT_VERSION):
|
||||||
|
"""Install or upgrade setuptools and EasyInstall"""
|
||||||
|
options = _parse_args()
|
||||||
|
tarball = download_setuptools(download_base=options.download_base)
|
||||||
|
return _install(tarball, _build_install_args(options))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
|
@ -0,0 +1,232 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of chaosc/psylib package
|
||||||
|
#
|
||||||
|
# chaosc/psylib is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# chaosc/psylib is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with chaosc/psylib. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 Stefan Kögl
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
|
||||||
|
from chaosc.lib import logger
|
||||||
|
from PyQt4 import QtCore
|
||||||
|
from PyQt4.QtCore import QByteArray
|
||||||
|
from PyQt4.QtNetwork import QTcpServer, QTcpSocket
|
||||||
|
|
||||||
|
__all__ = ["MjpegStreamingConsumerInterface", "MjpegStreamingServer"]
|
||||||
|
|
||||||
|
class MjpegStreamingConsumerInterface(object):
|
||||||
|
def pubdir(self):
|
||||||
|
""" returns the directory, from where your static files should be served
|
||||||
|
|
||||||
|
fast and dirty implementation e.g:
|
||||||
|
return os.path.dirname(os.path.abspath(__file__))
|
||||||
|
"""
|
||||||
|
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def render_image(self):
|
||||||
|
"""returns a QByteArray with the binary date of a jpg image
|
||||||
|
|
||||||
|
this method should implement the actual window/widget grabbing"""
|
||||||
|
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
class MjpegStreamingServer(QTcpServer):
|
||||||
|
"""A simple async http class which provides a mjpeg stream and if found,
|
||||||
|
an index.html file containing the mjpeg stream.
|
||||||
|
|
||||||
|
Parent should implement the interface 'MjpegStreamingConsumerInterface'
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, server_address, parent=None, fps=12.5):
|
||||||
|
super(MjpegStreamingServer, self).__init__(parent)
|
||||||
|
self.server_address = server_address
|
||||||
|
self.newConnection.connect(self.new_connection)
|
||||||
|
assert isinstance(parent, MjpegStreamingConsumerInterface)
|
||||||
|
self.widget = parent
|
||||||
|
|
||||||
|
self.sockets = list()
|
||||||
|
self.img_data = None
|
||||||
|
self.fps = fps
|
||||||
|
self.timer_delta = 1000 / fps
|
||||||
|
self.timer = QtCore.QTimer()
|
||||||
|
self.timer.timeout.connect(self.send_image)
|
||||||
|
self.timer.start(self.timer_delta)
|
||||||
|
self.stream_clients = list()
|
||||||
|
self.get_regex = re.compile("^GET /(\w+?)\.(\w+?) HTTP/(\d+\.\d+)$")
|
||||||
|
self.host_regex = re.compile("^Host: (\w+?):(\d+)$")
|
||||||
|
self.html_map = dict()
|
||||||
|
|
||||||
|
def handle_request(self):
|
||||||
|
sock = self.sender()
|
||||||
|
sock_id = id(sock)
|
||||||
|
logger.info("handle_request: sock_id=%r", sock_id)
|
||||||
|
if sock.state() in (
|
||||||
|
QTcpSocket.UnconnectedState, QTcpSocket.ClosingState):
|
||||||
|
logger.info("connection closed")
|
||||||
|
self.sockets.remove(sock)
|
||||||
|
sock.deleteLater()
|
||||||
|
return
|
||||||
|
|
||||||
|
client_data = str(sock.readAll())
|
||||||
|
logger.info("request %r", client_data)
|
||||||
|
line = client_data.split("\r\n")[0]
|
||||||
|
logger.info("first line: %r", line)
|
||||||
|
try:
|
||||||
|
resource, ext, http_version = self.get_regex.match(line).groups()
|
||||||
|
logger.info(
|
||||||
|
"resource=%r, ext=%r, http_version=%r",
|
||||||
|
resource, ext, http_version)
|
||||||
|
except AttributeError:
|
||||||
|
try:
|
||||||
|
host, port = self.host_regex.match(line).groups()
|
||||||
|
logger.info("found host header %r %r", host, port)
|
||||||
|
#return
|
||||||
|
#sock.write("HTTP/1.1 501 Not Implemented\r\n")
|
||||||
|
return
|
||||||
|
except AttributeError:
|
||||||
|
logger.info("no matching request - sending 404 not found")
|
||||||
|
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
if ext == "ico":
|
||||||
|
directory = self.widget.pubdir()
|
||||||
|
try:
|
||||||
|
data = open(
|
||||||
|
os.path.join(directory, "favicon.ico"), "rb").read()
|
||||||
|
except IOError:
|
||||||
|
logger.error(
|
||||||
|
"request not found/handled - sending 404 not found")
|
||||||
|
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type:' \
|
||||||
|
'image/x-ico\r\n\r\n%s' % data))
|
||||||
|
elif ext == "html":
|
||||||
|
directory = self.widget.pubdir()
|
||||||
|
try:
|
||||||
|
data = open(os.path.join(
|
||||||
|
directory, "index.html"), "rb").read() % sock_id
|
||||||
|
self.html_map[sock_id] = None
|
||||||
|
except IOError:
|
||||||
|
logger.error(
|
||||||
|
"request not found/handled - sending 404 not found")
|
||||||
|
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type:"\
|
||||||
|
"text/html;encoding: utf-8\r\n\r\n%s' % data))
|
||||||
|
elif ext == "mjpeg":
|
||||||
|
try:
|
||||||
|
_, html_sock_id = resource.split("_", 1)
|
||||||
|
html_sock_id = int(html_sock_id)
|
||||||
|
except ValueError:
|
||||||
|
html_sock_id = None
|
||||||
|
|
||||||
|
if sock not in self.stream_clients:
|
||||||
|
logger.info("starting streaming...")
|
||||||
|
if html_sock_id is not None:
|
||||||
|
self.html_map[html_sock_id] = sock
|
||||||
|
self.stream_clients.append(sock)
|
||||||
|
sock.write(QByteArray('HTTP/1.1 200 Ok\r\n" \
|
||||||
|
"Content-Type: multipart/x-mixed-replace;" \
|
||||||
|
"boundary=--2342\r\n\r\n'))
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
"request not found/handled - sending 404 not found")
|
||||||
|
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||||
|
|
||||||
|
def slot_remove_connection(self):
|
||||||
|
try:
|
||||||
|
sock = self.sender()
|
||||||
|
except RuntimeError:
|
||||||
|
return
|
||||||
|
if sock.state() == QTcpSocket.UnconnectedState:
|
||||||
|
self.__remove_connection(sock)
|
||||||
|
|
||||||
|
def __remove_connection(self, sock):
|
||||||
|
sock_id = id(sock)
|
||||||
|
sock.disconnected.disconnect(self.slot_remove_connection)
|
||||||
|
sock.close()
|
||||||
|
sock.deleteLater()
|
||||||
|
try:
|
||||||
|
self.sockets.remove(sock)
|
||||||
|
logger.info("connection %r removed", sock_id)
|
||||||
|
except ValueError, msg:
|
||||||
|
logger.info("connection %r was not stored?", sock_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.stream_clients.remove(sock)
|
||||||
|
except ValueError:
|
||||||
|
logger.info("connection %r was not streaming", sock_id)
|
||||||
|
|
||||||
|
# cleaning up streaming connections if that sock is serving index.html
|
||||||
|
try:
|
||||||
|
stream_client = self.html_map.pop(sock_id)
|
||||||
|
except KeyError:
|
||||||
|
logger.info("connection %r has no child connections", sock_id)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
stream_client.close()
|
||||||
|
stream_client.deleteLater()
|
||||||
|
except AttributeError, msg:
|
||||||
|
logger.info("no stream client")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.stream_clients.remove(stream_client)
|
||||||
|
logger.info("child connection %r removed from streaming",
|
||||||
|
id(stream_client))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.sockets.remove(stream_client)
|
||||||
|
logger.info("child connection %r removed from storage",
|
||||||
|
id(stream_client))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def send_image(self):
|
||||||
|
if not self.stream_clients:
|
||||||
|
return
|
||||||
|
|
||||||
|
img_data = self.widget.render_image()
|
||||||
|
len_data = len(img_data)
|
||||||
|
array = QByteArray("--2342\r\nContent-Type: image/jpeg\r\n" \
|
||||||
|
"Content-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len_data, img_data))
|
||||||
|
for sock in self.stream_clients:
|
||||||
|
sock.write(array)
|
||||||
|
|
||||||
|
def new_connection(self):
|
||||||
|
while self.hasPendingConnections():
|
||||||
|
sock = self.nextPendingConnection()
|
||||||
|
logger.info("new connection=%r", id(sock))
|
||||||
|
sock.readyRead.connect(self.handle_request)
|
||||||
|
sock.disconnected.connect(self.slot_remove_connection)
|
||||||
|
self.sockets.append(sock)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.stream_clients = list()
|
||||||
|
for sock in self.sockets:
|
||||||
|
sock.close()
|
||||||
|
sock.deleteLater()
|
||||||
|
self.sockets = list()
|
||||||
|
self.html_map = dict()
|
||||||
|
self.close()
|
|
@ -0,0 +1,164 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of chaosc and psychosis
|
||||||
|
#
|
||||||
|
# chaosc/psychosis is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# chaosc/psychosis is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with chaosc/psychosis. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 Stefan Kögl
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from chaosc.argparser_groups import *
|
||||||
|
from chaosc.lib import logger, resolve_host
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
|
||||||
|
from PyQt4.QtNetwork import QTcpServer
|
||||||
|
|
||||||
|
class MjpegStreamingServer(QTcpServer):
|
||||||
|
|
||||||
|
def __init__(self, server_address, parent=None):
|
||||||
|
super(MjpegStreamingServer, self).__init__(parent)
|
||||||
|
self.server_address = server_address
|
||||||
|
self.newConnection.connect(self.new_connection)
|
||||||
|
self.widget = parent
|
||||||
|
self.win_id = self.widget.winId()
|
||||||
|
self.sockets = list()
|
||||||
|
self.img_data = None
|
||||||
|
self.timer = QtCore.QTimer()
|
||||||
|
self.timer.timeout.connect(self.render_image)
|
||||||
|
self.timer.start(80)
|
||||||
|
self.stream_clients = list()
|
||||||
|
self.get_regex = re.compile("^GET /(\w+?)\.(\w+?) HTTP/(\d+\.\d+)$")
|
||||||
|
self.host_regex = re.compile("^Host: (\w+?):(\d+)$")
|
||||||
|
self.html_map = dict()
|
||||||
|
|
||||||
|
def handle_request(self):
|
||||||
|
sock = self.sender()
|
||||||
|
logger.info("handle_request: %s %d", sock.peerAddress(), sock.peerPort())
|
||||||
|
sock_id = id(sock)
|
||||||
|
if sock.state() in (QTcpSocket.UnconnectedState, QTcpSocket.ClosingState):
|
||||||
|
logger.info("connection closed")
|
||||||
|
self.sockets.remove(sock)
|
||||||
|
sock.deleteLater()
|
||||||
|
return
|
||||||
|
|
||||||
|
client_data = str(sock.readAll())
|
||||||
|
logger.info("request %r", client_data)
|
||||||
|
line = client_data.split("\r\n")[0]
|
||||||
|
logger.info("first line: %r", line)
|
||||||
|
try:
|
||||||
|
resource, ext, http_version = self.get_regex.match(line).groups()
|
||||||
|
logger.info("resource=%r, ext=%r, http_version=%r", resource, ext, http_version)
|
||||||
|
except AttributeError:
|
||||||
|
try:
|
||||||
|
host, port = self.host_regex.match(line).groups()
|
||||||
|
print "found host header", host, port
|
||||||
|
return
|
||||||
|
#sock.write("HTTP/1.1 501 Not Implemented\r\n")
|
||||||
|
except AttributeError:
|
||||||
|
logger.info("no matching request - sending 404 not found")
|
||||||
|
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
if ext == "ico":
|
||||||
|
directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
data = open(os.path.join(directory, "favicon.ico"), "rb").read()
|
||||||
|
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type: image/x-ico\r\n\r\n%s' % data))
|
||||||
|
elif ext == "html":
|
||||||
|
directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
data = open(os.path.join(directory, "index.html"), "rb").read() % sock_id
|
||||||
|
self.html_map[sock_id] = None
|
||||||
|
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type: text/html;encoding: utf-8\r\n\r\n%s' % data))
|
||||||
|
elif ext == "mjpeg":
|
||||||
|
try:
|
||||||
|
_, html_sock_id = resource.split("_", 1)
|
||||||
|
html_sock_id = int(html_sock_id)
|
||||||
|
except ValueError:
|
||||||
|
html_sock_id = None
|
||||||
|
|
||||||
|
if sock not in self.stream_clients:
|
||||||
|
logger.info("starting streaming...")
|
||||||
|
if html_sock_id is not None:
|
||||||
|
self.html_map[html_sock_id] = sock
|
||||||
|
self.stream_clients.append(sock)
|
||||||
|
sock.write(QByteArray('HTTP/1.1 200 Ok\r\nContent-Type: multipart/x-mixed-replace; boundary=--2342\r\n\r\n'))
|
||||||
|
else:
|
||||||
|
logger.error("request not found/handled - sending 404 not found")
|
||||||
|
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||||
|
|
||||||
|
def remove_connection(self):
|
||||||
|
try:
|
||||||
|
sock = self.sender()
|
||||||
|
except RuntimeError:
|
||||||
|
return
|
||||||
|
sock_id = id(sock)
|
||||||
|
logger.info("remove_connection: sock=%r, sock_id=%r", sock, sock_id)
|
||||||
|
if sock.state() == QTcpSocket.UnconnectedState:
|
||||||
|
sock.disconnected.disconnect(self.remove_connection)
|
||||||
|
self.sockets.remove(sock)
|
||||||
|
logger.info("removed sock_id=%r", sock_id)
|
||||||
|
sock.close()
|
||||||
|
try:
|
||||||
|
self.stream_clients.remove(sock)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
stream_client = self.html_map.pop(sock_id)
|
||||||
|
except KeyError:
|
||||||
|
logger.info("socket has no child socket")
|
||||||
|
else:
|
||||||
|
stream_client.close()
|
||||||
|
try:
|
||||||
|
self.stream_clients.remove(stream_client)
|
||||||
|
logger.info("removed stream_client=%r", id(stream_client))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.sockets.remove(stream_client)
|
||||||
|
logger.info("removed child sock_id=%r", id(stream_client))
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def render_image(self):
|
||||||
|
if not self.stream_clients:
|
||||||
|
return
|
||||||
|
|
||||||
|
img_data = self.widget.render_image()
|
||||||
|
len_data = len(img_data)
|
||||||
|
array = QByteArray("--2342\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len_data, img_data))
|
||||||
|
for sock in self.stream_clients:
|
||||||
|
sock.write(array)
|
||||||
|
|
||||||
|
def new_connection(self):
|
||||||
|
while self.hasPendingConnections():
|
||||||
|
sock = self.nextPendingConnection()
|
||||||
|
logger.info("new connection=%r", id(sock))
|
||||||
|
sock.readyRead.connect(self.handle_request)
|
||||||
|
sock.disconnected.connect(self.remove_connection)
|
||||||
|
self.sockets.append(sock)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.stream_clients = list()
|
||||||
|
self.sockets = list()
|
||||||
|
self.html_map = dict()
|
||||||
|
self.close()
|
|
@ -0,0 +1,108 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of chaosc/psylib package
|
||||||
|
#
|
||||||
|
# chaosc/psylib is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# chaosc/psylib is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with chaosc/psylib. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 Stefan Kögl
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from PyQt4 import QtCore, QtGui
|
||||||
|
from PyQt4.QtCore import QBuffer, QByteArray
|
||||||
|
from PyQt4.QtNetwork import QUdpSocket, QHostAddress
|
||||||
|
|
||||||
|
|
||||||
|
from chaosc.lib import logger
|
||||||
|
|
||||||
|
try:
|
||||||
|
from chaosc.c_osc_lib import OSCMessage, decode_osc
|
||||||
|
except ImportError as e:
|
||||||
|
from chaosc.osc_lib import OSCMessage, decode_osc
|
||||||
|
|
||||||
|
|
||||||
|
class PsyQtClientBase(QtCore.QObject):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(PsyQtClientBase, self).__init__()
|
||||||
|
# periodically trap into python interpreter domain to catch signals etc
|
||||||
|
timer = QtCore.QTimer()
|
||||||
|
timer.start(2000)
|
||||||
|
timer.timeout.connect(lambda: None)
|
||||||
|
|
||||||
|
def sigint_handler(self, ex_cls, ex, traceback):
|
||||||
|
"""Handler for the SIGINT signal."""
|
||||||
|
if ex_cls == KeyboardInterrupt:
|
||||||
|
logger.info("found KeyboardInterrupt")
|
||||||
|
QtGui.QApplication.exit()
|
||||||
|
else:
|
||||||
|
logger.critical(''.join(traceback.format_tb(tb)))
|
||||||
|
logger.critical('{0}: {1}'.format(ex_cls, ex))
|
||||||
|
|
||||||
|
class PsyQtChaoscClientBase(PsyQtClientBase):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(PsyQtChaoscClientBase, self).__init__()
|
||||||
|
self.osc_sock = QUdpSocket(self)
|
||||||
|
logger.info("osc bind localhost %d", self.args.client_port)
|
||||||
|
self.osc_sock.bind(QHostAddress(self.args.client_host), self.args.client_port)
|
||||||
|
self.osc_sock.readyRead.connect(self.got_message)
|
||||||
|
self.osc_sock.error.connect(self.handle_osc_error)
|
||||||
|
self.subscribe()
|
||||||
|
|
||||||
|
def sigint_handler(self, ex_cls, ex, tb):
|
||||||
|
"""Handler for the SIGINT signal."""
|
||||||
|
logger.info("sigint_handler")
|
||||||
|
if ex_cls == KeyboardInterrupt:
|
||||||
|
logger.info("found KeyboardInterrupt")
|
||||||
|
self.unsubscribe()
|
||||||
|
QtGui.QApplication.exit()
|
||||||
|
else:
|
||||||
|
logger.critical(''.join(traceback.format_tb(tb)))
|
||||||
|
logger.critical('{0}: {1}'.format(ex_cls, ex))
|
||||||
|
|
||||||
|
def sigterm_handler(self, *args):
|
||||||
|
logger.info("sigterm_handler")
|
||||||
|
self.unsubscribe()
|
||||||
|
QtGui.QApplication.exit()
|
||||||
|
|
||||||
|
def subscribe(self):
|
||||||
|
logger.info("subscribe")
|
||||||
|
msg = OSCMessage("/subscribe")
|
||||||
|
msg.appendTypedArg("localhost", "s")
|
||||||
|
msg.appendTypedArg(self.args.client_port, "i")
|
||||||
|
msg.appendTypedArg(self.args.authenticate, "s")
|
||||||
|
if self.args.subscriber_label is not None:
|
||||||
|
msg.appendTypedArg(self.args.subscriber_label, "s")
|
||||||
|
self.osc_sock.writeDatagram(QByteArray(msg.encode_osc()), QHostAddress(self.args.chaosc_host), self.args.chaosc_port)
|
||||||
|
|
||||||
|
def unsubscribe(self):
|
||||||
|
logger.info("unsubscribe")
|
||||||
|
msg = OSCMessage("/unsubscribe")
|
||||||
|
msg.appendTypedArg("localhost", "s")
|
||||||
|
msg.appendTypedArg(self.args.client_port, "i")
|
||||||
|
msg.appendTypedArg(self.args.authenticate, "s")
|
||||||
|
self.osc_sock.writeDatagram(QByteArray(msg.encode_osc()), QHostAddress(self.args.chaosc_host), self.args.chaosc_port)
|
||||||
|
|
||||||
|
def handle_osc_error(self, error):
|
||||||
|
logger.info("osc socket error %d", error)
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
logger.info("closeEvent", event)
|
||||||
|
self.unsubscribe()
|
||||||
|
event.accept()
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
if sys.version_info >= (3,):
|
||||||
|
extras['use_2to3'] = True
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='psylib',
|
||||||
|
version="0.2",
|
||||||
|
packages=find_packages(exclude=["scripts",]),
|
||||||
|
|
||||||
|
include_package_data = True,
|
||||||
|
|
||||||
|
exclude_package_data = {'': ['.gitignore']},
|
||||||
|
|
||||||
|
zip_safe = False,
|
||||||
|
|
||||||
|
# pypi metadata
|
||||||
|
author = "Stefan Kögl",
|
||||||
|
|
||||||
|
# FIXME: add author email
|
||||||
|
author_email = "hotte@ctdo.de",
|
||||||
|
description = "library for psychosis",
|
||||||
|
|
||||||
|
# FIXME: add long_description
|
||||||
|
long_description = """
|
||||||
|
""",
|
||||||
|
|
||||||
|
# FIXME: add license
|
||||||
|
license = "GPL",
|
||||||
|
|
||||||
|
# FIXME: add keywords
|
||||||
|
keywords = "",
|
||||||
|
|
||||||
|
# FIXME: add download url
|
||||||
|
url = "",
|
||||||
|
)
|
|
@ -0,0 +1,556 @@
|
||||||
|
#!python
|
||||||
|
"""Bootstrap distribute installation
|
||||||
|
|
||||||
|
If you want to use setuptools in your package's setup.py, just include this
|
||||||
|
file in the same directory with it, and add this to the top of your setup.py::
|
||||||
|
|
||||||
|
from distribute_setup import use_setuptools
|
||||||
|
use_setuptools()
|
||||||
|
|
||||||
|
If you want to require a specific version of setuptools, set a download
|
||||||
|
mirror, or use an alternate download directory, you can do so by supplying
|
||||||
|
the appropriate options to ``use_setuptools()``.
|
||||||
|
|
||||||
|
This file can also be run as a script to install or upgrade setuptools.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import fnmatch
|
||||||
|
import tempfile
|
||||||
|
import tarfile
|
||||||
|
import optparse
|
||||||
|
|
||||||
|
from distutils import log
|
||||||
|
|
||||||
|
try:
|
||||||
|
from site import USER_SITE
|
||||||
|
except ImportError:
|
||||||
|
USER_SITE = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
return subprocess.call(args) == 0
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# will be used for python 2.3
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
# quoting arguments if windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
def quote(arg):
|
||||||
|
if ' ' in arg:
|
||||||
|
return '"%s"' % arg
|
||||||
|
return arg
|
||||||
|
args = [quote(arg) for arg in args]
|
||||||
|
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||||
|
|
||||||
|
DEFAULT_VERSION = "0.6.49"
|
||||||
|
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||||
|
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||||
|
|
||||||
|
SETUPTOOLS_PKG_INFO = """\
|
||||||
|
Metadata-Version: 1.0
|
||||||
|
Name: setuptools
|
||||||
|
Version: %s
|
||||||
|
Summary: xxxx
|
||||||
|
Home-page: xxx
|
||||||
|
Author: xxx
|
||||||
|
Author-email: xxx
|
||||||
|
License: xxx
|
||||||
|
Description: xxx
|
||||||
|
""" % SETUPTOOLS_FAKED_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def _install(tarball, install_args=()):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# installing
|
||||||
|
log.warn('Installing Distribute')
|
||||||
|
if not _python_cmd('setup.py', 'install', *install_args):
|
||||||
|
log.warn('Something went wrong during the installation.')
|
||||||
|
log.warn('See the error message above.')
|
||||||
|
# exitcode will be 2
|
||||||
|
return 2
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_egg(egg, tarball, to_dir):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# building an egg
|
||||||
|
log.warn('Building a Distribute egg in %s', to_dir)
|
||||||
|
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
# returning the result
|
||||||
|
log.warn(egg)
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
raise IOError('Could not build the egg.')
|
||||||
|
|
||||||
|
|
||||||
|
def _do_download(version, download_base, to_dir, download_delay):
|
||||||
|
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||||
|
% (version, sys.version_info[0], sys.version_info[1]))
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
tarball = download_setuptools(version, download_base,
|
||||||
|
to_dir, download_delay)
|
||||||
|
_build_egg(egg, tarball, to_dir)
|
||||||
|
sys.path.insert(0, egg)
|
||||||
|
import setuptools
|
||||||
|
setuptools.bootstrap_install_from = egg
|
||||||
|
|
||||||
|
|
||||||
|
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
was_imported = 'pkg_resources' in sys.modules or \
|
||||||
|
'setuptools' in sys.modules
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
# Setuptools 0.7b and later is a suitable (and preferable)
|
||||||
|
# substitute for any Distribute version.
|
||||||
|
try:
|
||||||
|
pkg_resources.require("setuptools>=0.7b")
|
||||||
|
return
|
||||||
|
except (pkg_resources.DistributionNotFound,
|
||||||
|
pkg_resources.VersionConflict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not hasattr(pkg_resources, '_distribute'):
|
||||||
|
if not no_fake:
|
||||||
|
_fake_setuptools()
|
||||||
|
raise ImportError
|
||||||
|
except ImportError:
|
||||||
|
return _do_download(version, download_base, to_dir, download_delay)
|
||||||
|
try:
|
||||||
|
pkg_resources.require("distribute>=" + version)
|
||||||
|
return
|
||||||
|
except pkg_resources.VersionConflict:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if was_imported:
|
||||||
|
sys.stderr.write(
|
||||||
|
"The required version of distribute (>=%s) is not available,\n"
|
||||||
|
"and can't be installed while this script is running. Please\n"
|
||||||
|
"install a more recent version first, using\n"
|
||||||
|
"'easy_install -U distribute'."
|
||||||
|
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
except pkg_resources.DistributionNotFound:
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
finally:
|
||||||
|
if not no_fake:
|
||||||
|
_create_fake_setuptools_pkg_info(to_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, delay=15):
|
||||||
|
"""Download distribute from a specified location and return its filename
|
||||||
|
|
||||||
|
`version` should be a valid distribute version number that is available
|
||||||
|
as an egg for download under the `download_base` URL (which should end
|
||||||
|
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||||
|
`delay` is the number of seconds to pause before an actual download
|
||||||
|
attempt.
|
||||||
|
"""
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
try:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
except ImportError:
|
||||||
|
from urllib2 import urlopen
|
||||||
|
tgz_name = "distribute-%s.tar.gz" % version
|
||||||
|
url = download_base + tgz_name
|
||||||
|
saveto = os.path.join(to_dir, tgz_name)
|
||||||
|
src = dst = None
|
||||||
|
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||||
|
try:
|
||||||
|
log.warn("Downloading %s", url)
|
||||||
|
src = urlopen(url)
|
||||||
|
# Read/write all in one block, so we don't create a corrupt file
|
||||||
|
# if the download is interrupted.
|
||||||
|
data = src.read()
|
||||||
|
dst = open(saveto, "wb")
|
||||||
|
dst.write(data)
|
||||||
|
finally:
|
||||||
|
if src:
|
||||||
|
src.close()
|
||||||
|
if dst:
|
||||||
|
dst.close()
|
||||||
|
return os.path.realpath(saveto)
|
||||||
|
|
||||||
|
|
||||||
|
def _no_sandbox(function):
|
||||||
|
def __no_sandbox(*args, **kw):
|
||||||
|
try:
|
||||||
|
from setuptools.sandbox import DirectorySandbox
|
||||||
|
if not hasattr(DirectorySandbox, '_old'):
|
||||||
|
def violation(*args):
|
||||||
|
pass
|
||||||
|
DirectorySandbox._old = DirectorySandbox._violation
|
||||||
|
DirectorySandbox._violation = violation
|
||||||
|
patched = True
|
||||||
|
else:
|
||||||
|
patched = False
|
||||||
|
except ImportError:
|
||||||
|
patched = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
return function(*args, **kw)
|
||||||
|
finally:
|
||||||
|
if patched:
|
||||||
|
DirectorySandbox._violation = DirectorySandbox._old
|
||||||
|
del DirectorySandbox._old
|
||||||
|
|
||||||
|
return __no_sandbox
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_file(path, content):
|
||||||
|
"""Will backup the file then patch it"""
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
if existing_content == content:
|
||||||
|
# already patched
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return False
|
||||||
|
log.warn('Patching...')
|
||||||
|
_rename_path(path)
|
||||||
|
f = open(path, 'w')
|
||||||
|
try:
|
||||||
|
f.write(content)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_file = _no_sandbox(_patch_file)
|
||||||
|
|
||||||
|
|
||||||
|
def _same_content(path, content):
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
return existing_content == content
|
||||||
|
|
||||||
|
|
||||||
|
def _rename_path(path):
|
||||||
|
new_name = path + '.OLD.%s' % time.time()
|
||||||
|
log.warn('Renaming %s to %s', path, new_name)
|
||||||
|
os.rename(path, new_name)
|
||||||
|
return new_name
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_flat_installation(placeholder):
|
||||||
|
if not os.path.isdir(placeholder):
|
||||||
|
log.warn('Unkown installation at %s', placeholder)
|
||||||
|
return False
|
||||||
|
found = False
|
||||||
|
for file in os.listdir(placeholder):
|
||||||
|
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
log.warn('Could not locate setuptools*.egg-info')
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Moving elements out of the way...')
|
||||||
|
pkg_info = os.path.join(placeholder, file)
|
||||||
|
if os.path.isdir(pkg_info):
|
||||||
|
patched = _patch_egg_dir(pkg_info)
|
||||||
|
else:
|
||||||
|
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||||
|
|
||||||
|
if not patched:
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
# now let's move the files out of the way
|
||||||
|
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||||
|
element = os.path.join(placeholder, element)
|
||||||
|
if os.path.exists(element):
|
||||||
|
_rename_path(element)
|
||||||
|
else:
|
||||||
|
log.warn('Could not find the %s element of the '
|
||||||
|
'Setuptools distribution', element)
|
||||||
|
return True
|
||||||
|
|
||||||
|
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||||
|
|
||||||
|
|
||||||
|
def _after_install(dist):
|
||||||
|
log.warn('After install bootstrap.')
|
||||||
|
placeholder = dist.get_command_obj('install').install_purelib
|
||||||
|
_create_fake_setuptools_pkg_info(placeholder)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_fake_setuptools_pkg_info(placeholder):
|
||||||
|
if not placeholder or not os.path.exists(placeholder):
|
||||||
|
log.warn('Could not find the install location')
|
||||||
|
return
|
||||||
|
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||||
|
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||||
|
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||||
|
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
log.warn('%s already exists', pkg_info)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Creating %s', pkg_info)
|
||||||
|
try:
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
except EnvironmentError:
|
||||||
|
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||||
|
log.warn('Creating %s', pth_file)
|
||||||
|
f = open(pth_file, 'w')
|
||||||
|
try:
|
||||||
|
f.write(os.path.join(os.curdir, setuptools_file))
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||||
|
_create_fake_setuptools_pkg_info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_egg_dir(path):
|
||||||
|
# let's check if it's already patched
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
_rename_path(path)
|
||||||
|
os.mkdir(path)
|
||||||
|
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def _before_install():
|
||||||
|
log.warn('Before install bootstrap.')
|
||||||
|
_fake_setuptools()
|
||||||
|
|
||||||
|
|
||||||
|
def _under_prefix(location):
|
||||||
|
if 'install' not in sys.argv:
|
||||||
|
return True
|
||||||
|
args = sys.argv[sys.argv.index('install') + 1:]
|
||||||
|
for index, arg in enumerate(args):
|
||||||
|
for option in ('--root', '--prefix'):
|
||||||
|
if arg.startswith('%s=' % option):
|
||||||
|
top_dir = arg.split('root=')[-1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
elif arg == option:
|
||||||
|
if len(args) > index:
|
||||||
|
top_dir = args[index + 1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
if arg == '--user' and USER_SITE is not None:
|
||||||
|
return location.startswith(USER_SITE)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _fake_setuptools():
|
||||||
|
log.warn('Scanning installed packages')
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
except ImportError:
|
||||||
|
# we're cool
|
||||||
|
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||||
|
return
|
||||||
|
ws = pkg_resources.working_set
|
||||||
|
try:
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||||
|
)
|
||||||
|
except TypeError:
|
||||||
|
# old distribute API
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools')
|
||||||
|
)
|
||||||
|
|
||||||
|
if setuptools_dist is None:
|
||||||
|
log.warn('No setuptools distribution found')
|
||||||
|
return
|
||||||
|
# detecting if it was already faked
|
||||||
|
setuptools_location = setuptools_dist.location
|
||||||
|
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||||
|
|
||||||
|
# if --root or --preix was provided, and if
|
||||||
|
# setuptools is not located in them, we don't patch it
|
||||||
|
if not _under_prefix(setuptools_location):
|
||||||
|
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||||
|
' in another location')
|
||||||
|
return
|
||||||
|
|
||||||
|
# let's see if its an egg
|
||||||
|
if not setuptools_location.endswith('.egg'):
|
||||||
|
log.warn('Non-egg installation')
|
||||||
|
res = _remove_flat_installation(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log.warn('Egg installation')
|
||||||
|
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if (os.path.exists(pkg_info) and
|
||||||
|
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return
|
||||||
|
log.warn('Patching...')
|
||||||
|
# let's create a fake egg replacing setuptools one
|
||||||
|
res = _patch_egg_dir(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
log.warn('Patching complete.')
|
||||||
|
_relaunch()
|
||||||
|
|
||||||
|
|
||||||
|
def _relaunch():
|
||||||
|
log.warn('Relaunching...')
|
||||||
|
# we have to relaunch the process
|
||||||
|
# pip marker to avoid a relaunch bug
|
||||||
|
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||||
|
_cmd2 = ['-c', 'install', '--record']
|
||||||
|
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||||
|
sys.argv[0] = 'setup.py'
|
||||||
|
args = [sys.executable] + sys.argv
|
||||||
|
sys.exit(subprocess.call(args))
|
||||||
|
|
||||||
|
|
||||||
|
def _extractall(self, path=".", members=None):
|
||||||
|
"""Extract all members from the archive to the current working
|
||||||
|
directory and set owner, modification time and permissions on
|
||||||
|
directories afterwards. `path' specifies a different directory
|
||||||
|
to extract to. `members' is optional and must be a subset of the
|
||||||
|
list returned by getmembers().
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
import operator
|
||||||
|
from tarfile import ExtractError
|
||||||
|
directories = []
|
||||||
|
|
||||||
|
if members is None:
|
||||||
|
members = self
|
||||||
|
|
||||||
|
for tarinfo in members:
|
||||||
|
if tarinfo.isdir():
|
||||||
|
# Extract directories with a safe mode.
|
||||||
|
directories.append(tarinfo)
|
||||||
|
tarinfo = copy.copy(tarinfo)
|
||||||
|
tarinfo.mode = 448 # decimal for oct 0700
|
||||||
|
self.extract(tarinfo, path)
|
||||||
|
|
||||||
|
# Reverse sort directories.
|
||||||
|
if sys.version_info < (2, 4):
|
||||||
|
def sorter(dir1, dir2):
|
||||||
|
return cmp(dir1.name, dir2.name)
|
||||||
|
directories.sort(sorter)
|
||||||
|
directories.reverse()
|
||||||
|
else:
|
||||||
|
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||||
|
|
||||||
|
# Set correct owner, mtime and filemode on directories.
|
||||||
|
for tarinfo in directories:
|
||||||
|
dirpath = os.path.join(path, tarinfo.name)
|
||||||
|
try:
|
||||||
|
self.chown(tarinfo, dirpath)
|
||||||
|
self.utime(tarinfo, dirpath)
|
||||||
|
self.chmod(tarinfo, dirpath)
|
||||||
|
except ExtractError:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if self.errorlevel > 1:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self._dbg(1, "tarfile: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_install_args(options):
|
||||||
|
"""
|
||||||
|
Build the arguments to 'python setup.py install' on the distribute package
|
||||||
|
"""
|
||||||
|
install_args = []
|
||||||
|
if options.user_install:
|
||||||
|
if sys.version_info < (2, 6):
|
||||||
|
log.warn("--user requires Python 2.6 or later")
|
||||||
|
raise SystemExit(1)
|
||||||
|
install_args.append('--user')
|
||||||
|
return install_args
|
||||||
|
|
||||||
|
def _parse_args():
|
||||||
|
"""
|
||||||
|
Parse the command line for options
|
||||||
|
"""
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'--user', dest='user_install', action='store_true', default=False,
|
||||||
|
help='install in user site package (requires Python 2.6 or later)')
|
||||||
|
parser.add_option(
|
||||||
|
'--download-base', dest='download_base', metavar="URL",
|
||||||
|
default=DEFAULT_URL,
|
||||||
|
help='alternative URL from where to download the distribute package')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
# positional arguments are ignored
|
||||||
|
return options
|
||||||
|
|
||||||
|
def main(version=DEFAULT_VERSION):
|
||||||
|
"""Install or upgrade setuptools and EasyInstall"""
|
||||||
|
options = _parse_args()
|
||||||
|
tarball = download_setuptools(download_base=options.download_base)
|
||||||
|
return _install(tarball, _build_install_args(options))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
|
@ -28,6 +28,7 @@ import time
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from chaosc.argparser_groups import ArgParser
|
from chaosc.argparser_groups import ArgParser
|
||||||
|
from chaosc.lib import logger
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -47,8 +48,8 @@ class Platform(object):
|
||||||
|
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
print "connect serial"
|
logger.info("connect serial")
|
||||||
print "waiting for the device %r to come up" % self.args.device
|
logger.info("waiting for the device %r to come up", self.args.device)
|
||||||
self.serial_sock = serial.Serial()
|
self.serial_sock = serial.Serial()
|
||||||
self.serial_sock.port = self.args.device
|
self.serial_sock.port = self.args.device
|
||||||
self.serial_sock.baudrate = 115200
|
self.serial_sock.baudrate = 115200
|
||||||
|
@ -57,7 +58,7 @@ class Platform(object):
|
||||||
try:
|
try:
|
||||||
self.serial_sock.open()
|
self.serial_sock.open()
|
||||||
except (serial.serialutil.SerialException, os.error), e:
|
except (serial.serialutil.SerialException, os.error), e:
|
||||||
print "serial error", e
|
logger.exception(e)
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -66,12 +67,12 @@ class Platform(object):
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.serial_sock is not None:
|
if self.serial_sock is not None:
|
||||||
print "close serial"
|
logger.info("close serial")
|
||||||
self.serial_sock.close()
|
self.serial_sock.close()
|
||||||
|
|
||||||
|
|
||||||
def reconnect(self):
|
def reconnect(self):
|
||||||
print "reconnect serial"
|
logger.info("reconnect serial")
|
||||||
self.close()
|
self.close()
|
||||||
self.connect()
|
self.connect()
|
||||||
|
|
||||||
|
|
|
@ -39,20 +39,19 @@ def main():
|
||||||
#print repr(data)
|
#print repr(data)
|
||||||
except (socket.error, serial.serialutil.SerialException), msg:
|
except (socket.error, serial.serialutil.SerialException), msg:
|
||||||
# got disconnected?
|
# got disconnected?
|
||||||
print "serial socket error!!!", msg
|
logger.exception(msg)
|
||||||
platform.reconnect()
|
platform.reconnect()
|
||||||
|
|
||||||
print "data", repr(data)
|
|
||||||
try:
|
try:
|
||||||
airFlow, emg, temp = data.split(";")
|
airFlow, emg, temp = data.split(";")
|
||||||
except ValueError, e:
|
except ValueError, msg:
|
||||||
print e
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
airFlow = int(airFlow)
|
airFlow = int(airFlow)
|
||||||
except ValueError, e:
|
except ValueError, msg:
|
||||||
print e
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -60,14 +59,14 @@ def main():
|
||||||
osc_message.appendTypedArg(airFlow, "i")
|
osc_message.appendTypedArg(airFlow, "i")
|
||||||
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
||||||
except socket.error, msg:
|
except socket.error, msg:
|
||||||
print "cannot connect to chaosc", msg
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
emg = int(emg)
|
emg = int(emg)
|
||||||
except ValueError, e:
|
except ValueError, msg:
|
||||||
print e
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -75,14 +74,14 @@ def main():
|
||||||
osc_message.appendTypedArg(emg, "i")
|
osc_message.appendTypedArg(emg, "i")
|
||||||
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
||||||
except socket.error, msg:
|
except socket.error, msg:
|
||||||
print "cannot connect to chaosc", msg
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
temp = int(temp)
|
temp = int(temp)
|
||||||
except ValueError, e:
|
except ValueError, msg:
|
||||||
print e
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -90,7 +89,7 @@ def main():
|
||||||
osc_message.appendTypedArg(temp, "i")
|
osc_message.appendTypedArg(temp, "i")
|
||||||
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
||||||
except socket.error, msg:
|
except socket.error, msg:
|
||||||
print "cannot connect to chaosc", msg
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,11 +51,11 @@ def main():
|
||||||
except TypeError, e:
|
except TypeError, e:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if msg_count >= 20:
|
#if msg_count >= 20:
|
||||||
logger.info("value = %d", t)
|
# logger.info("value = %d", t)
|
||||||
msg_count = 0
|
# msg_count = 0
|
||||||
else:
|
#else:
|
||||||
msg_count += 1
|
# msg_count += 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
osc_message = OSCMessage("/%s/ekg" % actor)
|
osc_message = OSCMessage("/%s/ekg" % actor)
|
||||||
|
|
|
@ -29,7 +29,6 @@ import datetime
|
||||||
try:
|
try:
|
||||||
from chaosc.c_osc_lib import OSCMessage
|
from chaosc.c_osc_lib import OSCMessage
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
print(e)
|
|
||||||
from chaosc.osc_lib import OSCMessage
|
from chaosc.osc_lib import OSCMessage
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@ class Forwarder(object):
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Close all resources and unpublish service"""
|
"""Close all resources and unpublish service"""
|
||||||
print "%s: closing..." % (self.device, )
|
logger.info("%s: closing...", self.device)
|
||||||
self.serial.close()
|
self.serial.close()
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,7 +57,6 @@ class EHealth2OSC(Forwarder):
|
||||||
|
|
||||||
def handle_read(self, osc_sock):
|
def handle_read(self, osc_sock):
|
||||||
data = self.serial.readline()[:-2]
|
data = self.serial.readline()[:-2]
|
||||||
print repr(data)
|
|
||||||
try:
|
try:
|
||||||
airFlow, emg, temp = data.split(";")
|
airFlow, emg, temp = data.split(";")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -106,7 +104,7 @@ class RingBuffer(object):
|
||||||
self.head = (self.head + 1) % self.length
|
self.head = (self.head + 1) % self.length
|
||||||
|
|
||||||
def getData(self):
|
def getData(self):
|
||||||
print "getData", self.ring_buf, self.head
|
#print "getData", self.ring_buf, self.head
|
||||||
data = list()
|
data = list()
|
||||||
for i in range(7, 1, -1):
|
for i in range(7, 1, -1):
|
||||||
value = self.ring_buf[(self.head - i) % self.length]
|
value = self.ring_buf[(self.head - i) % self.length]
|
||||||
|
@ -146,7 +144,7 @@ class Pulse2OSC(Forwarder):
|
||||||
osc_message.appendTypedArg(heart_rate, "i")
|
osc_message.appendTypedArg(heart_rate, "i")
|
||||||
osc_message.appendTypedArg(o2, "i")
|
osc_message.appendTypedArg(o2, "i")
|
||||||
osc_sock.sendall(osc_message.encode_osc())
|
osc_sock.sendall(osc_message.encode_osc())
|
||||||
print "heartbeat", datetime.datetime.now(), heart_signal
|
#print "heartbeat", datetime.datetime.now(), heart_signal
|
||||||
self.heartbeat_on = True
|
self.heartbeat_on = True
|
||||||
elif pulse == 1 and self.heartbeat_on:
|
elif pulse == 1 and self.heartbeat_on:
|
||||||
#print "off heartbeat", datetime.datetime.now(), heart_signal
|
#print "off heartbeat", datetime.datetime.now(), heart_signal
|
||||||
|
|
|
@ -41,7 +41,7 @@ class RingBuffer(object):
|
||||||
self.head = (self.head + 1) % self.length
|
self.head = (self.head + 1) % self.length
|
||||||
|
|
||||||
def getData(self):
|
def getData(self):
|
||||||
print "getData", self.ring_buf, self.head
|
#print "getData", self.ring_buf, self.head
|
||||||
data = list()
|
data = list()
|
||||||
for i in range(self.length + 1, 1, -1):
|
for i in range(self.length + 1, 1, -1):
|
||||||
value = self.ring_buf[(self.head - i) % self.length]
|
value = self.ring_buf[(self.head - i) % self.length]
|
||||||
|
@ -52,7 +52,7 @@ class RingBuffer(object):
|
||||||
raise ValueError("not complete - reset ringbuffer")
|
raise ValueError("not complete - reset ringbuffer")
|
||||||
data.append(value)
|
data.append(value)
|
||||||
if data[0] != 0x0 or data[1] != 0xff:
|
if data[0] != 0x0 or data[1] != 0xff:
|
||||||
print "issue", data
|
#print "issue", data
|
||||||
self.reset()
|
self.reset()
|
||||||
self.ring_buf[0] = 0
|
self.ring_buf[0] = 0
|
||||||
self.head = 1
|
self.head = 1
|
||||||
|
@ -77,7 +77,7 @@ def main():
|
||||||
continue
|
continue
|
||||||
except (socket.error, serial.serialutil.SerialException), msg:
|
except (socket.error, serial.serialutil.SerialException), msg:
|
||||||
# got disconnected?
|
# got disconnected?
|
||||||
print "serial socket error!!!", msg
|
logger.exception(msg)
|
||||||
platform.reconnect()
|
platform.reconnect()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -91,8 +91,8 @@ def main():
|
||||||
if t == 0:
|
if t == 0:
|
||||||
try:
|
try:
|
||||||
heart_signal, heart_rate, o2, pulse = buf.getData()
|
heart_signal, heart_rate, o2, pulse = buf.getData()
|
||||||
except ValueError, e:
|
except ValueError, msg:
|
||||||
print e
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if pulse == 245 and not heartbeat_on:
|
if pulse == 245 and not heartbeat_on:
|
||||||
|
@ -103,12 +103,12 @@ def main():
|
||||||
osc_message.appendTypedArg(heart_rate, "i")
|
osc_message.appendTypedArg(heart_rate, "i")
|
||||||
osc_message.appendTypedArg(o2, "i")
|
osc_message.appendTypedArg(o2, "i")
|
||||||
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
||||||
print "on heartbeat", datetime.now(), heart_signal, heart_rate, o2, pulse
|
#print "on heartbeat", datetime.now(), heart_signal, heart_rate, o2, pulse
|
||||||
except socket.error, msg:
|
except socket.error, msg:
|
||||||
print "cannot connect to chaosc"
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
elif pulse == 1 and heartbeat_on:
|
elif pulse == 1 and heartbeat_on:
|
||||||
print "off heartbeat", datetime.now(), heart_signal, heart_rate, o2, pulse
|
#print "off heartbeat", datetime.now(), heart_signal, heart_rate, o2, pulse
|
||||||
heartbeat_on = False
|
heartbeat_on = False
|
||||||
try:
|
try:
|
||||||
osc_message = OSCMessage("/%s/heartbeat" % actor)
|
osc_message = OSCMessage("/%s/heartbeat" % actor)
|
||||||
|
@ -117,7 +117,7 @@ def main():
|
||||||
osc_message.appendTypedArg(o2, "i")
|
osc_message.appendTypedArg(o2, "i")
|
||||||
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
platform.osc_sock.sendto(osc_message.encode_osc(), platform.remote)
|
||||||
except socket.error, msg:
|
except socket.error, msg:
|
||||||
print "cannot connect to chaosc"
|
logger.exception(msg)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,556 @@
|
||||||
|
#!python
|
||||||
|
"""Bootstrap distribute installation
|
||||||
|
|
||||||
|
If you want to use setuptools in your package's setup.py, just include this
|
||||||
|
file in the same directory with it, and add this to the top of your setup.py::
|
||||||
|
|
||||||
|
from distribute_setup import use_setuptools
|
||||||
|
use_setuptools()
|
||||||
|
|
||||||
|
If you want to require a specific version of setuptools, set a download
|
||||||
|
mirror, or use an alternate download directory, you can do so by supplying
|
||||||
|
the appropriate options to ``use_setuptools()``.
|
||||||
|
|
||||||
|
This file can also be run as a script to install or upgrade setuptools.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import fnmatch
|
||||||
|
import tempfile
|
||||||
|
import tarfile
|
||||||
|
import optparse
|
||||||
|
|
||||||
|
from distutils import log
|
||||||
|
|
||||||
|
try:
|
||||||
|
from site import USER_SITE
|
||||||
|
except ImportError:
|
||||||
|
USER_SITE = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
return subprocess.call(args) == 0
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# will be used for python 2.3
|
||||||
|
def _python_cmd(*args):
|
||||||
|
args = (sys.executable,) + args
|
||||||
|
# quoting arguments if windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
def quote(arg):
|
||||||
|
if ' ' in arg:
|
||||||
|
return '"%s"' % arg
|
||||||
|
return arg
|
||||||
|
args = [quote(arg) for arg in args]
|
||||||
|
return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
|
||||||
|
|
||||||
|
DEFAULT_VERSION = "0.6.49"
|
||||||
|
DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
|
||||||
|
SETUPTOOLS_FAKED_VERSION = "0.6c11"
|
||||||
|
|
||||||
|
SETUPTOOLS_PKG_INFO = """\
|
||||||
|
Metadata-Version: 1.0
|
||||||
|
Name: setuptools
|
||||||
|
Version: %s
|
||||||
|
Summary: xxxx
|
||||||
|
Home-page: xxx
|
||||||
|
Author: xxx
|
||||||
|
Author-email: xxx
|
||||||
|
License: xxx
|
||||||
|
Description: xxx
|
||||||
|
""" % SETUPTOOLS_FAKED_VERSION
|
||||||
|
|
||||||
|
|
||||||
|
def _install(tarball, install_args=()):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# installing
|
||||||
|
log.warn('Installing Distribute')
|
||||||
|
if not _python_cmd('setup.py', 'install', *install_args):
|
||||||
|
log.warn('Something went wrong during the installation.')
|
||||||
|
log.warn('See the error message above.')
|
||||||
|
# exitcode will be 2
|
||||||
|
return 2
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_egg(egg, tarball, to_dir):
|
||||||
|
# extracting the tarball
|
||||||
|
tmpdir = tempfile.mkdtemp()
|
||||||
|
log.warn('Extracting in %s', tmpdir)
|
||||||
|
old_wd = os.getcwd()
|
||||||
|
try:
|
||||||
|
os.chdir(tmpdir)
|
||||||
|
tar = tarfile.open(tarball)
|
||||||
|
_extractall(tar)
|
||||||
|
tar.close()
|
||||||
|
|
||||||
|
# going in the directory
|
||||||
|
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
|
||||||
|
os.chdir(subdir)
|
||||||
|
log.warn('Now working in %s', subdir)
|
||||||
|
|
||||||
|
# building an egg
|
||||||
|
log.warn('Building a Distribute egg in %s', to_dir)
|
||||||
|
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
os.chdir(old_wd)
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
# returning the result
|
||||||
|
log.warn(egg)
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
raise IOError('Could not build the egg.')
|
||||||
|
|
||||||
|
|
||||||
|
def _do_download(version, download_base, to_dir, download_delay):
|
||||||
|
egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
|
||||||
|
% (version, sys.version_info[0], sys.version_info[1]))
|
||||||
|
if not os.path.exists(egg):
|
||||||
|
tarball = download_setuptools(version, download_base,
|
||||||
|
to_dir, download_delay)
|
||||||
|
_build_egg(egg, tarball, to_dir)
|
||||||
|
sys.path.insert(0, egg)
|
||||||
|
import setuptools
|
||||||
|
setuptools.bootstrap_install_from = egg
|
||||||
|
|
||||||
|
|
||||||
|
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, download_delay=15, no_fake=True):
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
was_imported = 'pkg_resources' in sys.modules or \
|
||||||
|
'setuptools' in sys.modules
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
# Setuptools 0.7b and later is a suitable (and preferable)
|
||||||
|
# substitute for any Distribute version.
|
||||||
|
try:
|
||||||
|
pkg_resources.require("setuptools>=0.7b")
|
||||||
|
return
|
||||||
|
except (pkg_resources.DistributionNotFound,
|
||||||
|
pkg_resources.VersionConflict):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not hasattr(pkg_resources, '_distribute'):
|
||||||
|
if not no_fake:
|
||||||
|
_fake_setuptools()
|
||||||
|
raise ImportError
|
||||||
|
except ImportError:
|
||||||
|
return _do_download(version, download_base, to_dir, download_delay)
|
||||||
|
try:
|
||||||
|
pkg_resources.require("distribute>=" + version)
|
||||||
|
return
|
||||||
|
except pkg_resources.VersionConflict:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if was_imported:
|
||||||
|
sys.stderr.write(
|
||||||
|
"The required version of distribute (>=%s) is not available,\n"
|
||||||
|
"and can't be installed while this script is running. Please\n"
|
||||||
|
"install a more recent version first, using\n"
|
||||||
|
"'easy_install -U distribute'."
|
||||||
|
"\n\n(Currently using %r)\n" % (version, e.args[0]))
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
del pkg_resources, sys.modules['pkg_resources'] # reload ok
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
except pkg_resources.DistributionNotFound:
|
||||||
|
return _do_download(version, download_base, to_dir,
|
||||||
|
download_delay)
|
||||||
|
finally:
|
||||||
|
if not no_fake:
|
||||||
|
_create_fake_setuptools_pkg_info(to_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
||||||
|
to_dir=os.curdir, delay=15):
|
||||||
|
"""Download distribute from a specified location and return its filename
|
||||||
|
|
||||||
|
`version` should be a valid distribute version number that is available
|
||||||
|
as an egg for download under the `download_base` URL (which should end
|
||||||
|
with a '/'). `to_dir` is the directory where the egg will be downloaded.
|
||||||
|
`delay` is the number of seconds to pause before an actual download
|
||||||
|
attempt.
|
||||||
|
"""
|
||||||
|
# making sure we use the absolute path
|
||||||
|
to_dir = os.path.abspath(to_dir)
|
||||||
|
try:
|
||||||
|
from urllib.request import urlopen
|
||||||
|
except ImportError:
|
||||||
|
from urllib2 import urlopen
|
||||||
|
tgz_name = "distribute-%s.tar.gz" % version
|
||||||
|
url = download_base + tgz_name
|
||||||
|
saveto = os.path.join(to_dir, tgz_name)
|
||||||
|
src = dst = None
|
||||||
|
if not os.path.exists(saveto): # Avoid repeated downloads
|
||||||
|
try:
|
||||||
|
log.warn("Downloading %s", url)
|
||||||
|
src = urlopen(url)
|
||||||
|
# Read/write all in one block, so we don't create a corrupt file
|
||||||
|
# if the download is interrupted.
|
||||||
|
data = src.read()
|
||||||
|
dst = open(saveto, "wb")
|
||||||
|
dst.write(data)
|
||||||
|
finally:
|
||||||
|
if src:
|
||||||
|
src.close()
|
||||||
|
if dst:
|
||||||
|
dst.close()
|
||||||
|
return os.path.realpath(saveto)
|
||||||
|
|
||||||
|
|
||||||
|
def _no_sandbox(function):
|
||||||
|
def __no_sandbox(*args, **kw):
|
||||||
|
try:
|
||||||
|
from setuptools.sandbox import DirectorySandbox
|
||||||
|
if not hasattr(DirectorySandbox, '_old'):
|
||||||
|
def violation(*args):
|
||||||
|
pass
|
||||||
|
DirectorySandbox._old = DirectorySandbox._violation
|
||||||
|
DirectorySandbox._violation = violation
|
||||||
|
patched = True
|
||||||
|
else:
|
||||||
|
patched = False
|
||||||
|
except ImportError:
|
||||||
|
patched = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
return function(*args, **kw)
|
||||||
|
finally:
|
||||||
|
if patched:
|
||||||
|
DirectorySandbox._violation = DirectorySandbox._old
|
||||||
|
del DirectorySandbox._old
|
||||||
|
|
||||||
|
return __no_sandbox
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_file(path, content):
|
||||||
|
"""Will backup the file then patch it"""
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
if existing_content == content:
|
||||||
|
# already patched
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return False
|
||||||
|
log.warn('Patching...')
|
||||||
|
_rename_path(path)
|
||||||
|
f = open(path, 'w')
|
||||||
|
try:
|
||||||
|
f.write(content)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_file = _no_sandbox(_patch_file)
|
||||||
|
|
||||||
|
|
||||||
|
def _same_content(path, content):
|
||||||
|
f = open(path)
|
||||||
|
existing_content = f.read()
|
||||||
|
f.close()
|
||||||
|
return existing_content == content
|
||||||
|
|
||||||
|
|
||||||
|
def _rename_path(path):
|
||||||
|
new_name = path + '.OLD.%s' % time.time()
|
||||||
|
log.warn('Renaming %s to %s', path, new_name)
|
||||||
|
os.rename(path, new_name)
|
||||||
|
return new_name
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_flat_installation(placeholder):
|
||||||
|
if not os.path.isdir(placeholder):
|
||||||
|
log.warn('Unkown installation at %s', placeholder)
|
||||||
|
return False
|
||||||
|
found = False
|
||||||
|
for file in os.listdir(placeholder):
|
||||||
|
if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
|
log.warn('Could not locate setuptools*.egg-info')
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Moving elements out of the way...')
|
||||||
|
pkg_info = os.path.join(placeholder, file)
|
||||||
|
if os.path.isdir(pkg_info):
|
||||||
|
patched = _patch_egg_dir(pkg_info)
|
||||||
|
else:
|
||||||
|
patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
|
||||||
|
|
||||||
|
if not patched:
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
# now let's move the files out of the way
|
||||||
|
for element in ('setuptools', 'pkg_resources.py', 'site.py'):
|
||||||
|
element = os.path.join(placeholder, element)
|
||||||
|
if os.path.exists(element):
|
||||||
|
_rename_path(element)
|
||||||
|
else:
|
||||||
|
log.warn('Could not find the %s element of the '
|
||||||
|
'Setuptools distribution', element)
|
||||||
|
return True
|
||||||
|
|
||||||
|
_remove_flat_installation = _no_sandbox(_remove_flat_installation)
|
||||||
|
|
||||||
|
|
||||||
|
def _after_install(dist):
|
||||||
|
log.warn('After install bootstrap.')
|
||||||
|
placeholder = dist.get_command_obj('install').install_purelib
|
||||||
|
_create_fake_setuptools_pkg_info(placeholder)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_fake_setuptools_pkg_info(placeholder):
|
||||||
|
if not placeholder or not os.path.exists(placeholder):
|
||||||
|
log.warn('Could not find the install location')
|
||||||
|
return
|
||||||
|
pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||||||
|
setuptools_file = 'setuptools-%s-py%s.egg-info' % \
|
||||||
|
(SETUPTOOLS_FAKED_VERSION, pyver)
|
||||||
|
pkg_info = os.path.join(placeholder, setuptools_file)
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
log.warn('%s already exists', pkg_info)
|
||||||
|
return
|
||||||
|
|
||||||
|
log.warn('Creating %s', pkg_info)
|
||||||
|
try:
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
except EnvironmentError:
|
||||||
|
log.warn("Don't have permissions to write %s, skipping", pkg_info)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
pth_file = os.path.join(placeholder, 'setuptools.pth')
|
||||||
|
log.warn('Creating %s', pth_file)
|
||||||
|
f = open(pth_file, 'w')
|
||||||
|
try:
|
||||||
|
f.write(os.path.join(os.curdir, setuptools_file))
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
_create_fake_setuptools_pkg_info = _no_sandbox(
|
||||||
|
_create_fake_setuptools_pkg_info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _patch_egg_dir(path):
|
||||||
|
# let's check if it's already patched
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if os.path.exists(pkg_info):
|
||||||
|
if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
|
||||||
|
log.warn('%s already patched.', pkg_info)
|
||||||
|
return False
|
||||||
|
_rename_path(path)
|
||||||
|
os.mkdir(path)
|
||||||
|
os.mkdir(os.path.join(path, 'EGG-INFO'))
|
||||||
|
pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
f = open(pkg_info, 'w')
|
||||||
|
try:
|
||||||
|
f.write(SETUPTOOLS_PKG_INFO)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
_patch_egg_dir = _no_sandbox(_patch_egg_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def _before_install():
|
||||||
|
log.warn('Before install bootstrap.')
|
||||||
|
_fake_setuptools()
|
||||||
|
|
||||||
|
|
||||||
|
def _under_prefix(location):
|
||||||
|
if 'install' not in sys.argv:
|
||||||
|
return True
|
||||||
|
args = sys.argv[sys.argv.index('install') + 1:]
|
||||||
|
for index, arg in enumerate(args):
|
||||||
|
for option in ('--root', '--prefix'):
|
||||||
|
if arg.startswith('%s=' % option):
|
||||||
|
top_dir = arg.split('root=')[-1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
elif arg == option:
|
||||||
|
if len(args) > index:
|
||||||
|
top_dir = args[index + 1]
|
||||||
|
return location.startswith(top_dir)
|
||||||
|
if arg == '--user' and USER_SITE is not None:
|
||||||
|
return location.startswith(USER_SITE)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _fake_setuptools():
|
||||||
|
log.warn('Scanning installed packages')
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
except ImportError:
|
||||||
|
# we're cool
|
||||||
|
log.warn('Setuptools or Distribute does not seem to be installed.')
|
||||||
|
return
|
||||||
|
ws = pkg_resources.working_set
|
||||||
|
try:
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools', replacement=False)
|
||||||
|
)
|
||||||
|
except TypeError:
|
||||||
|
# old distribute API
|
||||||
|
setuptools_dist = ws.find(
|
||||||
|
pkg_resources.Requirement.parse('setuptools')
|
||||||
|
)
|
||||||
|
|
||||||
|
if setuptools_dist is None:
|
||||||
|
log.warn('No setuptools distribution found')
|
||||||
|
return
|
||||||
|
# detecting if it was already faked
|
||||||
|
setuptools_location = setuptools_dist.location
|
||||||
|
log.warn('Setuptools installation detected at %s', setuptools_location)
|
||||||
|
|
||||||
|
# if --root or --preix was provided, and if
|
||||||
|
# setuptools is not located in them, we don't patch it
|
||||||
|
if not _under_prefix(setuptools_location):
|
||||||
|
log.warn('Not patching, --root or --prefix is installing Distribute'
|
||||||
|
' in another location')
|
||||||
|
return
|
||||||
|
|
||||||
|
# let's see if its an egg
|
||||||
|
if not setuptools_location.endswith('.egg'):
|
||||||
|
log.warn('Non-egg installation')
|
||||||
|
res = _remove_flat_installation(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log.warn('Egg installation')
|
||||||
|
pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
|
||||||
|
if (os.path.exists(pkg_info) and
|
||||||
|
_same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
|
||||||
|
log.warn('Already patched.')
|
||||||
|
return
|
||||||
|
log.warn('Patching...')
|
||||||
|
# let's create a fake egg replacing setuptools one
|
||||||
|
res = _patch_egg_dir(setuptools_location)
|
||||||
|
if not res:
|
||||||
|
return
|
||||||
|
log.warn('Patching complete.')
|
||||||
|
_relaunch()
|
||||||
|
|
||||||
|
|
||||||
|
def _relaunch():
|
||||||
|
log.warn('Relaunching...')
|
||||||
|
# we have to relaunch the process
|
||||||
|
# pip marker to avoid a relaunch bug
|
||||||
|
_cmd1 = ['-c', 'install', '--single-version-externally-managed']
|
||||||
|
_cmd2 = ['-c', 'install', '--record']
|
||||||
|
if sys.argv[:3] == _cmd1 or sys.argv[:3] == _cmd2:
|
||||||
|
sys.argv[0] = 'setup.py'
|
||||||
|
args = [sys.executable] + sys.argv
|
||||||
|
sys.exit(subprocess.call(args))
|
||||||
|
|
||||||
|
|
||||||
|
def _extractall(self, path=".", members=None):
|
||||||
|
"""Extract all members from the archive to the current working
|
||||||
|
directory and set owner, modification time and permissions on
|
||||||
|
directories afterwards. `path' specifies a different directory
|
||||||
|
to extract to. `members' is optional and must be a subset of the
|
||||||
|
list returned by getmembers().
|
||||||
|
"""
|
||||||
|
import copy
|
||||||
|
import operator
|
||||||
|
from tarfile import ExtractError
|
||||||
|
directories = []
|
||||||
|
|
||||||
|
if members is None:
|
||||||
|
members = self
|
||||||
|
|
||||||
|
for tarinfo in members:
|
||||||
|
if tarinfo.isdir():
|
||||||
|
# Extract directories with a safe mode.
|
||||||
|
directories.append(tarinfo)
|
||||||
|
tarinfo = copy.copy(tarinfo)
|
||||||
|
tarinfo.mode = 448 # decimal for oct 0700
|
||||||
|
self.extract(tarinfo, path)
|
||||||
|
|
||||||
|
# Reverse sort directories.
|
||||||
|
if sys.version_info < (2, 4):
|
||||||
|
def sorter(dir1, dir2):
|
||||||
|
return cmp(dir1.name, dir2.name)
|
||||||
|
directories.sort(sorter)
|
||||||
|
directories.reverse()
|
||||||
|
else:
|
||||||
|
directories.sort(key=operator.attrgetter('name'), reverse=True)
|
||||||
|
|
||||||
|
# Set correct owner, mtime and filemode on directories.
|
||||||
|
for tarinfo in directories:
|
||||||
|
dirpath = os.path.join(path, tarinfo.name)
|
||||||
|
try:
|
||||||
|
self.chown(tarinfo, dirpath)
|
||||||
|
self.utime(tarinfo, dirpath)
|
||||||
|
self.chmod(tarinfo, dirpath)
|
||||||
|
except ExtractError:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if self.errorlevel > 1:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
self._dbg(1, "tarfile: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_install_args(options):
|
||||||
|
"""
|
||||||
|
Build the arguments to 'python setup.py install' on the distribute package
|
||||||
|
"""
|
||||||
|
install_args = []
|
||||||
|
if options.user_install:
|
||||||
|
if sys.version_info < (2, 6):
|
||||||
|
log.warn("--user requires Python 2.6 or later")
|
||||||
|
raise SystemExit(1)
|
||||||
|
install_args.append('--user')
|
||||||
|
return install_args
|
||||||
|
|
||||||
|
def _parse_args():
|
||||||
|
"""
|
||||||
|
Parse the command line for options
|
||||||
|
"""
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option(
|
||||||
|
'--user', dest='user_install', action='store_true', default=False,
|
||||||
|
help='install in user site package (requires Python 2.6 or later)')
|
||||||
|
parser.add_option(
|
||||||
|
'--download-base', dest='download_base', metavar="URL",
|
||||||
|
default=DEFAULT_URL,
|
||||||
|
help='alternative URL from where to download the distribute package')
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
# positional arguments are ignored
|
||||||
|
return options
|
||||||
|
|
||||||
|
def main(version=DEFAULT_VERSION):
|
||||||
|
"""Install or upgrade setuptools and EasyInstall"""
|
||||||
|
options = _parse_args()
|
||||||
|
tarball = download_setuptools(download_base=options.download_base)
|
||||||
|
return _install(tarball, _build_install_args(options))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
|
@ -1,9 +1,6 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from distribute_setup import use_setuptools
|
|
||||||
use_setuptools()
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
@ -12,13 +9,15 @@ if sys.version_info >= (3,):
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='texter',
|
name='texter',
|
||||||
version="0.1",
|
version="0.2",
|
||||||
packages=find_packages(exclude=["scripts",]),
|
packages=find_packages(exclude=["scripts",]),
|
||||||
|
|
||||||
include_package_data = True,
|
include_package_data = True,
|
||||||
|
|
||||||
|
install_requires = ["psylib"],
|
||||||
|
|
||||||
package_data = {
|
package_data = {
|
||||||
"texter" : ["*.ui", "*.qrc", "*.png"]},
|
"texter" : ["*.ui", "*.qrc", "*.png", "*.ico", "*.html"]},
|
||||||
|
|
||||||
exclude_package_data = {'': ['.gitignore']},
|
exclude_package_data = {'': ['.gitignore']},
|
||||||
|
|
||||||
|
@ -47,7 +46,7 @@ setup(
|
||||||
""",
|
""",
|
||||||
|
|
||||||
# FIXME: add license
|
# FIXME: add license
|
||||||
license = "LGPL",
|
license = "GPL",
|
||||||
|
|
||||||
# FIXME: add keywords
|
# FIXME: add keywords
|
||||||
keywords = "",
|
keywords = "",
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
pyuic4 -o texter_ui.py texter3.ui
|
# pyuic4 -o texter_ui.py texter.ui
|
||||||
pyuic4 -o text_sorter_ui.py texter4.ui
|
pyuic4 -o edit_dialog_ui.py edit_dialog.ui
|
||||||
|
|
|
@ -0,0 +1,507 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>EditDialog</class>
|
||||||
|
<widget class="QWidget" name="EditDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1084</width>
|
||||||
|
<height>633</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QListView" name="text_list"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTextEdit" name="text_preview">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>100</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="palette">
|
||||||
|
<palette>
|
||||||
|
<active>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Button">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Light">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Midlight">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Dark">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Mid">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Text">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="BrightText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="ButtonText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Base">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Window">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Shadow">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="AlternateBase">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="ToolTipBase">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>220</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="ToolTipText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</active>
|
||||||
|
<inactive>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Button">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Light">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Midlight">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Dark">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Mid">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Text">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="BrightText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="ButtonText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Base">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Window">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Shadow">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="AlternateBase">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="ToolTipBase">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>220</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="ToolTipText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</inactive>
|
||||||
|
<disabled>
|
||||||
|
<colorrole role="WindowText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Button">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Light">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Midlight">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Dark">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Mid">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Text">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="BrightText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>255</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="ButtonText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Base">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Window">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="Shadow">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="AlternateBase">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="ToolTipBase">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>255</red>
|
||||||
|
<green>255</green>
|
||||||
|
<blue>220</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
<colorrole role="ToolTipText">
|
||||||
|
<brush brushstyle="SolidPattern">
|
||||||
|
<color alpha="255">
|
||||||
|
<red>0</red>
|
||||||
|
<green>0</green>
|
||||||
|
<blue>0</blue>
|
||||||
|
</color>
|
||||||
|
</brush>
|
||||||
|
</colorrole>
|
||||||
|
</disabled>
|
||||||
|
</palette>
|
||||||
|
</property>
|
||||||
|
<property name="undoRedoEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::NoTextInteraction</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="KButtonGroup" name="kbuttongroup">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="KArrowButton" name="move_down_button">
|
||||||
|
<property name="arrowType" stdset="0">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="KArrowButton" name="move_up_button"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="KPushButton" name="remove_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="edit-delete">
|
||||||
|
<normaloff>../../../../</normaloff>../../../../</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>KArrowButton</class>
|
||||||
|
<extends>QPushButton</extends>
|
||||||
|
<header>karrowbutton.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>KButtonGroup</class>
|
||||||
|
<extends>QGroupBox</extends>
|
||||||
|
<header>kbuttongroup.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>KPushButton</class>
|
||||||
|
<extends>QPushButton</extends>
|
||||||
|
<header>kpushbutton.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -1,8 +1,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'texter4.ui'
|
# Form implementation generated from reading ui file 'edit_dialog.ui'
|
||||||
#
|
#
|
||||||
# Created: Mon Apr 28 21:58:51 2014
|
# Created: Tue May 27 18:18:57 2014
|
||||||
# by: PyQt4 UI code generator 4.10.3
|
# by: PyQt4 UI code generator 4.10.3
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -23,32 +23,23 @@ except AttributeError:
|
||||||
def _translate(context, text, disambig):
|
def _translate(context, text, disambig):
|
||||||
return QtGui.QApplication.translate(context, text, disambig)
|
return QtGui.QApplication.translate(context, text, disambig)
|
||||||
|
|
||||||
class Ui_TextSorterDialog(object):
|
class Ui_EditDialog(object):
|
||||||
def setupUi(self, TextSorterDialog):
|
def setupUi(self, EditDialog):
|
||||||
TextSorterDialog.setObjectName(_fromUtf8("TextSorterDialog"))
|
EditDialog.setObjectName(_fromUtf8("EditDialog"))
|
||||||
TextSorterDialog.resize(1084, 633)
|
EditDialog.resize(1084, 633)
|
||||||
self.verticalLayout = QtGui.QVBoxLayout(TextSorterDialog)
|
self.verticalLayout = QtGui.QVBoxLayout(EditDialog)
|
||||||
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
|
||||||
self.splitter = QtGui.QSplitter(TextSorterDialog)
|
self.horizontalLayout_2 = QtGui.QHBoxLayout()
|
||||||
self.splitter.setOrientation(QtCore.Qt.Horizontal)
|
self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
|
||||||
self.splitter.setObjectName(_fromUtf8("splitter"))
|
self.text_list = QtGui.QListView(EditDialog)
|
||||||
self.text_list = QtGui.QListView(self.splitter)
|
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
|
||||||
sizePolicy.setHorizontalStretch(1)
|
|
||||||
sizePolicy.setVerticalStretch(0)
|
|
||||||
sizePolicy.setHeightForWidth(self.text_list.sizePolicy().hasHeightForWidth())
|
|
||||||
self.text_list.setSizePolicy(sizePolicy)
|
|
||||||
self.text_list.setMinimumSize(QtCore.QSize(200, 576))
|
|
||||||
self.text_list.setMaximumSize(QtCore.QSize(16777215, 576))
|
|
||||||
self.text_list.setObjectName(_fromUtf8("text_list"))
|
self.text_list.setObjectName(_fromUtf8("text_list"))
|
||||||
self.text_preview = KRichTextWidget(self.splitter)
|
self.horizontalLayout_2.addWidget(self.text_list)
|
||||||
|
self.text_preview = QtGui.QTextEdit(EditDialog)
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(100)
|
sizePolicy.setHorizontalStretch(100)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.text_preview.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.text_preview.sizePolicy().hasHeightForWidth())
|
||||||
self.text_preview.setSizePolicy(sizePolicy)
|
self.text_preview.setSizePolicy(sizePolicy)
|
||||||
self.text_preview.setMinimumSize(QtCore.QSize(0, 576))
|
|
||||||
self.text_preview.setMaximumSize(QtCore.QSize(768, 576))
|
|
||||||
palette = QtGui.QPalette()
|
palette = QtGui.QPalette()
|
||||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
|
@ -186,10 +177,13 @@ class Ui_TextSorterDialog(object):
|
||||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText, brush)
|
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText, brush)
|
||||||
self.text_preview.setPalette(palette)
|
self.text_preview.setPalette(palette)
|
||||||
|
self.text_preview.setUndoRedoEnabled(False)
|
||||||
self.text_preview.setReadOnly(True)
|
self.text_preview.setReadOnly(True)
|
||||||
|
self.text_preview.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
|
||||||
self.text_preview.setObjectName(_fromUtf8("text_preview"))
|
self.text_preview.setObjectName(_fromUtf8("text_preview"))
|
||||||
self.verticalLayout.addWidget(self.splitter)
|
self.horizontalLayout_2.addWidget(self.text_preview)
|
||||||
self.kbuttongroup = KButtonGroup(TextSorterDialog)
|
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||||
|
self.kbuttongroup = KButtonGroup(EditDialog)
|
||||||
self.kbuttongroup.setObjectName(_fromUtf8("kbuttongroup"))
|
self.kbuttongroup.setObjectName(_fromUtf8("kbuttongroup"))
|
||||||
self.horizontalLayout = QtGui.QHBoxLayout(self.kbuttongroup)
|
self.horizontalLayout = QtGui.QHBoxLayout(self.kbuttongroup)
|
||||||
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
||||||
|
@ -206,14 +200,12 @@ class Ui_TextSorterDialog(object):
|
||||||
self.remove_button.setObjectName(_fromUtf8("remove_button"))
|
self.remove_button.setObjectName(_fromUtf8("remove_button"))
|
||||||
self.horizontalLayout.addWidget(self.remove_button)
|
self.horizontalLayout.addWidget(self.remove_button)
|
||||||
self.verticalLayout.addWidget(self.kbuttongroup)
|
self.verticalLayout.addWidget(self.kbuttongroup)
|
||||||
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
|
||||||
self.verticalLayout.addItem(spacerItem)
|
|
||||||
|
|
||||||
self.retranslateUi(TextSorterDialog)
|
self.retranslateUi(EditDialog)
|
||||||
QtCore.QMetaObject.connectSlotsByName(TextSorterDialog)
|
QtCore.QMetaObject.connectSlotsByName(EditDialog)
|
||||||
|
|
||||||
def retranslateUi(self, TextSorterDialog):
|
def retranslateUi(self, EditDialog):
|
||||||
TextSorterDialog.setWindowTitle(_translate("TextSorterDialog", "Form", None))
|
EditDialog.setWindowTitle(_translate("EditDialog", "Form", None))
|
||||||
self.remove_button.setText(_translate("TextSorterDialog", "Remove", None))
|
self.remove_button.setText(_translate("EditDialog", "Remove", None))
|
||||||
|
|
||||||
from PyKDE4.kdeui import KButtonGroup, KArrowButton, KPushButton, KRichTextWidget
|
from PyKDE4.kdeui import KButtonGroup, KArrowButton, KPushButton
|
After Width: | Height: | Size: 766 B |
|
@ -0,0 +1,5 @@
|
||||||
|
P6
|
||||||
|
# CREATOR: GIMP PNM Filter Version 1.1
|
||||||
|
16 16
|
||||||
|
255
|
||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>哪尿蝌<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>èň揪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>殚<EFBFBD>种<><E7A78D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>揪<EFBFBD><14><><EFBFBD>晻暢吵yyy挝<79><E68C9D><EFBFBD><EFBFBD>eee悙愔种<E68494><E7A78D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>tttQQQ<51><51><EFBFBD>种謑llbbb篌蟥è厖區^^ⅱ<><E285B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ppp鞍<70>666鬃讞棗<E8AE9E>畘~~破歧珑览纀bb┅<62><E29485><EFBFBD><EFBFBD>行协<E8A18C><E58D8F><EFBFBD><EFBFBD>圹勖妹666噜鄅hh适蕯敂牋<E69582><E7898B><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>佑羽痧<E7BEBD><E797A7><EFBFBD>滗湫行<E6B9AB><E8A18C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>揪<EFBFBD><E68FAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>悙悽ⅱ<E682BD><E285B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
After Width: | Height: | Size: 579 B |
After Width: | Height: | Size: 611 B |
After Width: | Height: | Size: 697 B |
After Width: | Height: | Size: 563 B |
After Width: | Height: | Size: 802 B |
After Width: | Height: | Size: 485 B |
After Width: | Height: | Size: 639 B |
After Width: | Height: | Size: 618 B |
After Width: | Height: | Size: 499 B |
After Width: | Height: | Size: 735 B |
After Width: | Height: | Size: 931 B |
|
@ -0,0 +1,9 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="icon" type="image/png" href="/icon.png" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="/texter_%d.mjpeg" alt="Smiley face" />
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,38 +1,54 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# This file is part of texter package
|
||||||
|
#
|
||||||
|
# texter is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# texter is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with texter. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 Stefan Kögl
|
||||||
|
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
|
||||||
import cPickle
|
import cPickle
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
import subprocess
|
|
||||||
import sys
|
import sys
|
||||||
from math import pow
|
import traceback
|
||||||
|
|
||||||
from operator import itemgetter
|
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
|
||||||
|
from PyQt4.QtCore import QBuffer, QByteArray, QIODevice
|
||||||
|
from PyQt4.QtGui import QPixmap
|
||||||
|
|
||||||
from PyKDE4.kdecore import ki18n, KCmdLineArgs, KAboutData
|
from PyKDE4.kdeui import (KDialog, KActionCollection, KRichTextWidget,
|
||||||
from PyKDE4.kdeui import KDialog, KActionCollection, KRichTextWidget, KComboBox, KPushButton, KRichTextWidget, KMainWindow, KToolBar, KApplication, KAction, KToolBarSpacerAction, KSelectAction, KToggleAction, KShortcut
|
KRichTextWidget, KMainWindow, KToolBar, KAction, KToolBarSpacerAction,
|
||||||
|
KSelectAction, KToggleAction, KShortcut)
|
||||||
|
|
||||||
from texter_ui import Ui_MainWindow, _fromUtf8
|
from PyQt4.QtNetwork import QTcpServer, QTcpSocket
|
||||||
from text_sorter_ui import Ui_TextSorterDialog
|
|
||||||
from text_model import TextModel
|
|
||||||
|
|
||||||
appName = "texter"
|
from chaosc.argparser_groups import ArgParser
|
||||||
catalog = "448texter"
|
from chaosc.lib import resolve_host, logger
|
||||||
programName = ki18n("4.48 Psychose Texter")
|
|
||||||
version = "0.1"
|
|
||||||
|
|
||||||
aboutData = KAboutData(appName, catalog, programName, version)
|
from psylib.mjpeg_streaming_server import *
|
||||||
|
from psylib.psyqt_base import PsyQtClientBase
|
||||||
|
|
||||||
KCmdLineArgs.init (sys.argv, aboutData)
|
from texter.texter_ui import Ui_MainWindow, _fromUtf8
|
||||||
|
from texter.edit_dialog_ui import Ui_EditDialog
|
||||||
|
from texter.text_model import TextModel
|
||||||
|
|
||||||
app = KApplication()
|
qtapp = QtGui.QApplication([])
|
||||||
|
|
||||||
for path in QtGui.QIcon.themeSearchPaths():
|
|
||||||
print "%s/%s" % (path, QtGui.QIcon.themeName())
|
|
||||||
|
|
||||||
|
|
||||||
# NOTE: if the QIcon.fromTheme method does not find any icons, you can use
|
# NOTE: if the QIcon.fromTheme method does not find any icons, you can use
|
||||||
|
@ -40,15 +56,20 @@ for path in QtGui.QIcon.themeSearchPaths():
|
||||||
# in your local icon directory:
|
# in your local icon directory:
|
||||||
# ln -s /your/icon/theme/directory $HOME/.icons/hicolor
|
# ln -s /your/icon/theme/directory $HOME/.icons/hicolor
|
||||||
|
|
||||||
class TextSorterDialog(QtGui.QWidget, Ui_TextSorterDialog):
|
def get_preview_text(text):
|
||||||
|
return re.sub(" +", " ", text.replace("\n", " ")).strip()[:20]
|
||||||
|
|
||||||
|
|
||||||
|
class EditDialog(QtGui.QWidget, Ui_EditDialog):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(TextSorterDialog, self).__init__(parent)
|
super(EditDialog, self).__init__(parent)
|
||||||
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
self.model = None
|
||||||
self.fill_list()
|
self.fill_list()
|
||||||
|
|
||||||
self.text_list.clicked.connect(self.slot_show_text)
|
self.text_list.clicked.connect(self.slot_show_text)
|
||||||
self.remove_button.clicked.connect(self.slot_removeItem)
|
self.remove_button.clicked.connect(self.slot_remove_item)
|
||||||
self.move_up_button.clicked.connect(self.slot_text_up)
|
self.move_up_button.clicked.connect(self.slot_text_up)
|
||||||
self.move_down_button.clicked.connect(self.slot_text_down)
|
self.move_down_button.clicked.connect(self.slot_text_down)
|
||||||
self.text_list.clicked.connect(self.slot_toggle_buttons)
|
self.text_list.clicked.connect(self.slot_toggle_buttons)
|
||||||
|
@ -71,9 +92,9 @@ class TextSorterDialog(QtGui.QWidget, Ui_TextSorterDialog):
|
||||||
def fill_list(self):
|
def fill_list(self):
|
||||||
self.model = self.parent().parent().model
|
self.model = self.parent().parent().model
|
||||||
self.text_list.setModel(self.model)
|
self.text_list.setModel(self.model)
|
||||||
ix = self.parent().parent().current_index
|
index = self.parent().parent().current_index
|
||||||
index = self.model.index(ix, 0)
|
model_index = self.model.index(index, 0)
|
||||||
self.text_list.setCurrentIndex(index)
|
self.text_list.setCurrentIndex(model_index)
|
||||||
|
|
||||||
|
|
||||||
def slot_text_up(self):
|
def slot_text_up(self):
|
||||||
|
@ -103,12 +124,11 @@ class TextSorterDialog(QtGui.QWidget, Ui_TextSorterDialog):
|
||||||
|
|
||||||
def slot_show_text(self, model_index):
|
def slot_show_text(self, model_index):
|
||||||
try:
|
try:
|
||||||
self.text_preview.setTextOrHtml(self.parent().parent().model.text_db[model_index.row()][1])
|
self.text_preview.setHtml(self.parent().parent().model.text_db[model_index.row()][1])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def slot_remove_item(self):
|
||||||
def slot_removeItem(self):
|
|
||||||
index = self.text_list.currentIndex().row()
|
index = self.text_list.currentIndex().row()
|
||||||
self.model.removeRows(index, 1)
|
self.model.removeRows(index, 1)
|
||||||
index = self.model.index(0, 0)
|
index = self.model.index(0, 0)
|
||||||
|
@ -116,63 +136,6 @@ class TextSorterDialog(QtGui.QWidget, Ui_TextSorterDialog):
|
||||||
self.text_list.clicked.emit(index)
|
self.text_list.clicked.emit(index)
|
||||||
self.parent().parent().db_dirty = True
|
self.parent().parent().db_dirty = True
|
||||||
|
|
||||||
class FadeAnimation(QtCore.QObject):
|
|
||||||
animation_started = QtCore.pyqtSignal()
|
|
||||||
animation_finished = QtCore.pyqtSignal()
|
|
||||||
animation_stopped = QtCore.pyqtSignal()
|
|
||||||
|
|
||||||
def __init__(self, live_text, fade_steps=6, parent=None):
|
|
||||||
super(FadeAnimation, self).__init__(parent)
|
|
||||||
self.live_text = live_text
|
|
||||||
self.fade_steps = fade_steps
|
|
||||||
self.current_alpha = 255
|
|
||||||
self.timer = None
|
|
||||||
|
|
||||||
|
|
||||||
def start_animation(self):
|
|
||||||
print "start_animation"
|
|
||||||
self.animation_started.emit()
|
|
||||||
|
|
||||||
if self.current_alpha == 255:
|
|
||||||
self.fade_delta = 255 / self.fade_steps
|
|
||||||
else:
|
|
||||||
self.fade_delta = -255 / self.fade_steps
|
|
||||||
self.timer = QtCore.QTimer(self)
|
|
||||||
self.timer.timeout.connect(self.slot_animate)
|
|
||||||
self.timer.start(100)
|
|
||||||
|
|
||||||
|
|
||||||
def slot_animate(self):
|
|
||||||
print "slot_animate"
|
|
||||||
print "current_alpha", self.current_alpha
|
|
||||||
if self.fade_delta > 0:
|
|
||||||
if self.current_alpha > 0:
|
|
||||||
self.live_text.setStyleSheet("color:%d, %d, %d;" % (self.current_alpha, self.current_alpha,self.current_alpha))
|
|
||||||
self.current_alpha -= self.fade_delta
|
|
||||||
else:
|
|
||||||
self.live_text.setStyleSheet("color:black;")
|
|
||||||
self.current_alpha = 0
|
|
||||||
self.timer.stop()
|
|
||||||
self.timer.timeout.disconnect(self.slot_animate)
|
|
||||||
self.timer.deleteLater()
|
|
||||||
self.timer = None
|
|
||||||
self.animation_finished.emit()
|
|
||||||
print "animation_finished"
|
|
||||||
else:
|
|
||||||
if self.current_alpha < 255:
|
|
||||||
self.live_text.setStyleSheet("color:%d,%d, %d;" % (self.current_alpha, self.current_alpha,self.current_alpha))
|
|
||||||
self.current_alpha -= self.fade_delta
|
|
||||||
else:
|
|
||||||
self.live_text.setStyleSheet("color:white")
|
|
||||||
self.current_alpha = 255
|
|
||||||
self.timer.stop()
|
|
||||||
self.timer.timeout.disconnect(self.slot_animate)
|
|
||||||
self.timer.deleteLater()
|
|
||||||
self.timer = None
|
|
||||||
self.animation_finished.emit()
|
|
||||||
print "animation_finished"
|
|
||||||
|
|
||||||
|
|
||||||
class TextAnimation(QtCore.QObject):
|
class TextAnimation(QtCore.QObject):
|
||||||
animation_started = QtCore.pyqtSignal()
|
animation_started = QtCore.pyqtSignal()
|
||||||
animation_finished = QtCore.pyqtSignal()
|
animation_finished = QtCore.pyqtSignal()
|
||||||
|
@ -214,7 +177,6 @@ class TextAnimation(QtCore.QObject):
|
||||||
|
|
||||||
def slot_animate(self):
|
def slot_animate(self):
|
||||||
self.animation_started.emit()
|
self.animation_started.emit()
|
||||||
parent = self.parent()
|
|
||||||
|
|
||||||
if self.it is None:
|
if self.it is None:
|
||||||
src_root_frame = self.src_document.rootFrame()
|
src_root_frame = self.src_document.rootFrame()
|
||||||
|
@ -271,13 +233,14 @@ class TextAnimation(QtCore.QObject):
|
||||||
self.count += 1
|
self.count += 1
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(KMainWindow, Ui_MainWindow):
|
class MainWindow(KMainWindow, Ui_MainWindow, MjpegStreamingConsumerInterface):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, args, parent=None):
|
||||||
super(MainWindow, self).__init__(parent)
|
self.args = args
|
||||||
|
#super(MainWindow, self).__init__()
|
||||||
|
#PsyQtClientBase.__init__(self)
|
||||||
|
KMainWindow.__init__(self, parent)
|
||||||
self.is_streaming = False
|
self.is_streaming = False
|
||||||
self.ffserver = None
|
|
||||||
self.ffmpeg = None
|
|
||||||
self.live_center_action = None
|
self.live_center_action = None
|
||||||
self.preview_center_action = None
|
self.preview_center_action = None
|
||||||
self.live_size_action = None
|
self.live_size_action = None
|
||||||
|
@ -301,78 +264,81 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
self.is_auto_publish = False
|
self.is_auto_publish = False
|
||||||
|
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
self.win_id = self.live_text.winId()
|
||||||
|
|
||||||
self.fade_animation = FadeAnimation(self.live_text, 6, self)
|
self.fps = 12.5
|
||||||
|
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self, self.fps)
|
||||||
|
|
||||||
|
self.live_text.setLineWrapMode(QtGui.QTextEdit.LineWrapMode(QtGui.QTextEdit.FixedPixelWidth))
|
||||||
|
self.live_text.setLineWrapColumnOrWidth(768)
|
||||||
|
|
||||||
self.font = QtGui.QFont("monospace", self.default_size)
|
self.font = QtGui.QFont("monospace", self.default_size)
|
||||||
self.font.setStyleHint(QtGui.QFont.TypeWriter)
|
self.font.setStyleHint(QtGui.QFont.TypeWriter)
|
||||||
|
|
||||||
|
self.previous_action = None
|
||||||
|
self.next_action = None
|
||||||
|
self.publish_action = None
|
||||||
|
self.auto_publish_action = None
|
||||||
|
self.save_live_action = None
|
||||||
|
self.save_preview_action = None
|
||||||
|
self.save_action = None
|
||||||
|
self.dialog_widget = None
|
||||||
|
self.action_collection = None
|
||||||
|
self.streaming_action = None
|
||||||
|
self.text_combo = None
|
||||||
|
self.clear_live_action = None
|
||||||
|
self.clear_preview_action = None
|
||||||
|
self.toolbar = None
|
||||||
|
self.typer_animation_action = None
|
||||||
|
self.text_editor_action = None
|
||||||
|
|
||||||
self.create_toolbar()
|
|
||||||
|
|
||||||
#self.preview_text.document().setDefaultFont(self.font)
|
|
||||||
self.preview_text.setFont(self.font)
|
self.preview_text.setFont(self.font)
|
||||||
self.preview_text.setRichTextSupport(KRichTextWidget.RichTextSupport(0xffffffff))
|
self.preview_text.setRichTextSupport(KRichTextWidget.RichTextSupport(0xffffffff))
|
||||||
self.preview_editor_collection = KActionCollection(self)
|
self.preview_editor_collection = KActionCollection(self)
|
||||||
self.preview_text.createActions(self.preview_editor_collection)
|
self.preview_text.createActions(self.preview_editor_collection)
|
||||||
|
|
||||||
self.live_text.setRichTextSupport(KRichTextWidget.RichTextSupport(0xffffffff))
|
self.live_text.setRichTextSupport(KRichTextWidget.RichTextSupport(0xffffffff))
|
||||||
#self.live_text.document().setDefaultFont(self.font)
|
|
||||||
self.live_text.setFont(self.font)
|
self.live_text.setFont(self.font)
|
||||||
self.live_editor_collection = KActionCollection(self)
|
self.live_editor_collection = KActionCollection(self)
|
||||||
self.live_text.createActions(self.live_editor_collection)
|
self.live_text.createActions(self.live_editor_collection)
|
||||||
self.filter_editor_actions()
|
self.filter_editor_actions()
|
||||||
|
self.create_toolbar()
|
||||||
self.slot_load()
|
self.slot_load()
|
||||||
|
|
||||||
|
qtapp.focusChanged.connect(self.focusChanged)
|
||||||
|
self.start_streaming()
|
||||||
|
|
||||||
self.show()
|
self.show()
|
||||||
|
timer = QtCore.QTimer()
|
||||||
|
timer.start(2000)
|
||||||
|
timer.timeout.connect(lambda: None)
|
||||||
|
|
||||||
self.save_action.triggered.connect(self.slot_save)
|
def pubdir(self):
|
||||||
|
return os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
self.publish_action.triggered.connect(self.slot_publish)
|
|
||||||
self.clear_live_action.triggered.connect(self.slot_clear_live)
|
|
||||||
self.clear_preview_action.triggered.connect(self.slot_clear_preview)
|
|
||||||
self.text_combo.triggered[int].connect(self.slot_load_preview_text)
|
|
||||||
|
|
||||||
app.focusChanged.connect(self.focusChanged)
|
|
||||||
self.text_editor_action.triggered.connect(self.slot_open_dialog)
|
|
||||||
self.save_live_action.triggered.connect(self.slot_save_live_text)
|
|
||||||
self.save_preview_action.triggered.connect(self.slot_save_preview_text)
|
|
||||||
self.streaming_action.triggered.connect(self.slot_toggle_streaming)
|
|
||||||
self.auto_publish_action.toggled.connect(self.slot_auto_publish)
|
|
||||||
self.typer_animation_action.toggled.connect(self.slot_toggle_animation)
|
|
||||||
self.preview_size_action.triggered[QtGui.QAction].connect(self.slot_preview_font_size)
|
|
||||||
self.live_size_action.triggered[QtGui.QAction].connect(self.slot_live_font_size)
|
|
||||||
|
|
||||||
#self.fade_action.triggered.connect(self.slot_fade)
|
|
||||||
self.next_action.triggered.connect(self.slot_next_item)
|
|
||||||
self.previous_action.triggered.connect(self.slot_previous_item)
|
|
||||||
|
|
||||||
self.getLiveCoords()
|
|
||||||
print "desktop", app.desktop().availableGeometry()
|
|
||||||
|
|
||||||
|
|
||||||
def getLiveCoords(self):
|
|
||||||
public_rect = self.live_text.geometry()
|
|
||||||
global_rect = QtCore.QRect(self.mapToGlobal(public_rect.topLeft()), self.mapToGlobal(public_rect.bottomRight()))
|
|
||||||
x = global_rect.x()
|
|
||||||
y = global_rect.y()
|
|
||||||
self.statusBar().showMessage("live text editor dimensions: x=%r, y=%r, width=%r, height=%r" % (x, y, global_rect.width(), global_rect.height()))
|
|
||||||
|
|
||||||
def getPreviewCoords(self):
|
def getPreviewCoords(self):
|
||||||
public_rect = self.preview_text.geometry()
|
public_rect = self.preview_text.geometry()
|
||||||
global_rect = QtCore.QRect(self.mapToGlobal(public_rect.topLeft()), self.mapToGlobal(public_rect.bottomRight()))
|
global_rect = QtCore.QRect(self.mapToGlobal(public_rect.topLeft()), self.mapToGlobal(public_rect.bottomRight()))
|
||||||
return global_rect.x(), global_rect.y()
|
return global_rect.x(), global_rect.y()
|
||||||
|
|
||||||
|
def render_image(self):
|
||||||
|
public_rect = self.live_text_rect()
|
||||||
|
#global_rect = QtCore.QRect(self.mapToGlobal(public_rect.topLeft()), self.mapToGlobal(public_rect.bottomRight()))
|
||||||
|
pixmap = QPixmap.grabWindow(self.win_id, public_rect.x() + 1, public_rect.y() + 1, 768, 576)
|
||||||
|
buf = QBuffer()
|
||||||
|
buf.open(QIODevice.WriteOnly)
|
||||||
|
pixmap.save(buf, "JPG", 75)
|
||||||
|
return buf.data()
|
||||||
|
|
||||||
|
|
||||||
def filter_editor_actions(self):
|
def filter_editor_actions(self):
|
||||||
|
|
||||||
disabled_action_names = [
|
disabled_action_names = [
|
||||||
"action_to_plain_text",
|
"action_to_plain_text",
|
||||||
"format_painter",
|
"format_painter",
|
||||||
"direction_ltr",
|
"direction_ltr",
|
||||||
"direction_rtl",
|
"direction_rtl",
|
||||||
"format_font_family",
|
"format_font_family",
|
||||||
#"format_font_size",
|
|
||||||
"format_text_background_color",
|
"format_text_background_color",
|
||||||
"format_list_style",
|
"format_list_style",
|
||||||
"format_list_indent_more",
|
"format_list_indent_more",
|
||||||
|
@ -382,7 +348,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
"format_text_strikeout",
|
"format_text_strikeout",
|
||||||
"format_text_italic",
|
"format_text_italic",
|
||||||
"format_align_right",
|
"format_align_right",
|
||||||
#"format_align_justify",
|
|
||||||
"manage_link",
|
"manage_link",
|
||||||
"format_text_subscript",
|
"format_text_subscript",
|
||||||
"format_text_superscript",
|
"format_text_superscript",
|
||||||
|
@ -391,7 +356,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
for action in self.live_editor_collection.actions():
|
for action in self.live_editor_collection.actions():
|
||||||
text = str(action.objectName())
|
text = str(action.objectName())
|
||||||
print "text", text
|
|
||||||
if text in disabled_action_names:
|
if text in disabled_action_names:
|
||||||
action.setVisible(False)
|
action.setVisible(False)
|
||||||
|
|
||||||
|
@ -417,10 +381,10 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
self.slot_set_preview_defaults()
|
self.slot_set_preview_defaults()
|
||||||
self.slot_set_live_defaults()
|
self.slot_set_live_defaults()
|
||||||
|
|
||||||
|
|
||||||
def create_toolbar(self):
|
def create_toolbar(self):
|
||||||
|
|
||||||
self.toolbar = KToolBar(self, True, True)
|
self.toolbar = KToolBar(self, True, True)
|
||||||
|
self.toolbar.setIconDimensions(16)
|
||||||
self.toolbar.setAllowedAreas(QtCore.Qt.BottomToolBarArea)
|
self.toolbar.setAllowedAreas(QtCore.Qt.BottomToolBarArea)
|
||||||
self.toolbar.setMovable(False)
|
self.toolbar.setMovable(False)
|
||||||
self.toolbar.setFloatable(False)
|
self.toolbar.setFloatable(False)
|
||||||
|
@ -432,32 +396,31 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
self.action_collection.addAssociatedWidget(self.toolbar)
|
self.action_collection.addAssociatedWidget(self.toolbar)
|
||||||
|
|
||||||
self.clear_live_action = self.action_collection.addAction("clear_live_action")
|
self.clear_live_action = self.action_collection.addAction("clear_live_action")
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("edit-clear"))
|
icon = QtGui.QIcon(":texter/images/edit-clear.png")
|
||||||
self.clear_live_action.setIcon(icon)
|
self.clear_live_action.setIcon(icon)
|
||||||
self.clear_live_action.setIconText("clear live")
|
self.clear_live_action.setIconText("clear live")
|
||||||
self.clear_live_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Q)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
self.clear_live_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Q)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
||||||
|
|
||||||
self.save_live_action = self.action_collection.addAction("save_live_action")
|
self.save_live_action = self.action_collection.addAction("save_live_action")
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("document-new"))
|
icon = QtGui.QIcon(":texter/images/document-new.png")
|
||||||
self.save_live_action.setIcon(icon)
|
self.save_live_action.setIcon(icon)
|
||||||
self.save_live_action.setIconText("save live")
|
self.save_live_action.setIconText("save live")
|
||||||
self.save_live_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_W)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
self.save_live_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_W)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
||||||
|
|
||||||
self.clear_preview_action = self.action_collection.addAction("clear_preview_action")
|
self.clear_preview_action = self.action_collection.addAction("clear_preview_action")
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("edit-clear"))
|
icon = QtGui.QIcon(":texter/images/edit-clear.png")
|
||||||
self.clear_preview_action.setIcon(icon)
|
self.clear_preview_action.setIcon(icon)
|
||||||
self.clear_preview_action.setIconText("clear preview")
|
self.clear_preview_action.setIconText("clear preview")
|
||||||
#self.clear_preview_action.setObjectName("clear_preview")
|
|
||||||
self.clear_preview_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_A)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
self.clear_preview_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_A)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
||||||
|
|
||||||
self.save_preview_action = self.action_collection.addAction("save_preview_action")
|
self.save_preview_action = self.action_collection.addAction("save_preview_action")
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("document-new"))
|
icon = QtGui.QIcon(":texter/images/document-new.png")
|
||||||
self.save_preview_action.setIcon(icon)
|
self.save_preview_action.setIcon(icon)
|
||||||
self.save_preview_action.setIconText("save preview")
|
self.save_preview_action.setIconText("save preview")
|
||||||
self.save_preview_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_S)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
self.save_preview_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_S)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
||||||
|
|
||||||
self.publish_action = self.action_collection.addAction("publish_action")
|
self.publish_action = self.action_collection.addAction("publish_action")
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("edit-copy"))
|
icon = QtGui.QIcon(":texter/images/edit-copy.png")
|
||||||
self.publish_action.setIcon(icon)
|
self.publish_action.setIcon(icon)
|
||||||
self.publish_action.setIconText("publish")
|
self.publish_action.setIconText("publish")
|
||||||
self.publish_action.setShortcutConfigurable(True)
|
self.publish_action.setShortcutConfigurable(True)
|
||||||
|
@ -467,14 +430,14 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
self.auto_publish_action = KToggleAction(self.action_collection)
|
self.auto_publish_action = KToggleAction(self.action_collection)
|
||||||
self.action_collection.addAction("auto publish", self.auto_publish_action)
|
self.action_collection.addAction("auto publish", self.auto_publish_action)
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("view-refresh"))
|
icon = QtGui.QIcon(":texter/images/view-refresh.png")
|
||||||
self.auto_publish_action.setIcon(icon)
|
self.auto_publish_action.setIcon(icon)
|
||||||
self.auto_publish_action.setObjectName("auto_publish_action")
|
self.auto_publish_action.setObjectName("auto_publish_action")
|
||||||
self.auto_publish_action.setIconText("auto publish")
|
self.auto_publish_action.setIconText("auto publish")
|
||||||
self.auto_publish_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_P)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
self.auto_publish_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_P)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
||||||
|
|
||||||
self.typer_animation_action = KToggleAction(self.action_collection)
|
self.typer_animation_action = KToggleAction(self.action_collection)
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("media-playback-stop"))
|
icon = QtGui.QIcon(":texter/images/media-playback-stop.png")
|
||||||
self.typer_animation_action.setIcon(icon)
|
self.typer_animation_action.setIcon(icon)
|
||||||
self.typer_animation_action.setIconText("animate")
|
self.typer_animation_action.setIconText("animate")
|
||||||
self.typer_animation_action.setObjectName("typer_animation_action")
|
self.typer_animation_action.setObjectName("typer_animation_action")
|
||||||
|
@ -482,7 +445,7 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
self.action_collection.addAction("typer_animation_action", self.typer_animation_action)
|
self.action_collection.addAction("typer_animation_action", self.typer_animation_action)
|
||||||
|
|
||||||
self.text_editor_action = self.action_collection.addAction("text_editor_action")
|
self.text_editor_action = self.action_collection.addAction("text_editor_action")
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("document-open-data"))
|
icon = QtGui.QIcon(":texter/images/document-open-data.png")
|
||||||
self.text_editor_action.setIcon(icon)
|
self.text_editor_action.setIcon(icon)
|
||||||
self.text_editor_action.setIconText("edit")
|
self.text_editor_action.setIconText("edit")
|
||||||
self.text_editor_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_O)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
self.text_editor_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_O)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
||||||
|
@ -490,13 +453,13 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
self.toolbar.insertSeparator(self.text_editor_action)
|
self.toolbar.insertSeparator(self.text_editor_action)
|
||||||
|
|
||||||
self.save_action = self.action_collection.addAction("save_action")
|
self.save_action = self.action_collection.addAction("save_action")
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("document-save"))
|
icon = QtGui.QIcon(":texter/images/document-save.png")
|
||||||
self.save_action.setIcon(icon)
|
self.save_action.setIcon(icon)
|
||||||
self.save_action.setIconText("save")
|
self.save_action.setIconText("save")
|
||||||
self.save_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_S)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
self.save_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_S)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
||||||
|
|
||||||
self.streaming_action = KToggleAction(self.action_collection)
|
self.streaming_action = KToggleAction(self.action_collection)
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("media-record"))
|
icon = QtGui.QIcon(":texter/images/media-record.png")
|
||||||
self.streaming_action.setIcon(icon)
|
self.streaming_action.setIcon(icon)
|
||||||
self.streaming_action.setIconText("stream")
|
self.streaming_action.setIconText("stream")
|
||||||
self.streaming_action.setObjectName("stream")
|
self.streaming_action.setObjectName("stream")
|
||||||
|
@ -506,37 +469,49 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
spacer = KToolBarSpacerAction(self.action_collection)
|
spacer = KToolBarSpacerAction(self.action_collection)
|
||||||
self.action_collection.addAction("1_spacer", spacer)
|
self.action_collection.addAction("1_spacer", spacer)
|
||||||
|
|
||||||
#self.fade_action = self.action_collection.addAction("fade_action")
|
|
||||||
##icon = QtGui.QIcon.fromTheme(_fromUtf8("go-previous-view-page"))
|
|
||||||
##self.fade_action.setIcon(icon)
|
|
||||||
#self.fade_action.setIconText("fade")
|
|
||||||
#self.fade_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_F)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
|
||||||
|
|
||||||
self.previous_action = self.action_collection.addAction("previous_action")
|
self.previous_action = self.action_collection.addAction("previous_action")
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("go-previous-view-page"))
|
icon = QtGui.QIcon(":texter/images/go-previous-view-page.png")
|
||||||
self.previous_action.setIcon(icon)
|
self.previous_action.setIcon(icon)
|
||||||
self.previous_action.setIconText("previous")
|
self.previous_action.setIconText("previous")
|
||||||
self.previous_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Left)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
self.previous_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Left)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
||||||
|
|
||||||
self.text_combo = KSelectAction(self.action_collection)
|
self.text_combo = KSelectAction(self.action_collection)
|
||||||
self.text_combo.setEditable(False)
|
self.text_combo.setEditable(False)
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("document-open-recent"))
|
icon = QtGui.QIcon(":texter/images/document-open-recent.png")
|
||||||
self.text_combo.setIcon(icon)
|
self.text_combo.setIcon(icon)
|
||||||
self.text_combo.setIconText("saved texts")
|
self.text_combo.setIconText("saved texts")
|
||||||
self.text_combo.setObjectName("text_combo")
|
self.text_combo.setObjectName("text_combo")
|
||||||
self.action_collection.addAction("saved texts", self.text_combo)
|
self.action_collection.addAction("saved texts", self.text_combo)
|
||||||
|
|
||||||
self.next_action = self.action_collection.addAction("next_action")
|
self.next_action = self.action_collection.addAction("next_action")
|
||||||
icon = QtGui.QIcon.fromTheme(_fromUtf8("go-next-view-page"))
|
icon = QtGui.QIcon(":texter/images/go-next-view-page.png")
|
||||||
self.next_action.setIcon(icon)
|
self.next_action.setIcon(icon)
|
||||||
self.next_action.setIconText("next")
|
self.next_action.setIconText("next")
|
||||||
self.next_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Right)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
self.next_action.setShortcut(KShortcut(QtGui.QKeySequence(QtCore.Qt.ALT + QtCore.Qt.Key_Right)), KAction.ShortcutTypes(KAction.ActiveShortcut | KAction.DefaultShortcut))
|
||||||
|
|
||||||
self.toolbar.addSeparator()
|
self.toolbar.addSeparator()
|
||||||
|
|
||||||
|
self.save_action.triggered.connect(self.slot_save)
|
||||||
|
|
||||||
|
self.publish_action.triggered.connect(self.slot_publish)
|
||||||
|
self.clear_live_action.triggered.connect(self.slot_clear_live)
|
||||||
|
self.clear_preview_action.triggered.connect(self.slot_clear_preview)
|
||||||
|
self.text_combo.triggered[int].connect(self.slot_load_preview_text)
|
||||||
|
self.text_editor_action.triggered.connect(self.slot_open_dialog)
|
||||||
|
self.save_live_action.triggered.connect(self.slot_save_live_text)
|
||||||
|
self.save_preview_action.triggered.connect(self.slot_save_preview_text)
|
||||||
|
self.streaming_action.triggered.connect(self.slot_toggle_streaming)
|
||||||
|
self.auto_publish_action.toggled.connect(self.slot_auto_publish)
|
||||||
|
self.typer_animation_action.toggled.connect(self.slot_toggle_animation)
|
||||||
|
self.preview_size_action.triggered[QtGui.QAction].connect(self.slot_preview_font_size)
|
||||||
|
self.live_size_action.triggered[QtGui.QAction].connect(self.slot_live_font_size)
|
||||||
|
|
||||||
|
self.next_action.triggered.connect(self.slot_next_item)
|
||||||
|
self.previous_action.triggered.connect(self.slot_previous_item)
|
||||||
|
self.streaming_action.setChecked(True)
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
self.stop_streaming()
|
logger.info("closeEvent")
|
||||||
if self.db_dirty:
|
if self.db_dirty:
|
||||||
self.dialog = KDialog(self)
|
self.dialog = KDialog(self)
|
||||||
self.dialog.setCaption("4.48 texter - text db not saved")
|
self.dialog.setCaption("4.48 texter - text db not saved")
|
||||||
|
@ -545,23 +520,37 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
self.dialog.setButtons(KDialog.ButtonCodes(KDialog.Ok | KDialog.Cancel))
|
self.dialog.setButtons(KDialog.ButtonCodes(KDialog.Ok | KDialog.Cancel))
|
||||||
self.dialog.okClicked.connect(self.slot_save)
|
self.dialog.okClicked.connect(self.slot_save)
|
||||||
self.dialog.exec_()
|
self.dialog.exec_()
|
||||||
|
event.accept()
|
||||||
|
|
||||||
|
def live_text_rect(self):
|
||||||
|
return self.live_text.geometry()
|
||||||
|
|
||||||
def stop_streaming(self):
|
def stop_streaming(self):
|
||||||
self.is_streaming = False
|
self.is_streaming = False
|
||||||
if self.ffmpeg is not None:
|
self.http_server.stop()
|
||||||
self.ffmpeg.kill()
|
|
||||||
self.ffmpeg = None
|
|
||||||
if self.ffserver is not None:
|
|
||||||
self.ffserver.kill()
|
|
||||||
self.ffserver = None
|
|
||||||
|
|
||||||
def start_streaming(self):
|
def start_streaming(self):
|
||||||
public_rect = self.live_text.geometry()
|
self.http_server.listen(port=self.args.http_port)
|
||||||
global_rect = QtCore.QRect(self.mapToGlobal(public_rect.topLeft()), self.mapToGlobal(public_rect.bottomRight()))
|
|
||||||
self.ffserver = subprocess.Popen("ffserver -f /etc/ffserver.conf", shell=True, close_fds=True)
|
|
||||||
self.ffmpeg = subprocess.Popen("ffmpeg -f x11grab -show_region 1 -s 768x576 -r 30 -i :0.0+%d,%d -vcodec mjpeg -pix_fmt yuvj444p -r 30 -aspect 4:3 http://localhost:8090/webcam.ffm" % (global_rect.x()+3, global_rect.y()+3), shell=True, close_fds=True)
|
|
||||||
self.is_streaming = True
|
self.is_streaming = True
|
||||||
|
|
||||||
|
def fill_combo_box(self):
|
||||||
|
if self.dialog is not None:
|
||||||
|
self.dialog.deleteLater()
|
||||||
|
self.dialog = None
|
||||||
|
|
||||||
|
self.text_combo.clear()
|
||||||
|
current_row = -1
|
||||||
|
for index, list_obj in enumerate(self.model.text_db):
|
||||||
|
preview, text = list_obj
|
||||||
|
self.text_combo.addAction(preview)
|
||||||
|
if list_obj == self.current_object:
|
||||||
|
current_row = index
|
||||||
|
|
||||||
|
if current_row == -1:
|
||||||
|
current_row = self.current_index
|
||||||
|
self.slot_load_preview_text(current_row)
|
||||||
|
self.text_combo.setCurrentItem(current_row)
|
||||||
|
|
||||||
def focusChanged(self, old, new):
|
def focusChanged(self, old, new):
|
||||||
if new == self.preview_text:
|
if new == self.preview_text:
|
||||||
self.live_editor_collection.clearAssociatedWidgets()
|
self.live_editor_collection.clearAssociatedWidgets()
|
||||||
|
@ -570,18 +559,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
self.preview_editor_collection.clearAssociatedWidgets()
|
self.preview_editor_collection.clearAssociatedWidgets()
|
||||||
self.live_editor_collection.addAssociatedWidget(self.toolbar)
|
self.live_editor_collection.addAssociatedWidget(self.toolbar)
|
||||||
|
|
||||||
def custom_clear(self, cursor):
|
|
||||||
cursor.beginEditBlock()
|
|
||||||
cursor.movePosition(QtGui.QTextCursor.Start);
|
|
||||||
cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.KeepAnchor);
|
|
||||||
cursor.removeSelectedText()
|
|
||||||
cursor.endEditBlock()
|
|
||||||
|
|
||||||
|
|
||||||
def get_preview_text(self, text):
|
|
||||||
return re.sub(" +", " ", text.replace("\n", " ")).strip()[:20]
|
|
||||||
|
|
||||||
|
|
||||||
def slot_auto_publish(self, state):
|
def slot_auto_publish(self, state):
|
||||||
self.is_auto_publish = bool(state)
|
self.is_auto_publish = bool(state)
|
||||||
|
|
||||||
|
@ -589,11 +566,10 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
self.is_animate = bool(state)
|
self.is_animate = bool(state)
|
||||||
|
|
||||||
def slot_toggle_streaming(self):
|
def slot_toggle_streaming(self):
|
||||||
if self.ffserver is None:
|
if self.is_streaming:
|
||||||
self.start_streaming()
|
|
||||||
else:
|
|
||||||
self.stop_streaming()
|
self.stop_streaming()
|
||||||
|
else:
|
||||||
|
self.start_streaming()
|
||||||
|
|
||||||
def slot_next_item(self):
|
def slot_next_item(self):
|
||||||
try:
|
try:
|
||||||
|
@ -603,7 +579,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def slot_previous_item(self):
|
def slot_previous_item(self):
|
||||||
try:
|
try:
|
||||||
self.current = (self.text_combo.currentItem() - 1) % len(self.model.text_db)
|
self.current = (self.text_combo.currentItem() - 1) % len(self.model.text_db)
|
||||||
|
@ -612,26 +587,22 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def slot_publish(self):
|
def slot_publish(self):
|
||||||
if self.is_animate:
|
if self.is_animate:
|
||||||
self.animation.start_animation(self.preview_text, self.live_text, 0)
|
self.animation.start_animation(self.preview_text, self.live_text, 0)
|
||||||
else:
|
else:
|
||||||
self.live_text.setTextOrHtml(self.preview_text.textOrHtml())
|
self.live_text.setTextOrHtml(self.preview_text.textOrHtml())
|
||||||
|
|
||||||
|
|
||||||
def slot_live_font_size(self, action):
|
def slot_live_font_size(self, action):
|
||||||
self.default_size = self.live_size_action.fontSize()
|
self.default_size = self.live_size_action.fontSize()
|
||||||
self.slot_set_preview_defaults()
|
self.slot_set_preview_defaults()
|
||||||
self.slot_set_live_defaults()
|
self.slot_set_live_defaults()
|
||||||
|
|
||||||
|
|
||||||
def slot_preview_font_size(self, action):
|
def slot_preview_font_size(self, action):
|
||||||
self.default_size = self.preview_size_action.fontSize()
|
self.default_size = self.preview_size_action.fontSize()
|
||||||
self.slot_set_live_defaults()
|
self.slot_set_live_defaults()
|
||||||
self.slot_set_preview_defaults()
|
self.slot_set_preview_defaults()
|
||||||
|
|
||||||
|
|
||||||
def slot_toggle_publish(self, state=None):
|
def slot_toggle_publish(self, state=None):
|
||||||
|
|
||||||
if state:
|
if state:
|
||||||
|
@ -639,7 +610,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
else:
|
else:
|
||||||
self.slot_clear_live()
|
self.slot_clear_live()
|
||||||
|
|
||||||
|
|
||||||
def slot_set_preview_defaults(self):
|
def slot_set_preview_defaults(self):
|
||||||
self.preview_center_action.setChecked(True)
|
self.preview_center_action.setChecked(True)
|
||||||
self.preview_text.alignCenter()
|
self.preview_text.alignCenter()
|
||||||
|
@ -668,23 +638,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
if self.fade_animation.timer is None:
|
if self.fade_animation.timer is None:
|
||||||
self.fade_animation.start_animation()
|
self.fade_animation.start_animation()
|
||||||
|
|
||||||
def fill_combo_box(self):
|
|
||||||
if self.dialog is not None:
|
|
||||||
self.dialog.deleteLater()
|
|
||||||
self.dialog = None
|
|
||||||
|
|
||||||
self.text_combo.clear()
|
|
||||||
current_row = -1
|
|
||||||
for ix, list_obj in enumerate(self.model.text_db):
|
|
||||||
preview, text = list_obj
|
|
||||||
self.text_combo.addAction(preview)
|
|
||||||
if list_obj == self.current_object:
|
|
||||||
current_row = ix
|
|
||||||
|
|
||||||
if current_row == -1:
|
|
||||||
current_row = self.current_index
|
|
||||||
self.slot_load_preview_text(current_row)
|
|
||||||
self.text_combo.setCurrentItem(current_row)
|
|
||||||
|
|
||||||
def slot_load_preview_text(self, index):
|
def slot_load_preview_text(self, index):
|
||||||
try:
|
try:
|
||||||
|
@ -697,7 +650,7 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
def slot_save_live_text(self):
|
def slot_save_live_text(self):
|
||||||
text = self.live_text.toHtml()
|
text = self.live_text.toHtml()
|
||||||
preview = self.get_preview_text(unicode(self.live_text.toPlainText()))
|
preview = get_preview_text(unicode(self.live_text.toPlainText()))
|
||||||
if not preview:
|
if not preview:
|
||||||
return
|
return
|
||||||
old_item = self.model.text_by_preview(preview)
|
old_item = self.model.text_by_preview(preview)
|
||||||
|
@ -720,7 +673,7 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
|
|
||||||
def slot_save_preview_text(self):
|
def slot_save_preview_text(self):
|
||||||
text = self.preview_text.toHtml()
|
text = self.preview_text.toHtml()
|
||||||
preview = self.get_preview_text(unicode(self.preview_text.toPlainText()))
|
preview = get_preview_text(unicode(self.preview_text.toPlainText()))
|
||||||
|
|
||||||
if not preview:
|
if not preview:
|
||||||
return
|
return
|
||||||
|
@ -747,7 +700,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
cPickle.dump(self.model.text_db, f, cPickle.HIGHEST_PROTOCOL)
|
cPickle.dump(self.model.text_db, f, cPickle.HIGHEST_PROTOCOL)
|
||||||
self.db_dirty = False
|
self.db_dirty = False
|
||||||
|
|
||||||
|
|
||||||
def slot_open_dialog(self):
|
def slot_open_dialog(self):
|
||||||
self.current_index = self.text_combo.currentItem()
|
self.current_index = self.text_combo.currentItem()
|
||||||
self.current_object = self.model.text_db[self.current_index]
|
self.current_object = self.model.text_db[self.current_index]
|
||||||
|
@ -756,42 +708,61 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
||||||
self.dialog = None
|
self.dialog = None
|
||||||
|
|
||||||
self.dialog = KDialog(self)
|
self.dialog = KDialog(self)
|
||||||
self.dialog_widget = TextSorterDialog(self.dialog)
|
self.dialog.setButtons(KDialog.Close)
|
||||||
|
self.dialog_widget = EditDialog(self.dialog)
|
||||||
self.dialog.setMainWidget(self.dialog_widget)
|
self.dialog.setMainWidget(self.dialog_widget)
|
||||||
pos_x, pos_y = self.getPreviewCoords()
|
pos_x, pos_y = self.getPreviewCoords()
|
||||||
self.dialog.move(pos_x, 0)
|
self.dialog.move(pos_x, self.pos().y())
|
||||||
rect = app.desktop().availableGeometry()
|
|
||||||
global_width = rect.width()
|
|
||||||
global_height = rect.height()
|
|
||||||
x = global_width - pos_x - 10
|
|
||||||
#self.dialog.setFixedSize(x, global_height-40)
|
|
||||||
self.dialog.okClicked.connect(self.fill_combo_box)
|
|
||||||
self.dialog.exec_()
|
self.dialog.exec_()
|
||||||
|
self.fill_combo_box()
|
||||||
|
|
||||||
def slot_load(self):
|
def slot_load(self):
|
||||||
path = os.path.expanduser("~/.texter")
|
path = os.path.expanduser("~/.texter")
|
||||||
if not os.path.isdir(path):
|
if not os.path.isdir(path):
|
||||||
os.mkdir(path)
|
os.mkdir(path)
|
||||||
try:
|
try:
|
||||||
f = open(os.path.join(path, "texter.db"))
|
db_file = open(os.path.join(path, "texter.db"))
|
||||||
except IOError:
|
except IOError:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.model.text_db = [list(i) for i in cPickle.load(f)]
|
self.model.text_db = [list(i) for i in cPickle.load(db_file)]
|
||||||
except Exception, e:
|
except ValueError, error:
|
||||||
print e
|
logger.exception(error)
|
||||||
|
|
||||||
self.fill_combo_box()
|
self.fill_combo_box()
|
||||||
self.text_combo.setCurrentItem(0)
|
self.text_combo.setCurrentItem(0)
|
||||||
self.slot_load_preview_text(0)
|
self.slot_load_preview_text(0)
|
||||||
|
|
||||||
|
def sigint_handler(self, ex_cls, ex, tb):
|
||||||
|
"""Handler for the SIGINT signal."""
|
||||||
|
if ex_cls == KeyboardInterrupt:
|
||||||
|
logger.info("found KeyboardInterrupt")
|
||||||
|
QtGui.QApplication.exit()
|
||||||
|
else:
|
||||||
|
logger.critical(''.join(traceback.format_tb(tb)))
|
||||||
|
logger.critical('{0}: {1}'.format(ex_cls, ex))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
window = MainWindow()
|
arg_parser = ArgParser("texter")
|
||||||
app.exec_()
|
arg_parser.add_global_group()
|
||||||
|
client_group = arg_parser.add_client_group()
|
||||||
|
arg_parser.add_argument(client_group, '-x', "--http_host", default="::",
|
||||||
|
help='my host, defaults to "::"')
|
||||||
|
arg_parser.add_argument(client_group, '-X', "--http_port", default=9001,
|
||||||
|
type=int, help='my port, defaults to 9001')
|
||||||
|
arg_parser.add_chaosc_group()
|
||||||
|
arg_parser.add_subscriber_group()
|
||||||
|
args = arg_parser.finalize()
|
||||||
|
|
||||||
|
args.http_host, args.http_port = resolve_host(args.http_host, args.http_port, args.address_family)
|
||||||
|
args.chaosc_host, args.chaosc_port = resolve_host(args.chaosc_host, args.chaosc_port, args.address_family)
|
||||||
|
|
||||||
|
window = MainWindow(args, None)
|
||||||
|
sys.excepthook = window.sigint_handler
|
||||||
|
qtapp.exec_()
|
||||||
|
|
||||||
|
|
||||||
if ( __name__ == '__main__' ):
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -16,11 +16,9 @@ class TextModel(QtCore.QAbstractTableModel):
|
||||||
return len(self.text_db)
|
return len(self.text_db)
|
||||||
|
|
||||||
def columnCount(self, parent=QtCore.QModelIndex()):
|
def columnCount(self, parent=QtCore.QModelIndex()):
|
||||||
return 2
|
return 1
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if role not in (1,3,4,5,6,7,8,9,10,13):
|
|
||||||
print "role", role
|
|
||||||
if not index.isValid() or \
|
if not index.isValid() or \
|
||||||
not 0 <= index.row() < self.rowCount():
|
not 0 <= index.row() < self.rowCount():
|
||||||
return QVariant()
|
return QVariant()
|
||||||
|
@ -28,12 +26,9 @@ class TextModel(QtCore.QAbstractTableModel):
|
||||||
row = index.row()
|
row = index.row()
|
||||||
column = index.column()
|
column = index.column()
|
||||||
if role == QtCore.Qt.DisplayRole:
|
if role == QtCore.Qt.DisplayRole:
|
||||||
return self.text_db[row][column]
|
print "data", row, column, row
|
||||||
|
return QtCore.QVariant(self.text_db[row][column])
|
||||||
#return "foo bar"
|
#return "foo bar"
|
||||||
elif role == QtCore.Qt.ForegroundRole:
|
|
||||||
return QtGui.QBrush(QtCore.Qt.black)
|
|
||||||
elif role == QtCore.Qt.BackgroundRole:
|
|
||||||
return QtGui.QBrush(QtCore.Qt.white)
|
|
||||||
|
|
||||||
return QtCore.QVariant()
|
return QtCore.QVariant()
|
||||||
|
|
||||||
|
@ -47,6 +42,12 @@ class TextModel(QtCore.QAbstractTableModel):
|
||||||
return QtCore.QVariant()
|
return QtCore.QVariant()
|
||||||
|
|
||||||
def setData(self, index, value, role):
|
def setData(self, index, value, role):
|
||||||
|
if (not index.isValid() or
|
||||||
|
not 0 <= index.row() < self.rowCount()):
|
||||||
|
print "setData index not valid"
|
||||||
|
return False
|
||||||
|
|
||||||
|
print "setData", index.row(), index.column(), value, role
|
||||||
|
|
||||||
if role == QtCore.Qt.EditRole:
|
if role == QtCore.Qt.EditRole:
|
||||||
text = value.toString()
|
text = value.toString()
|
||||||
|
@ -54,14 +55,16 @@ class TextModel(QtCore.QAbstractTableModel):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self.text_db[index.row()][index.column()] = text
|
self.text_db[index.row()][index.column()] = text
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def flags(self, index):
|
def flags(self, index):
|
||||||
return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled
|
if index.column() == 0:
|
||||||
|
return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled
|
||||||
|
else:
|
||||||
|
return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
|
||||||
|
|
||||||
def supportedDropActions(self):
|
|
||||||
return QtCore.Qt.MoveAction
|
|
||||||
|
|
||||||
def insertRows(self, row, count, parent=QtCore.QModelIndex()):
|
def insertRows(self, row, count, parent=QtCore.QModelIndex()):
|
||||||
self.beginInsertRows(parent, row, row+count+1)
|
self.beginInsertRows(parent, row, row+count+1)
|
||||||
|
|
|
@ -1,157 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>text_sorter_dialog</class>
|
|
||||||
<widget class="QDialog" name="text_sorter_dialog">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Dialog</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QListView" name="text_list">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KButtonGroup" name="kbuttongroup">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="remove_button">
|
|
||||||
<property name="text">
|
|
||||||
<string>Remove</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="edit-delete"/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KArrowButton" name="move_up_button"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KArrowButton" name="move_down_button">
|
|
||||||
<property name="arrowType" stdset="0">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KRichTextWidget" name="text_preview"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>KArrowButton</class>
|
|
||||||
<extends>QPushButton</extends>
|
|
||||||
<header>karrowbutton.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KRichTextEdit</class>
|
|
||||||
<extends>KTextEdit</extends>
|
|
||||||
<header>krichtextedit.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KButtonGroup</class>
|
|
||||||
<extends>QGroupBox</extends>
|
|
||||||
<header>kbuttongroup.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KPushButton</class>
|
|
||||||
<extends>QPushButton</extends>
|
|
||||||
<header>kpushbutton.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KTextEdit</class>
|
|
||||||
<extends>QTextEdit</extends>
|
|
||||||
<header>ktextedit.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KRichTextWidget</class>
|
|
||||||
<extends>KRichTextEdit</extends>
|
|
||||||
<header>krichtextwidget.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>text_sorter_dialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>248</x>
|
|
||||||
<y>254</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>text_sorter_dialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>316</x>
|
|
||||||
<y>260</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
|
@ -0,0 +1 @@
|
||||||
|
index.html
|
|
@ -1,5 +1,16 @@
|
||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="texter">
|
<qresource prefix="texter">
|
||||||
|
<file>images/document-new.png</file>
|
||||||
|
<file>images/document-open-data.png</file>
|
||||||
|
<file>images/document-open-recent.png</file>
|
||||||
|
<file>images/document-save.png</file>
|
||||||
|
<file>images/edit-clear.png</file>
|
||||||
|
<file>images/edit-copy.png</file>
|
||||||
|
<file>images/go-next-view-page.png</file>
|
||||||
|
<file>images/go-previous-view-page.png</file>
|
||||||
|
<file>images/media-playback-stop.png</file>
|
||||||
|
<file>images/media-record.png</file>
|
||||||
|
<file>images/view-refresh.png</file>
|
||||||
<file>icon.png</file>
|
<file>icon.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -1,395 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>MainWindow</class>
|
|
||||||
<widget class="QMainWindow" name="MainWindow">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>1554</width>
|
|
||||||
<height>617</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="palette">
|
|
||||||
<palette>
|
|
||||||
<active>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</active>
|
|
||||||
<inactive>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</inactive>
|
|
||||||
<disabled>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>169</red>
|
|
||||||
<green>167</green>
|
|
||||||
<blue>167</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>244</red>
|
|
||||||
<green>244</green>
|
|
||||||
<blue>244</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</disabled>
|
|
||||||
</palette>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>4.48 Texter</string>
|
|
||||||
</property>
|
|
||||||
<property name="windowIcon">
|
|
||||||
<iconset resource="texter.qrc">
|
|
||||||
<normaloff>:/texter/icon.png</normaloff>:/texter/icon.png</iconset>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="centralwidget">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="KRichTextWidget" name="live_text">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>768</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>768</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Monospace</family>
|
|
||||||
<pointsize>22</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="cursor" stdset="0">
|
|
||||||
<cursorShape>BlankCursor</cursorShape>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="statusTip">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="whatsThis">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="autoFillBackground">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="acceptRichText">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="clear_live_button">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>clear live text [F1]</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="edit-clear">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>F1</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="live_save_button">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>save live text [F2]</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="document-save">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<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="KPushButton" name="streaming_button">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>starts/stops live textfield streaming [F9]</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="media-record"/>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="KRichTextWidget" name="preview_text">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>400</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>768</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Monospace</family>
|
|
||||||
<pointsize>22</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="contextMenuPolicy">
|
|
||||||
<enum>Qt::ActionsContextMenu</enum>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>preview text</string>
|
|
||||||
</property>
|
|
||||||
<property name="autoFillBackground">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::StyledPanel</enum>
|
|
||||||
</property>
|
|
||||||
<property name="acceptRichText">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="clear_preview_button">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>clear preview text [F4]</string>
|
|
||||||
</property>
|
|
||||||
<property name="statusTip">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="whatsThis">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="edit-clear">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>F2</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="preview_save_button">
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="document-save">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="publish_button">
|
|
||||||
<property name="cursor">
|
|
||||||
<cursorShape>ArrowCursor</cursorShape>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>go live with text [F5]</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="media-playback-start">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>F4</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="previous_button">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>load previous text [F6]</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="media-skip-backward">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="next_button">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>load next text [F7]</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="media-skip-forward">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KComboBox" name="text_combo">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="editable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="text_open_button">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>edit sorting of saved texts [F10]</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="document-open">
|
|
||||||
<normaloff/>
|
|
||||||
</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>KRichTextEdit</class>
|
|
||||||
<extends>KTextEdit</extends>
|
|
||||||
<header>krichtextedit.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KComboBox</class>
|
|
||||||
<extends>QComboBox</extends>
|
|
||||||
<header>kcombobox.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KPushButton</class>
|
|
||||||
<extends>QPushButton</extends>
|
|
||||||
<header>kpushbutton.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KTextEdit</class>
|
|
||||||
<extends>QTextEdit</extends>
|
|
||||||
<header>ktextedit.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KRichTextWidget</class>
|
|
||||||
<extends>KRichTextEdit</extends>
|
|
||||||
<header>krichtextwidget.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<tabstops>
|
|
||||||
<tabstop>live_text</tabstop>
|
|
||||||
<tabstop>preview_text</tabstop>
|
|
||||||
<tabstop>clear_preview_button</tabstop>
|
|
||||||
<tabstop>clear_live_button</tabstop>
|
|
||||||
</tabstops>
|
|
||||||
<resources>
|
|
||||||
<include location="texter.qrc"/>
|
|
||||||
</resources>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
|
@ -1,403 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>MainWindow</class>
|
|
||||||
<widget class="QMainWindow" name="MainWindow">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>1475</width>
|
|
||||||
<height>651</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="palette">
|
|
||||||
<palette>
|
|
||||||
<active>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</active>
|
|
||||||
<inactive>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</inactive>
|
|
||||||
<disabled>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>169</red>
|
|
||||||
<green>167</green>
|
|
||||||
<blue>167</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>244</red>
|
|
||||||
<green>244</green>
|
|
||||||
<blue>244</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</disabled>
|
|
||||||
</palette>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>4.48 Texter</string>
|
|
||||||
</property>
|
|
||||||
<property name="windowIcon">
|
|
||||||
<iconset resource="texter.qrc">
|
|
||||||
<normaloff>:/texter/icon.png</normaloff>:/texter/icon.png</iconset>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="centralwidget">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="KRichTextWidget" name="live_text">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>775</width>
|
|
||||||
<height>582</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>775</width>
|
|
||||||
<height>582</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="palette">
|
|
||||||
<palette>
|
|
||||||
<active>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Window">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Highlight">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Link">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</active>
|
|
||||||
<inactive>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Window">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Highlight">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Link">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</inactive>
|
|
||||||
<disabled>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Window">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Highlight">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Link">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</disabled>
|
|
||||||
</palette>
|
|
||||||
</property>
|
|
||||||
<property name="autoFillBackground">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="verticalScrollBarPolicy">
|
|
||||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
|
||||||
</property>
|
|
||||||
<property name="horizontalScrollBarPolicy">
|
|
||||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
|
||||||
</property>
|
|
||||||
<property name="acceptRichText">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
<property name="richTextSupport">
|
|
||||||
<set>KRichTextWidget::SupportAlignment|KRichTextWidget::SupportFontFamily|KRichTextWidget::SupportFontSize|KRichTextWidget::SupportTextForegroundColor</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KRichTextWidget" name="preview_text">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>10</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>300</width>
|
|
||||||
<height>582</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>775</width>
|
|
||||||
<height>582</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="palette">
|
|
||||||
<palette>
|
|
||||||
<active>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Window">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</active>
|
|
||||||
<inactive>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Window">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</inactive>
|
|
||||||
<disabled>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Window">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</disabled>
|
|
||||||
</palette>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>preview text</string>
|
|
||||||
</property>
|
|
||||||
<property name="autoFillBackground">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::StyledPanel</enum>
|
|
||||||
</property>
|
|
||||||
<property name="acceptRichText">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextEditable|Qt::TextEditorInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
<property name="richTextSupport">
|
|
||||||
<set>KRichTextWidget::SupportAlignment|KRichTextWidget::SupportChangeListStyle|KRichTextWidget::SupportFontFamily|KRichTextWidget::SupportFontSize|KRichTextWidget::SupportTextForegroundColor</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>KRichTextEdit</class>
|
|
||||||
<extends>KTextEdit</extends>
|
|
||||||
<header>krichtextedit.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KTextEdit</class>
|
|
||||||
<extends>QTextEdit</extends>
|
|
||||||
<header>ktextedit.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KRichTextWidget</class>
|
|
||||||
<extends>KRichTextEdit</extends>
|
|
||||||
<header>krichtextwidget.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<tabstops>
|
|
||||||
<tabstop>live_text</tabstop>
|
|
||||||
<tabstop>preview_text</tabstop>
|
|
||||||
</tabstops>
|
|
||||||
<resources>
|
|
||||||
<include location="texter.qrc"/>
|
|
||||||
</resources>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
|
@ -1,559 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>TextSorterDialog</class>
|
|
||||||
<widget class="QWidget" name="TextSorterDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>1084</width>
|
|
||||||
<height>633</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Form</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QListView" name="text_list">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>1</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>200</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
<widget class="KRichTextWidget" name="text_preview">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>100</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>768</width>
|
|
||||||
<height>576</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="palette">
|
|
||||||
<palette>
|
|
||||||
<active>
|
|
||||||
<colorrole role="WindowText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Button">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Light">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Midlight">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Dark">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Mid">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="BrightText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="ButtonText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Window">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Shadow">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="AlternateBase">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="ToolTipBase">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>220</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="ToolTipText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</active>
|
|
||||||
<inactive>
|
|
||||||
<colorrole role="WindowText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Button">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Light">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Midlight">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Dark">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Mid">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="BrightText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="ButtonText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Window">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Shadow">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="AlternateBase">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="ToolTipBase">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>220</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="ToolTipText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</inactive>
|
|
||||||
<disabled>
|
|
||||||
<colorrole role="WindowText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Button">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Light">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Midlight">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Dark">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Mid">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Text">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="BrightText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>255</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="ButtonText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Base">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Window">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="Shadow">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="AlternateBase">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="ToolTipBase">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>255</red>
|
|
||||||
<green>255</green>
|
|
||||||
<blue>220</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
<colorrole role="ToolTipText">
|
|
||||||
<brush brushstyle="SolidPattern">
|
|
||||||
<color alpha="255">
|
|
||||||
<red>0</red>
|
|
||||||
<green>0</green>
|
|
||||||
<blue>0</blue>
|
|
||||||
</color>
|
|
||||||
</brush>
|
|
||||||
</colorrole>
|
|
||||||
</disabled>
|
|
||||||
</palette>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KButtonGroup" name="kbuttongroup">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="KArrowButton" name="move_down_button">
|
|
||||||
<property name="arrowType" stdset="0">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KArrowButton" name="move_up_button"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="KPushButton" name="remove_button">
|
|
||||||
<property name="text">
|
|
||||||
<string>Remove</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset theme="edit-delete">
|
|
||||||
<normaloff>../../../../</normaloff>../../../../</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>KArrowButton</class>
|
|
||||||
<extends>QPushButton</extends>
|
|
||||||
<header>karrowbutton.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KRichTextEdit</class>
|
|
||||||
<extends>KTextEdit</extends>
|
|
||||||
<header>krichtextedit.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KButtonGroup</class>
|
|
||||||
<extends>QGroupBox</extends>
|
|
||||||
<header>kbuttongroup.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KPushButton</class>
|
|
||||||
<extends>QPushButton</extends>
|
|
||||||
<header>kpushbutton.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KTextEdit</class>
|
|
||||||
<extends>QTextEdit</extends>
|
|
||||||
<header>ktextedit.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
|
||||||
<class>KRichTextWidget</class>
|
|
||||||
<extends>KRichTextEdit</extends>
|
|
||||||
<header>krichtextwidget.h</header>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Resource object code
|
# Resource object code
|
||||||
#
|
#
|
||||||
# Created: Sa. Apr 12 08:49:54 2014
|
# Created: So. Mai 11 12:37:13 2014
|
||||||
# by: The Resource Compiler for PyQt (Qt v4.8.5)
|
# by: The Resource Compiler for PyQt (Qt v4.8.5)
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -47,6 +47,482 @@ qt_resource_data = "\
|
||||||
\x38\x8f\xeb\x38\x43\x35\x89\xdd\x94\xa5\xf7\x2f\xa8\x01\x6a\x80\
|
\x38\x8f\xeb\x38\x43\x35\x89\xdd\x94\xa5\xf7\x2f\xa8\x01\x6a\x80\
|
||||||
\x1a\xa0\x06\xf8\xdf\xf2\x1b\xf1\xb2\x57\x16\x4f\x60\xf0\x28\x00\
|
\x1a\xa0\x06\xf8\xdf\xf2\x1b\xf1\xb2\x57\x16\x4f\x60\xf0\x28\x00\
|
||||||
\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
|
\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
|
||||||
|
\x00\x00\x02\x7f\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x03\x00\x00\x00\x28\x2d\x0f\x53\
|
||||||
|
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
|
||||||
|
\x09\x70\x48\x59\x73\x00\x00\x06\xec\x00\x00\x06\xec\x01\x1e\x75\
|
||||||
|
\x38\x35\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x07\x03\x0a\x15\
|
||||||
|
\x1c\xbc\x0f\x78\x91\x00\x00\x01\x11\x50\x4c\x54\x45\x00\x00\x00\
|
||||||
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||||
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x00\x00\
|
||||||
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x32\x71\x2d\x8f\x90\x91\
|
||||||
|
\x93\x93\x94\x8c\x8e\x8f\x90\x90\x91\x18\x48\x1d\x18\x49\x28\x1b\
|
||||||
|
\x57\x19\x1d\x56\x17\x21\x62\x1e\x27\x70\x28\x32\x82\x34\x3d\x8e\
|
||||||
|
\x3c\x3e\x7e\x18\x54\x9d\x4c\x55\x87\x5d\x55\x9e\x4f\x5b\x9d\x56\
|
||||||
|
\x63\x9f\x38\x64\xa7\x53\x74\xa4\x77\x75\xac\x0c\x77\xb2\x50\x7c\
|
||||||
|
\xb3\x78\x85\xbe\x20\x8b\xa9\x92\x8e\xc4\x23\x8f\x94\x92\x91\xc8\
|
||||||
|
\x24\x99\xd2\x0b\x9b\x9d\x9e\x9e\x9f\xa0\x9f\x9f\xa0\x9f\xad\xa3\
|
||||||
|
\xa0\xd7\x0c\xa2\xa3\xa3\xa6\xa7\xa8\xa7\xa7\xa8\xa8\xa8\xa8\xa8\
|
||||||
|
\xd0\x6a\xaa\xd0\x72\xb9\xb9\xb9\xba\xba\xba\xbf\xde\x9a\xc5\xc5\
|
||||||
|
\xc5\xc5\xc6\xc6\xc8\xca\xcb\xd2\xd2\xd2\xd2\xda\xd4\xd2\xe2\xd2\
|
||||||
|
\xd8\xe9\xd6\xd9\xd9\xd9\xdb\xdb\xdb\xdf\xed\xde\xe3\xe3\xe3\xe9\
|
||||||
|
\xef\xe9\xea\xea\xea\xee\xee\xee\xee\xef\xef\xef\xef\xef\xf0\xf0\
|
||||||
|
\xf0\xf2\xf7\xf1\xf4\xf5\xf5\xf5\xf5\xf5\xf5\xf6\xf6\xf6\xf6\xf6\
|
||||||
|
\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf9\xf9\xf9\xf9\xf9\xfa\xfa\xfa\xfb\
|
||||||
|
\xfb\xfb\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfe\xfe\xff\xff\xff\x79\x1f\
|
||||||
|
\xc0\x25\x00\x00\x00\x14\x74\x52\x4e\x53\x00\x10\x13\x15\x1b\x1c\
|
||||||
|
\x24\x25\x26\x3a\x3b\x44\x4e\x4f\x7e\x8b\xdb\xdb\xdc\xdc\x37\x8a\
|
||||||
|
\x8c\x11\x00\x00\x00\x01\x62\x4b\x47\x44\x5a\x03\xbb\xa5\xa2\x00\
|
||||||
|
\x00\x00\xc7\x49\x44\x41\x54\x78\xda\x3d\x8c\x7b\x57\x01\x51\x14\
|
||||||
|
\x47\xaf\x47\x1e\xdd\x48\x49\x09\x21\xa2\xbc\x9a\xd0\x28\xc9\x23\
|
||||||
|
\x0a\x0d\xaa\x99\xdc\xb9\xe7\xce\xf7\xff\x20\x9d\xb3\xe6\xae\x7e\
|
||||||
|
\x7f\x9d\xbd\xd7\x5e\x87\x05\xe3\xff\x0b\x30\x5a\xc2\xd3\x7b\x7b\
|
||||||
|
\xe7\x5a\xec\x7e\x9c\xbd\x10\xa2\x74\x75\x7c\x48\x55\x42\xd9\xbf\
|
||||||
|
\x42\xb8\xae\x9b\x7f\xa9\xd4\xb7\x1e\x47\xb1\x47\x94\x52\xe6\x9e\
|
||||||
|
\x06\xb5\xf2\x0c\x85\x27\x10\x01\xe0\xf2\xb6\xd5\xb8\xae\x92\x20\
|
||||||
|
\x56\x0a\xb2\xed\x6e\xa1\xb8\xe4\xec\x08\x05\x28\x69\x5b\x17\x37\
|
||||||
|
\xe7\x77\x12\x48\x20\xc3\xca\x34\xce\x32\x0f\x00\x0a\x85\x42\x61\
|
||||||
|
\x9b\x0a\xa6\xcd\x85\xb5\xfe\xf6\x0b\xd8\x18\xe0\x74\x46\xa6\xd1\
|
||||||
|
\x1f\x6b\xf1\xf9\xe8\xdc\x4f\xb0\x72\xd2\x07\xfe\x8f\xaf\xd7\xde\
|
||||||
|
\x9c\xaa\xd3\x18\x63\x21\xce\x79\x72\xf8\xfc\x41\x55\x2a\xca\xfc\
|
||||||
|
\xe9\xea\x24\xa2\x99\x2a\x5a\x98\xee\x3f\xcd\x34\x32\x2a\x58\xbf\
|
||||||
|
\xee\x5f\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
|
||||||
|
\x00\x00\x02\x6a\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x03\x00\x00\x00\x28\x2d\x0f\x53\
|
||||||
|
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
|
||||||
|
\x09\x70\x48\x59\x73\x00\x00\x06\xec\x00\x00\x06\xec\x01\x1e\x75\
|
||||||
|
\x38\x35\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x07\x03\x0f\x2d\
|
||||||
|
\x32\x71\x8d\x0b\x4e\x00\x00\x01\x0b\x50\x4c\x54\x45\x00\x00\x00\
|
||||||
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||||
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||||
|
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8f\x90\x91\x93\x93\x94\
|
||||||
|
\x8c\x8e\x8f\x90\x90\x91\x0b\x47\x16\x16\x47\x1d\x18\x5c\x1c\x20\
|
||||||
|
\x59\x1a\x23\x6e\x25\x28\x56\x32\x34\x83\x35\x3f\x8f\x3c\x40\x7e\
|
||||||
|
\x17\x54\x98\x51\x54\x9d\x4c\x55\x95\x2a\x5a\x8a\x61\x5d\xa2\x58\
|
||||||
|
\x61\xa5\x51\x73\xaf\x4e\x74\xa9\x70\x75\x91\x7c\x84\xb7\x0d\x84\
|
||||||
|
\xbd\x23\x87\xaf\x89\x89\xc2\x20\x90\xc7\x24\x9d\xd4\x0d\x9f\x9f\
|
||||||
|
\xa0\xa1\xd9\x0c\xa6\xa7\xa8\xa6\xc6\xa4\xa7\xa7\xa8\xa7\xd0\x6a\
|
||||||
|
\xa8\xa8\xa8\xab\xd1\x71\xaf\xaf\xaf\xb0\xb0\xb0\xbf\xde\x99\xc0\
|
||||||
|
\xc0\xc0\xc1\xc1\xc1\xc5\xc6\xc6\xc8\xca\xcb\xca\xd6\xcd\xcc\xe2\
|
||||||
|
\xca\xd3\xdc\xd6\xd6\xe4\xd7\xe2\xee\xe1\xe5\xe5\xe5\xea\xea\xea\
|
||||||
|
\xea\xef\xea\xed\xf2\xed\xee\xee\xee\xee\xef\xef\xee\xf2\xef\xef\
|
||||||
|
\xef\xef\xf0\xf0\xf0\xf4\xf5\xf5\xf5\xf5\xf5\xf5\xf6\xf5\xf5\xf6\
|
||||||
|
\xf6\xf6\xf6\xf6\xf6\xf7\xf6\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf9\xf8\
|
||||||
|
\xf9\xf9\xf9\xfa\xfa\xfa\xfb\xfb\xfb\xfc\xfc\xfc\xfd\xfd\xfd\xfd\
|
||||||
|
\xfe\xfd\xfe\xfe\xfe\xff\xff\xff\xd9\x1d\x54\xe2\x00\x00\x00\x13\
|
||||||
|
\x74\x52\x4e\x53\x00\x10\x13\x15\x1b\x1c\x24\x25\x26\x3a\x44\x4e\
|
||||||
|
\x4f\x6f\x7e\xdb\xdb\xdc\xdc\xc6\x90\x16\x3a\x00\x00\x00\x01\x62\
|
||||||
|
\x4b\x47\x44\x58\xed\xb5\xc4\x8e\x00\x00\x00\xb9\x49\x44\x41\x54\
|
||||||
|
\x18\x19\x05\xc1\x5d\x2e\x03\x51\x18\x00\xd0\xf3\xdd\x7e\x4a\x91\
|
||||||
|
\x8c\x90\x88\x48\x08\x89\x58\x8d\xd5\x76\x05\x7e\x36\x60\x05\xbc\
|
||||||
|
\xe0\x41\x24\xd5\xd0\x76\x66\x6a\xee\x38\x27\xcb\x2e\x80\x76\x44\
|
||||||
|
\xee\xdf\xc1\xc7\x70\xc1\x7c\x8d\xe4\x3b\x7f\x16\x8b\xc9\x56\x4c\
|
||||||
|
\x66\xb4\x69\x9c\xfe\xbe\xd5\xb3\xf7\xab\xe2\x1a\xf3\x64\xf1\x3a\
|
||||||
|
\x6d\x86\x71\x35\x0d\x90\xe2\xb3\x64\x37\xd6\x12\x81\x90\x9c\xbf\
|
||||||
|
\xac\x9a\x49\x15\x01\x72\x74\x7c\xf2\xfc\xd5\xd4\x21\x82\x52\x25\
|
||||||
|
\x11\xcd\xe9\x4b\x4c\xa3\xa8\xb5\x48\x23\x71\x79\xb0\xd9\x29\x43\
|
||||||
|
\xdf\x0e\x7b\x52\x40\x73\x54\xea\xd7\xb2\x2f\x87\x12\x8c\xe8\x96\
|
||||||
|
\xb7\xb5\x7f\xda\x26\x08\x6a\xd7\xd7\xfe\x71\xb3\xcd\x76\x4e\xde\
|
||||||
|
\x60\xc8\xfe\xbe\xed\xe4\xb0\xe6\x00\x65\x67\xf6\xb0\xe9\x49\x68\
|
||||||
|
\xe7\xa0\xff\xc3\x3f\x9e\x71\x4d\xf4\x47\x46\x2f\xfd\x00\x00\x00\
|
||||||
|
\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
|
||||||
|
\x00\x00\x02\x43\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
|
||||||
|
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
|
||||||
|
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
|
||||||
|
\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
|
||||||
|
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
|
||||||
|
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x01\xc0\x49\x44\
|
||||||
|
\x41\x54\x78\xda\x8d\x8f\xbd\x6b\x53\x51\x18\x87\x9f\x73\x72\xc1\
|
||||||
|
\xb6\x41\x90\x82\x52\x2a\xc5\x39\xdd\x8c\x93\x75\xab\x83\x9b\xbb\
|
||||||
|
\x53\xbb\xe4\x3f\x68\x07\x11\x8a\x25\xd4\x82\x43\x87\xa2\x20\x0e\
|
||||||
|
\x15\x07\xe9\x6a\x16\xc5\x3d\xb5\x88\xa1\x1f\x42\xd3\x4d\x25\xe8\
|
||||||
|
\xcd\x87\x83\x12\x92\x9b\x8f\x9b\x9c\xd7\xe6\xe0\xe1\x70\x89\x5f\
|
||||||
|
\x3f\xf8\x71\xce\x19\x9e\xe7\x7d\x8f\x02\x2e\x00\xf3\xfc\x2b\xab\
|
||||||
|
\xdc\xce\x5c\xcb\x2c\x65\x2f\x67\xa7\x0f\xab\x87\xf5\x72\xbb\xfc\
|
||||||
|
\x40\x96\xe5\x49\x30\x82\x1b\x8d\xc6\x9e\x11\x41\x6b\x6d\xab\x94\
|
||||||
|
\x4a\xf4\xd9\xc7\x1d\x76\x7f\xec\xb2\x78\x69\x91\xcd\xf9\x4d\xee\
|
||||||
|
\x95\xef\xce\xa5\xbf\xa5\x1f\xab\x1d\x25\x1a\xc0\x08\x7f\xcd\xf6\
|
||||||
|
\xe9\x36\xd5\x4e\x95\xfd\x4f\x05\x00\x3e\x57\x0b\x98\x41\x4d\x63\
|
||||||
|
\x58\x0d\x00\x52\x29\xeb\xb1\xd3\xdc\x06\xda\x6f\x40\xed\x7b\x8d\
|
||||||
|
\xe8\x4e\x84\xcb\x8b\x9b\x65\x00\xd4\x23\x35\x1b\x00\x16\x42\x04\
|
||||||
|
\xf5\xeb\x0b\x16\x76\xe7\x59\x67\xae\xcc\x10\x3c\x57\x5c\x05\xde\
|
||||||
|
\x2f\x09\xb9\x82\xe2\x40\x80\x8b\x84\xda\x4d\x76\xb0\x6b\xca\xdf\
|
||||||
|
\x59\xc9\xac\x20\xe7\x35\x61\x0a\x9b\x0f\xc0\xb1\xc1\x30\xc5\x43\
|
||||||
|
\xbf\x01\x78\x81\xff\x8a\x6d\x6e\x2e\x07\x1a\xb6\xbe\x6e\x91\x7e\
|
||||||
|
\x99\x26\x0a\xf8\xc2\x04\x79\xb9\x25\x4f\x15\xb0\xd0\x6c\x36\xf7\
|
||||||
|
\xbc\xc0\xd7\x6d\xe7\x4e\x97\x20\x08\x6e\x88\xc8\x5b\x7b\x07\x50\
|
||||||
|
\x7e\x03\x57\x0f\x26\xce\x64\xbc\x00\xdc\xba\x6e\xb2\x83\xfe\x4f\
|
||||||
|
\x40\x12\x76\x60\x42\x60\x8c\xb1\x6d\xb7\x23\x01\x62\x2f\x18\x03\
|
||||||
|
\xc6\xe1\x4a\xa5\x42\x18\x86\x4c\x4c\x4e\xf2\xea\xf5\x9b\x77\xc0\
|
||||||
|
\x11\xf8\x2c\x44\x51\x24\xdd\x6e\x57\xfa\xfd\xbe\xc4\x71\x2c\x83\
|
||||||
|
\xc1\x40\x86\xc3\xa1\x18\x63\xec\xbb\x58\x2c\xda\xf7\xfd\x8d\x8d\
|
||||||
|
\x13\x60\x4a\x44\x70\xc5\x0a\x3a\x9d\x3f\x0a\x5a\xad\x96\x94\x4a\
|
||||||
|
\x25\x59\xcb\xe7\x47\xf0\xb4\x87\xbd\xe0\xfa\x99\xc0\xf4\x7a\xbd\
|
||||||
|
\x11\x9c\x10\x8c\x52\xaf\x37\xcc\xda\xfa\xfa\xbe\x9f\x9c\xac\x02\
|
||||||
|
\xce\x01\x59\x40\xf1\xfb\xc4\xc0\x91\x88\xc4\x30\x9e\x9f\xaf\xc9\
|
||||||
|
\x06\x51\x54\x9d\xd3\x94\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
|
||||||
|
\x60\x82\
|
||||||
|
\x00\x00\x02\xdf\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x03\x00\x00\x00\x28\x2d\x0f\x53\
|
||||||
|
\x00\x00\x00\x03\x73\x42\x49\x54\x08\x08\x08\xdb\xe1\x4f\xe0\x00\
|
||||||
|
\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\x01\
|
||||||
|
\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\
|
||||||
|
\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\
|
||||||
|
\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x01\x4d\x50\x4c\x54\
|
||||||
|
\x45\xff\xff\xff\x59\x59\x59\x5c\x5c\x5c\x80\x80\x80\x83\x83\x83\
|
||||||
|
\x56\x56\x56\x63\x63\x63\x79\x79\x79\x86\x86\x86\x57\x57\x57\x5e\
|
||||||
|
\x5e\x5e\x7a\x7a\x7a\x81\x81\x81\x64\x64\x64\x74\x74\x74\x55\x55\
|
||||||
|
\x55\x64\x64\x64\x74\x74\x74\x84\x84\x84\x53\x53\x53\x66\x66\x66\
|
||||||
|
\x6f\x6f\x6f\x82\x82\x82\x5b\x5b\x5b\x7f\x7f\x7f\x52\x52\x52\x67\
|
||||||
|
\x67\x67\x6b\x6b\x6b\x80\x80\x80\x55\x55\x55\x5f\x5f\x5f\x74\x74\
|
||||||
|
\x74\x7d\x7d\x7d\x52\x52\x52\x54\x54\x54\x58\x58\x58\x5d\x5d\x5d\
|
||||||
|
\x5f\x5f\x5f\x61\x61\x61\x66\x66\x66\x6a\x6a\x6a\x6b\x6b\x6b\x6d\
|
||||||
|
\x6d\x6d\x6f\x6f\x6f\x71\x71\x71\x74\x74\x74\x75\x75\x75\x76\x76\
|
||||||
|
\x76\x77\x77\x77\x79\x79\x79\x7a\x7a\x7a\x80\x80\x80\x81\x81\x81\
|
||||||
|
\x88\x88\x88\x8f\x8f\x8f\x90\x90\x90\x9c\x9c\x9c\xb8\xb8\xb8\xba\
|
||||||
|
\xba\xba\xbe\xbe\xbe\xce\xce\xce\xd0\xd0\xd0\xd3\xd3\xd3\xd4\xd4\
|
||||||
|
\xd4\xd5\xd5\xd5\xd6\x04\x08\xd6\x35\x39\xd9\x06\x09\xd9\xd9\xd9\
|
||||||
|
\xda\x1f\x22\xda\x45\x48\xdb\xdb\xdb\xdc\x55\x58\xdd\xdd\xdd\xde\
|
||||||
|
\x37\x3a\xdf\x2d\x30\xdf\x39\x3c\xdf\x3d\x40\xdf\x60\x63\xe1\x08\
|
||||||
|
\x0a\xe1\x39\x3b\xe2\xe2\xe2\xe3\x1c\x1e\xe7\x0b\x0c\xe7\x39\x3b\
|
||||||
|
\xe8\xe8\xe8\xe9\xe9\xe9\xea\xea\xea\xeb\x2f\x30\xeb\x9e\xa0\xec\
|
||||||
|
\x9e\xa0\xec\xec\xec\xed\xa3\xa5\xed\xa8\xaa\xed\xed\xed\xef\xef\
|
||||||
|
\xef\xf0\xa0\xa1\xf0\xb8\xb9\xf1\xbd\xbf\xf1\xf1\xf1\xf2\xf2\xf2\
|
||||||
|
\xf3\xf3\xf3\xf5\x0f\x0f\xf6\xf6\xf6\xfa\xfa\xfa\xfb\xfb\xfb\xfc\
|
||||||
|
\xfa\xfa\xfc\xfc\xfc\xfd\xfd\xfd\xfe\xfa\xfa\xff\xff\xff\x7f\x3d\
|
||||||
|
\xcd\x14\x00\x00\x00\x21\x74\x52\x4e\x53\x00\x01\x01\x01\x01\x26\
|
||||||
|
\x26\x26\x26\x71\x71\x71\x71\x80\x80\x81\x81\x81\x81\xb5\xb5\xb5\
|
||||||
|
\xb5\xb6\xb6\xe7\xe7\xe7\xe7\xf6\xf6\xf6\xf6\x96\x0a\xc3\x45\x00\
|
||||||
|
\x00\x00\xd7\x49\x44\x41\x54\x18\x19\x05\xc1\xd1\x4e\x83\x30\x18\
|
||||||
|
\x06\xd0\xaf\xf4\x83\xb6\x38\xe6\x46\x3a\x97\xc5\xc4\xf7\x7f\x21\
|
||||||
|
\xaf\xbd\xd2\xe0\x2c\x66\x13\x18\x5d\xf9\x59\x3d\x87\x00\x60\x6b\
|
||||||
|
\x56\x48\x72\x8b\x00\x08\xd0\xfa\x67\x10\x82\x6b\x88\x02\x42\xfb\
|
||||||
|
\x17\x5a\x6d\x74\x5c\x8a\xed\xf9\x67\x25\xac\x77\xe6\x58\x97\xea\
|
||||||
|
\x31\xfe\xf5\x7e\x98\x68\xbc\x76\x6f\xae\xd0\xc8\xe5\xc6\x7e\x78\
|
||||||
|
\x61\xed\x36\xaf\x4e\xcf\x7d\x3a\xec\x74\x1b\xa2\x21\x0b\x65\x39\
|
||||||
|
\x7f\x56\xba\xcb\x6d\x79\xfa\x35\xac\x8c\x12\x84\xca\x32\x5d\x5b\
|
||||||
|
\xed\x5c\xc5\x9c\x35\xd5\xa8\xcc\xb6\xd7\x50\x44\x66\x9a\x1b\xc9\
|
||||||
|
\xc7\x4e\x7a\xd9\x23\xcb\x98\x28\xab\xcc\xce\xab\x8b\xda\x37\x58\
|
||||||
|
\x3b\xb9\xf3\x96\x2e\xbb\x46\x7b\x0f\x60\x5d\xbe\xd3\x9d\x29\x94\
|
||||||
|
\xc1\xb6\xa5\x56\x79\x5d\xde\x87\x90\x88\x38\xe6\xe1\x70\x72\x94\
|
||||||
|
\xee\x6b\x9a\x22\x88\xc7\xd9\xfa\x7b\xf7\xa4\xa6\x45\x42\xcc\x20\
|
||||||
|
\x90\xe7\xae\xe6\x88\x24\xb7\x05\xc0\x3f\x59\xa3\x6c\xf8\xab\x3b\
|
||||||
|
\x12\xed\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
|
||||||
|
\x00\x00\x02\xb9\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
|
||||||
|
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
|
||||||
|
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
|
||||||
|
\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
|
||||||
|
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
|
||||||
|
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x02\x36\x49\x44\
|
||||||
|
\x41\x54\x78\xda\x8d\x93\x4b\x68\x13\x51\x14\x86\xff\x99\xa4\x8d\
|
||||||
|
\x12\xcd\x22\x2a\x51\x31\xad\xa4\xf5\x85\x56\x11\x44\xa9\x82\x14\
|
||||||
|
\xb4\x2e\x02\x45\x21\x88\x0b\x37\x82\x1b\xf7\xa2\xa8\x28\xda\xba\
|
||||||
|
\x93\x22\x92\x16\xb5\x50\x1b\xba\x71\xa1\xb8\xa8\x95\x22\x3e\x16\
|
||||||
|
\x6e\x8a\x56\xac\x9a\x88\x91\xd0\xa4\xa0\x74\x9c\x49\x9a\x57\xf3\
|
||||||
|
\xec\x4c\x26\xc7\x7b\xad\x03\xce\x10\x8b\x1f\xfc\x5c\x38\x33\xe7\
|
||||||
|
\xbb\xe7\x32\x77\x04\x22\x82\x20\x08\x4e\x00\x3e\xfc\x0b\xa7\xc7\
|
||||||
|
\x81\x03\xe7\x4e\x41\x68\xf6\x42\x2f\x7f\xc7\xc7\xd0\x63\xe4\xa5\
|
||||||
|
\xaf\x44\x54\xb2\x63\x09\x1f\x11\x85\xd1\x80\x2f\x52\x11\xa7\xef\
|
||||||
|
\xbc\x81\xbf\xb3\x1d\xfb\x3d\xc0\x94\x02\x4c\x4c\x1d\xba\x10\x7e\
|
||||||
|
\xf5\xe4\x0c\x80\x51\xf0\x09\x18\x1d\xc4\xf8\x29\xcb\xa4\x24\x53\
|
||||||
|
\x34\x9f\x4e\x53\x26\x9b\x25\x29\x99\x26\xd7\xc9\x21\x1a\x8f\xa4\
|
||||||
|
\xa8\xbc\xa8\xd2\xc0\xe0\x20\x65\x72\x0b\x74\xeb\xe1\x24\x89\x3d\
|
||||||
|
\x03\x45\x1c\xbd\xb7\x42\xc4\x5f\xd8\x6c\x36\x16\x11\xa2\x20\x40\
|
||||||
|
\x60\x09\x8e\x4d\xc3\xe5\xdb\x82\xae\x36\x17\x6a\x9a\x8a\xf9\x54\
|
||||||
|
\x0a\x92\x3c\x87\xc0\xc1\x4d\xd8\xb0\x7d\x87\x13\xb6\xfc\x65\x93\
|
||||||
|
\x40\x14\xc5\xa5\x30\x11\x97\x84\x67\x15\x74\x77\xac\x07\xa0\xa3\
|
||||||
|
\x50\x2c\x21\x18\x0c\x22\x70\xfc\x04\x8e\x74\x1d\x66\x75\x0f\x2b\
|
||||||
|
\xab\x7b\xed\xd6\x09\xf8\xce\x5c\x22\x00\xd8\xb8\x6e\x15\xc6\x3f\
|
||||||
|
\x49\xe8\xef\xf1\xa2\x5c\x2a\x61\x38\x34\x02\xb7\x7b\x0d\xda\xda\
|
||||||
|
\xb7\x61\xdf\xed\x30\xd0\xa4\xcf\x35\x9e\x80\x49\xb8\xec\xbc\x7f\
|
||||||
|
\x17\x72\xd5\x2c\xee\xbe\x4e\x40\x27\xa0\xa5\xa5\x15\x0e\x4f\x2b\
|
||||||
|
\x46\xdf\x29\x48\x16\xd2\x1a\x3e\x3f\xea\x37\x4d\x60\x9c\xdd\x10\
|
||||||
|
\xf9\x36\x7b\x71\x71\xe7\x7b\xdc\x7c\xfb\x03\xc1\xe7\x45\x1c\xdb\
|
||||||
|
\xea\xc6\xcb\x99\x38\xf2\xab\x1d\xc0\xe4\xc8\x30\xa4\x68\xc2\x34\
|
||||||
|
\x81\xc0\x1b\x2d\xb9\x76\x36\x80\xa7\xdd\x2b\xb1\x67\x6d\x06\x1f\
|
||||||
|
\xa4\x38\x3a\xc5\x6f\x78\xe6\x77\x01\x91\x17\xf7\x89\x61\x5c\x24\
|
||||||
|
\xfe\x19\xc3\x95\x4a\xc5\x98\x80\xaf\xa6\xfc\x79\x0f\x0c\xe3\xf9\
|
||||||
|
\x6e\x56\x8b\x98\x8e\xc0\x8a\xcb\x46\xd7\x75\x96\x3a\x2a\xaa\x56\
|
||||||
|
\x07\xa0\x83\xd1\x50\x60\x95\x71\xf8\x74\xb2\x2c\xc3\xde\xdc\x84\
|
||||||
|
\xa1\x07\xa1\x09\x00\x51\x30\x4c\x37\xb1\x5a\xad\x92\xaa\xaa\xa4\
|
||||||
|
\x69\x1a\xd5\x6a\x35\x62\x3b\x52\xbd\x5e\xff\x5d\x8b\xc5\x62\x6c\
|
||||||
|
\x5d\xa4\xab\x7d\x7d\xd3\xdc\xcf\xfb\x58\xcc\x02\xa3\xd9\x2a\x58\
|
||||||
|
\x28\x14\x68\x26\x11\xa7\x2b\xbd\xbd\xa6\x66\xb3\x60\x19\x94\x74\
|
||||||
|
\x4e\xbf\x74\xfd\xc6\x98\xb5\x99\xe7\xff\x7e\x67\x40\x67\x89\x12\
|
||||||
|
\x03\x16\x7e\x01\x57\xcf\x68\x6a\x5b\x49\x87\x93\x00\x00\x00\x00\
|
||||||
|
\x49\x45\x4e\x44\xae\x42\x60\x82\
|
||||||
|
\x00\x00\x02\x33\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
|
||||||
|
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
|
||||||
|
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
|
||||||
|
\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
|
||||||
|
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
|
||||||
|
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x01\xb0\x49\x44\
|
||||||
|
\x41\x54\x78\xda\xa5\x93\x3f\x48\xc3\x40\x18\xc5\x5f\xa2\xd8\x74\
|
||||||
|
\xab\xda\xc1\x3a\xd6\x55\xc4\xcd\x41\x10\xff\xd0\xad\x45\xa1\xe2\
|
||||||
|
\x24\xae\x8e\xea\xe0\x20\xc5\x4d\xb0\xe8\xac\xb8\xbb\xa8\xb8\xd9\
|
||||||
|
\xc1\x41\x67\x37\x05\xc7\x42\xc1\x0e\xd6\x52\x41\xcd\x35\x7f\x9a\
|
||||||
|
\xb6\x97\x78\x5f\x22\xe1\x42\x1d\x0a\x7d\xb9\x7c\x97\xc0\xbd\xdf\
|
||||||
|
\x3d\xbe\x5c\x14\xcf\xf3\x30\x88\x86\xa9\xe4\xb2\xd9\xef\x56\xcb\
|
||||||
|
\x49\xec\xec\xed\x43\x96\xa2\x52\x55\xa1\xaa\x0a\x14\x05\x50\x10\
|
||||||
|
\xdc\xa7\x27\x45\x68\x5a\xec\xe7\xae\x54\x1a\xf5\x01\x96\x69\x25\
|
||||||
|
\x26\x52\x13\x58\x58\x5c\x82\x27\x03\x80\xc0\x28\x0a\x41\xc4\xf0\
|
||||||
|
\xe7\xdb\x9b\x2b\x54\x2a\x95\x44\x98\xc0\x75\x5d\x68\x31\x0d\xda\
|
||||||
|
\xc8\x10\x2e\x1f\x5e\xa3\x29\xfc\x42\x23\x48\xb1\x95\x99\x01\xe7\
|
||||||
|
\xdc\xf7\x84\x00\x2e\x5e\xba\xdd\xae\xa0\x03\x9b\x2b\xd3\xb4\x3e\
|
||||||
|
\x4c\x42\x3d\x72\xbd\xbf\x59\x3c\x98\x4e\x87\xd6\xfa\x9e\x48\x02\
|
||||||
|
\xa2\x36\xed\x36\x99\x43\x79\x01\x81\x06\x5c\x02\x04\x90\xde\x04\
|
||||||
|
\x2e\xe7\x3e\xd5\x10\x80\xeb\xfb\x27\xc8\x0a\xbf\x12\xa5\x10\x57\
|
||||||
|
\x3e\x33\x47\x6b\xc9\xd3\x9b\x80\x19\x36\x32\xf3\xb3\xb2\x1b\x9e\
|
||||||
|
\x64\x26\x56\xd3\x74\xfe\x49\xe0\x72\x70\x41\x3d\xdc\xdd\x46\x9f\
|
||||||
|
\x22\x8f\xd4\x44\x1e\x34\xb1\x7f\x05\x9e\x68\x0f\x3a\x1d\x90\x8e\
|
||||||
|
\x8a\xc7\x88\xc7\xe3\x61\x7c\x3a\x03\x24\x8a\xbd\x91\x5f\xf7\xe7\
|
||||||
|
\xa9\x74\x3a\xda\x83\x8e\xd8\xdd\x69\xb7\x41\x2a\x97\xcb\xb8\x38\
|
||||||
|
\x3b\x87\x65\x5b\x38\x28\x14\x20\x2b\x35\x39\x89\xda\x47\x8d\x3e\
|
||||||
|
\x21\x79\x24\x80\xd8\xdd\x71\x1c\x90\x18\x63\x30\x4d\x13\x86\x61\
|
||||||
|
\x40\xd7\x75\xc8\xf2\x84\xd1\x15\xd1\x93\xc9\x24\xde\xaa\xd5\x48\
|
||||||
|
\x13\xbf\x18\xd3\xc7\xe8\x34\x32\x9d\xc1\xb6\x6d\x4a\xd4\x03\x20\
|
||||||
|
\x30\x6d\x66\x5b\x16\xb8\x9c\x40\xe1\x7c\x99\x35\x9b\x8f\xba\xce\
|
||||||
|
\xc6\x1b\x9f\x0d\xe4\xd6\x56\x41\xaa\xd7\xeb\x90\xf5\x5e\xab\x51\
|
||||||
|
\x0e\x3c\xbf\xbc\x40\x1d\x52\x7f\x20\x34\xf0\xef\xfc\x0b\xfb\xd2\
|
||||||
|
\x1e\xf6\x17\x50\x4f\x5c\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
|
||||||
|
\x60\x82\
|
||||||
|
\x00\x00\x02\x63\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
|
||||||
|
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
|
||||||
|
\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\
|
||||||
|
\x00\x00\x09\x70\x48\x59\x73\x00\x00\x6e\xba\x00\x00\x6e\xba\x01\
|
||||||
|
\xd6\xde\xb1\x17\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd9\x0a\x16\
|
||||||
|
\x0d\x00\x3a\x08\xf3\xbd\x44\x00\x00\x01\xe3\x49\x44\x41\x54\x78\
|
||||||
|
\xda\x8d\x92\x3f\x68\x53\x51\x14\xc6\xbf\x73\xef\x7d\x7f\x92\x34\
|
||||||
|
\x8d\x49\x15\x42\xc5\x14\x8b\x83\xe8\xa6\x4b\x90\x0a\x8a\x4b\x07\
|
||||||
|
\x09\x0e\x4e\x0e\x42\x10\x5c\x1c\x1d\x9c\x9d\x9c\x05\xd7\x2e\x82\
|
||||||
|
\x9b\x9b\x19\x3a\x18\x3a\xb4\x81\x88\x8b\x53\x51\x04\x21\x81\x56\
|
||||||
|
\xa9\x22\xea\x4b\x1a\xfb\x5e\xee\xbb\x9e\xfb\x4c\x87\xa6\xde\xe0\
|
||||||
|
\x0f\x3e\x1e\x9c\x77\xbe\x73\xbe\xfb\xee\x23\x4c\x28\x16\x8b\x0b\
|
||||||
|
\x51\x14\xf9\x00\x08\xff\x46\xb3\xf6\x58\x06\x0e\x96\x8c\x03\xad\
|
||||||
|
\xb5\xe9\x74\x3a\xaf\x00\x9c\x9b\x5e\xa0\xae\x3f\xf9\x68\x46\x31\
|
||||||
|
\x10\xb1\x18\xd3\xed\x76\x49\x4a\x09\x36\xa1\x5e\xaf\xc3\xd2\x6a\
|
||||||
|
\xb5\xd0\x68\x34\x6e\x6e\x6e\x6d\xd1\xd5\x95\x95\xfb\x00\x76\x31\
|
||||||
|
\x81\xea\x8f\x3f\xc4\x6b\xf7\xce\x78\xa3\x38\xc5\xe5\xb3\x85\x23\
|
||||||
|
\x91\x78\x39\x88\x08\xfd\x7e\x1f\xb5\x5a\x0d\x96\x17\x6f\x06\x78\
|
||||||
|
\xba\xfe\x19\x4a\x12\x42\x05\x28\x41\xa0\xde\xd7\x03\x0c\x0e\xfe\
|
||||||
|
\x0e\xe0\x04\x98\x4e\xd0\x6e\xb7\x51\x2a\x95\x10\x04\x01\xee\xac\
|
||||||
|
\xde\x40\xd9\x3f\x85\x62\x28\xf1\xe8\x25\x0f\x02\x81\x86\xb1\xc6\
|
||||||
|
\x90\x13\x30\xd6\x74\x2c\x41\xb3\xd9\x3c\x92\x6c\x6f\x10\x61\x94\
|
||||||
|
\x68\x10\x01\x0a\xb0\x4f\xc2\x84\xe9\x04\xce\xda\xa1\x47\x09\x12\
|
||||||
|
\x94\x0f\xf8\x25\x70\x2c\x01\x1c\x35\xdb\x9f\x63\xb1\x17\xb4\xfc\
|
||||||
|
\x60\xc3\xfc\xdc\x4f\x80\x78\x1f\x03\xed\xf1\x26\xe5\xbc\x68\x62\
|
||||||
|
\x69\x3d\xc6\x9c\xe4\x7e\x3f\x8f\x52\xde\x83\x22\x21\xc7\x0f\x6f\
|
||||||
|
\x5d\x54\x5f\x76\x7a\xb8\xbb\x7a\x01\xdf\x87\xda\xf9\x27\x19\x56\
|
||||||
|
\xa5\x20\xf1\x7c\x7d\x1b\xd5\xd3\x4b\x58\x7b\xfd\x7e\xac\x0a\xa1\
|
||||||
|
\x4f\xbf\x46\x09\xde\xf5\x87\xb8\xf6\xed\x37\x76\x7f\x68\x08\xc7\
|
||||||
|
\x80\x94\xb5\x78\x42\x66\xbd\x57\x2a\x09\xac\x57\x85\x81\x4f\x9e\
|
||||||
|
\x12\x3c\x59\x21\xf4\x88\x8b\x12\x44\x8e\x04\x06\xb6\x27\xeb\xb5\
|
||||||
|
\x1e\xf6\x66\x03\xb0\x30\xef\x63\xb1\x1c\x60\x3e\x27\xf8\x7e\x69\
|
||||||
|
\xe6\x37\x20\x32\xb6\x37\xf3\x58\xaf\x0a\x7d\x45\xb5\x93\x39\xcc\
|
||||||
|
\x89\x2a\xde\x6e\xef\x40\x08\x81\x59\xa4\x69\x8a\x4b\xe7\xab\xa8\
|
||||||
|
\x54\x72\xb0\x5e\xba\xfd\xac\x67\x12\x73\x18\x9b\xf0\x7f\x98\xec\
|
||||||
|
\x38\x1e\xe9\xcc\x51\x66\x2d\xcf\x74\xbb\x2f\xe5\xd3\x1f\x03\xf5\
|
||||||
|
\xc1\x56\xb6\x09\x0d\x58\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
|
||||||
|
\x60\x82\
|
||||||
|
\x00\x00\x03\x22\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
|
||||||
|
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
|
||||||
|
\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x06\xec\x00\x00\
|
||||||
|
\x06\xec\x01\x1e\x75\x38\x35\x00\x00\x00\x07\x74\x49\x4d\x45\x07\
|
||||||
|
\xd8\x01\x03\x12\x35\x13\x24\x41\x46\xca\x00\x00\x02\xaf\x49\x44\
|
||||||
|
\x41\x54\x38\xcb\x95\x92\x59\x48\x54\x61\x18\x86\xdf\xff\xec\xce\
|
||||||
|
\x9c\x99\xd1\x99\xb1\x74\x74\x5c\xa6\x2c\x4b\xa4\xdd\x68\xca\x16\
|
||||||
|
\x2c\x83\x0a\x8c\x24\x8d\x16\x23\x91\x08\xea\x22\xc2\xa0\x20\x8a\
|
||||||
|
\x0a\x82\xa0\xe8\x22\x22\x28\x93\x2e\x0a\xb2\x81\x88\x92\xd2\x8b\
|
||||||
|
\xa0\x05\x53\x88\x2e\x24\xb2\xc5\x2c\x4b\x31\x9d\xc5\xd4\x59\xce\
|
||||||
|
\xcc\x59\xfe\xd3\x55\x51\x12\xa1\xdf\xed\xc3\xfb\xf0\xf1\x7d\x2f\
|
||||||
|
\x30\x85\x79\x7c\xfb\xfc\xc1\x47\x4d\xc7\xdf\x6e\xa9\x58\xc1\x4c\
|
||||||
|
\x66\xcc\x54\x04\x7a\x2a\xd6\xe0\x74\xb9\xba\x5b\x9f\x74\xd2\x69\
|
||||||
|
\x0b\x9e\x3d\xbc\x5e\x26\x30\xe6\x42\x03\x7c\xd3\xbf\xf8\x7f\x05\
|
||||||
|
\x17\x8f\xed\x75\x06\x87\xbf\x9f\x83\x69\x7e\x6a\x6e\x69\x7f\x3a\
|
||||||
|
\x2d\x41\xf5\xfa\xa5\x2c\x2f\x8a\x87\x48\x3c\x5c\xf1\xb9\x7f\xb8\
|
||||||
|
\xe7\xc6\x9d\x47\x74\xca\x82\x8b\x47\xb7\xbb\x76\x56\xf9\xbb\xe6\
|
||||||
|
\xe4\x65\x9c\x8e\xc6\x53\x60\x23\x51\xf1\x1e\xc0\xfd\xe2\xf7\x08\
|
||||||
|
\xc9\x7a\xe0\xf7\xaf\x07\x00\x76\x72\xb8\xa4\x04\xa8\x58\xba\xec\
|
||||||
|
\xbe\xc7\x93\x5d\xae\xa8\x3a\x58\x35\x0a\x97\x68\xc9\x11\x83\xb1\
|
||||||
|
\x9c\xd5\xa1\x48\x5b\x35\x30\xb3\x60\xed\xca\xbb\xb3\x16\x2d\xd8\
|
||||||
|
\x53\xde\xd3\x33\xc0\x4d\x16\xec\xab\xaa\xaf\xb5\xdb\xd2\x2a\x95\
|
||||||
|
\x44\x1c\x48\xa5\x40\xa9\x0e\xaa\xe8\xa6\xaf\xbc\x7c\x53\x77\x52\
|
||||||
|
\x69\x2a\x74\xbb\x66\xcf\x98\x5b\x92\x67\x1a\x26\x84\x1c\xcf\x66\
|
||||||
|
\xf2\x67\xf8\xcc\x81\x8d\xb2\x35\x4d\xec\x9e\x91\x5b\xe0\x63\x08\
|
||||||
|
\x80\x78\x04\x0c\xcb\x40\xfa\x18\x1c\xcb\x1d\x50\xa3\x9a\xc4\x43\
|
||||||
|
\xe2\x04\xc0\x92\x86\xbe\xae\x8e\x8e\x1f\x5f\x86\xea\xff\xda\x20\
|
||||||
|
\xd3\x21\x5d\xb3\xd8\x6c\x3e\x99\xd3\x10\x1e\x1d\x47\x22\xa1\x41\
|
||||||
|
\x07\x01\xf3\x2d\x74\x55\x0c\x46\x76\x8b\x43\x51\x28\x02\x8f\x11\
|
||||||
|
\x49\x1f\x0b\xf6\x47\xf6\x1f\x06\x94\xdf\x37\xb8\x79\x72\xdb\x51\
|
||||||
|
\x30\xec\x91\xcc\x0c\x3b\x26\xc6\xa2\xd0\xd4\x24\x5c\x32\x07\x81\
|
||||||
|
\x67\x20\xbf\xfa\x30\xd3\x37\x18\x16\x34\x9e\x10\xdb\x44\x0c\x6e\
|
||||||
|
\x40\x0a\xd9\xac\x85\xcb\xe3\xc9\x36\x16\x00\x9a\x4f\x6c\xdd\x91\
|
||||||
|
\xe9\x94\xaf\x24\x12\x3a\x03\x6a\xc0\x2a\x71\xd0\x35\x15\x76\xbb\
|
||||||
|
\x05\x9a\xaa\x9b\x65\xef\x87\xa8\x91\x6e\x67\x6e\x39\xac\x3d\x23\
|
||||||
|
\xe9\x0e\x7e\x4d\x70\x5c\x2a\x10\x85\xa2\x89\xe2\xe2\x02\xe6\x54\
|
||||||
|
\xfd\xba\xc5\xb2\x55\x6c\xec\xfd\x1a\xe2\xf2\xb2\x1d\xa6\x95\x63\
|
||||||
|
\xa1\xa8\x29\x64\xbb\x6d\x00\x28\x32\x24\x9e\xc6\xf3\x3c\x4c\xbb\
|
||||||
|
\xd3\xfe\xae\xac\xb2\xf4\xf8\xa8\x84\x86\xb6\x7c\x6f\x38\xe9\x72\
|
||||||
|
\x23\x34\x38\xf8\x86\x9b\x5f\xe4\x9d\x00\x54\x5a\x9a\xef\x31\x19\
|
||||||
|
\x83\x42\x92\x58\x83\x81\xc8\x5a\x25\x16\x34\x09\xf0\x92\xf0\xb6\
|
||||||
|
\x93\xd3\xbb\xbc\x7e\x5f\x93\xc5\x29\xf7\x6e\xd8\xb5\x2a\xda\x77\
|
||||||
|
\xf9\x45\x6d\x6b\x38\xbc\xb8\x71\x7c\xbc\x85\x04\x2e\xd4\x59\xa8\
|
||||||
|
\x61\xf8\x89\x89\x6a\x01\xc4\xc7\x89\xc4\x2b\xf0\x4c\x2e\x55\x35\
|
||||||
|
\x19\x94\x4d\xa9\x2c\xdb\x6c\x18\xe4\xac\xa6\x93\x70\xe0\x75\x54\
|
||||||
|
\x0f\x04\x02\x7f\xbd\x9d\x00\x40\xeb\xa5\x3a\xd6\xa4\x44\x34\x28\
|
||||||
|
\xb1\x9b\x84\x7a\x35\x83\xce\x8b\xc7\xe2\xb3\xb2\x1c\xb2\xd2\x1b\
|
||||||
|
\x52\x9e\x67\x2d\x21\x2f\x6b\x6a\x02\xff\xac\xfc\x4f\x89\x4f\x0d\
|
||||||
|
\x65\xb8\x03\x8d\x9c\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\
|
||||||
|
\x82\
|
||||||
|
\x00\x00\x01\xf3\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x04\x00\x00\x00\xb5\xfa\x37\xea\
|
||||||
|
\x00\x00\x00\x02\x73\x42\x49\x54\x08\x08\x55\xec\x46\x04\x00\x00\
|
||||||
|
\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\x01\x3a\
|
||||||
|
\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\x74\x77\
|
||||||
|
\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\
|
||||||
|
\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x01\x72\x49\x44\x41\x54\
|
||||||
|
\x28\xcf\x45\x91\x4f\x2b\x04\x71\x1c\xc6\xbf\xf3\x32\xe4\x6c\xde\
|
||||||
|
\x80\xa2\x44\x39\xbb\xec\x1f\xb3\x23\x6d\x9b\x25\x8b\x10\xfd\x76\
|
||||||
|
\x36\xec\xa2\x31\x89\x13\x0e\x2e\xca\xfb\x98\x4d\x7b\xf0\x12\xb4\
|
||||||
|
\x85\x83\x36\x17\x97\xb1\xa2\xe9\x47\xfd\x0e\x63\xb6\x8f\x83\xb5\
|
||||||
|
\x9e\xe7\xf6\xf4\xf4\x1c\x9e\x8f\x20\xbf\x3e\xb1\x8f\x83\x20\xf4\
|
||||||
|
\x23\x3f\x0a\xc2\xe3\xe0\xc4\xfe\xcb\x05\x41\x7c\xeb\x50\xd5\x4d\
|
||||||
|
\x95\x1a\x3e\x3e\x35\xaa\xd4\xcd\xa1\xf2\xad\x7e\xa1\x61\xd5\x9b\
|
||||||
|
\xdb\xec\xd2\xa2\xcd\x13\x1d\x1e\x68\xb1\xc3\x36\xf5\x66\xc3\x42\
|
||||||
|
\x04\xf1\xd4\x06\x17\xdc\xf3\x4a\xcc\x27\x5f\x68\xde\x78\xe6\x9c\
|
||||||
|
\x0d\x3c\x85\x88\xb2\x37\x8d\xc7\x23\x1f\x18\xbe\xe9\xd1\x23\x25\
|
||||||
|
\x41\xf3\x42\x8d\x4d\xa3\x6c\x59\x0f\x16\xb9\xe5\x1d\xc3\x15\x67\
|
||||||
|
\x1c\xa0\xd8\x42\x91\xa2\x69\xb3\xc8\xfa\x91\x54\xc2\x15\xee\xd0\
|
||||||
|
\xa4\x5c\xd2\xa0\x82\x4b\x8e\x59\x20\xa1\xcb\x1a\x95\x50\xca\x91\
|
||||||
|
\x47\x9b\x98\x94\x3d\x96\xc9\x31\xc5\x38\xd3\x40\x4a\xcc\x3e\xe5\
|
||||||
|
\x48\x4a\x51\x95\x47\x34\x3d\xb2\x8c\x32\x84\x30\xc4\x28\xd0\x43\
|
||||||
|
\x73\x40\x29\x92\x62\x58\xee\x2f\xb8\x4c\x30\xc2\x30\x23\x4c\xf4\
|
||||||
|
\x17\x96\x29\x86\x52\x0c\x1c\x6e\xe8\x92\xb0\xc4\x0c\x93\x8c\x31\
|
||||||
|
\xc9\x0c\x90\xd0\xc1\xa1\x78\x24\xf3\x76\xc1\xac\xf2\x8c\x26\xe5\
|
||||||
|
\x5f\x29\x1a\x8f\x82\x99\xb7\x05\x71\x55\x96\x53\x5e\xd0\x24\xa4\
|
||||||
|
\x83\x1f\xae\xc9\xe2\x2a\x44\x90\x39\xcb\x6d\x66\x58\xa3\x4d\x97\
|
||||||
|
\x18\x4d\x4c\x87\x2a\x19\xdc\xe6\x9c\xd5\x87\xe5\x5a\x8e\xca\x9b\
|
||||||
|
\x0c\x25\x76\xd8\x63\x81\x0c\x79\xe3\x28\xd7\x1a\xd0\x44\x90\x82\
|
||||||
|
\xed\x04\xf9\x30\x17\xe5\xa2\x7c\xe8\x04\x85\x01\xee\x1f\x8d\x42\
|
||||||
|
\x66\xb3\xf5\x8b\xfe\x99\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
|
||||||
|
\x60\x82\
|
||||||
|
\x00\x00\x03\xa3\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
|
||||||
|
\x00\x00\x00\x04\x73\x42\x49\x54\x08\x08\x08\x08\x7c\x08\x64\x88\
|
||||||
|
\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x01\xbb\x00\x00\x01\xbb\
|
||||||
|
\x01\x3a\xec\xe3\xe2\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6f\x66\
|
||||||
|
\x74\x77\x61\x72\x65\x00\x77\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\
|
||||||
|
\x70\x65\x2e\x6f\x72\x67\x9b\xee\x3c\x1a\x00\x00\x03\x20\x49\x44\
|
||||||
|
\x41\x54\x78\xda\x6d\x93\xcd\x6b\x5c\x55\x18\xc6\x9f\xf7\xdc\x73\
|
||||||
|
\xee\xd7\x24\x33\x49\x27\xa9\x49\x27\xa1\x4d\x86\xd6\x18\x34\x4e\
|
||||||
|
\x28\xad\x8d\x42\x68\xfd\xa0\xd0\xa2\xfe\x01\x45\xb0\xb8\x75\xa3\
|
||||||
|
\xe0\xd2\x55\x45\x37\x0a\xba\x13\x37\x82\x3b\x17\x12\x14\x14\x8d\
|
||||||
|
\x45\x51\x6a\x21\x15\xa3\x26\x25\xc1\x8f\x36\x89\x69\xd2\x74\xec\
|
||||||
|
\x24\x73\x33\x9d\xfb\x71\xce\x3d\xf7\x78\x47\x0c\x66\xd1\x1f\x3c\
|
||||||
|
\xbb\xf3\xbc\xe7\xe5\x79\xdf\x97\x8c\x31\xd8\x0f\x3d\x47\x55\x30\
|
||||||
|
\x5c\xb0\xba\xac\x27\x47\x2a\x23\x93\xe5\xae\x32\x5b\xd9\x5c\x59\
|
||||||
|
\xaa\x6f\xd5\x2f\x43\xe3\x43\xf3\x99\xf9\xf3\xbf\x77\x43\x00\x78\
|
||||||
|
\xa7\xc0\x9e\x91\x81\xf0\x4a\x79\xb4\xfc\xc6\xf9\x13\xe7\xdd\x4a\
|
||||||
|
\x7f\x05\x83\x7d\x83\xb0\x98\x85\x20\x08\x70\xe3\xf6\x0d\xcc\x5c\
|
||||||
|
\x9d\x89\xb7\xd7\xb6\x2f\x21\xc3\x8f\xa5\x4a\xf1\x93\x24\x48\xe2\
|
||||||
|
\x4e\x81\x7f\xcd\xcc\xa1\x6f\xa7\x4e\x9d\x9a\x3a\x33\xf9\x94\x60\
|
||||||
|
\x36\xc3\xfd\xd0\x52\xe3\xea\xc2\x15\xf5\xeb\xfa\x2f\x74\xf1\xe9\
|
||||||
|
\x97\xf8\x7b\x1f\xbf\x0b\x8e\x1c\x62\x78\xb5\x36\xf6\xf0\xd4\x89\
|
||||||
|
\xb1\xc7\x44\x10\x06\xa0\x90\xd0\x68\x34\xb0\x71\x7b\x03\x64\x08\
|
||||||
|
\xd5\xe1\x2a\xbc\x1e\x0f\x1d\x26\x8e\xd6\xc4\x44\xb5\x86\xcc\x18\
|
||||||
|
\x30\x10\x78\xfe\xfb\x83\xfd\x03\x3d\x97\x8e\x1e\x19\x17\x8d\x66\
|
||||||
|
\x03\x3a\xd5\x98\xff\x79\x1e\x7f\xac\xfc\x0e\x47\x0b\x78\xb6\x87\
|
||||||
|
\x2b\x73\xdf\xa3\xb7\x52\xc6\xc9\xe3\x27\xd1\x5b\xec\x05\x0c\x60\
|
||||||
|
\x19\x0b\x8c\x18\x38\x11\x5e\xa8\x94\x86\x9c\x76\xdc\x46\x47\x8b\
|
||||||
|
\xd7\x17\xf1\x77\x7d\xd3\x14\x5c\x21\x43\xa9\x2e\x27\x99\xd2\x3e\
|
||||||
|
\x13\x67\x9b\x71\xc3\x9e\x5d\x9d\xa5\xe9\xf1\x69\xb8\xc6\x05\x49\
|
||||||
|
\x82\x45\x04\xee\xf8\xe2\x8c\xd1\xa0\xed\xe6\x36\x76\x83\x5d\x6c\
|
||||||
|
\xdc\x5a\x87\xef\x8b\x68\x37\x4a\x1e\xed\x24\x9e\x77\x38\x09\x0b\
|
||||||
|
\xcf\x98\x47\x88\x1e\x38\x7c\x10\x2d\xde\x42\x74\x2f\x42\xb0\x13\
|
||||||
|
\x80\x32\x18\x2e\x1c\x56\x8b\xb5\x42\x1a\x04\xa8\xdf\xad\xc3\xd2\
|
||||||
|
\x0c\x6d\xa9\xbe\xde\x1b\x57\x97\xe7\xf6\x89\x22\xf3\x44\xaf\x87\
|
||||||
|
\xf4\x4e\x82\xb5\xe0\x26\x5a\x77\x5a\x30\xed\x0c\x69\xac\xbf\x24\
|
||||||
|
\xff\x82\x90\x59\xdb\x12\xe0\x80\x72\x14\x84\x22\x48\xa9\x67\xf5\
|
||||||
|
\x4c\x76\x76\xdf\x6e\xb8\x00\x4a\x02\x16\x81\x8c\xce\x72\x69\x63\
|
||||||
|
\x94\xf9\xd4\xb4\x98\x4c\xf4\x35\x84\x29\x62\x11\x43\x97\x35\xcc\
|
||||||
|
\x28\xe0\xb8\xd6\x74\x27\x5c\xfc\xcf\x21\x46\xf4\x11\x4d\x50\x9f\
|
||||||
|
\xae\x65\x5c\x0c\x5b\xaa\xbb\xe8\xc4\xc8\xe1\xa9\xcc\xbe\x70\x6d\
|
||||||
|
\xf1\x38\x0e\xa4\x84\x3e\x20\xeb\xce\x50\x2e\x0a\x87\x96\xd8\x4f\
|
||||||
|
\xec\x79\xfa\x1c\x44\xe4\xd8\xfc\x5c\x69\xd8\x9d\x4b\x87\xb2\xd3\
|
||||||
|
\x89\xa2\xd5\xb8\x94\x6e\x5a\xcb\x6c\x8b\x2e\xd2\x26\xe1\x59\x3c\
|
||||||
|
\xe4\xb9\x62\x1e\x23\x70\xe5\x40\x0a\x5f\xd8\x28\x38\x36\xca\xdc\
|
||||||
|
\x87\x6a\x68\x63\x81\xe0\x0d\xf0\x34\xa4\xf4\xaf\x58\xa5\x8b\xa1\
|
||||||
|
\x94\xcb\xaa\x95\xad\x45\xbf\xa9\xaf\xa2\x0f\xd4\x2a\xcb\xc3\x5a\
|
||||||
|
\x8e\x62\xf5\xba\xbf\x23\x94\xcb\x3b\x73\xe7\x79\x01\x01\xee\x13\
|
||||||
|
\x0a\xc7\x6c\xb2\x26\x18\xc9\xfe\x4c\x14\x7c\xbb\xda\xe5\xd8\xe3\
|
||||||
|
\x25\xdb\x1f\x4b\x16\xf4\x6b\xf1\x56\x7a\x04\x39\x7b\x3b\xfb\x4e\
|
||||||
|
\x63\x2b\xfc\xa6\xe7\xa6\x9b\xf4\x30\x0f\xae\x10\xa0\x02\x61\xf7\
|
||||||
|
\x60\x8c\x9d\x43\x11\x9a\x83\x31\x5a\xfd\x09\x8a\xdc\xa9\x46\xd7\
|
||||||
|
\xe5\xe9\xb0\x29\x97\x00\x7c\x87\x9c\xfd\xc7\x44\x00\x5e\xee\x3e\
|
||||||
|
\xe0\xbe\xe5\x8d\x72\xaf\x32\x56\x64\xf1\xb1\x14\xed\xb2\x84\x75\
|
||||||
|
\x8b\xe1\xee\x5c\xdb\xe8\x6b\x59\x18\xde\x53\x6f\x02\x78\x3b\xef\
|
||||||
|
\x5c\x22\xe7\x7e\xe7\x7c\x18\xc0\x8b\xb9\x9e\xb0\x18\x1d\x37\x06\
|
||||||
|
\x94\x19\xb3\x00\xe0\x87\x5c\xef\xe7\xc6\x75\xec\xe3\x1f\x51\x72\
|
||||||
|
\x6b\x1e\x49\x70\xdf\x2c\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
|
||||||
|
\x60\x82\
|
||||||
|
\x00\x00\x01\xe5\
|
||||||
|
\x89\
|
||||||
|
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
|
||||||
|
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
|
||||||
|
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
|
||||||
|
\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\
|
||||||
|
\x00\x00\x09\x70\x48\x59\x73\x00\x00\x06\xec\x00\x00\x06\xec\x01\
|
||||||
|
\x1e\x75\x38\x35\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xd8\x03\x14\
|
||||||
|
\x12\x23\x3b\xba\x62\x67\xa1\x00\x00\x01\x65\x49\x44\x41\x54\x78\
|
||||||
|
\xda\x95\x90\xcf\x4a\xc3\x40\x10\xc6\x67\x37\xa6\xa5\x81\x5e\x8a\
|
||||||
|
\xa7\x3c\x86\x78\xf1\x01\xd4\x1e\xac\x6f\xe0\xc5\x73\xbd\xd8\x53\
|
||||||
|
\x2d\xf8\x08\xbe\x4b\xcf\x3e\x80\xa0\x10\x3c\xfb\x00\x56\xda\x54\
|
||||||
|
\x4a\x82\x25\x7f\x77\x3a\xb3\x6c\xe8\x9a\x90\xa2\x1f\x7c\x7c\xbb\
|
||||||
|
\xec\xcc\x6f\x77\x56\x00\xc0\x80\x7c\x46\x16\x70\x58\x48\x7e\x21\
|
||||||
|
\x7f\x43\x4d\x57\xf8\x37\x31\x60\x04\x35\x1d\x55\x37\xaf\xc2\x10\
|
||||||
|
\xa4\x94\x20\x85\x00\x41\x29\x38\xd9\xa6\xb0\xdf\xef\x73\x88\x26\
|
||||||
|
\xc0\xc8\x71\x1c\x0d\x88\xa3\x08\x82\x20\x00\x2d\x0b\xd0\xed\x76\
|
||||||
|
\x39\x4e\xc8\xa9\x35\xd2\x2b\x2f\x46\x48\xda\x6c\x36\x18\xc5\x31\
|
||||||
|
\xce\xe7\x73\xfc\xc7\x48\xc3\xc6\x0b\xf8\x56\x56\xb8\x5e\x83\xc3\
|
||||||
|
\x23\x19\x0b\xb2\x3d\x92\xe7\x79\x1c\xb2\x02\xe8\x22\x0d\x31\x00\
|
||||||
|
\xdd\x4c\x7b\x9d\x55\x33\x67\xdb\x1f\x48\xab\xd0\xec\xf7\x10\xeb\
|
||||||
|
\x53\xa1\x15\x60\x15\xd9\x40\xa7\x06\xa6\x6c\x00\xea\x07\x36\x60\
|
||||||
|
\x0f\x3e\x0c\x68\x42\x44\xad\xb9\x28\x0a\x08\xc3\x10\x3a\x1d\x17\
|
||||||
|
\x7a\x3d\x0f\x14\x08\xa4\xb2\x82\x01\x8a\x0e\xd1\x75\x5d\x51\xdd\
|
||||||
|
\xac\xb3\x76\x2b\x37\xfb\xbe\x0f\xac\xed\xf6\x07\x1e\x67\xb3\x67\
|
||||||
|
\x5a\x06\xbc\x3f\x26\xdf\x90\x6f\x8d\x9f\x90\x94\x24\x09\x66\x59\
|
||||||
|
\x86\x0c\x2f\xcb\x12\x17\x5f\x0b\x54\x4a\x61\x1c\xc7\x38\xbe\x1b\
|
||||||
|
\xbf\x51\xdd\x29\xb4\x68\xc8\x80\x34\x4d\x31\xcf\x73\x06\xe8\xc6\
|
||||||
|
\xe5\x6a\xa9\x9b\x27\x93\xfb\x77\xaa\xb9\x26\xcb\x36\xc0\x05\x35\
|
||||||
|
\x2a\xb4\x94\x15\x25\x7e\x2e\x57\x38\x7d\x98\xf2\x93\x2f\x7f\x7d\
|
||||||
|
\x3e\x34\x35\x20\x9f\x9b\x22\x5b\x68\x66\xfe\x20\x2b\x30\xda\x01\
|
||||||
|
\x68\x0b\xe8\x88\x71\x7b\x2b\x7d\x00\x00\x00\x00\x49\x45\x4e\x44\
|
||||||
|
\xae\x42\x60\x82\
|
||||||
"
|
"
|
||||||
|
|
||||||
qt_resource_name = "\
|
qt_resource_name = "\
|
||||||
|
@ -54,16 +530,82 @@ qt_resource_name = "\
|
||||||
\x07\xac\xfa\xc2\
|
\x07\xac\xfa\xc2\
|
||||||
\x00\x74\
|
\x00\x74\
|
||||||
\x00\x65\x00\x78\x00\x74\x00\x65\x00\x72\
|
\x00\x65\x00\x78\x00\x74\x00\x65\x00\x72\
|
||||||
|
\x00\x06\
|
||||||
|
\x07\x03\x7d\xc3\
|
||||||
|
\x00\x69\
|
||||||
|
\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x73\
|
||||||
\x00\x08\
|
\x00\x08\
|
||||||
\x0a\x61\x5a\xa7\
|
\x0a\x61\x5a\xa7\
|
||||||
\x00\x69\
|
\x00\x69\
|
||||||
\x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
\x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x15\
|
||||||
|
\x0f\x21\xb3\x87\
|
||||||
|
\x00\x67\
|
||||||
|
\x00\x6f\x00\x2d\x00\x6e\x00\x65\x00\x78\x00\x74\x00\x2d\x00\x76\x00\x69\x00\x65\x00\x77\x00\x2d\x00\x70\x00\x61\x00\x67\x00\x65\
|
||||||
|
\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x19\
|
||||||
|
\x0d\x16\x46\x27\
|
||||||
|
\x00\x67\
|
||||||
|
\x00\x6f\x00\x2d\x00\x70\x00\x72\x00\x65\x00\x76\x00\x69\x00\x6f\x00\x75\x00\x73\x00\x2d\x00\x76\x00\x69\x00\x65\x00\x77\x00\x2d\
|
||||||
|
\x00\x70\x00\x61\x00\x67\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x10\
|
||||||
|
\x0c\xbc\x2e\x67\
|
||||||
|
\x00\x64\
|
||||||
|
\x00\x6f\x00\x63\x00\x75\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x2d\x00\x6e\x00\x65\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x10\
|
||||||
|
\x08\x12\xae\xa7\
|
||||||
|
\x00\x6d\
|
||||||
|
\x00\x65\x00\x64\x00\x69\x00\x61\x00\x2d\x00\x72\x00\x65\x00\x63\x00\x6f\x00\x72\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x18\
|
||||||
|
\x00\x8c\x38\x27\
|
||||||
|
\x00\x64\
|
||||||
|
\x00\x6f\x00\x63\x00\x75\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x2d\x00\x6f\x00\x70\x00\x65\x00\x6e\x00\x2d\x00\x72\x00\x65\x00\x63\
|
||||||
|
\x00\x65\x00\x6e\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x11\
|
||||||
|
\x0f\xe3\xd5\x67\
|
||||||
|
\x00\x64\
|
||||||
|
\x00\x6f\x00\x63\x00\x75\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x2d\x00\x73\x00\x61\x00\x76\x00\x65\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\
|
||||||
|
\x00\x16\
|
||||||
|
\x04\x98\x82\x67\
|
||||||
|
\x00\x64\
|
||||||
|
\x00\x6f\x00\x63\x00\x75\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x2d\x00\x6f\x00\x70\x00\x65\x00\x6e\x00\x2d\x00\x64\x00\x61\x00\x74\
|
||||||
|
\x00\x61\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x0e\
|
||||||
|
\x0d\x8b\x39\xe7\
|
||||||
|
\x00\x65\
|
||||||
|
\x00\x64\x00\x69\x00\x74\x00\x2d\x00\x63\x00\x6c\x00\x65\x00\x61\x00\x72\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x17\
|
||||||
|
\x09\x10\x6a\x47\
|
||||||
|
\x00\x6d\
|
||||||
|
\x00\x65\x00\x64\x00\x69\x00\x61\x00\x2d\x00\x70\x00\x6c\x00\x61\x00\x79\x00\x62\x00\x61\x00\x63\x00\x6b\x00\x2d\x00\x73\x00\x74\
|
||||||
|
\x00\x6f\x00\x70\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x10\
|
||||||
|
\x08\x15\x13\x67\
|
||||||
|
\x00\x76\
|
||||||
|
\x00\x69\x00\x65\x00\x77\x00\x2d\x00\x72\x00\x65\x00\x66\x00\x72\x00\x65\x00\x73\x00\x68\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
|
\x00\x0d\
|
||||||
|
\x01\x1c\xb1\xa7\
|
||||||
|
\x00\x65\
|
||||||
|
\x00\x64\x00\x69\x00\x74\x00\x2d\x00\x63\x00\x6f\x00\x70\x00\x79\x00\x2e\x00\x70\x00\x6e\x00\x67\
|
||||||
"
|
"
|
||||||
|
|
||||||
qt_resource_struct = "\
|
qt_resource_struct = "\
|
||||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
|
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
|
||||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
|
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\
|
||||||
\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
\x00\x00\x00\x12\x00\x02\x00\x00\x00\x0b\x00\x00\x00\x04\
|
||||||
|
\x00\x00\x00\x24\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||||
|
\x00\x00\x00\xee\x00\x00\x00\x00\x00\x01\x00\x00\x0c\x4b\
|
||||||
|
\x00\x00\x01\xfa\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x6a\
|
||||||
|
\x00\x00\x01\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x11\x3f\
|
||||||
|
\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x01\x00\x00\x09\x68\
|
||||||
|
\x00\x00\x01\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x18\xc3\
|
||||||
|
\x00\x00\x01\xa0\x00\x00\x00\x00\x00\x01\x00\x00\x16\xcc\
|
||||||
|
\x00\x00\x00\xa2\x00\x00\x00\x00\x00\x01\x00\x00\x07\x21\
|
||||||
|
\x00\x00\x00\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x04\xb3\
|
||||||
|
\x00\x00\x01\x7e\x00\x00\x00\x00\x00\x01\x00\x00\x13\xa6\
|
||||||
|
\x00\x00\x00\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x02\x30\
|
||||||
|
\x00\x00\x01\x24\x00\x00\x00\x00\x00\x01\x00\x00\x0f\x08\
|
||||||
"
|
"
|
||||||
|
|
||||||
def qInitResources():
|
def qInitResources():
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'texter3.ui'
|
# Form implementation generated from reading ui file 'texter.ui'
|
||||||
#
|
#
|
||||||
# Created: Mon Apr 21 22:38:51 2014
|
# Created: Sat May 10 18:57:19 2014
|
||||||
# by: PyQt4 UI code generator 4.10.3
|
# by: PyQt4 UI code generator 4.10.3
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
@ -26,7 +26,7 @@ except AttributeError:
|
||||||
class Ui_MainWindow(object):
|
class Ui_MainWindow(object):
|
||||||
def setupUi(self, MainWindow):
|
def setupUi(self, MainWindow):
|
||||||
MainWindow.setObjectName(_fromUtf8("MainWindow"))
|
MainWindow.setObjectName(_fromUtf8("MainWindow"))
|
||||||
MainWindow.resize(1475, 651)
|
MainWindow.resize(1475, 592)
|
||||||
palette = QtGui.QPalette()
|
palette = QtGui.QPalette()
|
||||||
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
|
||||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
|
@ -47,6 +47,11 @@ class Ui_MainWindow(object):
|
||||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
|
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
|
||||||
MainWindow.setPalette(palette)
|
MainWindow.setPalette(palette)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setFamily(_fromUtf8("Helvetica"))
|
||||||
|
font.setPointSize(8)
|
||||||
|
font.setBold(True)
|
||||||
|
MainWindow.setFont(font)
|
||||||
icon = QtGui.QIcon()
|
icon = QtGui.QIcon()
|
||||||
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/texter/icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/texter/icon.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
MainWindow.setWindowIcon(icon)
|
MainWindow.setWindowIcon(icon)
|
||||||
|
@ -57,8 +62,8 @@ class Ui_MainWindow(object):
|
||||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
self.horizontalLayout = QtGui.QHBoxLayout()
|
||||||
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
|
||||||
self.live_text = KRichTextWidget(self.centralwidget)
|
self.live_text = KRichTextWidget(self.centralwidget)
|
||||||
self.live_text.setMinimumSize(QtCore.QSize(775, 582))
|
self.live_text.setMinimumSize(QtCore.QSize(778, 586))
|
||||||
self.live_text.setMaximumSize(QtCore.QSize(775, 582))
|
self.live_text.setMaximumSize(QtCore.QSize(778, 586))
|
||||||
palette = QtGui.QPalette()
|
palette = QtGui.QPalette()
|
||||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
|
@ -102,7 +107,7 @@ class Ui_MainWindow(object):
|
||||||
self.live_text.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
self.live_text.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
self.live_text.setAcceptRichText(True)
|
self.live_text.setAcceptRichText(True)
|
||||||
self.live_text.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByKeyboard|QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextBrowserInteraction|QtCore.Qt.TextEditable|QtCore.Qt.TextEditorInteraction|QtCore.Qt.TextSelectableByKeyboard|QtCore.Qt.TextSelectableByMouse)
|
self.live_text.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByKeyboard|QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextBrowserInteraction|QtCore.Qt.TextEditable|QtCore.Qt.TextEditorInteraction|QtCore.Qt.TextSelectableByKeyboard|QtCore.Qt.TextSelectableByMouse)
|
||||||
self.live_text.setRichTextSupport(KRichTextWidget.RichTextSupportValues(KRichTextWidget.SupportAlignment|KRichTextWidget.SupportChangeListStyle|KRichTextWidget.SupportFontFamily|KRichTextWidget.SupportFontSize|KRichTextWidget.SupportTextForegroundColor))
|
self.live_text.setRichTextSupport(KRichTextWidget.RichTextSupportValues(KRichTextWidget.SupportAlignment|KRichTextWidget.SupportFontFamily|KRichTextWidget.SupportFontSize|KRichTextWidget.SupportTextForegroundColor))
|
||||||
self.live_text.setObjectName(_fromUtf8("live_text"))
|
self.live_text.setObjectName(_fromUtf8("live_text"))
|
||||||
self.horizontalLayout.addWidget(self.live_text)
|
self.horizontalLayout.addWidget(self.live_text)
|
||||||
self.preview_text = KRichTextWidget(self.centralwidget)
|
self.preview_text = KRichTextWidget(self.centralwidget)
|
||||||
|
@ -111,8 +116,8 @@ class Ui_MainWindow(object):
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.preview_text.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.preview_text.sizePolicy().hasHeightForWidth())
|
||||||
self.preview_text.setSizePolicy(sizePolicy)
|
self.preview_text.setSizePolicy(sizePolicy)
|
||||||
self.preview_text.setMinimumSize(QtCore.QSize(300, 582))
|
self.preview_text.setMinimumSize(QtCore.QSize(300, 586))
|
||||||
self.preview_text.setMaximumSize(QtCore.QSize(769, 582))
|
self.preview_text.setMaximumSize(QtCore.QSize(778, 586))
|
||||||
palette = QtGui.QPalette()
|
palette = QtGui.QPalette()
|
||||||
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
|
||||||
brush.setStyle(QtCore.Qt.SolidPattern)
|
brush.setStyle(QtCore.Qt.SolidPattern)
|
||||||
|
@ -140,11 +145,7 @@ class Ui_MainWindow(object):
|
||||||
self.preview_text.setRichTextSupport(KRichTextWidget.RichTextSupportValues(KRichTextWidget.SupportAlignment|KRichTextWidget.SupportChangeListStyle|KRichTextWidget.SupportFontFamily|KRichTextWidget.SupportFontSize|KRichTextWidget.SupportTextForegroundColor))
|
self.preview_text.setRichTextSupport(KRichTextWidget.RichTextSupportValues(KRichTextWidget.SupportAlignment|KRichTextWidget.SupportChangeListStyle|KRichTextWidget.SupportFontFamily|KRichTextWidget.SupportFontSize|KRichTextWidget.SupportTextForegroundColor))
|
||||||
self.preview_text.setObjectName(_fromUtf8("preview_text"))
|
self.preview_text.setObjectName(_fromUtf8("preview_text"))
|
||||||
self.horizontalLayout.addWidget(self.preview_text)
|
self.horizontalLayout.addWidget(self.preview_text)
|
||||||
spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Minimum)
|
|
||||||
self.horizontalLayout.addItem(spacerItem)
|
|
||||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||||
spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
|
||||||
self.verticalLayout.addItem(spacerItem1)
|
|
||||||
MainWindow.setCentralWidget(self.centralwidget)
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
|
|
||||||
self.retranslateUi(MainWindow)
|
self.retranslateUi(MainWindow)
|
||||||
|
|