class UndoableEditor(QWidget): def __init__(self): QWidget.__init__(self) self.filename = "" self.undoStack = QUndoStack() self.undo = FlatButton(":/images/undo_normal.png", ":/images/undo_hover.png", "", ":/images/undo_disabled.png") self.redo = FlatButton(":/images/redo_normal.png", ":/images/redo_hover.png", "", ":/images/redo_disabled.png") self.undo.setToolTip("Undo") self.redo.setToolTip("Redo") self.undo.setEnabled(False) self.redo.setEnabled(False) hbox = QHBoxLayout() hbox.addStretch(0) hbox.addWidget(self.undo) hbox.addWidget(self.redo) self.titleLabel = QLabel() fnt = self.titleLabel.font() fnt.setPointSize(20) fnt.setBold(True) self.titleLabel.setFont(fnt) self.layout = QGridLayout() self.layout.addWidget(self.titleLabel, 0, 0) self.layout.addLayout(hbox, 0, 2) self.setLayout(self.layout) #connect(self.redo, SIGNAL(clicked()), self, SLOT(redo())) #connect(self.undo, SIGNAL(clicked()), self, SLOT(undo())) #connect(self.undoStack, SIGNAL(canUndoChanged(bool)), self, SLOT(canUndoChanged(bool))) #connect(self.undoStack, SIGNAL(canRedoChanged(bool)), self, SLOT(canRedoChanged(bool))) #connect(self.undoStack, SIGNAL(undoTextChanged(QString)), self, SLOT(undoTextChanged(QString))) #connect(self.undoStack, SIGNAL(redoTextChanged(QString)), self, SLOT(redoTextChanged(QString))) def contentChanged(self, text): changeCommand = ChangeFileCommand(self, self.filename, text) self.undoStack.push(changeCommand)
class ContentList(QWidget): editContent = pyqtSignal(object) def __init__(self, site, type): QWidget.__init__(self) self.site = site self.addedContentName = "" self.type = type self.undoStack = QUndoStack() vbox = QVBoxLayout() layout = QGridLayout() titleLabel = QLabel() button = QPushButton() if self.type == ContentType.PAGE: button.setText("Add Page") else: button.setText("Add Post") button.setMaximumWidth(120) if self.type == ContentType.PAGE: titleLabel.setText("Pages") else: titleLabel.setText("Posts") fnt = titleLabel.font() fnt.setPointSize(20) fnt.setBold(True) titleLabel.setFont(fnt) self.undo = FlatButton(":/images/undo_normal.png", ":/images/undo_hover.png", "", ":/images/undo_disabled.png") self.redo = FlatButton(":/images/redo_normal.png", ":/images/redo_hover.png", "", ":/images/redo_disabled.png") self.undo.setToolTip("Undo") self.redo.setToolTip("Redo") self.undo.setEnabled(False) self.redo.setEnabled(False) hbox = QHBoxLayout() hbox.addStretch(0) hbox.addWidget(self.undo) hbox.addWidget(self.redo) self.list = QTableWidget(0, 6, self) self.list.verticalHeader().hide() self.list.setSelectionMode(QAbstractItemView.SingleSelection) self.list.setSelectionBehavior(QAbstractItemView.SelectRows) self.list.horizontalHeader().setSectionResizeMode( 1, QHeaderView.Stretch) self.list.setToolTip("Double click to edit item") labels = ["", "Name", "Source", "Layout", "Author", "Date"] self.list.setHorizontalHeaderLabels(labels) self.reload() layout.addWidget(titleLabel, 0, 0) layout.addLayout(hbox, 0, 2) layout.addWidget(button, 1, 0) layout.addWidget(self.list, 2, 0, 1, 3) vbox.addLayout(layout) self.setLayout(vbox) button.clicked.connect(self.addPage) self.list.cellDoubleClicked.connect(self.tableDoubleClicked) self.redo.clicked.connect(self.doredo) self.undo.clicked.connect(self.doundo) self.undoStack.canUndoChanged.connect(self.canUndoChanged) self.undoStack.canRedoChanged.connect(self.canRedoChanged) self.undoStack.redoTextChanged.connect(self.redoTextChanged) def reload(self): self.list.setRowCount(0) row = -1 itemToEdit = None if self.type == ContentType.PAGE: self.site.loadPages() for i in range(len(self.site.pages)): content = self.site.pages[i] self.addListItem(content) if content.source == self.addedContentName: row = self.list.rowCount() - 1 itemToEdit = self.list.item(row, 1) else: self.site.loadPosts() for i in range(0, len(self.site.posts)): content = self.site.posts[i] self.addListItem(content) if content.source == self.addedContentName: row = self.list.rowCount() - 1 if itemToEdit: self.addedContentName = "" self.list.selectRow(row) self.editContent.emit(itemToEdit) def addListItem(self, content): rows = self.list.rowCount() self.list.setRowCount(rows + 1) tcb = TableCellButtons() tcb.setItem(content) tcb.deleteItem.connect(self.deleteContent) tcb.editItem.connect(self.edit) self.list.setCellWidget(rows, 0, tcb) self.list.setRowHeight(rows, tcb.sizeHint().height()) titleItem = QTableWidgetItem(content.title) titleItem.setFlags(titleItem.flags() ^ Qt.ItemIsEditable) titleItem.setData(Qt.UserRole, content) self.list.setItem(rows, 1, titleItem) sourceItem = QTableWidgetItem(content.source) sourceItem.setFlags(titleItem.flags() ^ Qt.ItemIsEditable) self.list.setItem(rows, 2, sourceItem) layoutItem = QTableWidgetItem(content.layout) layoutItem.setFlags(layoutItem.flags() ^ Qt.ItemIsEditable) self.list.setItem(rows, 3, layoutItem) authorItem = QTableWidgetItem(content.author) authorItem.setFlags(authorItem.flags() ^ Qt.ItemIsEditable) self.list.setItem(rows, 4, authorItem) dateItem = QTableWidgetItem(content.date.toString("dd.MM.yyyy")) dateItem.setFlags(dateItem.flags() ^ Qt.ItemIsEditable) self.list.setItem(rows, 5, dateItem) def canUndoChanged(self, can): self.undo.setEnabled(can) def canRedoChanged(self, can): self.redo.setEnabled(can) def undoTextChanged(self, text): self.undo.setToolTip("Undo " + text) def redoTextChanged(self, text): self.redo.setToolTip("Redo " + text) def doundo(self): self.undoStack.undo() def doredo(self): self.undoStack.redo() def addPage(self): self.addedContentName = self.site.createTemporaryContent(self.type) info = QFileInfo(self.addedContentName) self.addedContentName = info.fileName() self.reload() def tableDoubleClicked(self, r, i): item = self.list.item(r, 1) self.undoStack.clear() self.editContent.emit(item) def edit(self, content): for row in range(self.list.rowCount()): item = self.list.item(row, 1) m = item.data(Qt.UserRole) if m == content: self.list.selectRow(row) self.undoStack.clear() self.editContent.emit(item) break def deleteContent(self, content): for row in range(self.list.rowCount()): item = self.list.item(row, 1) m = item.data(Qt.UserRole) if m == content: if m.content_type == ContentType.PAGE: subdir = "pages" else: subdir = "posts" delCommand = DeleteContentCommand( self, os.path.join(self.site.source_path, subdir, m.source), "delete content " + m.title) self.undoStack.push(delCommand) break
class MenuEditorTableCellButtons(QWidget): deleteItem = pyqtSignal(object) editItem = pyqtSignal(object) itemLeft = pyqtSignal(object) itemRight = pyqtSignal(object) itemUp = pyqtSignal(object) itemDown = pyqtSignal(object) def __init__(self): QWidget.__init__(self) self.delete = FlatButton(":/images/trash_normal.png", ":/images/trash_hover.png") self.edit = FlatButton(":/images/edit_normal.png", ":/images/edit_hover.png") self.left = FlatButton(":/images/left_normal.png", ":/images/left_hover.png", "", ":/images/left_disabled.png") self.right = FlatButton(":/images/right_normal.png", ":/images/right_hover.png", "", ":/images/right_disabled.png") self.up = FlatButton(":/images/up_normal.png", ":/images/up_hover.png", "", ":/images/up_disabled.png") self.down = FlatButton(":/images/down_normal.png", ":/images/down_hover.png", "", ":/images/down_disabled.png") self.edit.setToolTip("Edit Item") self.delete.setToolTip("Delete Item") self.left.setToolTip("Make Mainitem") self.right.setToolTip("Make Subitem") self.up.setToolTip("Sort Up") self.down.setToolTip("Sort Down") self.left.setEnabled(False) self.right.setEnabled(False) self.up.setEnabled(False) self.down.setEnabled(False) self.item = None hbox = QHBoxLayout() hbox.addWidget(self.edit) hbox.addWidget(self.up) hbox.addWidget(self.down) hbox.addWidget(self.left) hbox.addWidget(self.right) hbox.addWidget(self.delete) self.setLayout(hbox) self.delete.clicked.connect(self.deleteItemClicked) self.edit.clicked.connect(self.editItemClicked) self.left.clicked.connect(self.itemLeftClicked) self.right.clicked.connect(self.itemRightClicked) self.up.clicked.connect(self.itemUpClicked) self.down.clicked.connect(self.itemDownClicked) def setMenuItem(self, m): self.item = m def deleteItemClicked(self): self.deleteItem.emit(self.item) def editItemClicked(self): self.editItem.emit(self.item) def itemLeftClicked(self): self.itemLeft.emit(self.item) def itemRightClicked(self): self.itemRight.emit(self.item) def itemUpClicked(self): self.itemUp.emit(self.item) def itemDownClicked(self): self.itemDown.emit(self.item) def setEnableLeft(self, mode): self.left.setEnabled(mode) def setEnableRight(self, mode): self.right.setEnabled(mode) def setEnableUp(self, mode): self.up.setEnabled(mode) def setEnableDown(self, mode): self.down.setEnabled(mode)
class MenuEditor(AnimateableEditor): contentChanged = pyqtSignal(object) menuChanged = pyqtSignal(str) def __init__(self, win, menu, site): AnimateableEditor.__init__(self) self.win = win self.menu = menu self.site = site self.changed = False self.setAutoFillBackground(True) titleLabel = QLabel("Menu Editor") fnt = titleLabel.font() fnt.setPointSize(20) fnt.setBold(True) titleLabel.setFont(fnt) self.close = FlatButton(":/images/close_normal.png", ":/images/close_hover.png") self.close.setToolTip("Close Content Editor") self.undo = FlatButton(":/images/undo_normal.png", ":/images/undo_hover.png", "", ":/images/undo_disabled.png") self.redo = FlatButton(":/images/redo_normal.png", ":/images/redo_hover.png", "", ":/images/redo_disabled.png") self.undo.setToolTip("Undo") self.redo.setToolTip("Redo") self.undo.setEnabled(False) self.redo.setEnabled(False) hbox = QHBoxLayout() hbox.addStretch(0) hbox.addWidget(self.undo) hbox.addWidget(self.redo) hbox.addWidget(self.close) addButton = QPushButton("Add Menuitem") addButton.setMaximumWidth(120) self.name = QLineEdit() self.name.setText(menu.name) self.name.setMaximumWidth(200) labels = ["Title", "Url", "Icon", "", "Sort"] self.tree = QTreeWidget() self.tree.setHeaderLabels(labels) self.tree.header().setSectionResizeMode(0, QHeaderView.Stretch) self.tree.header().hideSection(4) self.tree.setSelectionMode(QAbstractItemView.NoSelection) self.tree.setToolTip("Double Click To Edit") self.tree.setColumnWidth(2, 40) layout = QGridLayout() layout.addWidget(titleLabel, 0, 0) layout.addLayout(hbox, 0, 2) layout.addWidget(QLabel("Name"), 1, 0) layout.addWidget(self.name, 2, 0) layout.addWidget(addButton, 3, 0) layout.addWidget(self.tree, 4, 0, 1, 3) self.setLayout(layout) self.reloadMenu(menu) addButton.clicked.connect(self.addButtonClicked) self.close.clicked.connect(self.closeEditor) self.name.editingFinished.connect(self.nameChanged) self.redo.clicked.connect(self.redoEdit) self.undo.clicked.connect(self.undoEdit) self.tree.itemChanged.connect(self.itemChanged) def reloadMenu(self, menu): if not menu: self.close.emit() return self.menu = menu self.tree.clear() self.name.setText(menu.name) for i in range(0, len(self.menu.items)): item = self.menu.items[i] self.addTreeItem(item) self.tree.expandAll() self.tree.sortItems(4, Qt.AscendingOrder) self.updateButtonStates() def addTreeItem(self, item): twi = QTreeWidgetItem() twi.setFlags(twi.flags() | Qt.ItemIsEditable) twi.setText(0, item.title) twi.setText(1, item.url) twi.setText(4, str(self.tree.topLevelItemCount())) twi.setData(0, Qt.UserRole, item) self.tree.addTopLevelItem(twi) self.addTableCellButtons(item, twi) for i in range(len(item.items)): sub = item.items[i] stwi = QTreeWidgetItem() stwi.setFlags(stwi.flags() | Qt.ItemIsEditable) stwi.setText(0, sub.title) stwi.setText(1, sub.url) stwi.setText(4, str(i)) stwi.setData(0, Qt.UserRole, sub) twi.addChild(stwi) self.addTableCellButtons(sub, stwi) def addTableCellButtons(self, item, twi): tcb = MenuEditorTableCellButtons() tcb.setMenuItem(item) self.tree.setItemWidget(twi, 3, tcb) self.tree.setColumnWidth(3, tcb.sizeHint().width()) if item.isSubitem(): tcb.deleteItem.connect(self.deleteSubItem) tcb.itemLeft.connect(self.itemLeft) else: tcb.deleteItem.connect(self.deleteItem) tcb.itemUp.connect(self.itemUp) tcb.itemDown.connect(self.itemDown) tcb.itemRight.connect(self.itemRight) tcb.editItem.connect(self.editItem) imgs = ImageSelector() imgs.setToolTip("Click to select image, right click to reset image") imgs.setItem(item) imgs.setMaximumSize(24, 24) isw = QWidget() vbox = QVBoxLayout() vbox.addWidget(imgs) isw.setLayout(vbox) if not item.icon: imgs.setImage(QImage(":/images/image_placeholder.png")) else: imgs.setImage(QImage(self.site.source_path + "/" + item.icon)) self.tree.setItemWidget(twi, 2, isw) imgs.clicked.connect(self.iconClicked) def registerUndoStack(self, stack): self.undoStack = stack self.undoStack.canUndoChanged.connect(self.canUndoChanged) self.undoStack.canRedoChanged.connect(self.canRedoChanged) self.undoStack.undoTextChanged.connect(self.undoTextChanged) self.undoStack.redoTextChanged.connect(self.redoTextChanged) self.undo.setEnabled(self.undoStack.canUndo()) self.redo.setEnabled(self.undoStack.canRedo()) self.undo.setToolTip("Undo " + self.undoStack.undoText()) self.redo.setToolTip("Redo " + self.undoStack.redoText()) def canUndoChanged(self, can): self.undo.setEnabled(can) def canRedoChanged(self, can): self.redo.setEnabled(can) def undoTextChanged(self, text): self.undo.setToolTip("Undo " + text) def redoTextChanged(self, text): self.redo.setToolTip("Redo " + text) def getUndoRedoText(self, item, action): return "menuitem (" + item.title + ") from menu (" + self.menu.name + ") " + action def undoEdit(self): self.undoStack.undo() def redoEdit(self): self.undoStack.redo() def addButtonClicked(self): menuitem = MenuItem() self.menu.addMenuitem(menuitem) self.addTreeItem(menuitem) self.menuChanged.emit(self.getUndoRedoText(menuitem, "added")) self.updateButtonStates() item = self.tree.topLevelItem(self.getRow(menuitem)) self.tree.editItem(item, 0) def closeEditor(self): self.closes.emit() def nameChanged(self): if self.menu.name != self.name.text: action = "menu name changed from \"" + self.menu.name + "\" to \"" + self.name.text + "\"" self.menu.setName(self.name.text()) self.contentChanged.emit(self.menu) self.menuChanged.emit(action) def itemChanged(self, twi, column): action = "" item = twi.data(0, Qt.UserRole) if column == 0: item.title = twi.text(0) action = "title changed" elif column == 1: item.url = twi.text(1) action = "url changed" self.menuChanged.emit(self.getUndoRedoText(item, action)) def getRow(self, menuitem): for i in range(0, self.tree.topLevelItemCount()): item = self.tree.topLevelItem(i) mi = item.data(0, Qt.UserRole) if mi == menuitem: return i return -1 def deleteSubItem(self, menuitem): row = self.getRow(menuitem.parentItem) parent = self.tree.topLevelItem(row) if parent: for i in range(0, parent.childCount()): child = parent.child(i) mi = child.data(0, Qt.UserRole) if mi == menuitem: parent.removeChild(child) del child break if menuitem.parentItem: menuitem.parentItem.removeMenuitem(menuitem) self.updateButtonStates() self.menuChanged.emit(self.getUndoRedoText(menuitem, "deleted")) def itemLeft(self, menuitem): row = self.getRow(menuitem.parentItem()) parent = self.tree.topLevelItem(row) for i in range(parent.childCount()): child = parent.child(i) mi = child.data(0, Qt.UserRole) if mi == menuitem: menuitem.parentItem().removeMenuitem(menuitem) menuitem.setSubitem(False) self.menu.addMenuitem(menuitem) parent.takeChild(i) self.addTreeItem(menuitem) break self.updateButtonStates() self.menuChanged.emit( self.getUndoRedoText(menuitem, "changed to top item")) def iconClicked(self, itemselector, button): mi = itemselector.item() action = "" if button == Qt.LeftButton: fileName = "" dialog = QFileDialog() dialog.setFileMode(QFileDialog.AnyFile) dialog.setNameFilter("Images (*.png *.gif *.jpg)All (*)") dialog.setWindowTitle("Load Image") dialog.setOption(QFileDialog.DontUseNativeDialog, True) dialog.setAcceptMode(QFileDialog.AcceptOpen) if dialog.exec_(): fileName = dialog.selectedFiles().first() del dialog if not fileName: return # copy file to assets dir info = QFileInfo(fileName) name = info.fileName().replace(" ", "_") path = self.site.source_path + "/assets/images/" + name QFile.copy(fileName, path) # also copy file to deploy dir for previews dpath = self.site.deploy_path + "/assets/images/" + name QFile.copy(fileName, dpath) mi.setIcon(path.mid(path.indexOf("assets/images/"))) itemselector.setImage(QImage(path)) action = "icon changed" elif button == Qt.RightButton: action = "icon removed" mi.setIcon("") itemselector.setImage(QImage(":/images/image_placeholder.png")) self.menuChanged.emit(self.getUndoRedoText(mi, action)) def updateButtonStates(self): for i in range(0, self.tree.topLevelItemCount()): twi = self.tree.topLevelItem(i) tcb = self.tree.itemWidget(twi, 3) menuitem = twi.data(0, Qt.UserRole) tcb.setEnableDown(i != self.tree.topLevelItemCount() - 1) tcb.setEnableUp(i != 0) tcb.setEnableRight(i != 0 and len(menuitem.items) == 0) tcb.setEnableLeft(False) for j in range(0, twi.childCount()): stwi = twi.child(j) stcb = self.tree.itemWidget(stwi, 3) stcb.setEnableLeft(True)
class ContentEditor(AnimateableEditor): contentChanged = pyqtSignal(object) preview = pyqtSignal(object) def __init__(self, win, site, content): AnimateableEditor.__init__(self) self.win = win self.site = site self.content = content self.is_new = False self.editor = None self.undoStack = QUndoStack() self.changed = False self.setAutoFillBackground(True) self.previewLink = HyperLink("") self.vbox = QVBoxLayout() self.layout = QGridLayout() self.titleLabel = QLabel() fnt = self.titleLabel.font() fnt.setPointSize(20) fnt.setBold(True) self.titleLabel.setFont(fnt) self.script = QPushButton("Page Script") self.title = QLineEdit() self.source = QLineEdit() self.source.setPlaceholderText("*.qml") self.excerpt = QLineEdit() self.date = QLineEdit() self.labelPermalink = QLabel("Permalink") self.labelTitle = QLabel("Title") self.labelAuthor = QLabel("Author") self.labelKeyword = QLabel("Keywords") self.labelLayout = QLabel("Layout") self.labelMenu = QLabel("Menu") self.author = QLineEdit() self.keywords = QLineEdit() self.menus = QComboBox() self.layouts = QComboBox() self.layouts.setMaximumWidth(100) for menu in self.site.menus.menus: self.menus.addItem(menu.name) for root, dirs, files in os.walk( os.path.join(self.site.source_path, "layouts")): for file in files: self.layouts.addItem(Path(file).stem) for root, dirs, files in os.walk( os.path.join(Generator.themesPath(), self.site.theme, "layouts")): for file in files: self.layouts.addItem(Path(file).stem) self.close = FlatButton(":/images/close_normal.png", ":/images/close_hover.png") self.close.setToolTip("Close Content Editor") self.undo = FlatButton(":/images/undo_normal.png", ":/images/undo_hover.png", "", ":/images/undo_disabled.png") self.redo = FlatButton(":/images/redo_normal.png", ":/images/redo_hover.png", "", ":/images/redo_disabled.png") self.undo.setToolTip("Undo") self.redo.setToolTip("Redo") self.undo.setEnabled(False) self.redo.setEnabled(False) hbox = QHBoxLayout() hbox.addWidget(self.undo) hbox.addWidget(self.redo) hbox.addWidget(self.close) self.scroll = QScrollArea() self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.scroll.setWidgetResizable(True) self.scroll.installEventFilter(self) self.layout.addWidget(self.titleLabel, 0, 0) self.layout.addWidget(self.previewLink, 0, 1) self.layout.addLayout(hbox, 0, 3) self.layout.addWidget(self.labelTitle, 1, 0) self.layout.addWidget(self.title, 2, 0) self.layout.addWidget(self.labelPermalink, 1, 1) self.layout.addWidget(self.source, 2, 1) self.layout.addWidget(self.labelAuthor, 3, 0) self.layout.addWidget(self.author, 4, 0) self.layout.addWidget(self.labelKeyword, 3, 1) self.layout.addWidget(self.keywords, 4, 1) self.layout.addWidget(self.labelMenu, 3, 2) self.layout.addWidget(self.menus, 4, 2) self.layout.addWidget(self.labelLayout, 3, 3) self.layout.addWidget(self.layouts, 4, 3) self.layout.addWidget(self.scroll, 7, 0, 1, 4) self.layout.addWidget(self.script, 8, 0, 1, 4) self.vbox.addLayout(self.layout) self.setLayout(self.vbox) if self.content.content_type == ContentType.POST: self.previewLink.setText("view post") self.excerptLabel = QLabel("Excerpt") self.layout.addWidget(self.excerptLabel, 5, 0) self.layout.addWidget(self.excerpt, 6, 0, 1, 2) self.datelabel = QLabel("Date") self.layout.addWidget(self.datelabel, 5, 2) self.layout.addWidget(self.date, 6, 2, 1, 2) self.filename = self.site.source_path + "/posts/" + content.source else: self.previewLink.setText("view page") self.filename = self.site.source_path + "/pages/" + content.source self.load() self.close.clicked.connect(self.closeEditor) self.title.editingFinished.connect(self.titleFinished) self.title.textChanged.connect(self.titleChanged) self.source.editingFinished.connect(self.sourceChanged) self.excerpt.editingFinished.connect(self.excerptChanged) self.date.editingFinished.connect(self.dateChanged) self.author.editingFinished.connect(self.authorChanged) self.keywords.editingFinished.connect(self.keywordsChanged) self.menus.currentTextChanged.connect(self.menuChanged) self.layouts.currentTextChanged.connect(self.layoutChanged) self.undoStack.canUndoChanged.connect(self.canUndoChanged) self.undoStack.canRedoChanged.connect(self.canRedoChanged) self.undoStack.undoTextChanged.connect(self.undoTextChanged) self.undoStack.redoTextChanged.connect(self.redoTextChanged) self.undo.clicked.connect(self.undoAction) self.redo.clicked.connect(self.redoAction) self.previewLink.clicked.connect(self.previewPage) self.script.clicked.connect(self.scriptClicked) def scriptClicked(self): self.editor = Plugins.element_plugins["TextEditor"] self.editor.setContent(None) self.editor.setText(self.content.script) self.editor.setCaption("Page Script") self.editor.close.connect(self.scriptEditorClose) self.animate(self.scroll.widget().placeholder) def scriptEditorClose(self): if self.editor and self.editor.changed: self.content.script = self.editor.getText() self.editChanged("Update Script") self.editor.close.disconnect() self.editorClosed() def previewPage(self): self.preview.emit(self.content) def rowEdit(self, re): from widgets.rowpropertyeditor import RowPropertyEditor self.row_editor = re self.editor = RowPropertyEditor() self.editor.setRow(re.row) self.editor.close.connect(self.rowEditorClose) self.animate(re) def rowEditorClose(self): if self.editor and self.editor.changed: self.row_editor.load(self.editor.row) self.editChanged("Update Row") self.editor.close.disconnect() self.editorClosed() def canUndoChanged(self, can): self.undo.setEnabled(can) def canRedoChanged(self, can): self.redo.setEnabled(can) def undoTextChanged(self, text): self.undo.setToolTip("Undo " + text) def redoTextChanged(self, text): self.redo.setToolTip("Redo " + text) def undoAction(self): self.undoStack.undo() def redoAction(self): self.undoStack.redo() def menuChanged(self, menu): if menu != self.content.menu: self.content.menu = menu self.contentChanged.emit(self.content) self.editChanged("Menu Changed") def layoutChanged(self, layout): if layout != self.content.layout: self.content.layout = layout self.contentChanged.emit(self.content) self.editChanged("Layout Changed") def keywordsChanged(self): if self.keywords.text() != self.content.keywords: self.content.keywords = self.keywords.text() self.contentChanged.emit(self.content) self.editChanged("Keywords Changed") def authorChanged(self): if self.author.text() != self.content.author: self.content.author = self.author.text() self.contentChanged.emit(self.content) self.editChanged("Author Changed") def excerptChanged(self): if self.excerpt.text() != self.content.excerpt: self.content.excerpt = self.excerpt.text() self.contentChanged.emit(self.content) self.editChanged("Excerpt Changed") def dateChanged(self): if self.date.text() != self.content.date.toString("dd.MM.yyyy"): self.content.date = QDate.fromString(self.date.text(), "dd.MM.yyyy") self.contentChanged.emit(self.content) self.editChanged("Date Changed") def sourceChanged(self): if self.source.text() != self.content.source: oldname = self.filename self.content.source = self.source.text() if self.content.content_type == ContentType.PAGE: self.filename = self.site.source_path + "/pages/" + self.content.source else: self.filename = self.site.source_path + "/posts/" + self.content.source self.contentChanged.emit(self.content) renameCommand = RenameContentCommand(self, oldname, self.filename, "content file renamed") self.undoStack.push(renameCommand) def titleChanged(self, title): if self.is_new: source = title.lower().replace(" ", "_") + ".qml" self.source.setText(source) def titleFinished(self): if self.title.text() != self.content.title: if self.is_new: self.sourceChanged() self.content.title = self.title.text() self.contentChanged.emit(self.content) self.editChanged("Titel Changed") def sectionEdit(self, se): self.section_editor = se self.editor = SectionPropertyEditor() self.editor.setSection(se.section) self.editor.close.connect(self.sectionEditorClose) self.animate(se) def sectionEditorClose(self): if self.editor.changed: self.section_editor.setSection(self.editor.section) self.editChanged("Update Section") self.editor.close.disconnect() self.editorClosed() def load(self): from widgets.sectioneditor import SectionEditor self.content = self.site.loadContent(self.content.source, self.content.content_type) self.is_new = not self.content.title self.title.setText(self.content.title) self.source.setText(self.content.source) self.author.setText(self.content.author) self.keywords.setText(self.content.keywords) self.menus.setCurrentText(self.content.menu) self.layouts.setCurrentText(self.content.layout) if self.content.content_type == ContentType.POST: self.excerpt.setText(self.content.excerpt) self.date.setText(self.content.date.toString("dd.MM.yyyy")) pe = PageEditor() self.scroll.setWidget(pe) for item in self.content.items: if isinstance(item, Section): se = SectionEditor(item.fullwidth) se.load(item) pe.addSection(se) # todo other types def siteLoaded(self, site): self.site = site if self.content.contentType == ContentType.PAGE: for c in self.site.pages: if c.source == self.content.source: self.title.setText(c.title) else: for c in self.site.posts: if c.source == self.content.source: self.excerpt.setText(c.excerpt) self.title.setText(c.title) def closeEditor(self): if self.editor: self.editor.closeEditor() self.closes.emit() def elementEdit(self, ee): self.element_editor = ee plugin_name = "" if ee.type: plugin_name = Plugins.getElementPluginByTagname(ee.type) if plugin_name: self.editor = Plugins.element_plugins[plugin_name] else: self.editor = Plugins.element_plugins["TextEditor"] self.editor.setCaption("Text Module") self.editor.site = self.site self.editor.setContent(ee.getContent()) self.editor.close.connect(self.editorClose) self.animate(ee) def animate(self, widget): self.sourcewidget = widget pos = widget.mapTo(self.scroll, QPoint(0, 0)) self.editor.setParent(self.scroll) self.editor.move(pos) self.editor.resize(widget.size()) self.editor.show() self.animationgroup = QParallelAnimationGroup() self.animx = QPropertyAnimation() self.animx.setDuration(300) self.animx.setStartValue(pos.x()) self.animx.setEndValue(0) self.animx.setTargetObject(self.editor) self.animx.setPropertyName("x".encode("utf-8")) self.animationgroup.addAnimation(self.animx) self.animy = QPropertyAnimation() self.animy.setDuration(300) self.animy.setStartValue(pos.y()) self.animy.setEndValue(0) self.animy.setTargetObject(self.editor) self.animy.setPropertyName("y".encode("utf-8")) self.animationgroup.addAnimation(self.animy) self.animw = QPropertyAnimation() self.animw.setDuration(300) self.animw.setStartValue(widget.size().width()) self.animw.setEndValue(self.scroll.size().width()) self.animw.setTargetObject(self.editor) self.animw.setPropertyName("width".encode("utf-8")) self.animationgroup.addAnimation(self.animw) self.animh = QPropertyAnimation() self.animh.setDuration(300) self.animh.setStartValue(widget.size().height()) self.animh.setEndValue(self.scroll.size().height()) self.animh.setTargetObject(self.editor) self.animh.setPropertyName("height".encode("utf-8")) self.animationgroup.addAnimation(self.animh) self.animationgroup.finished.connect(self.animationFineshedZoomIn) self.animationgroup.start() def animationFineshedZoomIn(self): self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.title.setEnabled(False) self.author.setEnabled(False) self.keywords.setEnabled(False) self.menus.setEnabled(False) self.layouts.setEnabled(False) self.labelAuthor.setEnabled(False) self.labelKeyword.setEnabled(False) self.labelMenu.setEnabled(False) self.labelLayout.setEnabled(False) self.labelTitle.setEnabled(False) self.labelPermalink.setEnabled(False) self.previewLink.hide() self.undo.hide() self.redo.hide() self.close.hide() self.source.setEnabled(False) if self.content.content_type == ContentType.POST: self.excerpt.setEnabled(False) self.excerptLabel.setEnabled(False) self.animationgroup.finished.disconnect(self.animationFineshedZoomIn) def editorClose(self): if self.editor.changed: self.element_editor.setContent(self.editor.getContent()) self.editChanged("Update Element") self.editor.close.disconnect() self.editorClosed() def editorClosed(self): self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) pos = self.sourcewidget.mapTo(self.scroll, QPoint(0, 0)) # correct end values in case of resizing the window self.animx.setStartValue(pos.x()) self.animy.setStartValue(pos.y()) self.animw.setStartValue(self.sourcewidget.size().width()) self.animh.setStartValue(self.sourcewidget.size().height()) self.animationgroup.setDirection(QAbstractAnimation.Backward) self.animationgroup.finished.connect(self.animationFineshedZoomOut) self.animationgroup.start() def animationFineshedZoomOut(self): from widgets.rowpropertyeditor import RowPropertyEditor from widgets.sectionpropertyeditor import SectionPropertyEditor self.title.setEnabled(True) self.source.setEnabled(True) self.author.setEnabled(True) self.keywords.setEnabled(True) self.menus.setEnabled(True) self.layouts.setEnabled(True) self.labelAuthor.setEnabled(True) self.labelKeyword.setEnabled(True) self.labelMenu.setEnabled(True) self.labelLayout.setEnabled(True) self.labelTitle.setEnabled(True) self.labelPermalink.setEnabled(True) self.previewLink.show() self.undo.show() self.redo.show() self.close.show() if self.content.content_type == ContentType.POST: self.excerpt.setEnabled(True) self.excerptLabel.setEnabled(True) del self.animationgroup self.editor.hide() # parent has to be set to NULL, otherwise the plugin will be dropped by parent self.editor.setParent(None) # only delete Row- and SectionPropertyEditor the other editors are plugins if isinstance(self.editor, RowPropertyEditor): del self.editor elif isinstance(self.editor, SectionPropertyEditor): self.editor.close.disconnect(self.sectionEditorClose) del self.editor self.editor = None def editChanged(self, text): changeCommand = ChangeContentCommand(self.win, self, text) self.undoStack.push(changeCommand) def save(self): self.content.save(self.filename) def contentRenamed(self, name): self.filename = name base = os.path.basename(name) self.source.setText(base) self.content.source = base