changeset 442:5968e273449b

Translator: added new modules; made fixes and many additions.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Tue, 16 Oct 2007 22:13:37 +0200
parents cdbb2bf6dd07
children 87c36c5ed434
files trunk/src/translator/langfile.py trunk/src/translator/project.py trunk/src/translator/project_properties.ui trunk/src/translator/translator.py trunk/src/translator/translator.ui trunk/src/translator/ui_project_properties.py trunk/src/translator/ui_translator.py
diffstat 7 files changed, 336 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/translator/langfile.py	Fri Oct 12 22:51:40 2007 +0200
+++ b/trunk/src/translator/langfile.py	Tue Oct 16 22:13:37 2007 +0200
@@ -1,52 +1,56 @@
 # -*- coding: utf-8 -*-
 # Author: Aziz Köksal
 # License: GPL2
-import exceptions
 import yaml
+from errors import LoadingError
 
 class LangFile:
-  class LoadingError(exceptions.Exception):
-    def __init__(self, msg):
-      self.msg = msg
-      return
-    def __str__(self):
-      return self.msg
-
   def __init__(self, filePath):
+    self.filePath = filePath
     # Load language file and check data integrity.
     doc = yaml.load(open(filePath, "r"))
     self.doc = doc
     self.checkType(doc, dict)
     try:
-      self.langCode = doc["LangCode"]
-      self.authors = doc["Authors"]
-      self.license = doc["License"]
-      self.messages = doc["Messages"]
+      self.langCode = str(doc["LangCode"])
+      self.authors = list(doc["Authors"])
+      self.license = unicode(doc["License"])
+      self.messages = list(doc["Messages"])
     except KeyError, e:
       raise LoadingError("Missing member '%s' in '%s'" % (e.message, filePath))
 
-    self.checkType(self.langCode, dict)
-    self.checkType(self.authors, list)
+    authors = []
     for author in self.authors:
-      self.checkType(author, list)
-      if len(author) != 2:
-        raise LoadingError("")
-      self.checkType(author[0], str)
-      self.checkType(author[1], str)
-    self.checkType(self.license, str)
-    self.checkType(self.messages, list)
+      author = list(author)
+      author_len = len(author)
+      if author_len == 0:
+        pass
+      elif author_len == 1:
+        authors += [unicode(author[0]), ""]
+      else:
+        authors += [unicode(author[0]), unicode(author[1])]
+    self.authors = authors
+
+    messages = []
     for msg in self.messages:
-      self.checkType(msg, dict)
-      if not msg.has_key("ID") or \
-         not msg.has_key("Text") or \
-         not msg.has_key("Annotation") or \
-         not msg.has_key("LastEdited"):
-        raise LoadingError("")
+      self.checkType(msg, dict, "LangFile: messages must be of type dict.")
+      try:
+        msg["ID"] = int(msg["ID"])
+        msg["Text"] = unicode(msg["Text"])
+        msg["Annot"] = unicode(msg["Annot"])
+        msg["LastEd"] = unicode(msg["LastEd"])
+      except KeyError, e:
+        raise LoadingError("LangFile: a message is missing the '%s' key." % str(e))
+      messages += [msg]
+    self.messages = messages
 
   def checkType(self, var, type_, msg=""):
     if not isinstance(var, type_):
       raise LoadingError(msg)
 
+  def save(self):
+    pass
+
   def newLangFile(langCode, authors, license):
     return {
       "LangCode":langCode,
--- a/trunk/src/translator/project.py	Fri Oct 12 22:51:40 2007 +0200
+++ b/trunk/src/translator/project.py	Tue Oct 16 22:13:37 2007 +0200
@@ -1,18 +1,13 @@
 # -*- coding: utf-8 -*-
 # Author: Aziz Köksal
 # License: GPL2
+import os
+from errors import LoadingError
 import langfile
 import datetime
-import exceptions
 import yaml
 
 class Project:
-  class LoadingError(exceptions.Exception):
-    def __init__(self, msg):
-      self.msg = msg
-      return
-    def __str__(self):
-      return self.msg
   # Members:
   # name
   # source
@@ -21,42 +16,53 @@
   # msgids
   # creationDate
   def __init__(self, projectPath):
+    self.projectPath = projectPath
     # Load project file and check data integrity.
     doc = yaml.load(open(projectPath, "r"))
     self.doc = doc
     self.checkType(doc, dict)
     try:
-      self.name = doc["Name"]
-      self.source = doc["SourceLangFile"]
-      self.langFilePaths = doc["LangFiles"]
-      self.msgIDs = doc["MsgIDs"]
-      self.creationDate = doc["CreationDate"]
+      self.name = str(doc["Name"])
+      self.source = str(doc["SourceLangFile"])
+      self.langFilePaths = list(doc["LangFiles"])
+      self.msgIDs = list(doc["MsgIDs"])
+      self.creationDate = str(doc["CreationDate"])
     except KeyError, e:
-      raise LoadingError("Missing member '%s' in '%s'" % (e.message, filePath))
+      raise LoadingError("Missing member '%s' in '%s'" % (e.message, projectPath))
 
-    self.checkType(self.name, str)
-    self.checkType(self.source, str)
-    self.checkType(self.langFilePaths, list)
     for path in self.langFilePaths:
       self.checkType(path, str)
-    self.checkType(self.msgIDs, list)
+
+    msgIDs = []
     for msg in self.msgIDs:
-      if not isinstance(msg, dict) or \
-         not msg.has_key("ID")     or \
-         not msg.has_key("Name")   or \
-         not msg.has_key("Order"):
-        raise LoadingError("")
-    self.checkType(self.creationDate, str)
+      self.checkType(msg, dict)
+      try:
+         msg["ID"]  = int(msg["ID"])
+         msg["Name"] = unicode(msg["Name"])
+         msg["Order"] = int(msg["Order"])
+      except KeyError, e:
+        raise LoadingError("Project: a message is missing the '%s' key." % str(e))
+      msgIDs += [msg]
+    self.msgIDs = msgIDs
 
     # Load language files.
     self.langFiles = []
     for filePath in self.langFilePaths:
-      self.langFiles += LangFile(filePath)
+      if not os.path.exists(filePath):
+        projectDir = os.path.dirname(projectPath)
+        filePath2 = os.path.join(projectDir, filePath)
+        if not os.path.exists(filePath2):
+          raise LoadingError("Project: Language file '%s' doesn't exist"%filePath)
+        filePath = filePath2
+      self.langFiles += [langfile.LangFile(filePath)]
 
   def checkType(self, var, type_):
     if not isinstance(var, type_):
       raise LoadingException("%s is not of type %s" % (str(var), str(type_)))
 
+  def save(self):
+    pass
+
   def newProjectData(projectName):
     return {
       "Name":projectName,
@@ -65,3 +71,4 @@
       "MsgIDs":[],
       "CreationDate":str(datetime.datetime.utcnow())
     }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/translator/project_properties.ui	Tue Oct 16 22:13:37 2007 +0200
@@ -0,0 +1,112 @@
+<ui version="4.0" >
+ <class>ProjectProperties</class>
+ <widget class="QDialog" name="ProjectProperties" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>148</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Project Properties</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <item>
+    <layout class="QGridLayout" >
+     <item row="0" column="0" >
+      <widget class="QLabel" name="label_2" >
+       <property name="text" >
+        <string>Project name:</string>
+       </property>
+       <property name="alignment" >
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+       <property name="buddy" >
+        <cstring>projectNameField</cstring>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1" >
+      <widget class="QLineEdit" name="projectNameField" />
+     </item>
+     <item row="1" column="0" >
+      <widget class="QLabel" name="label" >
+       <property name="text" >
+        <string>Build command:</string>
+       </property>
+       <property name="alignment" >
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+       <property name="buddy" >
+        <cstring>buildCommandField</cstring>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1" >
+      <widget class="QLineEdit" name="buildCommandField" />
+     </item>
+    </layout>
+   </item>
+   <item>
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox" >
+     <property name="orientation" >
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons" >
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>ProjectProperties</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>227</x>
+     <y>278</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>ProjectProperties</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>295</x>
+     <y>284</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
--- a/trunk/src/translator/translator.py	Fri Oct 12 22:51:40 2007 +0200
+++ b/trunk/src/translator/translator.py	Tue Oct 16 22:13:37 2007 +0200
@@ -10,11 +10,13 @@
 from ui_translator import Ui_MainWindow
 from ui_about import Ui_AboutDialog
 from ui_new_project import Ui_NewProjectDialog
+from ui_project_properties import Ui_ProjectProperties
 
 from project import Project
 
 g_scriptDir = sys.path[0]
 g_CWD = os.getcwd()
+g_projectExt = ".tproj"
 g_settingsFile = os.path.join(g_scriptDir, "settings.yaml")
 g_settings = {}
 
@@ -23,12 +25,15 @@
     QtGui.QMainWindow.__init__(self)
     self.setupUi(self)
 
+    self.project = None
     # Modifications
-
+    self.disableMenuItems()
     # Custom connections
     QtCore.QObject.connect(self.action_About, QtCore.SIGNAL("triggered()"), self.showAboutDialog)
     QtCore.QObject.connect(self.action_New_Project, QtCore.SIGNAL("triggered()"), self.createNewProject)
-    QtCore.QObject.connect(self.action_Open_Project, QtCore.SIGNAL("triggered()"), self.openProject)
+    QtCore.QObject.connect(self.action_Open_Project, QtCore.SIGNAL("triggered()"), self.openProjectAction)
+    QtCore.QObject.connect(self.action_Close_Project, QtCore.SIGNAL("triggered()"), self.closeProject)
+    QtCore.QObject.connect(self.action_Properties, QtCore.SIGNAL("triggered()"), self.showProjectProperties)
 
     self.readSettings()
 
@@ -37,15 +42,66 @@
     Ui_AboutDialog().setupUi(about)
     about.exec_()
 
+  def showProjectProperties(self):
+    dialog = QtGui.QDialog()
+    Ui_ProjectProperties().setupUi(dialog)
+    dialog.exec_()
+
   def createNewProject(self):
     NewProjectDialog().exec_()
 
-  def openProject(self):
-    filePath = QtGui.QFileDialog.getOpenFileName(self, "Select Project File", g_CWD, "Translator Project (*.tproj)");
+  def openProjectAction(self):
+    if self.closeProjectIfOpen():
+      return
+    filePath = QtGui.QFileDialog.getOpenFileName(self, "Select Project File", g_CWD, "Translator Project (*%s)" % g_projectExt);
+    if filePath:
+      self.openProject(str(filePath))
+
+  def openProject(self, filePath):
+    from errors import LoadingError
+    try:
+      self.project = Project(filePath)
+    except LoadingError, e:
+      QtGui.QMessageBox.critical(self, "Error", u"Couldn't load project file:\n\n"+str(e))
+      return
+    self.enableMenuItems()
+    self.projectTree = ProjectTree(self)
+    self.projectTree.setProject(self.project)
+    self.vboxlayout.addWidget(self.projectTree)
 
-    project = Project(filePath)
+  def closeProjectIfOpen(self):
+    if self.project == None:
+      return False
+    return self.closeProject()
+
+  def closeProject(self):
+    if self.project == None:
+      return True
+
+    button = QtGui.QMessageBox.question(self, "Closing", "Close the current project?", QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Cancel)
+    if button == QtGui.QMessageBox.Cancel:
+      return False
+
+    del self.project
+    self.project = None
+    self.disableMenuItems()
+    self.vboxlayout.removeWidget(self.projectTree)
+    self.projectTree.close()
+    return True
+
+  def enableMenuItems(self):
+    self.action_Close_Project.setEnabled(True)
+    self.menubar.insertMenu(self.menu_Help.menuAction(), self.menu_Project)
+
+  def disableMenuItems(self):
+    self.action_Close_Project.setEnabled(False)
+    self.menubar.removeAction(self.menu_Project.menuAction())
 
   def closeEvent(self, event):
+    if self.closeProject() == False:
+      event.ignore()
+      return
+    # Exitting
     self.writeSettings()
 
   def moveToCenterOfDesktop(self):
@@ -83,11 +139,35 @@
     }
     yaml.dump(g_settings, open(g_settingsFile, "w")) #default_flow_style=False
 
+class MsgIDItem(QtGui.QTreeWidgetItem):
+  def __init__(self, parent, text):
+    QtGui.QTreeWidgetItem.__init__(self, parent, [text])
+
+class LangFileItem(QtGui.QTreeWidgetItem):
+  def __init__(self, parent, text):
+    QtGui.QTreeWidgetItem.__init__(self, parent, [text])
 
 class ProjectTree(QtGui.QTreeWidget):
   def __init__(self, parent):
     QtGui.QTreeWidget.__init__(self, parent)
+    self.topItem = None
+    self.msgIDsItem = None
 
+  def setProject(self, project):
+   self.project = project
+
+   self.topItem = QtGui.QTreeWidgetItem([self.project.name])
+   self.addTopLevelItem(self.topItem)
+
+   self.msgIDsItem = QtGui.QTreeWidgetItem(self.topItem, ["Message IDs"])
+   for msgID in self.project.msgIDs:
+     MsgIDItem(self.msgIDsItem, msgID["Name"])
+
+   for langFile in self.project.langFiles:
+     langFileItem = LangFileItem(self.topItem, langFile.langCode)
+
+   for x in [self.topItem, self.msgIDsItem]:
+     x.setExpanded(True)
 
 class NewProjectDialog(QtGui.QDialog, Ui_NewProjectDialog):
   def __init__(self):
@@ -97,10 +177,12 @@
     QtCore.QObject.connect(self.pickFileButton, QtCore.SIGNAL("clicked()"), self.pickFilePath)
 
   def pickFilePath(self):
-    filePath = QtGui.QFileDialog.getSaveFileName(self, "New Project File", g_CWD, "Translator Project (*.tproj)");
+    filePath = QtGui.QFileDialog.getSaveFileName(self, "New Project File", g_CWD, "Translator Project (*%s)" % g_projectExt);
+    if not filePath:
+      return
     filePath = str(filePath) # Convert QString
-    if os.path.splitext(filePath)[1] != ".tproj":
-      filePath += ".tproj"
+    if os.path.splitext(filePath)[1] != g_projectExt:
+      filePath += g_projectExt
     self.projectFilePath.setText(filePath)
 
   def accept(self):
@@ -116,8 +198,8 @@
 
     projectData = Project.newProjectData(projectName)
 
-    if os.path.splitext(filePath)[1] != ".tproj":
-      filePath += ".tproj"
+    if os.path.splitext(filePath)[1] != g_projectExt:
+      filePath += g_projectExt
 
     try:
       yaml.dump(projectData, open(filePath, "w"), default_flow_style=False)
--- a/trunk/src/translator/translator.ui	Fri Oct 12 22:51:40 2007 +0200
+++ b/trunk/src/translator/translator.ui	Tue Oct 16 22:13:37 2007 +0200
@@ -44,7 +44,7 @@
     <property name="title" >
      <string>&amp;Project</string>
     </property>
-    <addaction name="action_Add_catalogue" />
+    <addaction name="action_Add_Catalogue" />
     <addaction name="action_Build_Project" />
     <addaction name="separator" />
     <addaction name="action_Properties" />
@@ -75,7 +75,7 @@
     <string>Ctrl+N</string>
    </property>
   </action>
-  <action name="action_Add_catalogue" >
+  <action name="action_Add_Catalogue" >
    <property name="text" >
     <string>&amp;Add catalogue</string>
    </property>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/translator/ui_project_properties.py	Tue Oct 16 22:13:37 2007 +0200
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'project_properties.ui'
+#
+# Created: Tue Oct 16 21:58:58 2007
+#      by: PyQt4 UI code generator 4.1
+#
+# WARNING! All changes made in this file will be lost!
+
+import sys
+from PyQt4 import QtCore, QtGui
+
+class Ui_ProjectProperties(object):
+    def setupUi(self, ProjectProperties):
+        ProjectProperties.setObjectName("ProjectProperties")
+        ProjectProperties.resize(QtCore.QSize(QtCore.QRect(0,0,400,148).size()).expandedTo(ProjectProperties.minimumSizeHint()))
+
+        self.vboxlayout = QtGui.QVBoxLayout(ProjectProperties)
+        self.vboxlayout.setObjectName("vboxlayout")
+
+        self.gridlayout = QtGui.QGridLayout()
+        self.gridlayout.setObjectName("gridlayout")
+
+        self.label_2 = QtGui.QLabel(ProjectProperties)
+        self.label_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
+        self.label_2.setObjectName("label_2")
+        self.gridlayout.addWidget(self.label_2,0,0,1,1)
+
+        self.projectNameField = QtGui.QLineEdit(ProjectProperties)
+        self.projectNameField.setObjectName("projectNameField")
+        self.gridlayout.addWidget(self.projectNameField,0,1,1,1)
+
+        self.label = QtGui.QLabel(ProjectProperties)
+        self.label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
+        self.label.setObjectName("label")
+        self.gridlayout.addWidget(self.label,1,0,1,1)
+
+        self.buildCommandField = QtGui.QLineEdit(ProjectProperties)
+        self.buildCommandField.setObjectName("buildCommandField")
+        self.gridlayout.addWidget(self.buildCommandField,1,1,1,1)
+        self.vboxlayout.addLayout(self.gridlayout)
+
+        spacerItem = QtGui.QSpacerItem(20,40,QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Expanding)
+        self.vboxlayout.addItem(spacerItem)
+
+        self.buttonBox = QtGui.QDialogButtonBox(ProjectProperties)
+        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
+        self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.NoButton|QtGui.QDialogButtonBox.Ok)
+        self.buttonBox.setObjectName("buttonBox")
+        self.vboxlayout.addWidget(self.buttonBox)
+        self.label_2.setBuddy(self.projectNameField)
+        self.label.setBuddy(self.buildCommandField)
+
+        self.retranslateUi(ProjectProperties)
+        QtCore.QObject.connect(self.buttonBox,QtCore.SIGNAL("accepted()"),ProjectProperties.accept)
+        QtCore.QObject.connect(self.buttonBox,QtCore.SIGNAL("rejected()"),ProjectProperties.reject)
+        QtCore.QMetaObject.connectSlotsByName(ProjectProperties)
+
+    def retranslateUi(self, ProjectProperties):
+        ProjectProperties.setWindowTitle(QtGui.QApplication.translate("ProjectProperties", "Project Properties", None, QtGui.QApplication.UnicodeUTF8))
+        self.label_2.setText(QtGui.QApplication.translate("ProjectProperties", "Project name:", None, QtGui.QApplication.UnicodeUTF8))
+        self.label.setText(QtGui.QApplication.translate("ProjectProperties", "Build command:", None, QtGui.QApplication.UnicodeUTF8))
+
--- a/trunk/src/translator/ui_translator.py	Fri Oct 12 22:51:40 2007 +0200
+++ b/trunk/src/translator/ui_translator.py	Tue Oct 16 22:13:37 2007 +0200
@@ -2,7 +2,7 @@
 
 # Form implementation generated from reading ui file 'translator.ui'
 #
-# Created: Fri Oct 12 22:49:36 2007
+# Created: Sun Oct 14 13:11:43 2007
 #      by: PyQt4 UI code generator 4.1
 #
 # WARNING! All changes made in this file will be lost!
@@ -49,8 +49,8 @@
         self.action_New_Project = QtGui.QAction(MainWindow)
         self.action_New_Project.setObjectName("action_New_Project")
 
-        self.action_Add_catalogue = QtGui.QAction(MainWindow)
-        self.action_Add_catalogue.setObjectName("action_Add_catalogue")
+        self.action_Add_Catalogue = QtGui.QAction(MainWindow)
+        self.action_Add_Catalogue.setObjectName("action_Add_Catalogue")
 
         self.action_Properties = QtGui.QAction(MainWindow)
         self.action_Properties.setObjectName("action_Properties")
@@ -69,7 +69,7 @@
         self.menu_File.addSeparator()
         self.menu_File.addAction(self.action_Quit)
         self.menu_Help.addAction(self.action_About)
-        self.menu_Project.addAction(self.action_Add_catalogue)
+        self.menu_Project.addAction(self.action_Add_Catalogue)
         self.menu_Project.addAction(self.action_Build_Project)
         self.menu_Project.addSeparator()
         self.menu_Project.addAction(self.action_Properties)
@@ -91,7 +91,7 @@
         self.action_About.setText(QtGui.QApplication.translate("MainWindow", "&About", None, QtGui.QApplication.UnicodeUTF8))
         self.action_New_Project.setText(QtGui.QApplication.translate("MainWindow", "&New Project...", None, QtGui.QApplication.UnicodeUTF8))
         self.action_New_Project.setShortcut(QtGui.QApplication.translate("MainWindow", "Ctrl+N", None, QtGui.QApplication.UnicodeUTF8))
-        self.action_Add_catalogue.setText(QtGui.QApplication.translate("MainWindow", "&Add catalogue", None, QtGui.QApplication.UnicodeUTF8))
+        self.action_Add_Catalogue.setText(QtGui.QApplication.translate("MainWindow", "&Add catalogue", None, QtGui.QApplication.UnicodeUTF8))
         self.action_Properties.setText(QtGui.QApplication.translate("MainWindow", "&Properties", None, QtGui.QApplication.UnicodeUTF8))
         self.action_Build_Project.setText(QtGui.QApplication.translate("MainWindow", "&Build Project", None, QtGui.QApplication.UnicodeUTF8))
         self.action_Open_Project.setText(QtGui.QApplication.translate("MainWindow", "&Open Project...", None, QtGui.QApplication.UnicodeUTF8))