changed from ffmpeg grabbing to internal grabbing and added a async http server

This commit is contained in:
Stefan Kögl 2014-05-10 14:52:21 +02:00
parent 28cc9798e7
commit d7f3a7daea
1 changed files with 256 additions and 116 deletions

View File

@ -1,38 +1,49 @@
#!/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
from math import pow
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
programName = ki18n("4.48 Psychose Texter")
version = "0.1"
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 = QtGui.QApplication([])
app = KApplication()
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,21 +51,155 @@ 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
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): class TextSorterDialog(QtGui.QWidget, Ui_TextSorterDialog):
def __init__(self, parent = None): def __init__(self, parent=None):
super(TextSorterDialog, self).__init__(parent) super(TextSorterDialog, self).__init__(parent)
self.setupUi(self) self.setupUi(self)
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)
self.move_up_button.setEnabled(False) self.move_up_button.setEnabled(False)
self.move_down_button.setEnabled(False) self.move_down_button.setEnabled(False)
self.model = None
def slot_toggle_buttons(self, index): def slot_toggle_buttons(self, index):
row = index.row() row = index.row()
@ -71,9 +216,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):
@ -107,8 +252,7 @@ class TextSorterDialog(QtGui.QWidget, Ui_TextSorterDialog):
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)
@ -128,7 +272,6 @@ class FadeAnimation(QtCore.QObject):
self.current_alpha = 255 self.current_alpha = 255
self.timer = None self.timer = None
def start_animation(self): def start_animation(self):
print "start_animation" print "start_animation"
self.animation_started.emit() self.animation_started.emit()
@ -141,13 +284,12 @@ class FadeAnimation(QtCore.QObject):
self.timer.timeout.connect(self.slot_animate) self.timer.timeout.connect(self.slot_animate)
self.timer.start(100) self.timer.start(100)
def slot_animate(self): def slot_animate(self):
print "slot_animate" print "slot_animate"
print "current_alpha", self.current_alpha print "current_alpha", self.current_alpha
if self.fade_delta > 0: if self.fade_delta > 0:
if self.current_alpha > 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 self.current_alpha -= self.fade_delta
else: else:
self.live_text.setStyleSheet("color:black;") self.live_text.setStyleSheet("color:black;")
@ -160,7 +302,7 @@ class FadeAnimation(QtCore.QObject):
print "animation_finished" print "animation_finished"
else: else:
if self.current_alpha < 255: 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 self.current_alpha -= self.fade_delta
else: else:
self.live_text.setStyleSheet("color:white") self.live_text.setStyleSheet("color:white")
@ -214,7 +356,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()
@ -272,12 +413,11 @@ class TextAnimation(QtCore.QObject):
class MainWindow(KMainWindow, Ui_MainWindow): class MainWindow(KMainWindow, Ui_MainWindow):
def __init__(self, parent=None): def __init__(self, args, parent=None):
super(MainWindow, self).__init__(parent) super(MainWindow, self).__init__(parent)
self.args = args
self.is_streaming = False self.is_streaming = False
self.ffserver = None self.http_server = MjpegStreamingServer((args.http_host, args.http_port), self)
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
@ -307,8 +447,22 @@ class MainWindow(KMainWindow, Ui_MainWindow):
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.create_toolbar() 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.document().setDefaultFont(self.font)
self.preview_text.setFont(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_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()
app.focusChanged.connect(self.focusChanged)
self.start_streaming()
self.get_live_coords()
self.show() self.show()
self.save_action.triggered.connect(self.slot_save) def get_live_coords(self):
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() public_rect = self.live_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()))
x = global_rect.x() x = global_rect.x()
y = global_rect.y() 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())) 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() 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 filter_editor_actions(self): def filter_editor_actions(self):
disabled_action_names = [ disabled_action_names = [
@ -391,7 +525,7 @@ 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 #print "text", text
if text in disabled_action_names: if text in disabled_action_names:
action.setVisible(False) action.setVisible(False)
@ -417,7 +551,6 @@ 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)
@ -534,9 +667,27 @@ class MainWindow(KMainWindow, Ui_MainWindow):
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.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): def closeEvent(self, event):
self.stop_streaming()
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")
@ -546,20 +697,15 @@ class MainWindow(KMainWindow, Ui_MainWindow):
self.dialog.okClicked.connect(self.slot_save) self.dialog.okClicked.connect(self.slot_save)
self.dialog.exec_() self.dialog.exec_()
def live_text_rect(self):
return 3, 3, 768, 576
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=9009)
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 focusChanged(self, old, new): def focusChanged(self, old, new):
@ -572,16 +718,11 @@ class MainWindow(KMainWindow, Ui_MainWindow):
def custom_clear(self, cursor): def custom_clear(self, cursor):
cursor.beginEditBlock() cursor.beginEditBlock()
cursor.movePosition(QtGui.QTextCursor.Start); cursor.movePosition(QtGui.QTextCursor.Start)
cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.KeepAnchor); cursor.movePosition(QtGui.QTextCursor.End, QtGui.QTextCursor.KeepAnchor)
cursor.removeSelectedText() cursor.removeSelectedText()
cursor.endEditBlock() 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 +730,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 +743,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 +751,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 +774,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()
@ -675,11 +809,11 @@ class MainWindow(KMainWindow, Ui_MainWindow):
self.text_combo.clear() self.text_combo.clear()
current_row = -1 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 preview, text = list_obj
self.text_combo.addAction(preview) self.text_combo.addAction(preview)
if list_obj == self.current_object: if list_obj == self.current_object:
current_row = ix current_row = index
if current_row == -1: if current_row == -1:
current_row = self.current_index current_row = self.current_index
@ -697,7 +831,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 +854,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 +881,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]
@ -758,13 +891,8 @@ class MainWindow(KMainWindow, Ui_MainWindow):
self.dialog = KDialog(self) self.dialog = KDialog(self)
self.dialog_widget = TextSorterDialog(self.dialog) self.dialog_widget = TextSorterDialog(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.get_preview_coords()
self.dialog.move(pos_x, 0) 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.okClicked.connect(self.fill_combo_box)
self.dialog.exec_() self.dialog.exec_()
@ -773,25 +901,37 @@ class MainWindow(KMainWindow, Ui_MainWindow):
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 print 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 main(): 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_() app.exec_()
if ( __name__ == '__main__' ): if __name__ == '__main__':
main() main()