Created
January 28, 2017 23:39
-
-
Save cryzed/2ac5802e2bc9c6d541787cd81fd63623 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import argparse | |
import hashlib | |
import os | |
import shutil | |
import sys | |
import xml.etree.ElementTree as ET | |
from argparse import Namespace | |
from PySide import QtCore | |
from PySide.QtCore import Qt | |
from PySide.QtGui import (QApplication, QIcon, QMainWindow, QWidget, QDialog, QListWidget, QListWidgetItem, QMenuBar, | |
QPushButton, QVBoxLayout) | |
argument_parser = argparse.ArgumentParser() | |
argument_parser.add_argument('pack_name') | |
class UnsupportedPlatformError(Exception): | |
pass | |
def _posix_get_emoji_path(): | |
data_home = os.getenv('XDG_DATA_HOME', os.path.join(os.getenv('HOME'), '.local', 'share')) | |
return os.path.join(data_home, 'emoticons') | |
def _nt_get_emoji_path(): | |
return os.path.join(os.getenv('%LOCALAPPDATA%'), 'Emoticons') | |
def get_emoticon_path(): | |
if os.name == 'posix': | |
return _posix_get_emoji_path() | |
elif os.name == 'nt': | |
return _nt_get_emoji_path() | |
raise UnsupportedPlatformError(f'Unsupported platform: {sys.platform}') | |
def get_md5_hexdigest(path): | |
with open(path, 'rb') as file: | |
return hashlib.md5(file.read()).hexdigest() | |
class Emoticon: | |
def __init__(self, filename, strings): | |
self.filename = filename | |
self.strings = strings | |
@classmethod | |
def from_etree_element(cls, element): | |
instance = cls(element.get('file'), [element.text for element in element.iterfind('string')]) | |
return instance | |
def to_etree_element(self): | |
emoticon = ET.Element('emoticon', {'file': self.filename}) | |
for text in self.strings: | |
string = ET.SubElement(emoticon, 'string') | |
string.text = text | |
return emoticon | |
# Sort by first substitution string | |
def __lt__(self, other): | |
return (self.strings[0] if self.strings else '') < (other.strings[0] if other.strings else '') | |
def __repr__(self): | |
return f'<Emoticon {", ".join(self.strings): {self.filename}}>' | |
def __str__(self): | |
return repr(self) | |
class EmoticonFolder: | |
_XML_TEMPLATE = "<?xml version='1.0'?><messaging-emoticon-map></messaging-emoticon-map>" | |
def __init__(self, path): | |
self.path = path | |
self._xml_path = os.path.join(path, 'emoticons.xml') | |
tree = ET.parse(self._xml_path) | |
self.emoticons = [Emoticon.from_etree_element(element) for element in tree.iter('emoticon')] | |
def add_emoticon_from_path(self, path, strings, filename=None): | |
filename = filename or os.path.basename(path) | |
shutil.copy(path, os.path.join(self.path, filename)) | |
emoticon = Emoticon(filename, strings) | |
self.emoticons.append(emoticon) | |
return emoticon | |
def write(self, path=None): | |
tree = ET.fromstring(self._XML_TEMPLATE) | |
tree.extend([emoticon.to_etree_element() for emoticon in self.emoticons]) | |
with open(path or self._xml_path, 'wb') as file: | |
file.write(ET.tostring(tree)) | |
def __iter__(self): | |
return iter(self.emoticons) | |
def __len__(self): | |
return len(self.emoticons) | |
def __repr__(self): | |
return f'<EmoticonFolder {self.path}: {len(self)} emoticons>' | |
def __str__(self): | |
return repr(self) | |
class EditEmoticonDialog(QDialog): | |
def __init__(self, item, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
self._item = item | |
self._emoticon = item.data(Qt.UserRole) | |
self.setWindowTitle(f'Emoticon - {", ".join(self._emoticon.strings)}') | |
self._ui = self._init_ui(self) | |
for string in self._emoticon.strings: | |
item = QListWidgetItem(string) | |
self._ui.strings.addItem(item) | |
def _init_ui(self, widget): | |
layout = QVBoxLayout(widget) | |
layout.setAlignment(Qt.AlignCenter) | |
icon = self._item.icon() | |
emoticon_button = QPushButton(icon, '') | |
emoticon_button.setIconSize(sorted(icon.availableSizes())[-1]) | |
emoticon_button.setToolTip('Open file...') | |
emoticon_button.setFlat(True) | |
strings_list_widget = QListWidget(widget) | |
strings_list_widget.setAlternatingRowColors(True) | |
strings_list_widget.setEditTriggers(strings_list_widget.AllEditTriggers) | |
close_button = QPushButton(widget, text='Close') | |
layout.addWidget(emoticon_button) | |
layout.addWidget(strings_list_widget) | |
layout.addWidget(close_button) | |
return Namespace(emoticon=emoticon_button, strings=strings_list_widget, close=close_button) | |
class EmoticonListWidget(QListWidget): | |
right_clicked = QtCore.Signal(QListWidgetItem) | |
def contextMenuEvent(self, event): | |
item = self.itemAt(event.pos()) | |
self.right_clicked.emit(item) | |
class MainWindow(QMainWindow): | |
TITLE = 'qTox Emoticons' | |
SIZE = 300, 300 | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
self.setWindowTitle(self.TITLE) | |
self.setGeometry(0, 0, *self.SIZE) | |
self.setCentralWidget(QWidget(self)) | |
self.setMenuBar(QMenuBar(self)) | |
self._emoticons = None | |
self._ui = self._init_ui(self.centralWidget()) | |
self._ui.emoticons.itemDoubleClicked.connect(self._on_emoticon_double_clicked) | |
self._ui.emoticons.right_clicked.connect(self._on_emoticon_right_clicked) | |
self._ui.save.pressed.connect(self._on_save_pressed) | |
def _init_ui(self, widget): | |
layout = QVBoxLayout(widget) | |
list_widget = EmoticonListWidget(widget) | |
list_widget.setViewMode(list_widget.IconMode) | |
list_widget.setResizeMode(list_widget.Adjust) | |
list_widget.setDragEnabled(False) | |
save_button = QPushButton(widget, text='Save') | |
layout.addWidget(list_widget) | |
layout.addWidget(save_button) | |
return Namespace(emoticons=list_widget, save=save_button) | |
def open(self, path): | |
self._emoticons = EmoticonFolder(path) | |
self.setWindowTitle(f'{self.TITLE} - {os.path.basename(path)}') | |
self._ui.emoticons.clear() | |
for emoticon in sorted(self._emoticons): | |
file_path = os.path.join(path, emoticon.filename) | |
item = QListWidgetItem(QIcon(file_path), '') | |
item.setToolTip(', '.join(emoticon.strings)) | |
item.setData(Qt.UserRole, emoticon) | |
self._ui.emoticons.addItem(item) | |
@QtCore.Slot() | |
def _on_save_pressed(self): | |
pass | |
@QtCore.Slot() | |
def _on_emoticon_double_clicked(self, item): | |
EditEmoticonDialog(item).exec_() | |
@QtCore.Slot() | |
def _on_emoticon_right_clicked(self, item): | |
pass | |
def main(): | |
application = QApplication(sys.argv) | |
window = MainWindow() | |
path = os.path.join(get_emoticon_path(), arguments.pack_name) | |
window.open(path) | |
window.show() | |
application.exec_() | |
if __name__ == '__main__': | |
arguments = argument_parser.parse_args() | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment