diff options
author | Xisco Fauli <anistenis@gmail.com> | 2011-07-21 19:24:50 +0200 |
---|---|---|
committer | Bjoern Michaelsen <bjoern.michaelsen@canonical.com> | 2011-08-18 02:57:43 +0200 |
commit | 89b7d1ae9e37b76a0e234cb5daa4e48104ab0c58 (patch) | |
tree | 9b1323ddc9d9f9309909fff82c3677052517849f /wizards/com | |
parent | 80fc1ff50180c7779014b5f060fb6db4ec06a63c (diff) |
First attempt to create the Agenda Wizard
the Document preview and the wizard are already shown
Diffstat (limited to 'wizards/com')
23 files changed, 3831 insertions, 123 deletions
diff --git a/wizards/com/sun/star/wizards/RemoteAgendaWizard b/wizards/com/sun/star/wizards/RemoteAgendaWizard new file mode 100755 index 000000000000..996ad35e4e76 --- /dev/null +++ b/wizards/com/sun/star/wizards/RemoteAgendaWizard @@ -0,0 +1,6 @@ +#!/usr/bin/env python +from agenda.AgendaWizardDialogImpl import AgendaWizardDialogImpl +import sys + +if __name__ == "__main__": + AgendaWizardDialogImpl.main(sys.argv) diff --git a/wizards/com/sun/star/wizards/agenda/AgendaTemplate.py b/wizards/com/sun/star/wizards/agenda/AgendaTemplate.py new file mode 100644 index 000000000000..274da3e67eeb --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaTemplate.py @@ -0,0 +1,1191 @@ +from text.TextDocument import * +from uno import Any +from TemplateConsts import * +from common.FileAccess import FileAccess +from common.Helper import Helper +from com.sun.star.i18n.NumberFormatIndex import TIME_HHMM, DATE_SYSTEM_LONG +from text.TextSectionHandler import TextSectionHandler +from com.sun.star.text.PlaceholderType import TEXT +from TopicsControl import TopicsControl +from threading import RLock + +def synchronized(lock): + ''' Synchronization decorator. ''' + def wrap(f): + def newFunction(*args, **kw): + lock.acquire() + try: + return f(*args, **kw) + finally: + lock.release() + return newFunction + return wrap + +''' +The classes here implement the whole document-functionality of the agenda wizard: +the live-preview and the final "creation" of the document, when the user clicks "finish". <br/> +<br/> +<h2>Some terminology:<h2/> +items are names or headings. we don't make any distinction. + +<br/> +The Agenda Template is used as general "controller" of the whole document, whereas the +two child-classes ItemsTable and TopicsTable control the item tables (note plural!) and the +topics table (note singular). +<br/> <br/> +Other small classes are used to abstract the handling of cells and text and we +try to use them as components. +<br/><br/> +We tried to keep the Agenda Template as flexible as possible, though there +must be many limitations, because it is generated dynamically.<br/><br/> +To keep the template flexible the following decisions were made:<br/> +1. Item tables.<br/> +1.a. there might be arbitrary number of Item tables.<br/> +1.b. Item tables design (bordewr, background) is arbitrary.<br/> +1.c. Items text styles are individual, and use stylelist styles with predefined names.<br/> +As result the following limitations:<br/> +Pairs of Name->value for each item.<br/> +Tables contain *only* those pairs.<br/> +2. Topics table.<br/> +2.a. arbitrary structure.<br/> +2.b. design is arbitrary.<br/> +As result the following limitations:<br/> +No column merge is allowed.<br/> +One compolsary Heading row.<br/> +<br/><br/> +To let the template be flexible, we use a kind of "detection": we look where +the items are read the design of each table, reaplying it after writing the +table.AgendaTemplate.document +<br/><br/> +A note about threads:<br/> +Many methods here are synchronized, in order to avoid colission made by +events fired too often. +@author rpiterman +''' +class AgendaTemplate(TextDocument): + + DAY_IN_MILLIS = (24 * 60 * 60 * 1000) + writtenTopics = [] + itemsCache = None + _allItems = [] + items = [] + itemsMap = {} + document = None + textSectionHandler = None + template = None + agenda = None + lock = RLock() + + + '''constructor. The document is *not* loaded here. + only some formal members are set. + @param AgendaTemplate.document_ service factory. + @param agenda_ the data model (CGAgenda) + @param resources_ resources. + ''' + + def __init__(self, xmsf_, agenda_, resources_, listener): + super(AgendaTemplate,self).__init__(xmsf_,listener, None, + "WIZARD_LIVE_PREVIEW") + AgendaTemplate.agenda = agenda_ + self.resources = resources_ + if AgendaTemplate.itemsCache is None: + self.initItemsCache() + + AgendaTemplate._allItems = None + + @synchronized(lock) + def load(self, templateURL, topics): + AgendaTemplate.template = self.calcTemplateName(templateURL) + AgendaTemplate.document = self.loadAsPreview(templateURL, False) + self.xFrame.ComponentWindow.Enable = False + self.xTextDocument.lockControllers() + self.initialize() + self.initializeData(topics) + self.xTextDocument.unlockControllers() + + ''' + The agenda templates are in format of aw-XXX.ott + the templates name is then XXX.ott. + This method calculates it. + @param url + @return the template name without the "aw-" at the beginning. + ''' + + def calcTemplateName(self, url): + return FileAccess.connectURLs(FileAccess.getParentDir(url), FileAccess.getFilename(url)[3:]) + + '''synchronize the document to the model.<br/> + this method rewrites all titles, item tables , and the topics table- + thus synchronizing the document to the data model (CGAgenda). + @param topicsData since the model does not contain Topics + information (it is only actualized on save) the given list + supplies this information. + ''' + + def initializeData(self, topicsData): + for i in self.itemsTables: + try: + i.write("") + except Exception, ex: + traceback.print_exc() + + self.redrawTitle("txtTitle") + self.redrawTitle("txtDate") + self.redrawTitle("txtTime") + self.redrawTitle("cbLocation") + Topics.writeAll(topicsData) + if AgendaTemplate.agenda.cp_TemplateName is None: + AgendaTemplate.agenda.cp_TemplateName = "" + self.setTemplateTitle(AgendaTemplate.agenda.cp_TemplateName) + + '''redraws/rewrites the table which contains the given item + This method is called when the user checks/unchecks an item. + The table is being found, in which the item is, and redrawn. + @param itemName + ''' + + @synchronized(lock) + def redraw(self, itemName): + try: + # get the table in which the item is... + itemsTable = AgendaTemplate.itemsMap.get(itemName) + # rewrite the table. + itemsTable.write(None) + except Exception, e: + traceback.print_exc() + + '''update the documents title property to the given title + @param newTitle title. + ''' + + @synchronized(lock) + def setTemplateTitle(self, newTitle): + self.m_xDocProps.Title = newTitle + + '''checks the data model if the + item corresponding to the given string should be shown + @param itemName a string representing an Item (name or heading). + @return true if the model specifies that the item should be displayed. + ''' + + @classmethod + def isShowItem(self, itemName): + if itemName == FILLIN_MEETING_TYPE: + return AgendaTemplate.agenda.cp_ShowMeetingType + elif itemName == FILLIN_READ: + return AgendaTemplate.agenda.cp_ShowRead + elif itemName == FILLIN_BRING: + return AgendaTemplate.agenda.cp_ShowBring + elif itemName == FILLIN_NOTES: + return AgendaTemplate.agenda.cp_ShowNotes + elif itemName == FILLIN_FACILITATOR: + return AgendaTemplate.agenda.cp_ShowFacilitator + elif itemName == FILLIN_TIMEKEEPER: + return AgendaTemplate.agenda.cp_ShowTimekeeper + elif itemName == FILLIN_NOTETAKER: + return AgendaTemplate.agenda.cp_ShowNotetaker + elif itemName == FILLIN_PARTICIPANTS: + return AgendaTemplate.agenda.cp_ShowAttendees + elif itemName == FILLIN_CALLED_BY: + return AgendaTemplate.agenda.cp_ShowCalledBy + elif itemName == FILLIN_OBSERVERS: + return AgendaTemplate.agenda.cp_ShowObservers + elif itemName == FILLIN_RESOURCE_PERSONS: + return AgendaTemplate.agenda.cp_ShowResourcePersons + else: + raise ValueError("No such item") + + '''itemsCache is a Map containing all agenda item. These are object which + "write themselfs" to the table, given a table cursor. + A cache is used in order to reuse the objects, instead of recreate them. + This method fills the cache will all items objects (names and headings). + ''' + + def initItemsCache(self): + AgendaTemplate.itemsCache = {} + # Headings + AgendaTemplate.itemsCache[FILLIN_MEETING_TYPE] = AgendaItem(FILLIN_MEETING_TYPE, TextElement (self.resources.itemMeetingType, STYLE_MEETING_TYPE), PlaceholderElement(STYLE_MEETING_TYPE_TEXT, self.resources.reschkMeetingTitle_value, self.resources.resPlaceHolderHint, self.xMSF)) + AgendaTemplate.itemsCache[FILLIN_BRING] = AgendaItem(FILLIN_BRING, TextElement (self.resources.itemBring, STYLE_BRING), PlaceholderElement (STYLE_BRING_TEXT, self.resources.reschkBring_value, self.resources.resPlaceHolderHint, self.xMSF)) + AgendaTemplate.itemsCache[FILLIN_READ] = AgendaItem (FILLIN_READ, TextElement (self.resources.itemRead, STYLE_READ), PlaceholderElement (STYLE_READ_TEXT, self.resources.reschkRead_value, self.resources.resPlaceHolderHint, self.xMSF)) + AgendaTemplate.itemsCache[FILLIN_NOTES] = AgendaItem (FILLIN_NOTES, TextElement (self.resources.itemNote, STYLE_NOTES), PlaceholderElement (STYLE_NOTES_TEXT, self.resources.reschkNotes_value, self.resources.resPlaceHolderHint, self.xMSF)) + # Names + AgendaTemplate.itemsCache[FILLIN_CALLED_BY] = AgendaItem (FILLIN_CALLED_BY, TextElement (self.resources.itemCalledBy, STYLE_CALLED_BY), PlaceholderElement (STYLE_CALLED_BY_TEXT, self.resources.reschkConvenedBy_value, self.resources.resPlaceHolderHint, self.xMSF)) + AgendaTemplate.itemsCache[FILLIN_FACILITATOR] =AgendaItem (FILLIN_FACILITATOR, TextElement (self.resources.itemFacilitator, STYLE_FACILITATOR), PlaceholderElement (STYLE_FACILITATOR_TEXT, self.resources.reschkPresiding_value, self.resources.resPlaceHolderHint, self.xMSF)) + AgendaTemplate.itemsCache[FILLIN_PARTICIPANTS] = AgendaItem (FILLIN_PARTICIPANTS, TextElement (self.resources.itemAttendees, STYLE_PARTICIPANTS), PlaceholderElement (STYLE_PARTICIPANTS_TEXT, self.resources.reschkAttendees_value, self.resources.resPlaceHolderHint, self.xMSF)) + AgendaTemplate.itemsCache[FILLIN_NOTETAKER] = AgendaItem (FILLIN_NOTETAKER, TextElement (self.resources.itemNotetaker, STYLE_NOTETAKER), PlaceholderElement (STYLE_NOTETAKER_TEXT, self.resources.reschkNoteTaker_value, self.resources.resPlaceHolderHint, self.xMSF)) + AgendaTemplate.itemsCache[FILLIN_TIMEKEEPER] = AgendaItem (FILLIN_TIMEKEEPER, TextElement (self.resources.itemTimekeeper, STYLE_TIMEKEEPER), PlaceholderElement (STYLE_TIMEKEEPER_TEXT, self.resources.reschkTimekeeper_value, self.resources.resPlaceHolderHint, self.xMSF)) + AgendaTemplate.itemsCache[FILLIN_OBSERVERS] = AgendaItem (FILLIN_OBSERVERS, TextElement (self.resources.itemObservers, STYLE_OBSERVERS), PlaceholderElement (STYLE_OBSERVERS_TEXT, self.resources.reschkObservers_value, self.resources.resPlaceHolderHint, self.xMSF)) + AgendaTemplate.itemsCache[FILLIN_RESOURCE_PERSONS] = AgendaItem (FILLIN_RESOURCE_PERSONS, TextElement (self.resources.itemResource, STYLE_RESOURCE_PERSONS), PlaceholderElement (STYLE_RESOURCE_PERSONS_TEXT, self.resources.reschkResourcePersons_value, self.resources.resPlaceHolderHint, self.xMSF)) + + '''Initializes a template.<br/> + This method does the following tasks:<br/> + Get a Time and Date format for the document, and retrieve the null date of the document (which is + document-specific).<br/> + Initializes the Items Cache map. + Analyses the document:<br/> + -find all "fille-ins" (apear as >xxx< in the document). + -analyze all items sections (and the tables in them). + -locate the titles and actualize them + -analyze the topics table + ''' + + def initialize(self): + ''' + Get the default locale of the document, and create the date and time formatters. + ''' + dateUtils = Helper.DateUtils(self.xMSF, AgendaTemplate.document) + self.formatter = dateUtils.formatter + self.dateFormat = dateUtils.getFormat(DATE_SYSTEM_LONG) + self.timeFormat = dateUtils.getFormat(TIME_HHMM) + + ''' + get the document properties object. + ''' + + self.m_xDocProps = AgendaTemplate.document.DocumentProperties + self.initItemsCache() + AgendaTemplate._allItems = self.searchFillInItems() + self.initializeTitles() + self.initializeItemsSections() + AgendaTemplate.textSectionHandler = TextSectionHandler(AgendaTemplate.document, AgendaTemplate.document) + self.topics = Topics() + del AgendaTemplate._allItems[:] + AgendaTemplate._allItems = None + + ''' + locates the titles (name, location, date, time) and saves a reference to thier Text ranges. + ''' + + def initializeTitles(self): + i = 0 + while i < len(AgendaTemplate._allItems): + workwith = AgendaTemplate._allItems[i] + text = workwith.String.lstrip().lower() + if text == FILLIN_TITLE: + self.teTitle = PlaceholderTextElement(workwith, self.resources.resPlaceHolderTitle, self.resources.resPlaceHolderHint, AgendaTemplate.document) + self.trTitle = workwith + del AgendaTemplate._allItems[i] + i -= 1 + elif text == FILLIN_DATE: + self.teDate = PlaceholderTextElement(workwith, self.resources.resPlaceHolderDate, self.resources.resPlaceHolderHint, AgendaTemplate.document) + self.trDate = workwith + del AgendaTemplate._allItems[i] + i -= 1 + elif text == FILLIN_TIME: + self.teTime = PlaceholderTextElement(workwith, self.resources.resPlaceHolderTime, self.resources.resPlaceHolderHint, AgendaTemplate.document) + self.trTime = workwith + del AgendaTemplate._allItems[i] + i -= 1 + elif text == FILLIN_LOCATION: + self.teLocation = PlaceholderTextElement(workwith, self.resources.resPlaceHolderLocation, self.resources.resPlaceHolderHint, AgendaTemplate.document) + self.trLocation = workwith + del AgendaTemplate._allItems[i] + i -= 1 + i += 1 + + ''' + searches the document for items in the format ">*<" + @return a vector containing the XTextRanges of the found items + ''' + + def searchFillInItems(self): + try: + sd = AgendaTemplate.document.createSearchDescriptor() + sd.setSearchString("<[^>]+>") + sd.setPropertyValue("SearchRegularExpression", True) + sd.setPropertyValue("SearchWords", True) + ia = AgendaTemplate.document.findAll(sd) + try: + l = [ia.getByIndex(i) for i in xrange(ia.Count)] + except Exception, ex: + print "Nonfatal Error in finding fillins." + return l + except Exception, ex: + traceback.print_exc() + raise AttributeError ("Fatal Error: Loading template failed: searching fillins failed"); + + ''' + analyze the item sections in the template. delegates the analyze of each table to the + ItemsTable class. + ''' + + def initializeItemsSections(self): + sections = self.getSections(AgendaTemplate.document, SECTION_ITEMS) + # for each section - there is a table... + self.itemsTables = [] + for i in xrange(len(sections)): + try: + self.itemsTables.append(ItemsTable(self.getSection(sections[i]), self.getTable(sections[i]))) + except Exception, ex: + traceback.print_exc() + raise IllegalArgumentException ("Fatal Error while initialilzing Template: items table in section " + sections[i]); + + + def getSections(self, document, s): + allSections = document.TextSections.ElementNames + return self.getNamesWhichStartWith(allSections, s) + + @classmethod + def getSection(self, name): + return AgendaTemplate.document.TextSections.getByName(name) + + @classmethod + def getTable(self, name): + return AgendaTemplate.document.TextTables.getByName(name) + + ''' + implementation of DataAware.Listener, is + called when title/date/time or location are + changed. + ''' + + @synchronized(lock) + def eventPerformed(self, param): + controlName = Helper.getUnoPropertyValue(UnoDialog2.getModel(param.Source), PropertyNames.PROPERTY_NAME) + self.redrawTitle(controlName) + + @synchronized(lock) + def redrawTitle(self, controlName): + if controlName == "txtTitle": + self.writeTitle(self.teTitle, self.trTitle, AgendaTemplate.agenda.cp_Title) + elif controlName == "txtDate": + self.writeTitle(self.teDate, self.trDate, self.getDateString(AgendaTemplate.agenda.cp_Date)) + elif controlName == "txtTime": + self.writeTitle(self.teTime, self.trTime, self.getTimeString(AgendaTemplate.agenda.cp_Time)) + elif controlName == "cbLocation": + self.writeTitle(self.teLocation, self.trLocation, AgendaTemplate.agenda.cp_Location) + else: + raise IllegalArgumentException ("No such title control..."); + + def writeTitle(self, te, tr, text): + if text is None: + te.text = "" + else: + te.text = text + te.write(tr) + + def getDateString(self, d): + if d is None or d == "": + return "" + + date = Integer(d).intValue.intValue() + self.calendar.clear() + self.calendar.set(date / 10000, (date % 10000) / 100 - 1, date % 100) + date1 = JavaTools.getTimeInMillis(self.calendar) + ''' + docNullTime and date1 are in millis, but + I need a day... + ''' + daysDiff = (date1 - self.docNullTime) / self.__class__.DAY_IN_MILLIS + 1 + return self.formatter.convertNumberToString(self.dateFormat, daysDiff) + + def getTimeString(self, s): + if s == None or s == "": + return "" + + time = Integer(s).intValue.intValue() + t = ((double)(time / 1000000) / 24) + ((double)((time % 1000000) / 1000) / (24 * 60)) + return self.formatter.convertNumberToString(self.timeFormat, t) + + @synchronized(lock) + def finish(self, topics): + createMinutes(topics) + deleteHiddenSections() + AgendaTemplate.textSectionHandler.removeAllTextSections() + + ''' + hidden sections exist when an item's section is hidden because the + user specified not to display any items which it contains. + When finishing the wizard removes this sections entireley from the document. + ''' + + def deleteHiddenSections(self): + allSections = AgendaTemplate.document.TextSections.ElementNames + try: + for i in allSections: + self.section = getSection(i) + visible = bool(Helper.getUnoPropertyValue(self.section, "IsVisible")) + if not visible: + self.section.Anchor.String = "" + + except Exception, ex: + traceback.print_exc() + + ''' + create the minutes for the given topics or remove the minutes section from the document. + If no topics are supplied, or the user + specified not to create minuts, the minutes section will be removed, + @param topicsData supplies PropertyValue arrays containing the values for the topics. + ''' + + @synchronized(lock) + def createMinutes(self, topicsData): + # if the minutes section should be removed (the + # user did not check "create minutes") + if not AgendaTemplate.agenda.cp_IncludeMinutes or (topicsData.size() <= 1): + try: + minutesAllSection = getSection(SECTION_MINUTES_ALL) + minutesAllSection.Anchor.String = "" + except Exception, ex: + traceback.print_exc() + + # the user checked "create minutes" + else: + try: + topicStartTime = 0 + try: + topicStartTime = Integer(AgendaTemplate.agenda.cp_Time).intValue.intValue() + except Exception, ex: + pass + #first I replace the minutes titles... + AgendaTemplate.items = searchFillInItems() + itemIndex = 0 + while itemIndex < self.items.size(): + item = (XTextRange) + self.items.get(itemIndex) + itemText = item.getString().trim().toLowerCase() + if itemText == FILLIN_MINUTES_TITLE: + fillMinutesItem(item, AgendaTemplate.agenda.cp_Title, self.resources.resPlaceHolderTitle) + elif itemText == FILLIN_MINUTES_LOCATION: + fillMinutesItem(item, AgendaTemplate.agenda.cp_Location, self.resources.resPlaceHolderLocation) + elif itemText == FILLIN_MINUTES_DATE: + fillMinutesItem(item, getDateString(AgendaTemplate.agenda.cp_Date), self.resources.resPlaceHolderDate) + elif itemText == FILLIN_MINUTES_TIME: + fillMinutesItem(item, getTimeString(AgendaTemplate.agenda.cp_Time), self.resources.resPlaceHolderTime) + + itemIndex += 1 + self.items.clear() + ''' + now add minutes for each topic. + The template contains *one* minutes section, so + we first use the one available, and then add a one... + topics data has *always* an empty topic at the end... + ''' + + i = 0 + while i < topicsData.size() - 1: + topic = topicsData.get(i) + AgendaTemplate.items = searchFillInItems() + itemIndex = 0 + while itemIndex < self.items.size(): + item = (XTextRange) + self.items.get(itemIndex) + itemText = item.getString().trim().toLowerCase() + if itemText == FILLIN_MINUTE_NUM: + fillMinutesItem(item, topic[0].Value, "") + elif itemText == FILLIN_MINUTE_TOPIC: + fillMinutesItem(item, topic[1].Value, "") + elif itemText == FILLIN_MINUTE_RESPONSIBLE: + fillMinutesItem(item, topic[2].Value, "") + elif itemText == FILLIN_MINUTE_TIME: + topicTime = 0 + try: + topicTime = topic[3].Value + except Exception, ex: + pass + + # if the topic has no time, we do not display any time here. + if topicTime == 0 or topicStartTime == 0: + time = (String) + topic[3].Value + else: + time = getTimeString(String.valueOf(topicStartTime)) + " - " + topicStartTime += topicTime * 1000 + time += getTimeString(String.valueOf(topicStartTime)) + + fillMinutesItem(item, time, "") + + itemIndex += 1 + AgendaTemplate.textSectionHandler.removeTextSectionbyName(SECTION_MINUTES) + # after the last section we do not insert a one. + if i < topicsData.size() - 2: + AgendaTemplate.textSectionHandler.insertTextSection(SECTION_MINUTES, AgendaTemplate.template, False) + + i += 1 + except Exception, ex: + traceback.print_exc() + + '''given a text range and a text, fills the given + text range with the given text. + If the given text is empty, uses a placeholder with the giveb placeholder text. + @param range text range to fill + @param text the text to fill to the text range object. + @param placeholder the placeholder text to use, if the text argument is empty (null or "") + ''' + + def fillMinutesItem(self, range, text, placeholder): + paraStyle = Helper.getUnoPropertyValue(range, "ParaStyleName") + range.setString(text) + Helper.setUnoPropertyValue(range, "ParaStyleName", paraStyle) + if text == None or text == "": + if placeholder != None and not placeholder == "": + placeHolder = createPlaceHolder(AgendaTemplate.document, placeholder, self.resources.resPlaceHolderHint) + try: + range.getStart().getText().insertTextContent(range.getStart(), placeHolder, True) + except Exception, ex: + traceback.print_exc() + + '''creates a placeholder field with the given text and given hint. + @param AgendaTemplate.document service factory + @param ph place holder text + @param hint hint text + @return the place holder field. + ''' + + @classmethod + def createPlaceHolder(self, xmsf, ph, hint): + try: + placeHolder = xmsf.createInstance("com.sun.star.text.TextField.JumpEdit") + except Exception, ex: + traceback.print_exc() + return None + + Helper.setUnoPropertyValue(placeHolder, "PlaceHolder", ph) + Helper.setUnoPropertyValue(placeHolder, "Hint", hint) + Helper.setUnoPropertyValue(placeHolder, "PlaceHolderType", Any("short",TEXT)) + return placeHolder + + def getNamesWhichStartWith(self, allNames, prefix): + v = [] + for i in allNames: + if i.startswith(prefix): + v.append(i) + return v + + '''convenience method, for removing a number of cells from a table. + @param table + @param start + @param count + ''' + + @classmethod + def removeTableRows(self, table, start, count): + rows = table.Rows + rows.removeByIndex(start, count) + + '''Convenience method for inserting some cells into a table. + @param table + @param start + @param count + ''' + + @classmethod + def insertTableRows(self, table, start, count): + rows = table.Rows + rows.insertByIndex(start, count) + + '''returns the row index for this cell name. + @param cellName + @return the row index for this cell name. + ''' + + @classmethod + def getRowIndex(self, cellName): + return int(cellName.RangeName[1:]) + + '''returns the rows count of this table, assuming + there is no vertical merged cells. + @param table + @return the rows count of the given table. + ''' + + @classmethod + def getRowCount(self, table): + cells = table.getCellNames() + return int(cells[len(cells) - 1][1:]) + +class ItemsTable(object): + ''' + the items in the table. + ''' + + def __init__(self, section_, table_): + Topics.table = table_ + self.section = section_ + ''' + go through all <*> items in the document + and each one if it is in this table. + If they are, register them to belong here, notice their order + and remove them from the list of all <*> items, so the next + search will be faster. + ''' + i = 0 + while i < len(AgendaTemplate._allItems): + workwith = AgendaTemplate._allItems[i] + t = Helper.getUnoPropertyValue(workwith, "TextTable") + if t == Topics.table: + iText = workwith.String.lower().lstrip() + ai = AgendaTemplate.itemsCache.get(iText) + if ai is not None: + AgendaTemplate.items.append(ai) + del AgendaTemplate._allItems[i] + AgendaTemplate.itemsMap[iText] = self + i -= 1 + i += 1 + ''' + link the section to the template. this will restore the original table + with all the items.<br/> + then break the link, to make the section editable.<br/> + then, starting at cell one, write all items that should be visible. + then clear the rest and remove obsolete rows. + If no items are visible, hide the section. + @param dummy we need a param to make this an Implementation of AgendaElement. + @throws Exception + ''' + + def write(self, dummy): + with AgendaTemplate.lock: + name = self.section.Name + # link and unlink the section to the template. + AgendaTemplate.textSectionHandler.linkSectiontoTemplate(self.section, AgendaTemplate.template, name) + AgendaTemplate.textSectionHandler.breakLinkOfTextSection(self.section) + # we need to get a instance after linking. + Topics.table = AgendaTemplate.getTable(name) + self.section = AgendaTemplate.getSection(name) + cursor = Topics.table.createCursorByCellName("A1") + # should this section be visible? + visible = False + # write items + # =========== + cellName = "" + ''' + now go through all items that belong to this + table. Check each one agains the model. If it should + be display, call it's write method. + All items are of type AgendaItem which means they write + two cells to the table: a title (text) and a placeholder. + see AgendaItem class below. + ''' + for i in AgendaTemplate.items: + if AgendaTemplate.isShowItem(i.name): + visible = True + i.table = Topics.table + i.write(cursor) + # I store the cell name which was last written... + cellName = cursor.RangeName + cursor.goRight(1, False) + + if visible: + boolean = True + else: + boolean = False + Helper.setUnoPropertyValue(self.section, "IsVisible", boolean) + if not visible: + return + ''' + remove obsolete rows + ==================== + if the cell that was last written is the current cell, + it means this is the end of the table, so we end here. + (because after getting the cellName above, I call the goRight method. + If it did not go right, it means its the last cell. + ''' + + if cellName == cursor.RangeName: + return + ''' + if not, we continue and clear all cells until we are at the end of the row. + ''' + + while (not cellName == cursor.RangeName and (not cursor.RangeName.startswith("A"))): + cell = xTextTable.getCellByName(cursor.RangeName) + cell.String = "" + cellName = cursor.RangeName + cursor.goRight(1, False) + + ''' + again: if we are at the end of the table, end here. + ''' + if cellName == cursor.RangeName: + return + + rowIndex = AgendaTemplate.getRowIndex(cursor) + rowsCount = AgendaTemplate.getRowCount(Topics.table) + ''' + now before deleteing i move the cursor up so it + does not disappear, because it will crash office. + ''' + cursor.gotoStart(False) + if rowsCount >= rowIndex: + pass + #COMMENTED + #removeTableRows(Topics.table, rowIndex - 1, (rowsCount - rowIndex) + 1) + +''' +This class handles the preview of the topics table. +You can call it the controller of the topics table. +It differs from ItemsTable in that it has no data model - +the update is done programttically.<br/> +<br/> +The decision to make this class a class by its own +was done out of logic reasons and not design/functionality reasons, +since there is anyway only one instance of this class at runtime +it could have also be implemented in the AgendaTemplate class +but for clarity and separation I decided to make a sub class for it. + +@author rp143992 +''' + +class Topics(object): + '''Analyze the structure of the Topics table. + The structure Must be as follows:<br> + -One Header Row. <br> + -arbitrary number of rows per topic <br> + -arbitrary content in the topics row <br> + -only soft formatting will be restored. <br> + -the topic rows must repeat three times. <br> + -in the topics rows, placeholders for number, topic, responsible, and duration + must be placed.<br> + <br> + A word about table format: to reconstruct the format of the + table we hold to the following formats: first row (header), topic, and last row. + We hold the format of the last row, because one might wish to give it + a special format, other than the one on the bottom of each topic. + The left and right borders of the whole table are, on the other side, + part of the topics rows format, and need not be preserved seperateley. + ''' + table = None + lastRowFormat = [] + numCell = -1 + topicCell = -1 + responsibleCell = -1 + timeCell = -1 + + def __init__(self): + self.topicItems = {} + self.topicCells = [] + self.topicCellFormats = [] + self.firstRowFormat = [] + # This is the topics table. say hallo :-) + try: + Topics.table = AgendaTemplate.getTable(SECTION_TOPICS) + except Exception, ex: + traceback.print_exc() + raise AttributeError ("Fatal error while loading template: table " + SECTION_TOPICS + " could not load."); + + ''' + first I store all <*> ranges + which are in the topics table. + I store each <*> range in this - the key + is the cell it is in. Later when analyzing the topic, + cell by cell, I check in this map to know + if a cell contains a <*> or not. + ''' + items = {} + for i in AgendaTemplate._allItems: + t = Helper.getUnoPropertyValue(i, "TextTable") + if t == Topics.table: + cell = Helper.getUnoPropertyValue(i, "Cell") + iText = cell.String + items[iText] = i + + ''' + in the topics table, there are always one + title row and three topics defined. + So no mutter how many rows a topic takes - we + can restore its structure and format. + ''' + rows = AgendaTemplate.getRowCount(Topics.table) + self.rowsPerTopic = (rows - 1) / 3 + firstCell = "A" + str(1 + self.rowsPerTopic + 1) + afterLastCell = "A" + str(1 + (self.rowsPerTopic * 2) + 1) + # go to the first row of the 2. topic + cursor = Topics.table.createCursorByCellName(firstCell) + # analyze the structure of the topic rows. + while not cursor.RangeName == afterLastCell: + cell = Topics.table.getCellByName(cursor.RangeName) + # first I store the content and para style of the cell + ae = TextElement(cell) + # if the cell contains a relevant <...> + # i add the text element to the hash, + # so it's text can be updated later. + if items[cell.String] is not None: + self.topicItems[cell.String.lower().lstrip()] = ae + + self.topicCells.append(ae) + # and store the format of the cell. + self.topicCellFormats.append( TableCellFormatter(Topics.table.getCellByName(cursor.RangeName))) + # goto next cell. + cursor.goRight(1, False) + ''' + now - in which cell is every fillin? + ''' + Topics.numCell = self.topicCells.index(self.topicItems[FILLIN_TOPIC_NUMBER]) + Topics.topicCell = self.topicCells.index(self.topicItems[FILLIN_TOPIC_TOPIC]) + Topics.responsibleCell = self.topicCells.index(self.topicItems[FILLIN_TOPIC_RESPONSIBLE]) + Topics.timeCell = self.topicCells.index(self.topicItems[FILLIN_TOPIC_TIME]) + '''now that we know how the topics look like, + we get the format of the first and last rows. + ''' + # format of first row + cursor.gotoStart(False) + tmp_do_var1 = True + while tmp_do_var1: + self.firstRowFormat.append(TableCellFormatter (Topics.table.getCellByName(cursor.RangeName))) + cursor.goRight(1, False) + tmp_do_var1 = not cursor.RangeName.startswith("A") + # format of the last row + cursor.gotoEnd(False) + while not cursor.RangeName.startswith("A"): + Topics.lastRowFormat.append(TableCellFormatter (Topics.table.getCellByName(cursor.RangeName))) + cursor.goLeft(1, False) + # we missed the A cell - so we have to add it also.. + Topics.lastRowFormat.append(TableCellFormatter (Topics.table.getCellByName(cursor.RangeName))) + #COMMENTED + #AgendaTemplate.removeTableRows(Topics.table, 1 + self.rowsPerTopic, rows - self.rowsPerTopic - 1) + + '''@param topic the topic number to write + @param data the data of the topic. + @return the number of rows that have been added + to the table. 0 or a negative number: no rows added. + ''' + + def write2(self, topic, data): + if topic >= len(AgendaTemplate.writtenTopics): + size = topic - len(AgendaTemplate.writtenTopics) + AgendaTemplate.writtenTopics += [None] * size + AgendaTemplate.writtenTopics.insert(topic, "") + # make sure threr are enough rows for me... + rows = AgendaTemplate.getRowCount(Topics.table) + reqRows = 1 + (topic + 1) * self.rowsPerTopic + firstRow = reqRows - self.rowsPerTopic + 1 + diff = reqRows - rows + if diff > 0: + AgendaTemplate.insertTableRows(Topics.table, rows, diff) + # set the item's text... + + self.setItemText(Topics.numCell, data[0].Value) + self.setItemText(Topics.topicCell, data[1].Value) + self.setItemText(Topics.responsibleCell, data[2].Value) + self.setItemText(Topics.timeCell, data[3].Value) + # now write ! + cursor = Topics.table.createCursorByCellName("A" + str(firstRow)) + for i in self.topicCells: + i.write(Topics.table.getCellByName(cursor.RangeName)) + cursor.goRight(1, False) + # now format ! + cursor.gotoCellByName("A" + str(firstRow), False) + self.formatTable(cursor, self.topicCellFormats, False) + return diff + + '''check if the topic with the given index is written to the table. + @param topic the topic number (0 base) + @return true if the topic is already written to the table. False if not. + (false would mean rows must be added to the table in order to + be able to write this topic). + ''' + + def isWritten(self, topic): + return (AgendaTemplate.writtenTopics.size() > topic and AgendaTemplate.writtenTopics.get(topic) != None) + + '''rewrites a single cell containing. + This is used in order to refresh the topic/responsible/duration data in the + preview document, in response to a change in the gui (by the user). + Since the structure of the topics table is flexible, we don't reference a cell + number. Rather, we use "what" argument to specify which cell should be redrawn. + The Topics object, which analyzed the structure of the topics table appon + initialization, refreshes the approperiate cell. + @param topic index of the topic (0 based). + @param what 0 for num, 1 for topic, 2 for responsible, 3 for duration + @param data the row's data. + @throws Exception if something goes wrong (thow nothing should) + ''' + + def writeCell(self, topic, what, data): + # if the whole row should be written... + if not isWritten(topic): + write(topic, data) + # write only the "what" cell. + else: + # calculate the table row. + firstRow = 1 + (topic * self.rowsPerTopic) + 1 + # go to the first cell of this topic. + cursor = Topics.table.createCursorByCellName("A" + firstRow) + te = None + cursorMoves = 0 + tmp_switch_var1 = what + if tmp_switch_var1 == 0: + te = setItemText(Topics.numCell, data[0].Value) + cursorMoves = Topics.numCell + elif tmp_switch_var1 == 1: + te = setItemText(Topics.topicCell, data[1].Value) + cursorMoves = Topics.topicCell + elif tmp_switch_var1 == 2: + te = setItemText(Topics.responsibleCell, data[2].Value) + cursorMoves = Topics.responsibleCell + elif tmp_switch_var1 == 3: + te = setItemText(Topics.timeCell, data[3].Value) + cursorMoves = Topics.timeCell + + # move the cursor to the needed cell... + cursor.goRight(cursorMoves, False) + xc = Topics.table.getCellByName(cursor.RangeName) + # and write it ! + te.write(xc) + (self.topicCellFormats.get(cursorMoves)).format(xc) + + '''writes the given topic. + if the first topic was involved, reformat the + first row. + If any rows were added to the table, reformat + the last row. + @param topic the index of the topic to write. + @param data the topic's data. (see TopicsControl + for explanation about the topics data model) + @throws Exception if something goes wrong (though nothing should). + ''' + + def write(self, topic, data): + diff = self.write2(topic, data) + '''if the first topic has been written, + one needs to reformat the first row. + ''' + if topic == 0: + self.formatFirstRow() + ''' + if any rows were added, one needs to format + the whole table again. + ''' + + if diff > 0: + self.formatLastRow() + + '''Writes all the topics to thetopics table. + @param topicsData a List containing all Topic's Data. + ''' + + @classmethod + def writeAll(self, topicsData): + try: + i = 0 + while i < (len(topicsData) - 1): + self.write2(i, topicsData[i]) + i += 1 + self.formatLastRow() + except Exception, ex: + traceback.print_exc() + + '''removes obsolete rows, reducing the + topics table to the given number of topics. + Note this method does only reducing - if + the number of topics given is greater than the + number of actuall topics it does *not* add + rows ! + Note also that the first topic will never be removed. + If the table contains no topics, the whole section will + be removed uppon finishing. + The reason for that is a "table-design" one: the first topic is + maintained in order to be able to add rows with a design of this topic, + and not of the header row. + @param topics the number of topics the table should contain. + @throws Exception + ''' + + def reduceDocumentTo(self, topics): + # we never remove the first topic... + if topics <= 0: + topics = 1 + + tableRows = Topics.table.getRows() + targetNumOfRows = topics * self.rowsPerTopic + 1 + if tableRows.getCount() > targetNumOfRows: + tableRows.removeByIndex(targetNumOfRows, tableRows.getCount() - targetNumOfRows) + + formatLastRow() + while AgendaTemplate.writtenTopics.size() > topics: + AgendaTemplate.writtenTopics.remove(topics) + + '''reapply the format of the first (header) row. + ''' + + def formatFirstRow(self): + cursor = Topics.table.createCursorByCellName("A1") + self.formatTable(cursor, self.firstRowFormat, False) + + '''reaply the format of the last row. + ''' + @classmethod + def formatLastRow(self): + cursor = Topics.table.createCursorByCellName("A1") + cursor.gotoEnd(False) + self.formatTable(cursor, Topics.lastRowFormat, True) + + '''returns a text element for the given cell, + which will write the given text. + @param cell the topics cell number. + @param value the value to write. + @return a TextElement object which will write the given value + to the given cell. + ''' + + def setItemText(self, cell, value): + if cell >= 0: + te = self.topicCells[cell] + if te is not None: + te.text = str(value) + return te + + return None + + '''formats a series of cells from the given one, + using the given List of TableCellFormatter objects, + in the given order. + This method is used to format the first (header) and the last + rows of the table. + @param cursor a table cursor, pointing to the start cell to format + @param formats a List containing TableCellFormatter objects. Each will format one cell in the direction specified. + @param reverse if true the cursor will move left, formatting in reverse order (used for the last row). + ''' + @classmethod + def formatTable(self, cursor, formats, reverse): + for i in formats: + i.format(Topics.table.getCellByName(cursor.RangeName)) + if reverse: + cursor.goLeft(1, False) + else: + cursor.goRight(1, False) + +''' +TODO To change the template for this generated type comment go to +Window - Preferences - Java - Code Style - Code Templates +''' +class ParaStyled(object): + + paraStyle = "" + + def __init__(self, paraStyle_): + ParaStyled.paraStyle = paraStyle_ + + def format(self, textRange): + if textRange is None: + textRange = textRange.Text + cursor = textRange.createTextCursorByRange(textRange) + Helper.setUnoPropertyValue(cursor, "ParaStyleName", ParaStyled.paraStyle) + + def write(self, textRange): + self.format(textRange) + +''' +A basic implementation of AgendaElement: +writes a String to the given XText/XTextRange, and applies +a ParaStyle to it (using the parent class). +@author rp143992 +''' +class TextElement(ParaStyled): + + def __init__(self, text_, paraStyle_=None): + if paraStyle_ is None: + self.text = text_.String + paraStyle_ = Helper.getUnoPropertyValue(text_.Start, "ParaStyleName") + else: + self.text = text_ + + super(TextElement,self).__init__(paraStyle_) + + def write(self, textRange): + textRange.String = self.text + if not self.text == "": + super(TextElement,self).write(textRange) + +''' +A Text element which, if the text to write is empty (null or "") +inserts a placeholder instead. +@author rp143992 + +TODO To change the template for this generated type comment go to +Window - Preferences - Java - Code Style - Code Templates +''' + +class PlaceholderTextElement(TextElement): + + def __init__(self, textRange, placeHolderText_, hint_, xmsf_): + super(PlaceholderTextElement,self).__init__(textRange) + + self.placeHolderText = placeHolderText_ + self.hint = hint_ + self.xmsf = xmsf_ + + def write(self, textRange): + super(PlaceholderTextElement,self).write(textRange) + if self.text is None or self.text == "": + try: + xTextContent = AgendaTemplate.createPlaceHolder( self.xmsf, self.placeHolderText, self.hint) + textRange.Text.insertTextContent(textRange.Start, xTextContent, True) + except Exception, ex: + traceback.print_exc() + + +''' +An Agenda element which writes no text, but inserts a placeholder, and formats +it using a ParaStyleName. +@author rp143992 +''' + +class PlaceholderElement(ParaStyled): + + def __init__(self, paraStyle, placeHolderText_, hint_, xmsf_): + super(PlaceholderElement,self).__init__(paraStyle) + self.placeHolderText = placeHolderText_ + self.hint = hint_ + self.xmsf = xmsf_ + + def write(self, textRange): + try: + xTextContent = AgendaTemplate.createPlaceHolder( AgendaTemplate.document, self.placeHolderText, self.hint) + textRange.Text.insertTextContent(textRange.Start, xTextContent, True) + super(PlaceholderElement,self).write(textRange) + except Exception, ex: + traceback.print_exc() + +''' +An implementation of AgendaElement which +gets as a parameter a table cursor, and writes +a text to the cell marked by this table cursor, and +a place holder to the next cell. +@author rp143992 + +TODO To change the template for this generated type comment go to +Window - Preferences - Java - Code Style - Code Templates +''' + +class AgendaItem(object): + + def __init__(self, name_, te, f): + self.name = name_ + self.field = f + self.textElement = te + + def write(self, tableCursor): + cellname = tableCursor.RangeName + cell = Topics.table.getCellByName(cellname) + self.textElement.write(cell) + tableCursor.goRight(1, False) + #second field is actually always null... + # this is a preparation for adding placeholders. + if self.field is not None: + self.field.write(cell) + + +''' +reads/write a table cell format from/to a table cell or a group of cells. +''' +class TableCellFormatter(object): + properties = ("BackColor", "BackTransparent", "BorderDistance", + "BottomBorderDistance", "LeftBorder", + "LeftBorderDistance", "RightBorder", "RightBorderDistance", + "TopBorder", "TopBorderDistance") + + def __init__(self, tableCell): + self.values = [] + for i in TableCellFormatter.properties: + pass + #COMMENTED + #self.values.append( Helper.getUnoPropertyValue(tableCell, i) ) + + + def format(self, tableCell): + pass + #COMMENTED + #Helper.setUnoPropertyValues( + # tableCell, TableCellFormatter.properties, tuple(self.values)) diff --git a/wizards/com/sun/star/wizards/agenda/AgendaWizardDialog.py b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialog.py new file mode 100644 index 000000000000..ec8a2b0c1223 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialog.py @@ -0,0 +1,280 @@ +from ui.WizardDialog import * +from com.sun.star.awt.FontUnderline import SINGLE +from AgendaWizardDialogConst import * +from AgendaWizardDialogResources import * + +class AgendaWizardDialog(WizardDialog): + + def __init__(self, xmsf): + super(AgendaWizardDialog,self).__init__(xmsf, HID ) + #Load Resources + self.resources = AgendaWizardDialogResources(xmsf) + #set dialog properties... + Helper.setUnoPropertyValues( + self.xDialogModel, ("Closeable", + PropertyNames.PROPERTY_HEIGHT, + "Moveable", + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + "Title", + PropertyNames.PROPERTY_WIDTH), + (True, 210, True, 200, 52, 1, 1, + self.resources.resAgendaWizardDialog_title,310)) + + self.IMGHELP1_HID = "" + self.PROPS_LIST = ("Dropdown", + PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + self.PROPS_LABEL_B = ("FontDescriptor", + PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_LABEL, + PropertyNames.PROPERTY_MULTILINE, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + self.PROPS_CHECK = (PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_LABEL, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STATE, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + self.PROPS_BUTTON = (PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_LABEL, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + self.PROPS_X = (PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + self.PROPS_TEXTAREA = (PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_LABEL, + PropertyNames.PROPERTY_MULTILINE, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + self.PROPS_TEXT = (PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_LABEL, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + self.PROPS_IMAGE = ("Border", + PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_IMAGEURL, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + "ScaleImage", + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + self.fontDescriptor1 = \ + uno.createUnoStruct('com.sun.star.awt.FontDescriptor') + self.fontDescriptor2 = \ + uno.createUnoStruct('com.sun.star.awt.FontDescriptor') + self.fontDescriptor4 = \ + uno.createUnoStruct('com.sun.star.awt.FontDescriptor') + #Set member- FontDescriptors... + self.fontDescriptor1.Weight = 150 + self.fontDescriptor1.Underline = SINGLE + self.fontDescriptor2.Weight = 100 + self.fontDescriptor4.Weight = 150 + + ''' + build components + ''' + def buildStep1(self): + self.insertLabel("lblTitle1", self.PROPS_LABEL_B, (self.fontDescriptor4, + 16, self.resources.reslblTitle1_value, True, 91, 8, 1, 100,212)) + self.insertLabel("lblPageDesign", self.PROPS_TEXT, + (8, self.resources.reslblPageDesign_value, 97, 32, 1, 101, 66)) + self.listPageDesign = self.insertListBox("listPageDesign", + None, LISTPAGEDESIGN_ACTION_PERFORMED, self.PROPS_LIST, + (True, 12, LISTPAGEDESIGN_HID, 166, 30, 1, 102, 70), self) + self.chkMinutes = self.insertCheckBox("chkMinutes", None, + self.PROPS_CHECK, (9, CHKMINUTES_HID, + self.resources.reschkMinutes_value, 97, 50, 0, 1, 103, 203), self) + self.insertImage("imgHelp1", self.PROPS_IMAGE, + (0, 10, self.IMGHELP1_HID, + INFO_IMAGE_URL, 92, + 145, False, 1, 104, 10)) + self.insertLabel("lblHelp1", self.PROPS_TEXTAREA, + (39, self.resources.reslblHelp1_value, True,104,145, 1, 105,199)) + + def buildStep2(self): + self.insertLabel("lblTitle2", self.PROPS_LABEL_B, + (self.fontDescriptor4, 16, + self.resources.reslblTitle2_value, True,91, 8, 2, 200,212)) + self.insertLabel("lblDate", self.PROPS_TEXT, + (8, self.resources.reslblDate_value, 97, 32, 2, 201,66)) + self.txtDate = self.insertDateField("txtDate", None, self.PROPS_LIST, + (True, 12, TXTDATE_HID,166,30, 2, 202,70), self) + self.insertLabel("lblTime", self.PROPS_TEXT, + (8, self.resources.reslblTime_value, 97, 50, 2, 203, 66)) + self.txtTime = self.insertTimeField("txtTime", None, + (PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + "StrictFormat", + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH), + (12, TXTTIME_HID, 166, 48, 2, True, 204,70), self) + self.insertLabel("lblTitle", self.PROPS_TEXT, + (8, self.resources.reslblTitle_value, 97, 68, 2, 205,66)) + self.txtTitle = self.insertTextField("txtTitle", None, + (PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_MULTILINE, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH), + (26, TXTTITLE_HID, True, 166, 66, 2, 206, 138), self) + self.insertLabel("lblLocation", self.PROPS_TEXT, + (8, self.resources.reslblLocation_value, 97, 100, 2, 207, 66)) + self.cbLocation = self.insertTextField("cbLocation", None, + (PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_MULTILINE, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH), + (34, CBLOCATION_HID, True, 166,98, 2, 208, 138), self) + self.insertImage("imgHelp2", self.PROPS_IMAGE, + (0, 10, self.IMGHELP1_HID, + INFO_IMAGE_URL, + 92, 145, False, 2, 209, 10)) + self.insertLabel("lblHelp2", self.PROPS_TEXTAREA, + (39, self.resources.reslblHelp2_value, True, 104, 145, 2, 210, 199)) + + def buildStep3(self): + self.insertLabel("lblTitle3", self.PROPS_LABEL_B, + (self.fontDescriptor4, 16, self.resources.reslblTitle3_value, + True, 91, 8, 3, 300,212)) + self.chkMeetingTitle = self.insertCheckBox("chkMeetingTitle", None, + self.PROPS_CHECK, + (8, CHKMEETINGTITLE_HID, self.resources.reschkMeetingTitle_value, + 97, 32, 1, 3, 301, 69), self) + self.chkRead = self.insertCheckBox("chkRead", None, self.PROPS_CHECK, + (8, CHKREAD_HID, self.resources.reschkRead_value, + 97, 46, 0, 3, 302, 162), self) + self.chkBring = self.insertCheckBox("chkBring", None, self.PROPS_CHECK, + (8, CHKBRING_HID, self.resources.reschkBring_value, + 97, 60, 0, 3, 303, 162), self) + self.chkNotes = self.insertCheckBox("chkNotes", None, self.PROPS_CHECK, + (8, CHKNOTES_HID, self.resources.reschkNotes_value, + 97, 74, 1, 3, 304, 160), self) + self.insertImage("imgHelp3", self.PROPS_IMAGE, (0, 10, + self.IMGHELP1_HID, INFO_IMAGE_URL, + 92, 145, False, 3, 305, 10)) + self.insertLabel("lblHelp3", self.PROPS_TEXTAREA, + (39, self.resources.reslblHelp3_value, True,104, 145, 3, 306, 199)) + + def buildStep4(self): + self.insertLabel("lblTitle5", self.PROPS_LABEL_B, + (self.fontDescriptor4, 16, self.resources.reslblTitle5_value, + True, 91, 8, 4, 400, 212)) + self.chkConvenedBy = self.insertCheckBox("chkConvenedBy", None, + self.PROPS_CHECK, (8, CHKCONVENEDBY_HID, + self.resources.reschkConvenedBy_value, 97, 32, 1, 4, 401, 150), self) + self.chkPresiding = self.insertCheckBox("chkPresiding", None, + self.PROPS_CHECK, (8, CHKPRESIDING_HID, + self.resources.reschkPresiding_value, 97, 46, 0, 4, 402, 150), self) + self.chkNoteTaker = self.insertCheckBox("chkNoteTaker", None, + self.PROPS_CHECK, (8, CHKNOTETAKER_HID, + self.resources.reschkNoteTaker_value, 97, 60, 0, 4, 403, 150), self) + self.chkTimekeeper = self.insertCheckBox("chkTimekeeper", None, + self.PROPS_CHECK, (8, CHKTIMEKEEPER_HID, + self.resources.reschkTimekeeper_value, 97, 74, 0, 4, 404, 150), self) + self.chkAttendees = self.insertCheckBox("chkAttendees", None, + self.PROPS_CHECK, (8, CHKATTENDEES_HID, + self.resources.reschkAttendees_value, 97, 88, 1, 4, 405, 150), self) + self.chkObservers = self.insertCheckBox("chkObservers", None, + self.PROPS_CHECK, (8, CHKOBSERVERS_HID, + self.resources.reschkObservers_value, 97, 102, 0, 4, 406, 150), self) + self.chkResourcePersons = self.insertCheckBox("chkResourcePersons", None, + self.PROPS_CHECK, (8, CHKRESOURCEPERSONS_HID, + self.resources.reschkResourcePersons_value, 97, 116, 0, + 4, 407, 150), self) + self.insertImage("imgHelp4", self.PROPS_IMAGE, + (0, 10, self.IMGHELP1_HID, INFO_IMAGE_URL, + 92, 145, False, 4, 408, 10)) + self.insertLabel("lblHelp4", self.PROPS_TEXTAREA, + (39, self.resources.reslblHelp4_value, True,104, 145, 4, 409, 199)) + + def buildStep5(self): + self.insertLabel("lblTitle4", self.PROPS_LABEL_B, + (self.fontDescriptor4, 16, self.resources.reslblTitle4_value, + True, 91, 8, 5, 500, 212)) + self.insertLabel("lblTopic", self.PROPS_TEXT, + (8, self.resources.reslblTopic_value, 107, 28, 5, 71, 501)) + self.insertLabel("lblResponsible", self.PROPS_TEXT, + (8, self.resources.reslblResponsible_value, 195, 28, 5, 72, 502)) + self.insertLabel("lblDuration", self.PROPS_TEXT, + (8, self.resources.reslblDuration_value, 267, 28, 5, 73, 503)) + self.btnInsert = self.insertButton("btnInsert", BTNINSERT_ACTION_PERFORMED, + self.PROPS_BUTTON, (14, BTNINSERT_HID, + self.resources.resButtonInsert, 92, 136, 5, 580, 40), self) + self.btnRemove = self.insertButton("btnRemove", BTNREMOVE_ACTION_PERFORMED, + self.PROPS_BUTTON, (14, BTNREMOVE_HID, + self.resources.resButtonRemove, 134, 136, 5, 581, 40), self) + self.btnUp = self.insertButton("btnUp", BTNUP_ACTION_PERFORMED, + self.PROPS_BUTTON, (14, BTNUP_HID, + self.resources.resButtonUp, 222, 136, 5, 582, 40), self) + self.btnDown = self.insertButton("btnDown", BTNDOWN_ACTION_PERFORMED, + self.PROPS_BUTTON, (14, BTNDOWN_HID, + self.resources.resButtonDown, 264, 136, 5, 583, 40), self) + + def buildStep6(self): + self.insertLabel("lblTitle6", self.PROPS_LABEL_B, + (self.fontDescriptor4, 16, self.resources.reslblTitle6_value, + True, 91, 8, 6, 600, 212)) + self.insertLabel("lblHelpPg6", self.PROPS_TEXTAREA, + (24, self.resources.reslblHelpPg6_value, True, + 97, 32, 6, 601,204)) + self.insertLabel("lblTemplateName", self.PROPS_TEXT, + (8, self.resources.reslblTemplateName_value, + 97, 62, 6, 602, 101)) + self.txtTemplateName = self.insertTextField("txtTemplateName", + TXTTEMPLATENAME_TEXT_CHANGED, self.PROPS_X, + (12, TXTTEMPLATENAME_HID, 202, 60, 6, 603, 100), self) + self.insertLabel("lblProceed", self.PROPS_TEXT, + (8, self.resources.reslblProceed_value, 97, 101, 6, 607,204)) + self.optCreateAgenda = self.insertRadioButton("optCreateAgenda", None, + self.PROPS_CHECK, (8, OPTCREATEAGENDA_HID, + self.resources.resoptCreateAgenda_value, + 103, 113, 1, 6, 608, 198), self) + self.optMakeChanges = self.insertRadioButton("optMakeChanges", None, + self.PROPS_BUTTON, (8, OPTMAKECHANGES_HID, + self.resources.resoptMakeChanges_value, 103, 125, 6, 609, 198), self) + self.insertImage("imgHelp6", self.PROPS_IMAGE, (0, 10, self.IMGHELP1_HID, + INFO_IMAGE_URL, 92, 145, False, 6, 610, 10)) + self.insertLabel("lblHelp6", self.PROPS_TEXTAREA, + (39, self.resources.reslblHelp6_value, True, 104, 145, 6, 611, 199)) diff --git a/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogConst.py b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogConst.py new file mode 100644 index 000000000000..dadd84240d78 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogConst.py @@ -0,0 +1,47 @@ +from common.HelpIds import HelpIds + +LISTPAGEDESIGN_ACTION_PERFORMED = "pageDesignChanged" +TXTTEMPLATENAME_TEXT_CHANGED = "templateTitleChanged" +BTNTEMPLATEPATH_ACTION_PERFORMED = "saveAs" +BTNINSERT_ACTION_PERFORMED = "insertRow" +BTNREMOVE_ACTION_PERFORMED = "removeRow" +BTNUP_ACTION_PERFORMED = "rowUp" +BTNDOWN_ACTION_PERFORMED = "rowDown" + +INFO_IMAGE_URL = "private:resource/dbu/image/19205" + +HID = 41051 + +LISTPAGEDESIGN_HID = HelpIds.getHelpIdString(HID + 6) +CHKMINUTES_HID = HelpIds.getHelpIdString(HID + 7) +TXTTIME_HID = HelpIds.getHelpIdString(HID + 8) +TXTDATE_HID = HelpIds.getHelpIdString(HID + 9) +TXTTITLE_HID = HelpIds.getHelpIdString(HID + 10) +CBLOCATION_HID = HelpIds.getHelpIdString(HID + 11) + +CHKMEETINGTITLE_HID = HelpIds.getHelpIdString(HID + 12) +CHKREAD_HID = HelpIds.getHelpIdString(HID + 13) +CHKBRING_HID = HelpIds.getHelpIdString(HID + 14) +CHKNOTES_HID = HelpIds.getHelpIdString(HID + 15) + +CHKCONVENEDBY_HID = HelpIds.getHelpIdString(HID + 16) +CHKPRESIDING_HID = HelpIds.getHelpIdString(HID + 17) +CHKNOTETAKER_HID = HelpIds.getHelpIdString(HID + 18) +CHKTIMEKEEPER_HID = HelpIds.getHelpIdString(HID + 19) +CHKATTENDEES_HID = HelpIds.getHelpIdString(HID + 20) +CHKOBSERVERS_HID = HelpIds.getHelpIdString(HID + 21) +CHKRESOURCEPERSONS_HID = HelpIds.getHelpIdString(HID + 22) + +TXTTEMPLATENAME_HID = HelpIds.getHelpIdString(HID + 23) +TXTTEMPLATEPATH_HID = HelpIds.getHelpIdString(HID + 24) +BTNTEMPLATEPATH_HID = HelpIds.getHelpIdString(HID + 25) + +OPTCREATEAGENDA_HID = HelpIds.getHelpIdString(HID + 26) +OPTMAKECHANGES_HID = HelpIds.getHelpIdString(HID + 27) + +BTNINSERT_HID = HelpIds.getHelpIdString(HID + 28) +BTNREMOVE_HID = HelpIds.getHelpIdString(HID + 29) +BTNUP_HID = HelpIds.getHelpIdString(HID + 30) +BTNDOWN_HID = HelpIds.getHelpIdString(HID + 31) + +LAST_HID = HID + 32 diff --git a/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogImpl.py b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogImpl.py new file mode 100644 index 000000000000..a29ea3c9cf21 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogImpl.py @@ -0,0 +1,386 @@ +from AgendaWizardDialog import * +from common.Configuration import * +from CGAgenda import CGAgenda +from AgendaTemplate import * +from common.NoValidPathException import * +from common.FileAccess import * +from ui.PathSelection import * +from ui.event.UnoDataAware import * +from ui.event.RadioDataAware import * + +from com.sun.star.awt.VclWindowPeerAttribute import OK +from common.NoValidPathException import * + +class AgendaWizardDialogImpl(AgendaWizardDialog): + + fileAccess1 = None + + def __init__(self, xmsf): + super(AgendaWizardDialogImpl, self).__init__(xmsf) + self.filenameChanged = False + + def enterStep(self, OldStep, NewStep): + pass + + def leaveStep(self, OldStep, NewStep): + pass + + ''' + used in developement to start the wizard + ''' + + @classmethod + def main(self, args): + ConnectStr = \ + "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" + try: + xLocMSF = Desktop.connect(ConnectStr) + wizard = AgendaWizardDialogImpl(xLocMSF) + wizard.startWizard() + except Exception, exception: + traceback.print_exc() + + ''' + read the configuration data, open the specified template, + initialize the template controller (AgendaTemplate) and + set the status of the displayed template to the one + read from the configuration. + build the dialog. + Synchronize the dialog to the same status (read from + the configuration). + show the dialog. + ''' + + def startWizard(self): + self.running = True + try: + # read configuration data. + self.agenda = CGAgenda() + root = Configuration.getConfigurationRoot( + self.xMSF, "/org.openoffice.Office.Writer/Wizards/Agenda", + False) + self.agenda.readConfiguration(root, "cp_") + # initialize the agenda temself.myPathSelectionListener()plate + self.agendaTemplate = AgendaTemplate( + self.xMSF, self.agenda, self.resources, self) + self.initializeTemplates() + self.agendaTemplate.load(self.agendaTemplates[1][0], []) + # build the dialog. + self.buildStep1() + self.buildStep2() + self.buildStep3() + self.buildStep4() + self.buildStep5() + self.topicsControl = TopicsControl(self, self.xMSF, self.agenda) + self.buildStep6() + self.drawNaviBar() + self.initializePaths() + #special Control for setting the save Path: + self.insertPathSelectionControl() + # create the peer + xw = self.agendaTemplate.xFrame.getContainerWindow() + self.createWindowPeer(xw) + # initialize roadmap + self.addRoadmap() + self.insertRoadMapItems( + [self.resources.resStep1, self.resources.resStep2, + self.resources.resStep3, self.resources.resStep4, + self.resources.resStep5, self.resources.resStep6], + [1, 2, 3, 4, 5, 6],[True, True, True, True, True, True]) + self.nMaxStep = 6 + self.setCurrentRoadmapItemID(1) + # synchronize GUI and CGAgenda object. + self.makeDA() + if self.myPathSelection.xSaveTextBox.Text.lower() == "": + self.myPathSelection.initializePath() + + self.executeDialogFromComponent(self.agendaTemplate.xFrame) + self.removeTerminateListener() + self.closeDocument() + self.running = False + except Exception, ex: + self.removeTerminateListener() + traceback.print_exc() + self.running = False + return + + def insertPathSelectionControl(self): + self.myPathSelection = PathSelection( + self.xMSF, self, PathSelection.TransferMode.SAVE, + PathSelection.DialogTypes.FILE) + self.myPathSelection.insert(6, 97, 70, 205, 45, + self.resources.reslblTemplatePath_value, True, + HelpIds.getHelpIdString(HID + 24), + HelpIds.getHelpIdString(HID + 25)) + self.myPathSelection.sDefaultDirectory = self.sUserTemplatePath + self.myPathSelection.sDefaultName = "myAgendaTemplate.ott" + self.myPathSelection.sDefaultFilter = "writer8_template" + self.myPathSelection.addSelectionListener( + self.myPathSelectionListener()) + + def initializePaths(self): + try: + self.sTemplatePath = FileAccess.getOfficePath2( + self.xMSF, "Template", "share", "/wizard") + self.sUserTemplatePath = FileAccess.getOfficePath2( + self.xMSF, "Template", "user", "") + self.sBitmapPath = FileAccess.combinePaths( + self.xMSF, self.sTemplatePath, "/../wizard/bitmap") + except NoValidPathException: + traceback.print_exc() + + def checkSavePath(self): + if self.agenda.cp_TemplatePath is None \ + or self.agenda.cp_TemplatePath == "" \ + or not self.getFileAccess().exists( + FileAccess.getParentDir(self.agenda.cp_TemplatePath), False) \ + or not self.getFileAccess().isDirectory( + FileAccess.getParentDir(self.agenda.cp_TemplatePath)): + try: + self.agenda.cp_TemplatePath = FileAccess.connectURLs( + FileAccess.getOfficePath(xMSF, "Work", "", ""), + resources.resDefaultFilename) + except Exception, ex: + traceback.print_exc() + + ''' + bind controls to the agenda member (DataAware model) + ''' + + def makeDA(self): + self.setControlProperty( + "listPageDesign", "StringItemList", tuple(self.agendaTemplates[0])) + self.checkSavePath() + #setFilename(agenda.cp_TemplatePath); + UnoDataAware.attachListBox( + self.agenda, "cp_AgendaType", self.listPageDesign, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_IncludeMinutes", self.chkMinutes, True).updateUI() + UnoDataAware.attachEditControl( + self.agenda, "cp_Title", self.txtTitle, True).updateUI() + UnoDataAware.attachDateControl( + self.agenda, "cp_Date", self.txtDate, True).updateUI() + UnoDataAware.attachTimeControl( + self.agenda, "cp_Time", self.txtTime, True).updateUI() + UnoDataAware.attachEditControl( + self.agenda, "cp_Location", self.cbLocation, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowMeetingType", self.chkMeetingTitle, True) + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowRead", self.chkRead, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowBring", self.chkBring, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowNotes", self.chkNotes, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowCalledBy", self.chkConvenedBy, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowFacilitator", self.chkPresiding, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowNotetaker", self.chkNoteTaker, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowTimekeeper", self.chkTimekeeper, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowAttendees", self.chkAttendees, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowObservers", self.chkObservers, True).updateUI() + UnoDataAware.attachCheckBox( + self.agenda, "cp_ShowResourcePersons",self.chkResourcePersons, True).updateUI() + UnoDataAware.attachEditControl( + self.agenda, "cp_TemplateName", self.txtTemplateName, True).updateUI() + RadioDataAware.attachRadioButtons( + self.agenda, "cp_ProceedMethod", + (self.optCreateAgenda, self.optMakeChanges), True).updateUI() + + ''' + read the available agenda wizard templates. + ''' + + def initializeTemplates(self): + try: + self.sTemplatePath = FileAccess.getOfficePath2( + self.xMSF, "Template", "share", "/wizard") + sAgendaPath = FileAccess.combinePaths( + self.xMSF, self.sTemplatePath, "/wizard/agenda") + self.agendaTemplates = FileAccess.getFolderTitles( + self.xMSF, "aw", sAgendaPath) + return True + except NoValidPathException: + traceback.print_exc() + return False + + ''' + first page, page design listbox changed. + ''' + + def pageDesignChanged(self, item): + try: + self.agendaTemplate.load( + self.agendaTemplates[1][item.Selected], + self.topicsControl.scrollfields) + except Exception: + SystemDialog.showMessageBox( + self.xMSF, "ErrBox", OK, self.resources.resErrOpenTemplate) + traceback.print_exc() + + ''' + last page, template title changed... + ''' + + def templateTitleChanged(self): + title = Helper.getUnoPropertyValue(getModel(txtTemplateName), "Text") + self.agendaTemplate.setTemplateTitle(title) + + ''' + convenience method. + instead of creating a FileAccess object every time + it is needed, I have a FileAccess object memeber. + the first time it is needed it will be created, and + then be reused... + @return the FileAccess memeber object. + ''' + + def getFileAccess(self): + if AgendaWizardDialogImpl.fileAccess1 is None: + try: + AgendaWizardDialogImpl.fileAccess1 = FileAccess(self.xMSF) + except Exception, e: + traceback.print_exc() + return AgendaWizardDialogImpl.fileAccess1 + + ''' + last page, "browse" ("...") button was clicked... + ''' + + def saveAs(self): + try: + checkSavePath() + saveAs = SystemDialog.createStoreDialog(xMSF) + saveAs.addFilterToDialog("ott", "writer8_template", True) + # call the saveAs dialog. + url = saveAs.callStoreDialog( + FileAccess.getParentDir(self.agenda.cp_TemplatePath), + FileAccess.getFilename(self.agenda.cp_TemplatePath)) + if url != None: + self.agenda.cp_TemplatePath = url + setFilename(url) + self.filenameChanged = True + + except Exception, ex: + traceback.print_exc() + + ''' + is called when the user + changes the path through the "save as" dialog. + The path displayed is a translated, user-friendly, platform dependant path. + @param url the new save url. + ''' + + def setFilename(self, url): + try: + path = getFileAccess().getPath(url, "") + Helper.setUnoPropertyValue( + getModel(self.myPathSelection.xSaveTextBox), "Text", path) + except Exception, ex: + traceback.print_exc() + + def insertRow(self): + self.topicsControl.insertRow() + + def removeRow(self): + self.topicsControl.removeRow() + + def rowUp(self): + self.topicsControl.rowUp() + + def rowDown(self): + self.topicsControl.rowDown() + + def cancelWizard(self): + self.xUnoDialog.endExecute() + self.running = False + + def finishWizard(self): + bSaveSuccess = False + # pesimistic :( + try: + fileAccess = FileAccess.FileAccess_unknown(xMSF) + self.sPath = self.myPathSelection.getSelectedPath() + if self.sPath.equals(""): + self.myPathSelection.triggerPathPicker() + self.sPath = self.myPathSelection.getSelectedPath() + + self.sPath = fileAccess.getURL(self.sPath) + #first, if the filename was not changed, thus + #it is coming from a saved session, check if the + # file exists and warn the user. + if not self.filenameChanged: + if fileAccess.exists(self.sPath, True): + answer = SystemDialog.showMessageBox( + xMSF, xControl.Peer, "MessBox", + VclWindowPeerAttribute.YES_NO + \ + VclWindowPeerAttribute.DEF_NO, + resources.resFileExists) + if (answer == 3): + # user said: no, do not overwrite.... + return False + + self.agendaTemplate.xTextDocument.lockControllers() + xTextDocument = self.agendaTemplate.document + bSaveSuccess = OfficeDocument.store( + xMSF, xTextDocument, self.sPath, "writer8_template", False) + except Exception, e: + SystemDialog.showMessageBox( + xMSF, xControl.Peer, "ErrBox", VclWindowPeerAttribute.OK, + resources.resErrSaveTemplate) + + if bSaveSuccess: + try: + self.topicsControl.saveTopics(self.agenda) + root = Configuration.getConfigurationRoot( + xMSF, "/org.openoffice.Office.Writer/Wizards/Agenda", True) + self.agenda.writeConfiguration(root, "cp_") + Configuration.commit(root) + + self.agendaTemplate.finish(self.topicsControl.getTopicsData()) + xStoreable = self.agendaTemplate.document + xStoreable.store() + + self.agendaTemplate.xTextDocument.unlockControllers() + loadValues = range(2) + loadValues[0] = PropertyValue.PropertyValue() + loadValues[0].Name = "AsTemplate" + if self.agenda.cp_ProceedMethod == 1: + loadValues[0].Value = Boolean.TRUE + else: + loadValues[0].Value = Boolean.FALSE + + loadValues[1] = PropertyValue.PropertyValue() + loadValues[1].Name = "InteractionHandler" + + xIH = xMSF.createInstance( + "com.sun.star.comp.uui.UUIInteractionHandler") + loadValues[1].Value = xIH + + oDoc = OfficeDocument.load( + Desktop.getDesktop(self.xMSF), + self.sPath, "_default", loadValues) + myViewHandler = ViewHandler(self.xMSF, oDoc) + myViewHandler.setViewSetting("ZoomType", OPTIMAL) + except Exception, ex: + traceback.print_exc() + + else: + self.agendaTemplate.xTextDocument.unlockControllers() + return False + + self.xUnoDialog.endExecute() + self.running = False + return True + + def closeDocument(self): + try: + xCloseable = self.agendaTemplate.xFrame + xCloseable.close(False) + except CloseVetoException, e: + traceback.print_exc() diff --git a/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogResources.py b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogResources.py new file mode 100644 index 000000000000..da84ee5b94e9 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/AgendaWizardDialogResources.py @@ -0,0 +1,153 @@ +from common.Resource import Resource + +class AgendaWizardDialogResources(Resource): + MODULE_NAME = "dbw" + RID_AGENDAWIZARDDIALOG_START = 5000 + RID_COMMON_START = 500 + + def __init__(self, xmsf): + super(AgendaWizardDialogResources,self).__init__(xmsf, + AgendaWizardDialogResources.MODULE_NAME) + #Delete the String, uncomment the getResText method + self.resAgendaWizardDialog_title = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 1) + self.resoptMakeChanges_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 2) + self.reslblTemplateName_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 3) + self.reslblTemplatePath_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 4) + self.reslblProceed_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 5) + self.reslblTitle1_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 6) + self.reslblTitle3_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 7) + self.reslblTitle2_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 8) + self.reslblTitle4_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 9) + self.reslblTitle5_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 10) + self.reslblTitle6_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 11) + self.reschkMinutes_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 12) + self.reslblHelp1_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 13) + self.reslblTime_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 14) + self.reslblTitle_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 15) + self.reslblLocation_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 16) + self.reslblHelp2_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 17) + self.resbtnTemplatePath_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 18) + self.resoptCreateAgenda_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 19) + self.reslblHelp6_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 20) + self.reslblTopic_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 21) + self.reslblResponsible_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 22) + self.reslblDuration_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 23) + self.reschkConvenedBy_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 24) + self.reschkPresiding_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 25) + self.reschkNoteTaker_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 26) + self.reschkTimekeeper_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 27) + self.reschkAttendees_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 28) + self.reschkObservers_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 29) + self.reschkResourcePersons_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 30) + self.reslblHelp4_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 31) + self.reschkMeetingTitle_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 32) + self.reschkRead_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 33) + self.reschkBring_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 34) + self.reschkNotes_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 35) + self.reslblHelp3_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 36) + self.reslblDate_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 38) + self.reslblHelpPg6_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 39) + self.reslblPageDesign_value = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 40) + self.resDefaultFilename = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 41) + self.resDefaultFilename = self.resDefaultFilename[:-4] + ".ott" + self.resDefaultTitle = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 42) + self.resErrSaveTemplate = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 43) + self.resPlaceHolderTitle = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 44) + self.resPlaceHolderDate = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 45) + self.resPlaceHolderTime = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 46) + self.resPlaceHolderLocation = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 47) + self.resPlaceHolderHint = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 48) + self.resStep1 = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 50) + self.resStep2 = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 51) + self.resStep3 = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 52) + self.resStep4 = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 53) + self.resStep5 = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 54) + self.resStep6 = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 55) + self.resErrOpenTemplate = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 56) + self.itemMeetingType = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 57) + self.itemBring = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 58) + self.itemRead = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 59) + self.itemNote = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 60) + self.itemCalledBy = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 61) + self.itemFacilitator = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 62) + self.itemAttendees = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 63) + self.itemNotetaker = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 64) + self.itemTimekeeper = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 65) + self.itemObservers = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 66) + self.itemResource = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 67) + self.resButtonInsert = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 68) + self.resButtonRemove = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 69) + self.resButtonUp = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 70) + self.resButtonDown = self.getResText( + AgendaWizardDialogResources.RID_AGENDAWIZARDDIALOG_START + 71) + + self.resFileExists = self.getResText( + AgendaWizardDialogResources.RID_COMMON_START + 19) diff --git a/wizards/com/sun/star/wizards/agenda/CGAgenda.py b/wizards/com/sun/star/wizards/agenda/CGAgenda.py new file mode 100644 index 000000000000..2e699d9ff4e8 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/CGAgenda.py @@ -0,0 +1,27 @@ +from common.ConfigGroup import * +from common.ConfigSet import ConfigSet +from CGTopic import CGTopic + +class CGAgenda(ConfigGroup): + cp_AgendaType = int() + cp_IncludeMinutes = bool() + cp_Title = "" + cp_Date = str() + cp_Time = str() + cp_Location = "" + cp_ShowMeetingType = bool() + cp_ShowRead = bool() + cp_ShowBring = bool() + cp_ShowNotes = bool() + cp_ShowCalledBy = bool() + cp_ShowFacilitator = bool() + cp_ShowNotetaker = bool() + cp_ShowTimekeeper = bool() + cp_ShowAttendees = bool() + cp_ShowObservers = bool() + cp_ShowResourcePersons = bool() + cp_TemplateName = str() + cp_TemplatePath = str() + cp_ProceedMethod = int() + + cp_Topics = ConfigSet(CGTopic()) diff --git a/wizards/com/sun/star/wizards/agenda/CGTopic.py b/wizards/com/sun/star/wizards/agenda/CGTopic.py new file mode 100644 index 000000000000..ae6fb5125533 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/CGTopic.py @@ -0,0 +1,45 @@ +from common.ConfigGroup import * + +''' +CGTopic means: Configuration Group Topic. +This object encapsulates a configuration group with topic information. +Since the topics gui conftrol uses its own data model, there is +also code here to convert from the data model to CGTopic object (the constructor) +and vice versa (setDataToRow method - used when loading the last session...) +''' + +class CGTopic(ConfigGroup): + + cp_Index = int() + cp_Topic = str() + cp_Responsible = str() + cp_Time = str() + + ''' + create a new CGTopic object with data from the given row. + the row object is a PropertyValue array, as used + by the TopicsControl's data model. + @param row PropertyValue array as used by the TopicsControl data model. + ''' + + def __init__(self, row=None): + if row is None: + return + num = row[0].Value + CGTopic.cp_Index = int(row[0].Value[:-1]) + CGTopic.cp_Topic = row[1].Value + CGTopic.cp_Responsible = row[2].Value + CGTopic.cp_Time = row[3].Value + + ''' + copies the data in this CGTopic object + to the given row. + @param row the row object (PropertyValue array) to + copy the data to. + ''' + + def setDataToRow(self, row): + row[0].Value = "" + str(CGTopic.cp_Index) + "." + row[1].Value = CGTopic.cp_Topic + row[2].Value = CGTopic.cp_Responsible + row[3].Value = CGTopic.cp_Time diff --git a/wizards/com/sun/star/wizards/agenda/TemplateConsts.py b/wizards/com/sun/star/wizards/agenda/TemplateConsts.py new file mode 100644 index 000000000000..364d3d8c1caf --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/TemplateConsts.py @@ -0,0 +1,110 @@ +FILLIN_TITLE = "<title>" +FILLIN_DATE = "<date>" +FILLIN_TIME = "<time>" +FILLIN_LOCATION = "<location>" +''' +section name <b>prefix</b> for sections that contain items. +this is also used as table name prefix, since each items section +must contain a table whos name is identical name to the section's name. +''' +SECTION_ITEMS = "AGENDA_ITEMS" +''' +the name of the section which contains the topics. +''' +SECTION_TOPICS = "AGENDA_TOPICS" +''' +the name of the parent minutes section. +''' +SECTION_MINUTES_ALL = "MINUTES_ALL" +''' +the name of the child nimutes section. +This section will be duplicated for each topic. +''' +SECTION_MINUTES = "MINUTES" +''' +taged headings and names. +These will be searched in item tables (in the template) and will be +replaced with resource strings. + +headings... +''' +FILLIN_MEETING_TYPE = "<meeting-type>" +FILLIN_BRING = "<bring>" +FILLIN_READ = "<read>" +FILLIN_NOTES = "<notes>" +''' +names... +''' +FILLIN_CALLED_BY = "<called-by>" +FILLIN_FACILITATOR = "<facilitator>" +FILLIN_PARTICIPANTS = "<attendees>" +FILLIN_NOTETAKER = "<notetaker>" +FILLIN_TIMEKEEPER = "<timekeeper>" +FILLIN_OBSERVERS = "<observers>" +FILLIN_RESOURCE_PERSONS = "<resource-persons>" +''' +Styles (paragraph styles) used for agenda items. +headings styles + +''' +STYLE_MEETING_TYPE = "MeetingType" +STYLE_BRING = "Bring" +STYLE_READ = "Read" +STYLE_NOTES = "Notes" +''' +names styles +''' +STYLE_CALLED_BY = "CalledBy" +STYLE_FACILITATOR = "Facilitator" +STYLE_PARTICIPANTS = "Attendees" +STYLE_NOTETAKER = "Notetaker" +STYLE_TIMEKEEPER = "Timekeeper" +STYLE_OBSERVERS = "Observers" +STYLE_RESOURCE_PERSONS = "ResourcePersons" +''' +Styles (paragraph styles) used for the <b>text</b> of agenda items +The agenda wizard creates fill-in fields with the given styles...) + +headings fields styles +''' +STYLE_MEETING_TYPE_TEXT = "MeetingTypeText" +STYLE_BRING_TEXT = "BringText" +STYLE_READ_TEXT = "ReadText" +STYLE_NOTES_TEXT = "NotesText" +''' +names field styles +''' +STYLE_CALLED_BY_TEXT = "CalledByText" +STYLE_FACILITATOR_TEXT = "FacilitatorText" +STYLE_PARTICIPANTS_TEXT = "AttendeesText" +STYLE_NOTETAKER_TEXT = "NotetakerText" +STYLE_TIMEKEEPER_TEXT = "TimekeeperText" +STYLE_OBSERVERS_TEXT = "ObserversText" +STYLE_RESOURCE_PERSONS_TEXT = "ResourcePersonsText" +''' +Fillins for the topic table. +These strings will be searched inside the topic table as +part of detecting its structure. +''' +FILLIN_TOPIC_NUMBER = "<num>" +FILLIN_TOPIC_TOPIC = "<topic>" +FILLIN_TOPIC_RESPONSIBLE = "<responsible>" +FILLIN_TOPIC_TIME = "<topic-time>" +''' +fillins for minutes. +These will be searched in the minutes section and will be replaced +with the appropriate data. +''' +FILLIN_MINUTES_TITLE = "<minutes-title>" +FILLIN_MINUTES_LOCATION = "<minutes-location>" +FILLIN_MINUTES_DATE = "<minutes-date>" +FILLIN_MINUTES_TIME = "<minutes-time>" +''' +Minutes-topic fillins +These will be searched in the minutes-child-section, and +will be replaced with topic data. +''' +FILLIN_MINUTE_NUM = "<mnum>" +FILLIN_MINUTE_TOPIC = "<mtopic>" +FILLIN_MINUTE_RESPONSIBLE = "<mresponsible>" +FILLIN_MINUTE_TIME = "<mtime>" diff --git a/wizards/com/sun/star/wizards/agenda/TopicsControl.py b/wizards/com/sun/star/wizards/agenda/TopicsControl.py new file mode 100644 index 000000000000..75c77e6db141 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/TopicsControl.py @@ -0,0 +1,909 @@ +from ui.ControlScroller import ControlScroller +from common.PropertyNames import PropertyNames +from threading import RLock +from AgendaWizardDialogConst import LAST_HID +from common.Properties import Properties +import traceback +import inspect +from common.HelpIds import HelpIds + +''' +@author rpiterman +This class implements the UI functionality of the topics scroller control. +<br/> +During developement, there has been a few changes which were not *fully* done +mainly in converting the topics and time boxes +from combobox and time box to normal textboxes, +so in the code they might be referenced as combobox or timebox. This should be +rather understood as topicstextbox and timetextbox.<br/><br/> +Important behaiviour of this control is that there is always a +blank row at the end, in which the user can enter data.<br/> +Once the row is not blank (thus, the user entered data...), +a new blank row is added.<br/> +Once the user removes the last *unempty* row, by deleteing its data, it becomes +the *last empty row* and the one after is being automatically removed.<br/><br/> +The contorl shows 5 rows at a time.<br/> +If, for example, only 2 rows exist (from which the 2ed one is empty...) +then the other three rows, which do not exist in the data model, are disabled. +<br/> +The following other functionality is implemented: +<br/> +0. synchroniting data between controls, data model and live preview. +1. Tab scrolling.<br/> +2. Keyboard scrolling.<br/> +3. Removing rows and adding new rows.<br/> +4. Moving rows up and down. <br/> +<br/> +This control relays on the ControlScroller control which uses the following +Data model:<br/> +1. It uses a vector, whos members are arrays of PropertyValue.<br/> +2. Each array represents a row.<br/> +(Note: the Name and Value memebrs of the PropertyValue object are being used) +3. Each property Value represents a value +for a single control with the following rules:<br/> +3. a. the Value of the property is used for as value +of the controls (usually text).<br/> +3. b. the Name of the property is used to map values +to UI controls in the following manner:<br/> +3. b. 1. only the Name of the first X Rows is regarded, +where X is the number of visible rows (in the agenda wizard this would be 5, +since 5 topic rows are visible on the dialog).<br/> +3. b. 2. The Names of the first X (or 5...) rows are the names +of the UI Controls to hold values. When the control scroller scrolls, +it looks at the first 5 rows and uses the names specified there to map the +current values to the specified controls. <br/> +This data model makes the following limitations on the implementation: +When moving rows, only the values should be moved. The Rows objects, +which contain also the Names of the controls should not be switched. <br/> +also when deleting or inserting rows, attention should be paid that no rows +should be removed or inserted. Instead, only the Values should rotate. <br/><br/> +To save the topics in the registry a ConfigSet of objects of type CGTopic is +being used. +This one is not synchronized "live", since it is unnecessary... instead, it is +synchronized on call, before the settings should be saved. +''' + +def synchronized(lock): + ''' Synchronization decorator. ''' + def wrap(f): + def newFunction(*args, **kw): + lock.acquire() + try: + return f(*args, **kw) + finally: + lock.release() + return newFunction + return wrap + +class TopicsControl(ControlScroller): + + lock = RLock() + LABEL = "lblTopicCnt_" + TOPIC = "txtTopicTopic_" + RESP = "cbTopicResp_" + TIME = "txtTopicTime_" + I_12 = 12 + I_8 = 8 + nscrollvalue = 0 + LABEL_PROPS = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_LABEL, + PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + TEXT_PROPS = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, + PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, PropertyNames.PROPERTY_TABINDEX, + PropertyNames.PROPERTY_WIDTH) + + def __init__(self, dialog, xmsf, agenda): + super(TopicsControl, self).__init__( + dialog, xmsf, 5, 92, 38, 212, 5, 18, LAST_HID) + self.initializeScrollFields(agenda) + self.initialize(agenda.cp_Topics.getSize() + 1) + # set some focus listeners for TAB scroll down and up... + try: + # prepare scroll down on tab press... + self.lastTime = \ + self.ControlGroupVector[self.nblockincrement - 1].timebox + + self.lastTime.addKeyListener(None) + #prepare scroll up on tab press... + self.firstTopic = self.ControlGroupVector[0].textbox + self.firstTopic.addKeyListener(None) + except Exception: + traceback.print_exc() + + ''' + initializes the data of the control. + @param agenda + ''' + + def initializeScrollFields(self, agenda): + # create a row for each topic with the given values.... + for i in xrange(agenda.cp_Topics.getSize()): + row = self.newRow(i) + agenda.cp_Topics.getElementAt(i).setDataToRow(row) + # a parent class method + self.registerControlGroup(row, i) + self.updateDocumentRow(i) + # inserts a blank row at the end... + self.insertRowAtEnd() + + ''' + Insert a blank (empty) row + as last row of the control. + The control has always a blank row at the + end, which enables the user to enter data... + ''' + + def insertRowAtEnd(self): + l = len(ControlScroller.scrollfields) + self.registerControlGroup(self.newRow(l), l) + self.setTotalFieldCount(l + 1) + # if the new row is visible, it must have been disabled + # so it should be now enabled... + if l - TopicsControl.nscrollvalue < self.nblockincrement: + self.ControlGroupVector[l - TopicsControl.nscrollvalue].Enabled \ + = True + + ''' + The Topics Set in the CGAgenda object is synchronized to + the current content of the topics. + @param agenda + ''' + + def saveTopics(self, agenda): + ControlScroller.ControlScroller_body() + agenda.cp_Topics.clear() + i = 0 + while i < len(scrollfields) - 1: + agenda.cp_Topics.add(i, CGTopic(scrollfields.get(i))) + i += 1 + + ''' + overrides the parent class method to also enable the + row whenever data is written to it. + @param guiRow + ''' + + def fillupControl(self, guiRow): + super(TopicsControl, self).fillupControl(guiRow) + self.ControlGroupVector[guiRow].Enabled = True + + ''' + remove the last row + ''' + + def removeLastRow(self): + l = len(scrollfields) + # if we should scroll up... + if (l - TopicsControl.nscrollvalue) >= 1 \ + and (l - TopicsControl.nscrollvalue) <= self.nblockincrement \ + and TopicsControl.nscrollvalue > 0: + while (l - TopicsControl.nscrollvalue >= 1) \ + and l - TopicsControl.nscrollvalue <= self.nblockincrement \ + and TopicsControl.nscrollvalue > 0: + setScrollValue(TopicsControl.nscrollvalue - 1) + # if we should disable a row... + elif TopicsControl.nscrollvalue == 0 and l - 1 < self.nblockincrement: + self.ControlGroupVector[l - 1].Enable = False + + unregisterControlGroup(l - 1) + setTotalFieldCount(l - 1) + + ''' + in order to use the "move up", "down" "insert" and "remove" buttons, + we track the last control the gained focus, in order to know which + row should be handled. + @param fe + ''' + + def focusGained(self, fe): + xc = fe.Source + focusGained(xc) + + ''' + Sometimes I set the focus programatically to a control + (for example when moving a row up or down, the focus should move + with it). + In such cases, no VCL event is being triggered so it must + be called programtically. + This is done by this method. + @param control + ''' + + def focusGained(self, control): + try: + #calculate in which row we are... + name = Helper.getUnoPropertyValue( + control.Model, PropertyNames.PROPERTY_NAME) + i = name.indexOf("_") + num = name.substring(i + 1) + self.lastFocusRow = int(num) + TopicsControl.nscrollvalue + self.lastFocusControl = control + # enable/disable the buttons... + enableButtons() + except Exception, ex: + ex.printStackTrace() + + ''' + enable or disable the buttons according to the + current row we are in. + ''' + + def enableButtons(self): + UnoDialog.setEnabled( + getAD().btnInsert, self.lastFocusRow < len(scrollfields) - 1) + UnoDialog.setEnabled( + getAD().btnRemove, self.lastFocusRow < len(scrollfields) - 1) + UnoDialog.setEnabled( + getAD().btnUp, self.lastFocusRow > 0) + UnoDialog.setEnabled( + getAD().btnDown, self.lastFocusRow < len(scrollfields) - 1) + + ''' + Removes the current row. + See general class documentation explanation about the + data model used and the limitations which explain the implementation here. + ''' + + def removeRow(self): + lockDoc() + i = self.lastFocusRow + while i < len(scrollfields) - 1: + pv1 = scrollfields.get(i) + pv2 = scrollfields.get(i + 1) + pv1[1].Value = pv2[1].Value + pv1[2].Value = pv2[2].Value + pv1[3].Value = pv2[3].Value + updateDocumentRow(i) + if i - TopicsControl.nscrollvalue < self.nblockincrement: + fillupControl(i - TopicsControl.nscrollvalue) + + i += 1 + removeLastRow() + # update the live preview background document + reduceDocumentToTopics() + # the focus should return to the edit control + focus(self.lastFocusControl) + unlockDoc() + + ''' + Inserts a row before the current row. + See general class documentation explanation about the + data model used and the limitations which explain the implementation here. + ''' + + def insertRow(self): + lockDoc() + insertRowAtEnd() + i = len(scrollfields) - 2 + while i > self.lastFocusRow: + pv1 = scrollfields.get(i) + pv2 = scrollfields.get(i - 1) + pv1[1].Value = pv2[1].Value + pv1[2].Value = pv2[2].Value + pv1[3].Value = pv2[3].Value + updateDocumentRow(i) + if i - TopicsControl.nscrollvalue < self.nblockincrement: + fillupControl(i - TopicsControl.nscrollvalue) + + i -= 1 + # after rotating all the properties from this row on, + # we clear the row, so it is practically a new one... + pv1 = scrollfields.get(self.lastFocusRow) + pv1[1].Value = "" + pv1[2].Value = "" + pv1[3].Value = "" + # update the preview document. + updateDocumentRow(self.lastFocusRow) + fillupControl(self.lastFocusRow - TopicsControl.nscrollvalue) + focus(self.lastFocusControl) + unlockDoc() + + ''' + create a new row with the given index. + The index is important because it is used in the + Name member of the PropertyValue objects. + To know why see general class documentation above (data model explanation) + @param i the index of the new row + @return + ''' + + def newRow(self, i): + pv = [None] * 4 + pv[0] = Properties.createProperty( + TopicsControl.LABEL + str(i), "" + str(i + 1) + ".") + pv[1] = Properties.createProperty(TopicsControl.TOPIC + str(i), "") + pv[2] = Properties.createProperty(TopicsControl.RESP + str(i), "") + pv[3] = Properties.createProperty(TopicsControl.TIME + str(i), "") + return pv + + ''' + Implementation of ControlScroller + This is a UI method which inserts a new row to the control. + It uses the child-class ControlRow. (see below). + @param _index + @param npos + @see ControlRow + ''' + + def insertControlGroup(self, _index, npos): + oControlRow = ControlRow( + ControlScroller.CurUnoDialog, self.iCompPosX, npos, _index, + ControlRow.tabIndex) + self.ControlGroupVector.append(oControlRow) + ControlRow.tabIndex += 4 + + ''' + Implementation of ControlScroller + This is a UI method which makes a row visibele. + As far as I know it is never called. + @param _index + @param _bIsVisible + @see ControlRow + ''' + + def setControlGroupVisible(self, _index, _bIsVisible): + self.ControlGroupVector[_index].Visible = _bIsVisible + + ''' + Checks if a row is empty. + This is used when the last row is changed. + If it is empty, the next row (which is always blank) is removed. + If it is not empty, a next row must exist. + @param row the index number of the row to check. + @return true if empty. false if not. + ''' + + def isRowEmpty(self, row): + data = getTopicData(row) + # now - is this row empty? + return data[1].Value.equals("") and data[2].Value.equals("") \ + and data[3].Value.equals("") + + ''' + update the preview document and + remove/insert rows if needed. + @param guiRow + @param column + ''' + + def fieldChanged(self, guiRow, column): + with TopicsControl.lock: + try: + # First, I update the document + data = getTopicData(guiRow + TopicsControl.nscrollvalue) + if data == None: + return + + equal = True + if self.oldData != None: + i = 0 + while i < data.length and equal: + equal = equal & data[i].Value == self.oldData[i] + i += 1 + if equal: + return + + else: + self.oldData = range(4) + + i = 0 + while i < data.length: + self.oldData[i] = data[i].Value + i += 1 + updateDocumentCell( + guiRow + TopicsControl.nscrollvalue, column, data) + if isRowEmpty(guiRow + TopicsControl.nscrollvalue): + ''' + if this is the row before the last one + (the last row is always empty) + delete the last row... + ''' + if (guiRow + TopicsControl.nscrollvalue) \ + == len(scrollfields) - 2: + removeLastRow() + '''now consequentially check the last two rows, + and remove the last one if they are both empty. + (actually I check always the "before last" row, + because the last one is always empty... + ''' + while len(scrollfields) > 1 \ + and isRowEmpty(len(scrollfields) - 2): + removeLastRow() + cr = self.ControlGroupVector[ + scrollfields.size - TopicsControl.nscrollvalue - 1] + # if a remove was performed, set focus + #to the last row with some data in it... + focus(getControl(cr, column)) + # update the preview document. + reduceDocumentToTopics() + + else: + # row contains data + # is this the last row? + if (guiRow + TopicsControl.nscrollvalue + 1) \ + == len(scrollfields): + insertRowAtEnd() + + except Exception, e: + e.printStackTrace() + + ''' + return the corresponding row data for the given index. + @param topic index of the topic to get. + @return a PropertyValue array with the data for the given topic. + ''' + + def getTopicData(self, topic): + if topic < len(scrollfields): + return scrollfields.get(topic) + else: + return None + + ''' + If the user presses tab on the last control, and + there *are* more rows in the model, scroll down. + @param event + ''' + + def lastControlKeyPressed(self, event): + # if tab without shift was pressed... + if event.KeyCode == Key.TAB and event.Modifiers == 0: + # if there is another row... + if (self.nblockincrement + TopicsControl.nscrollvalue) \ + < len(scrollfields): + setScrollValue(TopicsControl.nscrollvalue + 1) + #focus(firstTopic); + focus(getControl(self.ControlGroupVector[4], 1)) + + ''' + If the user presses shift-tab on the first control, and + there *are* more rows in the model, scroll up. + @param event + ''' + + def firstControlKeyPressed(self, event): + # if tab with shift was pressed... + if (event.KeyCode == Key.TAB) and \ + (event.Modifiers == KeyModifier.SHIFT): + if TopicsControl.nscrollvalue > 0: + setScrollValue(TopicsControl.nscrollvalue - 1) + focus(self.lastTime) + + ''' + sets focus to the given control. + @param textControl + ''' + + def focus(self, textControl): + textControl.setFocus() + text = textControl.Text + textControl.Selection = Selection (0, len(text)) + focusGained(textControl) + + ''' + moves the given row one row down. + @param guiRow the gui index of the row to move. + @param control the control to gain focus after moving. + ''' + + @synchronized(lock) + def rowDown(self, guiRow, control): + if guiRow is None and control is None: + guiRow = self.lastFocusRow - TopicsControl.nscrollvalue + control = self.lastFocusControl + # only perform if this is not the last row. + actuallRow = guiRow + TopicsControl.nscrollvalue + if actuallRow + 1 < len(scrollfields): + # get the current selection + selection = getSelection(control) + # the last row should scroll... + scroll = guiRow == (self.nblockincrement - 1) + if scroll: + setScrollValue(TopicsControl.nscrollvalue + 1) + + scroll1 = TopicsControl.nscrollvalue + if scroll: + aux = -1 + else: + aux = 1 + switchRows(guiRow, guiRow + aux) + if TopicsControl.nscrollvalue != scroll1: + guiRow += (TopicsControl.nscrollvalue - scroll1) + + setSelection(guiRow + (not scroll), control, selection) + + ''' + move the current row up + ''' + + @synchronized(lock) + def rowUp(self, guiRow=None, control=None): + if guiRow is None and control is None: + guiRow = self.lastFocusRow - TopicsControl.nscrollvalue + control = self.lastFocusControl + # only perform if this is not the first row + actuallRow = guiRow + TopicsControl.nscrollvalue + if actuallRow > 0: + # get the current selection + selection = getSelection(control) + # the last row should scroll... + scroll = (guiRow == 0) + if scroll: + setScrollValue(TopicsControl.nscrollvalue - 1) + if scroll: + aux = 1 + else: + aux = -1 + switchRows(guiRow, guiRow + aux) + setSelection(guiRow - (not scroll), control, selection) + + ''' + moves the cursor up. + @param guiRow + @param control + ''' + + @synchronized(lock) + def cursorUp(self, guiRow, control): + # is this the last full row ? + actuallRow = guiRow + TopicsControl.nscrollvalue + #if this is the first row + if actuallRow == 0: + return + # the first row should scroll... + + scroll = (guiRow == 0) + if scroll: + setScrollValue(TopicsControl.nscrollvalue - 1) + upperRow = self.ControlGroupVector[guiRow] + else: + upperRow = self.ControlGroupVector[guiRow - 1] + + focus(getControl(upperRow, control)) + + ''' + moves the cursor down + @param guiRow + @param control + ''' + + @synchronized(lock) + def cursorDown(self, guiRow, control): + # is this the last full row ? + actuallRow = guiRow + TopicsControl.nscrollvalue + #if this is the last row, exit + if actuallRow == len(scrollfields) - 1: + return + # the first row should scroll... + + scroll = (guiRow == self.nblockincrement - 1) + if scroll: + setScrollValue(TopicsControl.nscrollvalue + 1) + lowerRow = self.ControlGroupVector[guiRow] + else: + # if we scrolled we are done... + #otherwise.. + lowerRow = self.ControlGroupVector[guiRow + 1] + + focus(getControl(lowerRow, control)) + + ''' + changes the values of the given rows with eachother + @param row1 one can figure out what this parameter is... + @param row2 one can figure out what this parameter is... + ''' + + def switchRows(self, row1, row2): + o1 = scrollfields.get(row1 + TopicsControl.nscrollvalue) + o2 = scrollfields.get(row2 + TopicsControl.nscrollvalue) + temp = None + i = 1 + while i < o1.length: + temp = o1[i].Value + o1[i].Value = o2[i].Value + o2[i].Value = temp + i += 1 + fillupControl(row1) + fillupControl(row2) + updateDocumentRow(row1 + TopicsControl.nscrollvalue, o1) + updateDocumentRow(row2 + TopicsControl.nscrollvalue, o2) + ''' + if we changed the last row, add another one... + ''' + if (row1 + TopicsControl.nscrollvalue + 1 == len(scrollfields)) \ + or (row2 + TopicsControl.nscrollvalue + 1 == len(scrollfields)): + insertRowAtEnd() + ''' + if we did not change the last row but + we did change the one before - check if we + have two empty rows at the end. + If so, delete the last one... + ''' + elif (row1 + TopicsControl.nscrollvalue) + \ + (row2 + TopicsControl.nscrollvalue) \ + == (len(scrollfields) * 2 - 5): + if isRowEmpty(len(scrollfields) - 2) \ + and isRowEmpty(len(scrollfields) - 1): + removeLastRow() + reduceDocumentToTopics() + + ''' + sets a text selection to a given control. + This is used when one moves a row up or down. + After moving row X to X+/-1, the selection (or cursor position) of the + last focused control should be restored. + The control's row is the given guiRow. + The control's column is detecte4d according to the given event. + This method is called as subsequent to different events, + thus it is comfortable to use the event here to detect the column, + rather than in the different event methods. + @param guiRow the row of the control to set the selection to. + @param eventSource helps to detect + the control's column to set the selection to. + @param s the selection object to set. + ''' + + def setSelection(self, guiRow, eventSource, s): + cr = self.ControlGroupVector[guiRow] + control = getControl(cr, eventSource) + control.setFocus() + control.setSelection(s) + + ''' + returns a control out of the given row, according to a column number. + @param cr control row object. + @param column the column number. + @return the control... + ''' + + def getControl(self, cr, column): + tmp_switch_var1 = column + if tmp_switch_var1 == 0: + return cr.label + elif tmp_switch_var1 == 1: + return cr.textbox + elif tmp_switch_var1 == 2: + return cr.combobox + elif tmp_switch_var1 == 3: + return cr.timebox + else: + raise IllegalArgumentException ("No such column"); + + ''' + returns a control out of the given row, which is + in the same column as the given control. + @param cr control row object + @param control a control indicating a column. + @return + ''' + + def getControl(self, cr, control): + column = getColumn(control) + return getControl(cr, column) + + ''' + returns the column number of the given control. + @param control + @return + ''' + + def getColumn(self, control): + name = Helper.getUnoPropertyValue( + UnoDialog2.getModel(control), PropertyNames.PROPERTY_NAME) + if name.startswith(TopicsControl.TOPIC): + return 1 + if name.startswith(TopicsControl.RESP): + return 2 + if name.startswith(TopicsControl.TIME): + return 3 + if name.startswith(TopicsControl.LABEL): + return 0 + return -1 + + ''' + update the given row in the preview document with the given data. + @param row + @param data + ''' + + def updateDocumentRow(self, row, data=None): + if data is None: + data = ControlScroller.scrollfields[row] + try: + ControlScroller.CurUnoDialog.agendaTemplate.topics.write( + row, data) + except Exception, ex: + traceback.print_exc() + + ''' + updates a single cell in the preview document. + Is called when a single value is changed, since we really + don't have to update the whole row for one small changhe... + @param row the data row to update (topic number). + @param column the column to update (a gui column, not a document column). + @param data the data of the entire row. + ''' + + def updateDocumentCell(self, row, column, data): + try: + ControlScroller.CurUnoDialog.agendaTemplate.topics.writeCell( + row, column, data) + except Exception, ex: + traceback.print_exc() + + ''' + when removeing rows, this method updates + the preview document to show the number of rows + according to the data model. + ''' + + def reduceDocumentToTopics(self): + try: + ControlScroller.CurUnoDialog.agendaTemplate.topics.reduceDocumentTo(len(scrollfields) - 1) + except Exception, ex: + traceback.print_exc() + +''' +@author rp143992 +A class represting a single GUI row. +Note that the instance methods of this class +are being called and handle controls of +a single row. +''' +class ControlRow(object): + + + tabIndex = 520 + ''' + constructor. Create the row in the given dialog given cordinates, + with the given offset (row number) and tabindex. + Note that since I use this specifically for the agenda wizard, + the step and all control coordinates inside the + row are constant (5). + @param dialog the agenda dialog + @param x x coordinates + @param y y coordinates + @param i the gui row index + @param tabindex first tab index for this row. + ''' + + def __init__(self, dialog, x, y, i, tabindex): + self.offset = i + self.dialog = dialog + self.label = self.dialog.insertLabel( + TopicsControl.LABEL + str(i), + TopicsControl.LABEL_PROPS, + (TopicsControl.I_8, "" + str(i + 1) + ".", + x + 4, y + 2, ControlScroller.iStep, tabindex, 10)) + self.textbox = self.dialog.insertTextField( + TopicsControl.TOPIC + str(i), "topicTextChanged", + TopicsControl.TEXT_PROPS, + (TopicsControl.I_12, + HelpIds.getHelpIdString(ControlScroller.curHelpIndex + i * 3 + 1), + x + 15, y, ControlScroller.iStep, tabindex + 1, 84), self) + self.combobox = self.dialog.insertTextField( + TopicsControl.RESP + str(i), "responsibleTextChanged", + TopicsControl.TEXT_PROPS, + (TopicsControl.I_12, + HelpIds.getHelpIdString(ControlScroller.curHelpIndex + i * 3 + 2), + x + 103, y, ControlScroller.iStep, tabindex + 2, 68), self) + self.timebox = self.dialog.insertTextField( + TopicsControl.TIME + str(i), "timeTextChanged", + TopicsControl.TEXT_PROPS, + (TopicsControl.I_12, + HelpIds.getHelpIdString(ControlScroller.curHelpIndex + i * 3 + 3), + x + 175, y, ControlScroller.iStep, tabindex + 3, 20), self) + self.setEnabled(False) + self.textbox.addKeyListener(None) + self.combobox.addKeyListener(None) + self.timebox.addKeyListener(None) + self.textbox.addFocusListener(None) + self.combobox.addFocusListener(None) + self.timebox.addFocusListener(None) + + def topicTextChanged(self): + try: + # update the data model + fieldInfo(self.offset, 1) + # update the preview document + fieldChanged(self.offset, 1) + except Exception, ex: + ex.printStackTrace() + + ''' + called through an event listener when the + responsible text is changed by the user. + updates the data model and the preview document. + ''' + + def responsibleTextChanged(self): + try: + # update the data model + fieldInfo(self.offset, 2) + # update the preview document + fieldChanged(self.offset, 2) + except Exception, ex: + ex.printStackTrace() + + ''' + called through an event listener when the + time text is changed by the user. + updates the data model and the preview document. + ''' + + def timeTextChanged(self): + try: + # update the data model + fieldInfo(self.offset, 3) + # update the preview document + fieldChanged(self.offset, 3) + except Exception, ex: + ex.printStackTrace() + + ''' + enables/disables the row. + @param enabled true for enable, false for disable. + ''' + + def setEnabled(self, enabled): + if enabled: + b = True + else: + b = False + + self.dialog.setEnabled(self.label, b) + self.dialog.setEnabled(self.textbox, b) + self.dialog.setEnabled(self.combobox, b) + self.dialog.setEnabled(self.timebox, b) + + ''' + Impelementation of XKeyListener. + Optionally performs the one of the following: + cursor up, or down, row up or down + ''' + + def keyPressed(self, event): + if isMoveDown(event): + rowDown(self.offset, event.Source) + elif isMoveUp(event): + rowUp(self.offset, event.Source) + elif isDown(event): + cursorDown(self.offset, event.Source) + elif isUp(event): + cursorUp(self.offset, event.Source) + + enableButtons() + + ''' + returns the column number of the given control. + The given control must belong to this row or + an IllegalArgumentException will accure. + @param control + @return an int columnd number of the given control (0 to 3). + ''' + + def getColumn(self, control): + if control == self.textbox: + return 1 + elif control == self.combobox: + return 2 + elif control == self.timebox: + return 3 + elif control == self.label: + return 0 + else: + raise AttributeError("Control is not part of this ControlRow") + + def isMoveDown(self, e): + return (e.KeyCode == Key.DOWN) and (e.Modifiers == KeyModifier.MOD1) + + def isMoveUp(self, e): + return (e.KeyCode == Key.UP) and (e.Modifiers == KeyModifier.MOD1) + + def isDown(self, e): + return (e.KeyCode == Key.DOWN) and (e.Modifiers == 0) + + def isUp(self, e): + return (e.KeyCode == Key.UP) and (e.Modifiers == 0) diff --git a/wizards/com/sun/star/wizards/agenda/__init__.py b/wizards/com/sun/star/wizards/agenda/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/wizards/com/sun/star/wizards/agenda/__init__.py diff --git a/wizards/com/sun/star/wizards/common/ConfigSet.py b/wizards/com/sun/star/wizards/common/ConfigSet.py new file mode 100644 index 000000000000..8da07a638587 --- /dev/null +++ b/wizards/com/sun/star/wizards/common/ConfigSet.py @@ -0,0 +1,227 @@ +import traceback +from ConfigNode import * + +class ConfigSet(ConfigNode): + ''' + After reading the configuration set items, + the ConfigSet checks this field. + If it is true, it will remove any nulls from + the vector. + subclasses can change this field in the constructor + to avoid this "deletion" of nulls. + ''' + + def __init__(self, childType): + self.childClass = childType + self.childrenMap = {} + self.childrenList = [] + self.noNulls = False + + def add(self, name, o): + self.childrenMap[name] = o + if isinstance(name, int): + i = name + self.childrenList.insert(i, o) + self.fireListDataListenerIntervalAdded(i, i) + else: + i = o.cp_Index + oldSize = self.getSize() + if oldSize <= i: + newSize = i - oldSize + self.childrenList += [None] * newSize + self.noNulls = True + else: + self.noNulls = False + self.childrenList.insert(i, o); + if oldSize > i: + oldSize = i + #COMMENTED + #self.fireListDataListenerIntervalAdded(oldSize, i) + + def writeConfiguration(self, configView, param): + names = self.childrenMap.keySet().toArray() + if isinstance(self.childClass, ConfigNode): + #first I remove all the children from the configuration. + children = Configuration.getChildrenNames(configView) + i = 0 + while i < children.length: + try: + Configuration.removeNode(configView, children[i]) + except Exception, ex: + ex.printStackTrace() + + # and add them new. + i += 1 + for i in names: + try: + child = getElement(i) + childView = Configuration.addConfigNode(configView, i) + child.writeConfiguration(childView, param) + except Exception, ex: + ex.printStackTrace() + else: + raise AttributeError ( + "Unable to write primitive sets to configuration (not implemented)") + + def readConfiguration(self, configurationView, param): + names = configurationView.ElementNames + if isinstance(self.childClass, ConfigNode): + for i in names: + try: + child = type(self.childClass)() + child.setRoot(self.root) + child.readConfiguration( + configurationView.getByName(i), param) + self.add(i, child) + except Exception, ex: + traceback.print_exc() + #remove any nulls from the list + if self.noNulls: + i = 0 + while i < len(self.childrenList): + if self.childrenList[i] is None: + del self.childrenList[i] + i -= 1 + i += 1 + + else: + for i in names: + try: + child = configurationView.getByName(i) + self.add(i, child) + except Exception, ex: + traceback.print_exc() + + def remove(self, obj): + key = getKey(obj) + self.childrenMap.remove(key) + i = self.childrenList.indexOf(obj) + self.childrenList.remove(obj) + fireListDataListenerIntervalRemoved(i, i) + + def remove(self, i): + o = getElementAt(i) + remove(o) + + def clear(self): + self.childrenMap.clear() + del self.childrenList[:] + + def update(self, i): + fireListDataListenerContentsChanged(i, i) + + def createDOM(self, parent): + items = items() + i = 0 + while i < items.length: + item = items[i] + if item.instanceof.XMLProvider: + item.createDOM(parent) + + i += 1 + return parent + + def items(self): + return self.childrenList.toArray() + + def getKey(self, object): + i = self.childrenMap.entrySet().iterator() + while i.hasNext(): + me = i.next() + if me.getValue() == object: + return me.getKey() + + return None + + def getKey(self, i): + c = 0 + while i > -1: + if getElementAt(c) != None: + i -= 1 + + c += 1 + if c == 0: + return None + else: + return getKey(getElementAt(c - 1)) + + def setRoot(self, newRoot): + self.root = newRoot + + ''' + Notifies all registered listeners about the event. + @param event The event to be fired + ''' + + def fireListDataListenerIntervalAdded(self, i0, i1): + event = ListDataEvent(self, ListDataEvent.INTERVAL_ADDED, i0, i1) + if self.listenerList == None: + return + + listeners = self.listenerList.getListenerList() + i = listeners.length - 2 + while i >= 0: + if listeners[i] == javax.swing.event.ListDataListener: + (listeners[i + 1]).intervalAdded(event) + + i -= 2 + + def getElementAt(self, i): + return self.childrenList[i] + + def getElement(self, o): + return self.childrenMap[o] + + def getSize(self): + return len(self.childrenList) + + def keys(self): + return self.childrenMap.keySet() + + def getIndexOf(self, item): + return self.childrenList.index(item) + + ''' + Set members might include a property + which orders them. + This method reindexes the given member to be + the index number 0 + Do not forget to call commit() after calling this method. + @param confView + @param memebrName + ''' + + def reindexSet(self, confView, memberName, indexPropertyName): + ''' + First I read all memebrs of the set, + except the one that should be number 0 + to a vector, ordered by there index property + ''' + names = Configuration.getChildrenNames(confView) + v = Vector.Vector_unknown(names.length) + member = None + index = 0 + i = 0 + while i < names.length: + if not names[i].equals(memberName): + member = Configuration.getConfigurationNode(names[i], confView) + index = Configuration.getInt(indexPropertyName, member) + while index >= v.size(): + v.add(None) + v.setElementAt(member, index) + ''' + Now I reindex them + ''' + + i += 1 + index = 1 + i = 0 + while i < v.size(): + member = v.get(i) + if member != None: + Configuration.set((index + 1), indexPropertyName, member) + + i += 1 + + def sort(self, comparator): + Collections.sort(self.childrenList, comparator) diff --git a/wizards/com/sun/star/wizards/common/Desktop.py b/wizards/com/sun/star/wizards/common/Desktop.py index 3a64ecee8669..7184c5d99893 100644 --- a/wizards/com/sun/star/wizards/common/Desktop.py +++ b/wizards/com/sun/star/wizards/common/Desktop.py @@ -1,11 +1,10 @@ -import uno +from uno import getComponentContext import traceback from com.sun.star.frame.FrameSearchFlag import ALL, PARENT from com.sun.star.util import URL from com.sun.star.i18n.KParseTokens import ANY_LETTER_OR_NUMBER, ASC_UNDERSCORE from NoValidPathException import * - class Desktop(object): @classmethod @@ -54,38 +53,8 @@ class Desktop(object): return None @classmethod - def getDispatchURL(self, xMSF, _sURL): - try: - oTransformer = xMSF.createInstance( - "com.sun.star.util.URLTransformer") - oURL = range(1) - oURL[0] = com.sun.star.util.URL.URL() - oURL[0].Complete = _sURL - xTransformer.parseStrict(oURL) - return oURL[0] - except Exception, e: - e.printStackTrace(System.out) - - return None - - @classmethod - def dispatchURL(self, xMSF, sURL, xFrame, _stargetframe): - oURL = getDispatchURL(xMSF, sURL) - xDispatch = getDispatcher(xMSF, xFrame, _stargetframe, oURL) - dispatchURL(xDispatch, oURL) - - @classmethod - def dispatchURL(self, xMSF, sURL, xFrame): - dispatchURL(xMSF, sURL, xFrame, "") - - @classmethod - def dispatchURL(self, _xDispatch, oURL): - oArg = range(0) - _xDispatch.dispatch(oURL, oArg) - - @classmethod def connect(self, connectStr): - localContext = uno.getComponentContext() + localContext = getComponentContext() resolver = localContext.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", localContext) ctx = resolver.resolve( connectStr ) @@ -93,6 +62,27 @@ class Desktop(object): return orb @classmethod + def getIncrementSuffix(self, xElementContainer, sElementName): + bElementexists = True + i = 1 + sIncSuffix = "" + BaseName = sElementName + while bElementexists: + try: + bElementexists = xElementContainer.hasByName(sElementName) + except: + bElementexists = xElementContainer.hasByHierarchicalName( + sElementName) + if bElementexists: + i += 1 + sElementName = BaseName + str(i) + + if i > 1: + sIncSuffix = str(i) + + return sIncSuffix + + @classmethod def checkforfirstSpecialCharacter(self, _xMSF, _sString, _aLocale): try: nStartFlags = ANY_LETTER_OR_NUMBER + ASC_UNDERSCORE @@ -129,51 +119,9 @@ class Desktop(object): @classmethod def getUniqueName(self, xElementContainer, sElementName): - bElementexists = True - i = 1 - sIncSuffix = "" - BaseName = sElementName - while bElementexists == True: - bElementexists = xElementContainer.hasByName(sElementName) - if bElementexists == True: - i += 1 - sElementName = BaseName + str(i) - - if i > 1: - sIncSuffix = str(i) - + sIncSuffix = self.getIncrementSuffix(xElementContainer, sElementName) return sElementName + sIncSuffix - ''' - Checks if the passed Element Name already exists in the list If yes it - ppends a suffix to make it unique - @param _slist - @param _sElementName - @param _sSuffixSeparator - @return a unique Name not being in the passed list. - ''' - - @classmethod - def getUniqueNameList(self, _slist, _sElementName, _sSuffixSeparator): - a = 2 - scompname = _sElementName - bElementexists = True - if _slist == None: - return _sElementName - - if _slist.length == 0: - return _sElementName - - while bElementexists == True: - i = 0 - while i < _slist.length: - if JavaTools.FieldInList(_slist, scompname) == -1: - return scompname - - i += 1 - scompname = _sElementName + _sSuffixSeparator + (a + 1) - return "" - class OfficePathRetriever: def OfficePathRetriever(self, xMSF): diff --git a/wizards/com/sun/star/wizards/common/FileAccess.py b/wizards/com/sun/star/wizards/common/FileAccess.py index 5f92d8aa303c..1f6f741ad5dc 100644 --- a/wizards/com/sun/star/wizards/common/FileAccess.py +++ b/wizards/com/sun/star/wizards/common/FileAccess.py @@ -148,9 +148,8 @@ class FileAccess(object): _sPath + "_internal") Template_user = xPathInterface.getPropertyValue(_sPath + "_user") i = 0 - while i < len(Template_internal): - sPath = Template_internal[i] - if sPath.startsWith("vnd."): + for i in Template_internal: + if i.startsWith("vnd."): # if there exists a language in the directory, # we try to add the right language sPathToExpand = sPath.substring(len("vnd.sun.star.Expand:")) diff --git a/wizards/com/sun/star/wizards/common/SystemDialog.py b/wizards/com/sun/star/wizards/common/SystemDialog.py index d0e8400b7c97..54febcbf5180 100644 --- a/wizards/com/sun/star/wizards/common/SystemDialog.py +++ b/wizards/com/sun/star/wizards/common/SystemDialog.py @@ -158,13 +158,10 @@ class SystemDialog(object): "com.sun.star.document.FilterFactory") oObject = Helper.getUnoObjectbyName(oFactory, filterName) xPropertyValue = list(oObject) - i = 0 - while i < len(xPropertyValue): - aValue = xPropertyValue[i] - if aValue != None and aValue.Name == "UIName": - return str(aValue.Value) + for i in xPropertyValue: + if i is not None and i.Name == "UIName": + return str(i.Value) - i += 1 raise NullPointerException( "UIName property not found for Filter " + filterName); except Exception, exception: @@ -173,7 +170,7 @@ class SystemDialog(object): @classmethod def showErrorBox(self, xMSF, ResName, ResPrefix, - ResID,AddTag=None, AddString=None): + ResID, AddTag=None, AddString=None): ProductName = Configuration.getProductName(xMSF) oResource = Resource(xMSF, ResPrefix) sErrorMessage = oResource.getResText(ResID) @@ -216,7 +213,7 @@ class SystemDialog(object): oDescriptor.Type = MODALTOP oDescriptor.WindowAttributes = windowAttribute xMsgPeer = xToolkit.createWindow(oDescriptor) - xMsgPeer.setMessageText(MessageText) + xMsgPeer.MessageText = MessageText iMessage = xMsgPeer.execute() xMsgPeer.dispose() except Exception: diff --git a/wizards/com/sun/star/wizards/text/TextDocument.py b/wizards/com/sun/star/wizards/text/TextDocument.py index 60b4c080f294..0f5465a11750 100644 --- a/wizards/com/sun/star/wizards/text/TextDocument.py +++ b/wizards/com/sun/star/wizards/text/TextDocument.py @@ -190,7 +190,7 @@ class TextDocument(object): return iScale def unlockallControllers(self): - while TextDocument.xTextDocument.hasControllersLocked() == True: + while TextDocument.xTextDocument.hasControllersLocked(): TextDocument.xTextDocument.unlockControllers() def refresh(self): diff --git a/wizards/com/sun/star/wizards/text/TextSectionHandler.py b/wizards/com/sun/star/wizards/text/TextSectionHandler.py index 67eee12e2d51..ecd2c7a7c2c4 100644 --- a/wizards/com/sun/star/wizards/text/TextSectionHandler.py +++ b/wizards/com/sun/star/wizards/text/TextSectionHandler.py @@ -1,4 +1,6 @@ import traceback +from uno import createUnoStruct +from common.Helper import Helper class TextSectionHandler(object): '''Creates a new instance of TextSectionHandler''' @@ -65,24 +67,24 @@ class TextSectionHandler(object): def breakLinkofTextSections(self): try: - iSectionCount = self.xTextDocument.TextSections.getCount() - oSectionLink = SectionFileLink.SectionFileLink() + iSectionCount = self.xTextDocument.TextSections.Count + oSectionLink = \ + createUnoStruct('com.sun.star.text.SectionFileLink') oSectionLink.FileURL = "" - i = 0 - while i < iSectionCount: + for i in xrange(iSectionCount): oTextSection = xAllTextSections.getByIndex(i) Helper.setUnoPropertyValues( - oTextSection, ["FileLink", "LinkRegion"], - [oSectionLink, ""]) - i += 1 + oTextSection, ("FileLink", "LinkRegion"), + (oSectionLink, "")) except Exception, exception: traceback.print_exc() def breakLinkOfTextSection(self, oTextSection): - oSectionLink = SectionFileLink.SectionFileLink() + oSectionLink = \ + createUnoStruct('com.sun.star.text.SectionFileLink') oSectionLink.FileURL = "" Helper.setUnoPropertyValues( - oTextSection, ["FileLink", "LinkRegion"],[oSectionLink, ""]) + oTextSection, ("FileLink", "LinkRegion"),(oSectionLink, "")) def linkSectiontoTemplate(self, TemplateName, SectionName): try: @@ -93,14 +95,15 @@ class TextSectionHandler(object): traceback.print_exc() def linkSectiontoTemplate(self, oTextSection, TemplateName, SectionName): - oSectionLink = SectionFileLink.SectionFileLink() + oSectionLink = \ + createUnoStruct('com.sun.star.text.SectionFileLink') oSectionLink.FileURL = TemplateName Helper.setUnoPropertyValues( - oTextSection, ["FileLink", "LinkRegion"], - [oSectionLink, SectionName]) - NewSectionName = oTextSection.getName() - if NewSectionName.compareTo(SectionName) != 0: - oTextSection.setName(SectionName) + oTextSection, ("FileLink", "LinkRegion"), + (oSectionLink, SectionName)) + NewSectionName = oTextSection.Name + if NewSectionName != SectionName: + oTextSection.Name = SectionName def insertTextSection(self, GroupName, TemplateName, _bAddParagraph): try: diff --git a/wizards/com/sun/star/wizards/ui/ControlScroller.py b/wizards/com/sun/star/wizards/ui/ControlScroller.py new file mode 100644 index 000000000000..20820315e79b --- /dev/null +++ b/wizards/com/sun/star/wizards/ui/ControlScroller.py @@ -0,0 +1,293 @@ +from common.Desktop import Desktop +from common.PropertyNames import PropertyNames +from common.HelpIds import HelpIds +from com.sun.star.awt.ScrollBarOrientation import HORIZONTAL, VERTICAL +from uno import Any +from common.Helper import Helper +import traceback +from ui.UnoDialog import UnoDialog + +class ControlScroller(object): + + SORELFIRSTPOSY = 3 + iScrollBarWidth = 10 + scrollfields = [] + CurUnoDialog = None + iStep = None + curHelpIndex = None + + # TODO add parameters for tabindices and helpindex + def __init__(self, _CurUnoDialog, _xMSF, _iStep, _iCompPosX, _iCompPosY, + _iCompWidth, _nblockincrement, _nlinedistance, _firsthelpindex): + self.xMSF = _xMSF + self.nblockincrement = _nblockincrement + ControlScroller.CurUnoDialog = _CurUnoDialog + ControlScroller.iStep = _iStep + ControlScroller.curHelpIndex = _firsthelpindex + self.curtabindex = ControlScroller.iStep * 100 + self.linedistance = _nlinedistance + self.iCompPosX = _iCompPosX + self.iCompPosY = _iCompPosY + self.iCompWidth = _iCompWidth + self.iCompHeight = 2 * ControlScroller.SORELFIRSTPOSY + \ + self.nblockincrement * self.linedistance + self.iStartPosY = self.iCompPosY + ControlScroller.SORELFIRSTPOSY + ScrollHeight = self.iCompHeight - 2 + self.nlineincrement = 1 + self.sincSuffix = Desktop.getIncrementSuffix( + ControlScroller.CurUnoDialog.xDialogModel, "imgBackground") + self.oImgControl = ControlScroller.CurUnoDialog.insertControlModel( + "com.sun.star.awt.UnoControlImageControlModel", + "imgBackground" + self.sincSuffix, + ("Border", PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_WIDTH), + (Any("short", "1"),self.iCompHeight, self.iCompPosX, + self.iCompPosY, ControlScroller.iStep, self.iCompWidth)) + self.oImgControl = ControlScroller.CurUnoDialog.xUnoDialog.getControl( + "imgBackground" + self.sincSuffix) + self.setComponentMouseTransparent() + self.xScrollBar = ControlScroller.CurUnoDialog.insertScrollBar( + "TitleScrollBar" + self.sincSuffix, + ("Border", PropertyNames.PROPERTY_ENABLED, + PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, "Orientation", + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + PropertyNames.PROPERTY_STEP, + PropertyNames.PROPERTY_WIDTH), + (0, True, ScrollHeight, + HelpIds.getHelpIdString(ControlScroller.curHelpIndex), + VERTICAL, self.iCompPosX + self.iCompWidth - \ + ControlScroller.iScrollBarWidth - 1, + self.iCompPosY + 1, ControlScroller.iStep, + ControlScroller.iScrollBarWidth), 0, self) + self.nscrollvalue = 0 + self.ControlGroupVector = [] + ypos = self.iStartPosY + ControlScroller.SORELFIRSTPOSY + for i in xrange(self.nblockincrement): + self.insertControlGroup(i, ypos) + ypos += self.linedistance + + def setComponentMouseTransparent(self): + pass + #COMMENTED + #ControlScroller.CurUnoDialog.getPeerConfiguration(). + #setPeerProperties(self.oImgControl, ["MouseTransparent"], [True]) + + def setScrollBarOrientationHorizontal(self): + Helper.setUnoPropertyValue(self.xScrollBar, "Orientation",HORIZONTAL) + + ''' + @author bc93774 + @param _ntotfieldcount: The number of fields that are + to be administered by the ControlScroller + ''' + + def initialize(self, _ntotfieldcount): + try: + self.ntotfieldcount = _ntotfieldcount + self.setCurFieldCount() + self.nscrollvalue = 0 + Helper.setUnoPropertyValue( + self.xScrollBar.Model, "ScrollValue", self.nscrollvalue) + if self.ntotfieldcount > self.nblockincrement: + Helper.setUnoPropertyValues( + self.xScrollBar.Model, (PropertyNames.PROPERTY_ENABLED, + "BlockIncrement", "LineIncrement", + "ScrollValue", "ScrollValueMax"), + (True, self.nblockincrement, self.nlineincrement, + self.nscrollvalue, + self.ntotfieldcount - self.nblockincrement)) + else: + Helper.setUnoPropertyValues( + self.xScrollBar.Model, + (PropertyNames.PROPERTY_ENABLED, "ScrollValue"), + (False, self.nscrollvalue)) + + self.fillupControls(True) + except Exception: + traceback.print_exc() + + def fillupControls(self, binitialize): + for i in xrange(0, self.nblockincrement): + if i < self.ncurfieldcount: + self.fillupControl(i) + + if binitialize: + ControlScroller.CurUnoDialog.repaintDialogStep() + + @classmethod + def fillupControl(self, guiRow): + nameProps = ControlScroller.scrollfields[guiRow] + valueProps = ControlScroller.scrollfields[guiRow + self.nscrollvalue] + for i in nameProps: + if ControlScroller.CurUnoDialog.xDialogModel.hasByName(i.Name): + self.setControlData(i.Name, i.Value) + else: + raise AttributeError("No such control !") + + def setScrollValue(self, _nscrollvalue, _ntotfieldcount=None): + if _ntotfieldcount is not None: + setTotalFieldCount(_ntotfieldcount) + if _nscrollvalue >= 0: + Helper.setUnoPropertyValue( + self.xScrollBar.Model, "ScrollValue", _nscrollvalue) + scrollControls() + + def setCurFieldCount(self): + if self.ntotfieldcount > self.nblockincrement: + self.ncurfieldcount = self.nblockincrement + else: + self.ncurfieldcount = self.ntotfieldcount + + def setTotalFieldCount(self, _ntotfieldcount): + self.ntotfieldcount = _ntotfieldcount + self.setCurFieldCount() + if self.ntotfieldcount > self.nblockincrement: + Helper.setUnoPropertyValues( + self.xScrollBar.Model, + (PropertyNames.PROPERTY_ENABLED, "ScrollValueMax"), + (True, self.ntotfieldcount - self.nblockincrement)) + else: + Helper.setUnoPropertyValue(self.xScrollBar.Model, + PropertyNames.PROPERTY_ENABLED, False) + + def toggleComponent(self, _bdoenable): + bdoenable = _bdoenable and \ + (self.ntotfieldcount > self.nblockincrement) + ControlScroller.CurUnoDialog.setControlProperty( + "TitleScrollBar" + self.sincSuffix, + PropertyNames.PROPERTY_ENABLED, bdoenable) + + def toggleControls(self, _bdoenable): + n = 0 + while n < ControlScroller.scrollfields.size(): + curproperties = ControlScroller.scrollfields.elementAt(n) + m = 0 + while m < curproperties.length: + curproperty = curproperties[m] + ControlScroller.CurUnoDialog.setControlProperty( + curproperty.Name, PropertyNames.PROPERTY_ENABLED, _bdoenable) + m += 1 + n += 1 + + def setLineIncrementation(self, _nlineincrement): + self.nlineincrement = _nlineincrement + Helper.setUnoPropertyValue( + self.xScrollBar.Model, "LineIncrement", self.nlineincrement) + + def getLineIncrementation(self): + return self.nlineincrement + + def setBlockIncrementation(self, _nblockincrement): + self.nblockincrement = _nblockincrement + Helper.setUnoPropertyValues( + self.xScrollBar.Model, + (PropertyNames.PROPERTY_ENABLED, "BlockIncrement", + "ScrollValueMax"), + (self.ntotfieldcount > self.nblockincrement, self.nblockincrement, + self.ntotfieldcount - self.nblockincrement)) + + def scrollControls(self): + try: + scrollRowsInfo() + self.nscrollvalue = int(Helper.getUnoPropertyValue( + self.xScrollBar.Model, "ScrollValue")) + if self.nscrollvalue + self.nblockincrement >= self.ntotfieldcount: + self.nscrollvalue = self.ntotfieldcount - self.nblockincrement + + fillupControls(False) + except java.lang.Exception, ex: + ex.printStackTrace() + + def scrollRowsInfo(self): + if ControlScroller.scrollfields.size() > 0: + cols = len(ControlScroller.scrollfields[0]) + else: + cols = 0 + + a = 0 + while a < self.ncurfieldcount: + n = 0 + while n < cols: + fieldInfo(a, n) + n += 1 + a += 1 + + ''' + updates the corresponding data to + the control in guiRow and column + @param guiRow 0 based row index + @param column 0 based column index + @return the propertyValue object corresponding to + this control. + ''' + + def fieldInfo(self, guiRow, column): + if guiRow + self.nscrollvalue < ControlScroller.scrollfields.size(): + pv = fieldInfo( + (ControlScroller.scrollfields.elementAt( + guiRow + self.nscrollvalue))[column], + (ControlScroller.scrollfields.elementAt(guiRow))[column]) + return pv + else: + return None + + def fieldInfo(self, valueProp, nameProp): + if ControlScroller.CurUnoDialog.xDialogModel.hasByName(nameProp.Name): + valueProp.Value = getControlData(nameProp.Name) + else: + valueProp.Value = nameProp.Value + + return valueProp + + def unregisterControlGroup(self, _index): + ControlScroller.scrollfields.remove(_index) + + def registerControlGroup(self, _currowproperties, _i): + if _i == 0: + del ControlScroller.scrollfields[:] + + if _i >= len(ControlScroller.scrollfields): + ControlScroller.scrollfields.append(_currowproperties) + else: + ControlScroller.scrollfields.insert(_currowproperties, _i) + + def getControlGroupInfo(self, _i): + return ControlScroller.scrollfields.index(_i) + + @classmethod + def setControlData(self, controlname, newvalue): + oControlModel = ControlScroller.CurUnoDialog.xUnoDialog.getControl( + controlname).Model + propertyname = UnoDialog.getDisplayProperty(oControlModel) + if propertyname != "": + ControlScroller.CurUnoDialog.setControlProperty( + controlname, propertyname, newvalue) + + def getControlData(self, controlname): + oControlModel = ControlScroller.CurUnoDialog.xUnoDialog.getControl( + controlname).Model + propertyname = UnoDialog.getDisplayProperty(oControlModel) + if propertyname != "": + return ControlScroller.CurUnoDialog.getControlProperty( + controlname, propertyname) + else: + return None + + def getScrollFieldValues(self): + scrollRowsInfo() + retproperties = [[ControlScroller.scrollfields.size()],[]] + try: + i = 0 + while i < ControlScroller.scrollfields.size(): + curproperties = ControlScroller.scrollfields.elementAt(i) + retproperties[i] = curproperties + i += 1 + return retproperties + except java.lang.Exception, ex: + ex.printStackTrace(System.out) + return None diff --git a/wizards/com/sun/star/wizards/ui/UnoDialog.py b/wizards/com/sun/star/wizards/ui/UnoDialog.py index 2c7e993c67d1..d9e320a0cdbf 100644 --- a/wizards/com/sun/star/wizards/ui/UnoDialog.py +++ b/wizards/com/sun/star/wizards/ui/UnoDialog.py @@ -5,9 +5,13 @@ from com.sun.star.awt import Rectangle from common.Helper import Helper from com.sun.star.awt import Rectangle from com.sun.star.awt.PosSize import POS +import UIConsts class UnoDialog(object): + createDict = False + dictProperties = None + def __init__(self, xMSF, PropertyNames, PropertyValues): try: self.xMSF = xMSF @@ -35,12 +39,9 @@ class UnoDialog(object): return iKey - def createPeerConfiguration(self): - self.m_oPeerConfig = PeerConfig(self) - def getPeerConfiguration(self): if self.m_oPeerConfig == None: - self.createPeerConfiguration() + self.m_oPeerConfig = PeerConfig(self) return self.m_oPeerConfig def setControlProperty(self, ControlName, PropertyName, PropertyValue): @@ -256,7 +257,7 @@ class UnoDialog(object): def executeDialog(self, FramePosSize): if self.xUnoDialog.getPeer() == None: raise AttributeError( - "Please create a peer, using your own frame"); + "Please create a peer, using your own frame") self.calculateDialogPosition(FramePosSize) @@ -344,7 +345,95 @@ class UnoDialog(object): @classmethod def setEnabled(self, control, enabled): Helper.setUnoPropertyValue( - getModel(control), PropertyNames.PROPERTY_ENABLED, enabled) + control.Model, PropertyNames.PROPERTY_ENABLED, enabled) + + @classmethod + def getControlModelType(self, xServiceInfo): + if xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlFixedTextModel"): + return UIConsts.CONTROLTYPE.FIXEDTEXT + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlButtonModel"): + return UIConsts.CONTROLTYPE.BUTTON + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlCurrencyFieldModel"): + return UIConsts.CONTROLTYPE.CURRENCYFIELD + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlDateFieldModel"): + return UIConsts.CONTROLTYPE.DATEFIELD + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlFixedLineModel"): + return UIConsts.CONTROLTYPE.FIXEDLINE + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlFormattedFieldModel"): + return UIConsts.CONTROLTYPE.FORMATTEDFIELD + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlRoadmapModel"): + return UIConsts.CONTROLTYPE.ROADMAP + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlNumericFieldModel"): + return UIConsts.CONTROLTYPE.NUMERICFIELD + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlPatternFieldModel"): + return UIConsts.CONTROLTYPE.PATTERNFIELD + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlHyperTextModel"): + return UIConsts.CONTROLTYPE.HYPERTEXT + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlProgressBarModel"): + return UIConsts.CONTROLTYPE.PROGRESSBAR + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlTimeFieldModel"): + return UIConsts.CONTROLTYPE.TIMEFIELD + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlImageControlModel"): + return UIConsts.CONTROLTYPE.IMAGECONTROL + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlRadioButtonModel"): + return UIConsts.CONTROLTYPE.RADIOBUTTON + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlCheckBoxModel"): + return UIConsts.CONTROLTYPE.CHECKBOX + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlEditModel"): + return UIConsts.CONTROLTYPE.EDITCONTROL + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlComboBoxModel"): + return UIConsts.CONTROLTYPE.COMBOBOX + elif xServiceInfo.supportsService( + "com.sun.star.awt.UnoControlListBoxModel"): + return UIConsts.CONTROLTYPE.LISTBOX + else: + return UIConsts.CONTROLTYPE.UNKNOWN + + @classmethod + def getDisplayProperty(self, oControlModel): + itype = self.getControlModelType(oControlModel) + if not UnoDialog.createDict: + UnoDialog.createDict = True + UnoDialog.dictProperties = { + UIConsts.CONTROLTYPE.FIXEDTEXT:PropertyNames.PROPERTY_LABEL, + UIConsts.CONTROLTYPE.BUTTON:PropertyNames.PROPERTY_LABEL, + UIConsts.CONTROLTYPE.FIXEDLINE:PropertyNames.PROPERTY_LABEL, + UIConsts.CONTROLTYPE.NUMERICFIELD:"Value", + UIConsts.CONTROLTYPE.CURRENCYFIELD:"Value", + UIConsts.CONTROLTYPE.FORMATTEDFIELD:"EffectiveValue", + UIConsts.CONTROLTYPE.DATEFIELD:"Date", + UIConsts.CONTROLTYPE.TIMEFIELD:"Time", + UIConsts.CONTROLTYPE.SCROLLBAR:"ScrollValue", + UIConsts.CONTROLTYPE.PROGRESSBAR:"ProgressValue", + UIConsts.CONTROLTYPE.IMAGECONTROL:PropertyNames.PROPERTY_IMAGEURL, + UIConsts.CONTROLTYPE.RADIOBUTTON:PropertyNames.PROPERTY_STATE, + UIConsts.CONTROLTYPE.CHECKBOX:PropertyNames.PROPERTY_STATE, + UIConsts.CONTROLTYPE.EDITCONTROL:"Text", + UIConsts.CONTROLTYPE.COMBOBOX:"Text", + UIConsts.CONTROLTYPE.PATTERNFIELD:"Text", + UIConsts.CONTROLTYPE.LISTBOX:"SelectedItems" + } + try: + return UnoDialog.dictProperties[itype] + except KeyError: + return "" def addResourceHandler(self, _Unit, _Module): self.m_oResource = Resource(self.xMSF, _Unit, _Module) diff --git a/wizards/com/sun/star/wizards/ui/UnoDialog2.py b/wizards/com/sun/star/wizards/ui/UnoDialog2.py index 8986b3a963f9..f3b9c8bdf223 100644 --- a/wizards/com/sun/star/wizards/ui/UnoDialog2.py +++ b/wizards/com/sun/star/wizards/ui/UnoDialog2.py @@ -1,7 +1,6 @@ from UnoDialog import * from ui.event.CommonListener import * from common.Desktop import Desktop -import UIConsts ''' This class contains convenience methods for inserting components to a dialog. @@ -22,6 +21,7 @@ class UnoDialog2(UnoDialog): def __init__(self, xmsf): super(UnoDialog2,self).__init__(xmsf,(), ()) + ControlList = {} def insertButton( self, sName, actionPerformed, sPropNames, oPropValues, listener): @@ -86,10 +86,6 @@ class UnoDialog2(UnoDialog): "com.sun.star.awt.UnoControlListBoxModel", sName, sPropNames, oPropValues) - if actionPerformed is not None: - actionPerformed = getattr(listener, actionPerformed) - xListBox.addActionListener(actionPerformed) - if itemChanged is not None: itemChanged = getattr(listener, itemChanged) xListBox.addItemListener(ItemListenerProcAdapter(itemChanged)) @@ -213,10 +209,15 @@ class UnoDialog2(UnoDialog): sName, sPropNames, oPropValues) return oFixedText - def insertScrollBar(self, sName, sPropNames, oPropValues): + def insertScrollBar(self, sName, sPropNames, oPropValues, + iControlKey, listener): oScrollBar = self.insertControlModel( "com.sun.star.awt.UnoControlScrollBarModel", sName, sPropNames, oPropValues) + if listener is not None: + oScrollBar.addAdjustmentListener(None) + if self.ControlList is not None: + self.ControlList[sName] = iControlKey return oScrollBar def insertProgressBar(self, sName, sPropNames, oPropValues): diff --git a/wizards/com/sun/star/wizards/ui/WizardDialog.py b/wizards/com/sun/star/wizards/ui/WizardDialog.py index 9487d4077224..bcfcbef9c2b1 100644 --- a/wizards/com/sun/star/wizards/ui/WizardDialog.py +++ b/wizards/com/sun/star/wizards/ui/WizardDialog.py @@ -292,10 +292,8 @@ class WizardDialog(UnoDialog2): traceback.print_exc() def insertRoadMapItems(self, items, steps, enabled): - i = 0 - while i < items.length: - insertRoadmapItem(i, enabled(i), items(i), steps(i)) - i += 1 + for index, item in enumerate(items): + self.insertRoadmapItem(index, enabled[index], item, steps[index]) def setStepEnabled(self, _nStep, bEnabled, enableNextButton): setStepEnabled(_nStep, bEnabled) diff --git a/wizards/com/sun/star/wizards/ui/event/RadioDataAware.py b/wizards/com/sun/star/wizards/ui/event/RadioDataAware.py index 31d37407c4e7..181662b19b5f 100644 --- a/wizards/com/sun/star/wizards/ui/event/RadioDataAware.py +++ b/wizards/com/sun/star/wizards/ui/event/RadioDataAware.py @@ -16,10 +16,8 @@ class RadioDataAware(DataAware): def setToUI(self, value): selected = int(value) if selected == -1: - i = 0 - while i < self.radioButtons.length: - self.radioButtons[i].State = False - i += 1 + for i in self.radioButtons: + i.State = False else: self.radioButtons[selected].State = True diff --git a/wizards/com/sun/star/wizards/ui/event/UnoDataAware.py b/wizards/com/sun/star/wizards/ui/event/UnoDataAware.py index 7c3436caa59c..c10ccfb0cebe 100644 --- a/wizards/com/sun/star/wizards/ui/event/UnoDataAware.py +++ b/wizards/com/sun/star/wizards/ui/event/UnoDataAware.py @@ -47,6 +47,7 @@ class UnoDataAware(DataAware): return self.__attachTextControl( data, prop, unoControl, "Date", field, 0) + @classmethod def attachTimeControl(self, data, prop, unoControl, field): return self.__attachTextControl( data, prop, unoControl, "Time", field, 0) |