# HG changeset patch # User Miguel Ángel Bárcena Rodríguez # Date 1556807477 -7200 # Node ID 65e7ae0d0e63f6bcb19d4eeb00d8f2b4ffc416c8 # Parent 7bd4ca56607d31eeea645d2e9971ceff220aac82 GTK2 to GTK3 diff -r 7bd4ca56607d -r 65e7ae0d0e63 .hgignore --- a/.hgignore Tue Sep 30 17:16:50 2014 +0200 +++ b/.hgignore Thu May 02 16:31:17 2019 +0200 @@ -3,4 +3,3 @@ *.bak *.pyc *.sh -durus/* diff -r 7bd4ca56607d -r 65e7ae0d0e63 Generic/__init__.py --- a/Generic/__init__.py Tue Sep 30 17:16:50 2014 +0200 +++ b/Generic/__init__.py Thu May 02 16:31:17 2019 +0200 @@ -23,7 +23,6 @@ __all__ = [ 'base', 'config', - #'durusdatabase', 'fiebdc', 'globalVars', 'openwith', diff -r 7bd4ca56607d -r 65e7ae0d0e63 Generic/base.py --- a/Generic/base.py Tue Sep 30 17:16:50 2014 +0200 +++ b/Generic/base.py Thu May 02 16:31:17 2019 +0200 @@ -3,7 +3,7 @@ ## File base.py ## This file is part of pyArq-Presupuestos. ## -## Copyright (C) 2010-2014 Miguel Ángel Bárcena Rodríguez +## Copyright (C) 2010-2019 Miguel Ángel Bárcena Rodríguez ## ## ## pyArq-Presupuestos is free software: you can redistribute it and/or modify @@ -134,7 +134,11 @@ * Description +-- __synonyms: synonyms dictionary. TODO +-- __root: root record code - +-- __decimals: decimals dictionay = { int : Decimals } + +-- __decimals: List with the decimal places used to round the +- result of the calculations with prices and measures +- The values are Decimals objects +- The <0> objets is the default Decimals (seted in FIEBDC-3), +- The others keys are for the diferent groups of Prices * Decimals: +-- DN: Number of decimal places of the field "equal-size parts" in the measure lines. @@ -242,9 +246,25 @@ +-- cif: CIF +-- web: web page +-- email: email + +-- __comment + +-- __date + +-- __budgetType" A integer. Type of data in budget + 0 -> Undefined + 1 -> Base data. + 2 -> Budget. + 3 -> Certificate. + 4 -> Base date update. + +-- __budgetCerficateOrder" Only valid if budgetType is 3. + +-- __budgetCerficateDate" Only valid if budgetType is 3 + +-- __tec_info": Dictionary whith tecnical information + {ti_code : ["desciption text", "unit"]} + +-- __labels": Label dictionary { "label": [ "code", ], } """ # Modules +# python 2/3 compatibility +#from __future__ import absolute_import, division, print_function, unicode_literals + import re import datetime import os @@ -253,6 +273,26 @@ from Generic import fiebdc from Generic import utils + +# Translatable global Vars + +authors = ["Miguel Ángel Bárcena Rodríguez"] +copyright = "Copyright \xc2\xa9 2019 Autoras de Pyarq Presupuestos" +website = "http://pyarq.obraencurso.es/pyarq-Presupuestos" +website_label = "pyarq Presupuestos Web" +comments = _(""" +A free program of measurements, budgets and control of construction sites. +In beta development, still there is not a fully functional version. +""") +help = _( +""" +Usage: + pyarqPresupuestos [file]... + +Help Options: + -h, --help Show this help +""") + class Record(object): """base.Record: @@ -265,23 +305,23 @@ +-- object +-- Record Atributes: - "code": Code string - "recordType": RecordType object - "synonyms": List of synonym codes. - "parents":List of parent codes - "children": Decomposition list, + "code": Write/Read. Code string + "recordType": Write/Read. RecordType object + "synonyms": Write/Read. List of synonym codes. + "parents": Write/Read. List of parent codes + "children": Write/Read. Decomposition list, list of "Decomposition" instances - "unit": measure unit of the record - "summary": Short description of the record - "prices": List of prices/dates - "text": Long Description of the record - "sheet": Sheet of conditions object - "files": List of file object - "labels": List of record labels + "unit": Write/Read. measure unit of the record + "summary": Write/Read. Short description of the record + "prices": Read. List of prices/dates + "text": Write/Read. Long Description of the record + "sheet": Write/Read. Sheet of conditions object + "files": Write/Read. List of file object + "labels": Write/Read. List of record labels Methods: - __getstate__(self) - __setstate__(self, tuple) - __init__(self, filename=None, budget=None) + isPercentage + percentageMasq + hasPercentageMasq(masq) {get/set}Code {get/set}Synonyms {get/set}RecordType @@ -289,7 +329,6 @@ {get/set}Summary {get/set}Prices addPrice - _validate_price_date getPrice getAmount getDate @@ -351,23 +390,42 @@ self.files = [] self.labels = [] + def isPercentage(self): + if "%" in self.__code or "&" in self.__code: + return True + else: + return False + + def percentageMasq(self): + if "%" in self.__code: + return self.__code.split("%")[0] + elif "&" in self.__code: + return self.__code.split("&")[0] + + def hasPercentageMasq(self, masq): + if len(self.__code) >= len(masq): + _part_code = self.__code[:len(masq)] + if _part_code == masq: + return True + return False + def getCode(self): return self.__code def setCode(self, code): - """setCode(self,code) + """setCode(code) Sets the code, must be a valid code """ if not utils.is_valid_code(code)[0]: - raise ValueError, utils.mapping(_("Invalid code: $1"),(str(code),)) + raise ValueError( utils.mapping(_("Invalid code: $1"),(str(code),)) ) self.__code = code def getSynonyms(self): return self.__synonyms def setSynonyms(self,synonyms): - """setSynonyms(self,synonyms) + """setSynonyms(synonyms) Sets the synonyms codes of the record. synonyms must fulfill: @@ -375,19 +433,19 @@ - the items must be valid codes """ if not isinstance(synonyms, list): - raise TypeError, utils.mapping(_("Synonyms ($1) must be a list, " \ - "code: $2"), (str(synonyms), self.__code)) + raise TypeError( utils.mapping(_("Synonyms ($1) must be a list, " \ + "code: $2"), (str(synonyms), str(self.__code))) ) for code in synonyms: if not utils.is_valid_code(code)[0]: - raise ValueError, utils.mapping(_("Invalid Code in synomyms "\ - "list ($1) code: $2"), (str(code), self.__code)) + raise ValueError( utils.mapping(_("Invalid Code in synomyms "\ + "list ($1) code: $2"), (str(code), str(self.__code))) ) self.__synonyms = synonyms def getRecordType(self): return self.__recordType def setRecordType(self, recordType): - """setRecordType(self, recordType) + """setRecordType(recordType) Set the record type. recordType (hierarchy, type,subtype) @@ -404,35 +462,35 @@ return self.__unit def setUnit(self,unit): - """setUnit(self,unit) + """setUnit(unit) Set the unit of measure The unit must be a string. """ if not isinstance(unit, str): - raise TypeError, utils.mapping(_("Unit ($1) must be a string: $2"), - (str(unit), self.__code)) + raise TypeError( utils.mapping(_("Unit ($1) must be a string: $2"), + (str(unit), str(self.__code))) ) self.__unit = unit def getSummary(self): return self.__summary def setSummary(self,summary): - """setSummary(self,summary) + """setSummary(summary) Set the summary of a record The summary must be a string. """ if not isinstance(summary, str): - raise TypeError, utils.mapping(_("Summary ($1) must be a string: "\ - "$1"), (str(summary), self.__code)) + raise TypeError( utils.mapping(_("Summary ($1) must be a string: "\ + "$1"), (str(summary), str(self.__code))) ) self.__summary = summary def getPrices(self): return self.__prices def setPrices(self, prices, decimals): - """setPrice(self, prices, decimals) + """setPrice(prices, decimals) Set the price list of the record. prices must fulfill: @@ -441,8 +499,8 @@ - the first item: price must be a float """ if not isinstance(prices, list): - raise TypeError, utils.mapping(_("Prices ($1) must be a list: $2"), - (str(prices), self.__code)) + raise TypeError( utils.mapping(_("Prices ($1) must be a list: $2"), + (str(prices), str(self.__code))) ) for index in range(len(prices)): _price_date = prices[index] _price_date = self._validate_price_date(_price_date, decimals) @@ -450,7 +508,7 @@ self.__prices = prices def addPrice(self, price_date, decimals): - """addPrice(self, price_date, decimals) + """addPrice(price_date, decimals) Add a price to the price list of the record. price must fulfill: @@ -462,14 +520,14 @@ def _validate_price_date(self, price_date, decimals): if not isinstance(price_date, list) and len(price_date) == 2: - raise ValueError, utils.mapping(_("Price ($1) must be a list"\ - " with two items: $2"), (str(price_date), self.__code)) + raise ValueError( utils.mapping(_("Price ($1) must be a list"\ + " with two items: $2"), (str(price_date), str(self.__code))) ) _price = price_date[0] _date = price_date[1] if not isinstance(_price, float): - raise TypeError, utils.mapping(_("Price must be a float "\ - "number: $1"), (str(_price),)) - _D = decimals.getD(self.recordType) + raise TypeError( utils.mapping(_("Price must be a float "\ + "number: $1"), (str(_price),)) ) + _D = abs(decimals.getD(self.recordType)) _price = round(_price, _D) price_date[0] = _price # TODO: validate date @@ -477,20 +535,20 @@ def getPrice(self, index_price): if len(self.__prices) <= index_price: - raise IndexError, _("The record do not have this Price. Code: %s" - % self.__code) + raise IndexError( _("The record do not have this Price. Code: %s" + % self.__code) ) return self.__prices[index_price][0] def getDate(self, index_price): if len(self.__prices) <= index_price: - raise IndexError, _("The record do not have this Price") - return self.__prices[index_price][1] + raise IndexError( _("The record do not have this Price") ) + return self.__prices[index_price][1] def getParents(self): return self.__parents def setParents(self,parents): - """setParents(self,parents) + """setParents(parents) Sets the list of parents codes of the record. parents must fulfill @@ -498,31 +556,31 @@ - the items must be valid codes """ if not isinstance(parents, list): - raise TypeError, utils.mapping(_("Parents ($1) must be a list: $2"), - (str(parents), self.__code)) + raise TypeError( utils.mapping(_("Parents ($1) must be a list: $2"), + (str(parents), str(self.__code))) ) for parent in parents: if not utils.is_valid_code(parent)[0]: - raise ValueError, utils.mapping(_("Invalid parent code ($1) " \ - "in the record: $2"), (str(padre), self.__code)) + raise ValueError(utils.mapping(_("Invalid parent code ($1) " \ + "in the record: $2"), (str(padre), str(self.__code))) ) self.__parents = parents def appendParent(self, parent): - """appendParent(self, parent) + """appendParent(parent) parent must be a valid code Append a parent to the list of parents codes of the record. """ if not utils.is_valid_code(parent)[0]: - raise ValueError, utils.mapping(_("Invalid parent code ($1) " \ - "in the record: $2"), (str(parent), self.__code)) + raise ValueError( utils.mapping(_("Invalid parent code ($1) " \ + "in the record: $2"), (str(parent), str(self.__code))) ) self.__parents.append(parent) def getchildren(self): return self.__children def setchildren(self,children): - """setchildren(self,children) + """setchildren(children) Sets the list of children of a record children must fulfill @@ -530,13 +588,13 @@ - the items must be instances of Decomposition class """ if not isinstance(children, list): - raise TypeError, utils.mapping(_("children ($1) must be a list, "\ - "record: $2"), (str(children), self.__code)) + raise TypeError( utils.mapping(_("children ($1) must be a list, "\ + "record: $2"), (str(children), str(self.__code))) ) for _child in children: if not isinstance(_child, Decomposition): - raise ValueError, utils.mapping(_("child ($1) must be a "\ + raise ValueError( utils.mapping(_("child ($1) must be a "\ "Decomposition object, record: $2"), - (str(_child), self.__code)) + (str(_child), str(self.__code))) ) _record_code = self.code for _measure_list in [_child.budgetMeasures, _child.certification, _child.real_cost, _child.cost_goals, @@ -548,7 +606,7 @@ def appendChild(self, child_code, decimals, factor=0.0, yield_=0.0, measure=0.0, measure_list=None, type_=None, label=None): - """appendChildren(self, child_code, factor=0.0, yield_=0.0, + """appendChildren(child_code, factor=0.0, yield_=0.0, measure=0.0, measure_list=None, type_=None, label=None)) position: @@ -582,40 +640,39 @@ return self.__text def setText(self,text): - """setText(self,text) + """setText(text) Sets the text of the record It must be a string """ if not isinstance(text, str): - raise TypeError, utils.mapping(_("Text ($1) must be a string, "\ - "record: $2"), (str(text), self.__code)) + raise TypeError( utils.mapping(_("Text ($1) must be a string, "\ + "record: $2"), (str(text), str(self.__code))) ) self.__text = text def getSheet(self): return self.__sheet def setSheet(self, sheet): - """setSheet(self, sheet) + """setSheet(sheet) Sets the sheet of condition object """ if not isinstance(sheet, Sheet): - raise ValueError, _("sheet must be a Sheet instance") + raise ValueError( _("sheet must be a Sheet instance") ) self.__sheet = sheet def getFiles(self): return self.__files def setFiles(self, files): - """setFiles(self, files) + """setFiles(files) Sets the files list """ - # TODO: only sets files and File object format (durusdatabase) if not isinstance(files, list): - raise ValueError, utils.mapping(_("files must be a list: $1"), - str(files)) + raise ValueError( utils.mapping(_("files must be a list: $1"), + str(files)) ) _files = [] for file in files: if isinstance(file, File): @@ -625,22 +682,21 @@ _type = file[1] _description = file[2] if not os.path.exists(file[0]): - raise ValueError, _("Incorrect path") + raise ValueError( _("Incorrect path") ) _file = File(file_path, type_, description) _files.append(_file) else: - raise ValueError, utils.mapping(_( - "file must be a list or a File object: $1"),str(file)) + raise ValueError( utils.mapping(_( + "file must be a list or a File object: $1"),str(file)) ) self.__files = _files - def addFile(self, file_path, type_, description): - """addFile(self, file_path, type_, description) + """addFile(file_path, type_, description) Add a file to a record instance """ if not os.path.exists(file_path): - raise ValueError, _("Incorrect path") + raise ValueError( _("Incorrect path") ) _name = os.path.basename(file_path) _isin = False for _ofile in self.__files: @@ -654,32 +710,32 @@ return self.__labels def setLabels(self, labels): - """setLabels(self, labels) + """setLabels(labels) Sets the labels list of a record """ if not isinstance(labels, list): - raise ValueError, _("labels must be a list") + raise ValueError( _("labels must be a list") ) _labels = [] for _label in labels: if isinstance(_label, str): _labels.append(_label) else: - raise ValueError, _("label must be a string") + raise ValueError( _("label must be a string") ) self.__labels = _labels def addLabel(self, label): - """addLabel(self, label) + """addLabel(label) Add a label to a record instance """ if not isinstance(label, str): - raise ValueError, _("Label must be a string") + raise ValueError( _("Label must be a string") ) if not label in self.__labels: self.__labels.append(label) def getChildPositions(self, child_code): - """getChildPath(self, child_code): + """getChildPath(child_code): Try to return positions of a childcode """ @@ -723,6 +779,7 @@ labels = property(getLabels, setLabels, None, """Label list""") + class ParametricRecord(Record): """base.ParametricRecord: @@ -784,7 +841,7 @@ self.__vars = tuple[17] self.__parametric_summary = tuple[18] self.__parametric_text = tuple[19] - + def __init__(self, budget, code, synonyms, hierarchy, unit, summary, prices, type_, subtype, parents=None, text=None): if parents is None: @@ -813,6 +870,7 @@ def setSelectComment(self, select_comment): self.__select_comment = select_comment + def getVar(self, var): if var in self.__vars: return self.__vars[var] @@ -851,6 +909,7 @@ """Seclect comment """) + class Decomposition(object): """base.Decomposition: @@ -872,10 +931,6 @@ "cost_goals": list of cost goals of construction for months measures "cost_planned": list of costs planned and amended cost planned measures Methods: - __getstate__(self) - __setstate__(self, tuple) - __init__( position, code, budgetMeasures, certification=None, - real_cost=None, cost_goals=None, cost_planned=None) {get/set}position {get/set}Code {get/set}BudgetMeasures @@ -884,6 +939,7 @@ {get/set}CostGoals {get/set}CostPlanned """ + __slots__ = ["_Decomposition__position", "_Decomposition__code", "_Decomposition__budgetMeasures", @@ -892,10 +948,12 @@ "_Decomposition__cost_goals", "_Decomposition__cost_planned", ] + def __getstate__ (self): return (self.__position, self.__code, self.__budgetMeasures, self.__certification, self.__real_cost, self.__cost_goals, self.__cost_planned) + def __setstate__(self,tuple): self.__position = tuple[0] self.__code = tuple[1] @@ -914,50 +972,65 @@ self.real_cost = real_cost self.cost_goals = cost_goals self.cost_planned = cost_planned + def getPosition(self): return self.__position + def setPosition(self, position): if not isinstance(position, int): - raise ValueError, _("Position must be a integer") + raise ValueError( _("Position must be a integer") ) self.__position = position + def getCode(self): return self.__code + def setCode(self, code): self.__code = code + def getBudgetMeasures(self): return self.__budgetMeasures + def setBudgetMeasures(self, budgetMeasures): if not isinstance(budgetMeasures, list): - raise ValueError, _("BudgetMeasures atribute must be a list") + raise ValueError( _("BudgetMeasures atribute must be a list") ) for _measure in budgetMeasures: if not isinstance(_measure, Measure): - raise ValueError, _("BudgetMeasures item must be a Measure "/ - "object") + raise ValueError( _("BudgetMeasures item must be a Measure "/ + "object") ) self.__budgetMeasures = budgetMeasures + def getCertification(self): return self.__certification + def setCertification(self, certification): if not (certification is None or isinstance(certification, list)): - raise ValueError, _("Certification atribute must be a list or None") + raise ValueError( _("Certification atribute must be a list or None") ) self.__certification = certification + def getRealCost(self): return self.__real_cost + def setRealCost(self, real_cost): if not (real_cost is None or isinstance(real_cost, list)): - raise ValueError, _("Real cost atribute must be a list or None") + raise ValueError( _("Real cost atribute must be a list or None") ) self.__real_cost = real_cost + def getCostGoals(self): return self.__cost_goals + def setCostGoals(self, cost_goals): if not (cost_goals is None or isinstance(cost_goals, list)): - raise ValueError, _("Cost goals atribute must be a list or None") + raise ValueError( _("Cost goals atribute must be a list or None") ) self.__cost_goals = cost_goals + def getCostPlanned(self): return self.__cost_planned + def setCostPlanned(self, cost_planned): if not (cost_planned is None or isinstance(cost_planned, list)): - raise ValueError, _("Cost Planned atribute must be a list or None") + raise ValueError( _("Cost Planned atribute must be a list or None") ) self.__cost_planned = cost_planned + position = property(getPosition, setPosition, None, """Postion of the record in the budget """) @@ -1000,10 +1073,6 @@ "yield": "fixed": If fixed is True the yield is not calculated from measure Methods: - __getstate__() - __setstate__(tuple) - __init__(decimals, recordType, measure, lines, - label, factor, yield_) getMeasure() setMeasure(measure, decimals) {get/set}Lines @@ -1018,15 +1087,18 @@ calculateMeasure(decimals) updateYield(decimals) """ + __slots__ = ["_Measure__measure", "_Measure__lines", "_Measure__label", "_Measure__factor", "_Measure__yield_", "_Measure__fixed"] + def __getstate__ (self): return (self.__measure, self.__lines, self.__label, self.__factor, self.__yield_, self.__fixed) + def __setstate__(self,tuple): self.__measure = tuple[0] self.__lines = tuple[1] @@ -1034,6 +1106,7 @@ self.__factor = tuple[3] self.__yield_ = tuple[4] self.__fixed = tuple[5] + def __init__(self, decimals, recordType, measure, lines, label, factor, yield_): self.setMeasure(measure, decimals) @@ -1045,45 +1118,50 @@ def getMeasure(self): return self.__measure + def setMeasure(self, measure, decimals): if not isinstance(measure, float): - raise ValueError, utils.mapping(_("Measure must be a float "\ - "number. Type: $1"), (type(measure),)) + raise ValueError( utils.mapping(_("Measure must be a float "\ + "number. Type: $1"), (type(measure),)) ) # TODO: test after - _DS = decimals.DS + _DS = abs(decimals.DS) measure = round(measure, _DS) self.__measure = measure def getLines(self): return self.__lines + def setLines(self, lines): if not isinstance(lines, list): - raise ValueError, _("Lines must be a list") + raise ValueError( _("Lines must be a list") ) for _line in lines: if not isinstance(_line, MeasureLine): - raise ValueError, _("Line must be a MeasureLine objetc") + raise ValueError( _("Line must be a MeasureLine objetc") ) self.__lines = lines + def getLabel(self): return self.__label + def setLabel(self, label): self.__label = label + def setFactor(self, factor, decimals, recordType): if not isinstance(factor, float): - raise ValueError, utils.mapping(_("Factor must be a float number "\ - "|$1|"), (factor,)) + raise ValueError( utils.mapping(_("Factor must be a float number "\ + "|$1|"), (str(factor),)) ) # TODO: test after - _DF = decimals.getDF(recordType) + _DF = abs(decimals.getDF(recordType)) factor = round(factor, _DF) self.__factor = factor def getFactor(self): return self.__factor - + def setYield(self, yield_, decimals, recordType): if not isinstance(yield_, float): - raise ValueError, _("Yield must be a float number") + raise ValueError( _("Yield must be a float number") ) # TODO: test after - _DR = decimals.getDR(recordType) + _DR = abs(decimals.getDR(recordType)) yield_ = round(yield_, _DR) self.__yield_ = yield_ @@ -1092,7 +1170,7 @@ def setFixed(self, fixed, decimals): if not isinstance(fixed, bool): - raise ValueError, _("Fixed must be boolean object") + raise ValueError( _("Fixed must be boolean object") ) self.__fixed = fixed self.updateYield(decimals) @@ -1162,8 +1240,8 @@ elif type_ == "A": self.lines.extend(_lines) else: - raise ValueError, utils.mapping(_("Type must be M or A. Type: $1"), - (type_,)) + raise ValueError( utils.mapping(_("Type must be M or A. Type: $1"), + (str(type_),)) ) self.calculateMeasure(decimals, recordType) def calculateMeasure(self, decimals, recordType): @@ -1181,8 +1259,9 @@ line.setParcialSubtotal(_parcialSubtotal, decimals) _parcial_total = _acumulated_total self.setMeasure(_acumulated_total, decimals) - _DR = decimals.getDR(recordType) + _DR = abs(decimals.getDR(recordType)) self.updateYield(decimals, recordType) + def updateYield(self, decimals, recordType): if not self.fixed: self.setYield(self.measure, decimals, recordType) @@ -1217,10 +1296,6 @@ "parcial_subtotal" "acumulated_subtotal" Methods: - __getstate__(self) - __setstate__(self, tuple) - __init__(self, decimals, type_, comment, units, length, width, height, - formula) {get/set}LineType {get/set}Comment {get/set}Units @@ -1234,6 +1309,7 @@ calculateParcial eval_formula """ + __slots__ = ["_MeasureLine__lineType", "_MeasureLine__comment", "_MeasureLine__units", @@ -1245,10 +1321,12 @@ "_MeasureLine__parcial_subtotal", "_MeasureLine__acumulated_subtotal", ] + def __getstate__ (self): return (self.__lineType, self.__comment, self.__units, self.__length, self.__width, self.__height, self.__formula, self.__parcial) + def __setstate__(self,tuple): self.__lineType = tuple[0] self.__comment = tuple[1] @@ -1259,6 +1337,7 @@ self.__formula = tuple[6] self.__parcial = tuple[7] #self.calculateParcial() + def __init__(self, decimals, type_, comment, units, length, width, height, formula): self.__parcial = 0.0 @@ -1272,43 +1351,56 @@ self.setHeight(height, decimals) self.setFormula(formula, decimals) #self.calculateParcial() + def getLineType(self): return self.__lineType + def getComment(self): return self.__comment + def getUnits(self): return self.__units + def getLength(self): return self.__length + def getWidth(self): return self.__width + def getHeight(self): return self.__height + def getFormula(self): return self.__formula + def getParcial(self): return self.__parcial + def getParcialSubtotal(self): return self.__parcial_subtotal + def getAcumulatedSubtotal(self): return self.__acumulated_subtotal + def setParcialSubtotal(self, parcial_subtotal, decimals): if not isinstance(parcial_subtotal, float): - raise ValueError, utils.mapping(_(" Parcial Subtotal must be a "\ - "float number. Parcial: $1"), (str(parcial_subtotal),)) - _DS = decimals.DS + raise ValueError( utils.mapping(_(" Parcial Subtotal must be a "\ + "float number. Parcial: $1"), (str(parcial_subtotal),)) ) + _DS = abs(decimals.DS) parcial_subtotal = round(parcial_subtotal, _DS) self.__parcial_subtotal = parcial_subtotal + def setAcumulatedSubtotal(self, acumulated_subtotal, decimals): if not isinstance(acumulated_subtotal, float): - raise ValueError, utils.mapping(_(" Acumulated Subtotal must be "\ + raise ValueError( utils.mapping(_(" Acumulated Subtotal must be "\ "a float number. Parcial: $1"), - (str(acumulated_subtotal),)) - _DS = decimals.DS + (str(acumulated_subtotal),)) ) + _DS = abs(decimals.DS) acumulated_subtotal = round(acumulated_subtotal, _DS) self.__acumulated_subtotal = acumulated_subtotal + def calculateParcial(self, decimals): - _DS = decimals.DS + _DS = abs(decimals.DS) if self.lineType == 1 or self.lineType == 2: _parcial = 0.0 elif self.lineType == 0: # self.formula == "": @@ -1336,69 +1428,75 @@ def setLineType(self, type_): if not type_ in [0, 1, 2, 3]: - raise ValueError, utils.mapping(_("Invalid measure line type ($1)"), - (str(type_),)) + raise ValueError( utils.mapping(_("Invalid measure line type ($1)"), + (str(type_),)) ) self.__lineType = type_ + def setComment(self, comment): if not isinstance(comment, str): - raise ValueError, utils.mapping(_("Measure Comment must be a "\ - "string ($1)"), (str(comment),)) + raise ValueError( utils.mapping(_("Measure Comment must be a "\ + "string ($1)"), (str(comment),)) ) self.__comment = comment + def setUnits(self, units, decimals): if units != "": if not isinstance(units, float): - raise ValueError, utils.mapping(_("Invalid Measure Units ($1)"), - (str(units),)) - _DN = decimals.DN + raise ValueError( utils.mapping(_("Invalid Measure Units ($1)"), + (str(units),)) ) + _DN = abs(decimals.DN) units = round(units, _DN) self.__units = units try: self.calculateParcial(decimals) except AttributeError: pass + def setLength(self, length, decimals): if length != "": if not isinstance(length, float): - raise ValueError, utils.mapping(_("Invalid Measure length ($1)"), - (str(units),)) - _DD = decimals.DD + raise ValueError( utils.mapping(_("Invalid Measure length ($1)"), + (str(units),)) ) + _DD = abs(decimals.DD) length = round(length, _DD) self.__length = length try: self.calculateParcial(decimals) except AttributeError: pass + def setWidth(self, width, decimals): if width != "": if not isinstance(width, float): - raise ValueError, utils.mapping(_("Invalid Measure Width ($1)"), - (str(units),)) - _DD = decimals.DD + raise ValueError( utils.mapping(_("Invalid Measure Width ($1)"), + (str(units),)) ) + _DD = abs(decimals.DD) width = round(width, _DD) self.__width = width try: self.calculateParcial(decimals) except AttributeError: pass + def setHeight(self, height, decimals): if height != "": if not isinstance(height, float): - raise ValueError, utils.mapping(_("Invalid Measure Height ($1)"), - (str(height),)) - _DD = decimals.DD + raise ValueError( utils.mapping(_("Invalid Measure Height ($1)"), + (str(height),)) ) + _DD = abs(decimals.DD) height = round(height, _DD) self.__height = height try: self.calculateParcial(decimals) except AttributeError: pass + def setFormula(self, formula, decimals): if not isinstance(formula, str): - raise ValueError, utils.mapping(_("Formula must be a "\ - "string ($1)"), (str(formula),)) + raise ValueError( utils.mapping(_("Formula must be a "\ + "string ($1)"), (str(formula),)) ) if re.match(".*[^0123456789\.()\+\-\*/\^abcdp ].*", formula): - raise ValueError, utils.mapping(_("There is invalid characters"\ - "in formula ($1)"), (str(formula),)) + raise ValueError( utils.mapping(_("There is invalid characters"\ + "in formula ($1)"), (str(formula),)) ) self.__formula = formula try: self.calculateParcial(decimals) @@ -1437,6 +1535,7 @@ None, None, """Parcial subtotal """) + def eval_formula(self): """eval_formula() @@ -1462,19 +1561,19 @@ try: a = float(a) except: - raise ValueError, _("'a' value must be a float number") + raise ValueError( _("'a' value must be a float number") ) try: b = float(b) except: - raise ValueError, _("'b' value must be a float number") + raise ValueError( _("'b' value must be a float number") ) try: c = float(c) except: - raise ValueError, _("'c' value must be a float number") + raise ValueError( _("'c' value must be a float number") ) try: d = float(d) except: - raise ValueError, _("'d' value must be a float number") + raise ValueError( _("'d' value must be a float number") ) # spaces are erased formula.replace(" ","") # operators and varibles are replaced @@ -1502,7 +1601,8 @@ try: return eval(_formula2, _g) except: - raise ValueError, _("Invalid formula") + raise ValueError( _("Invalid formula") ) + class Decimals(object): """base.Decimals: @@ -1587,13 +1687,6 @@ Default: 2 decimal places. "DIVISA": monetary unit. Methods: - __init__(DN=2, DD=2, DSP=2, DS=2, - DFC=3, DFPU=3, DFUO=3, DFA=3, - DRC=3, DRPU=3, DRUO=3, DRA=3, - DP=2, DC=2, DPU=2, DUO=2, DEA=2, DES=2, - DIR=2, DIRC=2, DCD=2, - DIVISA="EUR") - __getitem__(key) haskey(key) getD(recordtype) getDF(recordType) @@ -1601,6 +1694,7 @@ getDI(recordType) """ # TODO: get/set methods + def __init__(self, DN=2, DD=2, DSP=2, DS=2, DFC=3, DFPU=3, DFUO=3, DFA=3, @@ -1632,10 +1726,13 @@ self.DIRC = DIRC self.DCD = DCD self.DIVISA = DIVISA + def __getitem__(self, key): return self.__dict__[key] + def haskey(self, key): return key in self.__dict__ + def getD(self, recordType): # DP: budget. # DC: chapter and subcharter. @@ -1662,6 +1759,7 @@ else: # unit type 0, subtipe ["EU", "EC", "EF", "PA"] _decimal = self.DUO return _decimal + def getDF(self, recordType): # Factor: DF # ->DFP: Budget @@ -1681,6 +1779,7 @@ else: # unit EU EC EF PA _decimal = self.DFUO return _decimal + def getDR(self, recordType): # Yield: DR # ->DRP: Budget @@ -1700,6 +1799,7 @@ else: # unit _decimal = self.DRUO return _decimal + def getDI(self, recordType): # DIRC: budget, chapter and subcharter. # DIR: unit, auxiliar element. @@ -1716,6 +1816,7 @@ _decimal = self.DIR return _decimal + class Sheet(object): """base.Sheet: Description: @@ -1731,9 +1832,6 @@
: must be in Budget.SheetSections : must be in Budget.SheetParagraph Methods: - __getstate__(self) - __setstate__(self, tuple) - __init__(self, sheet_dict={}) {get/set}Sheet_dict getFields getSections @@ -1742,108 +1840,121 @@ addSection """ __slots__ = ["_Sheet__sheet_dict"] + def __getstate__ (self): return (self.__sheet_dict,) + def __setstate__(self,tuple): self.__sheet_dict = tuple[0] + def __init__(self): self.__sheet_dict = {} + def getSheet_dict(self): return self.__sheet_dict + def setSheet_dict(self, sheet_dict): if not isinstance(sheet_dict, dict): - raise ValueError, _("sheet_dict must be a dictionay") + raise ValueError( _("sheet_dict must be a dictionay") ) self.__sheet_dict = sheet_dict + def getFields(self): return self.sheet_dict.keys() + def getSections(self, field): if field in self.__sheet_dict: return self.__sheet_dict[field].keys() else: return None + def getParagraph(self, field, section): if (field in self.__sheet_dict and section in self.__sheet_dict[field]): return self.__sheet_dict[field][section] else: return None + def addField(self, field, section_dict): if not isinstance(field, str): - raise ValueError, _("sheet field must be a string") + raise ValueError( _("sheet field must be a string") ) if not isinstance(section_dict, dict): - raise ValueError, _("section_dict must be a dictionary") + raise ValueError( _("section_dict must be a dictionary") ) self.__sheet_dict[field] = section_dict + def addSection(self, field, section, paragraph): if not isinstance(field, str): - raise ValueError, _("sheet field must be a string") + raise ValueError( _("sheet field must be a string") ) if not isinstance(section, str): - raise ValueError, _("sheet section must be a string") + raise ValueError( _("sheet section must be a string") ) if not isinstance(paragraph, str): - raise ValueError, _("sheet paragraph must be a string") + raise ValueError( _("sheet paragraph must be a string") ) if not field in self.__sheet_dict: self.addField(field, { }) _field = self.__sheet_dict[field] _field[section] = paragraph + sheet_dict = property(getSheet_dict, setSheet_dict, None, """Sheet dictionary { : {
: }""") + class Budget(object): """base.Budget: Description: - Budget objetc + Budget object + +-- __records: dictionary records { code : Record } + +-- __synonyms: synonyms dictionary. TODO { "code" : ["synonym",],} + Each record code can have synonym codes. + +-- __root: the root record code + +-- __decimals: List with the decimal places used to round the +- result of the calculations with prices and measures +- The values are Decimals objects +- The <0> objets is the default Decimals (seted in FIEBDC-3), +- The others keys are for the diferent groups of Prices + +-- __percentages: percentages dictionary: + { "CI" : "", + "GG" : "", + "BI" : "", + "BAJA": "", + "IVA" : ""} + +-- __file_owner + +-- __title_list: titles list: [ "Header", ["Title1", "Title2", ... ] ] + List with the Headers and list of Titles for prices and + decimal places. + The Headers is the type of hierarchy of the prices + Each Title have a group of Prices and a Decimals definition + The records can have diferent prices for diferent ages, geografical + places, ... + +-- __title_index: A integer. The active group of Prices and Decimals. + +-- __sheet_sections: sheet sections dictionary { sheet_code : sheet_title } + +-- __sheet_fields: sheet fields dictionary { field_code : field_title } + +-- __sheet_paragraphs: sheet paragraphs dictionary + { paragraph_code : paragraph_text} + +-- __companys: Dictionary whith companys object + { company_code: company_object } + + +-- __comment +- +-- __date +- +-- __budgetType" A integer. Type of data in budget +- 0 -> Undefined +- 1 -> Base data. +- 2 -> Budget. +- 3 -> Certificate. +- 4 -> Base date update. +- +-- __budgetCerficateOrder" Only valid if budgetType is 3. +- +-- __budgetCerficateDate" Only valid if budgetType is 3 +- +-- __tec_info": Dictionary whith tecnical information +- {ti_code : ["desciption text", "unit"]} +- +-- __labels": Label dictionary { "label": [ "code", ], } + + Constructor: base.Budget() Ancestry: +-- object +-- Budget Atributes: - "filename": file name of the budget file (FIEBDC) - "__records": Dictionary with the budget records. - { "code" : Record object, } - "__synonyms": Dictionary with the records synonums. - { "code" : ["synonym",],} - Each record code can have synonym codes. - "__root": The root record code. - "__title_list": List with the Headers and list of Titles for prices and - decimal places. - [ "Header", ["Title1", "Title2", ... ] ] - The records can have diferent prices for diferent ages, geografical - places, ... - The Headers is the type of hierarchy of the prices - Each Title have a group of Prices and a Decimals definition - "__decimals": List with the decimal places used to round the - result of the calculations with prices and measures - The values are Decimals objects - The <0> objets is the default Decimals (seted in FIEBDC-3), - The others keys are for the diferent groups of Prices - "__percentages": Dictionary with the percentages - keys: - "CI" Indirect Cost - "GG" General expenses - "BI" Industrial benefit - "BAJA" Low (what this do here?) - "IVA" Tax - "__file_owner" - "__comment" - "__date" - "__budgetType" A integer. Type of data in budget - 0 -> Undefined - 1 -> Base data. - 2 -> Budget. - 3 -> Certificate. - 4 -> Base date update. - "__budgetCerficateOrder" Only valid if budgetType is 3. - "__budgetCerficateDate" Only valid if budgetType is 3 - "__title_index": A integer. The active group of Prices and Decimals. - "__sheet_sections": Dictionary whith de sheet sections - "__sheet_fields": Dictionary whith sheet fields - "__sheet_paragraphs": Dictionary whith sheet paragraphs - "__companys": Dictionary whith companys object - { company_code: company_object } - "__tec_info": Dictionary whith tecnical information - {ti_code : ["desciption text", "unit"]} - "__labels": Label dictionary { "label": [ "code", ], } + No public Atributes Methods: iter iterPreOrder @@ -1911,31 +2022,70 @@ setParametricText """ - def __init__(self): """__init__(self) Initialize the budget atributes """ + # title_index: A integer. The active group of Prices and Decimals. + # TODO: change title_index self.__title_index = 0 + # List with the decimal places used to round the + # result of the calculations with prices and measures + # The values are Decimals objects + # The <0> objets is the default Decimals (seted in FIEBDC-3), + # The others keys are for the diferent groups of Prices self.__decimals = [Decimals(), Decimals()] + # Dictionary with the percentages + # keys: + # "CI" Indirect Cost + # "GG" General expenses + # "BI" Industrial benefit + # "BAJA" Low (what this do here?) + # "IVA" Tax self.__percentages = { "CI" : "" ,"GG": "", "BI": "", "BAJA": "", "IVA" : ""} + # List with the Headers and list of Titles for prices and + # decimal places. + # [ "Header", ["Title1", "Title2", ... ] ] + # The records can have diferent prices for diferent ages, geografical + # places, ... + # The Headers is the type of hierarchy of the prices + # Each Title have a group of Prices and a Decimals definition self.__title_list = [ "", [ ] ] + # The root record code. self.__root = None self.__file_owner = "" self.__comment = "" - self.__budgetCerficateOrder = None - self.__budgetCerficateDate = None + self.__budgetCerficateOrder = None # Only valid if budgetType is 3. + self.__budgetCerficateDate = None # Only valid if budgetType is 3. self.__date = (0,0,0) + # budgetType: A integer. Type of data in budget + # 0 -> Undefined + # 1 -> Base data. + # 2 -> Budget. + # 3 -> Certificate. + # 4 -> Base date update. self.__budgetType = 0 + # Dictionary with the budget records: { "code" : Record object, } self.__records = { } + # Dictionary with the records synonyms. + # { "code" : ["synonym",],} + # Each record code can have synonym codes. self.__synonyms = { } + # sheet_sections: Dictionary whith de sheet sections self.__sheet_sections = { } + # sheet_fields: Dictionary whith sheet fields self.__sheet_fields = { } + # sheet_paragraphs: Dictionary whith sheet paragraphs self.__sheet_paragraphs = { } + # companys: Dictionary whith companys object + # { company_code: company_object } self.__companys = { } + # tec_info: Dictionary whith tecnical information + # {ti_code : ["desciption text", "unit"]} self.__tec_info = { } + # labels: Label dictionary { "label": [ "code", ], } self.__labels = { } def __getstate__(self): @@ -1964,6 +2114,7 @@ def iter(self): for record in self.__records: yield record + def iterPreOrder(self, recordCode, codes=None): if codes is None: codes = [] @@ -1973,6 +2124,7 @@ codes.append(_child) self.iterPreOrder(_child, codes) return codes + def iterPostOrder(self, recordCode, codes=None): if codes is None: codes = [] @@ -2012,6 +2164,7 @@ _children = _record.children _child_code = [ _child.code for _child in _children ] return _child_code + def setOwner(self, owner): """setOwner(self, owner) @@ -2021,7 +2174,7 @@ if isinstance(owner, basestring): self.__file_owner = owner else: - raise TypeError, _("Owner must be a string") + raise TypeError( _("Owner must be a string") ) def setDate(self, date): """setOwner(self, date) @@ -2037,7 +2190,7 @@ datetime.date(*date) self.__date = date else: - raise TypeError, utils.mapping(_("Invalid Date: $1"),(str(date),)) + raise TypeError( utils.mapping(_("Invalid Date: $1"),(str(date),)) ) def setComment(self, comment): """setOwner(self, comment) @@ -2048,7 +2201,7 @@ if isinstance(comment, basestring): self.__comment = comment else: - raise TypeError, _("Comment must be a string") + raise TypeError( _("Comment must be a string") ) def setBudgeType(self, budget_type): """setOwner(self, budget_type) @@ -2064,8 +2217,8 @@ if budget_type in [1, 2, 3, 4]: self.__budgetType = budget_type else: - raise ValueError, _("Budget type must be 1, 2, 3 or 4.") - + raise ValueError( _("Budget type must be 1, 2, 3 or 4.") ) + def setCertificateOrder(self, certificate_order, certificate_date): """setOwner(self, budget_type) @@ -2076,7 +2229,7 @@ if isinstance(certificate_order, int): self.__budgetCerficateOrder = certificate_order else: - raise ValueError, _("Certificate order must be a integer.") + raise ValueError( _("Certificate order must be a integer.") ) def setCertificateDater(self, certificate_date): """setCertidicateDate(self, certificate_date) @@ -2091,7 +2244,7 @@ datetime.date(*certificate_date) self.__budgetCerficateDate = certificate_date else: - raise ValueError, _("Budget certificate Date must be a valid Date.") + raise ValueError( _("Budget certificate Date must be a valid Date.") ) def setTitleList(self, title_list): """setTitleList(self, title_list) @@ -2105,7 +2258,7 @@ title_list[1][i] = str(title_list[1][i]) self.__title_list = title_list else: - raise TypeError, _("Invalid title list format") + raise TypeError( _("Invalid title list format") ) def getTitleList(self): """ getTitleList(self) @@ -2134,7 +2287,7 @@ elif N < len(self.__decimals): _default_decimals = self.__decimals[N] else: - raise IndexError, _("Invalid Index Title") + raise IndexError( _("Invalid Index Title") ) for _decimal in dictionary: if dictionary[_decimal] == "": dictionary[_decimal] = eval("_default_decimals." + _decimal) @@ -2151,6 +2304,7 @@ dictionary["DIRC"], dictionary["DCD"], dictionary["DIVISA"]) self.__decimals[N] = decimals + def getDecimals(self, decimal=None, N=None): """getDecimals(self,decimal="All",N=None) @@ -2170,7 +2324,7 @@ elif self.__decimals[N+1].haskey(decimal): return self.__decimals[N+1][decimal] else: - raise KeyError, _("Decimal Key error") + raise KeyError( _("Decimal Key error") ) def setPercentages(self, dictionary): """setPercentages(self, dictionary): @@ -2208,7 +2362,7 @@ elif key in self.__percentages: return self.__percentages[key] else: - raise KeyError, _("Invalid Percentage key") + raise KeyError( _("Invalid Percentage key") ) def getAllParents(self,code): """getAllParents(self,code) @@ -2280,12 +2434,12 @@ def getStrYield(self, measure, recordType): #_DR = measure.getDR(self.getDecimals()) - _DR = self.getDecimals().getDR(recordType) + _DR = abs(self.getDecimals().getDR(recordType)) _yield = ("%." + str(_DR) + "f" ) % measure.yield_ return _yield def getStrFactor(self, measure, recorType): - _DF = self.getDecimals().getDF(recordType) + _DF = abs(self.getDecimals().getDF(recordType)) #_DF = measure.getDF(self.getDecimals()) _factor = ("%." + str(_DF) + "f" ) % measure.factor return _factor @@ -2325,29 +2479,29 @@ if code is None: # No-estructured measures code = self.getRoot() if code == None: # No root - print "No-estructured measures. Adding root record", - self.setRecord("root", [], 0, "", "", [0.0,], [(1,1,1970)], - 0, "") + print( "No-estructured measures. Adding root record " + + str(self.setRecord("root", [], 0, "", "", [0.0,], [(1,1,1970)], + 0, "") )) code = self.getRoot() if not utils.is_valid_code(code)[0]: - raise ValueError, utils.mapping(_("Invalid parent code: $1"), - (code,)) + raise ValueError( utils.mapping(_("Invalid parent code: $1"), + (str(code),)) ) if not utils.is_valid_code(child_code)[0]: - raise ValueError, utils.mapping(_("Invalid child code: $1 $2"), - (code,child_code)) + raise ValueError( utils.mapping(_("Invalid child code: $1 $2"), + (str(code),str(child_code))) ) if not isinstance(position, int): - raise ValueError, utils.mapping(_("Invalid position in measure "\ - "$1, in code $2"), (parent_code, position)) + raise ValueError( utils.mapping(_("Invalid position in measure "\ + "$1, in code $2"), (str(parent_code), str(position))) ) # Test circular references _all_parent_list = self.getAllParents(code) + [ code ] _all_child_list = self.getAllchildren(child_code) + [ child_code ] for _parent_code in _all_parent_list: if _parent_code in _all_child_list: # TODO: change return to except - print utils.mapping(_("Circular Decomposition, parent code: "\ + print(utils.mapping(_("Circular Decomposition, parent code: "\ "$1, child code: $2, repeated code: $3"), - (code, child_code, _parent_code)) + (str(code), str(child_code), str(_parent_code))) ) return # Creating reference to parent code in child record @@ -2370,15 +2524,15 @@ positions = _record.getChildPositions(child_code) if len(positions) == 1: position = positions[0] - print utils.mapping(_("No-estructured measure or empty position. Parent Code: "\ - "$1, Child code: $2, Position: $3"),(code, child_code, position)) + print(utils.mapping(_("No-estructured measure or empty position. Parent Code: "\ + "$1, Child code: $2, Position: $3"),(str(code), str(child_code), str(position))) ) else: position = _child_number - print utils.mapping(_("No-estructured measure or empty position. "\ + print(utils.mapping(_("No-estructured measure or empty position. "\ "Repeated child in unspecified position. "\ "It is impossible to determine the position. "\ "New child is added in the decomposition. "\ - "Parent code: $1, Child code: $2, Position: $3"),(code, child_code, position)) + "Parent code: $1, Child code: $2, Position: $3"),(str(code), str(child_code), str(position))) ) if position == _child_number: # The record do not have the child if not isinstance(factor, float): factor = 1.0 @@ -2414,21 +2568,21 @@ _measure.label = label else: # TODO: change return for except - print utils.mapping(_("Error: Invalid child position in " + print(utils.mapping(_("Error: Invalid child position in " "decomposition. Parent code: $1 Child code: $2 "\ - "Position: $3"), (code, child_code, position)) + "Position: $3"), (str(code), str(child_code), str(position))) ) return else: if child_code == "" : - print utils.mapping(_("Error: Empty child code. Parent code: "\ - "$1 Position: $2"), (code, position)) + print(utils.mapping(_("Error: Empty child code. Parent code: "\ + "$1 Position: $2"), (str(code), str(position))) ) return if position == -1: position = 0 elif position != 0: - print utils.mapping(_("Error: Invalid child position in "\ + print(utils.mapping(_("Error: Invalid child position in "\ "decomposition. Parent code: $1 Child code: $2 "\ - "Position: $3"), (code, child_code, position)) + "Position: $3"), (str(code), str(child_code), str(position))) ) return if not isinstance(factor, float): factor = 1.0 @@ -2461,19 +2615,19 @@ try: a = float(a) except: - raise ValueError, _("'a' value must be a float number") + raise ValueError( _("'a' value must be a float number") ) try: b = float(b) except: - raise ValueError, _("'b' value must be a float number") + raise ValueError( _("'b' value must be a float number") ) try: c = float(c) except: - raise ValueError, _("'c' value must be a float number") + raise ValueError( _("'c' value must be a float number") ) try: d = float(d) except: - raise ValueError, _("'d' value must be a float number") + raise ValueError( _("'d' value must be a float number") ) # spaces are erased sre.sub("[ ]","",formula) # operators and varibles are replaced @@ -2501,7 +2655,7 @@ try: return eval(_formula2, _g) except: - raise ValueError, _("Invalid formula") + raise ValueError( _("Invalid formula") ) def getText(self,code): """getText(self,code) @@ -2512,7 +2666,7 @@ if code in self.__records: return self.__records[code].text else: - raise IndexError, _("Invalid code") + raise IndexError( _("Invalid code") ) def setText(self,code,text): """setText(self,code,text) @@ -2522,7 +2676,7 @@ Sests the description text of a record """ if not utils.is_valid_code(code)[0]: - raise ValueError, utils.mapping(_("Invalid record: $1"), (code,)) + raise ValueError( utils.mapping(_("Invalid record: $1"), (str(code),)) ) if not code in self.__records: _record = self.setRecord(code, [], "", "", "", [], [], "", "") @@ -2585,7 +2739,7 @@ if self.__root is None: self.__root = code else: - print _("Only can be one root record") + print(_("Only can be one root record") ) return # TODO: If the root is created in settree. No-estructured measures # TODO Rewrite root values @@ -2659,9 +2813,22 @@ """ record.addPrice(price_date, self.getDecimals()) - def getStrPriceFromRecord(self, index_price, record): - _price = record.getPrice(index_price) - _D = self.getDecimals().getD(record.recordType) + def getStrPriceFromRecord(self, index_price, record, path): + if record.isPercentage(): + _percentageMasq = record.percentageMasq() + _parent_code = self.getCode(path[:-1]) + _N_record = path[-1] + _amount_sum = 0.0 + for N,_code in enumerate(self.getchildren(_parent_code)[:_N_record]): + _child_record = self.getRecord(_code) + if _child_record.hasPercentageMasq(_percentageMasq): + _path = path[:-1] + (N,) + _amount = self.getAmount(_path) + _amount_sum = _amount_sum + _amount + _price = _amount_sum + else: + _price = record.getPrice(index_price) + _D = abs(self.getDecimals().getD(record.recordType)) _price = ("%." + str(_D) + "f" ) % _price return _price @@ -2681,16 +2848,16 @@ try: _child = _children_list[i] except: - raise ValueError, _("This record does not exits") + raise ValueError( _("This record does not exits") ) _code = _child.code else: - raise ValueError, _("Path item must be a integer") + raise ValueError( _("Path item must be a integer") ) return _code else: - raise ValueError, _("This record does not exits") + raise ValueError( _("This record does not exits") ) else: - raise ValueError, utils.mapping(_("Path must be a not empty "\ - "tuple: $1"), (str(path),)) + raise ValueError( utils.mapping(_("Path must be a not empty "\ + "tuple: $1"), (str(path),)) ) def getAmount(self, path): """def getAmount(self,path) @@ -2698,6 +2865,7 @@ path: record path Calculate the record amount """ + if len(path) == 1: # root: amount is the root price _root = self.getRecord(self.getRoot()) @@ -2713,10 +2881,25 @@ _yield = _decomposition.budgetMeasures[0].yield_ _child_code = _decomposition.code _child_record = self.getRecord(_child_code) - _price = _child_record.getPrice(self.getActiveTitle()) - _DR = self.getDecimals().getDR(_parent_record.recordType) + _code = self.getCode(path) + _record = self.getRecord(_code) + if _record.isPercentage(): + _percentageMasq = _record.percentageMasq() + _N_record = path[-1] + _amount_sum = 0.0 + for N,_code in enumerate(self.getchildren(_parent_code)[:_N_record]): + _child_record = self.getRecord(_code) + if _child_record.hasPercentageMasq(_percentageMasq): + _path = path[:-1] + (N,) + _amount = self.getAmount(_path) + _amount_sum = _amount_sum + _amount + _price = _amount_sum + else: + _price = _child_record.getPrice(self.getActiveTitle()) + + _DR = abs(self.getDecimals().getDR(_parent_record.recordType)) _total_yield = round(_factor * _yield, _DR) - _DI = self.getDecimals().getDI(_parent_record.recordType) + _DI = abs(self.getDecimals().getDI(_parent_record.recordType)) _amount = round(_total_yield * _price, _DI) return _amount @@ -2728,74 +2911,86 @@ """ if len(path) == 1: #root _root = self.getRecord(self.getRoot()) - _amount = self.getStrPriceFromRecord(self.__title_index, _root) + _amount = self.getStrPriceFromRecord(self.__title_index, _root, path) return _amount else: _parent_code = self.getCode(path[:-1]) _parent_record = self.getRecord(_parent_code) _amount = self.getAmount(path) - _DI = self.getDecimals().getDI(_parent_record.recordType) + _DI = abs(self.getDecimals().getDI(_parent_record.recordType)) _amount = ("%." + str(_DI) + "f") % _amount return _amount def setSheetSection(self,sheet_code,sheet_title): if not isinstance(sheet_code, str): - raise ValueError, _("The sheet code must be a string") + raise ValueError( _("The sheet code must be a string") ) if not isinstance(sheet_title, str): - raise ValueError, _("The sheet title must be a string") + raise ValueError( _("The sheet title must be a string") ) self.__sheet_sections[sheet_code] = sheet_title + def hasSheetSection(self, section): return section in self.__sheet_sections + def getSheetSection(self, section): return self.__sheet_sections[section] + def setSheetSections(self,dictionary): if not isinstance(dictionary, dict): - raise ValueError, _("The sheet sections must be a dictionary") + raise ValueError( _("The sheet sections must be a dictionary") ) for sheet_code in dictionary.keys(): self.setSheetSection(sheet_code, dictionary[sheet_code]) + def setSheetField(self, field_code, field_title): if not isinstance(field_code, str): - raise ValueError, _("The field code must be a string") + raise ValueError( _("The field code must be a string") ) if not isinstance(field_title, str): - raise ValueError, _("The field title must be a string") + raise ValueError( _("The field title must be a string") ) self.__sheet_fields[field_code] = field_title + def hasSheetField(self, field): return field in self.__sheet_fields + def getSheetField(self, field): return self.__sheet_fields[field] + def setSheetFields(self, field_dict): if not isinstance(field_dict, dict): - raise ValueError, _("The sheet field must be a dictionary") + raise ValueError( _("The sheet field must be a dictionary") ) for field_code in field_dict.keys(): self.setSheetField( field_code, field_dict[field_code]) + def setSheetParagraph(self, paragraph_code, paragraph_text): if not isinstance(paragraph_code, str): - raise ValueError, _("The paragraph code must be a string") + raise ValueError( _("The paragraph code must be a string") ) if not isinstance(paragraph_text, str): - raise ValueError, _("The paragraph text must be a string") + raise ValueError( _("The paragraph text must be a string") ) self.__sheet_paragraphs[paragraph_code] = paragraph_text + def hasSheetParagraph(self, paragraph): return paragraph in self.__sheet_paragraphs + def getSheetParagraph(self, paragraph): return self.__sheet_paragraphs[paragraph] + def setSheetParagraphs(self, paragraph_dict): if not isinstance(paragraph_dict, dict): - raise ValueError, _("The paragraph dict must be a dictionary") + raise ValueError( _("The paragraph dict must be a dictionary") ) for paragraph_code in paragraph_dict.keys(): self.setSheetParagraph( paragraph_code, paragraph_dict[paragraph_code]) + def setSheetRecord(self, record_code, field, section_dict): if not isinstance(record_code, str): - raise ValueError, _("The record_code code must be a string") + raise ValueError( _("The record_code code must be a string") ) if not isinstance(field, str): - raise ValueError, _("The field must be a string") + raise ValueError( _("The field must be a string") ) if not isinstance(section_dict, dict): - raise ValueError, _("The section dict must be a dictionary") + raise ValueError( _("The section dict must be a dictionary") ) #-# # TODO: Add a empty record? if not self.hasRecord(record_code): - print utils.mapping(_("Error: The budget do not have this record "\ + print(utils.mapping(_("Error: The budget do not have this record "\ "code and can not be added the sheet text in the field $1. "\ - "Record Code: $2"), ( field, record_code)) + "Record Code: $2"), ( str(field), str(record_code))) ) return #-# if not self.hasSheetField(field): @@ -2807,45 +3002,48 @@ self.setSheetSection(section, "") _sheet = self.getRecord(record_code).getSheet() _sheet.addSection(field, section, paragraph) + def addFile(self, record_code, filepath, type_, description): if not isinstance(record_code, str): - raise ValueError, _("The record_code code must be a string") - if not isinstance(filepath, str): - raise ValueError, _("The filename must be a string") + raise ValueError( _("The record_code code must be a string") ) + #-# str and unicode + if not isinstance(filepath, str) and not isinstance(filepath, unicode): + raise ValueError( _("The filename must be a string") ) #-# # TODO: Add a empty record? if not self.hasRecord(record_code): - print utils.mapping(_("Error: The budget do not have the record "\ + print(utils.mapping(_("Error: The budget do not have the record "\ "code $1 and can not be added the file: $2"), - (record_code, filepath)) + (str(record_code), str(filepath))) ) return #-# _record = self.getRecord(record_code) _record.addFile(filepath, type_, description) + def setCompany(self, company_code, sumamary, name, offices, cif, web, email): if not isinstance(company_code, str): - raise ValueError, _("The company code must be a string") + raise ValueError( _("The company code must be a string") ) if not isinstance(sumamary, str): - raise ValueError, _("The summary must be a string") + raise ValueError( _("The summary must be a string") ) if not isinstance(name, str): - raise ValueError, _("The name must be a string") + raise ValueError( _("The name must be a string") ) if not isinstance(offices, list): - raise ValueError, _("The name must be a list") + raise ValueError( _("The name must be a list") ) _offices = [] for _office in offices: if not isinstance(_office, list): - raise ValueError, _("The office must be a list") + raise ValueError( _("The office must be a list") ) if not len(_office) == 10: - raise ValueError, _("The office must be a 10 items list") + raise ValueError( _("The office must be a 10 items list") ) for _item in _office[:7] + _office[9:10]: if not isinstance(_item, str): - raise ValueError, _("This office item must be a "\ - "string") + raise ValueError( _("This office item must be a "\ + "string") ) for _item in _office[7:8]: if not isinstance(_item, list): - raise ValueError, _("This office item must be a "\ - "list") + raise ValueError( _("This office item must be a "\ + "list") ) _offices.append(Office(_office[0], _office[1], _office[2], @@ -2857,31 +3055,36 @@ _office[8], _office[9])) if not isinstance(cif, str): - raise ValueError, _("The name must be a string") + raise ValueError( _("The name must be a string") ) if not isinstance(web, str): - raise ValueError, _("The web must be a string") + raise ValueError( _("The web must be a string") ) if not isinstance(email, str): - raise ValueError, _("The email must be a string") + raise ValueError( _("The email must be a string") ) self.__companys[company_code] = Company(company_code, sumamary, name, _offices, cif, web, email) def getCompany(self, company_code): return self.__companys[company_code] + def getCompanyKeys(self): return self.__companys.keys() + def addTecInfo(self, ti_code, text, unit): if not isinstance(ti_code, str): - raise ValueError, _("The tecnical info code must be a string") + raise ValueError( _("The tecnical info code must be a string") ) if not isinstance(text, str): - raise ValueError, _("The tecnical info description must be a "\ - "string") + raise ValueError( _("The tecnical info description must be a "\ + "string") ) if not isinstance(unit, str): - raise ValueError, _("The tecnical info unit must be a string") + raise ValueError( _("The tecnical info unit must be a string") ) self.__tec_info[ti_code] = [text, unit] + def hasTecInfo(self, ti_code): return ti_code in self.__tec_info + def getTecInfo(self, ti_code): return self.__tec_info[ti_code] + def setTecnicalInformation(self, record_code, ti_dict): """setTecnicalInformation(record_code, ti_dict) @@ -2891,6 +3094,7 @@ """ # TODO: setTecnicalInformation pass + def changeCode(self, record_code, new_record_code): """changeCode(self, record_code, new_record_code): @@ -2923,7 +3127,7 @@ Add a label to a record """ if not isinstance(label,str): - raise ValueError, _("The label must be a string") + raise ValueError( _("The label must be a string") ) if self.hasRecord(record_code): _record = self.__records[record_code] _record.addLabel(label) @@ -2933,27 +3137,28 @@ _codes = self.__labels[label] if not record_code in _codes: _codes.append(record_code) + def setParametricSelectComment(self, record_code, comment): """setParametricSelectComment(self, record_code, comment) Sets Paramtric Record Select Comment """ if not isinstance(record_code, str): - raise ValueError, _("The record_code code must be a string") + raise ValueError( _("The record_code code must be a string") ) if not isinstance(comment, str): - raise ValueError, _("The parametric select comment must be a "\ - "string") + raise ValueError( _("The parametric select comment must be a "\ + "string") ) if not self.hasRecord(record_code): - print utils.mapping(_("Error: The budget do not have the record "\ + print(utils.mapping(_("Error: The budget do not have the record "\ "code $1 and can not be added the Parametric select comment: "\ "$2"), - (record_code, comment)) + (str(record_code), str(comment))) ) return _record = self.getRecord(record_code) if not isinstance(_record, ParametricRecord): - print utils.mapping(_("Error: The Record $1 is not a "\ + print(utils.mapping(_("Error: The Record $1 is not a "\ "Parametric Record and can not have Parametric comment"), - (record_code,)) + (str(record_code),)) ) else: _record.select_comment = comment @@ -2963,19 +3168,19 @@ Sets parametric record summary """ if not isinstance(record_code, str): - raise ValueError, _("The record_code code must be a string") + raise ValueError( _("The record_code code must be a string") ) if not isinstance(summary, str): - raise ValueError, _("The summary record must be a string") + raise ValueError( _("The summary record must be a string") ) if not self.hasRecord(record_code): - print utils.mapping(_("Error: The budget do not have the record "\ + print(utils.mapping(_("Error: The budget do not have the record "\ "code $1 and can not be seted the summary: $2"), - (record_code, summary)) + (str(record_code), str(summary))) ) return _record = self.getRecord(record_code) if not isinstance(_record, ParametricRecord): - print utils.mapping(_("Error: The Record $1 is not a "\ + print(utils.mapping(_("Error: The Record $1 is not a "\ "Parametric Record and can not have Parametric summary"), - (record_code,)) + (str(record_code),)) ) else: self.getRecord(record_code).parametric_summary = summary @@ -2985,22 +3190,23 @@ Sets parametric record text """ if not isinstance(record_code, str): - raise ValueError, _("The record_code code must be a string") + raise ValueError( _("The record_code code must be a string") ) if not isinstance(text, str): - raise ValueError, _("The text record must be a string") + raise ValueError( _("The text record must be a string") ) if not self.hasRecord(record_code): - print utils.mapping(_("Error: The budget do not have the record "\ + print(utils.mapping(_("Error: The budget do not have the record "\ "code $1 and can not be seted the text: $2"), - (record_code, text)) + (str(record_code), str(text))) ) return _record = self.getRecord(record_code) if not isinstance(_record, ParametricRecord): - print utils.mapping(_("Error: The Record $1 is not a "\ + print(utils.mapping(_("Error: The Record $1 is not a "\ "Parametric Record and can not have Parametric text"), - (record_code,)) + (str(record_code),)) ) else: self.getRecord(record_code).parametric_text = text + class Office(object): """base.Office: @@ -3044,6 +3250,7 @@ {get/set}ContactPerson getValues """ + __slots__ = ["_Office__officeType", "_Office__subname", "_Office__address", @@ -3055,6 +3262,7 @@ "_Office__fax", "_Office__contact_person", ] + def __getstate__ (self): return ( self.__officeType, self.__subname, @@ -3066,6 +3274,7 @@ self.__phone, self.__fax, self.__contact_person) + def __setstate__(self,tuple): self.__officeType = tuple[0] self.__subname = tuple[1] @@ -3090,46 +3299,67 @@ self.phone = phone self.fax = fax self.contact_person = contact_person + def getOfficeType(self): return self.__officeType + def setOfficeType(self, type_): self.__officeType = type_ + def getSubname(self): return self.__subname + def setSubname(self, subname): self.__subname = subname + def getAddress(self): return self.__address + def setAddress(self, address): self.__address = address + def getPostalCode(self): return self.__postal_code + def setPostalCode(self, postal_code): self.__postal_code = postal_code + def getTown(self): return self.__town + def setTown(self, town): self.__town = town + def getProvince(self): return self.__province + def setProvince(self, province): self.__province = province + def getCountry(self): return self.__country + def setCountry(self, country): self.__country = country + def getPhone(self): return self.__phone + def setPhone(self, phone): self.__phone = phone + def getFax(self): return self.__fax + def setFax(self, fax): self.__fax = fax + def getContactPerson(self): return self.__contact_person + def setContactPerson(self, contact_person): self.__contact_person = contact_person + def getValues(self): return {"officeType": self.officeType, "subname": self.subname, @@ -3142,6 +3372,7 @@ "fax": self.fax, "contact person": self.contact_person, } + officeType = property(getOfficeType, setOfficeType, None, """Type of office """) @@ -3176,6 +3407,7 @@ """Dictionary with comapany values """) + class Company(object): """base.Company: @@ -3210,6 +3442,7 @@ {get/set}Email getValues """ + __slots__ = ["_Company__code", "_Company__summary", "_Company__name", @@ -3218,6 +3451,7 @@ "_Company__web", "_Company__email", ] + def __getstate__ (self): return ( self.__code, self.__summary, @@ -3226,6 +3460,7 @@ self.__cif, self.__web, self.__email) + def __setstate__(self,tuple): self.__code = tuple[0] self.__summary = tuple[1] @@ -3243,34 +3478,49 @@ self.cif = cif self.web = web self.email = email + def getCode(self): return self.__code + def setCode(self, code): self.__code = code + def getSummary(self): return self.__summary + def setSummary(self, summary): self.__summary = summary + def getName(self): return self.__name + def setName(self, name): self.__name = name + def getOffices(self): return self.__offices + def setOffices(self, offices): self.__offices = offices + def getCif(self): return self.__cif + def setCif(self, cif): self.__cif = cif + def getWeb(self): return self.__web + def setWeb(self, web): self.__web = web + def getEmail(self): return self.__email + def setEmail(self, email): self.__email = email + def getValues(self): return {"code": self.code, "summary": self.summary, @@ -3278,6 +3528,7 @@ "cif": self.cif, "web": self.web, "email": self.email} + code = property(getCode, setCode, None, """Company code """) @@ -3303,6 +3554,7 @@ """Dictionary with comapany values """) + class File(object): """base.Company: @@ -3326,41 +3578,52 @@ {get/set}Description getValues """ + __slots__ = ["_File__name", "_File__fileType", "_File__description", - ] + def __getstate__ (self): return (self.__name, self.__description, self.__fileType, ) + def __setstate__(self,tuple): self.__name = tuple[0] self.__fileType = tuple[1] self.__description = tuple[2] + def __init__(self, name, type_, description): self.name = name self.fileType = type_ self.description = description + def getName(self): return self.__name + def setName(self, name): self.__name = name + def getFileType(self): return self.__fileType + def setFileType(self, type_): self.__fileType = type_ + def getDescription(self): return self.__description + def setDescription(self, description): self.__description = description + def getValues(self): return {"name": self.name, "fileType": self.fileType, "description": self.description, } + name = property(getName, setName, None, """File name """) @@ -3374,6 +3637,7 @@ """Dictionary with file values """) + class RecordType(object): """base.RecordType: @@ -3432,51 +3696,62 @@ {get/set}Type {get/set}Subtype """ + __slots__ = ["_RecordType__hierarchy", "_RecordType__type", "_RecordType__subtype", ] + def __getstate__ (self): return (self.__hierarchy, self.__type, self.__subtype, ) + def __setstate__(self,tuple): self.__hierarchy = tuple[0] self.__type = tuple[1] self.__subtype = tuple[2] + def __init__(self, hierarchy, type_, subtype): self.hierarchy = hierarchy self.type = type_ self.subtype = subtype + def getHierarchy(self): return self.__hierarchy + def setHierarchy(self, hierarchy): if not hierarchy in [-1, 0 , 1 ,2, ""]: - raise ValueError, utils.mapping(_("Invalid Hierarchy ($1) "\ - "The hierarchy must be -1, 0, 1, 2"), (str(hierarchy),)) + raise ValueError( utils.mapping(_("Invalid Hierarchy ($1) "\ + "The hierarchy must be -1, 0, 1, 2"), (str(hierarchy),)) ) elif hierarchy == "": - print "Hierarchy temporarily set to an empty string" + print("Hierarchy temporarily set to an empty string") #TODO Check empty Hierarchy in Generic.fiebdc.Read._testBudget self.__hierarchy = hierarchy + def getType(self): return self.__type + def setType(self, type_): if not type_ in ["", 0, 1, 2, 3] : - raise ValueError, utils.mapping(_("Invalid type ($1),"\ - "the type must be (empty string,0,1,2,3)"),(str(type_)),) + raise ValueError( utils.mapping(_("Invalid type ($1),"\ + "the type must be (empty string,0,1,2,3)"),(str(type_)),) ) self.__type = type_ + def getSubtype(self): return self.__subtype + def setSubtype(self, subtype): if not subtype in ["", "OB", "PU", "EA", "EU", "EC", "EF", "PA", "H", "Q", "%", "MC", "MCr", "MM", "MS", "ME", "MCu", "Mal","ML","M"]: - raise ValueError, utils.mapping(_("Invalid subtype ($1), The "\ + raise ValueError( utils.mapping(_("Invalid subtype ($1), The "\ "subtype must one in (empty string, EA, "\ "EU, EC, EF, OB, PA, PU, H, Q, %, MC, MCr, "\ - "MM, MS, ME, MCu, MAl, ML, M)"), (str(subtype),)) + "MM, MS, ME, MCu, MAl, ML, M)"), (str(subtype),)) ) self.__subtype = subtype + hierarchy = property(getHierarchy, setHierarchy, None, """Record Hierarchy -1 -> temporarily unfixed diff -r 7bd4ca56607d -r 65e7ae0d0e63 Generic/durusdatabase.py --- a/Generic/durusdatabase.py Tue Sep 30 17:16:50 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -## File durus.py -## This file is part of pyArq-Presupuestos. -## -## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez -## -## -## pyArq-Presupuestos is free software: you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation, either version 3 of the License, or -## (at your option) any later version. -## -## pyArq-Presupuestos is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with this program. If not, see . - -# Modules -import os.path -import time -# Durus Modules -from durus.file_storage import FileStorage -from durus.connection import Connection -# pyArq Presupuestos Modules -from Generic import utils -from Generic import globalVars -class DurusFile(object): - def __init__(self, file, new): - self.__file = file - if new: - if os.path.exists(self.__file): - os.remove(self.__file) - self.__connection = Connection(FileStorage(self.__file)) - self.__root = self.__connection.get_root() - - def close(self): - self.__connection.get_storage().close() - - def getBudget(self): - if self.__root.has_key("baseversion") and \ - globalVars.baseversion == self.__root["baseversion"]: - return self.__root["budget"] - else: - print _("Incorrent Base version") - return None - - def setBudget(self, budget): - self.__root["budget"] = budget - self.__root["baseversion"] = globalVars.baseversion - self.__connection.commit() - -class Read(object): - def __init__(self, filename=None, budget=None): - self.__budget = budget - self.__filename = filename - self.__cancel = False - - def cancel(self): - """def cancel(self) - - It do nothing - """ - # TODO: Cancel reading Durus database. - self.__cancel = True - - def readFile(self, budget=None, filename=None, interface=None): - if not filename is None: - self.__filename = filename - if self.__filename is None or self.__cancel == True: - return None - if not os.path.exists(self.__filename): - return None - print utils.mapping(_("Loading file: $1:"), (self.__filename,)) - _time = time.time() - _durus_file = DurusFile(self.__filename, False) - self.__budget = _durus_file.getBudget() - _durus_file.close() - print utils.mapping(_("Loadig time: $1 seconds"), - (("%.2f" %(time.time()-_time)),)) - return self.__budget diff -r 7bd4ca56607d -r 65e7ae0d0e63 Generic/fiebdc.py --- a/Generic/fiebdc.py Tue Sep 30 17:16:50 2014 +0200 +++ b/Generic/fiebdc.py Thu May 02 16:31:17 2019 +0200 @@ -3,7 +3,7 @@ ## File fiebdc.py ## This file is part of pyArq-Presupuestos. ## -## Copyright (C) 2010-2014 Miguel Ángel Bárcena Rodríguez +## Copyright (C) 2010-2019 Miguel Ángel Bárcena Rodríguez ## ## ## pyArq-Presupuestos is free software: you can redistribute it and/or modify @@ -38,49 +38,45 @@ Description: Reads and parses a fiebdc file + +-- __budget: budget ("base.Budget" object) + +-- __file_format: File format of the fiebdc file + +-- __format_list: List of file format that can be readed + +-- __character_sets_dict: Dictionary with the character sets supported + +-- __character_set: character_set of the file + +- __generator: program which the file is created + +-- __cancel: Boolean value, True mean that the read process must stop + +-- __filename: The filename of the fiebdc file that is readed + +-- __pattern: re compiled pattern dict + +-- __statistics: Statistics object, records number Constructor: fiebdc.Read(filename=None, budget=None) Ancestry: +-- object +-- Read Atributes: - "__budget": budget ("base.Budget" object) - "__file_format": File format of the fiebdc file - "__format_list": List of file format that can be readed - "__character_sets_dict": Dictionary with the character sets supported - "__character_set": character_set of the file - "__generator": program which the file is created - "__cancel": Boolean value, True mean that the read process must stop - "__filename": The filename of the fiebdc file that is readed - "__pattern": re compiled pattern dict - "__statistics": Statistics object, records number + No public Atributes Methods: - __init__(self, filename=None, budget=None) - cancel(self) - eraseControlCharacters(self, string) - validateCode(self, code) - parseDate(self, date) - parseRecord(self,record) - _parseV(self, field_list) - _parseC(self, field_list) - _parseDY(self, field_list) - _parseMN(self, field_list) - _parseT(self, field_list) - _parseK(self, field_list) - _parseW(self, field_list) - _parseL(self, field_list) - _parseQ(self, field_list) - _parseJ(self, field_list) - _parseG(self, field_list) - _parseE(self, field_list) - _parseX(self, field_list) - _parseF(self, field_list) - readFile(self, budget=None, filename=None) + cancel() + eraseControlCharacters(string) + validateCode(code) + parseDate(date) + parseRecord(record) + readFile(budget=None, filename=None) """ def __init__(self, filename=None, budget=None): - """def __init__(self, filename=None, budget=None) + """def __init__(filename=None, budget=None) Sets the instance attributes + __budget: budget ("base.Budget" object) + __file_format: File format of the fiebdc file + __format_list: List of file format that can be readed + __character_sets_dict: Dictionary with the character sets supported + __character_set: character_set of the file + __generator: program which the file is created + __cancel: Boolean value, True mean that the read process must stop + __filename: The filename of the fiebdc file that is readed + __pattern: re compiled pattern dict + __statistics: Statistics object, records number """ self.__budget = budget self.__filename = filename @@ -96,7 +92,7 @@ "850" : "850", "437" : "cp437"} self.__file_format = "FIEBDC-3/2007" - self.__generator = globalVars.version + self.__generator = globalVars.name + " " + globalVars.version self.__character_set = "850" self.__pattern = { "control_tilde" : re.compile(u"((\r\n)| |\t)+~"), @@ -121,14 +117,14 @@ self.__statistics = Statistics() def cancel(self): - """def cancel(self) + """def cancel() Sets the "__cancel" attribute to True, It stops the read process. """ self.__cancel = True def eraseControlCharacters(self, string): - """eraseControlCharacters(self,string) + """eraseControlCharacters(string) Return a copy of the string with the blank characters (32), tabs (9) and end of line (13 and 10) before of the separators @@ -145,23 +141,23 @@ return string def validateCode(self, code): - """validateCode(self, code) + """validateCode(code) Test if the code have invalid characters and try to erase it, if it is posible return a valid code else return a empty string. """ if not isinstance(code, unicode): - print _("Invalid code, it must be a unicode string") + print(_("Invalid code, it must be a unicode string") ) return u"" # Valid chararcter: A-Z a-z 0-9 ñ Ñ . $ # % & _ # "valid_code" : "[^A-Za-z0-9ñÑ.$#%&_]" - _ucode = self.__pattern["valid_code"].sub(u"", code) + _ucode = self.__pattern["valid_code"].sub(u"_", code) if _ucode != code: try: - print utils.mapping(_("The code '$1' have invalid characters."), - (code.encode("utf8"),)) + print(utils.mapping(_("The code '$1' have invalid characters, replaced by '$2'."), + (code.encode("utf8"),_ucode.encode("utf8"))) ) except: - print utils.mapping(_("The code '$1' have invalid characters and can not be encoded in utf8."), (code,)) + print(utils.mapping(_("The code '$1' have invalid characters and can not be encoded in utf8."), (code,)) ) if len(_ucode) == 0: _normalize_code = ''.join((c for c in unicodedata.normalize('NFD', _ucode) if unicodedata.category(c) != 'Mn')) @@ -173,25 +169,30 @@ _hexdigest_code = _hash_code.hexdigest() _ucode = self.__pattern["valid_code"].sub(u"", _hexdigest_code) code = _ucode + if code == u"##": + # root code is an empty code : set to ROOT + return u"ROOT" # the lasts characters can not be <#> or <##> # <##> -> root record in FIEFDC-3 # <#> -> chapter record in FIEFDC-3 if len(code) > 0: while code[-1] == u"#": code = code[:-1] + if len(code) == 0: + return code if len(code) > 20: code = code[:20] # only one charecter # % or & if sum([code.count(c) for c in u'#%&']) > 1: - print utils.mapping(_("The code '$1' contains special "\ - "characters repeated."),(code.encode("utf8"),)) + print(utils.mapping(_("The code '$1' contains special "\ + "characters repeated."),(code.encode("utf8"),)) ) _i = min([code.find(c) for c in u'#%&']) code = code[:_i+1] + \ self.__pattern["special_char"].sub(u"", code[_i+1:]) return code def parseDate(self, date): - """parseDate(self, date) + """parseDate(date) date: in the format: uneven len: add a Leading 0 @@ -233,8 +234,8 @@ _d = 0 return (_y, _m, _d) - def parseRecord(self,record): - """parseRecord(self,record) + def parseRecord(self, record, interface): + """parseRecord(record, interface) record: the record line readed from the file whith the format: type|field|field|subfield\subfield|... @@ -317,6 +318,7 @@ A: Labels 1- Record Code 2- + interface: """ # TODO: ~L ~J RTF and HTML files # TODO: test ~Q ~J ~G @@ -331,13 +333,13 @@ self._parseV(_field_list) elif _field_list[0] == u"C": self.__statistics.C += 1 - self._parseC(_field_list) + self._parseC(_field_list, interface) elif _field_list[0] == u"D": self.__statistics.D += 1 - self._parseDY(_field_list) + self._parseDY(_field_list, interface) elif _field_list[0] == u"Y": self.__statistics.Y += 1 - self._parseDY(_field_list) + self._parseDY(_field_list, interface) elif _field_list[0] == u"M": self.__statistics.M += 1 self._parseMN(_field_list) @@ -386,10 +388,11 @@ self.__statistics.A += 1 self._parseA(_field_list) else: + print(utils.mapping(_("FIEBDC. Unknow record: $1"),(record[:100],))) self.__statistics.unknow += 1 def _parseV(self, field_list): - """_parseV(self, field_list) + """_parseV(field_list) field_list: field list of the record 0- V :Property and Version @@ -404,11 +407,11 @@ 9- [Date budget certificate] """ if self.__statistics.records != 1: - print utils.mapping(_("The 'V' record (Property and Version) "\ + print(utils.mapping(_("The 'V' record (Property and Version) "\ "must be the first record in the file but it is the "\ - "number: $1"), (self.__statistics.records,)) - print _("The default values were taken and this V record is "\ - "ignored") + "number: $1"), (str(self.__statistics.records),)) ) + print(_("The default values were taken and this V record is "\ + "ignored") ) return # _____number of fields_____ # Any INFORMATION after last field separator is ignored @@ -441,7 +444,7 @@ _file_format = _version_date[0] if _file_format in self.__format_list: self.__file_format = _file_format - print utils.mapping(_("FIEBDC format: $1"),(_file_format,)) + print(utils.mapping(_("FIEBDC format: $1"),(_file_format,)) ) if len(_version_date) > 1: _date = _version_date[1] @@ -451,7 +454,7 @@ self.__budget.setDate(_parsed_date) # _____Generator_____ # ignored field - print utils.mapping(_("FIEBDC file generated by $1"),(_generator,)) + print(utils.mapping(_("FIEBDC file generated by $1"),(_generator,)) ) # _____Header_Title_____ _header_title = _header_title.split(u"\\") _header_title = [_title.strip() for _title in _header_title] @@ -499,7 +502,7 @@ self.__statistics.valid = self.__statistics.valid + 1 def _parseK(self, field_list): - """_parseK(self, field_list) + """_parseK(field_list) field_list: field list of the record 0- K: Coefficients @@ -740,8 +743,8 @@ (_decimal_index//13)) self.__statistics.valid = self.__statistics.valid +1 - def _parseC(self, field_list): - """_parseC(self, field_list) + def _parseC(self, field_list, interface): + """_parseC(field_list) field_list: field list of the record 0- C: Record @@ -774,9 +777,9 @@ if len(_codes) > 0: # parse the hierarchy of the first code # hierarchy: 0->root, 1->Chapter/subchapter, 2->other - if len(_codes[0]) > 2 and _codes[0][-2:] == u"##": + if len(_codes[0]) > 1 and _codes[0][-2:] == u"##": _hierarchy = 0 - elif len(_codes[0]) > 1 and _codes[0][-1:] == u"#": + elif len(_codes[0]) > 0 and _codes[0][-1:] == u"#": _hierarchy = 1 else: _hierarchy = 2 @@ -792,7 +795,7 @@ _code = _codes[0] _synonyms = [synonym.encode("utf8") for synonym in _codes] else: - print _("Record C without a valid code") + print(_("Record C without a valid code") ) return # _____Unit_____ # nothing to do @@ -804,6 +807,7 @@ _dates = _dates[:-1] if len(_prices) > 0 and _prices[-1] == u"\\": _prices = _prices[:-1] + interface.updateGui() _dates = _dates.split(u"\\") _prices = _prices.split(u"\\") # number of prices = number of titles in "V" line @@ -860,6 +864,7 @@ # 1 -> None,H # 2 -> None,Q,% # 3 -> None,MC,MCr,MM,MS,ME,MCu,Mal,ML,M + interface.updateGui() if _hierarchy == 0: if _type == u"OB": _subtype = _type @@ -868,8 +873,8 @@ _subtype = u"" _type = 0 else: - print utils.mapping(_("Incorrect type ($1) in the code $2"), - (_type.encode("utf8"), _code.encode("utf8"))) + print(utils.mapping(_("Incorrect type ($1) in the code $2"), + (_type.encode("utf8"), _code.encode("utf8"))) ) _type = 0 _subtype = u"" elif _hierarchy == 1: @@ -880,8 +885,8 @@ _subtype = u"" _type = 0 else: - print utils.mapping(_("Incorrect type ($1) in the code $2"), - (_type.encode("utf8"), _code.encode("utf8"))) + print(utils.mapping(_("Incorrect type ($1) in the code $2"), + (_type.encode("utf8"), _code.encode("utf8"))) ) _type = 0 _subtype = u"" else: @@ -908,8 +913,8 @@ _subtype = u"" _type = 0 else: - print utils.mapping(_("Incorrect type ($1) in the code $2"), - (_type.encode("utf8"), _code.encode("utf8"))) + print(utils.mapping(_("Incorrect type ($1) in the code $2"), + (_type.encode("utf8"), _code.encode("utf8"))) ) _type = 0 _subtype = u"" self.__budget.setRecord(_code.encode("utf8"), _synonyms, _hierarchy, @@ -917,8 +922,8 @@ _prices, _dates, _type, _subtype.encode("utf8")) self.__statistics.valid = self.__statistics.valid + 1 - def _parseDY(self, field_list): - """_parseDY(self, field_list) + def _parseDY(self, field_list, interface): + """_parseDY(field_list) field_list: field list of the record 0- D or Y: DECOMPOSITION or ADD DECOMPOSITION @@ -939,6 +944,7 @@ _record_type = field_list[0] _code = self.delete_control_space(field_list[1]) _children = self.delete_control_space(field_list[2]) + interface.updateGui() # _____Code_____ # "#" and "##" characters at the end of the code are erased # invalid characters are also erased @@ -948,6 +954,7 @@ _children = _children.split(u"\\") _children_list = [ ] _child_index = 0 + interface.updateGui() while _child_index < len(_children)-3: # _____subfields_____ _child_code = _children[_child_index] @@ -960,22 +967,22 @@ try: _factor = float(_factor) except ValueError: - print utils.mapping(_("ValueError loadig the "\ + print(utils.mapping(_("ValueError loadig the "\ "descomposition of the record $1, the factor "\ "of the child $2 must be a float number and "\ "can not be $3, seted default value 1.0"), - (_code.encode("utf8"), _child_code.encode("utf8"), _factor.encode("utf8"))) + (_code.encode("utf8"), _child_code.encode("utf8"), _factor.encode("utf8"))) ) _factor = 1.0 #____yield___ if _yield != u"": try: _yield = float(_yield) except ValueError: - print utils.mapping(_("ValueError loading the "\ + print(utils.mapping(_("ValueError loading the "\ "descomposition of the record $1, the yield of "\ "the child $2, must be a float number and can"\ "not be $3, seted default value 1.0"), - (_code.encode("utf8"), _child_code.encode("utf8"), _factor.encode("utf8"))) + (_code.encode("utf8"), _child_code.encode("utf8"), _factor.encode("utf8"))) ) _yield = 1.0 if _child_code != u"" and _code != u"": _children_list.append([_child_code, _factor, _yield ]) @@ -986,10 +993,11 @@ self.__budget.setTree(_code.encode("utf8"), _child_code.encode("utf8"), _position, _factor, _yield, "", "", "", "") _child_index = _child_index + 3 + interface.updateGui() self.__statistics.valid = self.__statistics.valid +1 def _parseT(self, field_list): - """_parseT(self, field_list) + """_parseT(field_list) field_list: field list of the record 0- T: Text @@ -1017,7 +1025,7 @@ self.__statistics.valid = self.__statistics.valid + 1 def _parseMN(self, field_list): - """_parseMN(self, field_list) + """_parseMN(field_list) field_list: field list of the record 0- M or N: MEASURE or ADD MEASURE @@ -1059,12 +1067,12 @@ _child_code = self.validateCode(_code_list[0]) _parent_code = None else: - print utils.mapping(_("Invalid codes in $1 record, codes $2"), - (_record_type.encode("utf8"), _codes.encode("utf8"))) + print(utils.mapping(_("Invalid codes in $1 record, codes $2"), + (_record_type.encode("utf8"), _codes.encode("utf8"))) ) return if _child_code == u"": - print utils.mapping(_("Empty child code in $1 record, codes: "\ - "$2"), (_record_type.encode("utf8"), _codes.encode("utf8"))) + print(utils.mapping(_("Empty child code in $1 record, codes: "\ + "$2"), (_record_type.encode("utf8"), _codes.encode("utf8"))) ) return if _parent_code == None: # Empty parent code. No-estructured measures. @@ -1083,8 +1091,8 @@ try: _path = int(_path) except ValueError: - print utils.mapping(_("Invalid path in $1 record, "\ - "codes $2"), (_record_type.encode("utf8"), _codes.encode("utf8"))) + print(utils.mapping(_("Invalid path in $1 record, "\ + "codes $2"), (_record_type.encode("utf8"), _codes.encode("utf8"))) ) return if _path > 0: _path -= 1 @@ -1094,9 +1102,9 @@ try: _total = float(_total) except ValueError: - print utils.mapping(_("Invalid Total Measure value in $1 "\ + print(utils.mapping(_("Invalid Total Measure value in $1 "\ "record, codes $2. Total fixed to 0."), - (_record_type.encode("utf8"), _codes.encode("utf8"))) + (_record_type.encode("utf8"), _codes.encode("utf8"))) ) _total = 0 # _____Measure lines_____ _lines = _lines.split(u"\\") @@ -1115,9 +1123,9 @@ if _linetype == 3: # "formula": ".*[^0123456789\.()\+\-\*/\^abcdp ].*" if self.__pattern["formula"].match(_comment): - print utils.mapping(_("The comment is not a formula or "\ + print(utils.mapping(_("The comment is not a formula or "\ "its have invalid characters, in the $1 record, "\ - "codes $2"), (_record_type.encode("utf8"), _codes.encode("utf8"))) + "codes $2"), (_record_type.encode("utf8"), _codes.encode("utf8"))) ) return else: _formula = _comment.encode("utf8") @@ -1141,8 +1149,8 @@ if _width != u"": _width = float(_width) if _height != u"": _height = float(_height) except ValueError: - print utils.mapping(_("The measure values are not float "\ - "numbers, code $1"), (_codes.encode("utf8"),)) + print(utils.mapping(_("The measure values are not float "\ + "numbers, code $1"), (_codes.encode("utf8"),)) ) return # Prevent subfield units remains empty. if (_units == u"" and (_length != u"" or _width != u"" @@ -1156,7 +1164,7 @@ self.__statistics.valid = self.__statistics.valid + 1 def _parseW(self, field_list): - """_parseW(self, field_list) + """_parseW(field_list) field_list: field list of the record 0- W: Geografical field @@ -1195,7 +1203,7 @@ self.__statistics.valid = self.__statistics.valid +1 def _parseL(self, field_list): - """_parseL(self, field_list) + """_parseL(field_list) field_list: field list of the record 0- L: Sheet of Conditions 1 @@ -1259,7 +1267,7 @@ _scodes_text = field_list[1] if _scodes_text == u"": # TODO: rtf and html files - print "Html and rtf files not yet implemented in ~L record" + print("Html and rtf files not yet implemented in ~L record" ) else: # _____Section-code_Section-text_____ # last \ is erased @@ -1288,7 +1296,7 @@ self.__statistics.valid = self.__statistics.valid +1 def _parseQ(self, field_list): - """_parseQ(self, field_list) + """_parseQ(field_list) field_list: field list of the record 0- Q: Sheet of Conditions 2 @@ -1349,7 +1357,7 @@ self.__statistics.valid = self.__statistics.valid +1 def _parseJ(self, field_list): - """_parseJ(self, field_list) + """_parseJ(field_list) field_list: field list of the record 0- J: Sheet of Conditions 3 @@ -1374,13 +1382,13 @@ _paragraph_text = field_list[1] if _paragraph_text == u"": # TODO: rtf and html files - print "Html and rtf files not yet implemented in ~J record" + print("Html and rtf files not yet implemented in ~J record" ) else: self.__budget.setSheetParagraph(paragraph_code.encode("utf8"), paragraph_text.encode("utf8")) self.__statistics.valid = self.__statistics.valid +1 def _parseG(self, field_list): - """_parseG(self, field_list) + """_parseG(field_list) field_list: field list of the record 0- G: Grafic info @@ -1412,7 +1420,7 @@ _tested_grafic_file_list = [] for _grafic_file in _grafic_file_list: _str_grafic_file = _grafic_file.encode("utf8") - _path = os.path.dirname(self.__filename) + _path = os.path.dirname(self.__filename).encode("utf8") _grafic_file_path = os.path.join(_path, _str_grafic_file) if os.path.exists(_grafic_file_path): _tested_grafic_file_list.append(_grafic_file_path) @@ -1441,15 +1449,15 @@ elif os.path.exists(_grafic_file_path_ll): _tested_grafic_file_list.append(_grafic_file_path_ll) else: - print utils.mapping(_("The file $1 do not exist"), - (_grafic_file_path,)) + print(utils.mapping(_("The file $1 do not exist"), + (_grafic_file_path.decode("utf8"),)) ) if len(_grafic_file_list) > 0: for _grafic_file in _tested_grafic_file_list: self.__budget.addFile(_record_code.encode("utf8"), _grafic_file, "img", "") self.__statistics.valid = self.__statistics.valid +1 def _parseE(self, field_list): - """_parseE(self, field_list) + """_parseE(field_list) field_list: field list of the record 0- E: Company @@ -1548,7 +1556,7 @@ self.__statistics.valid = self.__statistics.valid +1 def _parseX(self, field_list): - """_parseX(self, field_list) + """_parseX(field_list) field_list: field list of the record A) @@ -1603,14 +1611,15 @@ self.__statistics.valid = self.__statistics.valid +1 def _parseF(self, field_list): - """_parseF(self, field_list) + """_parseF(field_list) field_list: field list of the record 0- F: Files 1- Record code 2- { Type \ { Filenames; } \ [Description] } """ - + print("parseF") + print(field_list) # _____Number of fields_____ # The record must have at least 3 fields if len(field_list) < 3: @@ -1638,23 +1647,24 @@ _files_list.extend[u""]*(3 - len(_files_list)%3) _file_index = 0 _tested_files_list = [] + print(_files_list) while _file_index < len(_files_list)-3: _type = _files_list[_file_index].replace(u" ",u"") -## _types = { -## "0": _("others"), -## "1": _("características técnicas y de fabricación"), -## "2": _("manual de colocación, uso y mantenimiento"), -## "3": _("certificado/s de elementos y sistemas"), -## "4": _("normativa y bibliografía"), -## "5": _("tarifa de precios"), -## "6": _("condiciones de venta"), -## "7": _("carta de colores"), -## "8": _("ámbito de aplicación y criterios selección"), -## "9": _("cálculo de elementos y sistemas"), -## "10": _("presentación, datos generales, objetivos, etc. de "\ -## "empresa"), -## "11": _("certificado/s de empresa"), -## "12": _("obras realizadas")} + ## _types = { + ## "0": _("others"), + ## "1": _("características técnicas y de fabricación"), + ## "2": _("manual de colocación, uso y mantenimiento"), + ## "3": _("certificado/s de elementos y sistemas"), + ## "4": _("normativa y bibliografía"), + ## "5": _("tarifa de precios"), + ## "6": _("condiciones de venta"), + ## "7": _("carta de colores"), + ## "8": _("ámbito de aplicación y criterios selección"), + ## "9": _("cálculo de elementos y sistemas"), + ## "10": _("presentación, datos generales, objetivos, " \ + ## "etc. de empresa"), + ## "11": _("certificado/s de empresa"), + ## "12": _("obras realizadas")} _types = [u"0", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"10", u"11", u"12"] if not _type in _types: @@ -1662,11 +1672,15 @@ _filenames = _files_list[_file_index + 1] _description = _files_list[_file_index + 2] _file_index += 3 + print(u"type: " + _type) + print(u"filenames: " + _filenames) + print(u"_description: " + _description) if len(_filenames) and _filenames[-1] == u";": _files = _files[:-1] - _filenames_list = _files.split(u";") + _filenames_list = _filenames.split(u";") + _path = os.path.dirname(self.__filename) - for _filename in filenames_list: + for _filename in _filenames_list: _file_path = os.path.join(_path, _filename.encode("utf8")) if os.path.exists(_file_path): _tested_files_list.append([_file_path, _type.encode("utf8"), @@ -1700,15 +1714,15 @@ _tested_files_list.append([_file_path_ll, _type.encode("utf8"), _description.encode("utf8")]) else: - print utils.mapping(_("The file $1 do not exist"), - (_file_path,)) + print(utils.mapping(_("The file $1 do not exist"), + (_file_path,)) ) if len(_tested_files_list) > 0: - for _file in _tested_file_list: - self.__budget.addFile(_record_code.encode("utf8"), _file[0], file[1], file[2]) + for _file in _tested_files_list: + self.__budget.addFile(_record_code.encode("utf8"), _file[0], _file[1], _file[2]) self.__statistics.valid = self.__statistics.valid +1 def _parseB(self, field_list): - """_parseB(self, field_list) + """_parseB(field_list) field_list: field list of the record 0- B: Change code @@ -1737,7 +1751,7 @@ self.__statistics.valid = self.__statistics.valid + 1 def _parseA(self, field_list): - """_parseA(self, field_list) + """_parseA(field_list) field_list: field list of the record 0- A: Labels @@ -1774,7 +1788,7 @@ self.__statistics.valid = self.__statistics.valid + 1 def _parseP(self, field_list): - """_parseP(self, field_list) + """_parseP(field_list) field_list: Parametric record A) Global paremetric record @@ -1806,14 +1820,14 @@ field_list = field_list[0:3] field_list = field_list[1:] if len(field_list) != 2: - print _("PyArq hates parametric DLLs") + print(_("PyArq hates parametric DLLs") ) return else: return # _____Description_____ _description = field_list[1] if _description == u"": - print _("PyArq hates parametric DLLs") + print(_("PyArq hates parametric DLLs") ) return # Adding last end of line _description = _description + u"\r\n" @@ -1878,19 +1892,19 @@ # parse data if len(_line) > 2 and _line[:2] == u"::": # Delete spaces out " delimiter - #print "__PRECIO__" + _line[2:] + #print("__PRECIO__" + _line[2:]) pass elif len(_line) > 2 and _line[:2] == u"%:": # Delete spaces out " delimiter - #print "__%AUX__" + _line[2:] + #print("__%AUX__" + _line[2:]) pass elif len(_line) > 3 and _line[:2] == u"%%:": # Delete spaces out " delimiter - #print "__%%AUX__" + _line[2:] + #print("__%%AUX__" + _line[2:] ) pass elif self.__pattern["var"].search(_line): # Delete spaces out " delimiter - #print "line =", _line + #print( "line =", _line ) while _line.count(u'"') % 2 == 1 and \ index + _pass_line + 1 < len(_lines) -1: _line = _line + _lines[index + _pass_line + 1] @@ -1898,10 +1912,10 @@ _search = self.__pattern["var"].search(_line) if _search is not None: _var = _search.groups()[0] + u" = " + _search.groups()[1] - #print "__VAR__" + str(_var) + #print("__VAR__" + str(_var) ) pass else: - #print "no __VAR__", _line + #print( "no __VAR__", _line ) pass elif self.__pattern["descomposition"].search(_line): # Delete spaces out " delimiter @@ -1909,73 +1923,73 @@ _search = self.__pattern["descomposition"].search(_line) if _search is not None: _var = _search.groups()[0] + u":" + _search.groups()[1] - #print "__Descomposición__" + str(_var) + #print( "__Descomposición__" + str(_var) ) pass else: - #print "no __Descomposición__", _line + #print("no __Descomposición__", _line ) pass else: - print "Parametric: code: " + _family_code.encode("utf8") - print "******* Desconocido *** : " + _line - if index-10 > 0: print "-11 :", _lines[index-11].encode("utf8") - if index-10 > 0: print "-10 :", _lines[index-10].encode("utf8") - if index-9 > 0: print "-9 :", _lines[index-9].encode("utf8") - if index-8 > 0: print "-8 :", _lines[index-8].encode("utf8") - if index-7 > 0: print "-7 :", _lines[index-7].encode("utf8") - if index-6 > 0: print "-6 :", _lines[index-6].encode("utf8") - if index-5 > 0: print "-5 :", _lines[index-5].encode("utf8") - if index-4 > 0: print "-4 :", _lines[index-4].encode("utf8") - if index-3 > 0: print "-3 :", _lines[index-3].encode("utf8") - if index-2 > 0: print "-2 :", _lines[index-2].encode("utf8") - if index-1 > 0: print "-1 :", _lines[index-1].encode("utf8") - print "-0 :", _lines[index-0] + print("Parametric: code: " + _family_code.encode("utf8") ) + print("******* Desconocido *** : " + _line ) + if index-10 > 0: print("-11 : " + _lines[index-11].encode("utf8") ) + if index-10 > 0: print("-10 : " + _lines[index-10].encode("utf8") ) + if index-9 > 0: print("-9 : " + _lines[index-9].encode("utf8") ) + if index-8 > 0: print("-8 : " + _lines[index-8].encode("utf8") ) + if index-7 > 0: print("-7 : " + _lines[index-7].encode("utf8") ) + if index-6 > 0: print("-6 : " + _lines[index-6].encode("utf8") ) + if index-5 > 0: print("-5 : " + _lines[index-5].encode("utf8") ) + if index-4 > 0: print("-4 : " + _lines[index-4].encode("utf8") ) + if index-3 > 0: print("-3 : " + _lines[index-3].encode("utf8") ) + if index-2 > 0: print("-2 : " + _lines[index-2].encode("utf8") ) + if index-1 > 0: print("-1 : " + _lines[index-1].encode("utf8") ) + print("-0 :" + _lines[index-0] ) pass else: _parameter_list = _line.split(u"\\")[1:-1] if len(_parameter_list) >= 2: if _parameter_list[0] == u"C" or \ _parameter_list[0] == u"COMENTARIO": - #print "__COMENTARIO__" + _parameter_list[1] + #print( "__COMENTARIO__" + _parameter_list[1]) self.__budget.setParametricSelectComment( _family_code.encode("utf8"), _parameter_list[1].encode("utf8")) elif _parameter_list[0] == u"R" or \ _parameter_list[0] == u"RESUMEN": - #print "__RESUMEN__" + _parameter_list[1] + #print( "__RESUMEN__" + _parameter_list[1]) self.__budget.setParametricSummary(_family_code.encode("utf8"), _parameter_list[1].encode("utf8")) elif _parameter_list[0] == u"T" or \ _parameter_list[0] == u"TEXTO": - #print "__TEXTO__" + _parameter_list[1] + #print( "__TEXTO__" + _parameter_list[1]) self.__budget.setParametricText(_family_code.encode("utf8"), _parameter_list[1].encode("utf8")) elif _parameter_list[0] == u"P" or \ _parameter_list[0] == u"PLIEGO": - #print "__PLIEGO__" + str(_parameter_list[1:]) + #print( "__PLIEGO__" + str(_parameter_list[1:]) ) pass elif _parameter_list[0] == u"K" or \ _parameter_list[0] == u"CLAVES": - #print "__CLAVES__" + str(_parameter_list[1:]) + #print( "__CLAVES__" + str(_parameter_list[1:]) ) pass elif _parameter_list[0] == u"F" or \ _parameter_list[0] == u"COMERCIAL": - #print "__COMERCIAL__" + str(_parameter_list[1:]) + #print( "__COMERCIAL__" + str(_parameter_list[1:]) ) pass else: - #print "==PARAMETRO==" + str(_parameter_list[:]) + #print( "==PARAMETRO==" + str(_parameter_list[:]) ) pass _final_description = _final_description + _line + u"\r\n" - #print _line + #print( _line ) # Delete last empty line _description = _final_description[:-2] _lines = _description.split(u"\r\n") for _line in _lines: pass - #print _line + #print( _line ) self.__statistics.valid = self.__statistics.valid + 1 def readFile(self, budget=None, filename=None, interface=None): - """readFile(self, budget=None, filename=None) + """readFile(budget=None, filename=None) filename: the filename of the fiebdc file budget: base.obra object @@ -1985,7 +1999,8 @@ readFile_progress(percent) readFile_end() readFile_cancel() - Return the budget objetc or None if the file can be readed + updateGui() + Return None """ if not filename is None and not budget is None: self.__filename = filename @@ -2002,14 +2017,19 @@ try: _file = open(self.__filename, 'r') except IOError: - print utils.mapping("IOError: $1", (self.__filename,)) + print( utils.mapping("IOError: $1", (self.__filename,)) ) + return None + _filesize = float(os.path.getsize(self.__filename)) + if _filesize == 0.0: + print( utils.mapping("Empty File: $1", (self.__filename,)) ) + # Todo: Create empty budget return None self.__budget.filename = self.__filename interface.readFile_send_message(utils.mapping(_("Loading file $1"), (self.__filename,))) - _filesize = float(os.path.getsize(self.__filename)) interface.readFile_progress(_file.tell() / _filesize) _buffer = _file.read(1000) + interface.updateGui() # set codepage from V record _record_list = _buffer.split("~") registro_V = _record_list[1] @@ -2043,6 +2063,7 @@ "Not 'V' record in File! Default character encoding: "\ "$1"), (self.__character_set,))) _buffer = unicode(_buffer, self.__character_set) + interface.updateGui() # Any INFORMATION between the beginning of the file and the # beginning of the first registry “~” is ignored #"after_first_tilde" : "^[^~]*~" @@ -2056,11 +2077,12 @@ _record_list = _buffer.split(u"~") # The last record can be incomplete unless it is the last one of # the file - if len(_record_list) > 1: + #if len(_record_list) > 1: + if (_file.tell() / _filesize) != 1.0: # not the end _last_record = _record_list.pop() else: - # the end record + # The last record # The blank characters (32), tabs (9) and end of line # (13 and 10) at the end of the file are ignored. #"end_control" : "((\r\n)| |\t)+$" @@ -2070,11 +2092,14 @@ for record in _record_list: if self.__cancel: break - self.parseRecord(record) + self.parseRecord(record, interface) + interface.updateGui() interface.readFile_progress(_file.tell() / _filesize) _buffer2 = _file.read(100000) + interface.updateGui() _buffer2 = unicode(_buffer2, self.__character_set) _buffer = _last_record + _buffer2 + interface.updateGui() _file.close() if self.__cancel: interface.readFile_cancel() @@ -2084,22 +2109,22 @@ if self.__statistics.O > 0: interface.readFile_send_message( utils.mapping(_("$1 unsuported record type O: "\ - "Comercial Relationship"), (self.__statistics.O,))) + "Comercial Relationship"), (str(self.__statistics.O,)))) if self.__statistics.valid == 0: interface.readFile_send_message(_("This file is not a valid FIBDC3 file")) return None interface.readFile_end() - self._testBudget(self.__budget) - return self.__budget + self._testBudget(self.__budget, interface) + return None - def _testBudget(self, budget): - """testBudget(self,budget) + def _testBudget(self, budget, interface): + """testBudget(budget) budget: base.obra object Test and repair budget object after read it from bc3 file """ # TODO: more to do here - print _("Testing budget ...") + print( _("Testing budget ...") ) # Add price to records without price _iter = budget.iter() _titlelist = budget.getTitleList()[1] @@ -2117,7 +2142,8 @@ _root = budget.getRecord(budget.getRoot()) _price = [0.0, _root.getDate(_len_prices + _index)] budget.addPriceToRecord(_price,_record) - print _("End Test") + interface.updateGui() + print( _("End Test") ) def delete_control_space(self, text): text = self.delete_control(text) @@ -2141,6 +2167,7 @@ +-- object +-- Interface Atributes: + "endSuccessfully": True/False "__progress": The progress percentage "__statistics": The record statistics Methods: @@ -2150,11 +2177,13 @@ readFile_set_statistics(statistics) readFile_end() readFile_cancel() + updateGui() """ def __init__(self): self.__progress = 0.0 self.__statistics = Statistics() + self.endSuccessfully = False def readFile_set_statistics(self, statistics): """readFile_set_statistics(statistics) @@ -2170,9 +2199,9 @@ message: mesage from readFile method - print message + print( message ) """ - print message + print( message ) def readFile_progress(self, percent): """progress(percent) @@ -2188,14 +2217,26 @@ The readFile method end successfully """ - print self.__statistics + self.endSuccessfully == True + print(self.__statistics) + print("progreso = " + str(self.__progress)) def readFile_cancel(self): """readFile_cancel() The readFile method is canceled """ - print _("Process terminated") + self.endSuccessfully == False + print( _("Process terminated") ) + print("progreso = " + str(self.__progress)) + + def updateGui(self): + """updateGui(self) + + Some interfaces need update gui while doing some time intensive + computation. Do it here. + """ + pass class Statistics(object): """fiebdc.Statistics @@ -2264,10 +2305,14 @@ self.time = 0.0 def __str__(self): + return self.str().encode("utf8") + + def str(self): + return utils.mapping(_("Time to load: $1 seconds"), (("%.2f" %(self.time)),)) + "\n" + \ utils.mapping(_("Records/Valid Records: $1/$2"), - (self.records, self.valid)) + "\n" +\ + (str(self.records), str(self.valid))) + "\n" +\ "V: %s\n" %(self.V,) + \ "C: %s\n" %(self.C,) + \ "D: %s\n" %(self.D,) + \ diff -r 7bd4ca56607d -r 65e7ae0d0e63 Generic/globalVars.py --- a/Generic/globalVars.py Tue Sep 30 17:16:50 2014 +0200 +++ b/Generic/globalVars.py Thu May 02 16:31:17 2019 +0200 @@ -3,7 +3,7 @@ ## File globalVars.py ## This file is part of pyArq-Presupuestos. ## -## Copyright (C) 2010-2014 Miguel Ángel Bárcena Rodríguez +## Copyright (C) 2010-2019 Miguel Ángel Bárcena Rodríguez ## ## ## pyArq-Presupuestos is free software: you can redistribute it and/or modify @@ -20,20 +20,26 @@ ## along with this program. If not, see . # module for global variables +# not translatable strings here _("strig") + import os import sys -version = "pyArq Presupuestos v0.0.0" -changeset = 22 +name = "pyArq Presupuestos" +version = "v0.0.0" +changeset = "c23" baseversion = 0 # path: Paths where find the program files needed path = { "HOME" : "", "APPDATA" : "", - #"DURUS-DATABASE": "/pyArq-Presupuestos/durus/", "BUDGET": "/pyArq-Presupuestos/budget/", "ICON" : "/images/pyArq-Presupuestos.png", + "ICON16" : "/images/pyArq-Presupuestos-16.svg", + "ICON32" : "/images/pyArq-Presupuestos-32.svg", + "ICON64" : "/images/pyArq-Presupuestos-64.svg", + "ICON128" : "/images/pyArq-Presupuestos-128.svg", "CHAPTER-ICON" : "/images/chapter.png", "UNIT-ICON" : "/images/unit.png", "MATERIAL-ICON" : "/images/material.png", @@ -43,10 +49,14 @@ "CONNECTED-ICON": "/images/connected.png", "DISCONNECTED-ICON": "/images/disconnected.png", "CLOSE-ICON": "/images/close.png", + "HORIZONTAL": "/images/horizontal.svg", + "VERTICAL": "/images/vertical.svg", "DESCRIPTION-ICON": "/images/description.png", "SHEET-ICON": "/images/sheet.png", "DECOMPOSITION-ICON" : "/images/decomposition.png", "MEASURE-ICON" : "/images/measure.png", + "FILEVIEW-ICON" : "/images/fileview.png", + "COMPANY-ICON" : "/images/company.png", "ACUMULATEDLINE-ICON" : "/images/acumulatedline.png", "PARCIALLINE-ICON" : "/images/parcialline.png", "NORMALLINE-ICON" : "/images/normalline.png", @@ -54,33 +64,37 @@ "ARROW-ICON": "/images/arrow.png", "IMAGE-ICON": "/images/image.png", "DXF-ICON": "/images/dxf.png", - "THROBBER-ICON": "/images/throbber.png", - "THROBBER-GIF": "/images/throbber.gif", + "PDF-ICON": "/images/pdf.png", "BUDGET-ICON": "/images/budget.png", "PYARQ-ICON": "/images/pyArq.png", } color = { - "ACTIVE" : "#CDD7FF", # blue - "INDEX-EVEN" : "#C4C4C4", # dark grey - "INDEX-UNEVEN" : "#DDDDDD", # grey - "EVEN" : "#E6E6E6", # dark white - "UNEVEN": "#FFFFFF", # white - "CHAPTER-EVEN": "#D8E6E6", # dark cian - "CHAPTER-UNEVEN": "#F0FFFF", # cian - "TEXT": "#000000", # black - "CALCULATED-TEXT": "#FF00FF", # - "SUBTOTAL": "#FAC8C8", - "SUBTOTAL-PARCIAL": "#ADD8E6", + "ACTIVE" : "#CDD7FF", # Lavender Blue (205,215,255,1) + "INDEX-EVEN" : "#C4C4C4", # Silver, dark grey (196,196,196,1) + "INDEX-UNEVEN" : "#DDDDDD", # Gainsboro, grey (221,221,221,1) + "EVEN" : "#E6E6E6", # Whisper, dark white (230,230,230,1) + "UNEVEN": "#FFFFFF", # White (255,255,255,1) + "CHAPTER-EVEN": "#D8E6E6", # Zircon, dark cian (216,230,230,1) + "CHAPTER-UNEVEN": "#F0FFFF", # Azure, cian (240,255,255,1) + "TEXT": "#000000", # Black ( 0, 0, 0,1) + "CALCULATED-TEXT": "#FF00FF", # Magenta (255, 0,255,1) + "SUBTOTAL": "#FAC8C8", # Coral Candy (250,200,200,1) + "SUBTOTAL-PARCIAL": "#ADD8E6", # Light Blue (173,216,230,1) } desktop = { - "autodetect" : True, - "desktop" : "", - "browser" : "firefox", - "mailapp" : "evolution", - "imageapp" : "gthumb", - "cadapp" : "qcad", + "autodetect" : True, # True: try to autodect desktop + "desktop" : "", # "linux", "macosx" or "windows" + "browser" : "", # "firefox" + "mailapp" : "", # "evolution" + "imageapp" : "", # "gthumb" + "wmfapp" : "", # "inkscape" + "cadapp" : "", # "librecad" + "videoapp" : "", # "vlc" + "officeapp" : "", # "libreoffice" + "txtapp" : "", # "gedit" + "rtfapp" : "", # "libreoffice" } def getAppPath(key): diff -r 7bd4ca56607d -r 65e7ae0d0e63 Generic/openwith.py --- a/Generic/openwith.py Tue Sep 30 17:16:50 2014 +0200 +++ b/Generic/openwith.py Thu May 02 16:31:17 2019 +0200 @@ -3,10 +3,10 @@ ## File openwith.py ## This file is part of pyArq-Presupuestos. ## -## Copyright (C) 2010-2013 Miguel Ángel Bárcena Rodríguez +## Copyright (C) 2010-2019 Miguel Ángel Bárcena Rodríguez ## ## -## This file is based in gtkgui_helpers.py and common/helpers.py from gajim +## This file is based in common/helpers.py from gajim ## ## Copyright (C) 2003-2008 Yann Leboulanger ## Copyright (C) 2005-2006 Dimitur Kirov @@ -33,72 +33,39 @@ ## along with Gajim. If not, see . ## # Modules + +# python 2/3 compatibility +from __future__ import absolute_import, division, print_function, unicode_literals + import subprocess import os +import platform +import sys # pyArq-Presupuestos modules -import globalVars - -# from gtkgui_helpers.py -def autodetect_desktop(): - # recognize the environment and sets it in globalVars - if os.name == 'nt': - globalVars.desktop["desktop"] = "windows" - else: - _processes = get_running_processes() - if 'gnome-session' in _processes: - globalVars.desktop["desktop"] = "gnome" - elif 'startkde' in _processes: - globalVars.desktop["desktop"] = "kde" - elif 'startxfce4' in _processes or 'xfce4-session' in _processes: - globalVars.desktop["desktop"] = "xfce" - elif 'startlxde' in _processes or 'lxsession' in _processes: - globalVars.desktop["desktop"] = "lxde" - elif 'awesome' in _processes: - globalVars.desktop["desktop"] = "awesome" - elif 'dwm' in _processes: - globalVars.desktop["desktop"] = "dwm" - elif 'startfluxbox' in _processes: - globalVars.desktop["desktop"] = "fluxbox" - elif 'fvwm2' in _processes: - globalVars.desktop["desktop"] = "fvwm" - else: - globalVars.desktop["desktop"] = "" +from Generic import globalVars -def get_running_processes(): - '''returns running processes or None (if not /proc exists)''' - if os.path.isdir('/proc'): - # under Linux: checking if 'gnome-session' or - # 'startkde' programs were run before gajim, by - # checking /proc (if it exists) - # - # if something is unclear, read `man proc`; - # if /proc exists, directories that have only numbers - # in their names contain data about processes. - # /proc/[xxx]/exe is a symlink to executable started - # as process number [xxx]. - # filter out everything that we are not interested in: - files = os.listdir('/proc') - - # files that doesn't have only digits in names... - files = filter(str.isdigit, files) - - # files that aren't directories... - files = [f for f in files if os.path.isdir('/proc/' + f)] - - # processes owned by somebody not running gajim... - # (we check if we have access to that file) - files = [f for f in files if os.access('/proc/' + f +'/exe', os.F_OK)] - - # be sure that /proc/[number]/exe is really a symlink - # to avoid TBs in incorrectly configured systems - files = [f for f in files if os.path.islink('/proc/' + f + '/exe')] - - # list of processes - processes = [os.path.basename(os.readlink('/proc/' + f +'/exe')) for f in files] - - return processes - return [] +def autodetect_desktop(): + """ + recognize the environment and sets it in globalVars + os.name: + python2 'posix', 'nt', 'os2', 'ce', 'java', 'riscos'. + python3 'posix', 'nt', 'java'. + sys.platform + unix: return by uname + Linux 'linux', 'linux2' + Windows 'win32' + Windows/Cygwin 'cygwin' + Mac OS X 'darwin' + """ + if os.name == "nt": + globalVars.desktop["desktop"] = "windows" + elif sys.platform == "darwin": + globalVars.desktop["desktop"] = "macosx" + elif sys.platform.startswith('linux'): + globalVars.desktop["desktop"] = "linux" + else: + globalVars.desktop["desktop"] = sys.platform # from common/helpers.py @@ -113,33 +80,69 @@ return command def launch_file(kind, uri): - # kind = "url" ,"mail", "image", "dxf" + """ + kind = "url" ,"mail", "image", "dxf", "wmf", "pdf", video", + "office-document", "office-presentation", "office-spreadsheet", + "html", "rtf", "txt", "" + Linux: xdg-open supports: + Xfce (exo-open "$1"), + Gnome (gvfs-open "$1", gnome-open "$1" with fallback to generic open), + KDE (kde-open "$1" with fallback to kfmclient exec "$1"), + Mate (gvfs-open "$1", mate-open $1), + LXDE (pcmanfm $1 with fallback to generic open), + Enlightenment (enlightenment_open $1), + Cinnamon (open_gnome3 $1, which is gvfs-open "$1" with fallback to generic open), + Cygwin (cygstart "$1"), + Darwin (open "$1"). + + + """ + # TODO: test in Mac os X + # TODO: test in Windows + # TODO: configured apps in windows? + + if kind == "mail" and not uri.startswith("mailto:"): + uri = "mailto:" + uri + _desktop = globalVars.desktop["desktop"] + if _desktop == "windows": try: os.startfile(uri) # if pywin32 is installed we open except Exception: pass else: - if kind == 'mail' and not uri.startswith('mailto:'): - uri = 'mailto:' + uri - if _desktop == "gnome": - command = 'gnome-open' - elif _desktop == "kde": - command = 'kfmclient exec' - elif _desktop == "xfce": - command = 'exo-open' + # if app is configured in globarVars use it + if kind in ("url", "html") and globalVars.desktop["browser"] != "": + command = globalVars.desktop["browser"] + elif kind == "mail" and globalVars.desktop["mailapp"] != "": + command = globalVars.desktop["mailapp"] + elif kind == "image" and globalVars.desktop["imageapp"] != "": + command = globalVars.desktop["imageapp"] + elif kind == "wmf" and globalVars.desktop["wmfapp"] != "": + command = globalVars.desktop["wmfapp"] + elif kind == "dxf" and globalVars.desktop["cadapp"] != "": + command = globalVars.desktop["cadapp"] + elif kind == "video" and globalVars.desktop["videoapp"] != "": + command = globalVars.desktop["videoapp"] + elif kind in ("office-document", "office-presentation", + "office-spreadsheet") and \ + globalVars.desktop["officeapp"] != "": + command = globalVars.desktop["officeapp"] + elif kind == "txt" and globalVars.desktop["txtapp"] != "": + command = globalVars.desktop["txtapp"] + elif kind == "rtf" and globalVars.desktop["rtfapp"] != "": + command = globalVars.desktop["rtfapp"] + # if no app is configured + elif _desktop == "macosx": + command = "open" + elif _desktop == "linux": + command = "xdg-open" else: - if kind == 'url': - command = globalVars.desktop["browser"] - elif kind == 'mail': - command = globalVars.desktop["mailapp"] - elif kind == 'image': - command = globalVars.desktop["imageapp"] - elif kind == 'dxf': - command = globalVars.desktop["cadapp"] - else: # if no app is configured - return + # if no desktop is detected + # try xdg-open and cross your fingers + command = "xdg-open" + command = build_command(command, uri) try: exec_command(command) diff -r 7bd4ca56607d -r 65e7ae0d0e63 Generic/utils.py --- a/Generic/utils.py Tue Sep 30 17:16:50 2014 +0200 +++ b/Generic/utils.py Thu May 02 16:31:17 2019 +0200 @@ -3,7 +3,7 @@ ## File utils.py ## This file is part of pyArq-Presupuestos. ## -## Copyright (C) 2010-2013 Miguel Ángel Bárcena Rodríguez +## Copyright (C) 2010-2019 Miguel Ángel Bárcena Rodríguez ## ## ## pyArq-Presupuestos is free software: you can redistribute it and/or modify @@ -22,6 +22,38 @@ # Modules import re import imghdr +import os.path + +# add svg to imghdr +def test_svg(h, f): + """SVG """ + if isinstance(f,file): + _pos = f.tell() + f.seek(0) + _h = f.read(32) + f.seek(-32, 2) + _l = f.read(32) + f.seek(_pos) + else: + _h = h + _l = h[-32:] + if "" in _l: + return 'svg' +imghdr.tests.append(test_svg) + +# add ico to imghdr +def test_ico(h, f): + """ico image file""" + if h[:4] == "\x00\x00\x01\x00": + return 'ico' +imghdr.tests.append(test_ico) + +# add wmf to imghdr +def test_pdf(h, f): + """pdf file""" + if h[:4] == "%PDF": + return 'pdf' +imghdr.tests.append(test_pdf) # add wmf to imghdr def test_wmf(h, f): @@ -57,18 +89,19 @@ imghdr.tests.append(test_dxf) -def mapping(string, tuple): +def mapping(string, tuple_strings): """mapping(string, tuple) string: a message string - tuple: a truple with string items + tuple_strings: a truple with string items Return the string replacing the $[n] words whith its corresponding value from the tuple. It is used because the gettext module can not #-#supotr#-# strings as: "Invalid type (%s) in record: %s" %(type, record) """ - for _index in range(len(tuple)): - string = string.replace("$" + str(_index+1), str(tuple[_index])) + for _index in range(len(tuple_strings)): + string = string.replace("$" + str(_index+1), tuple_strings[_index]) + #string = string.replace("$" + str(_index+1), str(tuple[_index])) return string def eliminate_duplicates(list): @@ -111,10 +144,9 @@ """ _is_valid = True if not isinstance(code, str): - print "Not a string, code:", code, type(code) + print("Not a string, code: " + code + type(code) ) return False, False if code == "": - return False, False try: _unicode_code = unicode(code, "utf8",'replace') @@ -123,28 +155,28 @@ _unicode_code = unicode(_code_cp850, "cp850",'replace') except UnicodeError: - print "Unicode Error, code:", code + print ("Unicode Error, code: " + code ) return False, False if _code_utf8 != code: - print "Not in cp950, code:", code + print ("Not in cp950, code: " + code ) _is_valid = False if _code_utf8 == "": return False, False code = _code_utf8 _code2 = re.sub("[\t \n\r~|\\\]","",code) if _code2 != code: - print "Control characters in code:", code + print("Control characters in code: " + code ) if _code2 == "": return False, False _is_valid = False code = _code2 if code[-1] == "#": - print "# in code:", code + print("# in code: " + code ) _is_valid = False while code[-1] == "#": code = code[:-1] if code == "": - print "Empty code" + print("Empty code") return False, False return _is_valid, code @@ -154,20 +186,48 @@ filename: the filename to test h: raw string, if h is not None the filename is ignored and h is assumed to contain the byte stream to test + + valid types: + "image", "wmf", "dxf", "pdf" , "video", + "office-document", "office-presentation", "office-spreadsheet", + "html", "rtf", "txt" """ + _ext = os.path.splitext(filename)[1][1:].lower() + + _video_types = ["avi", "mp4", "m4p", "m4v2", "m4v","amv", "mpg", "m2v", + "mp2", "mpe", "mpv", "mpeg", "ogg", "ogv", "webm", "mkv", + "ogm", "flv", "f4v", "f4p", "f4a", "f4b", "vob", "drc", + "mts", "m2ts", "mov", "qt", "wmv", "yuv", "rm", "rmvb", + "asf", "svi", "3gp", "3g2", "mxf", "roq", "nsv"] + _document_types = ["doc", "docx", "odt"] + _spreadsheet_types = ["xls", "xlsx", "ods"] + _presentation_types = ["pps", "ppsx", "ppt", "pptx", "odp"] + _html_types = ["html", "xhtml"] + if _ext in _video_types: + return "video" + elif _ext in _document_types: + return "office-document" + elif _ext in _spreadsheet_types: + return "office-spreadsheet" + elif _ext in _presentation_types: + return "office-presentation" + elif _ext in _html_types: + return "html" + elif _ext == "rtf": + return "rtf" + elif _ext == "txt": + return "txt" _type = imghdr.what(filename, h) - _image_types = ["rgb", "gif", "pbm", "pgm", "ppm", "tiff", "rast", "xbm", - "jpeg", "bmp", "png", "wmf"] - if _type in _image_types: + _image_types = ["rgb", "gif", "pbm", "pgm", "ppm" ,"tiff", "tif", "rast", + "xbm", "jpeg", "jpg", "bmp", "png", "webp", "exr", + "ico", "svg"] + if _type in _image_types and _ext in _image_types: return "image" - elif _type == "dxf": + elif _type == "wmf" and _ext == "wmf": + return "wmf" + elif _type == "dxf" and _ext == "dxf": return "dxf" -## _video_types = ["avi", "mpg", "mkv", "ogm"] -## elif _type in _video_types: -## return "video" -## elif _type == "pdf": -## return "pdf" -## elif _type == "ppt" or _type == "odp": -## return "presentation" - else: - return None + + elif _type == "pdf" and _ext == "pdf": + return "pdf" + return None diff -r 7bd4ca56607d -r 65e7ae0d0e63 Gtk/__init__.py --- a/Gtk/__init__.py Tue Sep 30 17:16:50 2014 +0200 +++ b/Gtk/__init__.py Thu May 02 16:31:17 2019 +0200 @@ -2,7 +2,7 @@ ## ## This file is part of pyArq-Presupuestos. ## -## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## Copyright (C) 2019 Miguel Ángel Bárcena Rodríguez ## ## ## pyArq-Presupuestos is free software: you can redistribute it and/or modify diff -r 7bd4ca56607d -r 65e7ae0d0e63 Gtk/gui.py --- a/Gtk/gui.py Tue Sep 30 17:16:50 2014 +0200 +++ b/Gtk/gui.py Thu May 02 16:31:17 2019 +0200 @@ -2,7 +2,7 @@ ## File gui.py ## This file is part of pyArq-Presupuestos. ## -## Copyright (C) 2010-2014 Miguel Ángel Bárcena Rodríguez +## Copyright (C) 2010-2019 Miguel Ángel Bárcena Rodríguez ## ## ## pyArq-Presupuestos is free software: you can redistribute it and/or modify @@ -26,9 +26,9 @@ Each budget or notebook page is showed by the Page class, this class contain the main widget showed in a page notebook. The main widget can show the budget information in several panes. -This panes are ordened in gtk.Paned represented for the class Paned which can -have 2 viewes represented for the View class or other gtk.Paned that have other -viewes or more gtk.Paned. +This panes are ordened in Gtk.Paned represented for the class Paned which can +have 2 viewes represented for the View class or other Gtk.Paned that have other +viewes or more Gtk.Paned. The view can have diferente type of widgets to show the budget information. The DecompositionList class show the decompositon list information of a record The Measure class show the measure information of a record @@ -42,44 +42,235 @@ """ # TODO: Config file +# Modules + +# python 2/3 compatibility +from __future__ import absolute_import, division, print_function, unicode_literals + # Standar Modules +import sys import os import time -import pygtk -pygtk.require('2.0') -import gtk -import gobject + +# gui +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk +from gi.repository import GdkPixbuf +from gi.repository import Gio +from gi.repository import GLib +from gi.repository import Gdk +from gi.repository import Pango + import weakref # pyArq-Presupuestos Modules from Gtk import importFiebdc from Generic import base from Generic import fiebdc -#from Generic import durusdatabase from Generic import utils from Generic import globalVars from Generic import openwith # Load default icon -if os.path.exists(globalVars.getAppPath("ICON")): - icon = gtk.gdk.pixbuf_new_from_file(globalVars.getAppPath("ICON")) - gtk.window_set_default_icon_list(icon) +_icons = [ "ICON16", "ICON32","ICON64","ICON128"] +_pixbufIcons = [] +for _icon in _icons: + if os.path.exists(globalVars.getAppPath(_icon)): + _pixbufIcon = GdkPixbuf.Pixbuf.new_from_file(globalVars.getAppPath(_icon)) + _pixbufIcons.append(_pixbufIcon) + else: + print(utils.mapping(_("The icon file does not exist. '$1'"), + (str(globalVars.getAppPath(_icon)),)) ) +if len(_pixbufIcons) > 0: + Gtk.Window.set_default_icon_list(_pixbufIcons) + else: - print utils.mapping(_("The icon file does not exist. '$1'"), - (globalVars.getAppPath("ICON"),)) + print(utils.mapping(_("The icon file does not exist. '$1'"), + (str(globalVars.getAppPath("ICON")),)) ) # Autodetect desktop if globalVars.desktop["autodetect"]: openwith.autodetect_desktop() - print utils.mapping(_("pyArq-Presupuestos running on $1"), - (globalVars.desktop["desktop"],)) - -# Add MenutoolButton to Uimanager -class MenuToolAction(gtk.Action): - __gtype_name__ = "MenuToolAction" - -gobject.type_register(MenuToolAction) -MenuToolAction.set_tool_item_type(gtk.MenuToolButton) + print(utils.mapping(_("pyArq-Presupuestos running on $1"), + (globalVars.desktop["desktop"],))) + + +class App(Gtk.Application): + """gui.App: + + Description: + This is the Gtk application base class. + Constructor: + App() + Ancestry: + +-- Gtk.Application https://lazka.github.io/pgi-docs/Gtk-3.0/classes/Application.html + +-- App + Atributes: + Methods: + do_activate + do_startup + do_open + """ + + def __init__(self, *args, **kwargs): + """__init__() + + Sets the application id and application_name. + """ + self.filesToOpen = [] + self._application_id = "es.obraencurso.pyarq.presupuestos" + super(App, self).__init__(application_id=self._application_id, + flags=Gio.ApplicationFlags.HANDLES_OPEN, + **kwargs) + GLib.set_prgname(self._application_id) + + def do_open(self, files, n_files, hint): + """do_open(files, n_files, hint) + + Set the filename list to open. + """ + self.filesToOpen = files + self.activate() + self.filesToOpen = [] + return 0 + + def do_activate(self): + """do_activate() + + Shows new appplication windows. + """ + _mainWindow = MainWindow(self, self.filesToOpen ) + _mainWindow.window.present_with_time(GLib.get_monotonic_time() / 1000) + + def do_startup(self): + """do_startup() + + Sets the app actions. + """ + Gtk.Application.do_startup(self) + # App Actions + action = Gio.SimpleAction.new("newWindow", None) + action.connect("activate", self._on_newWindow) + self.add_action(action) + + action = Gio.SimpleAction.new("acell_newWindow", None) + action.connect("activate", self._on_control_n) + self.add_action(action) + + action = Gio.SimpleAction.new("about", None) + action.connect("activate", self._on_about) + self.add_action(action) + + action = Gio.SimpleAction.new("quit", None) + action.connect("activate", self._on_quit) + self.add_action(action) + + action = Gio.SimpleAction.new("acell_quit", None) + action.connect("activate", self._on_control_q) + self.add_action(action) + + # App menu + _app_menu = Gio.Menu() + _section_window = Gio.Menu() + _section_window.append(_("_New window"), "app.newWindow") + _section_window.append(_("_Close window"), "win.CloseWindow") + _app_menu.append_section(None,_section_window) + self.set_accels_for_action('win.acell_close', ["x"]) + self.set_accels_for_action('app.acell_newWindow', ["n"]) + _section_general = Gio.Menu() + _section_general.append(_("About") + " " + globalVars.name, "app.about") + _app_menu.append_section(None,_section_general) + _section_quit = Gio.Menu() + _section_quit.append(_("_Quit application"), "app.quit") + self.set_accels_for_action('app.acell_quit', ["q"]) + _app_menu.append_section(None,_section_quit) + self.set_app_menu(_app_menu) + # TODO : from gui config + win_menu = False + # Win Menu + if win_menu: + _win_menu = Gio.Menu() + _win_submenu_file = Gio.Menu.new() + _import_fiebdc = Gio.MenuItem.new(_("_Import Fiebdc"), "win.ImportFiebdc") + _import_fiebdc.set_icon(Gio.Icon.new_for_string("document-open")) + _win_submenu_file.append_item(_import_fiebdc) + + _close_tab = Gio.MenuItem.new(_("_Close tab"), "win.CloseTab") + _close_tab.set_icon(Gio.Icon.new_for_string("window-close")) + _win_submenu_file.append_item(_close_tab) + + _win_menu.append_submenu(_("_File"), _win_submenu_file) + _win_submenu_go = Gio.Menu.new() + _back = Gio.MenuItem.new(_("_Back"), "win.GoPrevious") + _back.set_icon(Gio.Icon.new_for_string("go-previous")) + _win_submenu_go.append_item(_back) + _forward = Gio.MenuItem.new(_("_Forward"), "win.GoPosterior") + _forward.set_icon(Gio.Icon.new_for_string("go-next")) + _win_submenu_go.append_item(_forward) + _up = Gio.MenuItem.new(_("_Up Item"), "win.GoUp") + _up.set_icon(Gio.Icon.new_for_string("go-up")) + _win_submenu_go.append_item(_up) + _root = Gio.MenuItem.new(_("_Root"), "win.GoToRoot") + _root.set_icon(Gio.Icon.new_for_string("go-top")) + _win_submenu_go.append_item(_root) + _win_menu.append_submenu(_("_Go"), _win_submenu_go) + self.set_menubar(_win_menu) + + def _on_newWindow(self, action, param): + """on_newWindow(action, param) + + Shows new appplication windows. + """ + _mainWindow = MainWindow(self, []) + _mainWindow.window.present_with_time(GLib.get_monotonic_time() / 1000) + + def _on_about(self, action, param): + """_on_about(action, param) + + Shows About dialog. + """ + _aboutDialog = Gtk.AboutDialog(modal=False) + _aboutDialog.set_program_name(globalVars.name) + _aboutDialog.set_copyright(base.copyright) + _aboutDialog.set_authors(base.authors) + _aboutDialog.set_version(globalVars.version + globalVars.changeset) + _aboutDialog.set_website(base.website) + _aboutDialog.set_website_label(base.website_label) + _aboutDialog.set_license_type(Gtk.License(3)) + _aboutDialog.set_comments(base.comments) + _aboutDialog.connect("response", self._on_close_aboutdialog) + _aboutDialog.present_with_time(GLib.get_monotonic_time() / 1000) + + def _on_close_aboutdialog(self, action, parameter): + """on_close_aboutdialog(action, param) + + Close About dialog. + """ + action.destroy() + + def _on_control_q(self, action, param): + """on_control_q(action, param) + + Quit app. + """ + print("Control q -> Quit app") + self.quit() + + def _on_quit(self, action, param): + """_on_quit(action, param) + + Quit app. + """ + self.quit() + + def _on_control_n(self, action, param): + """on_control_n(action, param) + + Shows new appplication windows. + """ + print("Control n -> New window") + self._on_newWindow(action, param) class MainWindow(object): @@ -89,11 +280,12 @@ Creates and shows the main window. This is the interface base class. Constructor: - gui.MainWindow() + MainWindow(app, files) Ancestry: +-- object +-- MainWindow Atributes: + self.window: Gtk.ApplicationWindow object Methods: changeHistorySignal changeActiveSignal @@ -104,138 +296,178 @@ # TODO:* Can choose open budget in new window # TODO:* Can choose show more than one notebook in the same window or # TODO: can show basedata notebook in a side pane - __ui = ''' - - - - - - - - - - - - - - - - - - - - - - - - ''' - - # - # - # - # - - def __init__(self): - """__init__() + + def __init__(self, app, files): + """__init__(app, files) Initialize the atributes self.__page_list without data. Creates the widgets "window" and "__notebook". - self.__window: gtk.Window object - self.__uimanager: gtk.UIManager object + app: Gtk.Application instance + files: Gio.file list from command line + + self.window: Gtk.ApplicationWindow object self.__page_list: List of pages ("Page" object) - self.__notebook: Notebook widget ("gtk.Notebook" object) + self.__notebook: Notebook widget ("Gtk.Notebook" object) self.__general_action_group: "General" action group self.__navigation_action_group: "Navigation" action group + self.__navigation_is_enabled: True/False + self.__goBack_button """ self.__page_list = [] # Main window - self.__window = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.__window.set_default_size(771, 570) - self.__window.set_title("Presupuestos") - self.__window.set_border_width(0) - self.__window.connect("destroy", self._destroy) - self.__window.connect("delete_event", self._delete_event) - # Vertical box - _vbox1 = gtk.VBox(False, 0) - self.__window.add(_vbox1) + self.window = Gtk.ApplicationWindow(application=app) + self.window.set_default_size(771, 570) + self.window.set_title("Presupuestos") + self.window.set_border_width(5) + self.window.connect("delete_event", self._delete_event) + # HeaderBar + _hb = Gtk.HeaderBar() + _hb.set_show_close_button(True) + _hb.props.title = "Presupuestos" + self.window.set_titlebar(_hb) + _hb.show() + # Actions + # General Actions + self.__general_action_group = Gio.SimpleActionGroup.new() + # CloseWindow Action + _action = Gio.SimpleAction.new("CloseWindow", None) + _action.connect("activate", self._menuitemClose) + self.window.add_action(_action) + self.__general_action_group.insert(_action) + # CloseWindow from acell Action + _action = Gio.SimpleAction.new("acell_close", None) + _action.connect("activate", self._on_control_x) + self.window.add_action(_action) + self.__general_action_group.insert(_action) + # ImportFiebdc Action + _action = Gio.SimpleAction.new("ImportFiebdc", None) + _action.connect("activate", self._on_menuitemImportFiebdc) + self.window.add_action(_action) + self.__general_action_group.insert(_action) + # CloseTab action + self.__closeTab_action = Gio.SimpleAction.new("CloseTab", None) + self.__closeTab_action.connect("activate", self._on_CloseTab) + self.window.add_action(self.__closeTab_action) + self.__general_action_group.insert(self.__closeTab_action) + # Navigation Actions + self.__navigation_is_enabled = False + self.__navigation_action_group = Gio.SimpleActionGroup.new() + # Go Previous action + self.__GoPrevious_action = Gio.SimpleAction.new("GoPrevious", None) + self.__GoPrevious_action.connect("activate", self._menuitemGoPrevious) + self.window.add_action(self.__GoPrevious_action) + self.__general_action_group.insert(self.__GoPrevious_action) + self.__GoPrevious_action.set_enabled(False) + # Go posterior action + self.__GoPosterior_action = Gio.SimpleAction.new("GoPosterior", None) + self.__GoPosterior_action.connect("activate", self._menuitemGoPosterior) + self.window.add_action(self.__GoPosterior_action) + self.__general_action_group.insert(self.__GoPosterior_action) + self.__GoPosterior_action.set_enabled(False) + # Go Up action + self.__GoUp_action = Gio.SimpleAction.new("GoUp", None) + self.__GoUp_action.connect("activate", self._menuitemGoUp) + self.window.add_action(self.__GoUp_action) + self.__general_action_group.insert(self.__GoUp_action) + self.__GoUp_action.set_enabled(False) + # Go to Root action + self.__GoToRoot_action = Gio.SimpleAction.new("GoToRoot", None) + self.__GoToRoot_action.connect("activate", self._menuitemGoToRoot) + self.window.add_action(self.__GoToRoot_action) + self.__general_action_group.insert(self.__GoToRoot_action) + self.__GoToRoot_action.set_enabled(False) + # Vertical Grid + _vbox1 = Gtk.Grid() + _vbox1.set_orientation(Gtk.Orientation(1)) # 1 Vertical + self.window.add(_vbox1) _vbox1.show() - #Uimanager - self.__uimanager = gtk.UIManager() - _accelgroup = self.__uimanager.get_accel_group() - self.__window.add_accel_group(_accelgroup) - self.__general_action_group = gtk.ActionGroup("General") - self.__general_action_group.add_actions( - [("File", None, _("_File"), None), - ("ImportFiebdc", gtk.STOCK_OPEN, _('_Import Fiebdc'), "", - _('Import FIEBDC'), self._menuitemImportFiebdc), - ("Close", gtk.STOCK_CLOSE, _("_Close"), None, _('Close'), - self._menuitemClose), - ("View", None, _("_View")), - ("Go", None, _("_Go")), - ("Test", None, _("_Test")), - #('ImportFiebdcPriceDatabase', gtk.STOCK_OPEN, - # _("Import Fiebdc _price database"), "", _("Import database"), - # self._menuitemImportPriceDatabase ), - #("OpenPriceDatabase", gtk.STOCK_OPEN, _('_Open price database'), - # "", _('Open Database'), self._menuitemOpenPriceDatabase), - ]) - self.__navigation_action_group = gtk.ActionGroup("Navigation") - self.__navigation_action_group.add_actions( - [("Go", None, _("_Go")), - ("GoPrevious", gtk.STOCK_GO_BACK, _("_Back"),"", - _("Go to the previous visited item"), - self._menuitemGoPrevious), - ("GoPosterior", gtk.STOCK_GO_FORWARD, _("_Forward"),"", - _("Go to the next visited item"), self._menuitemGoPosterior), - ("GoUp", gtk.STOCK_GO_UP, _("_Up Item"),"", - _("Go up item"), self._menuitemGoUp), - ("GoToRoot", gtk.STOCK_GOTO_TOP, _("_Root"),"", - _("Go to root"), self._menuitemGoToRoot), - ]) - self.__navigation_action_group.add_action( - MenuToolAction("GoPrevMenu", None , - _("Go to the previous visited item"), - gtk.STOCK_GO_BACK)) - self.__navigation_action_group.add_action( - MenuToolAction("GoPostMenu", None , - _("Go to the next visited item"), - gtk.STOCK_GO_FORWARD)) - self.__navigation_action_group.set_sensitive(False) - self.__navigation_action_group.get_action("GoPostMenu").set_sensitive( - False) - self.__navigation_action_group.get_action("GoPrevMenu").set_sensitive( - False) - self.__uimanager.insert_action_group(self.__general_action_group, 0) - self.__uimanager.insert_action_group(self.__navigation_action_group, 1) - self.__uimanager.add_ui_from_string(self.__ui) - _menu_bar = self.__uimanager.get_widget("/MenuBar") - _vbox1.pack_start(_menu_bar, False, False, 0) - _toolbar = self.__uimanager.get_widget("/ToolBar") - _toolbar.get_settings().set_long_property("gtk-toolbar-icon-size", - gtk.ICON_SIZE_SMALL_TOOLBAR, "pyArq-Presupuestos:toolbar") - _vbox1.pack_start(_toolbar, False, False, 0) - # menuToolButton go prev - _go_prev_button = self.__uimanager.get_widget( - "/ToolBar/GoPrevMenu") - _go_prev_button.set_arrow_tooltip_text(_("Back history")) - _go_prev_button.connect('clicked', self._menuitemGoPrevious) - # menuToolButton go pos - _go_post_button = self.__uimanager.get_widget( - "/ToolBar/GoPostMenu") - _go_post_button.set_arrow_tooltip_text(_("Forward history")) - _go_post_button.connect('clicked', self._menuitemGoPosterior) + # Toolbar + _toolbar = Gtk.Toolbar() + _toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR) + # Import Fiebdc + _gtk_image = Gtk.Image.new_from_icon_name("document-open",1) + _gtk_image.show() + _ImportFiebdc_button = Gtk.ToolButton.new(_gtk_image , _("Import Fiebdc")) + _ImportFiebdc_button.set_tooltip_text(_("Import Fiebdc")) + _ImportFiebdc_button.set_is_important(False) # label not shown + _toolbar.insert(_ImportFiebdc_button, -1) + _ImportFiebdc_button.show() + _ImportFiebdc_button.set_action_name("win.ImportFiebdc") + # Close tab + _gtk_image = Gtk.Image.new_from_icon_name("window-close",1) + _gtk_image.show() + _closeTabButton = Gtk.ToolButton.new(_gtk_image , _("_Close tab")) + _closeTabButton.set_tooltip_text(_("Close tab")) + _closeTabButton.set_is_important(False) # label not shown + _toolbar.insert(_closeTabButton, -1) + _closeTabButton.show() + _closeTabButton.set_action_name("win.CloseTab") + # Separator item + _separator = Gtk.SeparatorToolItem() + _separator.show() + _toolbar.insert(_separator, -1) + # Go Back + _gtk_image = Gtk.Image.new_from_icon_name("go-previous",1) + _gtk_image.show() + self.__goBack_button = Gtk.MenuToolButton.new(_gtk_image ,_("Back")) + self.__goBack_button.set_tooltip_text(_("Back")) + self.__goBack_button.set_is_important(False) # label not shown + _toolbar.insert(self.__goBack_button, -1) + self.__goBack_button.show() + self.__goBack_button.set_action_name("win.GoPrevious") + # Go Forward + _gtk_image = Gtk.Image.new_from_icon_name("go-next",1) + _gtk_image.show() + self.__goForward_button = Gtk.MenuToolButton.new(_gtk_image ,_("Forward")) + self.__goForward_button.set_tooltip_text(_("Forward")) + self.__goForward_button.set_is_important(False) # label not shown + _toolbar.insert(self.__goForward_button, -1) + self.__goForward_button.show() + self.__goForward_button.set_action_name("win.GoPosterior") + # Go Up Item + _gtk_image = Gtk.Image.new_from_icon_name("go-up",1) + _gtk_image.show() + _goUP_button = Gtk.ToolButton.new(_gtk_image ,_("Up Item")) + _goUP_button.set_tooltip_text(_("Up Item")) + _goUP_button.set_is_important(False) # label not shown + _toolbar.insert(_goUP_button, -1) + _goUP_button.show() + _goUP_button.set_action_name("win.GoUp") + # Go Root Item + _gtk_image = Gtk.Image.new_from_icon_name("go-top",1) + _gtk_image.show() + _goRoot_button = Gtk.ToolButton.new(_gtk_image ,_("Root")) + _goRoot_button.set_tooltip_text(_("Root")) + _goRoot_button.set_is_important(False) # label not shown + _toolbar.insert(_goRoot_button, -1) + _goRoot_button.show() + _goRoot_button.set_action_name("win.GoToRoot") + # Pack and show + _toolbar.set_hexpand(True) # with extra horizontal space + _toolbar.show() + _vbox1.add(_toolbar) # Notebook - self.__notebook = gtk.Notebook() - _vbox1.pack_start(self.__notebook, True, True, 0) - self.__notebook.set_tab_pos(gtk.POS_TOP) + self.__notebook = Gtk.Notebook() + _vbox1.add(self.__notebook) + self.__notebook.set_tab_pos(Gtk.PositionType(2)) # Up + self.__notebook.set_property("expand", True) # widget expand all space self.__notebook.set_show_tabs(True) self.__notebook.set_show_border(True) self.__notebook.set_scrollable(True) self.__notebook.connect("switch-page", self._switch_page) self.__notebook.show() self._main() - #TODO: create budget object in mainwindow? + if len(files) > 0: + for file in files: + _budget = base.Budget() + _budget_file = fiebdc.Read() + _read_method = _budget_file.readFile + _filename = file.get_path() + _filetype = "budget" + _exit_method = _budget_file.cancel + _file_window = FileSelectionWindow(self, + _read_method, _budget, _filename, _exit_method, _filetype) def changeHistorySignal(self): """changeHistorySignal() @@ -260,78 +492,84 @@ page_num: page number in notebook - Check and if necessary update the sensitive state of the navigation + Check and if necessary update the enabled state of the navigation buttons. """ _page = self.__page_list[page_num] if isinstance(_page, Page) and \ - self.__navigation_action_group.get_sensitive(): + self.__navigation_is_enabled: # GoToRoot and GoUp actions - _goto_root = self.__navigation_action_group.get_action("GoToRoot") - _go_up = self.__navigation_action_group.get_action("GoUp") + _goto_root = self.__GoToRoot_action + _go_up = self.__GoUp_action if len(_page.activePathRecord) == 1 and \ - _goto_root.get_sensitive(): - _goto_root.set_sensitive(False) - _go_up.set_sensitive(False) + _goto_root.get_enabled(): + _goto_root.set_enabled(False) + _go_up.set_enabled(False) elif len(_page.activePathRecord) != 1 and \ - not _goto_root.get_sensitive(): - _goto_root.set_sensitive(True) - _go_up.set_sensitive(True) + not _goto_root.get_enabled(): + _goto_root.set_enabled(True) + _go_up.set_enabled(True) # GoPrevMenu action - _go_Previous = self.__navigation_action_group.get_action( - "GoPrevious") - _go_prev = self.__navigation_action_group.get_action("GoPrevMenu") + _go_Previous = self.__GoPrevious_action + _go_prev = self.__GoPrevious_action if _page.previousPathRecord is None: - if _go_prev.get_sensitive(): - _go_prev.set_sensitive(False) - _go_Previous .set_sensitive(False) + if _go_prev.get_enabled(): + _go_prev.set_enabled(False) + self.__goBack_button.props.menu = None else: - if not _go_prev.get_sensitive(): - _go_prev.set_sensitive(True) - _go_Previous.set_sensitive(True) + if not _go_prev.get_enabled(): + _go_prev.set_enabled(True) + self.__goBack_button.set_menu(_page.back_menu) # GoPostMenu action - _go_Posterior = self.__navigation_action_group.get_action( - "GoPosterior") - _go_post = self.__navigation_action_group.get_action("GoPostMenu") + _go_Posterior = self.__GoPosterior_action if _page.posteriorPathRecord is None: - if _go_post.get_sensitive(): - _go_post.set_sensitive(False) - _go_Posterior.set_sensitive(False) + if _go_Posterior.get_enabled(): + _go_Posterior.set_enabled(False) + self.__goForward_button.props.menu = None else: - if not _go_post.get_sensitive(): - _go_post.set_sensitive(True) - _go_Posterior.set_sensitive(True) + if not _go_Posterior.get_enabled(): + _go_Posterior.set_enabled(True) + self.__goForward_button.set_menu(_page.forward_menu) + + def _disable_navigation(self): + self.__GoPrevious_action.set_enabled(False) + self.__GoPosterior_action.set_enabled(False) + self.__GoUp_action.set_enabled(False) + self.__GoToRoot_action.set_enabled(False) + self.__navigation_is_enabled = False def _switch_page(self, notebook, page, page_num,): """_switch_page(notebook, page, page_num) Method connected to the "switch-page" signal of the notebook widget - It changes the sensitive state of the navigation action group - """ + It shows/hides closeTabButton + and changes the sensitive state of the navigation action group + """ + for _page_num, _page in enumerate(self.__page_list): + if _page_num == page_num: + _page.closeTabButton.show() + else: + _page.closeTabButton.hide() _page = self.__page_list[page_num] + if isinstance(_page, EmptyPage) and \ - self.__navigation_action_group.get_sensitive(): - self.__navigation_action_group.set_sensitive(False) + self.__navigation_is_enabled: + self._disable_navigation() elif isinstance(_page, Page): - if not self.__navigation_action_group.get_sensitive(): - self.__navigation_action_group.set_sensitive(True) - self._checkButtonsSensitive(page_num) - _go_prev = self.__uimanager.get_widget("/ToolBar/GoPrevMenu") - _go_prev.set_menu(_page.back_menu) - _go_post = self.__uimanager.get_widget("/ToolBar/GoPostMenu") - _go_post.set_menu(_page.forward_menu) + if not self.__navigation_is_enabled: + self.__navigation_is_enabled = True + self._checkButtonsSensitive(page_num) def _main(self): """main() - Shows window and starts the GTK+ event processing loop. - """ - self.__window.show() - gtk.main() + Shows window. + """ + self.window.show() def appendEmptyPage(self, emptyPage): - """appendEmptyPage(widget, label) + """appendEmptyPage(emptyPage) Append a empty page to the notebook. """ @@ -349,18 +587,19 @@ _page_num = self.__notebook.page_num(empty_page.widget) self.__page_list[_page_num] = page if self.__notebook.get_current_page() == _page_num: - _go_prev = self.__uimanager.get_widget("/ToolBar/GoPrevMenu") - _go_prev.set_menu(page.back_menu) - _go_post = self.__uimanager.get_widget("/ToolBar/GoPostMenu") - _go_post.set_menu(page.forward_menu) - if not self.__navigation_action_group.get_sensitive(): - self.__navigation_action_group.set_sensitive(True) + if not self.__navigation_is_enabled: + self.__navigation_is_enabled = True self._checkButtonsSensitive(_page_num) - def _menuitemImportFiebdc(self, widget): - """_menuitemImportFiebdc(widget) - - widget: the widget where the event is emitted from + def _on_control_x(self, action, param): + print("Control x -> Close window") + self.window.destroy() + + def _on_menuitemImportFiebdc(self, action, parameter): + """_on_menuitemImportFiebdc(action, parameter) + + action: the action where the event is emitted from + parameter: None Callback to open a budget file. Creates and shows a file selection window to open a budget file. @@ -368,61 +607,33 @@ _budget = base.Budget() _budget_file = fiebdc.Read() _read_method = _budget_file.readFile - _filename = "file" + _filename = "" _filetype = "budget" _exit_method = _budget_file.cancel - _file_window = importFiebdc.FileSelectionWindow(self, + _file_window = FileSelectionWindow(self, _read_method, _budget, _filename, _exit_method, _filetype) - #def _menuitemImportPriceDatabase(self, widget): - # """_menuitemImportPriceDatabase(widget) - # - # widget: the widget where the event is emitted from - # Callback to open a price database file. - # - # Creates and shows a file selection window to open a price database - # file. - # """ - # _budget = base.Budget() - # _budget_file = fiebdc.Read() - # _read_method = _budget_file.readFile - # _filename = "file" - # _filetype = "database" - # _exit_method = _budget_file.cancel - # _file_window = importFiebdc.FileSelectionWindow(self, - # _read_method, _budget, _filename, _exit_method, _filetype) - - #def _menuitemOpenPriceDatabase(self, widget): - # """_menuitemOpenPriceDatabase(widget) - # - # widget: the widget where the event is emitted from - # Callback to open a price database from a durus file. - # - # Creates and shows a file selection window to open a durus database - # """ - # _budget = None - # _budget_file = durusdatabase.Read() - # _read_method = _budget_file.readFile - # _filename = "file" - # _filetype = "durus" - # _exit_method = _budget_file.cancel - # _file_window = importFiebdc.FileSelectionWindow(self, - # _read_method, _budget, _filename, _exit_method, _filetype) - - def _menuitemClose(self, widget): - """_menuitemClose(widget) - - widget: the widget where the event is emitted from - - Callback to close a budget file. + def _menuitemClose(self, action, parameter): + """_menuitemClose(action, parameter) + + action: the action where the event is emitted from + parameter: None + + Callback to close the main window. + """ + self.window.destroy() + + def _on_CloseTab(self, action, parameter): + """_on_CloseTab(action, parameter) + + action: the action where the event is emitted from + parameter: None + + Callback to close tab. """ _page_num = self.__notebook.get_current_page() if _page_num != -1: _page = self.__page_list[_page_num] - #if isinstance(_page, EmptyPage) and _page.filetype == "durus": - # print _("Cancel reading Durus database has not been " - # "implemented.") - #else: _page.close() def closePage(self, page): @@ -439,15 +650,15 @@ page.clear() self.__notebook.remove_page(_page_num) if len(self.__page_list) == 0: - self.__navigation_action_group.set_sensitive(False) + self._disable_navigation() else: - raise IndexError, _("The page is not in the page list") - - - def _menuitemGoToRoot(self, widget): - """_menuitemGoToRoot(widget) - - widget: the widget where the event is emitted from + raise IndexError( _("The page is not in the page list") ) + + def _menuitemGoToRoot(self, action, parameter): + """_menuitemGoToRoot(action, parameter) + + action: the action where the event is emitted from + parameter: None Callback to go to root record. """ @@ -456,13 +667,14 @@ return _page = self.__page_list[_page_num] if isinstance(_page, Page): - #not loading budget + # not loading budget _page.propagateMessageFrom("change_active", (-1,), (0,)) - def _menuitemGoUp(self, widget): - """_menuitemGoUp(widget) - - widget: the widget where the event is emitted from + def _menuitemGoUp(self, action, parameter): + """_menuitemGoUp(action, parameter) + + action: the action where the event is emitted from + parameter: None Callback to go to up record. """ @@ -470,7 +682,7 @@ if _page_num != -1: _page = self.__page_list[_page_num] if isinstance(_page, Page): - #not loading budget + # not loading budget _active_path = _page.activePathRecord if len(_active_path) > 1: _budget = _page.budget @@ -479,10 +691,11 @@ _page.propagateMessageFrom("change_active", (-1,), _up_path) - def _menuitemGoPrevious(self, widget): - """_menuitemGoPrevious(widget) - - widget: the widget where the event is emitted from + def _menuitemGoPrevious(self, action, parameter): + """_menuitemGoPrevious(action, parameter) + + action: the action where the event is emitted from + parameter: None Callback to go to previous record. """ @@ -490,7 +703,7 @@ if _page_num != -1: _page = self.__page_list[_page_num] if isinstance(_page, Page): - #not loading budget + # not loading budget _previous_path = _page.previousPathRecord if _previous_path is not None: _budget = _page.budget @@ -498,10 +711,11 @@ _page.propagateMessageFrom("change_active", (-1,), _previous_path) - def _menuitemGoPosterior(self, widget): - """_menuitemPosterior(widget) - - widget: the widget where the event is emitted from + def _menuitemGoPosterior(self, action, parameter): + """_menuitemPosterior(action, parameter) + + action: the action where the event is emitted from + parameter: None Callback to go to posterior record. """ @@ -509,7 +723,7 @@ if _page_num != -1: _page = self.__page_list[_page_num] if isinstance(_page, Page): - #not loading budget + # not loading budget _posterior_path = _page.posteriorPathRecord if _posterior_path is not None: _budget = _page.budget @@ -521,7 +735,7 @@ """_delete_event(widget, event) widget: the widget where the event is emitted from - event: the "gtk.gdk.Event" + event: the "Gdk.Event" Method connected to "delete_event" signal of main window widget This signal is emitted when a user press the close titlebar button. @@ -531,18 +745,97 @@ _page.clear() return False # -> destroy - def _destroy(self, widget): - """_destroy(widget) - - widget: the widget where the event is emitted from - Method connected to "destroy" signal of main window widget - - This signal is emited when the method connected to "delete_event" - signal returns True or when the program call the destroy() method of - the gtk.Window widget. - The window is closed and the GTK+ event processing loop is ended. - """ - gtk.main_quit() + +class FileSelectionWindow(object): + """gui.FileSelectionWindow: + + Description: + Class to show the selection file window + Constructor: + FileSelectionWindow(mainWindow, readFileMethod, budget, + filename, cancelMethod, filetype) + Ancestry: + +-- object + +-- FileSelectionWindow + Atributes: + No public Atributes + Methods: + No public Methods + """ + + def __init__(self, mainWindow, readFileMethod, budget, filename, + cancelMethod, filetype): + """__init__(mainWindow, readFileMethod, budget, + filename, cancelMethod, filetype) + + mainWindow: MainWindow object + readFileMethod: Method to read the selected file + budget: base.Budget object + filename: "file" + cancelMethod: Method to cancel the read method + fileytpe: "budget" or "database". + Sets the init atributes, creates the file selection window + Connects the events: + * clicked ok button: _openFile + * clicked cancel button: destroy window + * destroy event: _destroy + """ + # TODO: Add file filter + self.__mainWindow = mainWindow + self.__readFileMethod = readFileMethod + self.__budget = budget + self.__filetype = filetype + self.__cancelMethod = cancelMethod + self.__file = None + self.__filename = filename + if self.__filename == "": + self.__dialog = Gtk.FileChooserNative.new(_("Open File"), + mainWindow.window, Gtk.FileChooserAction.OPEN, _("Open File"), + _("Cancel") ) + self.__dialog.set_current_folder(globalVars.getHomePath("BUDGET")) + _response = self.__dialog.run() + if _response in [ Gtk.ResponseType.OK, Gtk.ResponseType.ACCEPT, + Gtk.ResponseType.YES, Gtk.ResponseType.APPLY]: + self._openFile(self.__dialog.get_filename()) + elif _response == Gtk.ResponseType.CANCEL: + self.__dialog.destroy() + else: + self.__dialog = None + self._openFile(self.__filename) + + def _launchProgressWindow(self, file): + """_launchProgressWindow(file) + + Launch the progress window + """ + self.__filename = file + _emptyPage = EmptyPage(self.__mainWindow, self.__readFileMethod, + self.__budget, self.__filename, + self.__cancelMethod, self.__filetype) + self.__mainWindow.appendEmptyPage(_emptyPage) + _emptyPage.run() + + def _openFile(self, filename): + """_openFile(filename) + + filename: the filename to open + If the selected file has a bc3 extension + _launchProgressWindow is called + """ + _file = filename + if sys.getfilesystemencoding(): + _file = _file.decode(sys.getfilesystemencoding()) + self.__file = _file + _filename = os.path.basename(self.__file) + _filename_ext = _filename.split(".")[-1] + if (self.__filetype == "budget" or self.__filetype == "database") and \ + _filename_ext != "bc3" and _filename_ext != "BC3": + print(_("The file must have 'bc3' extension") ) + else: + if self.__dialog is not None: + self.__dialog.destroy() + # TODO: the file exits? is it not binary?, can it be readed? + self._launchProgressWindow(self.__file) class EmptyPage(object): @@ -552,21 +845,22 @@ It creates and shows a page in the notebook while a budget is loaded. The page show the pyarq logo, loading time and a progress bar. Constructor: - gui.EmptyPage(mainWindow, readFileMethod, budget, filename, + EmptyPage(mainWindow, readFileMethod, budget, filename, cancelMethod, filetype): - mainWindow: gui.Mainwindow object + mainWindow: Mainwindow object readFileMethod: Method to read the selected file budget: base.Budget object filename: "file" cancelMethod: Method to cancel the read method - filetype: "budget", "database" or "durus" + filetype: "budget", "database" Ancestry: +-- object +-- EmptyPage Atributes: widget: Read. Main widget showed in the pane title: Read. Page Title - filetype: Read. budget, basedata or durus + filetype: Read. budget or basedata + endSuccessfully: Read-Write. False/True Methods: run readFile_progress @@ -575,8 +869,10 @@ readFile_end readFile_cancel stopLoading + updateGui threadFinishedSignal threadCanceled + on_close_button close clear """ @@ -586,34 +882,34 @@ """__init__(mainWindow, readFileMethod, budget, filename, cancelMethod, filetype) - mainWindow: gui.Mainwindow object + mainWindow: Mainwindow object readFileMethod: Method to read the selected file budget: base.Budget object filename: "file" cancelMethod: Method to cancel the read method - filetype: "budget", "database" or "durus" - - self.__mainWindow: gui.Mainwindow object + filetype: "budget" or "database" + + self.__mainWindow: Mainwindow object + self.endSuccessfully False/True self.__readFileMethod: Method to read the selected file self.__budget: base.Budget object self.__filename: "file" self.__cancelMethod: Method to cancel the read method - self.__filetype: "budget", "database" or "durus" + self.__filetype: "budget" or "database" self.__children: the read thread self.__progress: 0 to 1 progress self.__statistics: record statistics - self.__widget: main widget, a gtk.VBox object + self.__widget: main widget, a vertial Gtk.Grid object self.__main_item: None - self.__throbber: a gtk.Image - self.__animationThobber: a gtk.gdk.PixbufAnimation - self.__quietThobber: a pixbuf - self.__budget_icon: a gtk.gdk.pixbuf - self.__title: a gtk.HBox - self.__statusbar: a gtk.Statusbar + self.__throbber: Gtk.Spinner() + self.__budget_icon: Gtk.Image() + self.__title: a horizontal Gtk.Grid + self.__statusbar: a Gtk.Statusbar self.__statuscontext: the statusbar context - self.__progress_bar: a gtk.ProgressBar + self.__progress_bar: a Gtk.ProgressBar """ self.__mainWindow = mainWindow + self.endSuccessfully = False self.__readFileMethod = readFileMethod self.__budget = budget self.__filename = filename @@ -623,51 +919,68 @@ self.__cancel = [False, False] self.__progress = 0.0 self.__statistics = None - self.__widget = gtk.VBox() + self.__widget = Gtk.Grid() + self.__widget.set_orientation(Gtk.Orientation(1)) # 1 Vertical self.__main_item = None self.__widget.show() - self.__throbber = gtk.Image() - self.__throbber.set_from_file(globalVars.getAppPath("THROBBER-ICON")) + # Throbber + self.__throbber = Gtk.Spinner() self.__throbber.show() - self.__animationThobber = gtk.gdk.PixbufAnimation( - globalVars.getAppPath("THROBBER-GIF")) - self.__quietThobber = self.__throbber.get_pixbuf() - self.__budget_icon = gtk.gdk.pixbuf_new_from_file( + self.__budget_icon = Gtk.Image() + _budget_pixbuf = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("BUDGET-ICON")) + self.__budget_icon.set_from_pixbuf(_budget_pixbuf) _filename = os.path.basename(filename) _rootfilename = os.path.splitext(_filename)[0] if not _rootfilename == "": _filename = _rootfilename - _titleLabel = gtk.Label(_filename) + if len(_filename) > 28: + _titleLabel = Gtk.Label(_filename[:25] + "...") + _titleLabel.set_tooltip_text(_filename) + else: + _titleLabel = Gtk.Label(_filename) _titleLabel.show() - self.__title = gtk.HBox() + self.__title = Gtk.Grid() + self.__title.set_column_spacing(4) + self.__title.set_orientation(Gtk.Orientation(0)) # 0 Horizontal + self.__title.add(self.__budget_icon) self.__title.add(self.__throbber) self.__title.add(_titleLabel) - self.__statusbar = gtk.Statusbar() + # Close tab + _gtk_image = Gtk.Image() + _gtk__pixbuf = Gtk.IconTheme.get_default().load_icon( + "window-close-symbolic", 16, 0) + _gtk_image.set_from_pixbuf(_gtk__pixbuf) + _gtk_image.show() + self.closeTabButton = Gtk.ToolButton.new(_gtk_image , _("_Close tab")) + self.closeTabButton.set_tooltip_text(_("Close tab")) + self.closeTabButton.set_is_important(False) # label not shown + self.__title.add(self.closeTabButton) + self.closeTabButton.hide() + self.__closeTabId = self.closeTabButton.connect("clicked", self.on_close_button) + # Statusbar + self.__statusbar = Gtk.Statusbar() self.__statuscontext = self.__statusbar.get_context_id("Statusbar") self.__statusbar.show() - _align = gtk.Alignment(0.5, 0.5, 0, 0) - _iconVbox = gtk.VBox() - _pyArqIcon = gtk.Image() + _iconVbox = Gtk.Grid() + _iconVbox.set_orientation(Gtk.Orientation(1)) # 1 Vertical + _iconVbox.props.halign = Gtk.Align(3) # 3 Center + _iconVbox.props.valign = Gtk.Align(3) # 3 Center + _iconVbox.set_property("expand", True) # widget expand all space + _pyArqIcon = Gtk.Image() _pyArqIcon.set_from_file(globalVars.getAppPath("PYARQ-ICON")) _pyArqIcon.show() - _iconVbox.pack_start(_pyArqIcon, True, True, 0) - _link = gtk.LinkButton("http://pyarq.obraencurso.es", - "http://pyarq.obraencurso.es") - _iconVbox.pack_start(_link, True, True, 0) + _iconVbox.add(_pyArqIcon) + _link = Gtk.LinkButton.new("http://pyarq.obraencurso.es") + _iconVbox.add(_link) _link.show() _iconVbox.show() - _align.add(_iconVbox) - _align.show() - self.__widget.pack_start(_align, True, True, 0) - _progressframe = gtk.Frame() - _progressframe.set_shadow_type(gtk.SHADOW_IN) - _progressframe.show() - self.__progress_bar = gtk.ProgressBar() + self.__widget.add(_iconVbox) + self.__progress_bar = Gtk.ProgressBar() + self.__progress_bar.set_show_text(True) self.__progress_bar.show() - _progressframe.add(self.__progress_bar) - self.__statusbar.pack_start(_progressframe, False, False, 0) - self.__widget.pack_end(self.__statusbar, False, True, 0) + self.__statusbar.pack_start(self.__progress_bar, False, False, 0) + self.__widget.add(self.__statusbar) self.__main_item = None def run(self): @@ -676,7 +989,7 @@ Launch clildren and timeouts """ self.__statusbar.push(self.__statuscontext, _("Time: 0s")) - self.__throbber.set_from_animation(self.__animationThobber) + self.__throbber.start() self._launchChildren() self._launchTimeout() @@ -695,9 +1008,9 @@ message: mesage from readFile method - print message - """ - print message + print( message ) + """ + print( message ) def readFile_set_statistics(self, statistics): """readFile_set_statistics(statistics) @@ -713,21 +1026,24 @@ The readFile method end successfully """ - print self.__statistics + self.endSuccessfully = True + print( self.__statistics.str() ) def readFile_cancel(self): """readFile_cancel() The readFile method is canceled """ - print _("Process terminated") + self.endSuccessfully = False + print(_("Process terminated") ) def stopLoading(self): """stopLoading() Stop progressbar """ - self.__throbber.set_from_pixbuf(self.__budget_icon) + self.__throbber.destroy() + self.__budget_icon.show() self.__progress_bar.hide() self.__statusbar.pop(self.__statuscontext) @@ -750,12 +1066,15 @@ 2- update time label 3- If the other timetouts are stoped the window is closed """ - gobject.timeout_add(1000, self._updateLabel, time.time()) - gobject.timeout_add(500, self._updateProgressBar) + GLib.timeout_add(1000, self._updateLabel, time.time()) + GLib.timeout_add(500, self._updateProgressBar) self.__cancel = [False, False] - #self.__cancel = [True, False] - gobject.timeout_add(1000, self._autoClose) - + GLib.timeout_add(1000, self._autoClose) + + def updateGui(self): + while Gtk.events_pending(): + Gtk.main_iteration() + def _updateProgressBar(self): """_updateProgressBar() @@ -772,7 +1091,7 @@ return True def _updateLabel(self, _time): - """_updateProgressBar(_time) + """_updateLabel(_time) update time label in a timeout If the thread end or is canceled the timeout is stoped @@ -788,11 +1107,12 @@ return True def _autoClose(self): - """_updateProgressBar() + """_autoClose() If the time label and progress bar timeouts are stoped the window is closed and ist tiemeout is stoped """ + #_autoClose timeout do nothig if self.__cancel == [ True, True ]: return False else: @@ -808,11 +1128,13 @@ self.__budget = budget self.__children = None self.stopLoading() - _page = Page(self.__mainWindow, self.__budget) + _page = Page(self.__mainWindow, self.__budget, self.closeTabButton) _children = self.__widget.get_children() for _child in _children: self.__widget.remove(_child) - self.__widget.pack_start(_page.widget, True, True, 0) + self.__widget.add(_page.widget) + self.closeTabButton.disconnect(self.__closeTabId) + self.closeTabButton.connect("clicked", _page.on_close_button) self.__mainWindow.updatePage(self, _page) def threadCanceled(self): @@ -826,6 +1148,13 @@ self.stopLoading() self.__mainWindow.closePage(self) + def on_close_button(self, widget): + """on_close_button() + + Call close + """ + self.close() + def close(self): """close() @@ -836,7 +1165,7 @@ def clear(self): """clear() - clear vars + Nothig to do now """ pass @@ -850,14 +1179,14 @@ def _getTitle(self): """_getTitle() - Return the title of the page, a gtk.Label objetc + Return the title of the page, a Gtk.Label objetc """ return self.__title def _getFiletype(self): """_getFiletipe() - Return the title of the page, a gtk.Label objetc + Return the title of the page, a Gtk.Label objetc """ return self.__filetype @@ -866,7 +1195,7 @@ title = property(_getTitle, None, None, "Page Title") filetype = property(_getFiletype, None, None, - "Filetype: budget, basedata or durus") + "Filetype: budget or basedata") class Page(object): @@ -877,15 +1206,16 @@ The page can show the budget information in several panes ordered according to "panes_list" information. Constructor: - gui.Page(mainWindow, budget, active_code=None) + Page(mainWindow, budget, closeTabButton, active_code=None) mainwindow: MainWindow object budget: base.Budget object + closeTabButton. button winget to close tab active_code: Active record code Ancestry: +-- object +-- Page Atributes: - widget: Read. Notebook page Widget. (a gtk.VBox instance) + widget: Read. Notebook page Widget. (a vertical Gtk.Grid instance) budget: Read-Write. Budget to show in the page. (base.obra object) panes_list: Read. info list for create the panes ej: [ "v", pane1, pane2 ] , [ "h", pane1, pane2 ] @@ -896,7 +1226,7 @@ * "Measure": its creates a "Measure" objetc * "FileView": its creates a "FileView" objet * "CompanyView": its creates a "CompanyView" object - title: Read. Notebook page title (gtk.Label object) + title: Read. Notebook page title (Gtk.Label object) activePathRecord: Read. The active path record previousPathRecord: Read. The previous path record posteriorPathRecord Read. The posterior path record @@ -905,6 +1235,7 @@ Methods: propagateMessageFrom sendMessageTo + on_close_button close clear getItem @@ -914,52 +1245,59 @@ # TODO: * pane types # TODO: * General budget properties (is better a dialog?) - def __init__(self, mainWindow, budget, path_record=None): - """__init__(mainWindow, budget, path_record=None) + def __init__(self, mainWindow, budget, closeTabButton, path_record=None): + """__init__(mainWindow, budget, closeTabButton, path_record=None) mainWindow: MainWindow object budget: "base.Budget" object + closeTabButton: Button widget to close tab path_record: the active path record self.__mainWindow: MainWindow object - self.__widget: a gtk.VBox + self.__widget: a Gtk.Grid self.__panes_list: - self.__main_item: + self.__main_item: Main item in Page. (Paned object or View object) + self.closeTabButton: : Button widget to close tab self.__active_path_record: self.__history_back: self.__history_forward: - self.__back_menu: a gtk.Menu - self.__forward_menu: a gtk.Menu + self.__back_menu: a Gtk.Menu + self.__forward_menu: a Gtk.Menu """ if path_record is None: path_record = (0,) - #TODO: __panes_list should come from config file... self.__mainWindow = mainWindow - self.__widget = gtk.VBox() + self.closeTabButton = closeTabButton + self.__widget = Gtk.Grid() + self.__widget.set_orientation(Gtk.Orientation(1)) # 1 Vertical + self.__widget.props.margin = 5 + #TODO: __panes_list should come from gui config file... + # "DecompositionList" "RecordDescription" "Measure" "Sheet of Conditions" + # "FileView" "CompanyView" self.__panes_list = [ "v", "DecompositionList", [ "v", "Measure", "RecordDescription" ]] self.__main_item = None self.__active_path_record = () self.__history_back = [] self.__history_forward = [] - self.__back_menu = gtk.Menu() + self.__back_menu = Gtk.Menu() self.__back_menu.show() - self.__forward_menu = gtk.Menu() + self.__forward_menu = Gtk.Menu() self.__forward_menu.show() - self.budget = budget + self.budget = budget # Create all items and widgets self._setActivePathRecord(path_record) self.__widget.show() - self.__budget_icon = gtk.gdk.pixbuf_new_from_file( + self.__budget_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("BUDGET-ICON")) - self.__chapter_icon = gtk.gdk.pixbuf_new_from_file( + self.__chapter_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("CHAPTER-ICON")) - self.__unit_icon = gtk.gdk.pixbuf_new_from_file( + self.__unit_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("UNIT-ICON") ) - self.__material_icon = gtk.gdk.pixbuf_new_from_file( + self.__material_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("MATERIAL-ICON") ) - self.__machinery_icon = gtk.gdk.pixbuf_new_from_file( + self.__machinery_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("MACHINERY-ICON")) - self.__labourforce_icon = gtk.gdk.pixbuf_new_from_file( + self.__labourforce_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("LABOURFORCE-ICON")) def propagateMessageFrom(self, message, pane_path, arg=None): @@ -980,7 +1318,7 @@ if message == "change_active" and _budget.hasPath(arg): self.sendMessageTo(self.__main_item, message, pane_path, arg) self._setActivePathRecord(arg) - self.__mainWindow.changeActiveSignal() + self.__mainWindow.changeActiveSignal() # Check sensitive buttons elif message == "autoclose": self._closeItem(pane_path) elif message == "split h": @@ -997,8 +1335,10 @@ Sends a message to a pane """ - if not pane.pane_path == pane_path: - pane.runMessage(message, pane_path, arg) + pane.runMessage(message, pane_path, arg) + + def on_close_button(self, widget): + self.close() def close(self): """close() @@ -1043,7 +1383,7 @@ self.__main_item = item _main_widget = self.__main_item.widget _main_widget.show() - self.__widget.pack_start(_main_widget, True, True, 0) + self.__widget.add(_main_widget) def _splitItem(self, pane_path, orientation): """_splitItem(pane_path, orientation) @@ -1051,12 +1391,12 @@ Splits the item that is identifies by the pane_path and the orientation """ _item = self.getItem(pane_path) - _parent = self.getItem(pane_path[:-1]) - _item.pane_path = pane_path + (0,) + _item.pane_path = pane_path + (0,) _item_clone0 = _item.getClone(pane_path + (0,)) _item_clone1 = _item.getClone(pane_path + (1,)) _paned = Paned(orientation, pane_path, _item_clone0, _item_clone1) if len(pane_path) > 1: + _parent = self.getItem(pane_path[:-1]) _parent.setItem(pane_path[-1], [_paned]) else: self._setMainItem(_paned) @@ -1112,10 +1452,10 @@ if pane_path is None: pane_path = (0,) if not isinstance(list_paned , list): - raise ValueError, _("The value must be a list") + raise ValueError( _("The value must be a list") ) if list_paned[0] == "v" or list_paned[0] == "h": if len(list_paned) != 3: - raise ValueError, _("Incorrect len") + raise ValueError( _("Incorrect len") ) if not isinstance(list_paned[1],list): list_paned[1] = [list_paned[1]] if not isinstance(list_paned[2],list): @@ -1125,26 +1465,26 @@ _item = Paned(list_paned[0], pane_path, _item1, _item2) elif list_paned[0] == "DecompositionList": _item = View( "DecompositionList", self.__budget, - weakref.ref(self), pane_path, self.__active_path_record) + weakref.ref(self), pane_path, self.__active_path_record, True) elif list_paned[0] == "RecordDescription": _item = View( "RecordDescription", self.__budget,weakref.ref(self), - pane_path, self.__active_path_record) + pane_path, self.__active_path_record, True) elif list_paned[0] == "Measure": _item = View( "Measure", self.__budget, weakref.ref(self), pane_path, - self.__active_path_record) + self.__active_path_record, True) elif list_paned[0] == "Sheet of Conditions": - _item = Sheet(sef.__budget, weakref.ref(self), pane_path, + _item = View("Sheet of Conditions", self.__budget, weakref.ref(self), pane_path, self.__active_path_record) elif list_paned[0] == "FileView": - _item = FileView(sef.__budget, weakref.ref(self), pane_path, + _item = View("FileView", self.__budget, weakref.ref(self), pane_path, self.__active_path_record) elif list_paned[0] == "CompanyView": - _item = CompanyView(sef.__budget, weakref.ref(self), pane_path, + _item = View("CompanyView", self.__budget, weakref.ref(self), pane_path, self.__active_path_record) else: _item = None - raise ValueError, utils.mapping(_("Incorrect item $1"), - (str(list_paned[0]),)) + raise ValueError( utils.mapping(_("Incorrect item $1"), + (str(list_paned[0]),)) ) return _item def _setActivePathRecord(self, path_record): @@ -1159,8 +1499,8 @@ self.__active_path_record = path_record self._appendHistory(path_record) else: - raise ValueError, utils.mapping(_("The budget does not have "\ - "the path record: $1"), (str(path_record),)) + raise ValueError( utils.mapping(_("The budget does not have "\ + "the path record: $1"), (str(path_record),)) ) def _appendHistory(self, path): """_appendHistory(path)) @@ -1250,7 +1590,7 @@ _icon = self.__machinery_icon else: _icon = self.__material_icon - _image = gtk.Image() + _image = Gtk.Image() _image.set_from_pixbuf(_icon) return _image @@ -1261,7 +1601,6 @@ Creates menus for history back an history forward tool buttons """ - # Back Menu # clear menu for _child in self.__back_menu.get_children(): @@ -1270,7 +1609,7 @@ if len(self.__history_back) > 1: for _record_path in self.__history_back[:-1]: _menuitem = self._menuItemFactory(_record_path) - _menuitem.connect_object("activate", self._menuHistoryBack, + _menuitem.connect("activate", self._menuHistoryBack, _record_path, _menuitem) self.__back_menu.prepend(_menuitem) # Forward Menu @@ -1281,7 +1620,7 @@ if len(self.__history_forward) > 0: for _record_path in self.__history_forward[:]: _menuitem = self._menuItemFactory(_record_path) - _menuitem.connect_object("activate", self._menuHistoryForward, + _menuitem.connect("activate", self._menuHistoryForward, _record_path, _menuitem) self.__forward_menu.prepend(_menuitem) @@ -1295,13 +1634,19 @@ _code = self.budget.getCode(record_path) _record = self.budget.getRecord(_code) _summary = _record.summary - _text = _code + " " + _summary + _text = _code.decode("utf8") + " " + _summary.decode("utf8") if len(_text) > 30: _text = _text[:27] + "..." - _image = self._getImage(_record) - _menuitem = gtk.ImageMenuItem(_text) - _menuitem.set_image(_image) - _menuitem.show() + _icon = self._getImage(_record) + _grid = Gtk.Grid() + _grid.set_orientation(Gtk.Orientation(0)) # 0 Horizontal + _grid.set_column_spacing(6) + _label = Gtk.Label(_text) + _menuitem = Gtk.MenuItem.new() + _grid.add(_icon) + _grid.add(_label) + _menuitem.add(_grid) + _menuitem.show_all() return _menuitem def _menuHistoryBack(self, record_path, menu_item): @@ -1364,7 +1709,7 @@ def _getTitle(self): """_getTitle() - Return the page title, a gtk.Label objetc + Return the page title, a Gtk.Label objetc """ return self.__title @@ -1390,13 +1735,13 @@ self.__budget = budget self._setActivePathRecord((0,)) # Todo: change page title - self.__title = gtk.Label(self.__budget.getCode( + self.__title = Gtk.Label(self.__budget.getCode( self.__active_path_record)) _panes_list = self.__panes_list self.__main_item = self._itemsFactory(_panes_list) _main_widget = self.__main_item.widget _main_widget.show() - self.__widget.pack_start(_main_widget, True, True, 0) + self.__widget.add(_main_widget) def _getBudget(self): """_getBudget() @@ -1437,7 +1782,8 @@ Description: It creates a view to show the budget info Constructor: - View(view_type, budget, wr_page, pane_path, active_path_record) + View(view_type, budget, wr_page, pane_path, active_path_record, + connected) view_type: the object type to show * DecompositionList * Description @@ -1449,14 +1795,16 @@ wr_page: weak reference to the page where the view must be showed pane_path: the position or path of the view in the page notebook active_path_record: the record path that must be showed + connected: boolean value, True means that the View object sends + and receives signals from/to others views. Ancestry: +-- object +-- View Atributes: pane_path: Read-Write. The tuple that identifies the view in the main notebook page - widget: Read. the main gtk widget to show in a view object, - a gtk.VBox object + widget: Read. the main Gtk widget to show in a view object, + a Gtk.Grid object Methods: getItem propagateMessgeFrom @@ -1466,8 +1814,9 @@ """ def __init__(self, view_type, budget, wr_page, pane_path, - active_path_record): - """__init__(view_type, budget, wr_page, pane_path, active_path_record) + active_path_record, connected=True): + """__init__(view_type, budget, wr_page, pane_path, active_path_record, + connected ) view_type: the object type to show * DecompositionList * Description @@ -1480,7 +1829,6 @@ pane_path: the position or path of the view in the page notebook active_path_record: the record path that must be showed - self.__active_path_record: the record path that must be showed self.__view_type: the object type to show * DecompositionList * Description @@ -1494,7 +1842,7 @@ self.__pane_path: the position or path of the view in the page notebook self.__connected: boolean value, True means that the View object sends and receives signals from/to others views - self.__widget: main widget. a gtk.VBox + self.__widget: main widget. a Gtk.Grid self.__view: the object to show: * DecompositionList object * Description object @@ -1507,101 +1855,135 @@ Creates and shows a new view """ - self.__active_path_record = active_path_record self.__view_type = view_type self.__wr_page = wr_page self.__budget = budget self.__pane_path = pane_path - self.__connected = True + self.__connected = connected # view_type liststore - _liststore = gtk.ListStore(str) + _liststore = Gtk.ListStore(str) _liststore.append([_("Decomposition")]) #0 _liststore.append([_("Description")]) #1 _liststore.append([_("Measure")]) #2 _liststore.append([_("Sheet of Conditions")]) #3 _liststore.append([_("Files")]) #4 _liststore.append([_("Companies")]) #5 - _combobox = gtk.ComboBox(_liststore) - _cell = gtk.CellRendererText() + _combobox = Gtk.ComboBox.new_with_model(_liststore) + _cell = Gtk.CellRendererText() _combobox.pack_start(_cell, True) _combobox.add_attribute(_cell, 'text', 0) - self.__widget = gtk.VBox() - _hbox = gtk.HBox() + self.__widget = Gtk.Grid() + self.__widget.set_orientation(Gtk.Orientation(1)) # 1 Vertical + _hbox = Gtk.Grid() + _hbox.set_orientation(Gtk.Orientation(0)) # 0 Horizontal if view_type == "DecompositionList": self.__view = DecompositionList(budget, weakref.ref(self), pane_path, active_path_record) _combobox.set_active(0) - _view_icon = gtk.Image() + _view_icon = Gtk.Image() _view_icon.set_from_file(globalVars.getAppPath( "DECOMPOSITION-ICON")) elif view_type == "RecordDescription": self.__view = Description(budget, weakref.ref(self), pane_path, active_path_record) _combobox.set_active(1) - _view_icon = gtk.Image() + _view_icon = Gtk.Image() _view_icon.set_from_file(globalVars.getAppPath( "DESCRIPTION-ICON")) elif view_type == "Measure": self.__view = Measure(budget, weakref.ref(self), pane_path, active_path_record) _combobox.set_active(2) - _view_icon = gtk.Image() + _view_icon = Gtk.Image() _view_icon.set_from_file(globalVars.getAppPath("MEASURE-ICON")) elif view_type == "Sheet of Conditions": self.__view = Sheet(budget, weakref.ref(self), pane_path, active_path_record) _combobox.set_active(3) - _view_icon = gtk.Image() + _view_icon = Gtk.Image() _view_icon.set_from_file(globalVars.getAppPath("SHEET-ICON")) elif view_type == "FileView": self.__view = FileView(budget, weakref.ref(self), pane_path, active_path_record) _combobox.set_active(4) - _view_icon = gtk.Image() - _view_icon.set_from_file(globalVars.getAppPath("SHEET-ICON")) + _view_icon = Gtk.Image() + _view_icon.set_from_file(globalVars.getAppPath("FILEVIEW-ICON")) elif view_type == "CompanyView": self.__view = CompanyView(budget, weakref.ref(self), pane_path, active_path_record) _combobox.set_active(5) - _view_icon = gtk.Image() - _view_icon.set_from_file(globalVars.getAppPath("SHEET-ICON")) + _view_icon = Gtk.Image() + _view_icon.set_from_file(globalVars.getAppPath("COMPANY-ICON")) else: - raise ValueError, _(utils.mapping("Invalid type of View: $1", - view_type)) + raise ValueError( _(utils.mapping("Invalid type of View: $1", + view_type)) ) _view_icon.show() _combobox.connect("changed", self._change_combo) _combobox.show() - self.__widget.pack_start(_hbox,False) - self.__widget.pack_start(self.__view.widget, True, True) - _hbox.pack_start(_view_icon, False, False,0) - _hbox.pack_start(_combobox, False, False,0) - _invisible = gtk.HBox() + self.__widget.add(_hbox) + self.__widget.add(self.__view.widget) + _hbox.add(_view_icon) + _hbox.add(_combobox) + _invisible = Gtk.Grid() + _invisible.set_orientation(Gtk.Orientation(0)) # 0 Horizontal + _invisible.set_property("hexpand", True) # widget expand horizontal space _invisible.show() - _hbox.pack_start(_invisible, True, False,0) - _icon_menu = gtk.Image() - _icon_menu.set_from_file(globalVars.getAppPath("MENU-ICON")) - _icon_menu.show() - _menu_button = gtk.ToolButton() - _menu_button.set_icon_widget(_icon_menu) - _menu_button.connect("clicked", self._menu_view) - _menu_button.show() - _icon_connected = gtk.Image() - _icon_connected.set_from_file(globalVars.getAppPath("CONNECTED-ICON")) + _hbox.add(_invisible) + # TODO : Set thist with config + add_menu = False + if add_menu: + _icon_menu = Gtk.Image() + _icon_menu.set_from_file(globalVars.getAppPath("MENU-ICON")) + _icon_menu.show() + _menu_button = Gtk.ToolButton() + _menu_button.set_icon_widget(_icon_menu) + _menu_button.connect("clicked", self._menu_view) + _menu_button.show() + _hbox.add(_menu_button) + + _icon_horizontal = Gtk.Image() + _icon_horizontal.set_from_file(globalVars.getAppPath("HORIZONTAL")) + _icon_horizontal.show() + _horizontal_button = Gtk.ToolButton() + _horizontal_button.set_icon_widget(_icon_horizontal) + _horizontal_button.connect("clicked", self._split_view, "h") + _horizontal_button.set_tooltip_text(_("Split View Left/Right")) + _horizontal_button.show() + _hbox.add(_horizontal_button) + + _icon_vertical = Gtk.Image() + _icon_vertical.set_from_file(globalVars.getAppPath("VERTICAL")) + _icon_vertical.show() + _vertical_button = Gtk.ToolButton() + _vertical_button.set_icon_widget(_icon_vertical) + _vertical_button.connect("clicked", self._split_view, "v") + _vertical_button.set_tooltip_text(_("Split View Top/Bottom")) + _vertical_button.show() + _hbox.add(_vertical_button) + + self.__connected_button = Gtk.ToolButton() + _icon_connected = Gtk.Image() + if self.__connected: + _icon_connected.set_from_file(globalVars.getAppPath("CONNECTED-ICON")) + self.__connected_button.set_tooltip_text(_("Disconnect view")) + else: + _icon_connected.set_from_file(globalVars.getAppPath("DISCONNECTED-ICON")) + self.__connected_button.set_tooltip_text(_("Connect view")) _icon_connected.show() - _hbox.pack_start(_menu_button, False, False, 0) - self.__connected_button = gtk.ToolButton() self.__connected_button.set_icon_widget(_icon_connected) self.__connected_button.connect("clicked", self._connected) self.__connected_button.show() - _hbox.pack_start(self.__connected_button, False, False, 0) - _icon_close = gtk.Image() + _hbox.add(self.__connected_button) + + _icon_close = Gtk.Image() _icon_close.set_from_file(globalVars.getAppPath("CLOSE-ICON")) _icon_close.show() - _close_button = gtk.ToolButton() + _close_button = Gtk.ToolButton() _close_button.set_icon_widget(_icon_close) - _close_button.connect("clicked", self._closeItem) + _close_button.connect("clicked", self._closeItem_from_button) + _close_button.set_tooltip_text(_("Close view")) _close_button.show() - _hbox.pack_start(_close_button, False, False, 0) + _hbox.add(_close_button) _hbox.show() self.__widget.show() @@ -1612,8 +1994,16 @@ """ return self - def _closeItem(self, close_button): - """_closeItem(close_button) + def _closeItem_from_menu(self, close_menuitem): + """_closeItem_from_menu(close_menuitem) + + Method connected to the "clicked" signal of the _close_button widget + Send the "autoclose" message to the page to close this view + """ + self.propagateMessageFrom("autoclose", self.__pane_path) + + def _closeItem_from_button(self, close_button): + """_closeItem_from_button(close_button) Method connected to the "clicked" signal of the _close_button widget Send the "autoclose" message to the page to close this view @@ -1628,24 +2018,15 @@ """ _index = combobox.get_active() _budget = self.__view.budget - _wr_page = self.__view.page + _wr_page = self.__view.wr_page _pane_path = self.__view.pane_path _path_record = self.__view.active_path_record - _hbox = self.__widget.get_children()[0] - _combobox = _hbox.get_children()[1] - _hbox.remove(_combobox) - _invisible = _hbox.get_children()[1] - _hbox.remove(_invisible) - _menu_button = _hbox.get_children()[1] - _hbox.remove(_menu_button) - _connected_button = _hbox.get_children()[1] - _hbox.remove(_connected_button) - _close_button = _hbox.get_children()[1] - _hbox.remove(_close_button) + _hbox = self.__widget.get_children()[1] + _view_icon = _hbox.get_child_at(0, 0) + _hbox.remove(_view_icon) + _view_icon.destroy() self.__widget.remove(self.__view.widget) - self.__widget.remove(_hbox) - _hbox.destroy() - _view_icon = gtk.Image() + _view_icon = Gtk.Image() if _index == 0: self.__view = DecompositionList(_budget, _wr_page, _pane_path, _path_record) @@ -1671,24 +2052,16 @@ elif _index == 4: self.__view = FileView(_budget, _wr_page, _pane_path, _path_record) - _view_icon.set_from_file(globalVars.getAppPath("SHEET-ICON")) + _view_icon.set_from_file(globalVars.getAppPath("FILEVIEW-ICON")) self.__view_type = "FileView" elif _index == 5: self.__view = CompanyView(_budget, _wr_page, _pane_path, _path_record) - _view_icon.set_from_file(globalVars.getAppPath("SHEET-ICON")) + _view_icon.set_from_file(globalVars.getAppPath("COMPANY-ICON")) self.__view_type = "CompanyView" _view_icon.show() - _hbox = gtk.HBox() - _hbox.pack_start(_view_icon, False, False,0) - _hbox.pack_start(_combobox, False, False,0) - _hbox.pack_start(_invisible, True, False,0) - _hbox.pack_start(_menu_button, False, False, 0) - _hbox.pack_start(_connected_button, False, False, 0) - _hbox.pack_start(_close_button, False, False, 0) - _hbox.show() - self.__widget.pack_start(_hbox, False, False, 0) - self.__widget.pack_start(self.__view.widget, True, True, 0) + _hbox.attach(_view_icon, 0, 0, 1, 1) + self.__widget.add(self.__view.widget) def _menu_view(self, widget): """_menu_view(widget) @@ -1696,22 +2069,22 @@ Method connected to the "clicked" signal of the __connected_button It shows a popup menu with some options """ - _menu_view = gtk.Menu() - _item_leftright = gtk.MenuItem(_("Split View Left/Right")) + _menu_view = Gtk.Menu() + _item_leftright = Gtk.MenuItem(_("Split view Left/Right")) _menu_view.append(_item_leftright) - _item_leftright.connect_object("activate", self._split_view, "h") + _item_leftright.connect("activate", self._split_view, "h") _item_leftright.show() - _item_topbottom = gtk.MenuItem(_("Split View Top/Bottom")) + _item_topbottom = Gtk.MenuItem(_("Split view Top/Bottom")) _menu_view.append(_item_topbottom) - _item_topbottom.connect_object("activate", self._split_view, "v") + _item_topbottom.connect("activate", self._split_view, "v") _item_topbottom.show() - _item_close = gtk.MenuItem(_("Close view")) + _item_close = Gtk.MenuItem(_("Close view")) _menu_view.append(_item_close) - _item_close.connect_object("activate", self._closeItem, None) + _item_close.connect("activate",self._closeItem_from_menu) _item_close.show() - _menu_view.popup(None, None, None, 0, 0) - - def _split_view(self, orientation): + _menu_view.popup_at_widget(widget, Gdk.Gravity(7), Gdk.Gravity(1), Gtk.get_current_event()) + + def _split_view(self, widget, orientation): """_menu_view(orientation) orientation: orientation split, "h" or "v" @@ -1732,15 +2105,17 @@ to/from others views """ if self.__connected: - _icon = gtk.Image() + _icon = Gtk.Image() _icon.set_from_file(globalVars.getAppPath("DISCONNECTED-ICON")) _icon.show() self.__connected_button.set_icon_widget(_icon) + self.__connected_button.set_tooltip_text(_("Connect View")) self.__connected = False else: - _icon = gtk.Image() + _icon = Gtk.Image() _icon.set_from_file(globalVars.getAppPath("CONNECTED-ICON")) _icon.show() + self.__connected_button.set_tooltip_text(_("Disconnect View")) self.__connected_button.set_icon_widget(_icon) self.__connected = True @@ -1770,10 +2145,6 @@ """ if self.__connected: self.__view.runMessage(message, pane_path, arg) - if message == "change_active": - if self.__budget.hasPath(arg): - _path_record = arg - self.__active_path_record = _path_record def _getWidget(self): """_getWidget() @@ -1805,7 +2176,8 @@ return a clone of itself """ return View(self.__view_type, self.__budget, self.__wr_page, - new_pane_path, self.__active_path_record) + new_pane_path, self.__view.active_path_record, + self.__connected) def clear(self): """clear() @@ -1829,7 +2201,7 @@ """gui.Paned: Description: - It creates and shows gtk.Hpaned or gtk.Vpaned to show in page budget + It creates and shows Gtk.Paned to show in page budget Constructor: Paned(orientation, widget1, widget2) orientation: The orientation of the pane separator, can be "v" or @@ -1840,7 +2212,7 @@ +-- object +-- Paned Atributes: - widget: Read. Pane widget("gtk.VPaned" or "gtk.HPaned" object) + widget: Read. Pane widget("Gtk.Paned" object) pane_path: Read-Write. The paned path in the page Methods: getClone @@ -1857,29 +2229,31 @@ def __init__(self, orientation, pane_path, item1, item2): """__init__(oritentation, pane_path, item1, item2) - orientation: The orientation of de gtk.Paned, can be "v" or "h" + orientation: The orientation of de Gtk.Paned, can be "v" or "h" pane_path: the paned path in the page item1: the top or left pane object item2: the bottom or right pane object - self.__orientation: The orientation of de gtk.Paned, can be "v" or "h" - self.__widget: Main widget, a gtk.VPaned o gtk.HPaned + self.__orientation: The orientation of de Gtk.Paned, can be "v" or "h" + self.__widget: Main widget, a Gtk.Paned self.__items: list of items showed in the paned, its can be View or Paned instances self.__pane_path: the paned path in the page - Creates and shows a new gtk.Paned + Creates and shows a new Gtk.Paned """ self.__orientation = orientation - if not isinstance(item1.widget, gtk.Widget) or \ - not isinstance(item2.widget, gtk.Widget): - raise ValueError, _("The item must be a widget object.") + if not isinstance(item1.widget, Gtk.Widget) or \ + not isinstance(item2.widget, Gtk.Widget): + raise ValueError( _("The item must be a widget object.") ) if orientation == "v": - self.__widget = gtk.VPaned() + self.__widget = Gtk.Paned.new(Gtk.Orientation(1)) + self.__widget.set_wide_handle(True) elif orientation == "h": - self.__widget = gtk.HPaned() + self.__widget = Gtk.Paned.new(Gtk.Orientation(0)) + self.__widget.set_wide_handle(True) else: - raise ValueError, _("Invalid orientation.") + raise ValueError( _("Invalid orientation.") ) self.__widget.pack1(item1.widget,True,False) self.__widget.pack2(item2.widget,True,False) self.__widget.show() @@ -1950,7 +2324,7 @@ def _getWidget(self): """_getWidget() - Return de gtk.Paned widget + Return de Gtk.Paned widget """ return self.__widget @@ -1980,7 +2354,7 @@ del self.__items del self.__pane_path - widget = property(_getWidget, None, None, "gtk.Paned widget") + widget = property(_getWidget, None, None, "Gtk.Paned widget") pane_path = property(_getPanePath, _setPanePath, None, "Pane path in the notebook page") @@ -2010,7 +2384,7 @@ +-- object +-- TreeView Atributes: - columns: list of columns (gtk.TreeViewColumn objects) + columns: list of columns (Gtk.TreeViewColumn objects) Methods: createColumn createTextBaseColumn @@ -2039,7 +2413,7 @@ """ self.columns = [ self.createColumn(arg) for arg in args ] self.columns.append(self.createColumn(("END",))) - + def createColumn(self, args): """createColumn(args) @@ -2061,19 +2435,19 @@ """ if args[0] == "INDEX": _index_column = self.createBaseColumn(args) - _text_index_cell = gtk.CellRendererText() - _text_index_cell.set_property('foreground-gdk', - gtk.gdk.color_parse(globalVars.color["TEXT"])) - _pixbuf_index_cell = gtk.CellRendererPixbuf() - _arrow_icon = gtk.gdk.pixbuf_new_from_file( + _text_index_cell = Gtk.CellRendererText() + _text_index_cell.set_property('foreground', + globalVars.color["TEXT"]) + _pixbuf_index_cell = Gtk.CellRendererPixbuf() + _arrow_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("ARROW-ICON")) _pixbuf_index_cell.set_property("pixbuf", _arrow_icon) _index_column.pack_start(_text_index_cell, True) _index_column.pack_start(_pixbuf_index_cell, True) _index_column.set_cell_data_func(_text_index_cell, self._colorCell, - [gtk.gdk.color_parse(globalVars.color["INDEX-UNEVEN"]), - gtk.gdk.color_parse(globalVars.color["INDEX-EVEN"])]) + [globalVars.color["INDEX-UNEVEN"], + globalVars.color["INDEX-EVEN"]]) return _index_column elif args[0] == "TEXT": _column, _cell = self.createTextBaseColumn(args) @@ -2082,20 +2456,20 @@ elif args[0] == "FLOAT": _column, _cell = self.createTextBaseColumn(args) _column.add_attribute(_cell, 'text', args[5]) - _column.get_cell_renderers()[0].set_property('xalign', 1.0) + _column.get_cells()[0].set_property('xalign', 1.0) return _column elif args[0] == "CALCULATED": _column, cell = self.createTextBaseColumn(args) - _column.get_cell_renderers()[0].set_property('xalign', 1.0) + _column.get_cells()[0].set_property('xalign', 1.0) return _column elif args[0] == "CALCULATEDTEXT": _column, cell = self.createTextBaseColumn(args) return _column elif args[0] == "TYPE": _column = self.createBaseColumn(args) - _type_cell1 = gtk.CellRendererPixbuf() - _type_cell2 = gtk.CellRendererText() - _type_cell2.set_property('foreground-gdk', args[3]) + _type_cell1 = Gtk.CellRendererPixbuf() + _type_cell2 = Gtk.CellRendererText() + _type_cell2.set_property('foreground', args[3]) _column.pack_start(_type_cell1, True) _column.pack_start(_type_cell2, True) _column.add_attribute(_type_cell2, 'text', args[5]) @@ -2106,17 +2480,17 @@ return _column elif args[0] == "PIXBUF": _column = self.createBaseColumn(args) - _type_cell1 = gtk.CellRendererPixbuf() + _type_cell1 = Gtk.CellRendererPixbuf() _column.pack_start(_type_cell1, True) _column.set_cell_data_func(_type_cell1, self._colorCell, args[4]) return _column elif args[0] == "END": - _end_column = gtk.TreeViewColumn() + _end_column = Gtk.TreeViewColumn() _end_column.set_clickable(False) - _end_cell = gtk.CellRendererText() - _end_cell.set_property('cell-background-gdk', - gtk.gdk.color_parse(globalVars.color["UNEVEN"])) + _end_cell = Gtk.CellRendererText() + _end_cell.set_property('background', + globalVars.color["UNEVEN"]) _end_column.pack_start(_end_cell, True) return _end_column return None @@ -2139,8 +2513,8 @@ Return a column and its CellREndererText """ _column = self.createBaseColumn(args) - _cell = gtk.CellRendererText() - _cell.set_property('foreground-gdk', args[3]) + _cell = Gtk.CellRendererText() + _cell.set_property('foreground', args[3]) _column.pack_start(_cell, True) _column.set_cell_data_func(_cell, self._colorCell, args[4]) return _column, _cell @@ -2164,10 +2538,10 @@ Return a column """ - _column = gtk.TreeViewColumn() + _column = Gtk.TreeViewColumn() _column.set_clickable(True) _column.connect("clicked", args[1]) - _column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + _column.set_sizing(Gtk.TreeViewColumnSizing(2)) # 2 Fixed _column.set_fixed_width(args[2]) _column.set_resizable(True) return _column @@ -2179,7 +2553,7 @@ Description: Class to show a budget Decomposition List Constructor: - DecompositionList(budget, page, pane_path, path_record=(0,)) + DecompositionList(budget, page, pane_path, path_record=None) budget: budget showed ("base.Budget" object) page: weak reference from Page instance which creates this class pane_path: tuple that represents the view path in the Page @@ -2191,15 +2565,15 @@ +-- DecompositionList Atributes: budget: Read. Budget to show, base.obra object. - widget: Read. Window that contains the table, gtk.ScrolledWindow + widget: Read. Window that contains the table, Gtk.ScrolledWindow pane_path: Read-Write. Pane page identifier - page: Read-Write. weak ref from Page object which creates this class + wr_page: Read-Write. weak ref from Page object which creates this class active_path_record: Read. Active path record Methods: runMessage """ - def __init__(self, budget, page, pane_path, path_record=None): + def __init__(self, budget, wr_page, pane_path, path_record=None): """__init__(budget, page, pane_path, path_record=None) budget: budget showed ("base.Budget" object) @@ -2208,33 +2582,33 @@ path_record: the record path that must be showed self.__budget: budget showed ("base.Budget" object) - self.__page: weak reference from Page instance which creates this class + self.__wr_page: weak reference from Page instance which creates this class self.__pane_path: tuple that represents the path of the List in the Page self.__liststore: list model which store the list data - (gtk.ListStore object) + (Gtk.ListStore object) self.__active_path_record: the record path that must be showed self.__treeview: widget for displaying decomposition lists - (gtk.TreeView) + (Gtk.TreeView) self.__scrolled_window: widget to contain the treeview object self.__chapter_background_colors: background colors of the Code column cells when there is a chapter record, - list of gtk.gdk.Color objects [even cell, uneven cell] + list of color [even cell, uneven cell] self.__chapter_background_colors - self.__index_column: Index column (gtk.TreeViewColumn object) - self.__code_column: Record code column (gtk.TreeViewColumn) - self.__type_column: Record Type column (gtk.TreeViewColumn) - self.__unit_column: Unit of measure column (gtk.TreeViewColumn) + self.__index_column: Index column (Gtk.TreeViewColumn object) + self.__code_column: Record code column (Gtk.TreeViewColumn) + self.__type_column: Record Type column (Gtk.TreeViewColumn) + self.__unit_column: Unit of measure column (Gtk.TreeViewColumn) self.__description_column: record's short description column - (gtk.TreeViewColumn) - self.__measure_column: Measure column (gtk.TreeViewColumn) - self.__price_column: Price column (gtk.TreeViewColumn) - self.__amount_column: Amount column(gtk.TreeViewColumn) - self.__end_column: End empty column (gtk.TreeViewColumn) - self.__chapter_icon: a gtk.gdk.pixbuf - self.__unit_icon: a gtk.gdk.pixbuf - self.__material_icon: a gtk.gdk.pixbuf - self.__machinery_icon: a gtk.gdk.pixbuf - self.__labourforce_icon: a gtk.gdk.pixbuf + (Gtk.TreeViewColumn) + self.__measure_column: Measure column (Gtk.TreeViewColumn) + self.__price_column: Price column (Gtk.TreeViewColumn) + self.__amount_column: Amount column(Gtk.TreeViewColumn) + self.__end_column: End empty column (Gtk.TreeViewColumn) + self.__chapter_icon: a GdkPixbuf.Pixbuf + self.__unit_icon: a GdkPixbuf.Pixbuf + self.__material_icon: a GdkPixbuf.Pixbuf + self.__machinery_icon: a GdkPixbuf.Pixbuf + self.__labourforce_icon: a GdkPixbuf.Pixbuf self.__treeselection: active selection self.__selection_control: state of the selection control (True/False) self.__cursor: cursor position in the table @@ -2250,63 +2624,55 @@ """ # TODO: to group all columns in a dicctionary # Budget - if path_record is None: - parh_record = (0,) if not isinstance(budget, base.Budget): - raise ValueError, _("Argument must be a Budget object") + raise ValueError( _("Argument must be a Budget object") ) self.__budget = budget - self.__page = page + self.__wr_page = wr_page self.__pane_path = pane_path # ListStore - self.__liststore = gtk.ListStore(object + self.__liststore = Gtk.ListStore(object #, int, int, str, str, str, str, str,str ) if path_record is None: - print _("Record path can not be None") path_record = (0,) self.__active_path_record = path_record self._setListstoreValues(self.__active_path_record) # Treeview - self.__treeview = gtk.TreeView(self.__liststore) + self.__treeview = Gtk.TreeView(self.__liststore) self.__treeview.set_enable_search(False) self.__treeview.set_reorderable(False) self.__treeview.set_headers_clickable(True) self.__treeview.show() # Scrolled_window - self.__scrolled_window = gtk.ScrolledWindow() - self.__scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) + self.__scrolled_window = Gtk.ScrolledWindow() + self.__scrolled_window.set_property("expand", True) # widget expand all space + self.__scrolled_window.set_policy(Gtk.PolicyType(1), + Gtk.PolicyType(1)) # 1 Automatic self.__scrolled_window.add(self.__treeview) # colors - _text_color = gtk.gdk.color_parse(globalVars.color["TEXT"]) + _text_color = globalVars.color["TEXT"] _background_color = [ - gtk.gdk.color_parse(globalVars.color["UNEVEN"]), - gtk.gdk.color_parse(globalVars.color["EVEN"])] + globalVars.color["UNEVEN"], + globalVars.color["EVEN"]] self.__chapter_background_colors = [ - gtk.gdk.color_parse(globalVars.color["CHAPTER-UNEVEN"]), - gtk.gdk.color_parse(globalVars.color["CHAPTER-EVEN"])] + globalVars.color["CHAPTER-UNEVEN"], + globalVars.color["CHAPTER-EVEN"]] super(DecompositionList,self).__init__( [("INDEX",self._selectAll,42), ("CALCULATEDTEXT", self._showParentRecord, - gtk.Label("A"*10).size_request()[0] +10, - _text_color, _background_color), + 100, _text_color, _background_color), ("PIXBUF", self._showParentRecord, 26, _text_color, _background_color), ("CALCULATEDTEXT", self._showParentRecord, - gtk.Label(_("a"*4)).size_request()[0] +10, - _text_color, _background_color), + 52, _text_color, _background_color), ("CALCULATEDTEXT", self._showParentRecord, - gtk.Label("a"*30).size_request()[0] +10, - _text_color, _background_color), + 245, _text_color, _background_color), ("CALCULATED", self._showParentRecord, - gtk.Label("a"*10).size_request()[0] +10, - _text_color, _background_color), + 90, _text_color, _background_color), ("CALCULATED", self._showParentRecord, - gtk.Label("a"*10).size_request()[0] +10, - _text_color, _background_color), + 90, _text_color, _background_color), ("CALCULATED", self._showParentRecord, - gtk.Label("a"*10).size_request()[0] +10, - gtk.gdk.color_parse(globalVars.color["CALCULATED-TEXT"]), + 90, globalVars.color["CALCULATED-TEXT"], _background_color), ]) self.__index_column = self.columns[0] @@ -2324,19 +2690,18 @@ self.__treeview.append_column(self.__code_column) # Type column self.__treeview.append_column(self.__type_column) - self.__chapter_icon = gtk.gdk.pixbuf_new_from_file( + self.__chapter_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("CHAPTER-ICON")) - self.__unit_icon = gtk.gdk.pixbuf_new_from_file( + self.__unit_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("UNIT-ICON") ) - self.__material_icon = gtk.gdk.pixbuf_new_from_file( + self.__material_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("MATERIAL-ICON") ) - self.__machinery_icon = gtk.gdk.pixbuf_new_from_file( + self.__machinery_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("MACHINERY-ICON")) - self.__labourforce_icon = gtk.gdk.pixbuf_new_from_file( + self.__labourforce_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("LABOURFORCE-ICON")) - self.__type_column.get_cell_renderers()[0].set_property("pixbuf", + self.__type_column.get_cells()[0].set_property("pixbuf", self.__labourforce_icon) - # Unit column self.__treeview.append_column(self.__unit_column) # Description column @@ -2358,12 +2723,13 @@ self.__treeview.connect("cursor-changed", self._treeviewCursorChanged) # control selection self.__treeselection = self.__treeview.get_selection() - self.__treeselection.set_mode(gtk.SELECTION_MULTIPLE) + self.__treeselection.set_mode(Gtk.SelectionMode(3)) # 3 MULTIPLE self.__treeselection.set_select_function(self._controlSelection) self.__selection_control = True if len(self.__liststore) > 0: - self.__treeview.set_cursor_on_cell((0,),self.__unit_column, - self.__unit_column.get_cell_renderers()[0],True) + _tree_path = Gtk.TreePath.new_from_indices((0,)) + self.__treeview.set_cursor_on_cell(_tree_path ,self.__unit_column, + self.__unit_column.get_cells()[0],True) self.__treeview.grab_focus() self.__cursor = self.__treeview.get_cursor() # Show @@ -2379,9 +2745,9 @@ Sets the new cursor position in self.__cursor, it is used to avoid unnecessary changes in cursor position. """ - event = gtk.get_current_event() + event = Gtk.get_current_event() (_cursor_path, _column) = treeview.get_cursor() - if event is None or event.type != gtk.gdk.BUTTON_RELEASE: + if event is None or event.type != Gdk.EventType(7): # 7 BUTTON_RELEASE if not _column is self.__index_column: self.__cursor = treeview.get_cursor() @@ -2427,9 +2793,11 @@ in the code column the event is estoped, else the event is propagated. """ (_cursor_path, _column) = self.__treeview.get_cursor() - if (event.keyval == gtk.keysyms.Right \ + if (event.keyval in [Gdk.keyval_from_name("Right"), + Gdk.keyval_from_name("KP_Right")] \ and _column == self.columns[-2]) \ - or (event.keyval == gtk.keysyms.Left \ + or (event.keyval in [Gdk.keyval_from_name("Left"), + Gdk.keyval_from_name("KP_Left")] \ and _column == self.columns[1]): return True return False @@ -2450,7 +2818,7 @@ """ return False - def _controlSelection(self, selection): + def _controlSelection(self, selection, model, path, path_currently_selected, *data): """_controlSelection(selection) selection: treeselection @@ -2485,15 +2853,16 @@ """ (_model, _pathlist) = self.__treeselection.get_selected_rows() # it avoid to set cursor in the index column - self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) - self.__selection_control = False - if len(_pathlist) == 0: - # select all - self.__treeselection.select_all() - else: - # unselect all - self.__treeselection.unselect_all() - self.__selection_control = True + if isinstance(self.__cursor[0],Gtk.TreePath): + self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) + self.__selection_control = False + if len(_pathlist) == 0: + # select all + self.__treeselection.select_all() + else: + # unselect all + self.__treeselection.unselect_all() + self.__selection_control = True def _setColumnsHeaders(self): """_setColumnsHeaders() @@ -2511,7 +2880,7 @@ _unit = _record.unit _description = _record.summary _price = _budget.getStrPriceFromRecord(self.budget.getActiveTitle(), - _record) + _record, _path_record) # TODO: round to decimal places in amount _amount = float(_stryield) * float(_price) if len(_path_record) == 1: # root record @@ -2520,11 +2889,10 @@ _parent_code = self.budget.getCode(self.__active_path_record[:-1]) _parent_record = self.__budget.getRecord(_parent_code) _amount = _budget.getStrAmount(self.__active_path_record) - - self.__code_column.set_title(_("Code") + chr(10) + "[" + _code + "]") - self.__unit_column.set_title(_("Unit") + chr(10) + "[" + _unit + "]") + self.__code_column.set_title(_("Code") + chr(10) + "[" + _code.decode("utf8") + "]") + self.__unit_column.set_title(_("Unit") + chr(10) + "[" + _unit.decode("utf8") + "]") self.__description_column.set_title( - _("Description") + chr(10) + "[" + _description + "]") + _("Description") + chr(10) + "[" + _description.decode("utf8") + "]") self.__measure_column.set_title( _("Measure") + chr(10) + "[" + _stryield + "]") self.__price_column.set_title( @@ -2541,7 +2909,7 @@ self.__liststore.clear() _budget = self.__budget if not _budget.hasPath(path_record): - raise ValueError, _("Invalid path") + raise ValueError( _("Invalid path") ) else: _parent_code = _budget.getCode(path_record) for N,_code in enumerate(_budget.getchildren(_parent_code)): @@ -2564,34 +2932,35 @@ def _colorCell(self, column, cell_renderer, tree_model, iter, lcolor): """_colorCell(column, cell_renderer, tree_model, iter, lcolor) - column: the gtk.TreeViewColumn in the treeview - cell_renderer: a gtk.CellRenderer - tree_model: the gtk.TreeModel - iter: gtk.TreeIter pointing at the row - lcolor: list with 2 gtk colors for even and uneven record + column: the Gtk.TreeViewColumn in the treeview + cell_renderer: a Gtk.CellRenderer + tree_model: the Gtk.TreeModel + iter: Gtk.TreeIter pointing at the row + lcolor: list with 2 Gtk colors for even and uneven record Method connected to "set_cell_data_func" of many column The set_cell_data_func() method sets the data function (or method) - to use for the column gtk.CellRenderer specified by cell_renderer. + to use for the column Gtk.CellRenderer specified by cell_renderer. This function (or method) is used instead of the standard attribute mappings for setting the column values, and should set the attributes of the cell renderer as appropriate. func may be None to remove the current data function. The signature of func is: - -def celldatafunction(column, cell, model, iter, user_data) - -def celldatamethod(self, column, cell, model, iter, user_data) - where column is the gtk.TreeViewColumn in the treeview, cell is the - gtk.CellRenderer for column, model is the gtk.TreeModel for the - treeview and iter is the gtk.TreeIter pointing at the row. + -def celldatafunction(column, cell_renderer, tree_model, iter, lcolor) + -def celldatamethod(self,column,cell_renderer,tree_model, iter, lcolor) + where column is the Gtk.TreeViewColumn in the treeview, cell is the + Gtk.CellRenderer for column, model is the Gtk.TreeModel for the + treeview and iter is the Gtk.TreeIter pointing at the row. The method sets cell background color and text for all columns. """ _row_path = tree_model.get_path(iter) + _global_row_path = self.__active_path_record + (_row_path[0],) _number = _row_path[-1] _record = tree_model[_row_path][0] if column is self.__index_column: cell_renderer.set_property('text', str(_number + 1)) - self.__index_column.get_cell_renderers()[1].set_property( - 'cell-background-gdk', lcolor[_number % 2]) + self.__index_column.get_cells()[1].set_property( + 'cell-background', lcolor[_number % 2]) elif column is self.__code_column: # if the record is a chapter if tree_model.get_value(iter, 0).recordType.hierarchy == 1: @@ -2613,7 +2982,7 @@ cell_renderer.set_property('text', _stryield) elif column is self.__price_column: _price = self.budget.getStrPriceFromRecord( - self.budget.getActiveTitle(), _record) + self.budget.getActiveTitle(), _record, _global_row_path) cell_renderer.set_property('text', _price) elif column is self.__amount_column: _parent_code = self.budget.getCode(self.__active_path_record) @@ -2639,10 +3008,10 @@ else: cell_renderer.set_property("pixbuf",self.__material_icon) if self.__treeview.get_cursor() == (_row_path,column): - cell_renderer.set_property('cell-background-gdk', - gtk.gdk.color_parse(globalVars.color["ACTIVE"])) + cell_renderer.set_property('cell-background', + globalVars.color["ACTIVE"]) else: - cell_renderer.set_property('cell-background-gdk', + cell_renderer.set_property('cell-background', lcolor[_number % 2]) def _showParentRecord(self, column): @@ -2656,15 +3025,16 @@ if len(self.__active_path_record) == 1: # The active record is the root record # This avoid to move the cursor to the clicked column - self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) + if isinstance(self.__cursor[0],Gtk.TreePath): + self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) else: _path_record = self.__active_path_record[:-1] _parent = self.__active_path_record[-1] self.__active_path_record = _path_record self._setColumnsHeaders() self._setListstoreValues(self.__active_path_record) - arg = ( _path_record ) - _page = self.__page() + arg = _path_record + _page = self.__wr_page() _page.propagateMessageFrom("change_active", self.__pane_path, arg) self.__treeview.set_cursor(_parent, self.__cursor[1]) self.__cursor = self.__treeview.get_cursor() @@ -2702,16 +3072,17 @@ _model = treeview.get_model() _iter = _model.get_iter(treeview_path) _code = _model.get_value(_iter, 0).code - #_code = _model.get_value(_iter, 4) - _path_record = self.__active_path_record + treeview_path + _path_record = self.__active_path_record + for _indice in treeview_path.get_indices(): + _path_record = _path_record + (_indice,) if self.__budget.hasPath(_path_record): # if this record path is valid self.__active_path_record = _path_record self._setColumnsHeaders() self._setListstoreValues(self.__active_path_record) self.__treeview.set_cursor((0,)) - _arg = ( _path_record ) - _page = self.__page() + _arg = _path_record + _page = self.__wr_page() _page.propagateMessageFrom("change_active", self.__pane_path, _arg ) @@ -2745,7 +3116,7 @@ def _getWidget(self): """_getWidget() - return the main widget (gtk.ScrolledWindow) + return the main widget (Gtk.ScrolledWindow) """ return self.__scrolled_window @@ -2763,19 +3134,19 @@ """ self.__pane_path = pane_path - def _getPage(self): + def _getWrPage(self): """_getPage() return the Page """ - return self.__page - - def _setPage(self,page): - """_setPage() - - set the Page - """ - self.__page = page + return self.__wr_page + + def _setWrPage(self,wr_page): + """_setWrPage() + + set the wr_Page + """ + self.__wr_page = wr_page def _getBudget(self): """_getBudget() @@ -2795,7 +3166,7 @@ "Pane configuration list") pane_path = property(_getPanePath, _setPanePath, None, "path that identifie the item in the page notebook") - page = property(_getPage, _setPage, None, + wr_page = property(_getWrPage, _setWrPage, None, "weak reference from Page instance which creates this class") budget = property(_getBudget, None, None, "Budget object") @@ -2809,7 +3180,7 @@ Description: Class to show a Measure List Constructor: - Measure(budget, page, pane_path, path_record=(0,) + Measure(budget, page, pane_path, path_record=None) budget: budget showed ("base.Budget" object) page: weak reference from Page instance which creates this class pane_path: tuple that represents the path of the List in the Page @@ -2820,9 +3191,9 @@ +-- DecompositionList Atributes: budget: Read. Budget to show, base.obra instance. - widget: Read. Window that contains the table, gtk.ScrolledWindow + widget: Read. Window that contains the table, Gtk.ScrolledWindow pane_path: Read-Write. Pane page identifier - page: Read-Write. weak reference from Page instance which creates + wr_page: Read-Write. weak reference from Page instance which creates this class active_path_record: Read. Path of the active record in the budget Methods: @@ -2833,7 +3204,7 @@ """__init__(budget, page, pane_path, path_record=None) budget: budget: budget showed ("base.Budget" object) - page: weak reference from Page instance which creates this class + wr_page: weak reference from Page instance which creates this class pane_path: tuple that represents the path of the List in the Page path_record: path of the active record in the budget @@ -2842,29 +3213,29 @@ self.__pane_path: tuple that represents the path of the List in the Page self.__active_path_record: path of the active record in the budget self.__liststore: list model which store the list data - (gtk.ListStore object) + (Gtk.ListStore object) self.__treeview: widget to display decomposition lists - (gtk.TreeView) + (Gtk.TreeView) self.__scrolled_window: widget to scroll the treeview - gtk.ScrolledWindow() + Gtk.ScrolledWindow() self.__chapter_background_colors: The background colors of the Code column cells when there is a chapter record - as a list of gtk.gdk.Color objects [even cell, uneven cell] - self.__index_column: Index column (gtk.TreeViewColumn object) - self.__linetype_column: Linetype column (gtk.TreeViewColumn object) - self.__comment_column: Comment column (gtk.TreeViewColumn) - self.__unit_column: Unit column (gtk.TreeViewColumn) - self.__length_column: Legth column (gtk.TreeViewColumn) - self.__width_column: With column (gtk.TreeViewColumn) - self.__height_column: Height column (gtk.TreeViewColumn) - self.__formula_column: Formula column (gtk.TreeViewColumn) - self.__parcial_column: Parcial column (gtk.TreeViewColumn) - self.__subtotal_column: Subtotal column (gtk.TreeViewColumn) - self.__end_column: End empty column (gtk.TreeViewColumn - self.__calculatedline_icon: gtk.gdk.pixbuf - self.__normalline_icon: gtk.gdk.pixbuf - self.__parcialline_icon: gtk.gdk.pixbuf - self.__acumulatedline_icon: gtk.gdk.pixbuf + as a list of color [even cell, uneven cell] + self.__index_column: Index column (Gtk.TreeViewColumn object) + self.__linetype_column: Linetype column (Gtk.TreeViewColumn object) + self.__comment_column: Comment column (Gtk.TreeViewColumn) + self.__unit_column: Unit column (Gtk.TreeViewColumn) + self.__length_column: Legth column (Gtk.TreeViewColumn) + self.__width_column: With column (Gtk.TreeViewColumn) + self.__height_column: Height column (Gtk.TreeViewColumn) + self.__formula_column: Formula column (Gtk.TreeViewColumn) + self.__parcial_column: Parcial column (Gtk.TreeViewColumn) + self.__subtotal_column: Subtotal column (Gtk.TreeViewColumn) + self.__end_column: End empty column (Gtk.TreeViewColumn + self.__calculatedline_icon: GdkPixbuf.Pixbuf + self.__normalline_icon: GdkPixbuf.Pixbuf + self.__parcialline_icon: GdkPixbuf.Pixbuf + self.__acumulatedline_icon: GdkPixbuf.Pixbuf self.__treeselection: active selection self.__selection_control: state of the selection control (True/False) self.__cursor: Situation of the cursor in the table @@ -2882,65 +3253,57 @@ if path_record is None: path_record = (0,) if not isinstance(budget, base.Budget): - raise ValueError, _("Argument must be a Budget object") + raise ValueError( _("Argument must be a Budget object") ) self.__budget = budget - self.__page = page + self.__wr_page = page self.__pane_path = pane_path if not isinstance(path_record, tuple): - print _("Record path must be a tuple") + print(_("Record path must be a tuple") ) path_record = (0,) self.__active_path_record = path_record # ListStore - self.__liststore = gtk.ListStore(object) + self.__liststore = Gtk.ListStore(object) self._setListstoreValues(self.__active_path_record) # Treeview - self.__treeview = gtk.TreeView(self.__liststore) + self.__treeview = Gtk.TreeView(self.__liststore) self.__treeview.set_enable_search(False) self.__treeview.set_reorderable(False) self.__treeview.set_headers_clickable(True) self.__treeview.show() # Scrolled_window - self.__scrolled_window = gtk.ScrolledWindow() - self.__scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) + self.__scrolled_window = Gtk.ScrolledWindow() + self.__scrolled_window.set_property("expand", True) # widget expand all space + self.__scrolled_window.set_policy(Gtk.PolicyType(1), + Gtk.PolicyType(1)) # 1 Automatic self.__scrolled_window.add(self.__treeview) # colors - _text_color = gtk.gdk.color_parse(globalVars.color["TEXT"]) - _calculated_text =gtk.gdk.color_parse(globalVars.color["CALCULATED-TEXT"]) + _text_color = globalVars.color["TEXT"] + _calculated_text = globalVars.color["CALCULATED-TEXT"] _background_color = [ - gtk.gdk.color_parse(globalVars.color["UNEVEN"]), - gtk.gdk.color_parse(globalVars.color["EVEN"])] + globalVars.color["UNEVEN"], + globalVars.color["EVEN"]] self.__chapter_background_colors = [ - gtk.gdk.color_parse(globalVars.color["CHAPTER-UNEVEN"]), - gtk.gdk.color_parse(globalVars.color["CHAPTER-EVEN"])] + globalVars.color["CHAPTER-UNEVEN"], + globalVars.color["CHAPTER-EVEN"]] super(Measure,self).__init__( [("INDEX",self._selectAll,42), - ("PIXBUF", self._passMethod, - gtk.Label("A"*4).size_request()[0] +10, + ("PIXBUF", self._passMethod, 40, _text_color, _background_color), - ("CALCULATEDTEXT", self._passMethod, - gtk.Label("A"*12).size_request()[0] +10, + ("CALCULATEDTEXT", self._passMethod, 128, _text_color, _background_color), - ("CALCULATED", self._passMethod, - gtk.Label("A"*5).size_request()[0] +10, + ("CALCULATED", self._passMethod, 55, _text_color, _background_color), - ("CALCULATED", self._passMethod, - gtk.Label("A"*7).size_request()[0] +10, + ("CALCULATED", self._passMethod, 70, _text_color, _background_color), - ("CALCULATED", self._passMethod, - gtk.Label("A"*7).size_request()[0] +10, + ("CALCULATED", self._passMethod, 70, _text_color, _background_color), - ("CALCULATED", self._passMethod, - gtk.Label("A"*7).size_request()[0] +10, + ("CALCULATED", self._passMethod, 70, _text_color, _background_color), - ("CALCULATEDTEXT", self._passMethod, - gtk.Label("A"*12).size_request()[0] +10, + ("CALCULATEDTEXT", self._passMethod, 120, _text_color, _background_color), - ("CALCULATED", self._passMethod, - gtk.Label("A"*7).size_request()[0] +10, + ("CALCULATED", self._passMethod, 70, _calculated_text, _background_color), - ("CALCULATED", self._passMethod, - gtk.Label("A"*7).size_request()[0] +10, + ("CALCULATED", self._passMethod, 70, _calculated_text, _background_color), ]) # Colums @@ -2959,13 +3322,13 @@ self.__treeview.append_column(self.__index_column) # Linetype column self.__treeview.append_column(self.__linetype_column) - self.__calculatedline_icon = gtk.gdk.pixbuf_new_from_file( + self.__calculatedline_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("CALCULATEDLINE-ICON")) - self.__normalline_icon = gtk.gdk.pixbuf_new_from_file( + self.__normalline_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("NORMALLINE-ICON") ) - self.__parcialline_icon = gtk.gdk.pixbuf_new_from_file( + self.__parcialline_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("PARCIALLINE-ICON") ) - self.__acumulatedline_icon = gtk.gdk.pixbuf_new_from_file( + self.__acumulatedline_icon = GdkPixbuf.Pixbuf.new_from_file( globalVars.getAppPath("ACUMULATEDLINE-ICON")) # Comment column self.__treeview.append_column(self.__comment_column) @@ -2993,104 +3356,19 @@ self.__treeview.connect("cursor-changed", self._treeviewCursorChanged) # control selection self.__treeselection = self.__treeview.get_selection() - self.__treeselection.set_mode(gtk.SELECTION_MULTIPLE) + self.__treeselection.set_mode(Gtk.SelectionMode(3)) # 3 MULTIPLE self.__treeselection.set_select_function(self._controlSelection) self.__selection_control = True - self.__treeview.set_cursor_on_cell((1,), self.columns[1], - self.columns[1].get_cell_renderers()[0],True) + if len(self.__liststore) > 0: + _tree_path = Gtk.TreePath.new_from_indices((1,)) + self.__treeview.set_cursor_on_cell(_tree_path, self.columns[1], + self.columns[1].get_cells()[0],True) self.__treeview.grab_focus() self.__cursor = self.__treeview.get_cursor() # Show self._setColumnsHeaders() self.__scrolled_window.show() - def _passMethod(self, column): - """_passMethod(column) - - column: the column that is clicked - Method connected to "clicked" event of many columns - Do nothing - """ - pass - - def _setListstoreValues(self, path_record): - """_setListstoreValues(path_record) - - path_record: Record path in the budget - Sets the liststore record values from a path record - """ - self.__liststore.clear() - _budget = self.__budget - if not _budget.hasPath(path_record): - raise ValueError, _("Invalid path") - else: - _measure = _budget.getMeasure(path_record) - if isinstance(_measure, base.Measure): - _lines = _measure.lines - for _line in _lines: - _values = [ _line ] - _treeiter = self.__liststore.append(_values) - else: - raise ValueError, utils.mapping(_("measure must be a Measure "\ - "object. Type: $1"), (type(_measure),)) - - def _setColumnsHeaders(self): - """_setColumnsHeaders() - - Sets the headers column values - """ - _measure = self.__budget.getMeasure(self.__active_path_record) - _DS = self.__budget.getDecimals("DS") - _total = _measure.measure - _total_str = ("%." + str(_DS) + "f" ) % _total - self.columns[1].set_title(_("Type")) # Σ parcial Σ total - self.columns[2].set_title(_("Comment")) - self.columns[3].set_title(_("N\n(a)")) - self.columns[4].set_title(_("Length\n(b)")) - self.columns[5].set_title(_("Width\n(c)")) - self.columns[6].set_title(_("Height\n(d)")) - self.columns[7].set_title(_("Formula")) - self.columns[8].set_title(_("Parcial\n[%s]" % _total_str)) - self.columns[9].set_title(_("Subtotal")) - - def _controlSelection(self, selection): - """_controlSelection(selection) - - selection: treeselection - - Method connected to set_selection_function() - This method is called before any node is selected or unselected, - giving some control over which nodes are selected. - The selection function should return TRUE if the state - of the node may be toggled, and FALSE if the state of the node should - be left unchanged. - - The selection only run if the user click in the index column, else - the previous selection is erased. - """ - _column = self.__treeview.get_cursor()[1] - if _column is self.columns[0] \ - or self.__selection_control == False: - return True - else: - self.__selection_control = False - self.__treeselection.unselect_all() - self.__selection_control = True - return False - - def _showMessageRecord(self, record_path): - """_showMessageRecord(record_path) - - record_path: the path of the record to show - Method connected to "change_active" message - Show the record especified in the "change_active" message - """ - _budget = self.__budget - self.__active_path_record = record_path - self._setColumnsHeaders() - self._setListstoreValues(self.__active_path_record) - self.__treeview.set_cursor((0,)) - def _treeviewCursorChanged(self, treeview): """_treeviewCursorChanged(treeview) @@ -3100,28 +3378,12 @@ Sets the new cursor position in self.__cursor, it is used to avoid unnecessary changes in cursor position. """ - event = gtk.get_current_event() + event = Gtk.get_current_event() (_cursor_path, _column) = treeview.get_cursor() - if event is None or event.type != gtk.gdk.BUTTON_RELEASE: + if event is None or event.type != Gdk.EventType(7): # 7 BUTTON_RELEASE if not _column is self.__index_column: self.__cursor = treeview.get_cursor() - def _moveCursor(self, treeview, step, count): - """moveCursor(treeview, step, count) - - treeview: the treeview that received the signal - step: the movement step size - count: the number of steps to take - - Method connected to "move-cursor" signal - The "move-cursor" signal is emitted when the user moves the cursor - using the Right, Left, Up or Down arrow keys or the Page Up, - Page Down, Home and End keys. - - Returns :TRUE if the signal was handled. - """ - return False - def _treeviewClickedEvent(self, widget, event): """_treeviewClickedEvent(widget, event) @@ -3164,13 +3426,255 @@ in the code column the event is estoped, else the event is propagated. """ (_cursor_path, _column) = self.__treeview.get_cursor() - if (event.keyval == gtk.keysyms.Right \ + if (event.keyval in [Gdk.keyval_from_name("Right"), + Gdk.keyval_from_name("KP_Right")] \ and _column == self.columns[-2]) \ - or (event.keyval == gtk.keysyms.Left \ + or (event.keyval in [Gdk.keyval_from_name("Left"), + Gdk.keyval_from_name("KP_Left")] \ and _column == self.columns[1]): return True return False + def _moveCursor(self, treeview, step, count): + """moveCursor(treeview, step, count) + + treeview: the treeview that received the signal + step: the movement step size + count: the number of steps to take + + Method connected to "move-cursor" signal + The "move-cursor" signal is emitted when the user moves the cursor + using the Right, Left, Up or Down arrow keys or the Page Up, + Page Down, Home and End keys. + + Returns :TRUE if the signal was handled. + """ + return False + + def _controlSelection(self, selection, model, path, path_currently_selected, *data): + """_controlSelection(selection) + + selection: treeselection + + Method connected to set_selection_function() + This method is called before any node is selected or unselected, + giving some control over which nodes are selected. + The selection function should return TRUE if the state + of the node may be toggled, and FALSE if the state of the node should + be left unchanged. + + The selection only run if the user click in the index column, else + the previous selection is erased. + """ + _column = self.__treeview.get_cursor()[1] + if _column is self.columns[0] \ + or self.__selection_control == False: + return True + else: + self.__selection_control = False + self.__treeselection.unselect_all() + self.__selection_control = True + return False + + def _selectAll(self, column): + """_selectAll(column) + + column: index column + Method connected to "clicked" event in the index column + If the user clickes in the index column header selecs or deselects + all rows + """ + (_model, _pathlist) = self.__treeselection.get_selected_rows() + # it avoid to set cursor in the index column + if isinstance(self.__cursor[0],Gtk.TreePath): + self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) + self.__selection_control = False + if len(_pathlist) == 0: + # select all + self.__treeselection.select_all() + else: + # unselect all + self.__treeselection.unselect_all() + self.__selection_control = True + + def _setColumnsHeaders(self): + """_setColumnsHeaders() + + Sets the headers column values + """ + _measure = self.__budget.getMeasure(self.__active_path_record) + _DS = self.__budget.getDecimals("DS") + _total = _measure.measure + _total_str = ("%." + str(abs(_DS)) + "f" ) % _total + self.columns[1].set_title(_("Type")) # Σ parcial Σ total + self.columns[2].set_title(_("Comment")) + self.columns[3].set_title(_("N\n(a)")) + self.columns[4].set_title(_("Length\n(b)")) + self.columns[5].set_title(_("Width\n(c)")) + self.columns[6].set_title(_("Height\n(d)")) + self.columns[7].set_title(_("Formula")) + self.columns[8].set_title(_("Parcial\n[%s]" % _total_str)) + self.columns[9].set_title(_("Subtotal")) + + def _setListstoreValues(self, path_record): + """_setListstoreValues(path_record) + + path_record: Record path in the budget + Sets the liststore record values from a path record + """ + self.__liststore.clear() + _budget = self.__budget + if not _budget.hasPath(path_record): + raise ValueError( _("Invalid path") ) + else: + _measure = _budget.getMeasure(path_record) + if isinstance(_measure, base.Measure): + _lines = _measure.lines + for _line in _lines: + _values = [ _line ] + _treeiter = self.__liststore.append(_values) + else: + raise ValueError( utils.mapping(_("measure must be a Measure "\ + "object. Type: $1"), (str(type(_measure)),)) ) + + def _colorCell(self, column, cell_renderer, tree_model, iter, lcolor): + """_colorCell(column, cell_renderer, tree_model, iter, lcolor) + + column: the Gtk.TreeViewColumn in the treeview + cell_renderer: a Gtk.CellRenderer + tree_model: the Gtk.TreeModel + iter: Gtk.TreeIter pointing at the row + lcolor: list with 2 colors for even and uneven record + + Method connected to "set_cell_data_func" of many column + The set_cell_data_func() method sets the data function (or method) + to use for the column Gtk.CellRenderer specified by cell_renderer. + This function (or method) is used instead of the standard attribute + mappings for setting the column values, and should set the attributes + of the cell renderer as appropriate. func may be None to remove the + current data function. The signature of func is: + -def celldatafunction(column, cell, model, iter, user_data) + -def celldatamethod(self, column, cell, model, iter, user_data) + where column is the Gtk.TreeViewColumn in the treeview, cell is the + Gtk.CellRenderer for column, model is the Gtk.TreeModel for the + treeview and iter is the Gtk.TreeIter pointing at the row. + + The method sets cell background color for all columns + and text for index and amount columns. + """ + _row_path = tree_model.get_path(iter) + _number = _row_path[-1] + if column is self.__index_column: + cell_renderer.set_property('text', str(_number + 1)) + self.__index_column.get_cells()[1].set_property( + 'cell-background', lcolor[_number % 2]) + elif column is self.__linetype_column: + _measure = tree_model[_row_path][0] + _type = _measure.lineType + if _type == 0: + cell_renderer.set_property("pixbuf",self.__normalline_icon) + elif _type == 1: + cell_renderer.set_property("pixbuf",self.__parcialline_icon) + elif _type == 2: + cell_renderer.set_property("pixbuf", + self.__acumulatedline_icon) + else: #elif _type == 3: + cell_renderer.set_property("pixbuf", + self.__calculatedline_icon) + elif column is self.__comment_column: + _measure = tree_model[_row_path][0] + _comment = str(_measure.comment) + cell_renderer.set_property('text', _comment) + elif column is self.__units_column: + _measure = tree_model[_row_path][0] + _units = _measure.units + if isinstance(_units, float): + _DN = self.__budget.getDecimals("DN") + _units = ("%." + str(abs(_DN)) + "f" ) % _units + cell_renderer.set_property('text', _units) + elif column is self.__length_column: + _measure = tree_model[_row_path][0] + _length = _measure.length + if isinstance(_length, float): + _DD = self.__budget.getDecimals("DD") + _length = ("%." + str(abs(_DD)) + "f" ) % _length + cell_renderer.set_property('text', _length) + elif column is self.__width_column: + _measure = tree_model[_row_path][0] + _width = _measure.width + if isinstance(_width, float): + _DD = self.__budget.getDecimals("DD") + _width = ("%." + str(abs(_DD)) + "f" ) % _width + cell_renderer.set_property('text', _width) + elif column is self.__height_column: + _measure = tree_model[_row_path][0] + _height = _measure.height + if isinstance(_height, float): + _DD = self.__budget.getDecimals("DD") + _height = ("%." + str(abs(_DD)) + "f" ) % _height + cell_renderer.set_property('text', _height) + elif column is self.__formula_column: + _measure = tree_model[_row_path][0] + _formula = _measure.formula + cell_renderer.set_property('text', _formula) + elif column is self.__parcial_column: + _measure_line = tree_model[_row_path][0] + _parcial = _measure_line.parcial + _type = _measure_line.lineType + if _type == 1 or _type == 2: + _parcial = "" + else: + if isinstance(_parcial, float): + _DS = self.__budget.getDecimals("DS") + _parcial = ("%." + str(abs(_DS)) + "f" ) % _parcial + cell_renderer.set_property('text', _parcial) + elif column is self.__subtotal_column: + _measure_line = tree_model[_row_path][0] + _type = _measure_line.lineType + if _type == 1 or _type == 2: + if _type == 1: + _color = globalVars.color["SUBTOTAL-PARCIAL"] + _subtotal = _measure_line.parcial_subtotal + else: #elif _type == 2: + _color = globalVars.color["SUBTOTAL"] + _subtotal = _measure_line.acumulated_subtotal + lcolor = [_color, _color] + if isinstance(_subtotal, float): + _DS = self.__budget.getDecimals("DS") + _subtotal= ("%." + str(abs(_DS)) + "f" ) % _subtotal + cell_renderer.set_property('text', _subtotal) + else: + cell_renderer.set_property('text', "") + + if self.__treeview.get_cursor() == (_row_path,column): + cell_renderer.set_property('cell-background', + globalVars.color["ACTIVE"]) + else: + cell_renderer.set_property('cell-background', + lcolor[_number % 2]) + + def _passMethod(self, column): + """_passMethod(column) + + column: the column that is clicked + Method connected to "clicked" event of many columns + Do nothing + """ + pass + + def _showMessageRecord(self, record_path): + """_showMessageRecord(record_path) + + record_path: the path of the record to show + Method connected to "change_active" message + Show the record especified in the "change_active" message + """ + _budget = self.__budget + self.__active_path_record = record_path + self._setColumnsHeaders() + self._setListstoreValues(self.__active_path_record) + self.__treeview.set_cursor((0,)) + def runMessage(self, message, pane_path, arg=None): """runMessage(message, pane_path, arg=None) @@ -3191,144 +3695,6 @@ elif message == "clear": self._clear() - def _selectAll(self, column): - """_selectAll(column) - - column: index column - Method connected to "clicked" event in the index column - If the user clickes in the index column header selecs or deselects - all rows - """ - (_model, _pathlist) = self.__treeselection.get_selected_rows() - # it avoid to set cursor in the index column - self.__treeview.set_cursor(self.__cursor[0], self.__cursor[1]) - self.__selection_control = False - if len(_pathlist) == 0: - # select all - self.__treeselection.select_all() - else: - # unselect all - self.__treeselection.unselect_all() - self.__selection_control = True - - def _colorCell(self, column, cell_renderer, tree_model, iter, lcolor): - """_colorCell(column, cell_renderer, tree_model, iter, lcolor) - - column: the gtk.TreeViewColumn in the treeview - cell_renderer: a gtk.CellRenderer - tree_model: the gtk.TreeModel - iter: gtk.TreeIter pointing at the row - lcolor: list with 2 gtk colors for even and uneven record - - Method connected to "set_cell_data_func" of many column - The set_cell_data_func() method sets the data function (or method) - to use for the column gtk.CellRenderer specified by cell_renderer. - This function (or method) is used instead of the standard attribute - mappings for setting the column values, and should set the attributes - of the cell renderer as appropriate. func may be None to remove the - current data function. The signature of func is: - -def celldatafunction(column, cell, model, iter, user_data) - -def celldatamethod(self, column, cell, model, iter, user_data) - where column is the gtk.TreeViewColumn in the treeview, cell is the - gtk.CellRenderer for column, model is the gtk.TreeModel for the - treeview and iter is the gtk.TreeIter pointing at the row. - - The method sets cell background color for all columns - and text for index and amount columns. - """ - _row_path = tree_model.get_path(iter) - _number = _row_path[-1] - if column is self.__index_column: - cell_renderer.set_property('text', str(_number + 1)) - self.__index_column.get_cell_renderers()[1].set_property( - 'cell-background-gdk', lcolor[_number % 2]) - elif column is self.__linetype_column: - _measure = tree_model[_row_path][0] - _type = _measure.lineType - if _type == 0: - cell_renderer.set_property("pixbuf",self.__normalline_icon) - elif _type == 1: - cell_renderer.set_property("pixbuf",self.__parcialline_icon) - elif _type == 2: - cell_renderer.set_property("pixbuf", - self.__acumulatedline_icon) - else: #elif _type == 3: - cell_renderer.set_property("pixbuf", - self.__calculatedline_icon) - - elif column is self.__comment_column: - _measure = tree_model[_row_path][0] - _comment = str(_measure.comment) - cell_renderer.set_property('text', _comment) - elif column is self.__units_column: - _measure = tree_model[_row_path][0] - _units = _measure.units - if isinstance(_units, float): - _DN = self.__budget.getDecimals("DN") - _units = ("%." + str(_DN) + "f" ) % _units - cell_renderer.set_property('text', _units) - elif column is self.__length_column: - _measure = tree_model[_row_path][0] - _length = _measure.length - if isinstance(_length, float): - _DD = self.__budget.getDecimals("DD") - _length = ("%." + str(_DD) + "f" ) % _length - cell_renderer.set_property('text', _length) - elif column is self.__width_column: - _measure = tree_model[_row_path][0] - _width = _measure.width - if isinstance(_width, float): - _DD = self.__budget.getDecimals("DD") - _width = ("%." + str(_DD) + "f" ) % _width - cell_renderer.set_property('text', _width) - elif column is self.__height_column: - _measure = tree_model[_row_path][0] - _height = _measure.height - if isinstance(_height, float): - _DD = self.__budget.getDecimals("DD") - _height = ("%." + str(_DD) + "f" ) % _height - cell_renderer.set_property('text', _height) - elif column is self.__formula_column: - _measure = tree_model[_row_path][0] - _formula = _measure.formula - cell_renderer.set_property('text', _formula) - elif column is self.__parcial_column: - _measure_line = tree_model[_row_path][0] - _parcial = _measure_line.parcial - _type = _measure_line.lineType - if _type == 1 or _type == 2: - _parcial = "" - else: - if isinstance(_parcial, float): - _DS = self.__budget.getDecimals("DS") - _parcial = ("%." + str(_DS) + "f" ) % _parcial - cell_renderer.set_property('text', _parcial) - elif column is self.__subtotal_column: - _measure_line = tree_model[_row_path][0] - _type = _measure_line.lineType - if _type == 1 or _type == 2: - if _type == 1: - _color = gtk.gdk.color_parse( - globalVars.color["SUBTOTAL-PARCIAL"]) - _subtotal = _measure_line.parcial_subtotal - else: #elif _type == 2: - _color = gtk.gdk.color_parse(globalVars.color["SUBTOTAL"]) - _subtotal = _measure_line.acumulated_subtotal - lcolor = [_color, _color] - if isinstance(_subtotal, float): - _DS = self.__budget.getDecimals("DS") - _subtotal= ("%." + str(_DS) + "f" ) % _subtotal - cell_renderer.set_property('text', _subtotal) - else: - cell_renderer.set_property('text', "") - - if self.__treeview.get_cursor() == (_row_path,column): - cell_renderer.set_property('cell-background-gdk', - gtk.gdk.color_parse(globalVars.color["ACTIVE"])) - else: - cell_renderer.set_property('cell-background-gdk', - lcolor[_number % 2]) - def _clear(self): """_clear() @@ -3339,7 +3705,7 @@ def _getWidget(self): """_getWidget() - return the main widget (gtk.ScrolledWindow) + return the main widget (Gtk.ScrolledWindow) """ return self.__scrolled_window @@ -3357,19 +3723,19 @@ """ self.__pane_path = pane_path - def _getPage(self): + def _getWrPage(self): """_getPage() return the Page """ - return self.__page - - def _setPage(self,page): + return self.__wr_page + + def _setWrPage(self,wr_page): """_setPage() set the Page """ - self.__page = page + self.__wr_page = wr_page def _getBudget(self): """_getBudget() @@ -3389,7 +3755,7 @@ "Pane configuration list") pane_path = property(_getPanePath, _setPanePath, None, "Path that identifies the item in the page notebook") - page = property(_getPage, _setPage, None, + wr_page = property(_getWrPage, _setWrPage, None, "Weak reference from Page instance which creates this class") budget = property(_getBudget, None, None, "Budget object") @@ -3403,39 +3769,42 @@ Description: Class to show a description text of a record in a pane Constructor: - Description(budget, code) - budget: base.Budget object - code: record code + budget: budget showed ("base.Budget" object) + page: weak reference from Page instance which creates this class + pane_path: tuple that represents the view path in the Page + path_record: the record path that must be showed + Returns the newly created DecompositionList instance Ancestry: +-- object +-- Description Atributes: - widget: the main widget (gtk.ScrolledWindow object) - pane_path: the tuple that identifies the pane in the notebook page - budget: The budget (base.obra objetc) - active_path_record: The active path record + budget: Read. Budget to show, base.obra object. + widget: the main widget (Gtk.ScrolledWindow object) + pane_path: Read-Write. Pane page identifier + wr_page: Read-Write. weak ref from Page object which creates this class + active_path_record: Read. Active path record Methods: runMessage """ - # TODO: make standar: "DecompositonList and Description" - - def __init__(self, budget, page, pane_path, path_record=None): + # TODO: make standard: "DecompositonList and Description" + + def __init__(self, budget, wr_page, pane_path, path_record=None): """__init__(budget, page, pane_path, path_record=None) budget: the budget (base.obra object) - page: weak reference from Page instance which creates this class + wr_page: weak reference from Page instance which creates this class pane_path: the path position of the description in the page path_record: the path of the active record self.__budget: the budget (base.obra object) - self.__page: weak reference from Page instance which creates this class + self.__wr_page: weak reference from Page instance which creates this class self.__pane_path: the path position of the description in the page self.__active_path_recordthe path of the active record self.__textbuffer: The textbuffer of the textview that contain the record text. - self.__label: The gtk.label with the title of the pane - self.__widget: the main pane widget, a gtk.ScrolledWindow() + self.__label: The Gtk.label with the title of the pane + self.__widget: the main pane widget, a Gtk.ScrolledWindow() Creates an shows the scroledwindow that contain the description text of the record to be showed in a pane. @@ -3443,37 +3812,38 @@ if path_record is None: path_record = (0,) self.__budget = budget - self.__page = page + self.__wr_page = wr_page self.__pane_path = pane_path self.__active_path_record = path_record _budget = budget _text = _budget.getRecord(self.__budget.getCode( self.__active_path_record)).text - _scrollwindow = gtk.ScrolledWindow() - _scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) - _textview = gtk.TextView() - _textview.set_wrap_mode(gtk.WRAP_WORD) + _scrollwindow = Gtk.ScrolledWindow() + _scrollwindow.set_property("expand", True) # widget expand all space + _scrollwindow.set_policy(Gtk.PolicyType(1), + Gtk.PolicyType(1)) # 1 Automatic + _scrollwindow.set_shadow_type(1) # NONE 0, IN 1, OUT 2, ETCHED_IN 3,ETCHED_OUT 4 + _textview = Gtk.TextView() + _textview.set_wrap_mode(2) # 2 Word + _textview.set_hexpand(True) + _textview.set_vexpand(True) self.__textbuffer = _textview.get_buffer() self.__textbuffer.set_text(_text) _textview.show() - _hbox = gtk.HBox() - _hbox.pack_start(_textview, True, True, 5) - _hbox.show() - _vbox = gtk.VBox() - self.__label = gtk.Label(utils.mapping(_("Description text of the "\ - "record $1"), (self.__budget.getCode( - self.__active_path_record),))) + _vbox = Gtk.Grid() + _vbox.set_orientation(Gtk.Orientation(1)) # 1 Vertical + self.__label = Gtk.Label(utils.mapping(_("Description text of the "\ + "record $1"), (str(self.__budget.getCode( + self.__active_path_record)),))) self.__label.set_alignment(0, 0) self.__label.show() - _vbox.pack_start(self.__label, False, False, 5) - _vbox.pack_start(_hbox, True, True, 5) + _vbox.add(self.__label) + _vbox.add(_textview) _vbox.show() - _scrollwindow.add_with_viewport(_vbox) + _scrollwindow.add(_vbox) _scrollwindow.show() self.__widget = _scrollwindow - def _setActivePathRecord(self, path_record): """_setActivePathRecord(path_record)) @@ -3484,7 +3854,7 @@ self.__active_path_record = path_record _code = _budget.getCode(self.__active_path_record) self.__label.set_text(utils.mapping(_("Description text of the record "\ - "$1"), (_code,))) + "$1"), (_code.decode("utf8"),))) _text = _budget.getRecord(_code).text self.__textbuffer.set_text(_text) @@ -3522,7 +3892,7 @@ def _getWidget(self): """_getWidget() - return the main widget (gtk.ScrolledWindow) + return the main widget (Gtk.ScrolledWindow) """ return self.__widget @@ -3540,19 +3910,19 @@ """ self.__pane_path = pane_path - def _getPage(self): - """_getPage() + def _getWrPage(self): + """_getWrPage() return the weak reference from Page instance """ - return self.__page - - def _setPage(self, page): - """_setPage() + return self.__wr_page + + def _setWrPage(self, wr_page): + """_setWrPage() set the weak reference from Page instance """ - self.__page = page + self.__wr_page = wr_page def _getBudget(self): """_getBudget() @@ -3571,8 +3941,8 @@ pane_path = property(_getPanePath, _setPanePath, None, "Path that identifie the item in the page notebook") widget = property(_getWidget, None, None, - "The main widget (gtk.ScrolledWindow)") - page = property(_getPage, _setPage, None, + "The main widget (Gtk.ScrolledWindow)") + wr_page = property(_getWrPage, _setWrPage, None, "Weak reference from Page instance which creates this class") budget = property(_getBudget, None, None, "Budget object") @@ -3593,28 +3963,28 @@ +-- object +-- Sheet Atributes: - widget: the main widget (gtk.VBox() object) + budget: The budget (base.obra objetc) + widget: the main widget (Gtk.Grid object) pane_path: the tuple that identifies the pane in the notebook page - page: weak reference from Page instance which creates this class - budget: The budget (base.obra objetc) + wr_page: weak reference from Page instance which creates this class active_path_record: The active path record Methods: runMessage """ - def __init__(self, budget, page, pane_path, path_record=None): - """__init__(budget, page, pane_path, path_record=None) + def __init__(self, budget, wr_page, pane_path, path_record=None): + """__init__(budget, wr_page, pane_path, path_record=None) budget: the budget (base.obra object) - page: weak reference from Page instance which creates this class + wr_page: weak reference from Page instance which creates this class pane_path: the path position of the description in the page path_record: the path of the active record self.__budget: the budget (base.obra object) - self.__page: weak reference from Page instance which creates this class + self.__wr_page: weak reference from Page instance which creates this class self.__pane_path: the path position of the description in the page self.__active_path_record: the path of the active record - self.__label: The gtk.label with the title of the pane + self.__label: The Gtk.label with the title of the pane self.__field_liststore: the field liststore self.__field_treeview: the field treeview self.__field_selection: the field selected in field treview @@ -3623,7 +3993,7 @@ self.__section_selection: the section selected in the section treeview self.__textbuffer: The textbuffer of the textview that contain the record text. - self.__widget: main widget, a gtk.VBox() + self.__widget: main widget, a Gtk.Grid() Creates an shows the scroledwindow that contain the description text of the record to be showed in a pane. @@ -3631,89 +4001,101 @@ if path_record is None: path_record = (0,) self.__budget = budget - self.__page = page + self.__wr_page = wr_page self.__pane_path = pane_path self.__active_path_record = path_record _budget = budget - _main_box = gtk.VBox() - self.__label = gtk.Label(utils.mapping(_("Sheet of Conditions of the "\ + _main_box = Gtk.Grid() + _main_box.set_orientation(Gtk.Orientation(1)) # 1 Vertical + self.__label = Gtk.Label(utils.mapping(_("Sheet of Conditions of the "\ "record $1"), (self.__budget.getCode( self.__active_path_record),))) - self.__label.set_alignment(0, 0) + self.__label.set_xalign(0) + self.__label.set_yalign(0) self.__label.show() - _frame = gtk.Frame() - _frame.set_shadow_type(gtk.SHADOW_IN) - _frame_box = gtk.VBox() - _list_box = gtk.HBox() - self.__field_liststore = gtk.ListStore(str, str) - self.__field_treeview = gtk.TreeView(self.__field_liststore) + _frame = Gtk.Frame() + _frame.set_shadow_type(Gtk.ShadowType(1)) # 1 In + _frame_box = Gtk.Grid() + _frame_box.set_orientation(Gtk.Orientation(1)) # 1 Vertical + _list_box = Gtk.Grid() + _list_box.set_orientation(Gtk.Orientation(0)) # 0 Horizontal + self.__field_liststore = Gtk.ListStore(str, str) + self.__field_treeview = Gtk.TreeView(self.__field_liststore) _field_treeselection = self.__field_treeview.get_selection() - _field_treeselection.set_mode(gtk.SELECTION_SINGLE) + _field_treeselection.set_mode(Gtk.SelectionMode(1)) # 1 SINGLE self.__field_selection = None _field_treeselection.set_select_function( self._field_controlSelection) self.__field_treeview.show() - _fieldcode_cell = gtk.CellRendererText() - _field_column = gtk.TreeViewColumn(_("Field")) + _fieldcode_cell = Gtk.CellRendererText() + _field_column = Gtk.TreeViewColumn(_("Field")) _field_column.pack_start(_fieldcode_cell, False) - _field_cell = gtk.CellRendererText() + _field_cell = Gtk.CellRendererText() _field_column.pack_end(_field_cell, True) _field_column.add_attribute(_fieldcode_cell, "text", 0) _field_column.add_attribute(_field_cell, "text", 1) self.__field_treeview.append_column(_field_column) - _field_scrollwindow = gtk.ScrolledWindow() - _field_scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) + _field_scrollwindow = Gtk.ScrolledWindow() + _field_scrollwindow.set_policy(Gtk.PolicyType(1), + Gtk.PolicyType(1)) # 1 Automatic + _field_scrollwindow.set_property("hexpand", True) # widget expand all space _field_scrollwindow.add(self.__field_treeview) + _field_scrollwindow.set_size_request(-1, 80) _field_scrollwindow.show() - self.__section_liststore = gtk.ListStore(str, str) - self.__section_treeview = gtk.TreeView(self.__section_liststore) + self.__section_liststore = Gtk.ListStore(str, str) + self.__section_treeview = Gtk.TreeView(self.__section_liststore) _section_treeselection = self.__section_treeview.get_selection() - _section_treeselection.set_mode(gtk.SELECTION_SINGLE) + _section_treeselection.set_mode(Gtk.SelectionMode(1)) # 1 SINGLE self.__section_selection = None _section_treeselection.set_select_function( self._section_controlSelection) self.__section_treeview.show() - _sectioncode_cell = gtk.CellRendererText() - _section_column = gtk.TreeViewColumn(_("Section")) + _sectioncode_cell = Gtk.CellRendererText() + _section_column = Gtk.TreeViewColumn(_("Section")) _section_column.pack_start(_sectioncode_cell, False) _section_column.add_attribute(_sectioncode_cell, "text", 0) - _section_cell = gtk.CellRendererText() + _section_cell = Gtk.CellRendererText() _section_column.pack_end(_section_cell, True) _section_column.add_attribute(_section_cell, "text", 1) self.__section_treeview.append_column(_section_column) - _section_scrollwindow = gtk.ScrolledWindow() - _section_scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) + _section_scrollwindow = Gtk.ScrolledWindow() + _section_scrollwindow.set_policy(Gtk.PolicyType(1), + Gtk.PolicyType(1)) # 1 Automatic + _section_scrollwindow.set_property("hexpand", True) # widget expand all space + _section_scrollwindow.set_size_request(-1, 90) _section_scrollwindow.add(self.__section_treeview) _section_scrollwindow.show() - _list_box.pack_start(_field_scrollwindow, True, True, 5) - _list_box.pack_start(_section_scrollwindow, True, True, 5) + _list_box.add(_field_scrollwindow) + _list_box.add(_section_scrollwindow) _list_box.show() - _scrollwindow = gtk.ScrolledWindow() - _scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) - _textview = gtk.TextView() - _textview.set_wrap_mode(gtk.WRAP_WORD) + _scrollwindow = Gtk.ScrolledWindow() + _scrollwindow.set_policy(Gtk.PolicyType(1), + Gtk.PolicyType(1)) # 1 Automatic + _scrollwindow.set_property("expand", True) # widget expand all space + _textview = Gtk.TextView() + _textview.set_wrap_mode(2) # 2 Word + _textview.set_property("expand", True) # widget expand all space self.__textbuffer = _textview.get_buffer() _textview.show() - _hbox = gtk.HBox() - _hbox.pack_start(_textview, True, True, 5) + _hbox = Gtk.Grid() + _hbox.set_orientation(Gtk.Orientation(0)) # 0 Horizontal + _hbox.add(_textview) _hbox.show() - _frame_box.pack_start(self.__label, False, False, 5) - _frame_box.pack_start(_list_box, False, False, 5) + _frame_box.add(self.__label) + _frame_box.add(_list_box) _frame_box.show() _frame.add(_frame_box) _frame.show() - _main_box.pack_start(_frame, False) - _vbox = gtk.VBox() - _vbox.pack_start(_hbox, True, True, 5) + _main_box.add(_frame) + _vbox = Gtk.Grid() + _vbox.set_orientation(Gtk.Orientation(1)) # 1 Vertical + _vbox.add(_hbox) _vbox.show() - _main_box.pack_start(_scrollwindow, True, True, 5) + _main_box.add(_scrollwindow) _main_box.show() - _scrollwindow.add_with_viewport(_vbox) + _scrollwindow.add(_vbox) _scrollwindow.show() self.__widget = _main_box self._setFields() @@ -3768,10 +4150,13 @@ else: self.__textbuffer.set_text("") - def _field_controlSelection(self, selection): - """_controlSelection(selection) + def _field_controlSelection(self, selection, model, path, + path_currently_selected, *data): + """_controlSelection(selection, model, path, + path_currently_selected, *data) selection: treeselection + path: selected path Method connected to set_selection_function() in field treeview This method is called before any node is selected or unselected, @@ -3783,15 +4168,18 @@ When a user select a row in the field treeview the section treeview is reloaded to show the sections of this field and already the text sheet. """ - _treeiter = self.__field_liststore.get_iter(selection) + _treeiter = self.__field_liststore.get_iter(path) self.__field_selection = self.__field_liststore.get_value(_treeiter, 0) self._setSection() return True - def _section_controlSelection(self, selection): - """_section_controlSelection(selection) + def _section_controlSelection(self, selection, model, path, + path_currently_selected, *data): + """_section_controlSelection(selection, model, + path, path_currently_selected, *data) selection: treeselection + path: selected path Method connected to set_selection_function() in sector treeview This method is called before any node is selected or unselected, @@ -3803,7 +4191,7 @@ When a user select a row in the field treeview the text sheet for this section in showed """ - _treeiter = self.__section_liststore.get_iter(selection) + _treeiter = self.__section_liststore.get_iter(path) self.__section_selection = self.__section_liststore.get_value(_treeiter, 0) self._setText() return True @@ -3851,7 +4239,7 @@ Deletes all the instance atributes """ - del self.__page + del self.__wr_page del self.__widget del self.__pane_path del self.__budget @@ -3870,7 +4258,7 @@ def _getWidget(self): """_getWidget() - return the main widget (gtk.ScrolledWindow) + return the main widget (Gtk.ScrolledWindow) """ return self.__widget @@ -3888,19 +4276,19 @@ """ self.__pane_path = pane_path - def _getPage(self): - """_getPage() + def _getWrPage(self): + """_getWrPage() return the weak reference from Page instance """ - return self.__page - - def _setPage(self, page): - """_setPage() + return self.__wr_page + + def _setWrPage(self, wr_page): + """_setWrPage() set the weak reference from Page instance """ - self.__page = page + self.__wr_page = wr_page def _getBudget(self): """_getBudget() @@ -3920,7 +4308,7 @@ "Path that identifie the item in the page notebook") widget = property(_getWidget, None, None, "Lista de configuracion de vistas") - page = property(_getPage, _setPage, None, + wr_page = property(_getWrPage, _setWrPage, None, "Weak reference from Page instance which creates this class") budget = property(_getBudget, None, None, "Budget object") @@ -3934,38 +4322,39 @@ Description: Class to show the file icons of a record in a pane Constructor: - Description(budget, page, pane_path, path_record=(0,)) + Description(budget, page, pane_path, path_record=None) budget: the budget (base.obra object) - page: weak reference from Page instance which creates this class + wr_page: weak reference from Page instance which creates this class pane_path: the path position of the description in the page path_record: the path of the active record Ancestry: +-- object +-- FileView Atributes: - widget: the main widget (gtk.ScrolledWindow object) + widget: the main widget (Gtk.ScrolledWindow object) pane_path: the tuple that identifies the pane in the notebook page - budget: The budget (base.obra objetc) - active_code: The active code of the record + budget: The budget (base.obra object) + active_path_record: Read. + wr_page: Read-Write. weak reference from Page instance which creates this class Methods: runMessage """ - def __init__(self, budget, page, pane_path, path_record=None): + def __init__(self, budget, wr_page, pane_path, path_record=None): """__init__(budget, page, pane_path, path_record=None) budget: the budget (base.obra object) - page: weak reference from Page instance which creates this class + wr_page: weak reference from Page instance which creates this class pane_path: the path position of the description in the page path_record: the path of the active record self.__budget: the budget (base.obra object) - self.__page: weak reference from Page instance which creates this class + self.__wr_page: weak reference from Page instance which creates this class self.__pane_path: the path position of the description in the page self.__active_path_record: the path of the active record self.__active_code: the code of the active record self.__icon_box: the box that contains the icon - self.__widget: main widget, a gtk.ScrolledWindow + self.__widget: main widget, a Gtk.ScrolledWindow Creates an shows the scroledwindow that contain icon files of the record to be showed in a pane. @@ -3973,7 +4362,7 @@ if path_record is None: path_record = (0,) self.__budget = budget - self.__page = page + self.__wr_page = wr_page self.__pane_path = pane_path self.__active_path_record = path_record self.__active_code = budget.getCode(self.__active_path_record) @@ -3982,11 +4371,10 @@ self.__active_path_record)) self.__icon_box = self._getIconBox(_record) - _scrollwindow = gtk.ScrolledWindow() - _scrollwindow.set_policy(gtk.POLICY_ALWAYS, - gtk.POLICY_NEVER) + _scrollwindow = Gtk.ScrolledWindow() + _scrollwindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.__icon_box.show() - _scrollwindow.add_with_viewport(self.__icon_box) + _scrollwindow.add(self.__icon_box) _scrollwindow.show() self.__widget = _scrollwindow @@ -3997,75 +4385,138 @@ Creates and returns the box whith te icon files of the active record. """ - ## TODO: add others filetypes: avi, pdf, ppt... _files = record.getFiles() - _hbox = gtk.HBox() - _frame = gtk.Frame() - _frame.set_shadow_type(gtk.SHADOW_IN) + _flowbox = Gtk.FlowBox() + _flowbox.set_valign(Gtk.Align.START) + _flowbox.set_max_children_per_line(30) + _flowbox.set_selection_mode(Gtk.SelectionMode.NONE) + _flowbox.set_property("expand", True) # widget expand all space for _file in _files: _path = os.path.dirname(self.__budget.filename) _file_path = os.path.join(_path, _file.name) - _filetype = utils.getFiletype(_file_path) - _box = gtk.VBox() - if _filetype == "image": - _event_box = gtk.EventBox() - try: - _image_pixbuf = gtk.gdk.pixbuf_new_from_file(_file_path) - _image_pixbuf = _image_pixbuf.scale_simple(64, 64, - gtk.gdk.INTERP_BILINEAR) - except: - _image_pixbuf = gtk.gdk.pixbuf_new_from_file( - globalVars.getAppPath("IMAGE-ICON")) - _image_pixbuf = _image_pixbuf.scale_simple(64, 64, - gtk.gdk.INTERP_BILINEAR) - _image_icon = gtk.Image() - _image_icon.set_from_pixbuf(_image_pixbuf) - _image_icon.show() - _event_box.add(_image_icon) - _box.pack_start(_event_box, False, False, 5) - _event_box.connect("button-press-event", self._launchFile, - "image", _file_path) + _box = Gtk.Grid() + _box.set_orientation(Gtk.Orientation(1)) # 1 Vertical + if os.path.exists(_file_path): + _filetype = utils.getFiletype(_file_path) + _event_box = Gtk.LinkButton() + _file_icon = Gtk.Image() + # "image", "wmf", "dxf", "pdf" , "video", + # "office-document", "office-presentation", "office-spreadsheet", + # "html", "rtf", "txt", "" + # icon + if _filetype in ["image", "wmf"]: + try: + _image_pixbuf = GdkPixbuf.Pixbuf.new_from_file(_file_path) + _image_pixbuf = _image_pixbuf.scale_simple(64, 64, + GdkPixbuf.InterpType(2)) # 2 BILINEAR + except: + _image_pixbuf = GdkPixbuf.Pixbuf.new_from_file( + globalVars.getAppPath("IMAGE-ICON")) + _image_pixbuf = _image_pixbuf.scale_simple(64, 64, + GdkPixbuf.InterpType(2)) # 2 BILINEAR + _file_icon.set_from_pixbuf(_image_pixbuf) + _event_box.connect("activate-link", self._launchFile, + _filetype, _file_path) + elif _filetype == "dxf": + _dxf_pixbuf = GdkPixbuf.Pixbuf.new_from_file( + globalVars.getAppPath("DXF-ICON")) + _dxf_pixbuf = _dxf_pixbuf.scale_simple(64, 64, + GdkPixbuf.InterpType(2)) # 2 BILINEAR + _file_icon.set_from_pixbuf(_dxf_pixbuf) + _event_box.connect("activate-link", self._launchFile, + "dxf", _file_path) + elif _filetype == "pdf": + _pdf_pixbuf = GdkPixbuf.Pixbuf.new_from_file( + globalVars.getAppPath("PDF-ICON")) + _pdf_pixbuf = _pdf_pixbuf.scale_simple(64, 64, + GdkPixbuf.InterpType(2)) # 2 BILINEAR + _file_icon.set_from_pixbuf(_pdf_pixbuf) + _event_box.connect("activate-link", self._launchFile, + "pdf", _file_path) + elif _filetype == "video": + _video_pixbuf = Gtk.IconTheme.get_default().load_icon( + "video-x-generic", 64, 0) + _file_icon.set_from_pixbuf(_video_pixbuf) + _event_box.connect("activate-link", self._launchFile, + "video", _file_path) + elif _filetype == "office-document": + _document_pixbuf = Gtk.IconTheme.get_default().load_icon( + "x-office-document", 64, 0) + _file_icon.set_from_pixbuf(_document_pixbuf) + _event_box.connect("activate-link", self._launchFile, + "office-document", _file_path) + elif _filetype == "office-presentation": + _presentation_pixbuf = Gtk.IconTheme.get_default().load_icon( + "x-office-presentation", 64, 0) + _file_icon.set_from_pixbuf(_presentation_pixbuf) + _event_box.connect("activate-link", self._launchFile, + "office-presentation", _file_path) + elif _filetype == "office-spreadsheet": + _spreadsheet_pixbuf = Gtk.IconTheme.get_default().load_icon( + "x-office-spreadsheet", 64, 0) + _file_icon.set_from_pixbuf(_spreadsheet_pixbuf) + _event_box.connect("activate-link", self._launchFile, + "office-spreadsheet", _file_path) + elif _filetype == "html": + _html_pixbuf = Gtk.IconTheme.get_default().load_icon( + "text-html", 64, 0) + _file_icon.set_from_pixbuf(_html_pixbuf) + _event_box.connect("activate-link", self._launchFile, + "html", _file_path) + elif _filetype == "rtf": + _rtf_pixbuf = Gtk.IconTheme.get_default().load_icon( + "text-x-generic", 64, 0) + _file_icon.set_from_pixbuf(_rtf_pixbuf) + _event_box.connect("activate-link", self._launchFile, + "rtf", _file_path) + elif _filetype == "txt": + _txt_pixbuf = Gtk.IconTheme.get_default().load_icon( + "text-x-generic", 64, 0) + _file_icon.set_from_pixbuf(_txt_pixbuf) + _event_box.connect("activate-link", self._launchFile, + "txt", _file_path) + else: + _missing_pixbuf = Gtk.IconTheme.get_default().load_icon( + "image-missing", 64, 0) + _file_icon.set_from_pixbuf(_missing_pixbuf) + # Is secure open no detected filetype? + #_event_box.connect("activate-link", self._launchFile, + # "", _file_path) + _event_box = Gtk.EventBox() + _event_box.add(_file_icon) + _event_box.props.margin = 5 + _box.add(_event_box) + _file_icon.show() _event_box.show() - - elif _filetype == "dxf": - _event_box = gtk.EventBox() - _dxf_icon = gtk.Image() - _dxf_pixbuf = gtk.gdk.pixbuf_new_from_file( - globalVars.getAppPath("DXF-ICON")) - _dxf_pixbuf = _dxf_pixbuf.scale_simple(64, 64, - gtk.gdk.INTERP_BILINEAR) - _dxf_icon.set_from_pixbuf(_dxf_pixbuf) - _dxf_icon.show() - _event_box.add(_dxf_icon) - _box.pack_start(_event_box, False, False, 5) - _event_box.connect("button-press-event", self._launchFile, - "dxf", _file_path) - _event_box.show() - _label_event_box = gtk.EventBox() - _label = gtk.Label(_file.name) + # label + _label_event_box = Gtk.EventBox() + _label = Gtk.Label(_file.name) _label_event_box.add(_label) _label_event_box.show() _label.show() - _box.pack_start(_label_event_box, False, False, 5) + _label_event_box.props.margin = 5 + _box.add(_label_event_box) _box.show() - _hbox.pack_start(_box, False, False, 5) - _hbox.show() - _frame.add(_hbox) - return _frame - - def _launchFile(self, widget, event, kind, file_path): + _box.props.margin = 5 + _flowbox.add(_box) + _flowbox.show() + #_scrolled.show() + return _flowbox + + def _launchFile(self, widget, kind, file_path): """_launchFile(widget, event, kind, file_path) widget: the widget that emit the signal - event: the event that emit the signal king: kind of file file_path: the path file to be launch - Launch the file if a double click emit the signal. - Method connected to "button-press-event" signal in images event box - """ - if event.type is gtk.gdk._2BUTTON_PRESS: - openwith.launch_file(kind, file_path) + Launch the file if a click emit the signal. + Method connected to "activate-link" signal in images botton link + Return True: stops propagate event and avoids to raise an error + when opening an empty uri. + """ + openwith.launch_file(kind, file_path) + return True def _setActivePathRecord(self, path_record): """_setActivePathRecord(path_record)) @@ -4078,7 +4529,7 @@ _code = _budget.getCode(self.__active_path_record) _record = self.__budget.getRecord(_code) self.__icon_box.destroy() - self.__icon_box = self._getIconBox(_record) + self.__icon_box = self._getIconBox(_record) self.__icon_box.show() self.__widget.add_with_viewport(self.__icon_box) @@ -4114,7 +4565,7 @@ def _getWidget(self): """_getWidget() - return the main widget (gtk.ScrolledWindow) + return the main widget (Gtk.ScrolledWindow) """ return self.__widget @@ -4132,19 +4583,19 @@ """ self.__pane_path = pane_path - def _getPage(self): - """_getPage() + def _getWrPage(self): + """_getWrPage() return the weak reference from Page instance """ - return self.__page - - def _setPage(self, page): + return self.__wr_page + + def _setWrPage(self, wr_page): """setPage() set the weak reference from Page instance """ - self.__page = page + self.__wr_page = wr_page def _getBudget(self): """getBudget() @@ -4163,8 +4614,8 @@ pane_path = property(_getPanePath, _setPanePath, None, "Path that identifie the item in the page notebook") widget = property(_getWidget, None, None, - "The main widget (gtk.ScrolledWindow)") - page = property(_getPage, _setPage, None, + "The main widget (Gtk.ScrolledWindow)") + wr_page = property(_getWrPage, _setWrPage, None, "Weak reference from Page instance which creates this class") budget = property(_getBudget, None, None, "Budget object") @@ -4173,14 +4624,14 @@ class CompanyView(object): - """gui.CompanyView: + """gui:CompanyView: Description: Class to show the company records of a budget Constructor: - CompanyView(budget, page, pane_path, path_record=(0,)) + CompanyView(budget, wr_page, pane_path, path_record=(None) budget: budget showed ("base.Budget" object) - page: weak reference from Page instance which creates this class + wr_page: weak reference from Page instance which creates this class pane_path: tuple that represents the path of the List in the Page path_record: path of the active record in the budget Ancestry: @@ -4188,92 +4639,94 @@ +-- CompanyView Atributes: active_path_record: Read. Path of the active record in the budget - widget: Read. Window that contains the main widget, a gtk.HPaned + widget: Read. Window that contains the main widget, a Gtk.Paned pane_path: Read-Write. Pane page identifier - page: Read-Write. weak reference from Page instance which creates this class + wr_page: Read-Write. weak reference from Page instance which creates this class budget: Read. Budget to show, base.budget instance. Methods: runMessage """ - def __init__(self, budget, page, pane_path, path_record=None): - """__init__(budget, page, pane_path, path_record=None) - - budget: budget: budget showed ("base.Budget" object) - page: weak reference from Page instance which creates this class - pane_path: tuple that represents the path of the List in the Page + def __init__(self, budget, wr_page, pane_path, path_record=None): + """__init__(budget, wr_page, pane_path, path_record=None) + + budget: budget showed ("base.Budget" object) + wr_page: weak reference from Page instance which creates this class + pane_path: tuple that represents the path of the pane in the Page path_record: path of the active record in the budget - self.__selection: + self.__selection: "company" or "office" selected treeview self.__budget: budget: budget showed ("base.Budget" object) - self.__page: weak reference from Page instance which creates this class + self.__wr_page: weak reference from Page instance which creates this class self.__pane_path: tuple that represents the path of the List in the Page self.__active_path_record: path of the active record in the budget - self.__widget: main widget, a gtk.HPaned + self.__widget: main widget, a Gtk.Paned self.__treestore: to store companys data self.__option_View: OptionView object - Creates an shows the scroledwindow that contain the company data. + Creates an shows the widgets with the company data. """ if path_record is None: path_record = (0,) self.__selection = None # Seting init args if not isinstance(budget, base.Budget): - raise ValueError, _("Argument must be a Budget object") + raise ValueError( _("Argument must be a Budget object") ) self.__budget = budget - self.__page = page + self.__wr_page = wr_page self.__pane_path = pane_path self.__active_path_record = path_record # main widget - self.__widget = gtk.HPaned() + self.__widget = Gtk.Paned.new(Gtk.Orientation(0)) # 0 Horizontal self.__widget.set_position(230) # TreeStore - self.__treestore = gtk.TreeStore(str, str) + self.__treestore = Gtk.TreeStore(str, str) self._setTreeStoreValues() # Select Treeview - _select_treeview = gtk.TreeView(self.__treestore) + _select_treeview = Gtk.TreeView(self.__treestore) _select_treeview.set_enable_search(False) _select_treeview.set_reorderable(False) _select_treeview.set_headers_visible(False) _select_treeview.show() # Scrolled_window - _scrolled_window = gtk.ScrolledWindow() - _scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) + _scrolled_window = Gtk.ScrolledWindow() + _scrolled_window.set_property("expand", True) # widget expand all space + _scrolled_window.set_policy(Gtk.PolicyType(1), + Gtk.PolicyType(1)) # 1 Automatic _scrolled_window.add(_select_treeview) # colors - _text_color = gtk.gdk.color_parse(globalVars.color["TEXT"]) + _text_color = globalVars.color["TEXT"] _background_color = [ - gtk.gdk.color_parse(globalVars.color["UNEVEN"]), - gtk.gdk.color_parse(globalVars.color["EVEN"])] - _code_column = gtk.TreeViewColumn() + globalVars.color["UNEVEN"], + globalVars.color["EVEN"]] + _code_column = Gtk.TreeViewColumn() _code_column.set_clickable(True) _code_column.set_fixed_width(200) - _code_cell = gtk.CellRendererText() - _code_cell.set_property('foreground-gdk', _text_color) + _code_cell = Gtk.CellRendererText() + _code_cell.set_property('foreground', _text_color) _code_column.pack_start(_code_cell, True) _code_column.add_attribute(_code_cell, 'text', 0) - _summary_cell = gtk.CellRendererText() - _summary_cell.set_property('foreground-gdk', _text_color) + _summary_cell = Gtk.CellRendererText() + _summary_cell.set_property('foreground', _text_color) _code_column.pack_start(_summary_cell, True) _code_column.add_attribute(_summary_cell, 'text', 1) # Index column _select_treeview.append_column(_code_column) # control selection _treeselection = _select_treeview.get_selection() - _treeselection.set_mode(gtk.SELECTION_SINGLE) + _treeselection.set_mode(Gtk.SelectionMode(1)) # 1 SINGLE _treeselection.set_select_function(self._controlSelection) # Show _scrolled_window.show() # Option View - self.__option_View = OptionView("") + self.__option_View = OptionView() + # Add to main widget + self.__widget.add1(_scrolled_window) + self.__widget.add2(self.__option_View.widget) # Selection _select_treeview.set_cursor((0,), None, False) _select_treeview.grab_focus() - # - self.__widget.add1(_scrolled_window) - self.__widget.add2(self.__option_View.widget) + # Show self.__widget.show() def _setOptions(self, type): @@ -4298,7 +4751,7 @@ ] self.__option_View.options = _options elif type == "office": - _options = [("type", _("Type"), "string", + _options = [("officeType", _("Type"), "string", _("""Type of Office: C: Central office D: Local office @@ -4319,7 +4772,7 @@ ] self.__option_View.options = _options else: - print _("Unknow Option Type") + print(_("Unknow Option Type") ) def _setTreeStoreValues(self): """_setTreeStoreValues() @@ -4338,9 +4791,8 @@ _values = [_office.officeType, _office.subname] self.__treestore.append(_treeiter, _values) - - def _controlSelection(self, selection): - """_controlSelection(selection) + def _controlSelection(self, selection, model, path, path_currently_selected, *data): + """_controlSelection(selection, model, path, path_currently_selected, *data) selection: selection @@ -4353,24 +4805,23 @@ The selection changes the company/office in the option treeview """ - if len(selection) == 1: + if len(path) == 1: # The selection is a company - _company_key = self.__treestore[selection][0] + _company_key = self.__treestore[path][0] _company = self.__budget.getCompany(_company_key) _selection = "company" _values = _company.values else: # The selection is a office - _company_key = self.__treestore[selection[:1]][0] + _company_key = self.__treestore[path[:1]][0] _company = self.__budget.getCompany(_company_key) _selection = "office" - _office = _company.offices[selection[1]] + _office = _company.offices[path[1]] _values = _office.values if not self.__selection == _selection: self.__selection = _selection - self.options = _selection + self._setOptions(_selection) self.__option_View.values = _values - return True def _showMessageRecord(self, record_path): @@ -4406,24 +4857,24 @@ def _colorCell(self, column, cell_renderer, tree_model, iter, lcolor): """_colorCell(column, cell_renderer, tree_model, iter, lcolor) - column: the gtk.TreeViewColumn in the treeview - cell_renderer: a gtk.CellRenderer - tree_model: the gtk.TreeModel - iter: gtk.TreeIter pointing at the row + column: the Gtk.TreeViewColumn in the treeview + cell_renderer: a Gtk.CellRenderer + tree_model: the Gtk.TreeModel + iter: Gtk.TreeIter pointing at the row lcolor: list with 2 gtk colors for even and uneven record Method connected to "set_cell_data_func" of many column The set_cell_data_func() method sets the data function (or method) - to use for the column gtk.CellRenderer specified by cell_renderer. + to use for the column Gtk.CellRenderer specified by cell_renderer. This function (or method) is used instead of the standard attribute mappings for setting the column values, and should set the attributes of the cell renderer as appropriate. func may be None to remove the current data function. The signature of func is: -def celldatafunction(column, cell, model, iter, user_data) -def celldatamethod(self, column, cell, model, iter, user_data) - where column is the gtk.TreeViewColumn in the treeview, cell is the - gtk.CellRenderer for column, model is the gtk.TreeModel for the - treeview and iter is the gtk.TreeIter pointing at the row. + where column is the Gtk.TreeViewColumn in the treeview, cell is the + Gtk.CellRenderer for column, model is the Gtk.TreeModel for the + treeview and iter is the Gtk.TreeIter pointing at the row. The method sets cell background color for all columns and text for index and amount columns. @@ -4432,13 +4883,13 @@ _number = _row_path[-1] if column is self.__index_column: cell_renderer.set_property('text', str(_number + 1)) - self.__index_column.get_cell_renderers()[1].set_property( - 'cell-background-gdk', lcolor[_number % 2]) + self.__index_column.get_cells()[1].set_property( + 'cell-background', lcolor[_number % 2]) if self.__treeview.get_cursor() == (_row_path,column): - cell_renderer.set_property('cell-background-gdk', - gtk.gdk.color_parse(globalVars.color["ACTIVE"])) + cell_renderer.set_property('cell-background', + globalVars.color["ACTIVE"]) else: - cell_renderer.set_property('cell-background-gdk', + cell_renderer.set_property('cell-background', lcolor[_number % 2]) def _clear(self): @@ -4451,7 +4902,7 @@ def _getWidget(self): """_getWidget() - return the main widget (gtk.ScrolledWindow) + return the main widget (Gtk.ScrolledWindow) """ return self.__widget @@ -4469,19 +4920,19 @@ """ self.__pane_path = pane_path - def _getPage(self): - """_getPage() + def _getWrPage(self): + """_getWrPage() return the Page """ - return self.__page - - def _setPage(self,page): - """_setPage() + return self.__wr_page + + def _setWrPage(self,wr_page): + """_setWrPage() set the Page """ - self.__page = page + self.__wr_page = wr_page def _getBudget(self): """_getBudget() @@ -4503,7 +4954,7 @@ "main widget") pane_path = property(_getPanePath, _setPanePath, None, "Path that identifies the item in the page notebook") - page = property(_getPage, _setPage, None, + wr_page = property(_getWrPage, _setWrPage, None, "Weak reference from Page instance which creates this class") budget = property(_getBudget, None, None, "Budget object") @@ -4516,9 +4967,7 @@ It creates a treeview whith the column "Option Name" "Value" and "Type" to show and edit Options Constructor: - OptionView(option_list) - option_list: list of options - (option_name, type) + OptionView() Ancestry: +-- object +-- OptionView @@ -4527,22 +4976,23 @@ options: Write values: Write Methods: + No public Methods """ - def __init__(self, option_list): - """__init__(option_list) + def __init__(self): + """__init__() self.__option_dict: {"option key" : ["option name", "value", "option type", "option_description"]} self.__option_list: option keys list self.__option_types: valid option types list - self.__liststore: gtk.ListStore - self.__treeview: gtk.TreeView + self.__liststore: Gtk.ListStore + self.__treeview: Gtk.TreeView self.__option_column: option column self.__value_column: value column self.__type_column: type column - self.__description_label: gtk.Label + self.__description_label: Gtk.Label self.__widget: Main widget Creates an shows the widget that contain the option data. @@ -4555,33 +5005,35 @@ "color" : _("Color"), "list" : _("List")} # ListStore - self.__liststore = gtk.ListStore(str, str, str, str, str) + self.__liststore = Gtk.ListStore(str, str, str, str, str) # Treeview - self.__treeview = gtk.TreeView(self.__liststore) + self.__treeview = Gtk.TreeView(self.__liststore) self.__treeview.set_enable_search(False) self.__treeview.set_reorderable(False) self.__treeview.set_headers_clickable(False) # vbox - _vbox = gtk.VBox() + _vbox = Gtk.Grid() + _vbox.set_orientation(Gtk.Orientation(1)) # 1 Vertical # Scrolled_window - _scrolled_window = gtk.ScrolledWindow() - _scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) + _scrolled_window = Gtk.ScrolledWindow() + _scrolled_window.set_property("expand", True) # widget expand all space + _scrolled_window.set_policy(Gtk.PolicyType(1), + Gtk.PolicyType(1)) # 1 Automatic _scrolled_window.add(self.__treeview) _scrolled_window.show() - _vbox.pack_start(_scrolled_window) + _vbox.add(_scrolled_window) # colors - _text_color = gtk.gdk.color_parse(globalVars.color["TEXT"]) + _text_color = globalVars.color["TEXT"] _background_color = [ - gtk.gdk.color_parse(globalVars.color["UNEVEN"]), - gtk.gdk.color_parse(globalVars.color["EVEN"])] + globalVars.color["UNEVEN"], + globalVars.color["EVEN"]] # Option Column - self.__option_column = gtk.TreeViewColumn() - self.__option_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + self.__option_column = Gtk.TreeViewColumn() + self.__option_column.set_sizing(Gtk.TreeViewColumnSizing(2)) # 2 Fixed self.__option_column.set_fixed_width(150) self.__option_column.set_resizable(True) - _option_cell = gtk.CellRendererText() - _option_cell.set_property('foreground-gdk', _text_color) + _option_cell = Gtk.CellRendererText() + _option_cell.set_property('foreground', _text_color) self.__option_column.pack_start(_option_cell, True) self.__option_column.set_cell_data_func(_option_cell, self._colorCell, _background_color) @@ -4589,12 +5041,12 @@ self.__option_column.add_attribute(_option_cell, 'text', 1) self.__treeview.append_column(self.__option_column) # Value Column - self.__value_column = gtk.TreeViewColumn() - self.__value_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + self.__value_column = Gtk.TreeViewColumn() + self.__value_column.set_sizing(Gtk.TreeViewColumnSizing(2)) # 2 Fixed self.__value_column.set_fixed_width(275) self.__value_column.set_resizable(True) - _value_cell = gtk.CellRendererText() - _value_cell.set_property('foreground-gdk', _text_color) + _value_cell = Gtk.CellRendererText() + _value_cell.set_property('foreground', _text_color) self.__value_column.pack_start(_value_cell, True) self.__value_column.set_cell_data_func(_value_cell, self._colorCell, _background_color) @@ -4602,23 +5054,23 @@ self.__value_column.add_attribute(_value_cell, 'text', 2) self.__treeview.append_column(self.__value_column) # Type Column - self.__type_column = gtk.TreeViewColumn() - self.__type_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + self.__type_column = Gtk.TreeViewColumn() + self.__type_column.set_sizing(Gtk.TreeViewColumnSizing(2)) # 2 Fixed self.__type_column.set_fixed_width(70) self.__type_column.set_resizable(True) - _type_cell = gtk.CellRendererText() - _type_cell.set_property('foreground-gdk', _text_color) + _type_cell = Gtk.CellRendererText() + _type_cell.set_property('foreground', _text_color) self.__type_column.pack_start(_type_cell, True) self.__type_column.set_cell_data_func(_type_cell, self._colorCell, _background_color) self.__type_column.set_title(_("Type")) self.__treeview.append_column(self.__type_column) # End Column - _end_column = gtk.TreeViewColumn() + _end_column = Gtk.TreeViewColumn() _end_column.set_clickable(False) - _end_cell = gtk.CellRendererText() - _end_cell.set_property('cell-background-gdk', - gtk.gdk.color_parse(globalVars.color["UNEVEN"])) + _end_cell = Gtk.CellRendererText() + _end_cell.set_property('cell-background', + globalVars.color["UNEVEN"]) _end_column.pack_start(_end_cell, True) self.__treeview.append_column(_end_column) # Connect @@ -4627,31 +5079,30 @@ self._treeviewClickedEvent) # control selection _treeselection = self.__treeview.get_selection() - _treeselection.set_mode(gtk.SELECTION_MULTIPLE) + _treeselection.set_mode(Gtk.SelectionMode(3)) # 3 MULTIPLE _treeselection.set_select_function(self._controlSelection) # labels - _frame = gtk.Frame() - _frame.set_shadow_type(gtk.SHADOW_OUT) - _vbox2 = gtk.VBox() + _frame = Gtk.Frame() + _frame.set_shadow_type(2) # NONE 0, IN 1, OUT 2, ETCHED_IN 3,ETCHED_OUT 4 + _vbox2 = Gtk.Grid() + _vbox2.set_orientation(Gtk.Orientation(1)) # 1 Vertical _frame.add(_vbox2) - _alignement = gtk.Alignment(xalign=0, yalign=0, xscale=0, yscale=0) - _alignement.set_padding(0, 0, 12, 0) - _label = gtk.Label() + _label = Gtk.Label() + _label.set_xalign(0) + _label.set_yalign(0) + _label.set_margin_start(12) _label.set_markup("" + _("Description:") + "") _label.show() - _alignement.add(_label) - _alignement.show() - _alignement2 = gtk.Alignment(xalign=0, yalign=0, xscale=0, yscale=0) - _alignement2.set_padding(0, 0, 24, 0) - self.__description_label = gtk.Label() + self.__description_label = Gtk.Label() + self.__description_label.set_xalign(0) + self.__description_label.set_yalign(0) + self.__description_label.set_margin_start(24) self.__description_label.show() - _alignement2.add(self.__description_label) - _alignement2.show() - _vbox2.pack_start(_alignement, False) - _vbox2.pack_start(_alignement2, False) + _vbox2.add(_label) + _vbox2.add(self.__description_label) _vbox2.show() _frame.show() - _vbox.pack_start(_frame, False) + _vbox.add(_frame) # Show self.__treeview.show() _vbox.show() @@ -4669,13 +5120,15 @@ Returns :FALSE to propagate the event further. If the user press the right cursor button and the cursor is in the - value column or pres the left cursor button and the cursor is + value column or press the left cursor button and the cursor is in the value column the event is estoped, else the event is propagated. """ (_cursor_path, _column) = self.__treeview.get_cursor() - if (event.keyval == gtk.keysyms.Right \ + if (event.keyval in [Gdk.keyval_from_name("Right"), + Gdk.keyval_from_name("KP_Right")] \ and _column == self.__value_column) \ - or (event.keyval == gtk.keysyms.Left \ + or (event.keyval in [Gdk.keyval_from_name("Left"), + Gdk.keyval_from_name("KP_Left")] \ and _column == self.__value_column): return True else: @@ -4711,8 +5164,10 @@ return True return True - def _controlSelection(self, selection): - """_controlSelection(selection) + def _controlSelection(self, selection, model, path, path_currently_selected, + *data): + """_controlSelection(selection, model, path, path_currently_selected, + *data) selection: treeselection @@ -4730,24 +5185,24 @@ def _colorCell(self, column, cell_renderer, tree_model, iter, lcolor): """_colorCell(column, cell_renderer, tree_model, iter, lcolor) - column: the gtk.TreeViewColumn in the treeview - cell_renderer: a gtk.CellRenderer - tree_model: the gtk.TreeModel - iter: gtk.TreeIter pointing at the row - lcolor: list with 2 gtk colors for even and uneven record + column: the Gtk.TreeViewColumn in the treeview + cell_renderer: a Gtk.CellRenderer + tree_model: the Gtk.TreeModel + iter: Gtk.TreeIter pointing at the row + lcolor: list with 2 colors for even and uneven record Method connected to "set_cell_data_func" of the column The set_cell_data_func() method sets the data function (or method) - to use for the column gtk.CellRenderer specified by cell_renderer. + to use for the column Gtk.CellRenderer specified by cell_renderer. This function (or method) is used instead of the standard attribute mappings for setting the column values, and should set the attributes of the cell renderer as appropriate. func may be None to remove the current data function. The signature of func is: -def celldatafunction(column, cell, model, iter, user_data) -def celldatamethod(self, column, cell, model, iter, user_data) - where column is the gtk.TreeViewColumn in the treeview, cell is the - gtk.CellRenderer for column, model is the gtk.TreeModel for the - treeview and iter is the gtk.TreeIter pointing at the row. + where column is the Gtk.TreeViewColumn in the treeview, cell is the + Gtk.CellRenderer for column, model is the Gtk.TreeModel for the + treeview and iter is the Gtk.TreeIter pointing at the row. The method sets cell background color for all columns and text for type column. @@ -4755,10 +5210,10 @@ _row_path = tree_model.get_path(iter) _number = _row_path[-1] if self.__treeview.get_cursor() == (_row_path,column): - cell_renderer.set_property('cell-background-gdk', - gtk.gdk.color_parse(globalVars.color["ACTIVE"])) + cell_renderer.set_property('cell-background', + globalVars.color["ACTIVE"]) else: - cell_renderer.set_property('cell-background-gdk', + cell_renderer.set_property('cell-background', lcolor[_number % 2]) if column is self.__type_column: _type = self.__option_types[tree_model[_row_path][3]] @@ -4788,7 +5243,9 @@ _option_name = _option[1] _option_type = _option[2] _option_description = _option[3] - if isinstance(_option_key, str) and \ + #-# str and unicode + if (isinstance(_option_key, str) or \ + isinstance(_option_key, unicode)) and \ (isinstance(_option_name, str) or\ isinstance(_option_name, unicode))and \ _option_type in self.__option_types.keys(): @@ -4798,11 +5255,11 @@ _option_type, _option_description] self.__option_list.append(_option_key) else: - print _("Option values must be strings") + print(_("Option values must be strings") ) else: - print _("Option must be a tuple with 4 items") + print(_("Option must be a tuple with 4 items") ) else: - print _("Option list must be a list") + print(_("Option list must be a list") ) def _setValues(self, values): """_setValues(values) @@ -4822,12 +5279,12 @@ self.__liststore.set_value(_iter, 2, _value) self.__option_dict[_option][1] = _value else: - print _("Icorrect type, must be boolean") + print(_("Icorrect type, must be boolean") ) elif _type == "integer": try: _value = int(_value) except ValueError: - print _("Icorrect type, must be integer") + print(_("Icorrect type, must be integer") ) else: _num = self.__option_list.index(_option) _iter = self.__liststore.get_iter((_num,)) @@ -4840,7 +5297,7 @@ self.__liststore.set_value(_iter, 2, _value) self.__option_dict[_option][1] = _value else: - print _("Icorrect type, must be string") + print(_("Icorrect type, must be string") ) elif _type == "list": if isinstance(_value, list): _num = self.__option_list.index(_option) @@ -4853,27 +5310,27 @@ self.__liststore.set_value(_iter, 2, _str_value) self.__option_dict[_option][1] = _value else: - print _("Icorrect type, must be list") + print(_("Icorrect type, must be list") ) elif _type == "color": if isinstance(_value, str): - try: - _color = gtk.gdk.color_parse(_value) - except ValueError: - print _("Icorrect type, must be a parseable " \ - "color") + if Gdk.RGBA().parse(_value): + print(_("Icorrect type, must be a parseable " \ + "color") ) else: _num = self.__option_list.index(_option) _iter = self.__liststore.get_iter((_num,)) self.__liststore.set_value(_iter, 2, _value) self.__option_dict[_option][1] = _value else: - print _("Type must be boolean, integer, string or "\ - "color") + print(_("Type must be boolean, integer, string or "\ + "color") ) else: - print _("Value must be in the option dict") + print( _("Value must be in the option dict") ) + print(_option, _value) else: - print _("Values must be a dict") - self.__treeview.set_cursor((0),self.__value_column, False) + print( _("Values must be a dict") ) + self.__treeview.set_cursor(Gtk.TreePath.new_from_indices((0,)), + self.__value_column, False) self.__treeview.grab_focus() (_cursor_path, _column) = self.__treeview.get_cursor() _description = self.__liststore[_cursor_path][4] @@ -4882,7 +5339,7 @@ def _getWidget(self): """_getWidget() - return the main widget (gtk.ScrolledWindow) + return the main widget (Gtk.ScrolledWindow) """ return self.__widget @@ -4892,3 +5349,4 @@ "values") options = property(None, _setOptions, None, "options") + diff -r 7bd4ca56607d -r 65e7ae0d0e63 Gtk/importFiebdc.py --- a/Gtk/importFiebdc.py Tue Sep 30 17:16:50 2014 +0200 +++ b/Gtk/importFiebdc.py Thu May 02 16:31:17 2019 +0200 @@ -3,7 +3,7 @@ ## File importFiebdc.py ## This file is part of pyArq-Presupuestos. ## -## Copyright (C) 2010-2014 Miguel Ángel Bárcena Rodríguez +## Copyright (C) 2010-2019 Miguel Ángel Bárcena Rodríguez ## ## ## pyArq-Presupuestos is free software: you can redistribute it and/or modify @@ -20,344 +20,17 @@ ## along with this program. If not, see . # Modules -import sys -import time -import os.path -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import threading -gobject.threads_init() -# pyArq-Presupuestos Modules -from Generic import utils -from Generic import globalVars -#from Generic import durusdatabase -import gui - -class FileSelectionWindow(object): - """importFiebdc.FileSelectionWindow: - - Description: - Class to show the selection file window - Constructor: - importFiebdc.FileSelectionWindow(mainWindow, readFileMethod, budget, - filename, cancelMethod, filetype) - Ancestry: - +-- object - +-- FileSelectionWindow - Atributes: - "__mainWindow": gui.MainWindow object - "__readFileMethod": Method to read the selected file - "__budget": Budget object - "__filename": "file" - "__filetype": "budget" ,"database" or "durus" - "__cancelMethod": Method to cancel the read method - "__file": The selected file - "__window": The selection file window - Methods: - __init__(self, mainWindow, readFileMethod, budget - arg_List, cancelMethod) - _launchProgressWindow(self, _file) - _openFile(self, filename) - """ - - def __init__(self, mainWindow, readFileMethod, budget, filename, - cancelMethod, filetype): - """def __init__(self, mainWindow, readFileMethod, budget, - filename, cancelMethod, filetype) - - mainWindow: gui.MainWindow object - readFileMethod: Method to read the selected file - budget: base.Budget object - filename: "file" - cancelMethod: Method to cancel the read method - fileytpe: "budget", "database" or "durus". - Sets the init atributes, creates the file selection window - Connects the events: - * clicked ok button: _openFile - * clicked cancel button: destroy window - * destroy event: _destroy - """ - # TODO: Add file filter - self.__mainWindow = mainWindow - self.__readFileMethod = readFileMethod - self.__budget = budget - self.__filename = filename - self.__filetype = filetype - self.__cancelMethod = cancelMethod - self.__file = None - self.__window = gtk.FileChooserDialog(title=_("Open File"), - action=gtk.FILE_CHOOSER_ACTION_OPEN, - buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN,gtk.RESPONSE_OK)) - self.__window.set_default_response(gtk.RESPONSE_OK) - #if self.__filetype == "budget" or self.__filetype == "database": - self.__window.set_current_folder(globalVars.getHomePath("BUDGET")) - #else: # "durus" - # self.__window.set_current_folder( - # globalVars.getHomePath("DURUS-DATABASE")) - if self.__window.run() == gtk.RESPONSE_OK: - self._openFile(self.__window.get_filename()) - self.__window.destroy() - - def _launchProgressWindow(self, file): - """def _launchProgressWindow(self, file) - - Launch the progress window - """ - self.__filename = file - _emptyPage = gui.EmptyPage(self.__mainWindow, self.__readFileMethod, - self.__budget, self.__filename, - self.__cancelMethod, self.__filetype) - self.__mainWindow.appendEmptyPage(_emptyPage) - _emptyPage.run() - - def _openFile(self, filename): - """def _openFile(self, filename) - - filename: the filename to open - If the selected file has a bc3 extension - _launchProgressWindow is called - """ - _file = filename - if sys.getfilesystemencoding(): - _file = _file.decode(sys.getfilesystemencoding()) - #-# - _file = _file.encode("utf-8") - #-# - self.__file = _file - _filename = os.path.basename(self.__file) - _filename_ext = _filename.split(".")[-1] - if (self.__filetype == "budget" or self.__filetype == "database") and \ - _filename_ext != "bc3" and _filename_ext != "BC3": - print _("The file must have 'bc3' extension") - #elif self.__filetype == "durus" and _filename_ext != "durus": - # print _("The file must have 'durus' extension") - else: - self.__window.destroy() - # TODO: the file exits? is it not binary?, can it be readed? - self._launchProgressWindow(self.__file) - - -class ProgressWindow(object): - """importFiebdc.ProgressWindow: - - Description: - Class to show the progress window and launch a thread to read - the database file - Constructor: - importFiebdc.ProgressWindow(mainWindow, readFileMethod, budget, - filename, cancelMethod) - Ancestry: - +-- object - +-- ProgressWindow - Atributes: - "__mainWindow": - "__readFileMethod": - "__budget": - "__filename": - "__cancelMethod": - "__children": Thread instance - "__cancel": list with boolean values - "__window": progress window widget - "__progress_bar": probres bar widget - "__label": label widget - Methods: - closeWindow(self) - __init__(self, mainWindow, readFileMethod, budget - filename, cancelMethod) - closeWindow(self) - main(self) - _autoClose(self) - _updateLabel(self, _time) - _updateProgressBar(self) - _launchTimeout(self) - _launchChildren(self, mainWindow, readFileMethod, budget - filename, cancelMethod) - _cancelChildren(self,widget=None) - _destroy(self, widget) - _delete_event(self, widget, event) +# python 2/3 compatibility +from __future__ import absolute_import, division, print_function, unicode_literals - """ - def __init__(self, mainWindow, readFileMethod, budget, - filename, cancelMethod): - """def __init__(self, mainWindow, readFileMethod, budget - filename, cancelMethod) - - mainWindow: gui.MainWindow object - readFileMethod: Method to read the selected file - budget: base.Budget object - filenamer: "file" - cancelMethod: Method to cancel the read method - Sets the init atributes, creates the progress window - Connects the events: - * destroy signal: self._destroy - * delete_event signal: self._delete_event - * clicked cancel button: self._cancelChildren - """ - self.__mainWindow = mainWindow - self.__readFileMethod = readFileMethod - self.__filename = filename - self.__budget = budget - self.__cancelMethod = cancelMethod - self.__children = None - self.__cancel = [False, False] - self.__window = gtk.Window() - self.__window.set_title(_("Loading file ...")) - self.__window.connect("destroy", self._destroy) - self.__window.connect("delete_event", self._delete_event) - _Vbox1 = gtk.VBox(False, 0) - self.__window.add(_Vbox1) - _align = gtk.Alignment(0.5, 0.5, 0, 0) - _align.show() - _Vbox1.pack_start(_align, False, False, 5) - self.__progress_bar = gtk.ProgressBar() - self.__progress_bar.show() - _align.add(self.__progress_bar) - self.__label = gtk.Label() - self.__label.set_text(_("Time: 0s")) - self.__label.show() - _Vbox1.add(self.__label) - self.__throbber = gtk.Image() - self.__throbber.set_from_file(globalVars.getAppPath("THROBBER-ICON")) - _Vbox1.add(self.__throbber) - self.__throbber.show() - self.__animation = gtk.gdk.PixbufAnimation(globalVars.getAppPath("THROBBER-GIF")) - _pixbuf = self.__throbber.get_pixbuf() - self.__throbber.set_from_animation(self.__animation) - _Hbox1 = gtk.HBox(False, 0) - _Vbox1.add(_Hbox1) - _button1 = gtk.Button(_("Cancel")) - _button1.connect("clicked", self._cancelChildren) - _button1.show() - _Hbox1.pack_start(_button1, True, True, 0) - _Hbox1.show() - _Vbox1.show() - - def main(self): - """def main(self) - - Launch the thread - Launch the timeouts - Shows window and starts the GTK+ event processing loop. - """ - - self._launchChildren() - self._launchTimeout() - self.__window.show() - gtk.main() - - def closeWindow(self): - """def closeWindow(self) - - Sets the __children atribute to None - This causes that the timiouts is ended and then the window is - closed. - This method is called from thread when it is finished - """ - self.__children = None +# gui +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk +from gi.repository import GLib - def _launchTimeout(self): - """def _launchTimeout(self) - - Launch the timeouts: - 1- update progress bar - 2- update time labal - 3- If the other timetouts are stoped the window is closed - """ - gobject.timeout_add(100, self._updateProgressBar) - gobject.timeout_add(1000, self._updateLabel, time.time()) - self.__cancel = [False, False] - gobject.timeout_add(1000, self._autoClose) - - def _updateProgressBar(self): - """def _updateProgressBar(self) - - update progress bar in a timeout - If the thread end or is canceled the timeout is stoped - """ - if self.__children is None or self.__children.isCanceled() == True: - self.__cancel[0] = True - return False - else: - self.__progress_bar.pulse() - return True - - def _updateLabel(self, _time): - """def _updateProgressBar(self) - - update time label in a timeout - If the thread end or is canceled the timeout is stoped - """ - if self.__children is None or self.__children.isCanceled() == True: - self.__cancel[1] = True - return False - else: - _time = time.time() - _time - self.__label.set_text(utils.mapping(_("Time: $1"), - ("%.0f" %_time,))) - return True - - def _autoClose(self): - """def _updateProgressBar(self) - - If the time label and progress bar timeouts are stoped the window is - closed and ist tiemeout is stoped - """ - if self.__cancel == [ True, True ]: - self.__window.destroy() - return False - else: - return True - - def _launchChildren(self): - """_launchChildren(self) - - Launch the thread to read the file - """ - if self.__children is None: - self.__children = Thread(self, self.__mainWindow, - self.__readFileMethod, self.__budget, self.__filename, - self.__cancelMethod) - self.__children.start() - - def _cancelChildren(self,widget=None): - """_cancelChildren(self,widget=None) - - Method connected to "clicked" singal of cancel button - Stops the thread and close the window - """ - if self.__children: - self.__children.cancel() - self.__window.destroy() - - def _delete_event(self, widget, event): - """_delete_event(self, widget, event) - - widget: the widget where the event is emitted from - event: the "gtk.gdk.Event" - Method connected to "delete_event" signal of window widget - This signal is emitted when a user press the close titlebar button. - Stops the thread if exits. - Returns True so the signal "destroy" is emitted. - """ - if self.__children: - self._cancelChildren() - return True - - def _destroy(self, widget): - """_destroy(self, widget) - - widget: the widget where the event is emitted from - Method connected to "destroy" signal of window widget - This signal is emited when the method connected to "delete_event" - signal returns True or when the program call the destroy() method of - the gtk.Window widget. - The window is closed and the GTK+ event processing loop is ended. - """ - gtk.main_quit() +import threading class Thread(threading.Thread): """importFiebdc.Thread: @@ -377,16 +50,14 @@ "__budget "__filename": "file" "__cancelMethod": Method to cancel the read method - "__filetype": "budget", "database" or "durus" + "__filetype": "budget" or "database" "__cancel": Boolean value, True: the thread is stoped Methods: - __init__(self, page, mainWindow, - readFileMethod, arg_tuple, cancelMethod) - run(self) - cancel(self) - isCanceled(self) + run() + cancel() + isCanceled() + clear() """ - def __init__(self, page, mainWindow, readFileMethod, budget, filename, cancelMethod, filetype): """def __init__(page, mainWindow, readFileMethod, budget, @@ -398,7 +69,8 @@ budget: base.Budget object filename: "file" cancelMethod: Method to cancel the read method - filetype: "budget", "database" or "durus" + filetype: "budget" or "database" + Sets the instance atributes. """ super(Thread, self).__init__() @@ -412,37 +84,19 @@ self.__cancel = False def run(self): - """run(self) + """run() """ - _budget = self.__readFileMethod(self.__budget, self.__filename, - self.__page) - if _budget is None: - self.__page.threadCanceled() + self.__readFileMethod(self.__budget, self.__filename, self.__page) + if not self.__page.endSuccessfully: + GLib.idle_add(self.__page.threadCanceled) else: - _mainWindow = self.__mainWindow - self.__page.threadFinishedSignal(_budget) - #if self.__filetype == "database": - # self.saveDurusDatabase() + GLib.idle_add(self.__page.threadFinishedSignal, self.__budget) self.clear() - - #def saveDurusDatabase(self): - # _path = globalVars.getHomePath("DURUS-DATABASE") - # _file_whit_path_bc3 = self.__budget.filename - # _filename_bc3 = _file_whit_path_bc3.split("/")[-1] - # _filename = _filename_bc3.split(".")[-2] - # _file = _path + _filename + ".durus" - # print utils.mapping(_("Saving file: $1"), (_file,)) - # _time = time.time() - # _durus_file = durusdatabase.DurusFile(_file,True) - # _durus_file.setBudget(self.__budget) - # _durus_file.close() - # print utils.mapping(_("Saving time: $1 seconds"), - # (("%.2f" %(time.time()-_time) ),)) def cancel(self): - """cancel(self) + """cancel() Sets the "__cancel" atribute to True and call "__cancelMethod" to stop read the file @@ -451,7 +105,7 @@ self.__cancelMethod() def isCanceled(self): - """isCanceled(self) + """isCanceled() Return True if the thread has been canceled """ @@ -464,4 +118,4 @@ del self.__budget del self.__filename del self.__cancelMethod - del self.__cancel + #del self.__cancel diff -r 7bd4ca56607d -r 65e7ae0d0e63 __init__.py --- a/__init__.py Tue Sep 30 17:16:50 2014 +0200 +++ b/__init__.py Thu May 02 16:31:17 2019 +0200 @@ -7,4 +7,4 @@ # # this file is needed for Python's import mechanism # - +name = "pyArq-Presupuestos" diff -r 7bd4ca56607d -r 65e7ae0d0e63 images/close.svg --- a/images/close.svg Tue Sep 30 17:16:50 2014 +0200 +++ b/images/close.svg Thu May 02 16:31:17 2019 +0200 @@ -1,8 +1,9 @@ + + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.1"> + inkscape:window-x="235" + inkscape:window-y="35" + inkscape:window-maximized="0"> + id="guide3733" + inkscape:locked="false" /> + id="guide3735" + inkscape:locked="false" /> @@ -54,6 +59,7 @@ image/svg+xml + diff -r 7bd4ca56607d -r 65e7ae0d0e63 images/throbber.gif Binary file images/throbber.gif has changed diff -r 7bd4ca56607d -r 65e7ae0d0e63 images/throbber.png Binary file images/throbber.png has changed diff -r 7bd4ca56607d -r 65e7ae0d0e63 images/throbber.svg --- a/images/throbber.svg Tue Sep 30 17:16:50 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,243 +0,0 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - diff -r 7bd4ca56607d -r 65e7ae0d0e63 mo/es/LC_MESSAGES/pyArq-Presupuestos.mo Binary file mo/es/LC_MESSAGES/pyArq-Presupuestos.mo has changed diff -r 7bd4ca56607d -r 65e7ae0d0e63 mo/pyArq-Presupuestos.es.po --- a/mo/pyArq-Presupuestos.es.po Tue Sep 30 17:16:50 2014 +0200 +++ b/mo/pyArq-Presupuestos.es.po Thu May 02 16:31:17 2019 +0200 @@ -1,19 +1,19 @@ # pyArq-Presupuestos translatión to Spanish. -# Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +# Copyright (C) 2019 Miguel Ángel Bárcena Rodríguez # This file is distributed under the same license as the pyArq-Presupuestos # package. # Changes: # - Initial translation: -# Miguel Ángel Bárcena Rodríguez , 2010-2013 +# Miguel Ángel Bárcena Rodríguez , 2010-2019 # # msgid "" msgstr "" "Project-Id-Version: pyArq-Presupuestos 0.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-11-02 18:58+0100\n" -"PO-Revision-Date: 2013-11-02 18:58+0100\n" -"Last-Translator: Miguel Ángel Bárcena Rodríguez \n" "Language-Team: Spanish\n" "Language: Spannish\n" @@ -21,309 +21,336 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../Generic/base.py:359 +#: ../Generic/base.py:283 +msgid "" +"\n" +"A free program of measurements, budgets and control of construction sites.\n" +"In beta development, still there is not a fully functional version.\n" +msgstr "" +"\n" +"Un programa libre de mediciones, presupuestos y control de obras de " +"construcción.\n" +"En estado beta de desarrollo, aún no hay una versión plenamente funcional.\n" + +#: ../Generic/base.py:288 +msgid "" +"\n" +"Usage:\n" +" pyarqPresupuestos [file]...\n" +"\n" +"Help Options:\n" +" -h, --help Show this help\n" +msgstr "" +"\n" +"Uso:\n" +" pyarqPresupuestos [fichero]...\n" +"\n" +"Opciones de ayuda:\n" +" -h, --help Muestra esta ayuda\n" + +#: ../Generic/base.py:421 msgid "Invalid code: $1" msgstr "Código no válido: $1" -#: ../Generic/base.py:374 +#: ../Generic/base.py:436 msgid "Synonyms ($1) must be a list, code: $2" msgstr "«Synonyms» ($1) debe ser una lista, código: $2" -#: ../Generic/base.py:378 +#: ../Generic/base.py:440 msgid "Invalid Code in synomyms list ($1) code: $2" msgstr "Código no válido es la lista de sinónimos ($1) código: $2" -#: ../Generic/base.py:409 +#: ../Generic/base.py:471 msgid "Unit ($1) must be a string: $2" msgstr "«Unit» ($1) debe ser una cadena: $2" -#: ../Generic/base.py:423 +#: ../Generic/base.py:485 msgid "Summary ($1) must be a string: $1" msgstr "«Summary» ($1) debe ser una cadena: $1" -#: ../Generic/base.py:440 +#: ../Generic/base.py:502 msgid "Prices ($1) must be a list: $2" msgstr "«Prices» ($1) debe ser una lista: $2" -#: ../Generic/base.py:461 +#: ../Generic/base.py:523 msgid "Price ($1) must be a list with two items: $2" msgstr "«Price» ($1) debe ser una lista con dos elementos: $2" -#: ../Generic/base.py:466 +#: ../Generic/base.py:528 msgid "Price must be a float number: $1" msgstr "Precio debe ser un número de coma flotante: $1" -#: ../Generic/base.py:476 +#: ../Generic/base.py:538 #, python-format msgid "The record do not have this Price. Code: %s" msgstr "El registro no tiene ese precio. Código: %s" -#: ../Generic/base.py:482 +#: ../Generic/base.py:544 msgid "The record do not have this Price" msgstr "El registro no tiene ese precio" -#: ../Generic/base.py:497 +#: ../Generic/base.py:559 msgid "Parents ($1) must be a list: $2" msgstr "«Parents» ($1) debe ser una lista: $2" -#: ../Generic/base.py:501 ../Generic/base.py:513 +#: ../Generic/base.py:563 ../Generic/base.py:575 msgid "Invalid parent code ($1) in the record: $2" msgstr "Código padre no válido ($1) en el registro: $2" -#: ../Generic/base.py:529 +#: ../Generic/base.py:591 msgid "children ($1) must be a list, record: $2" msgstr "«children» ($1) debe ser una lista, registro: $2" -#: ../Generic/base.py:533 +#: ../Generic/base.py:595 msgid "child ($1) must be a Decomposition object, record: $2" msgstr "«child» ($1) debe ser una objeto «Decomposition», registro $2" -#: ../Generic/base.py:581 +#: ../Generic/base.py:649 msgid "Text ($1) must be a string, record: $2" msgstr "«Text» ($1) debe ser una cadena, registro: $2" -#: ../Generic/base.py:594 +#: ../Generic/base.py:662 msgid "sheet must be a Sheet instance" msgstr "«sheet» debe ser una instancia de Sheet" -#: ../Generic/base.py:607 +#: ../Generic/base.py:674 msgid "files must be a list: $1" msgstr "«files» debe ser una lista: $1" -#: ../Generic/base.py:618 ../Generic/base.py:633 +#: ../Generic/base.py:685 ../Generic/base.py:699 msgid "Incorrect path" msgstr "Ruta incorrecta" -#: ../Generic/base.py:623 +#: ../Generic/base.py:690 msgid "file must be a list or a File object: $1" msgstr "«file» debe ser una lista o un objeto «File: $1" -#: ../Generic/base.py:652 +#: ../Generic/base.py:718 msgid "labels must be a list" msgstr "«labels» debe ser una lista" -#: ../Generic/base.py:658 +#: ../Generic/base.py:724 msgid "label must be a string" msgstr "«label» debe ser una cadena de texto." -#: ../Generic/base.py:667 +#: ../Generic/base.py:733 msgid "Label must be a string" msgstr "«Label» debe ser una cadena de texto." -#: ../Generic/base.py:907 +#: ../Generic/base.py:981 msgid "Position must be a integer" msgstr "«Position» debe ser un número entero" -#: ../Generic/base.py:917 +#: ../Generic/base.py:995 msgid "BudgetMeasures atribute must be a list" msgstr "El atributo «BudgetMeasures» debe ser una lista" -#: ../Generic/base.py:920 +#: ../Generic/base.py:998 msgid "BudgetMeasures item must be a Measure " msgstr "El atributo «BudgetMeasures» debe ser un objeto «Measure»" -#: ../Generic/base.py:927 +#: ../Generic/base.py:1007 msgid "Certification atribute must be a list or None" msgstr "El atributo «Certification» debe ser una lista o «None»" -#: ../Generic/base.py:933 +#: ../Generic/base.py:1015 msgid "Real cost atribute must be a list or None" msgstr "El atributo «Real cost» debe ser una lista o «None»" -#: ../Generic/base.py:939 +#: ../Generic/base.py:1023 msgid "Cost goals atribute must be a list or None" msgstr "El atributo «Cost goals» debe ser una lista o «None»" -#: ../Generic/base.py:945 +#: ../Generic/base.py:1031 msgid "Cost Planned atribute must be a list or None" msgstr "El atributo «Cost Planned» debe ser una lista o «None»" -#: ../Generic/base.py:1036 +#: ../Generic/base.py:1124 msgid "Measure must be a float number. Type: $1" msgstr "«Measure» debe ser un número de coma flotante. Tipo: $1" -#: ../Generic/base.py:1047 +#: ../Generic/base.py:1136 msgid "Lines must be a list" msgstr "«Lines» debe ser una lista" -#: ../Generic/base.py:1050 +#: ../Generic/base.py:1139 msgid "Line must be a MeasureLine objetc" msgstr "«Line» debe ser un objeto «MeasureLine»" -#: ../Generic/base.py:1058 +#: ../Generic/base.py:1150 msgid "Factor must be a float number |$1|" msgstr "«Factor» debe ser un número de coma flotante |$1|" -#: ../Generic/base.py:1070 +#: ../Generic/base.py:1162 msgid "Yield must be a float number" msgstr "«Yield» debe ser un número de coma flotante" -#: ../Generic/base.py:1081 +#: ../Generic/base.py:1173 msgid "Fixed must be boolean object" msgstr "«Fixed» debe ser un objeto booleano" -#: ../Generic/base.py:1151 +#: ../Generic/base.py:1243 msgid "Type must be M or A. Type: $1" msgstr "«Type» debe ser M o A. Type: $1" -#: ../Generic/base.py:1283 +#: ../Generic/base.py:1387 msgid " Parcial Subtotal must be a float number. Parcial: $1" msgstr "«Parcial Subtotal» debe ser un número de coma flotante. Parcial: $1" -#: ../Generic/base.py:1290 +#: ../Generic/base.py:1395 msgid " Acumulated Subtotal must be a float number. Parcial: $1" msgstr " «Acumulate Subtotal» debe ser un número de coma flotante. Parcial: $1" -#: ../Generic/base.py:1325 +#: ../Generic/base.py:1431 msgid "Invalid measure line type ($1)" msgstr "Tipo de línea de medición no válido ($1)" -#: ../Generic/base.py:1330 +#: ../Generic/base.py:1437 msgid "Measure Comment must be a string ($1)" msgstr "El comentario de la medición debe ser una cadena ($1)" -#: ../Generic/base.py:1336 +#: ../Generic/base.py:1444 msgid "Invalid Measure Units ($1)" msgstr "Unidades de medición no válidas ($1)" -#: ../Generic/base.py:1348 +#: ../Generic/base.py:1457 msgid "Invalid Measure length ($1)" msgstr "Longitud de medición no válida ($1)" -#: ../Generic/base.py:1360 +#: ../Generic/base.py:1470 msgid "Invalid Measure Width ($1)" msgstr "Anchura de medición no válida ($1)" -#: ../Generic/base.py:1372 +#: ../Generic/base.py:1483 msgid "Invalid Measure Height ($1)" msgstr "Altura de medición no válida ($1)" -#: ../Generic/base.py:1383 +#: ../Generic/base.py:1495 msgid "Formula must be a string ($1)" msgstr "«Formula» debe ser una cadena de texto ($1)" -#: ../Generic/base.py:1386 +#: ../Generic/base.py:1498 msgid "There is invalid charactersin formula ($1)" msgstr "Hay caracteres no válidos en la fórmula ($1)" -#: ../Generic/base.py:1451 ../Generic/base.py:2443 +#: ../Generic/base.py:1564 ../Generic/base.py:2618 msgid "'a' value must be a float number" msgstr "El valor «a» debe ser un número de coma flotante" -#: ../Generic/base.py:1455 ../Generic/base.py:2447 +#: ../Generic/base.py:1568 ../Generic/base.py:2622 msgid "'b' value must be a float number" msgstr "El valor «b» debe ser un número de coma flotante" -#: ../Generic/base.py:1459 ../Generic/base.py:2451 +#: ../Generic/base.py:1572 ../Generic/base.py:2626 msgid "'c' value must be a float number" msgstr "El valor «c» debe ser un número de coma flotante" -#: ../Generic/base.py:1463 ../Generic/base.py:2455 +#: ../Generic/base.py:1576 ../Generic/base.py:2630 msgid "'d' value must be a float number" msgstr "El valor «d» debe ser un número de coma flotante" -#: ../Generic/base.py:1491 ../Generic/base.py:2483 +#: ../Generic/base.py:1604 ../Generic/base.py:2658 msgid "Invalid formula" msgstr "Fórmula no válida" -#: ../Generic/base.py:1741 +#: ../Generic/base.py:1858 msgid "sheet_dict must be a dictionay" msgstr "«sheet_dict» debe ser un diccionario." -#: ../Generic/base.py:1758 ../Generic/base.py:1764 +#: ../Generic/base.py:1879 ../Generic/base.py:1886 msgid "sheet field must be a string" msgstr "«sheet field» debe ser una cadena de texto" -#: ../Generic/base.py:1760 +#: ../Generic/base.py:1881 msgid "section_dict must be a dictionary" msgstr "«section_dict» debe ser un dicionario" -#: ../Generic/base.py:1766 +#: ../Generic/base.py:1888 msgid "sheet section must be a string" msgstr "La seccion del pliego debe ser una cadena de texto" -#: ../Generic/base.py:1768 +#: ../Generic/base.py:1890 msgid "sheet paragraph must be a string" msgstr "«sheet paragraph» debe ser una cadena de texto" -#: ../Generic/base.py:2006 +#: ../Generic/base.py:2177 msgid "Owner must be a string" msgstr "«Owner» debe ser una cadena de texto." -#: ../Generic/base.py:2022 +#: ../Generic/base.py:2193 msgid "Invalid Date: $1" msgstr "Fecha no válida: $1" -#: ../Generic/base.py:2033 +#: ../Generic/base.py:2204 msgid "Comment must be a string" msgstr "«Comment» debe ser una cadena" -#: ../Generic/base.py:2049 +#: ../Generic/base.py:2220 msgid "Budget type must be 1, 2, 3 or 4." msgstr "El tipo de presupuesto debe ser 1, 2, 3 o 4" -#: ../Generic/base.py:2061 +#: ../Generic/base.py:2232 msgid "Certificate order must be a integer." msgstr "«Certificate order» debe ser un número entero" -#: ../Generic/base.py:2076 +#: ../Generic/base.py:2247 msgid "Budget certificate Date must be a valid Date." msgstr "«Budget certificate Date» debe ser una fecha válida" -#: ../Generic/base.py:2090 +#: ../Generic/base.py:2261 msgid "Invalid title list format" msgstr "Formato de lista de rótulos no válida" -#: ../Generic/base.py:2119 +#: ../Generic/base.py:2290 msgid "Invalid Index Title" msgstr "Índice de rótulo no válido" -#: ../Generic/base.py:2154 +#: ../Generic/base.py:2327 msgid "Decimal Key error" msgstr "Clave de decimales errónea" -#: ../Generic/base.py:2190 +#: ../Generic/base.py:2365 msgid "Invalid Percentage key" msgstr "Clave de porcentajes no válida" -#: ../Generic/base.py:2313 +#: ../Generic/base.py:2488 msgid "Invalid parent code: $1" msgstr "Código del padre inválido: $1" -#: ../Generic/base.py:2316 +#: ../Generic/base.py:2491 msgid "Invalid child code: $1 $2" msgstr "Código de hijo inválido: $1 $2" -#: ../Generic/base.py:2319 +#: ../Generic/base.py:2494 msgid "Invalid position in measure $1, in code $2" msgstr "Posición no válida en medición $1, en código $2" -#: ../Generic/base.py:2327 +#: ../Generic/base.py:2502 msgid "" "Circular Decomposition, parent code: $1, child code: $2, repeated code: $3" msgstr "" "Descomposición circular, código padre: $1, código hijo: $2, código repetido: " "$3" -#: ../Generic/base.py:2352 +#: ../Generic/base.py:2527 msgid "" "No-estructured measure or empty position. Parent Code: $1, Child code: $2, " "Position: $3" msgstr "" -"Mediciones no estructuradas o posicion vácia. Código padre: $1, Código hijo: $2, " -"Posición: $3" +"Mediciones no estructuradas o posicion vácia. Código padre: $1, Código hijo: " +"$2, Posición: $3" -#: ../Generic/base.py:2356 +#: ../Generic/base.py:2531 msgid "" "No-estructured measure or empty position. Repeated child in unspecified " "position. It is impossible to determine the position. New child is added in " "the decomposition. Parent code: $1, Child code: $2, Position: $3" msgstr "" "Mediciones no estructuradas o posicion vácia. Hijo repetido sin especificar " -"posición. Es imposible determinar la posición. Se añade un nuevo hijo en " -"la descomposicón. Código padre: $1, Código hijo: $2, Posición: $3" +"posición. Es imposible determinar la posición. Se añade un nuevo hijo en la " +"descomposicón. Código padre: $1, Código hijo: $2, Posición: $3" -#: ../Generic/base.py:2396 ../Generic/base.py:2408 +#: ../Generic/base.py:2571 ../Generic/base.py:2583 msgid "" "Error: Invalid child position in decomposition. Parent code: $1 Child code: " "$2 Position: $3" @@ -331,84 +358,84 @@ "Error: Posición del hijo no válida en descomposición. Código padre: $1 " "Código hijo: $2 Posición: $3" -#: ../Generic/base.py:2402 +#: ../Generic/base.py:2577 msgid "Error: Empty child code. Parent code: $1 Position: $2" msgstr "Error: Código hijo vacío. Código padre: $1 Posición: $2" -#: ../Generic/base.py:2494 +#: ../Generic/base.py:2669 msgid "Invalid code" msgstr "Código no válido" -#: ../Generic/base.py:2504 +#: ../Generic/base.py:2679 msgid "Invalid record: $1" msgstr "Registro no válido: $1" -#: ../Generic/base.py:2567 +#: ../Generic/base.py:2742 msgid "Only can be one root record" msgstr "Sólo puede haber un registro raíz" -#: ../Generic/base.py:2663 ../Generic/base.py:2669 +#: ../Generic/base.py:2851 ../Generic/base.py:2857 msgid "This record does not exits" msgstr "Este registro no existe" -#: ../Generic/base.py:2666 +#: ../Generic/base.py:2854 msgid "Path item must be a integer" msgstr "El elemento de la ruta debe ser un número entero" -#: ../Generic/base.py:2671 +#: ../Generic/base.py:2859 msgid "Path must be a not empty tuple: $1" msgstr "«Path» debe ser una tupla no vacía: $1" -#: ../Generic/base.py:2722 +#: ../Generic/base.py:2926 msgid "The sheet code must be a string" msgstr "El código del pliego debe ser una cadena de texto" -#: ../Generic/base.py:2724 +#: ../Generic/base.py:2928 msgid "The sheet title must be a string" msgstr "El título del pliego debe ser una cadena de texto." -#: ../Generic/base.py:2732 +#: ../Generic/base.py:2939 msgid "The sheet sections must be a dictionary" msgstr "La sección del pliego debe ser un dicionario" -#: ../Generic/base.py:2737 +#: ../Generic/base.py:2945 msgid "The field code must be a string" msgstr "El código del ámbito debe ser una cadena de texto" -#: ../Generic/base.py:2739 +#: ../Generic/base.py:2947 msgid "The field title must be a string" msgstr "El título del ámbito debe ser una cadena de texto." -#: ../Generic/base.py:2747 +#: ../Generic/base.py:2958 msgid "The sheet field must be a dictionary" msgstr "El ámbito del pliego debe ser un dicionario." -#: ../Generic/base.py:2752 +#: ../Generic/base.py:2964 msgid "The paragraph code must be a string" msgstr "El código del parrafo debe ser una cadena de texto." -#: ../Generic/base.py:2754 +#: ../Generic/base.py:2966 msgid "The paragraph text must be a string" msgstr "El texto del parrafo debe ser una cadena de texto" -#: ../Generic/base.py:2762 +#: ../Generic/base.py:2977 msgid "The paragraph dict must be a dictionary" msgstr "El dicionario del parrafo debe ser un diccionario" -#: ../Generic/base.py:2767 ../Generic/base.py:2791 ../Generic/base.py:2921 -#: ../Generic/base.py:2945 ../Generic/base.py:2967 +#: ../Generic/base.py:2983 ../Generic/base.py:3008 ../Generic/base.py:3147 +#: ../Generic/base.py:3171 ../Generic/base.py:3193 msgid "The record_code code must be a string" msgstr "«record_code» debe ser una cadena de texto" -#: ../Generic/base.py:2769 +#: ../Generic/base.py:2985 msgid "The field must be a string" msgstr "El ámbito debe ser una cadena de texto." -#: ../Generic/base.py:2771 +#: ../Generic/base.py:2987 msgid "The section dict must be a dictionary" msgstr "El dicionario de la seccion debe ser un dicionario." -#: ../Generic/base.py:2775 +#: ../Generic/base.py:2991 msgid "" "Error: The budget do not have this record code and can not be added the " "sheet text in the field $1. Record Code: $2" @@ -416,11 +443,11 @@ "Error: El presupuesto no tiene ese código de registro y no puede añadirse el " "texto del pliego en el ámbito $1. Código del registro: $2" -#: ../Generic/base.py:2793 +#: ../Generic/base.py:3011 msgid "The filename must be a string" msgstr "El nombre del fichero debe ser una cadena de texto." -#: ../Generic/base.py:2797 +#: ../Generic/base.py:3015 msgid "" "Error: The budget do not have the record code $1 and can not be added the " "file: $2" @@ -428,67 +455,67 @@ "Error: El presupuesto no tiene el código de registro $1 y no puede añadirse " "el fichero: $2" -#: ../Generic/base.py:2807 +#: ../Generic/base.py:3026 msgid "The company code must be a string" msgstr "El código de la entidad debe ser una cadena de texto." -#: ../Generic/base.py:2809 +#: ../Generic/base.py:3028 msgid "The summary must be a string" msgstr "El resumen debe ser una cadena de texto" -#: ../Generic/base.py:2811 ../Generic/base.py:2839 +#: ../Generic/base.py:3030 ../Generic/base.py:3058 msgid "The name must be a string" msgstr "El nombre debe ser una cadena de texto." -#: ../Generic/base.py:2813 +#: ../Generic/base.py:3032 msgid "The name must be a list" msgstr "El nombre debe ser una lista" -#: ../Generic/base.py:2817 +#: ../Generic/base.py:3036 msgid "The office must be a list" msgstr "«The office» debe ser una lista" -#: ../Generic/base.py:2819 +#: ../Generic/base.py:3038 msgid "The office must be a 10 items list" msgstr "«The office» debe ser una lista de 10 elementos" -#: ../Generic/base.py:2822 +#: ../Generic/base.py:3041 msgid "This office item must be a string" msgstr "El elemento de la oficina debe ser una cadena de texto." -#: ../Generic/base.py:2826 +#: ../Generic/base.py:3045 msgid "This office item must be a list" msgstr "Este elemento de la oficina debe ser una lista" -#: ../Generic/base.py:2841 +#: ../Generic/base.py:3060 msgid "The web must be a string" msgstr "La web debe ser una cadena de texto." -#: ../Generic/base.py:2843 +#: ../Generic/base.py:3062 msgid "The email must be a string" msgstr "El email debe ser una cadena de texto." -#: ../Generic/base.py:2853 +#: ../Generic/base.py:3074 msgid "The tecnical info code must be a string" msgstr "La información técnica debe ser una cadena de texto." -#: ../Generic/base.py:2855 +#: ../Generic/base.py:3076 msgid "The tecnical info description must be a string" msgstr "La descripción de la información técnica debe ser una cadena de texto" -#: ../Generic/base.py:2858 +#: ../Generic/base.py:3079 msgid "The tecnical info unit must be a string" msgstr "La unidad de la información técnica debe ser una cadena de texto." -#: ../Generic/base.py:2905 +#: ../Generic/base.py:3130 msgid "The label must be a string" msgstr "La etiqueta debe ser una cadena de texto." -#: ../Generic/base.py:2923 +#: ../Generic/base.py:3149 msgid "The parametric select comment must be a string" msgstr "El comentario de selección paramétrico debe ser una cadena de texto" -#: ../Generic/base.py:2926 +#: ../Generic/base.py:3152 msgid "" "Error: The budget do not have the record code $1 and can not be added the " "Parametric select comment: $2" @@ -496,7 +523,7 @@ "Error: El presupuesto no tiene el código de registro $1 y no puede añadirse " "el comentario de selección paramétrico: $2" -#: ../Generic/base.py:2933 +#: ../Generic/base.py:3159 msgid "" "Error: The Record $1 is not a Parametric Record and can not have Parametric " "comment" @@ -504,11 +531,11 @@ "Error: El registro $1 no es un registro paramétrico y no puede tener " "comentario paramétrico." -#: ../Generic/base.py:2947 +#: ../Generic/base.py:3173 msgid "The summary record must be a string" msgstr "El resumen del registro debe ser una cadena de texto" -#: ../Generic/base.py:2949 +#: ../Generic/base.py:3175 msgid "" "Error: The budget do not have the record code $1 and can not be seted the " "summary: $2" @@ -516,7 +543,7 @@ "Error: El presupuesto no tiene el codigo de registro $1 y no puede fijarse " "el resumen: $2" -#: ../Generic/base.py:2955 +#: ../Generic/base.py:3181 msgid "" "Error: The Record $1 is not a Parametric Record and can not have Parametric " "summary" @@ -524,11 +551,11 @@ "Error: El registro $1 no es un registro paramétrico y no puede tener resumen " "paramétrico." -#: ../Generic/base.py:2969 +#: ../Generic/base.py:3195 msgid "The text record must be a string" msgstr "El texto del registro debe ser una cadena de texto" -#: ../Generic/base.py:2971 +#: ../Generic/base.py:3197 msgid "" "Error: The budget do not have the record code $1 and can not be seted the " "text: $2" @@ -536,7 +563,7 @@ "Error: El presupuesto no tiene el codigo de registro $1 y no puede fijarse " "el texto: $2" -#: ../Generic/base.py:2977 +#: ../Generic/base.py:3203 msgid "" "Error: The Record $1 is not a Parametric Record and can not have Parametric " "text" @@ -544,15 +571,15 @@ "Error: El registro $1 no es un registro paramétrico y no puede tener texto " "paramétrico." -#: ../Generic/base.py:3435 +#: ../Generic/base.py:3726 msgid "Invalid Hierarchy ($1) The hierarchy must be -1, 0, 1, 2" msgstr "Categoría no válida ($1) La categoria debe ser -1, 0, 1 or 2" -#: ../Generic/base.py:3445 +#: ../Generic/base.py:3738 msgid "Invalid type ($1),the type must be (empty string,0,1,2,3)" msgstr "Tipo no válido ($1), el tipo debe ser (cadena vacía, 0, 1, 2, 3)" -#: ../Generic/base.py:3454 +#: ../Generic/base.py:3749 msgid "" "Invalid subtype ($1), The subtype must one in (empty string, EA, EU, EC, EF, " "OB, PA, PU, H, Q, %, MC, MCr, MM, MS, ME, MCu, MAl, ML, M)" @@ -560,35 +587,28 @@ "Subtipo no válido ($1), el subtipo debe ser uno de (cadena vacía, EA, EU, " "EC, EF, OB, PA, PU, H, Q, %, MC, MCr, MM, MS, ME, MCu, MAl, ML, M)" -#: ../Generic/durusdatabase.py:48 -msgid "Incorrent Base version" -msgstr "Versión de la Base incorrecta" - -#: ../Generic/durusdatabase.py:77 -msgid "Loading file: $1:" -msgstr "Cargando archivo: $1" - -#: ../Generic/durusdatabase.py:82 -msgid "Loadig time: $1 seconds" -msgstr "Tiempo de carga: $1 segundos" - -#: ../Generic/fiebdc.py:152 +#: ../Generic/fiebdc.py:150 msgid "Invalid code, it must be a unicode string" msgstr "Código no válido, debe ser una cadena unicode" -#: ../Generic/fiebdc.py:159 -msgid "The code '$1' have invalid characters." -msgstr "El código «$1» tiene caracteres inválidos." +#: ../Generic/fiebdc.py:157 +msgid "The code '$1' have invalid characters, replaced by '$2'." +msgstr "El código «$1» tiene caracteres inválidos, reemplazado por «$2»." -#: ../Generic/fiebdc.py:162 +#: ../Generic/fiebdc.py:160 msgid "The code '$1' have invalid characters and can not be encoded in utf8." -msgstr "El código «$1» tiene caracteres inválidos y no puede ser codificado en utf8." +msgstr "" +"El código «$1» tiene caracteres inválidos y no puede ser codificado en utf8." -#: ../Generic/fiebdc.py:184 +#: ../Generic/fiebdc.py:187 msgid "The code '$1' contains special characters repeated." msgstr "El código «$1» contiene caractectes especiales repetidos." -#: ../Generic/fiebdc.py:405 +#: ../Generic/fiebdc.py:391 +msgid "FIEBDC. Unknow record: $1" +msgstr "FIEBDC. Registro desconocido: $1" + +#: ../Generic/fiebdc.py:410 msgid "" "The 'V' record (Property and Version) must be the first record in the file " "but it is the number: $1" @@ -596,27 +616,27 @@ "El registro «V» (Propiedad y versión) debe ser el primer registro en el " "archivo pero es el número: $1" -#: ../Generic/fiebdc.py:408 +#: ../Generic/fiebdc.py:413 msgid "The default values were taken and this V record is ignored" msgstr "El valor por amisión ha sido tomado y el registro V es ignorado" -#: ../Generic/fiebdc.py:442 +#: ../Generic/fiebdc.py:447 msgid "FIEBDC format: $1" -msgstr "Formato FIEBDC: $1" +msgstr "FIEBDC formato: $1" -#: ../Generic/fiebdc.py:452 +#: ../Generic/fiebdc.py:457 msgid "FIEBDC file generated by $1" -msgstr "Fichero FIEBDC generado por $1" +msgstr "FIEBDC fichero generado por $1" -#: ../Generic/fiebdc.py:793 +#: ../Generic/fiebdc.py:798 msgid "Record C without a valid code" msgstr "Registro C sin un código válido" -#: ../Generic/fiebdc.py:869 ../Generic/fiebdc.py:881 ../Generic/fiebdc.py:909 +#: ../Generic/fiebdc.py:876 ../Generic/fiebdc.py:888 ../Generic/fiebdc.py:916 msgid "Incorrect type ($1) in the code $2" msgstr "Tipo incorrecto ($1) en el código $2" -#: ../Generic/fiebdc.py:961 +#: ../Generic/fiebdc.py:970 msgid "" "ValueError loadig the descomposition of the record $1, the factor of the " "child $2 must be a float number and can not be $3, seted default value 1.0" @@ -625,7 +645,7 @@ "hijo $2 debe ser un número de coma flotante y no puede ser $3, fijado el " "valor por omisión 1.0" -#: ../Generic/fiebdc.py:972 +#: ../Generic/fiebdc.py:981 msgid "" "ValueError loading the descomposition of the record $1, the yield of the " "child $2, must be a float number and cannot be $3, seted default value 1.0" @@ -634,23 +654,25 @@ "del hijo $2, debe ser un número de coma flotante y no puede ser $3, fijado " "el valor por omisión 1.0" -#: ../Generic/fiebdc.py:1060 +#: ../Generic/fiebdc.py:1070 msgid "Invalid codes in $1 record, codes $2" msgstr "Códigos no válidos en registro $1, códigos $2" -#: ../Generic/fiebdc.py:1064 +#: ../Generic/fiebdc.py:1074 msgid "Empty child code in $1 record, codes: $2" msgstr "Código de hijo vacío en el registro $1, códigos: $2" -#: ../Generic/fiebdc.py:1084 +#: ../Generic/fiebdc.py:1094 msgid "Invalid path in $1 record, codes $2" msgstr "Camino no válido en el registro $1, códigos $2" -#: ../Generic/fiebdc.py:1095 +#: ../Generic/fiebdc.py:1105 msgid "Invalid Total Measure value in $1 record, codes $2. Total fixed to 0." -msgstr "El Total de la medición no es válido en el registro $1, códigos $2. Total fijado a 0." +msgstr "" +"El Total de la medición no es válido en el registro $1, códigos $2. Total " +"fijado a 0." -#: ../Generic/fiebdc.py:1116 +#: ../Generic/fiebdc.py:1126 msgid "" "The comment is not a formula or its have invalid characters, in the $1 " "record, codes $2" @@ -658,270 +680,294 @@ "El comentario no es una fórmula o tiene caracteres inválidos, en el registro " "$1, códigos $2" -#: ../Generic/fiebdc.py:1142 +#: ../Generic/fiebdc.py:1152 msgid "The measure values are not float numbers, code $1" msgstr "«Measure» debe ser un número de coma flotante. Tipo: $1" -#: ../Generic/fiebdc.py:1438 ../Generic/fiebdc.py:1697 +#: ../Generic/fiebdc.py:1452 ../Generic/fiebdc.py:1717 msgid "The file $1 do not exist" msgstr "El archivo $1 no existe" -#: ../Generic/fiebdc.py:1803 ../Generic/fiebdc.py:1810 +#: ../Generic/fiebdc.py:1823 ../Generic/fiebdc.py:1830 msgid "PyArq hates parametric DLLs" msgstr "PyArq odia las DLLs paramétricas" -#: ../Generic/fiebdc.py:2019 +#: ../Generic/fiebdc.py:2028 msgid "Loading file $1" msgstr "Cargando archivo $1" -#: ../Generic/fiebdc.py:2038 +#: ../Generic/fiebdc.py:2049 msgid "FIEBDC character encoding: $1" msgstr "FIEBDC codificación de caracteres: $1" -#: ../Generic/fiebdc.py:2040 +#: ../Generic/fiebdc.py:2053 msgid "" "This Character encoding do not exist in FIEBDC3! Default Character encoding: " "$1" msgstr "¡Esta codificación no existe en FIEBDC3! Codificación por omisión: $1" -#: ../Generic/fiebdc.py:2044 +#: ../Generic/fiebdc.py:2058 msgid "" "This V record dot have a character encoding! Default character encoding: $1" msgstr "¡Este registro V no define codificación! Codificación por omisión: $1" -#: ../Generic/fiebdc.py:2048 +#: ../Generic/fiebdc.py:2063 msgid "Not 'V' record in File! Default character encoding: $1" msgstr "¡No hay registro «V» en el archivo! Codificación por omisión: $1" -#: ../Generic/fiebdc.py:2085 -msgid "Process terminated" -msgstr "Proceso cancelado" - -#: ../Generic/fiebdc.py:2088 -msgid "Time to load: $1 seconds" -msgstr "Tiempo de carga: $1 segundos" - -#: ../Generic/fiebdc.py:2090 -msgid "Records/Valid Records: $1/$2" -msgstr "Registro/Registros válidos: $1/$2" - -#: ../Generic/fiebdc.py:2093 +#: ../Generic/fiebdc.py:2111 msgid "$1 unsuported record type O: Comercial Relationship" msgstr "$1 tipo de registro no soportado O: Releción comercial" -#: ../Generic/fiebdc.py:2096 +#: ../Generic/fiebdc.py:2114 msgid "This file is not a valid FIBDC3 file" msgstr "El archivo no es un archivo FIEBDC3 válido" -#: ../Generic/fiebdc.py:2133 +#: ../Generic/fiebdc.py:2127 msgid "Testing budget ..." msgstr "Comprobando presupuesto ..." -#: ../Generic/fiebdc.py:2151 +#: ../Generic/fiebdc.py:2146 msgid "End Test" msgstr "Comprobación finalizada" -#: ../Gtk/gui.py:68 +#: ../Generic/fiebdc.py:2230 ../Gtk/gui.py:1038 +msgid "Process terminated" +msgstr "Proceso cancelado" + +#: ../Generic/fiebdc.py:2312 +msgid "Time to load: $1 seconds" +msgstr "Tiempo de carga: $1 segundos" + +#: ../Generic/fiebdc.py:2314 +msgid "Records/Valid Records: $1/$2" +msgstr "Registro/Registros válidos: $1/$2" + +#: ../Gtk/gui.py:83 ../Gtk/gui.py:89 msgid "The icon file does not exist. '$1'" msgstr "El archivo de icono no existe. «$1»" -#: ../Gtk/gui.py:74 +#: ../Gtk/gui.py:95 msgid "pyArq-Presupuestos running on $1" msgstr "pyArq-Presupuestos ejecutandose en $1" -#: ../Gtk/gui.py:169 -msgid "_File" -msgstr "_Archivo" +#: ../Gtk/gui.py:176 +msgid "_New window" +msgstr "Ventana _Nueva" + +#: ../Gtk/gui.py:177 +msgid "_Close window" +msgstr "_Cerrar ventana" -#: ../Gtk/gui.py:170 +#: ../Gtk/gui.py:182 +msgid "About" +msgstr "Acerca de" + +#: ../Gtk/gui.py:185 +msgid "_Quit application" +msgstr "_Cerrar aplicación" + +#: ../Gtk/gui.py:195 msgid "_Import Fiebdc" msgstr "_Importar Fiebdc" -#: ../Gtk/gui.py:171 -msgid "Import FIEBDC" -msgstr "Importar FIEBDC" - -#: ../Gtk/gui.py:172 -msgid "_Close" -msgstr "_Cerrar" - -#: ../Gtk/gui.py:172 -msgid "Close" -msgstr "Cerrar" +#: ../Gtk/gui.py:199 ../Gtk/gui.py:400 ../Gtk/gui.py:955 +msgid "_Close tab" +msgstr "_Cerrar pestaña" -#: ../Gtk/gui.py:174 -msgid "_View" -msgstr "_Ver" +#: ../Gtk/gui.py:203 +msgid "_File" +msgstr "_Archivo" -#: ../Gtk/gui.py:175 ../Gtk/gui.py:185 -msgid "_Go" -msgstr "_Ir" - -#: ../Gtk/gui.py:176 -msgid "_Test" -msgstr "_Pruebas" - -#: ../Gtk/gui.py:186 +#: ../Gtk/gui.py:205 msgid "_Back" msgstr "A_tras" -#: ../Gtk/gui.py:187 ../Gtk/gui.py:198 -msgid "Go to the previous visited item" -msgstr "Ir al concepto anterior" - -#: ../Gtk/gui.py:189 +#: ../Gtk/gui.py:208 msgid "_Forward" msgstr "A_delante" -#: ../Gtk/gui.py:190 ../Gtk/gui.py:202 -msgid "Go to the next visited item" -msgstr "Ir al concepto siguiente" - -#: ../Gtk/gui.py:191 +#: ../Gtk/gui.py:211 msgid "_Up Item" msgstr "Concepto _Superior" -#: ../Gtk/gui.py:192 -msgid "Go up item" -msgstr "Ir al concepto superior" - -#: ../Gtk/gui.py:193 +#: ../Gtk/gui.py:214 msgid "_Root" msgstr "_Raiz" -#: ../Gtk/gui.py:194 -msgid "Go to root" -msgstr "Ir a la raiz" +#: ../Gtk/gui.py:217 +msgid "_Go" +msgstr "_Ir" + +#: ../Gtk/gui.py:391 ../Gtk/gui.py:392 +msgid "Import Fiebdc" +msgstr "Importar Fiebdc" + +#: ../Gtk/gui.py:401 ../Gtk/gui.py:956 +msgid "Close tab" +msgstr "Cerrar pestaña" -#: ../Gtk/gui.py:221 -msgid "Back history" -msgstr "Retroceder histórico" +#: ../Gtk/gui.py:413 ../Gtk/gui.py:414 +msgid "Back" +msgstr "Atras" + +#: ../Gtk/gui.py:422 ../Gtk/gui.py:423 +msgid "Forward" +msgstr "Adelante" -#: ../Gtk/gui.py:226 -msgid "Forward history" -msgstr "Adelantar histórico" +#: ../Gtk/gui.py:431 ../Gtk/gui.py:432 +msgid "Up Item" +msgstr "Concepto Superior" -#: ../Gtk/gui.py:444 +#: ../Gtk/gui.py:440 ../Gtk/gui.py:441 +msgid "Root" +msgstr "Raiz" + +#: ../Gtk/gui.py:655 msgid "The page is not in the page list" msgstr "La pestaña no está en la lista de pestañas" -#: ../Gtk/gui.py:673 ../Gtk/importFiebdc.py:220 +#: ../Gtk/gui.py:792 ../Gtk/gui.py:793 +msgid "Open File" +msgstr "Abrir archivo" + +#: ../Gtk/gui.py:794 +msgid "Cancel" +msgstr "Cancelar" + +#: ../Gtk/gui.py:833 +msgid "The file must have 'bc3' extension" +msgstr "El archivo debe tener extensión «bc3»" + +#: ../Gtk/gui.py:991 msgid "Time: 0s" msgstr "Tiempo: 0s" -#: ../Gtk/gui.py:750 ../Gtk/importFiebdc.py:299 +#: ../Gtk/gui.py:1104 msgid "Time: $1" msgstr "Tiempo: $1" -#: ../Gtk/gui.py:1076 +#: ../Gtk/gui.py:1455 msgid "The value must be a list" msgstr "El valor debe ser una lista" -#: ../Gtk/gui.py:1079 +#: ../Gtk/gui.py:1458 msgid "Incorrect len" msgstr "Longuitud incorrecta" -#: ../Gtk/gui.py:1107 +#: ../Gtk/gui.py:1486 msgid "Incorrect item $1" msgstr "Elemento incorrecto $1" -#: ../Gtk/gui.py:1123 +#: ../Gtk/gui.py:1502 msgid "The budget does not have the path record: $1" msgstr "El presupuesto no tiene el registro con camino: $1" -#: ../Gtk/gui.py:1479 +#: ../Gtk/gui.py:1865 msgid "Decomposition" msgstr "Descomposición" -#: ../Gtk/gui.py:1480 ../Gtk/gui.py:2486 +#: ../Gtk/gui.py:1866 ../Gtk/gui.py:2895 msgid "Description" msgstr "Descripción" -#: ../Gtk/gui.py:1481 ../Gtk/gui.py:2488 +#: ../Gtk/gui.py:1867 ../Gtk/gui.py:2897 msgid "Measure" msgstr "Medición" -#: ../Gtk/gui.py:1482 +#: ../Gtk/gui.py:1868 msgid "Sheet of Conditions" msgstr "Pliego de condicones" -#: ../Gtk/gui.py:1483 +#: ../Gtk/gui.py:1869 msgid "Files" msgstr "Archivos" -#: ../Gtk/gui.py:1484 +#: ../Gtk/gui.py:1870 msgid "Companies" msgstr "Entidades" -#: ../Gtk/gui.py:1661 +#: ../Gtk/gui.py:1950 msgid "Split View Left/Right" msgstr "Partir vista Izquierda/Derecha" -#: ../Gtk/gui.py:1665 +#: ../Gtk/gui.py:1960 msgid "Split View Top/Bottom" msgstr "Partir vista Arriba/Abajo" -#: ../Gtk/gui.py:1669 +#: ../Gtk/gui.py:1968 +msgid "Disconnect view" +msgstr "Desconectar vista" + +#: ../Gtk/gui.py:1971 +msgid "Connect view" +msgstr "Concectar vista" + +#: ../Gtk/gui.py:1984 ../Gtk/gui.py:2081 msgid "Close view" msgstr "Cerrar vista" -#: ../Gtk/gui.py:1837 +#: ../Gtk/gui.py:2073 +msgid "Split view Left/Right" +msgstr "Partir vista Izquierda/Derecha" + +#: ../Gtk/gui.py:2077 +msgid "Split view Top/Bottom" +msgstr "Partir vista Arriba/Abajo" + +#: ../Gtk/gui.py:2112 +msgid "Connect View" +msgstr "Conectar vista" + +#: ../Gtk/gui.py:2118 +msgid "Disconnect View" +msgstr "Desconectar vista" + +#: ../Gtk/gui.py:2248 msgid "The item must be a widget object." msgstr "El elemento debe ser un objeto «widget»." -#: ../Gtk/gui.py:1843 +#: ../Gtk/gui.py:2256 msgid "Invalid orientation." msgstr "Orientación no válida" -#: ../Gtk/gui.py:2215 ../Gtk/gui.py:2842 ../Gtk/gui.py:4172 +#: ../Gtk/gui.py:2628 ../Gtk/gui.py:3256 ../Gtk/gui.py:4674 msgid "Argument must be a Budget object" msgstr "El argumento debe ser un objeto «Budget»" -#: ../Gtk/gui.py:2224 -msgid "Record path can not be None" -msgstr "La ruta del registrio no puede ser None" - -#: ../Gtk/gui.py:2255 -msgid "a" -msgstr "a" - -#: ../Gtk/gui.py:2483 ../Gtk/gui.py:4235 +#: ../Gtk/gui.py:2892 ../Gtk/gui.py:4739 msgid "Code" msgstr "Código" -#: ../Gtk/gui.py:2484 +#: ../Gtk/gui.py:2893 msgid "Unit" msgstr "Unidad" -#: ../Gtk/gui.py:2490 +#: ../Gtk/gui.py:2899 msgid "Price" msgstr "Precio" -#: ../Gtk/gui.py:2492 +#: ../Gtk/gui.py:2901 msgid "Amount" msgstr "Importe" -#: ../Gtk/gui.py:2503 ../Gtk/gui.py:2982 +#: ../Gtk/gui.py:2912 ../Gtk/gui.py:3528 msgid "Invalid path" msgstr "Ruta no válida" -#: ../Gtk/gui.py:2847 +#: ../Gtk/gui.py:3261 msgid "Record path must be a tuple" msgstr "La posición del registro debe ser una tupla" -#: ../Gtk/gui.py:2991 -msgid "measure must be a Measure object. Type: $1" -msgstr "«measure» debe ser un objeto «Measure». Tipo: $1" - -#: ../Gtk/gui.py:3003 ../Gtk/gui.py:4250 ../Gtk/gui.py:4563 +#: ../Gtk/gui.py:3509 ../Gtk/gui.py:4754 ../Gtk/gui.py:5066 msgid "Type" msgstr "Tipo" -#: ../Gtk/gui.py:3004 +#: ../Gtk/gui.py:3510 msgid "Comment" msgstr "Comentario" -#: ../Gtk/gui.py:3005 +#: ../Gtk/gui.py:3511 msgid "" "N\n" "(a)" @@ -929,7 +975,7 @@ "N\n" "(a)" -#: ../Gtk/gui.py:3006 +#: ../Gtk/gui.py:3512 msgid "" "Length\n" "(b)" @@ -937,7 +983,7 @@ "Longitud\n" "(b)" -#: ../Gtk/gui.py:3007 +#: ../Gtk/gui.py:3513 msgid "" "Width\n" "(c)" @@ -945,7 +991,7 @@ "Anchura\n" "(c)" -#: ../Gtk/gui.py:3008 +#: ../Gtk/gui.py:3514 msgid "" "Height\n" "(d)" @@ -953,11 +999,11 @@ "Altura\n" "(d)" -#: ../Gtk/gui.py:3009 +#: ../Gtk/gui.py:3515 msgid "Formula" msgstr "Fórmula" -#: ../Gtk/gui.py:3010 +#: ../Gtk/gui.py:3516 #, python-format msgid "" "Parcial\n" @@ -966,227 +1012,256 @@ "Parcial\n" "[%s]" -#: ../Gtk/gui.py:3011 +#: ../Gtk/gui.py:3517 msgid "Subtotal" msgstr "Subtotal" -#: ../Gtk/gui.py:3419 ../Gtk/gui.py:3441 +#: ../Gtk/gui.py:3537 +msgid "measure must be a Measure object. Type: $1" +msgstr "«measure» debe ser un objeto «Measure». Tipo: $1" + +#: ../Gtk/gui.py:3835 ../Gtk/gui.py:3856 msgid "Description text of the record $1" msgstr "Texto descriptivo del registro $1" -#: ../Gtk/gui.py:3592 +#: ../Gtk/gui.py:4010 msgid "Sheet of Conditions of the record $1" msgstr "Pliego de condiciones del registro $1" -#: ../Gtk/gui.py:3610 +#: ../Gtk/gui.py:4031 msgid "Field" msgstr "Ámbito" -#: ../Gtk/gui.py:3631 +#: ../Gtk/gui.py:4054 msgid "Section" msgstr "Sección" -#: ../Gtk/gui.py:3779 +#: ../Gtk/gui.py:4214 msgid "Sheet2 of Conditions of the record $1" msgstr "Pliego2 de condiciones del registro $1" -#: ../Gtk/gui.py:4236 +#: ../Gtk/gui.py:4740 msgid "Code that define the company" msgstr "Código que define la entidad" -#: ../Gtk/gui.py:4237 +#: ../Gtk/gui.py:4741 msgid "Summary" msgstr "Resumen" -#: ../Gtk/gui.py:4238 +#: ../Gtk/gui.py:4742 msgid "Summary of the company name" msgstr "Resumen del nombre de la entidad" -#: ../Gtk/gui.py:4239 ../Gtk/gui.py:4255 +#: ../Gtk/gui.py:4743 ../Gtk/gui.py:4759 msgid "Name" msgstr "Nombre" -#: ../Gtk/gui.py:4240 +#: ../Gtk/gui.py:4744 msgid "Complete name" msgstr "Nombre completo" -#: ../Gtk/gui.py:4241 +#: ../Gtk/gui.py:4745 msgid "CIF" msgstr "CIF" -#: ../Gtk/gui.py:4242 +#: ../Gtk/gui.py:4746 msgid "Fiscal identifier number" msgstr "Número de identificación fiscal" -#: ../Gtk/gui.py:4243 +#: ../Gtk/gui.py:4747 msgid "Web" msgstr "Web" -#: ../Gtk/gui.py:4244 +#: ../Gtk/gui.py:4748 msgid "Company web page" msgstr "Página web de la entidad" -#: ../Gtk/gui.py:4245 +#: ../Gtk/gui.py:4749 msgid "Email" msgstr "Email" -#: ../Gtk/gui.py:4246 +#: ../Gtk/gui.py:4750 msgid "Company email" msgstr "Correo electrónico de la entidad" -#: ../Gtk/gui.py:4251 +#: ../Gtk/gui.py:4755 msgid "" "Type of Office:\n" " C: Central office\n" " D: Local office\n" " R: Performer" msgstr "" -"Type of Office:\n" +"Tipo de oficina:\n" " C: Oficina central\n" " D: Delegación\n" " R: Representante" -#: ../Gtk/gui.py:4256 +#: ../Gtk/gui.py:4760 msgid "Office name" msgstr "Nombre de la oficina" -#: ../Gtk/gui.py:4257 +#: ../Gtk/gui.py:4761 msgid "Address" msgstr "Dirección" -#: ../Gtk/gui.py:4258 +#: ../Gtk/gui.py:4762 msgid "Postal code" msgstr "Código postal" -#: ../Gtk/gui.py:4259 +#: ../Gtk/gui.py:4763 msgid "Town" msgstr "Ciudad" -#: ../Gtk/gui.py:4260 +#: ../Gtk/gui.py:4764 msgid "Province" msgstr "Provincia" -#: ../Gtk/gui.py:4261 +#: ../Gtk/gui.py:4765 msgid "Country" msgstr "Ciudad" -#: ../Gtk/gui.py:4262 +#: ../Gtk/gui.py:4766 msgid "Phone" msgstr "Teléfono" -#: ../Gtk/gui.py:4263 +#: ../Gtk/gui.py:4767 msgid "Phone numbers of the office" msgstr "Teléfono de la officina" -#: ../Gtk/gui.py:4264 +#: ../Gtk/gui.py:4768 msgid "Fax" msgstr "Fax" -#: ../Gtk/gui.py:4265 +#: ../Gtk/gui.py:4769 msgid "Fax numbers of the office" msgstr "Fax de la oficina" -#: ../Gtk/gui.py:4266 +#: ../Gtk/gui.py:4770 msgid "Contact person" msgstr "Persona de contacto" -#: ../Gtk/gui.py:4267 +#: ../Gtk/gui.py:4771 msgid "Contact persons in the office" msgstr "Persona de contacto en la oficina" -#: ../Gtk/gui.py:4271 +#: ../Gtk/gui.py:4775 msgid "Unknow Option Type" msgstr "Tipo de opcion desconocida" -#: ../Gtk/gui.py:4501 +#: ../Gtk/gui.py:5002 msgid "Boolean" msgstr "Booleano" -#: ../Gtk/gui.py:4502 +#: ../Gtk/gui.py:5003 msgid "Integer" msgstr "Entero" -#: ../Gtk/gui.py:4503 +#: ../Gtk/gui.py:5004 msgid "Text" msgstr "Texto" -#: ../Gtk/gui.py:4504 +#: ../Gtk/gui.py:5005 msgid "Color" msgstr "Color" -#: ../Gtk/gui.py:4505 +#: ../Gtk/gui.py:5006 msgid "List" msgstr "Lista" -#: ../Gtk/gui.py:4537 +#: ../Gtk/gui.py:5040 msgid "Option name" msgstr "Nombre de Opción" -#: ../Gtk/gui.py:4550 +#: ../Gtk/gui.py:5053 msgid "Value" msgstr "Valor" -#: ../Gtk/gui.py:4589 +#: ../Gtk/gui.py:5094 msgid "Description:" msgstr "Descripción:" -#: ../Gtk/gui.py:4750 +#: ../Gtk/gui.py:5258 msgid "Option values must be strings" msgstr "Los valores de la opción deben ser cadenas" -#: ../Gtk/gui.py:4752 +#: ../Gtk/gui.py:5260 msgid "Option must be a tuple with 4 items" msgstr "La opcion debe ser una tupla de 4 elementos" -#: ../Gtk/gui.py:4754 +#: ../Gtk/gui.py:5262 msgid "Option list must be a list" msgstr "La lista de opciones debe ser una lista lista" -#: ../Gtk/gui.py:4774 +#: ../Gtk/gui.py:5282 msgid "Icorrect type, must be boolean" msgstr "Tipo erroneo, debe ser booleano" -#: ../Gtk/gui.py:4779 +#: ../Gtk/gui.py:5287 msgid "Icorrect type, must be integer" msgstr "Tipo erroneo, debe ser un número entero" -#: ../Gtk/gui.py:4792 +#: ../Gtk/gui.py:5300 msgid "Icorrect type, must be string" msgstr "Tipo erroneo, debe ser una cadena de texto" -#: ../Gtk/gui.py:4805 +#: ../Gtk/gui.py:5313 msgid "Icorrect type, must be list" msgstr "Tipo erroneo, debe ser una lista" -#: ../Gtk/gui.py:4811 +#: ../Gtk/gui.py:5317 msgid "Icorrect type, must be a parseable color" msgstr "Tipo erroneo, debe ser un color parseable" -#: ../Gtk/gui.py:4819 +#: ../Gtk/gui.py:5325 msgid "Type must be boolean, integer, string or color" msgstr "El tipo debe ser booleano, entero, cadena de texto o color" -#: ../Gtk/gui.py:4822 +#: ../Gtk/gui.py:5328 msgid "Value must be in the option dict" msgstr "El valor debe estar en el diccionario de opciones" -#: ../Gtk/gui.py:4824 +#: ../Gtk/gui.py:5331 msgid "Values must be a dict" msgstr "El valor debe ser un dicionario" -#: ../Gtk/importFiebdc.py:91 -msgid "Open File" -msgstr "Abrir archivo" +#~ msgid "Incorrent Base version" +#~ msgstr "Versión de la Base incorrecta" + +#~ msgid "Loadig time: $1 seconds" +#~ msgstr "Tiempo de carga: $1 segundos" + +#~ msgid "Import FIEBDC" +#~ msgstr "Importar FIEBDC" -#: ../Gtk/importFiebdc.py:135 -msgid "The file must have 'bc3' extension" -msgstr "El archivo debe tener extensión «bc3»" +#~ msgid "_View" +#~ msgstr "_Ver" + +#~ msgid "_Test" +#~ msgstr "_Pruebas" + +#~ msgid "Go to the previous visited item" +#~ msgstr "Ir al concepto anterior" + +#~ msgid "Go to the next visited item" +#~ msgstr "Ir al concepto siguiente" -#: ../Gtk/importFiebdc.py:208 -msgid "Loading file ..." -msgstr "Cargando archivo ..." +#~ msgid "Go up item" +#~ msgstr "Ir al concepto superior" + +#~ msgid "Go to root" +#~ msgstr "Ir a la raiz" + +#~ msgid "Back history" +#~ msgstr "Retroceder histórico" -#: ../Gtk/importFiebdc.py:232 -msgid "Cancel" -msgstr "Cancelar" +#~ msgid "Forward history" +#~ msgstr "Adelantar histórico" + +#~ msgid "Record path can not be None" +#~ msgstr "La ruta del registrio no puede ser None" +#~ msgid "a" +#~ msgstr "a" + +#~ msgid "Loading file ..." +#~ msgstr "Cargando archivo ..." diff -r 7bd4ca56607d -r 65e7ae0d0e63 mo/pyArq-Presupuestos.pot --- a/mo/pyArq-Presupuestos.pot Tue Sep 30 17:16:50 2014 +0200 +++ b/mo/pyArq-Presupuestos.pot Thu May 02 16:31:17 2019 +0200 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-11-02 18:58+0100\n" +"POT-Creation-Date: 2019-04-27 10:53+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,973 +17,1010 @@ "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: ../Generic/base.py:359 +#: ../Generic/base.py:283 +msgid "" +"\n" +"A free program of measurements, budgets and control of construction sites.\n" +"In beta development, still there is not a fully functional version.\n" +msgstr "" + +#: ../Generic/base.py:288 +msgid "" +"\n" +"Usage:\n" +" pyarqPresupuestos [file]...\n" +"\n" +"Help Options:\n" +" -h, --help Show this help\n" +msgstr "" + +#: ../Generic/base.py:421 msgid "Invalid code: $1" msgstr "" -#: ../Generic/base.py:374 +#: ../Generic/base.py:436 msgid "Synonyms ($1) must be a list, code: $2" msgstr "" -#: ../Generic/base.py:378 +#: ../Generic/base.py:440 msgid "Invalid Code in synomyms list ($1) code: $2" msgstr "" -#: ../Generic/base.py:409 +#: ../Generic/base.py:471 msgid "Unit ($1) must be a string: $2" msgstr "" -#: ../Generic/base.py:423 +#: ../Generic/base.py:485 msgid "Summary ($1) must be a string: $1" msgstr "" -#: ../Generic/base.py:440 +#: ../Generic/base.py:502 msgid "Prices ($1) must be a list: $2" msgstr "" -#: ../Generic/base.py:461 +#: ../Generic/base.py:523 msgid "Price ($1) must be a list with two items: $2" msgstr "" -#: ../Generic/base.py:466 +#: ../Generic/base.py:528 msgid "Price must be a float number: $1" msgstr "" -#: ../Generic/base.py:476 +#: ../Generic/base.py:538 #, python-format msgid "The record do not have this Price. Code: %s" msgstr "" -#: ../Generic/base.py:482 +#: ../Generic/base.py:544 msgid "The record do not have this Price" msgstr "" -#: ../Generic/base.py:497 +#: ../Generic/base.py:559 msgid "Parents ($1) must be a list: $2" msgstr "" -#: ../Generic/base.py:501 ../Generic/base.py:513 +#: ../Generic/base.py:563 ../Generic/base.py:575 msgid "Invalid parent code ($1) in the record: $2" msgstr "" -#: ../Generic/base.py:529 +#: ../Generic/base.py:591 msgid "children ($1) must be a list, record: $2" msgstr "" -#: ../Generic/base.py:533 +#: ../Generic/base.py:595 msgid "child ($1) must be a Decomposition object, record: $2" msgstr "" -#: ../Generic/base.py:581 +#: ../Generic/base.py:649 msgid "Text ($1) must be a string, record: $2" msgstr "" -#: ../Generic/base.py:594 +#: ../Generic/base.py:662 msgid "sheet must be a Sheet instance" msgstr "" -#: ../Generic/base.py:607 +#: ../Generic/base.py:674 msgid "files must be a list: $1" msgstr "" -#: ../Generic/base.py:618 ../Generic/base.py:633 +#: ../Generic/base.py:685 ../Generic/base.py:699 msgid "Incorrect path" msgstr "" -#: ../Generic/base.py:623 +#: ../Generic/base.py:690 msgid "file must be a list or a File object: $1" msgstr "" -#: ../Generic/base.py:652 +#: ../Generic/base.py:718 msgid "labels must be a list" msgstr "" -#: ../Generic/base.py:658 +#: ../Generic/base.py:724 msgid "label must be a string" msgstr "" -#: ../Generic/base.py:667 +#: ../Generic/base.py:733 msgid "Label must be a string" msgstr "" -#: ../Generic/base.py:907 +#: ../Generic/base.py:981 msgid "Position must be a integer" msgstr "" -#: ../Generic/base.py:917 +#: ../Generic/base.py:995 msgid "BudgetMeasures atribute must be a list" msgstr "" -#: ../Generic/base.py:920 +#: ../Generic/base.py:998 msgid "BudgetMeasures item must be a Measure " msgstr "" -#: ../Generic/base.py:927 +#: ../Generic/base.py:1007 msgid "Certification atribute must be a list or None" msgstr "" -#: ../Generic/base.py:933 +#: ../Generic/base.py:1015 msgid "Real cost atribute must be a list or None" msgstr "" -#: ../Generic/base.py:939 +#: ../Generic/base.py:1023 msgid "Cost goals atribute must be a list or None" msgstr "" -#: ../Generic/base.py:945 +#: ../Generic/base.py:1031 msgid "Cost Planned atribute must be a list or None" msgstr "" -#: ../Generic/base.py:1036 +#: ../Generic/base.py:1124 msgid "Measure must be a float number. Type: $1" msgstr "" -#: ../Generic/base.py:1047 +#: ../Generic/base.py:1136 msgid "Lines must be a list" msgstr "" -#: ../Generic/base.py:1050 +#: ../Generic/base.py:1139 msgid "Line must be a MeasureLine objetc" msgstr "" -#: ../Generic/base.py:1058 +#: ../Generic/base.py:1150 msgid "Factor must be a float number |$1|" msgstr "" -#: ../Generic/base.py:1070 +#: ../Generic/base.py:1162 msgid "Yield must be a float number" msgstr "" -#: ../Generic/base.py:1081 +#: ../Generic/base.py:1173 msgid "Fixed must be boolean object" msgstr "" -#: ../Generic/base.py:1151 +#: ../Generic/base.py:1243 msgid "Type must be M or A. Type: $1" msgstr "" -#: ../Generic/base.py:1283 +#: ../Generic/base.py:1387 msgid " Parcial Subtotal must be a float number. Parcial: $1" msgstr "" -#: ../Generic/base.py:1290 +#: ../Generic/base.py:1395 msgid " Acumulated Subtotal must be a float number. Parcial: $1" msgstr "" -#: ../Generic/base.py:1325 +#: ../Generic/base.py:1431 msgid "Invalid measure line type ($1)" msgstr "" -#: ../Generic/base.py:1330 +#: ../Generic/base.py:1437 msgid "Measure Comment must be a string ($1)" msgstr "" -#: ../Generic/base.py:1336 +#: ../Generic/base.py:1444 msgid "Invalid Measure Units ($1)" msgstr "" -#: ../Generic/base.py:1348 +#: ../Generic/base.py:1457 msgid "Invalid Measure length ($1)" msgstr "" -#: ../Generic/base.py:1360 +#: ../Generic/base.py:1470 msgid "Invalid Measure Width ($1)" msgstr "" -#: ../Generic/base.py:1372 +#: ../Generic/base.py:1483 msgid "Invalid Measure Height ($1)" msgstr "" -#: ../Generic/base.py:1383 +#: ../Generic/base.py:1495 msgid "Formula must be a string ($1)" msgstr "" -#: ../Generic/base.py:1386 +#: ../Generic/base.py:1498 msgid "There is invalid charactersin formula ($1)" msgstr "" -#: ../Generic/base.py:1451 ../Generic/base.py:2443 +#: ../Generic/base.py:1564 ../Generic/base.py:2618 msgid "'a' value must be a float number" msgstr "" -#: ../Generic/base.py:1455 ../Generic/base.py:2447 +#: ../Generic/base.py:1568 ../Generic/base.py:2622 msgid "'b' value must be a float number" msgstr "" -#: ../Generic/base.py:1459 ../Generic/base.py:2451 +#: ../Generic/base.py:1572 ../Generic/base.py:2626 msgid "'c' value must be a float number" msgstr "" -#: ../Generic/base.py:1463 ../Generic/base.py:2455 +#: ../Generic/base.py:1576 ../Generic/base.py:2630 msgid "'d' value must be a float number" msgstr "" -#: ../Generic/base.py:1491 ../Generic/base.py:2483 +#: ../Generic/base.py:1604 ../Generic/base.py:2658 msgid "Invalid formula" msgstr "" -#: ../Generic/base.py:1741 +#: ../Generic/base.py:1858 msgid "sheet_dict must be a dictionay" msgstr "" -#: ../Generic/base.py:1758 ../Generic/base.py:1764 +#: ../Generic/base.py:1879 ../Generic/base.py:1886 msgid "sheet field must be a string" msgstr "" -#: ../Generic/base.py:1760 +#: ../Generic/base.py:1881 msgid "section_dict must be a dictionary" msgstr "" -#: ../Generic/base.py:1766 +#: ../Generic/base.py:1888 msgid "sheet section must be a string" msgstr "" -#: ../Generic/base.py:1768 +#: ../Generic/base.py:1890 msgid "sheet paragraph must be a string" msgstr "" -#: ../Generic/base.py:2006 +#: ../Generic/base.py:2177 msgid "Owner must be a string" msgstr "" -#: ../Generic/base.py:2022 +#: ../Generic/base.py:2193 msgid "Invalid Date: $1" msgstr "" -#: ../Generic/base.py:2033 +#: ../Generic/base.py:2204 msgid "Comment must be a string" msgstr "" -#: ../Generic/base.py:2049 +#: ../Generic/base.py:2220 msgid "Budget type must be 1, 2, 3 or 4." msgstr "" -#: ../Generic/base.py:2061 +#: ../Generic/base.py:2232 msgid "Certificate order must be a integer." msgstr "" -#: ../Generic/base.py:2076 +#: ../Generic/base.py:2247 msgid "Budget certificate Date must be a valid Date." msgstr "" -#: ../Generic/base.py:2090 +#: ../Generic/base.py:2261 msgid "Invalid title list format" msgstr "" -#: ../Generic/base.py:2119 +#: ../Generic/base.py:2290 msgid "Invalid Index Title" msgstr "" -#: ../Generic/base.py:2154 +#: ../Generic/base.py:2327 msgid "Decimal Key error" msgstr "" -#: ../Generic/base.py:2190 +#: ../Generic/base.py:2365 msgid "Invalid Percentage key" msgstr "" -#: ../Generic/base.py:2313 +#: ../Generic/base.py:2488 msgid "Invalid parent code: $1" msgstr "" -#: ../Generic/base.py:2316 +#: ../Generic/base.py:2491 msgid "Invalid child code: $1 $2" msgstr "" -#: ../Generic/base.py:2319 +#: ../Generic/base.py:2494 msgid "Invalid position in measure $1, in code $2" msgstr "" -#: ../Generic/base.py:2327 +#: ../Generic/base.py:2502 msgid "" "Circular Decomposition, parent code: $1, child code: $2, repeated code: $3" msgstr "" -#: ../Generic/base.py:2352 +#: ../Generic/base.py:2527 msgid "" "No-estructured measure or empty position. Parent Code: $1, Child code: $2, " "Position: $3" msgstr "" -#: ../Generic/base.py:2356 +#: ../Generic/base.py:2531 msgid "" "No-estructured measure or empty position. Repeated child in unspecified " "position. It is impossible to determine the position. New child is added in " "the decomposition. Parent code: $1, Child code: $2, Position: $3" msgstr "" -#: ../Generic/base.py:2396 ../Generic/base.py:2408 +#: ../Generic/base.py:2571 ../Generic/base.py:2583 msgid "" "Error: Invalid child position in decomposition. Parent code: $1 Child code: " "$2 Position: $3" msgstr "" -#: ../Generic/base.py:2402 +#: ../Generic/base.py:2577 msgid "Error: Empty child code. Parent code: $1 Position: $2" msgstr "" -#: ../Generic/base.py:2494 +#: ../Generic/base.py:2669 msgid "Invalid code" msgstr "" -#: ../Generic/base.py:2504 +#: ../Generic/base.py:2679 msgid "Invalid record: $1" msgstr "" -#: ../Generic/base.py:2567 +#: ../Generic/base.py:2742 msgid "Only can be one root record" msgstr "" -#: ../Generic/base.py:2663 ../Generic/base.py:2669 +#: ../Generic/base.py:2851 ../Generic/base.py:2857 msgid "This record does not exits" msgstr "" -#: ../Generic/base.py:2666 +#: ../Generic/base.py:2854 msgid "Path item must be a integer" msgstr "" -#: ../Generic/base.py:2671 +#: ../Generic/base.py:2859 msgid "Path must be a not empty tuple: $1" msgstr "" -#: ../Generic/base.py:2722 +#: ../Generic/base.py:2926 msgid "The sheet code must be a string" msgstr "" -#: ../Generic/base.py:2724 +#: ../Generic/base.py:2928 msgid "The sheet title must be a string" msgstr "" -#: ../Generic/base.py:2732 +#: ../Generic/base.py:2939 msgid "The sheet sections must be a dictionary" msgstr "" -#: ../Generic/base.py:2737 +#: ../Generic/base.py:2945 msgid "The field code must be a string" msgstr "" -#: ../Generic/base.py:2739 +#: ../Generic/base.py:2947 msgid "The field title must be a string" msgstr "" -#: ../Generic/base.py:2747 +#: ../Generic/base.py:2958 msgid "The sheet field must be a dictionary" msgstr "" -#: ../Generic/base.py:2752 +#: ../Generic/base.py:2964 msgid "The paragraph code must be a string" msgstr "" -#: ../Generic/base.py:2754 +#: ../Generic/base.py:2966 msgid "The paragraph text must be a string" msgstr "" -#: ../Generic/base.py:2762 +#: ../Generic/base.py:2977 msgid "The paragraph dict must be a dictionary" msgstr "" -#: ../Generic/base.py:2767 ../Generic/base.py:2791 ../Generic/base.py:2921 -#: ../Generic/base.py:2945 ../Generic/base.py:2967 +#: ../Generic/base.py:2983 ../Generic/base.py:3008 ../Generic/base.py:3147 +#: ../Generic/base.py:3171 ../Generic/base.py:3193 msgid "The record_code code must be a string" msgstr "" -#: ../Generic/base.py:2769 +#: ../Generic/base.py:2985 msgid "The field must be a string" msgstr "" -#: ../Generic/base.py:2771 +#: ../Generic/base.py:2987 msgid "The section dict must be a dictionary" msgstr "" -#: ../Generic/base.py:2775 +#: ../Generic/base.py:2991 msgid "" "Error: The budget do not have this record code and can not be added the " "sheet text in the field $1. Record Code: $2" msgstr "" -#: ../Generic/base.py:2793 +#: ../Generic/base.py:3011 msgid "The filename must be a string" msgstr "" -#: ../Generic/base.py:2797 +#: ../Generic/base.py:3015 msgid "" "Error: The budget do not have the record code $1 and can not be added the " "file: $2" msgstr "" -#: ../Generic/base.py:2807 +#: ../Generic/base.py:3026 msgid "The company code must be a string" msgstr "" -#: ../Generic/base.py:2809 +#: ../Generic/base.py:3028 msgid "The summary must be a string" msgstr "" -#: ../Generic/base.py:2811 ../Generic/base.py:2839 +#: ../Generic/base.py:3030 ../Generic/base.py:3058 msgid "The name must be a string" msgstr "" -#: ../Generic/base.py:2813 +#: ../Generic/base.py:3032 msgid "The name must be a list" msgstr "" -#: ../Generic/base.py:2817 +#: ../Generic/base.py:3036 msgid "The office must be a list" msgstr "" -#: ../Generic/base.py:2819 +#: ../Generic/base.py:3038 msgid "The office must be a 10 items list" msgstr "" -#: ../Generic/base.py:2822 +#: ../Generic/base.py:3041 msgid "This office item must be a string" msgstr "" -#: ../Generic/base.py:2826 +#: ../Generic/base.py:3045 msgid "This office item must be a list" msgstr "" -#: ../Generic/base.py:2841 +#: ../Generic/base.py:3060 msgid "The web must be a string" msgstr "" -#: ../Generic/base.py:2843 +#: ../Generic/base.py:3062 msgid "The email must be a string" msgstr "" -#: ../Generic/base.py:2853 +#: ../Generic/base.py:3074 msgid "The tecnical info code must be a string" msgstr "" -#: ../Generic/base.py:2855 +#: ../Generic/base.py:3076 msgid "The tecnical info description must be a string" msgstr "" -#: ../Generic/base.py:2858 +#: ../Generic/base.py:3079 msgid "The tecnical info unit must be a string" msgstr "" -#: ../Generic/base.py:2905 +#: ../Generic/base.py:3130 msgid "The label must be a string" msgstr "" -#: ../Generic/base.py:2923 +#: ../Generic/base.py:3149 msgid "The parametric select comment must be a string" msgstr "" -#: ../Generic/base.py:2926 +#: ../Generic/base.py:3152 msgid "" "Error: The budget do not have the record code $1 and can not be added the " "Parametric select comment: $2" msgstr "" -#: ../Generic/base.py:2933 +#: ../Generic/base.py:3159 msgid "" "Error: The Record $1 is not a Parametric Record and can not have Parametric " "comment" msgstr "" -#: ../Generic/base.py:2947 +#: ../Generic/base.py:3173 msgid "The summary record must be a string" msgstr "" -#: ../Generic/base.py:2949 +#: ../Generic/base.py:3175 msgid "" "Error: The budget do not have the record code $1 and can not be seted the " "summary: $2" msgstr "" -#: ../Generic/base.py:2955 +#: ../Generic/base.py:3181 msgid "" "Error: The Record $1 is not a Parametric Record and can not have Parametric " "summary" msgstr "" -#: ../Generic/base.py:2969 +#: ../Generic/base.py:3195 msgid "The text record must be a string" msgstr "" -#: ../Generic/base.py:2971 +#: ../Generic/base.py:3197 msgid "" "Error: The budget do not have the record code $1 and can not be seted the " "text: $2" msgstr "" -#: ../Generic/base.py:2977 +#: ../Generic/base.py:3203 msgid "" "Error: The Record $1 is not a Parametric Record and can not have Parametric " "text" msgstr "" -#: ../Generic/base.py:3435 +#: ../Generic/base.py:3726 msgid "Invalid Hierarchy ($1) The hierarchy must be -1, 0, 1, 2" msgstr "" -#: ../Generic/base.py:3445 +#: ../Generic/base.py:3738 msgid "Invalid type ($1),the type must be (empty string,0,1,2,3)" msgstr "" -#: ../Generic/base.py:3454 +#: ../Generic/base.py:3749 msgid "" "Invalid subtype ($1), The subtype must one in (empty string, EA, EU, EC, EF, " "OB, PA, PU, H, Q, %, MC, MCr, MM, MS, ME, MCu, MAl, ML, M)" msgstr "" -#: ../Generic/durusdatabase.py:48 -msgid "Incorrent Base version" -msgstr "" - -#: ../Generic/durusdatabase.py:77 -msgid "Loading file: $1:" -msgstr "" - -#: ../Generic/durusdatabase.py:82 -msgid "Loadig time: $1 seconds" -msgstr "" - -#: ../Generic/fiebdc.py:152 +#: ../Generic/fiebdc.py:150 msgid "Invalid code, it must be a unicode string" msgstr "" -#: ../Generic/fiebdc.py:159 -msgid "The code '$1' have invalid characters." +#: ../Generic/fiebdc.py:157 +msgid "The code '$1' have invalid characters, replaced by '$2'." msgstr "" -#: ../Generic/fiebdc.py:162 +#: ../Generic/fiebdc.py:160 msgid "The code '$1' have invalid characters and can not be encoded in utf8." msgstr "" -#: ../Generic/fiebdc.py:184 +#: ../Generic/fiebdc.py:187 msgid "The code '$1' contains special characters repeated." msgstr "" -#: ../Generic/fiebdc.py:405 +#: ../Generic/fiebdc.py:391 +msgid "FIEBDC. Unknow record: $1" +msgstr "" + +#: ../Generic/fiebdc.py:410 msgid "" "The 'V' record (Property and Version) must be the first record in the file " "but it is the number: $1" msgstr "" -#: ../Generic/fiebdc.py:408 +#: ../Generic/fiebdc.py:413 msgid "The default values were taken and this V record is ignored" msgstr "" -#: ../Generic/fiebdc.py:442 +#: ../Generic/fiebdc.py:447 msgid "FIEBDC format: $1" msgstr "" -#: ../Generic/fiebdc.py:452 +#: ../Generic/fiebdc.py:457 msgid "FIEBDC file generated by $1" msgstr "" -#: ../Generic/fiebdc.py:793 +#: ../Generic/fiebdc.py:798 msgid "Record C without a valid code" msgstr "" -#: ../Generic/fiebdc.py:869 ../Generic/fiebdc.py:881 ../Generic/fiebdc.py:909 +#: ../Generic/fiebdc.py:876 ../Generic/fiebdc.py:888 ../Generic/fiebdc.py:916 msgid "Incorrect type ($1) in the code $2" msgstr "" -#: ../Generic/fiebdc.py:961 +#: ../Generic/fiebdc.py:970 msgid "" "ValueError loadig the descomposition of the record $1, the factor of the " "child $2 must be a float number and can not be $3, seted default value 1.0" msgstr "" -#: ../Generic/fiebdc.py:972 +#: ../Generic/fiebdc.py:981 msgid "" "ValueError loading the descomposition of the record $1, the yield of the " "child $2, must be a float number and cannot be $3, seted default value 1.0" msgstr "" -#: ../Generic/fiebdc.py:1060 +#: ../Generic/fiebdc.py:1070 msgid "Invalid codes in $1 record, codes $2" msgstr "" -#: ../Generic/fiebdc.py:1064 +#: ../Generic/fiebdc.py:1074 msgid "Empty child code in $1 record, codes: $2" msgstr "" -#: ../Generic/fiebdc.py:1084 +#: ../Generic/fiebdc.py:1094 msgid "Invalid path in $1 record, codes $2" msgstr "" -#: ../Generic/fiebdc.py:1095 +#: ../Generic/fiebdc.py:1105 msgid "Invalid Total Measure value in $1 record, codes $2. Total fixed to 0." msgstr "" -#: ../Generic/fiebdc.py:1116 +#: ../Generic/fiebdc.py:1126 msgid "" "The comment is not a formula or its have invalid characters, in the $1 " "record, codes $2" msgstr "" -#: ../Generic/fiebdc.py:1142 +#: ../Generic/fiebdc.py:1152 msgid "The measure values are not float numbers, code $1" msgstr "" -#: ../Generic/fiebdc.py:1438 ../Generic/fiebdc.py:1697 +#: ../Generic/fiebdc.py:1452 ../Generic/fiebdc.py:1717 msgid "The file $1 do not exist" msgstr "" -#: ../Generic/fiebdc.py:1803 ../Generic/fiebdc.py:1810 +#: ../Generic/fiebdc.py:1823 ../Generic/fiebdc.py:1830 msgid "PyArq hates parametric DLLs" msgstr "" -#: ../Generic/fiebdc.py:2019 +#: ../Generic/fiebdc.py:2028 msgid "Loading file $1" msgstr "" -#: ../Generic/fiebdc.py:2038 +#: ../Generic/fiebdc.py:2049 msgid "FIEBDC character encoding: $1" msgstr "" -#: ../Generic/fiebdc.py:2040 +#: ../Generic/fiebdc.py:2053 msgid "" "This Character encoding do not exist in FIEBDC3! Default Character encoding: " "$1" msgstr "" -#: ../Generic/fiebdc.py:2044 +#: ../Generic/fiebdc.py:2058 msgid "" "This V record dot have a character encoding! Default character encoding: $1" msgstr "" -#: ../Generic/fiebdc.py:2048 +#: ../Generic/fiebdc.py:2063 msgid "Not 'V' record in File! Default character encoding: $1" msgstr "" -#: ../Generic/fiebdc.py:2085 -msgid "Process terminated" -msgstr "" - -#: ../Generic/fiebdc.py:2088 -msgid "Time to load: $1 seconds" -msgstr "" - -#: ../Generic/fiebdc.py:2090 -msgid "Records/Valid Records: $1/$2" -msgstr "" - -#: ../Generic/fiebdc.py:2093 +#: ../Generic/fiebdc.py:2111 msgid "$1 unsuported record type O: Comercial Relationship" msgstr "" -#: ../Generic/fiebdc.py:2096 +#: ../Generic/fiebdc.py:2114 msgid "This file is not a valid FIBDC3 file" msgstr "" -#: ../Generic/fiebdc.py:2133 +#: ../Generic/fiebdc.py:2127 msgid "Testing budget ..." msgstr "" -#: ../Generic/fiebdc.py:2151 +#: ../Generic/fiebdc.py:2146 msgid "End Test" msgstr "" -#: ../Gtk/gui.py:68 +#: ../Generic/fiebdc.py:2230 ../Gtk/gui.py:1038 +msgid "Process terminated" +msgstr "" + +#: ../Generic/fiebdc.py:2312 +msgid "Time to load: $1 seconds" +msgstr "" + +#: ../Generic/fiebdc.py:2314 +msgid "Records/Valid Records: $1/$2" +msgstr "" + +#: ../Gtk/gui.py:83 ../Gtk/gui.py:89 msgid "The icon file does not exist. '$1'" msgstr "" -#: ../Gtk/gui.py:74 +#: ../Gtk/gui.py:95 msgid "pyArq-Presupuestos running on $1" msgstr "" -#: ../Gtk/gui.py:169 -msgid "_File" +#: ../Gtk/gui.py:176 +msgid "_New window" +msgstr "" + +#: ../Gtk/gui.py:177 +msgid "_Close window" msgstr "" -#: ../Gtk/gui.py:170 +#: ../Gtk/gui.py:182 +msgid "About" +msgstr "" + +#: ../Gtk/gui.py:185 +msgid "_Quit application" +msgstr "" + +#: ../Gtk/gui.py:195 msgid "_Import Fiebdc" msgstr "" -#: ../Gtk/gui.py:171 -msgid "Import FIEBDC" -msgstr "" - -#: ../Gtk/gui.py:172 -msgid "_Close" -msgstr "" - -#: ../Gtk/gui.py:172 -msgid "Close" +#: ../Gtk/gui.py:199 ../Gtk/gui.py:400 ../Gtk/gui.py:955 +msgid "_Close tab" msgstr "" -#: ../Gtk/gui.py:174 -msgid "_View" +#: ../Gtk/gui.py:203 +msgid "_File" msgstr "" -#: ../Gtk/gui.py:175 ../Gtk/gui.py:185 -msgid "_Go" -msgstr "" - -#: ../Gtk/gui.py:176 -msgid "_Test" -msgstr "" - -#: ../Gtk/gui.py:186 +#: ../Gtk/gui.py:205 msgid "_Back" msgstr "" -#: ../Gtk/gui.py:187 ../Gtk/gui.py:198 -msgid "Go to the previous visited item" -msgstr "" - -#: ../Gtk/gui.py:189 +#: ../Gtk/gui.py:208 msgid "_Forward" msgstr "" -#: ../Gtk/gui.py:190 ../Gtk/gui.py:202 -msgid "Go to the next visited item" -msgstr "" - -#: ../Gtk/gui.py:191 +#: ../Gtk/gui.py:211 msgid "_Up Item" msgstr "" -#: ../Gtk/gui.py:192 -msgid "Go up item" -msgstr "" - -#: ../Gtk/gui.py:193 +#: ../Gtk/gui.py:214 msgid "_Root" msgstr "" -#: ../Gtk/gui.py:194 -msgid "Go to root" +#: ../Gtk/gui.py:217 +msgid "_Go" +msgstr "" + +#: ../Gtk/gui.py:391 ../Gtk/gui.py:392 +msgid "Import Fiebdc" +msgstr "" + +#: ../Gtk/gui.py:401 ../Gtk/gui.py:956 +msgid "Close tab" msgstr "" -#: ../Gtk/gui.py:221 -msgid "Back history" +#: ../Gtk/gui.py:413 ../Gtk/gui.py:414 +msgid "Back" +msgstr "" + +#: ../Gtk/gui.py:422 ../Gtk/gui.py:423 +msgid "Forward" msgstr "" -#: ../Gtk/gui.py:226 -msgid "Forward history" +#: ../Gtk/gui.py:431 ../Gtk/gui.py:432 +msgid "Up Item" msgstr "" -#: ../Gtk/gui.py:444 +#: ../Gtk/gui.py:440 ../Gtk/gui.py:441 +msgid "Root" +msgstr "" + +#: ../Gtk/gui.py:655 msgid "The page is not in the page list" msgstr "" -#: ../Gtk/gui.py:673 ../Gtk/importFiebdc.py:220 +#: ../Gtk/gui.py:792 ../Gtk/gui.py:793 +msgid "Open File" +msgstr "" + +#: ../Gtk/gui.py:794 +msgid "Cancel" +msgstr "" + +#: ../Gtk/gui.py:833 +msgid "The file must have 'bc3' extension" +msgstr "" + +#: ../Gtk/gui.py:991 msgid "Time: 0s" msgstr "" -#: ../Gtk/gui.py:750 ../Gtk/importFiebdc.py:299 +#: ../Gtk/gui.py:1104 msgid "Time: $1" msgstr "" -#: ../Gtk/gui.py:1076 +#: ../Gtk/gui.py:1455 msgid "The value must be a list" msgstr "" -#: ../Gtk/gui.py:1079 +#: ../Gtk/gui.py:1458 msgid "Incorrect len" msgstr "" -#: ../Gtk/gui.py:1107 +#: ../Gtk/gui.py:1486 msgid "Incorrect item $1" msgstr "" -#: ../Gtk/gui.py:1123 +#: ../Gtk/gui.py:1502 msgid "The budget does not have the path record: $1" msgstr "" -#: ../Gtk/gui.py:1479 +#: ../Gtk/gui.py:1865 msgid "Decomposition" msgstr "" -#: ../Gtk/gui.py:1480 ../Gtk/gui.py:2486 +#: ../Gtk/gui.py:1866 ../Gtk/gui.py:2895 msgid "Description" msgstr "" -#: ../Gtk/gui.py:1481 ../Gtk/gui.py:2488 +#: ../Gtk/gui.py:1867 ../Gtk/gui.py:2897 msgid "Measure" msgstr "" -#: ../Gtk/gui.py:1482 +#: ../Gtk/gui.py:1868 msgid "Sheet of Conditions" msgstr "" -#: ../Gtk/gui.py:1483 +#: ../Gtk/gui.py:1869 msgid "Files" msgstr "" -#: ../Gtk/gui.py:1484 +#: ../Gtk/gui.py:1870 msgid "Companies" msgstr "" -#: ../Gtk/gui.py:1661 +#: ../Gtk/gui.py:1950 msgid "Split View Left/Right" msgstr "" -#: ../Gtk/gui.py:1665 +#: ../Gtk/gui.py:1960 msgid "Split View Top/Bottom" msgstr "" -#: ../Gtk/gui.py:1669 +#: ../Gtk/gui.py:1968 +msgid "Disconnect view" +msgstr "" + +#: ../Gtk/gui.py:1971 +msgid "Connect view" +msgstr "" + +#: ../Gtk/gui.py:1984 ../Gtk/gui.py:2081 msgid "Close view" msgstr "" -#: ../Gtk/gui.py:1837 +#: ../Gtk/gui.py:2073 +msgid "Split view Left/Right" +msgstr "" + +#: ../Gtk/gui.py:2077 +msgid "Split view Top/Bottom" +msgstr "" + +#: ../Gtk/gui.py:2112 +msgid "Connect View" +msgstr "" + +#: ../Gtk/gui.py:2118 +msgid "Disconnect View" +msgstr "" + +#: ../Gtk/gui.py:2248 msgid "The item must be a widget object." msgstr "" -#: ../Gtk/gui.py:1843 +#: ../Gtk/gui.py:2256 msgid "Invalid orientation." msgstr "" -#: ../Gtk/gui.py:2215 ../Gtk/gui.py:2842 ../Gtk/gui.py:4172 +#: ../Gtk/gui.py:2628 ../Gtk/gui.py:3256 ../Gtk/gui.py:4674 msgid "Argument must be a Budget object" msgstr "" -#: ../Gtk/gui.py:2224 -msgid "Record path can not be None" -msgstr "" - -#: ../Gtk/gui.py:2255 -msgid "a" -msgstr "" - -#: ../Gtk/gui.py:2483 ../Gtk/gui.py:4235 +#: ../Gtk/gui.py:2892 ../Gtk/gui.py:4739 msgid "Code" msgstr "" -#: ../Gtk/gui.py:2484 +#: ../Gtk/gui.py:2893 msgid "Unit" msgstr "" -#: ../Gtk/gui.py:2490 +#: ../Gtk/gui.py:2899 msgid "Price" msgstr "" -#: ../Gtk/gui.py:2492 +#: ../Gtk/gui.py:2901 msgid "Amount" msgstr "" -#: ../Gtk/gui.py:2503 ../Gtk/gui.py:2982 +#: ../Gtk/gui.py:2912 ../Gtk/gui.py:3528 msgid "Invalid path" msgstr "" -#: ../Gtk/gui.py:2847 +#: ../Gtk/gui.py:3261 msgid "Record path must be a tuple" msgstr "" -#: ../Gtk/gui.py:2991 -msgid "measure must be a Measure object. Type: $1" -msgstr "" - -#: ../Gtk/gui.py:3003 ../Gtk/gui.py:4250 ../Gtk/gui.py:4563 +#: ../Gtk/gui.py:3509 ../Gtk/gui.py:4754 ../Gtk/gui.py:5066 msgid "Type" msgstr "" -#: ../Gtk/gui.py:3004 +#: ../Gtk/gui.py:3510 msgid "Comment" msgstr "" -#: ../Gtk/gui.py:3005 +#: ../Gtk/gui.py:3511 msgid "" "N\n" "(a)" msgstr "" -#: ../Gtk/gui.py:3006 +#: ../Gtk/gui.py:3512 msgid "" "Length\n" "(b)" msgstr "" -#: ../Gtk/gui.py:3007 +#: ../Gtk/gui.py:3513 msgid "" "Width\n" "(c)" msgstr "" -#: ../Gtk/gui.py:3008 +#: ../Gtk/gui.py:3514 msgid "" "Height\n" "(d)" msgstr "" -#: ../Gtk/gui.py:3009 +#: ../Gtk/gui.py:3515 msgid "Formula" msgstr "" -#: ../Gtk/gui.py:3010 +#: ../Gtk/gui.py:3516 #, python-format msgid "" "Parcial\n" "[%s]" msgstr "" -#: ../Gtk/gui.py:3011 +#: ../Gtk/gui.py:3517 msgid "Subtotal" msgstr "" -#: ../Gtk/gui.py:3419 ../Gtk/gui.py:3441 +#: ../Gtk/gui.py:3537 +msgid "measure must be a Measure object. Type: $1" +msgstr "" + +#: ../Gtk/gui.py:3835 ../Gtk/gui.py:3856 msgid "Description text of the record $1" msgstr "" -#: ../Gtk/gui.py:3592 +#: ../Gtk/gui.py:4010 msgid "Sheet of Conditions of the record $1" msgstr "" -#: ../Gtk/gui.py:3610 +#: ../Gtk/gui.py:4031 msgid "Field" msgstr "" -#: ../Gtk/gui.py:3631 +#: ../Gtk/gui.py:4054 msgid "Section" msgstr "" -#: ../Gtk/gui.py:3779 +#: ../Gtk/gui.py:4214 msgid "Sheet2 of Conditions of the record $1" msgstr "" -#: ../Gtk/gui.py:4236 +#: ../Gtk/gui.py:4740 msgid "Code that define the company" msgstr "" -#: ../Gtk/gui.py:4237 +#: ../Gtk/gui.py:4741 msgid "Summary" msgstr "" -#: ../Gtk/gui.py:4238 +#: ../Gtk/gui.py:4742 msgid "Summary of the company name" msgstr "" -#: ../Gtk/gui.py:4239 ../Gtk/gui.py:4255 +#: ../Gtk/gui.py:4743 ../Gtk/gui.py:4759 msgid "Name" msgstr "" -#: ../Gtk/gui.py:4240 +#: ../Gtk/gui.py:4744 msgid "Complete name" msgstr "" -#: ../Gtk/gui.py:4241 +#: ../Gtk/gui.py:4745 msgid "CIF" msgstr "" -#: ../Gtk/gui.py:4242 +#: ../Gtk/gui.py:4746 msgid "Fiscal identifier number" msgstr "" -#: ../Gtk/gui.py:4243 +#: ../Gtk/gui.py:4747 msgid "Web" msgstr "" -#: ../Gtk/gui.py:4244 +#: ../Gtk/gui.py:4748 msgid "Company web page" msgstr "" -#: ../Gtk/gui.py:4245 +#: ../Gtk/gui.py:4749 msgid "Email" msgstr "" -#: ../Gtk/gui.py:4246 +#: ../Gtk/gui.py:4750 msgid "Company email" msgstr "" -#: ../Gtk/gui.py:4251 +#: ../Gtk/gui.py:4755 msgid "" "Type of Office:\n" " C: Central office\n" @@ -991,146 +1028,130 @@ " R: Performer" msgstr "" -#: ../Gtk/gui.py:4256 +#: ../Gtk/gui.py:4760 msgid "Office name" msgstr "" -#: ../Gtk/gui.py:4257 +#: ../Gtk/gui.py:4761 msgid "Address" msgstr "" -#: ../Gtk/gui.py:4258 +#: ../Gtk/gui.py:4762 msgid "Postal code" msgstr "" -#: ../Gtk/gui.py:4259 +#: ../Gtk/gui.py:4763 msgid "Town" msgstr "" -#: ../Gtk/gui.py:4260 +#: ../Gtk/gui.py:4764 msgid "Province" msgstr "" -#: ../Gtk/gui.py:4261 +#: ../Gtk/gui.py:4765 msgid "Country" msgstr "" -#: ../Gtk/gui.py:4262 +#: ../Gtk/gui.py:4766 msgid "Phone" msgstr "" -#: ../Gtk/gui.py:4263 +#: ../Gtk/gui.py:4767 msgid "Phone numbers of the office" msgstr "" -#: ../Gtk/gui.py:4264 +#: ../Gtk/gui.py:4768 msgid "Fax" msgstr "" -#: ../Gtk/gui.py:4265 +#: ../Gtk/gui.py:4769 msgid "Fax numbers of the office" msgstr "" -#: ../Gtk/gui.py:4266 +#: ../Gtk/gui.py:4770 msgid "Contact person" msgstr "" -#: ../Gtk/gui.py:4267 +#: ../Gtk/gui.py:4771 msgid "Contact persons in the office" msgstr "" -#: ../Gtk/gui.py:4271 +#: ../Gtk/gui.py:4775 msgid "Unknow Option Type" msgstr "" -#: ../Gtk/gui.py:4501 +#: ../Gtk/gui.py:5002 msgid "Boolean" msgstr "" -#: ../Gtk/gui.py:4502 +#: ../Gtk/gui.py:5003 msgid "Integer" msgstr "" -#: ../Gtk/gui.py:4503 +#: ../Gtk/gui.py:5004 msgid "Text" msgstr "" -#: ../Gtk/gui.py:4504 +#: ../Gtk/gui.py:5005 msgid "Color" msgstr "" -#: ../Gtk/gui.py:4505 +#: ../Gtk/gui.py:5006 msgid "List" msgstr "" -#: ../Gtk/gui.py:4537 +#: ../Gtk/gui.py:5040 msgid "Option name" msgstr "" -#: ../Gtk/gui.py:4550 +#: ../Gtk/gui.py:5053 msgid "Value" msgstr "" -#: ../Gtk/gui.py:4589 +#: ../Gtk/gui.py:5094 msgid "Description:" msgstr "" -#: ../Gtk/gui.py:4750 +#: ../Gtk/gui.py:5258 msgid "Option values must be strings" msgstr "" -#: ../Gtk/gui.py:4752 +#: ../Gtk/gui.py:5260 msgid "Option must be a tuple with 4 items" msgstr "" -#: ../Gtk/gui.py:4754 +#: ../Gtk/gui.py:5262 msgid "Option list must be a list" msgstr "" -#: ../Gtk/gui.py:4774 +#: ../Gtk/gui.py:5282 msgid "Icorrect type, must be boolean" msgstr "" -#: ../Gtk/gui.py:4779 +#: ../Gtk/gui.py:5287 msgid "Icorrect type, must be integer" msgstr "" -#: ../Gtk/gui.py:4792 +#: ../Gtk/gui.py:5300 msgid "Icorrect type, must be string" msgstr "" -#: ../Gtk/gui.py:4805 +#: ../Gtk/gui.py:5313 msgid "Icorrect type, must be list" msgstr "" -#: ../Gtk/gui.py:4811 +#: ../Gtk/gui.py:5317 msgid "Icorrect type, must be a parseable color" msgstr "" -#: ../Gtk/gui.py:4819 +#: ../Gtk/gui.py:5325 msgid "Type must be boolean, integer, string or color" msgstr "" -#: ../Gtk/gui.py:4822 +#: ../Gtk/gui.py:5328 msgid "Value must be in the option dict" msgstr "" -#: ../Gtk/gui.py:4824 +#: ../Gtk/gui.py:5331 msgid "Values must be a dict" msgstr "" - -#: ../Gtk/importFiebdc.py:91 -msgid "Open File" -msgstr "" - -#: ../Gtk/importFiebdc.py:135 -msgid "The file must have 'bc3' extension" -msgstr "" - -#: ../Gtk/importFiebdc.py:208 -msgid "Loading file ..." -msgstr "" - -#: ../Gtk/importFiebdc.py:232 -msgid "Cancel" -msgstr "" diff -r 7bd4ca56607d -r 65e7ae0d0e63 pyArq-Presupuestos.py --- a/pyArq-Presupuestos.py Tue Sep 30 17:16:50 2014 +0200 +++ b/pyArq-Presupuestos.py Thu May 02 16:31:17 2019 +0200 @@ -3,7 +3,7 @@ ## File presupuestos.py ## This file is part of pyArq-Presupuestos. ## -## Copyright (C) 2010 Miguel Ángel Bárcena Rodríguez +## Copyright (C) 2010-2019 Miguel Ángel Bárcena Rodríguez ## ## ## pyArq-Presupuestos is free software: you can redistribute it and/or modify @@ -21,10 +21,11 @@ # Modules import sys +import getopt import gettext # pyArq-Presupuestos modules +from Generic import win32Locale from Generic import globalVars -from Generic import win32Locale def _take_APPDATA_path(): # take path to find mo file @@ -40,18 +41,45 @@ _dir = globalVars.path["APPDATA"] + "/mo/" if sys.platform == 'win32': win32Locale.check_win32_locale() - gettext.install(_app, _dir, unicode=1) + kwargs = {} + if sys.version_info < (3,): + kwargs['unicode'] = True + gettext.install(_app, _dir, **kwargs) -def _run_gui(): +def _run_gtk(): + print("Iniciando interfaz Gtk3.") + from Gtk import gui + _app = gui.App() + _app.run(sys.argv) + +def _run_gui(argumentList): """def _run_gui Shows main window and starts the GTK+ event processing loop. """ - from Gtk import gui - _window = gui.MainWindow() + unixOptions = "h" + gnuOptions = ["help"] + # import before transtale + from Generic import base + + help = base.help + try: + arguments, values = getopt.getopt(argumentList, unixOptions, gnuOptions) + if len(arguments) > 0: + for currentArgument, currentValue in arguments: + if currentArgument in ("-h", "--help"): + print(help) + break + else: + _run_gtk() + else: + _run_gtk() + except getopt.error as err: + # output error + print (str(err)) # Run pyArq-Presupuestos if __name__ == "__main__": _take_APPDATA_path() _translate() - _run_gui() + _run_gui(sys.argv[1:])