changed from ffmpeg grabbing to internal grabbing and added a async http server
This commit is contained in:
parent
28cc9798e7
commit
d7f3a7daea
|
@ -1,38 +1,49 @@
|
|||
#!/usr/bin/python
|
||||
# -*- 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 os.path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from math import pow
|
||||
|
||||
from operator import itemgetter
|
||||
|
||||
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, KComboBox, KPushButton, KRichTextWidget, KMainWindow, KToolBar, KApplication, KAction, KToolBarSpacerAction, KSelectAction, KToggleAction, KShortcut
|
||||
from PyKDE4.kdeui import (KDialog, KActionCollection, KRichTextWidget,
|
||||
KRichTextWidget, KMainWindow, KToolBar, KAction, KToolBarSpacerAction,
|
||||
KSelectAction, KToggleAction, KShortcut)
|
||||
|
||||
from texter_ui import Ui_MainWindow, _fromUtf8
|
||||
from text_sorter_ui import Ui_TextSorterDialog
|
||||
from text_model import TextModel
|
||||
from PyQt4.QtNetwork import QTcpServer, QTcpSocket
|
||||
|
||||
appName = "texter"
|
||||
catalog = "448texter"
|
||||
programName = ki18n("4.48 Psychose Texter")
|
||||
version = "0.1"
|
||||
from chaosc.argparser_groups import ArgParser
|
||||
from chaosc.lib import resolve_host
|
||||
|
||||
aboutData = KAboutData(appName, catalog, programName, version)
|
||||
from texter.texter_ui import Ui_MainWindow, _fromUtf8
|
||||
from texter.text_sorter_ui import Ui_TextSorterDialog
|
||||
from texter.text_model import TextModel
|
||||
|
||||
KCmdLineArgs.init (sys.argv, aboutData)
|
||||
|
||||
app = KApplication()
|
||||
|
||||
for path in QtGui.QIcon.themeSearchPaths():
|
||||
print "%s/%s" % (path, QtGui.QIcon.themeName())
|
||||
app = QtGui.QApplication([])
|
||||
|
||||
|
||||
# NOTE: if the QIcon.fromTheme method does not find any icons, you can use
|
||||
|
@ -40,21 +51,155 @@ for path in QtGui.QIcon.themeSearchPaths():
|
|||
# in your local icon directory:
|
||||
# ln -s /your/icon/theme/directory $HOME/.icons/hicolor
|
||||
|
||||
def get_preview_text(text):
|
||||
return re.sub(" +", " ", text.replace("\n", " ")).strip()[:20]
|
||||
|
||||
class MjpegStreamingServer(QTcpServer):
|
||||
|
||||
def __init__(self, server_address, parent=None):
|
||||
super(MjpegStreamingServer, self).__init__(parent)
|
||||
self.server_address = server_address
|
||||
self.newConnection.connect(self.start_streaming)
|
||||
self.widget = parent
|
||||
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.regex = re.compile("^GET /(\w+?)\.(\w+?) HTTP/(\d+\.\d+)$")
|
||||
self.html_map = dict()
|
||||
self.coords = parent.live_text_rect()
|
||||
|
||||
def handle_request(self):
|
||||
sock = self.sender()
|
||||
sock_id = id(sock)
|
||||
print "handle_request", sock
|
||||
if sock.state() in (QTcpSocket.UnconnectedState, QTcpSocket.ClosingState):
|
||||
print "connection closed"
|
||||
self.sockets.remove(sock)
|
||||
sock.deleteLater()
|
||||
return
|
||||
|
||||
client_data = str(sock.readAll())
|
||||
print "request", repr(client_data)
|
||||
line = client_data.split("\r\n")[0]
|
||||
print "first line", repr(line)
|
||||
try:
|
||||
resource, ext, http_version = self.regex.match(line).groups()
|
||||
print "resource, ext, http_version", resource, ext, http_version
|
||||
except AttributeError:
|
||||
print "regex not matched"
|
||||
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||
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))
|
||||
if 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))
|
||||
#sock.close()
|
||||
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:
|
||||
print "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:
|
||||
print "not found/handled"
|
||||
sock.write("HTTP/1.1 404 Not Found\r\n")
|
||||
self.sockets.remove(sock)
|
||||
sock.close()
|
||||
|
||||
def remove_stream_client(self):
|
||||
sock = self.sender()
|
||||
sock_id = id(sock)
|
||||
print "remove_stream_client", sock, sock_id
|
||||
if sock.state() == QTcpSocket.UnconnectedState:
|
||||
self.sockets.remove(sock)
|
||||
print "removed sock", sock
|
||||
sock.close()
|
||||
try:
|
||||
self.stream_clients.remove(sock)
|
||||
except ValueError, error:
|
||||
print "sock was not in stream_clients", error
|
||||
|
||||
try:
|
||||
stream_client = self.html_map.pop(sock_id)
|
||||
except KeyError, error:
|
||||
print "socket has no child socket"
|
||||
else:
|
||||
print "html socket has linked stream socket to remove", stream_client, id(stream_client)
|
||||
stream_client.close()
|
||||
try:
|
||||
self.stream_clients.remove(stream_client)
|
||||
except ValueError, error:
|
||||
print "error", error
|
||||
|
||||
try:
|
||||
self.sockets.remove(stream_client)
|
||||
except ValueError, error:
|
||||
print "error", error
|
||||
|
||||
def render_image(self):
|
||||
if not self.stream_clients:
|
||||
return
|
||||
|
||||
pixmap = QPixmap.grabWidget(self.widget.live_text, *self.coords)
|
||||
buf = QBuffer()
|
||||
buf.open(QIODevice.WriteOnly)
|
||||
pixmap.save(buf, "JPG", 25)
|
||||
self.img_data = buf.data()
|
||||
len_data = len(self.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, self.img_data))
|
||||
for sock in self.stream_clients:
|
||||
sock.write(array)
|
||||
|
||||
def start_streaming(self):
|
||||
while self.hasPendingConnections():
|
||||
sock = self.nextPendingConnection()
|
||||
sock.readyRead.connect(self.handle_request)
|
||||
sock.disconnected.connect(self.remove_stream_client)
|
||||
self.sockets.append(sock)
|
||||
|
||||
def stop(self):
|
||||
for sock in self.sockets:
|
||||
sock.close()
|
||||
sock.deleteLater()
|
||||
for sock in self.stream_clients:
|
||||
sock.close()
|
||||
sock.deleteLater()
|
||||
self.stream_clients = list()
|
||||
self.sockets = list()
|
||||
self.html_map = dict()
|
||||
self.close()
|
||||
|
||||
|
||||
class TextSorterDialog(QtGui.QWidget, Ui_TextSorterDialog):
|
||||
def __init__(self, parent = None):
|
||||
def __init__(self, parent=None):
|
||||
super(TextSorterDialog, self).__init__(parent)
|
||||
|
||||
self.setupUi(self)
|
||||
self.fill_list()
|
||||
|
||||
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_down_button.clicked.connect(self.slot_text_down)
|
||||
self.text_list.clicked.connect(self.slot_toggle_buttons)
|
||||
self.move_up_button.setEnabled(False)
|
||||
self.move_down_button.setEnabled(False)
|
||||
|
||||
self.model = None
|
||||
|
||||
def slot_toggle_buttons(self, index):
|
||||
row = index.row()
|
||||
|
@ -71,9 +216,9 @@ class TextSorterDialog(QtGui.QWidget, Ui_TextSorterDialog):
|
|||
def fill_list(self):
|
||||
self.model = self.parent().parent().model
|
||||
self.text_list.setModel(self.model)
|
||||
ix = self.parent().parent().current_index
|
||||
index = self.model.index(ix, 0)
|
||||
self.text_list.setCurrentIndex(index)
|
||||
index = self.parent().parent().current_index
|
||||
model_index = self.model.index(index, 0)
|
||||
self.text_list.setCurrentIndex(model_index)
|
||||
|
||||
|
||||
def slot_text_up(self):
|
||||
|
@ -107,8 +252,7 @@ class TextSorterDialog(QtGui.QWidget, Ui_TextSorterDialog):
|
|||
except IndexError:
|
||||
pass
|
||||
|
||||
|
||||
def slot_removeItem(self):
|
||||
def slot_remove_item(self):
|
||||
index = self.text_list.currentIndex().row()
|
||||
self.model.removeRows(index, 1)
|
||||
index = self.model.index(0, 0)
|
||||
|
@ -128,7 +272,6 @@ class FadeAnimation(QtCore.QObject):
|
|||
self.current_alpha = 255
|
||||
self.timer = None
|
||||
|
||||
|
||||
def start_animation(self):
|
||||
print "start_animation"
|
||||
self.animation_started.emit()
|
||||
|
@ -141,13 +284,12 @@ class FadeAnimation(QtCore.QObject):
|
|||
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.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;")
|
||||
|
@ -160,7 +302,7 @@ class FadeAnimation(QtCore.QObject):
|
|||
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.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")
|
||||
|
@ -214,7 +356,6 @@ class TextAnimation(QtCore.QObject):
|
|||
|
||||
def slot_animate(self):
|
||||
self.animation_started.emit()
|
||||
parent = self.parent()
|
||||
|
||||
if self.it is None:
|
||||
src_root_frame = self.src_document.rootFrame()
|
||||
|
@ -272,12 +413,11 @@ class TextAnimation(QtCore.QObject):
|
|||
|
||||
|
||||
class MainWindow(KMainWindow, Ui_MainWindow):
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, args, parent=None):
|
||||
super(MainWindow, self).__init__(parent)
|
||||
|
||||
self.args = args
|
||||
self.is_streaming = False
|
||||
self.ffserver = None
|
||||
self.ffmpeg = None
|
||||
self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self)
|
||||
self.live_center_action = None
|
||||
self.preview_center_action = None
|
||||
self.live_size_action = None
|
||||
|
@ -307,8 +447,22 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
self.font = QtGui.QFont("monospace", self.default_size)
|
||||
self.font.setStyleHint(QtGui.QFont.TypeWriter)
|
||||
|
||||
|
||||
self.create_toolbar()
|
||||
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.preview_text.document().setDefaultFont(self.font)
|
||||
self.preview_text.setFont(self.font)
|
||||
|
@ -322,48 +476,28 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
self.live_editor_collection = KActionCollection(self)
|
||||
self.live_text.createActions(self.live_editor_collection)
|
||||
self.filter_editor_actions()
|
||||
self.create_toolbar()
|
||||
self.slot_load()
|
||||
|
||||
|
||||
app.focusChanged.connect(self.focusChanged)
|
||||
self.start_streaming()
|
||||
self.get_live_coords()
|
||||
|
||||
self.show()
|
||||
|
||||
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)
|
||||
|
||||
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):
|
||||
def get_live_coords(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 get_preview_coords(self):
|
||||
public_rect = self.preview_text.geometry()
|
||||
global_rect = QtCore.QRect(self.mapToGlobal(public_rect.topLeft()), self.mapToGlobal(public_rect.bottomRight()))
|
||||
return global_rect.x(), global_rect.y()
|
||||
|
||||
|
||||
def filter_editor_actions(self):
|
||||
|
||||
disabled_action_names = [
|
||||
|
@ -391,7 +525,7 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
|
||||
for action in self.live_editor_collection.actions():
|
||||
text = str(action.objectName())
|
||||
print "text", text
|
||||
#print "text", text
|
||||
if text in disabled_action_names:
|
||||
action.setVisible(False)
|
||||
|
||||
|
@ -417,7 +551,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
self.slot_set_preview_defaults()
|
||||
self.slot_set_live_defaults()
|
||||
|
||||
|
||||
def create_toolbar(self):
|
||||
|
||||
self.toolbar = KToolBar(self, True, True)
|
||||
|
@ -534,9 +667,27 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
|
||||
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.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.streaming_action.setChecked(True)
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.stop_streaming()
|
||||
if self.db_dirty:
|
||||
self.dialog = KDialog(self)
|
||||
self.dialog.setCaption("4.48 texter - text db not saved")
|
||||
|
@ -546,20 +697,15 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
self.dialog.okClicked.connect(self.slot_save)
|
||||
self.dialog.exec_()
|
||||
|
||||
def live_text_rect(self):
|
||||
return 3, 3, 768, 576
|
||||
|
||||
def stop_streaming(self):
|
||||
self.is_streaming = False
|
||||
if self.ffmpeg is not None:
|
||||
self.ffmpeg.kill()
|
||||
self.ffmpeg = None
|
||||
if self.ffserver is not None:
|
||||
self.ffserver.kill()
|
||||
self.ffserver = None
|
||||
self.http_server.stop()
|
||||
|
||||
def start_streaming(self):
|
||||
public_rect = self.live_text.geometry()
|
||||
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.http_server.listen(port=9009)
|
||||
self.is_streaming = True
|
||||
|
||||
def focusChanged(self, old, new):
|
||||
|
@ -572,16 +718,11 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
|
||||
def custom_clear(self, cursor):
|
||||
cursor.beginEditBlock()
|
||||
cursor.movePosition(QtGui.QTextCursor.Start);
|
||||
cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.KeepAnchor);
|
||||
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):
|
||||
self.is_auto_publish = bool(state)
|
||||
|
||||
|
@ -589,11 +730,10 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
self.is_animate = bool(state)
|
||||
|
||||
def slot_toggle_streaming(self):
|
||||
if self.ffserver is None:
|
||||
self.start_streaming()
|
||||
else:
|
||||
if self.is_streaming:
|
||||
self.stop_streaming()
|
||||
|
||||
else:
|
||||
self.start_streaming()
|
||||
|
||||
def slot_next_item(self):
|
||||
try:
|
||||
|
@ -603,7 +743,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
except ZeroDivisionError:
|
||||
pass
|
||||
|
||||
|
||||
def slot_previous_item(self):
|
||||
try:
|
||||
self.current = (self.text_combo.currentItem() - 1) % len(self.model.text_db)
|
||||
|
@ -612,26 +751,22 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
except ZeroDivisionError:
|
||||
pass
|
||||
|
||||
|
||||
def slot_publish(self):
|
||||
if self.is_animate:
|
||||
self.animation.start_animation(self.preview_text, self.live_text, 0)
|
||||
else:
|
||||
self.live_text.setTextOrHtml(self.preview_text.textOrHtml())
|
||||
|
||||
|
||||
def slot_live_font_size(self, action):
|
||||
self.default_size = self.live_size_action.fontSize()
|
||||
self.slot_set_preview_defaults()
|
||||
self.slot_set_live_defaults()
|
||||
|
||||
|
||||
def slot_preview_font_size(self, action):
|
||||
self.default_size = self.preview_size_action.fontSize()
|
||||
self.slot_set_live_defaults()
|
||||
self.slot_set_preview_defaults()
|
||||
|
||||
|
||||
def slot_toggle_publish(self, state=None):
|
||||
|
||||
if state:
|
||||
|
@ -639,7 +774,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
else:
|
||||
self.slot_clear_live()
|
||||
|
||||
|
||||
def slot_set_preview_defaults(self):
|
||||
self.preview_center_action.setChecked(True)
|
||||
self.preview_text.alignCenter()
|
||||
|
@ -675,11 +809,11 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
|
||||
self.text_combo.clear()
|
||||
current_row = -1
|
||||
for ix, list_obj in enumerate(self.model.text_db):
|
||||
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 = ix
|
||||
current_row = index
|
||||
|
||||
if current_row == -1:
|
||||
current_row = self.current_index
|
||||
|
@ -697,7 +831,7 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
|
||||
def slot_save_live_text(self):
|
||||
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:
|
||||
return
|
||||
old_item = self.model.text_by_preview(preview)
|
||||
|
@ -720,7 +854,7 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
|
||||
def slot_save_preview_text(self):
|
||||
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:
|
||||
return
|
||||
|
@ -747,7 +881,6 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
cPickle.dump(self.model.text_db, f, cPickle.HIGHEST_PROTOCOL)
|
||||
self.db_dirty = False
|
||||
|
||||
|
||||
def slot_open_dialog(self):
|
||||
self.current_index = self.text_combo.currentItem()
|
||||
self.current_object = self.model.text_db[self.current_index]
|
||||
|
@ -758,13 +891,8 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
self.dialog = KDialog(self)
|
||||
self.dialog_widget = TextSorterDialog(self.dialog)
|
||||
self.dialog.setMainWidget(self.dialog_widget)
|
||||
pos_x, pos_y = self.getPreviewCoords()
|
||||
pos_x, pos_y = self.get_preview_coords()
|
||||
self.dialog.move(pos_x, 0)
|
||||
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_()
|
||||
|
||||
|
@ -773,25 +901,37 @@ class MainWindow(KMainWindow, Ui_MainWindow):
|
|||
if not os.path.isdir(path):
|
||||
os.mkdir(path)
|
||||
try:
|
||||
f = open(os.path.join(path, "texter.db"))
|
||||
db_file = open(os.path.join(path, "texter.db"))
|
||||
except IOError:
|
||||
return
|
||||
|
||||
try:
|
||||
self.model.text_db = [list(i) for i in cPickle.load(f)]
|
||||
except Exception, e:
|
||||
print e
|
||||
self.model.text_db = [list(i) for i in cPickle.load(db_file)]
|
||||
except ValueError, error:
|
||||
print error
|
||||
|
||||
self.fill_combo_box()
|
||||
self.text_combo.setCurrentItem(0)
|
||||
self.slot_load_preview_text(0)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
window = MainWindow()
|
||||
arg_parser = ArgParser("dump_grabber")
|
||||
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)
|
||||
|
||||
window = MainWindow(args)
|
||||
app.exec_()
|
||||
|
||||
|
||||
if ( __name__ == '__main__' ):
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
Loading…
Reference in New Issue