This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/shared/gcurses/Rubrics.py

407 lines
15 KiB
Python

# -*- coding: iso-8859-15 -*-
# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
# Romain Chantereau <rchantereau@entrouvert.com>
# Nicolas Clapiès <nclapies@easter-eggs.org>
# Pierre-Antoine Dejace <padejace@entrouvert.be>
# Thierry Dulieu <tdulieu@easter-eggs.com>
# Florent Monnier <monnier@codelutin.com>
# Cédric Musso <cmusso@easter-eggs.org>
# Frédéric Péters <fpeters@entrouvert.be>
# Benjamin Poussin <poussin@codelutin.com>
# Emmanuel Raviart <eraviart@entrouvert.com>
# Sébastien Régnier <regnier@codelutin.com>
# Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
# Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
# Régnier, Emmanuel Saracco, Théridion & Vecam
#
# This program 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 2
# of the License, or (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from glasnost.common.tools import *
import glasnost.common.tools_new as commonTools
from glasnost.proxy.tools import getProxyForServerRole, getProxy
from glasnost.web.WebAPI import GlasnostObject
from ObjectsCurses import CursesScreen
from tools import *
import curses
class CursesHierRubric:
def __init__(self, rubric, level):
self.rubric = rubric
self.level = level
self.expanded = 1
if not hasattr(self.rubric, 'membersSet') or not self.rubric.membersSet:
self.rubric.membersSet = []
if not hasattr(self.rubric, 'contentId'):
self.rubric.contentId = None
class RubricsScreen(CursesScreen):
def __init__(self, stdscr):
CursesScreen.__init__(self, stdscr)
self.loadRubrics()
self.keys = {
curses.KEY_UP: [ self.handleUp, 'Haut' ],
curses.KEY_DOWN: [ self.handleDown, 'Bas' ],
curses.KEY_LEFT: [ self.handleLeft, 'Vers la gauche' ],
curses.KEY_RIGHT: [ self.handleRight,'Vers la droite' ],
'k': [ self.moveDown, 'Descendre sélection' ],
'j': [ self.moveUp, 'Monter sélection' ],
'w': [ self.write, 'Enregistrer' ],
'q': [ self.quit, 'Quitter' ],
'E': [ self.editContent,'Créer/Éditer article \'contentId\'' ],
'v': [ self.viewRubric, 'Vue rubrique' ],
}
self.topLine = 0
self.selectedLine = 0
def buildHier(self, rubric, level):
if rubric in [x.rubric for x in self.rubrics]:
cR = CursesHierRubric(rubric, level)
cR.expanded = 0
self.rubrics.append(cR)
return
self.rubrics.append( CursesHierRubric(rubric, level) )
if not hasattr(rubric, 'membersSet'):
return
for r in rubric.membersSet:
if splitId(r)[1] != 'rubrics':
continue
r = [ x for x in self.rubricsL if x.id == r ][0]
self.buildHier(r, level+1)
def loadRubrics(self):
rubricsProxy = getProxyForServerRole('rubrics')
try:
self.mainRubric = rubricsProxy.getMainObject()
except faults.MissingMainRubric:
self.mainRubric = None
self.rubricsL = rubricsProxy.getObjects().values()
self.rubrics = []
if self.mainRubric:
self.buildHier(self.mainRubric, -1)
del self.rubrics[0]
for r in self.rubricsL:
if r.id in [ x.rubric.id for x in self.rubrics ] or \
self.mainRubric and r.id == self.mainRubric.id:
continue
self.rubrics.append( CursesHierRubric(r, -1) )
def view(self, height, width):
self.height = height
if len(self.rubrics) == 0:
return
currentRubric = self.rubrics[self.selectedLine]
for i, r in zip(range(height-4),
self.rubrics[self.topLine:self.topLine+height-4]):
options = 0
if r is currentRubric:
options = curses.color_pair(2) | curses.A_BOLD
state = (r.expanded and ' ') or '+'
if r.level == -1:
name = '!%c %s' % (state, r.rubric.name)
else:
name = ' %c %s%s' % (state, ' '*r.level, r.rubric.name)
self.stdscr.addstr(1+i, 0, name.ljust(width), options)
statusLine = '%s %s' % (
currentRubric.rubric.id.ljust(width-17),
(currentRubric.rubric.contentId and \
'contentId: %3d' % int(splitId(currentRubric.rubric.contentId)[2]))
or '')
self.stdscr.addstr(height-1, 0, statusLine.ljust(width-1))
def handleUp(self):
if self.selectedLine == 0:
return
self.selectedLine -= 1
if self.selectedLine - self.topLine < 0:
self.topLine -= 1
def handleDown(self):
if self.selectedLine+1 == len(self.rubrics):
return
self.selectedLine += 1
if self.selectedLine - self.topLine >= self.height-1:
self.topLine += 1
def handleLeft(self):
currentRubric = self.rubrics[self.selectedLine]
currentIndent = currentRubric.level
if currentIndent == -1:
return
if self.selectedLine != len(self.rubrics)-1 and \
self.rubrics[self.selectedLine+1].level > currentIndent:
return # cancelled (next line has greater indent)
wantedIndent = currentIndent - 1
if wantedIndent == -1:
# back to the end
l = len(self.rubrics)
self.rubrics.append(currentRubric)
del self.rubrics[self.selectedLine]
currentRubric.level = wantedIndent
def handleRight(self):
currentRubric = self.rubrics[self.selectedLine]
currentIndent = currentRubric.level
if currentIndent == -1:
i = 0
while i < len(self.rubrics) and self.rubrics[i].level > -1:
i += 1
self.rubrics[i], self.rubrics[self.selectedLine] = \
self.rubrics[self.selectedLine], self.rubrics[i]
currentRubric.level = 0
return
if self.selectedLine == 0 and currentIndent != -1:
return
if self.rubrics[self.selectedLine-1].level < currentIndent:
return
currentRubric.level += 1
def saveLevel(self, r, start, indent):
i = start
if not hasattr(r, 'membersSet'):
r.membersSet = []
r.membersSet = [ x for x in r.membersSet if splitId(x)[1] != 'rubrics' ]
for r2 in self.rubrics[start:]:
i += 1
if r2.level == indent:
r.membersSet.append(r2.rubric.id)
if not r2.expanded:
continue
self.saveLevel(r2.rubric, i, indent+1)
if r2.level < indent:
break
def write(self):
rubricsProxy = getProxyForServerRole('rubrics')
if self.mainRubric:
self.saveLevel(self.mainRubric, 0, 0)
for r in [self.mainRubric] + [x.rubric for x in self.rubrics]:
if not r:
continue
rubricsProxy.modifyObject(r)
def quit(self):
context.setVar('screens', context.getVar('screens')[:-1])
def moveDown(self):
i = self.selectedLine
currentRubric = self.rubrics[i]
if currentRubric.level == -1:
return
if i == len(self.rubrics)-1 or self.rubrics[i+1].level == -1:
return
self.rubrics[i], self.rubrics[i+1] = self.rubrics[i+1], self.rubrics[i]
self.selectedLine = i+1
if self.selectedLine == len(self.rubrics)-1:
currentRubric.level = 0
else:
currentRubric.level = self.rubrics[i].level
def moveUp(self):
currentRubric = self.rubrics[self.selectedLine]
if currentRubric.level == -1:
return
if self.selectedLine == 0:
return
i = self.selectedLine
self.rubrics[i], self.rubrics[i-1] = self.rubrics[i-1], self.rubrics[i]
self.selectedLine = i-1
if self.selectedLine == 0:
currentRubric.level = 0
else:
currentRubric.level = self.rubrics[i].level
def editContent(self):
currentRubric = self.rubrics[self.selectedLine]
if currentRubric.rubric.contentId:
articleId = currentRubric.rubric.contentId
proxy = getProxy(articleId)
article = proxy.getObject(articleId)
newBody = editText(article.body)
if newBody != article.body:
article.body = newBody
proxy.modifyObject(article)
else:
article = commonTools.newThing('object', 'articles.Article')
article.language = 'fr'
article.title = currentRubric.rubric.name
article.authorsSet = context.getVar('userId')
article.writersSet = [ article.authorsSet ]
article.format = 'spip'
article.body = editText()
if article.body:
currentRubric.rubric.contentId = proxy.addObject(article)
def viewRubric(self):
currentRubric = self.rubrics[self.selectedLine]
context.getVar('screens').append(RubricScreen(currentRubric.rubric, self.stdscr))
class RubricScreen(CursesScreen):
tabIndex = -1
def __init__(self, rubric, stdscr):
CursesScreen.__init__(self, stdscr)
self.keys = {
curses.KEY_UP: [ self.handleUp, 'Haut'],
curses.KEY_DOWN: [ self.handleDown, 'Bas'],
'e': [ self.edit, 'Éditer' ],
'\t': [ self.handleTab, '' ],
'\n': [ self.handleEnter, '' ],
'N': [ self.changePageName, 'Changement nom de page'],
'T': [ self.changePageNameArticle, 'idem pour article'],
'q': [ self.quit, 'Quitter' ],
}
self.rubric = rubric
self.objects = [ GlasnostObject(x) for x in rubric.membersSet \
if splitId(x)[1] != 'rubrics' ]
height, width = self.stdscr.getmaxyx()
for i in range(1, height-3):
self.stdscr.addstr(i, 0, ' '*width)
self.topLine = 0
self.selectedLine = 0
def view(self, height, width):
self.height = height
self.width = width
name = ' Nom: %s' % self.rubric.name
self.stdscr.addstr(2, 0, name.ljust(width))
if self.tabIndex == 0:
self.stdscr.addstr(2, 0, 'o', curses.A_BOLD)
else:
self.stdscr.addstr(2, 0, ' ', curses.A_BOLD)
if not self.objects:
self.stdscr.addstr(height-1, width-1, '')
self.stdscr.addstr(self.height-1, 0, ' '*(self.width-1))
return
currentObject = self.objects[self.selectedLine]
for i, o in zip(range(height-7),
self.objects[self.topLine:self.topLine+height-7]):
name = ' %s' % o.label
options = 0
if i == self.selectedLine:
options = curses.color_pair(2) | curses.A_BOLD
self.stdscr.addstr(4+i, 0, name.ljust(width), options)
self.stdscr.addstr(height-1, 0, currentObject.id.ljust(width-1))
def quit(self):
context.setVar('screens', context.getVar('screens')[:-1])
def handleUp(self):
if self.selectedLine == 0:
return
self.selectedLine -= 1
if self.selectedLine - self.topLine < 0:
self.topLine -= 1
def handleDown(self):
if self.selectedLine+1 == len(self.objects):
return
self.selectedLine += 1
if self.selectedLine - self.topLine >= self.height-1:
self.topLine += 1
def edit(self):
currentObject = self.objects[self.selectedLine]
articleId = currentObject.objectId
proxy = getProxy(articleId)
article = proxy.getObject(articleId)
newBody = editText(article.body)
if newBody != article.body:
article.body = newBody
proxy.modifyObject(article)
def handleTab(self):
# should be moved to a parent class
if self.tabIndex == -1:
self.tabIndex = 0
else:
self.tabIndex += 1
if self.tabIndex > 0:
self.tabIndex = 0
def handleEnter(self):
if self.tabIndex == 0:
self.stdscr.addstr(self.height-1, 0, 'Nouveau nom: '.ljust(self.width-1))
curses.echo()
name = self.stdscr.getstr(self.height-1, 13, 40)
curses.noecho()
if name:
self.rubric.name = name
def changePageName(self):
pagenameProxy = getProxyForServerRole('pagenames')
pagename = commonTools.newThing('object', 'pagenames.PageName')
self.stdscr.addstr(self.height-1, 0, 'Nom de page: '.ljust(self.width-1))
curses.echo()
pagename.name = self.stdscr.getstr(self.height-1, 13, 40)
curses.noecho()
pagename.mappedId = self.rubric.id
pagenameId = pagenameProxy.addObject(pagename)
def changePageNameArticle(self):
currentObject = self.objects[self.selectedLine]
pagenameProxy = getProxyForServerRole('pagenames')
pagename = commonTools.newThing('object', 'pagenames.PageName')
self.stdscr.addstr(self.height-1, 0, 'Nom de page: '.ljust(self.width-1))
curses.echo()
pagename.name = self.stdscr.getstr(self.height-1, 13, 40)
curses.noecho()
pagename.mappedId = currentObject.id
pagenameId = pagenameProxy.addObject(pagename)