407 lines
15 KiB
Python
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)
|
|
|