started reorderable content list

This commit is contained in:
Bachir Soussi Chiadmi
2017-05-27 23:19:36 +02:00
parent 6561188923
commit 3a735013a4
2 changed files with 344 additions and 4 deletions
+219 -4
View File
@@ -1,16 +1,231 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys, os
from PyQt5 import QtCore
from PyQt5.QtGui import QFont, QSyntaxHighlighter
from PyQt5.QtWidgets import QWidget, QLabel, QTabWidget, QHBoxLayout, QSplitter, QPlainTextEdit
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QSplitter, QListView, QAbstractItemView
import markdown
import re
import json
class Summary(QLabel):
def __init__(self):
class Summary(QWidget):
def __init__(self, core):
super(Summary, self).__init__()
self.core = core
sum_json = open(os.path.join(self.core.cwd,'.config/summary.json')).read()
self.sum = json.loads(sum_json)
vbox = QVBoxLayout()
vbox.setContentsMargins(0,0,0,0)
self.list = SummaryList(self)
vbox.addWidget(self.list)
# self.actions = SummaryActions(self)
# self.addWidget(self.actions)
self.setLayout(vbox)
class SumListModel(QtCore.QAbstractListModel):
dragDropFinished = QtCore.pyqtSignal()
def __init__(self,sum):
QtCore.QAbstractItemModel.__init__(self)
self.nodes = ['node0', 'node1', 'node2', 'node3', 'node4', 'node5']
self.lastDroppedItems = []
self.pendingRemoveRowsAfterDrop = False
def rowForItem(self, text):
'''
rowForItem method returns the row corresponding to the passed in item
or None if no such item exists in the model
'''
try:
row = self.nodes.index(text)
except ValueError:
return None
return row
def index(self, row, column, parent):
if row < 0 or row >= len(self.nodes):
return QtCore.QModelIndex()
return self.createIndex(row, column)
def parent(self, index):
return QtCore.QModelIndex()
def rowCount(self, index):
if index.isValid():
return 0
return len(self.nodes)
def data(self, index, role):
if not index.isValid():
return None
if role == QtCore.Qt.DisplayRole:
row = index.row()
if row < 0 or row >= len(self.nodes):
return None
return self.nodes[row]
else:
return None
def supportedDropActions(self):
return QtCore.Qt.MoveAction
def flags(self, index):
if not index.isValid():
return QtCore.Qt.ItemIsEnabled
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | \
QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled
def insertRows(self, row, count, index):
if index.isValid():
return False
if count <= 0:
return False
# inserting 'count' empty rows starting at 'row'
self.beginInsertRows(QtCore.QModelIndex(), row, row + count - 1)
for i in range(0, count):
self.nodes.insert(row + i, '')
self.endInsertRows()
return True
def removeRows(self, row, count, index):
if index.isValid():
return False
if count <= 0:
return False
num_rows = self.rowCount(QtCore.QModelIndex())
self.beginRemoveRows(QtCore.QModelIndex(), row, row + count - 1)
for i in range(count, 0, -1):
self.nodes.pop(row - i + 1)
self.endRemoveRows()
if self.pendingRemoveRowsAfterDrop:
'''
If we got here, it means this call to removeRows is the automatic
'cleanup' action after drag-n-drop performed by Qt
'''
self.pendingRemoveRowsAfterDrop = False
self.dragDropFinished.emit()
return True
def setData(self, index, value, role):
if not index.isValid():
return False
if index.row() < 0 or index.row() > len(self.nodes):
return False
self.nodes[index.row()] = str(value)
self.dataChanged.emit(index, index)
return True
def mimeTypes(self):
return ['application/vnd.treeviewdragdrop.list']
def mimeData(self, indexes):
mimedata = QtCore.QMimeData()
encoded_data = QtCore.QByteArray()
stream = QtCore.QDataStream(encoded_data, QtCore.QIODevice.WriteOnly)
for index in indexes:
if index.isValid():
text = self.data(index, 0)
stream << QtCore.QByteArray(text.encode('utf-8'))
mimedata.setData('application/vnd.treeviewdragdrop.list', encoded_data)
return mimedata
def dropMimeData(self, data, action, row, column, parent):
if action == QtCore.Qt.IgnoreAction:
return True
if not data.hasFormat('application/vnd.treeviewdragdrop.list'):
return False
if column > 0:
return False
num_rows = self.rowCount(QtCore.QModelIndex())
if num_rows <= 0:
return False
if row < 0:
if parent.isValid():
row = parent.row()
else:
return False
encoded_data = data.data('application/vnd.treeviewdragdrop.list')
stream = QtCore.QDataStream(encoded_data, QtCore.QIODevice.ReadOnly)
new_items = []
rows = 0
while not stream.atEnd():
text = QtCore.QByteArray()
stream >> text
text = bytes(text).decode('utf-8')
index = self.nodes.index(text)
new_items.append((text, index))
rows += 1
self.lastDroppedItems = []
for (text, index) in new_items:
target_row = row
if index < row:
target_row += 1
self.beginInsertRows(QtCore.QModelIndex(), target_row, target_row)
self.nodes.insert(target_row, text)
self.endInsertRows()
self.lastDroppedItems.append(text)
row += 1
self.pendingRemoveRowsAfterDrop = True
return True
class SumListSelectionModel(QtCore.QItemSelectionModel):
def __init__(self, parent=None):
QtCore.QItemSelectionModel.__init__(self, parent)
def onModelItemsReordered(self):
new_selection = QtCore.QItemSelection()
new_index = QtCore.QModelIndex()
for item in self.model().lastDroppedItems:
row = self.model().rowForItem(item)
if row is None:
continue
new_index = self.model().index(row, 0, QtCore.QModelIndex())
new_selection.select(new_index, new_index)
self.clearSelection()
flags = QtCore.QItemSelectionModel.ClearAndSelect | \
QtCore.QItemSelectionModel.Rows | \
QtCore.QItemSelectionModel.Current
self.select(new_selection, flags)
self.setCurrentIndex(new_index, flags)
class SummaryList(QListView):
def __init__(self,prt):
super(SummaryList, self).__init__()
print("list")
self.prt = prt
model = SumListModel(sum)
selectionModel = SumListSelectionModel(model)
model.dragDropFinished.connect(selectionModel.onModelItemsReordered)
self.setModel(model)
self.setSelectionModel(selectionModel)
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setDragDropOverwriteMode(False)
class SummaryActions(QWidget):
def __init__(self,sum):
print("actions")
# for p in self.sum:
# class SummaryActions():
# def
class ContentStack(QWidget):
def __init__(self, core):
@@ -23,7 +238,7 @@ class ContentStack(QWidget):
hsplitter = QSplitter(QtCore.Qt.Horizontal)
self.summary = QLabel("Summary (markdown files list).")
self.summary = Summary(core)
hsplitter.addWidget(self.summary)
self.mdsource = QLabel("Content (markdown src).")
+125
View File
@@ -0,0 +1,125 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys, os, re
from PyQt5 import QtCore
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QKeySequence, QFont, QSyntaxHighlighter
from PyQt5.QtWidgets import QWidget, QLabel, QTabWidget, QVBoxLayout, QHBoxLayout, QSplitter, QPlainTextEdit, QShortcut
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtWebKitWidgets import QWebView, QWebInspector
class WebkitView(QWebView):
def __init__(self, port):
self.port = port
self.view = QWebView.__init__(self)
self.load(QUrl('http://localhost:'+str(self.port)))
self.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
# self.settings().setAttribute(QWebSettings.PluginsEnabled, True)
class WebkitInspector(QWebInspector):
def __init__(self, webkitview):
super(WebkitInspector, self).__init__()
self.webkitview = webkitview
self.setPage(self.webkitview.page())
# TODO: webkitinspector is disappearing when chaging tabs
class CodeEditor(QPlainTextEdit):
def __init__(self, core, tabs, file=None):
super(CodeEditor, self).__init__()
self.core = core
self.tabs = tabs
# self.file = file
self.file = os.path.join(self.core.cwd,file)
self.insertPlainText(open(self.file, 'r').read())
self.changed = False
self.textChanged.connect(self.onTextChanged)
self.shortcut = QShortcut(QKeySequence("Ctrl+s"), self)
self.shortcut.activated.connect(self.save)
def onTextChanged(self):
# print('textChanged')
# print(self.toPlainText())
# open(self.file, 'w').write(self.toPlainText())
if not self.changed:
self.changed = True
i = self.tabs.currentIndex()
self.tabs.setTabText(i, "* "+self.tabs.tabText(i))
def save(self):
if self.changed:
open(self.file, 'w').write(self.toPlainText())
i = self.tabs.currentIndex()
self.tabs.setTabText(i, re.sub(r'^\*\s', '', self.tabs.tabText(i)))
self.changed = False
# TODO: how to combine file save and project save
class Editor(QWidget):
def __init__(self, core):
super(Editor, self).__init__()
self.core = core
self.layout = QVBoxLayout(self)
self.layout.setContentsMargins(0,0,0,0)
# Initialize tab screen
self.tabs = QTabWidget()
self.scsstab = CodeEditor(core, self.tabs, 'assets/scss/styles.scss')
self.jstab = CodeEditor(core, self.tabs, 'assets/js/script.js')
# Add tabs
self.tabs.addTab(self.scsstab,"scss")
self.tabs.addTab(self.jstab,"js")
# Add tabs to widget
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
# font = QFont()
# font.setFamily('Courier')
# font.setFixedPitch(True)
# font.setPointSize(10)
# self.setFont(font)
# self.highlighter = Highlighter(self.document())
# https://pypi.python.org/pypi/QScintilla/2.9.2
class DesignStack(QWidget):
def __init__(self, core):
super(DesignStack, self).__init__()
# self.grid = QGridLayout()
hbox = QHBoxLayout()
hbox.setContentsMargins(0,0,0,0)
self.setLayout(hbox)
# webviewbox = QVBoxLayout()
vsplitter = QSplitter(QtCore.Qt.Vertical)
self.webkitview = WebkitView(core.server.port)
vsplitter.addWidget(self.webkitview)
self.webkitinspector = WebkitInspector(self.webkitview)
vsplitter.addWidget(self.webkitinspector)
hsplitter = QSplitter(QtCore.Qt.Horizontal)
hsplitter.addWidget(vsplitter)
self.editor = Editor(core)
hsplitter.addWidget(self.editor)
hbox.addWidget(hsplitter)
# def onChanged(self, text):
# print("ViewTba Layout Changed")
# self.lbl.setText(text)
# self.lbl.adjustSize()