00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 import gettext
00031
00032 import Api
00033 from Settings import *
00034 from Koo import Rpc
00035
00036 import os
00037 import sys
00038 import Debug
00039
00040 from PyQt4.QtCore import *
00041 from PyQt4.QtGui import *
00042 from PyQt4.uic import *
00043
00044 from Paths import *
00045
00046 try:
00047 if Settings.value('kde.enabled'):
00048 from PyKDE4.kdecore import ki18n
00049 isKdeAvailable = True
00050 else:
00051 isKdeAvailable = False
00052 except:
00053 isKdeAvailable = False
00054
00055 def isQtVersion45():
00056 return PYQT_VERSION >= 0x40500
00057
00058
00059 import common_rc
00060
00061
00062
00063 sys.path.append( os.path.abspath(os.path.dirname(__file__)) )
00064
00065
00066
00067 def nodeAttributes(node):
00068 result = {}
00069 attrs = node.attributes
00070 if attrs is None:
00071 return {}
00072 for i in range(attrs.length):
00073 result[attrs.item(i).localName] = attrs.item(i).nodeValue
00074 return result
00075
00076 def sendEMail(to, subject, body):
00077
00078 import smtplib
00079
00080
00081 from email.mime.text import MIMEText
00082
00083 source = Settings.value('koo.smtp_from')
00084
00085 msg = MIMEText(body)
00086
00087
00088
00089 msg['Subject'] = subject
00090 msg['From'] = source
00091 msg['To'] = to
00092
00093
00094
00095 s = smtplib.SMTP( Settings.value('koo.smtp_server') )
00096 s.sendmail(source, [to], msg.as_string())
00097 s.quit()
00098
00099
00100 (SelectionDialogUi, SelectionDialogBase) = loadUiType( uiPath('win_selection.ui') )
00101
00102
00103
00104
00105
00106
00107 class SelectionDialog(QDialog, SelectionDialogUi):
00108 def __init__(self, title, values, parent=None):
00109 QDialog.__init__(self, parent)
00110 SelectionDialogUi.__init__(self)
00111 self.setupUi( self )
00112
00113 if title:
00114 self.uiTitle.setText( title )
00115 for x in values.keys():
00116 item = QListWidgetItem()
00117 item.setText(x)
00118 item.value = values[x]
00119 self.uiList.addItem( item )
00120 self.connect( self.pushAccept, SIGNAL('clicked()'), self.selected )
00121
00122 def selected(self):
00123 self.result = ""
00124 item = self.uiList.currentItem()
00125 self.result = ( unicode(item.text()), item.value )
00126 self.accept()
00127
00128
00129
00130
00131
00132
00133
00134
00135 def selection(title, values, alwaysask=False):
00136 if len(values) == 0:
00137 return None
00138 elif len(values)==1 and (not alwaysask):
00139 key = values.keys()[0]
00140 return (key, values[key])
00141 s = SelectionDialog(title, values)
00142 if s.exec_() == QDialog.Accepted:
00143 return s.result
00144 else:
00145 return False
00146
00147
00148 def warning(title, message):
00149 QApplication.setOverrideCursor( Qt.ArrowCursor )
00150 QMessageBox.warning(None, title, message)
00151 QApplication.restoreOverrideCursor()
00152
00153
00154
00155 class ConcurrencyErrorDialog(QMessageBox):
00156 def __init__(self, parent=None):
00157 QMessageBox.__init__(self, parent)
00158 self.setIcon( QMessageBox.Warning )
00159 self.setWindowTitle( _('Concurrency warning') )
00160 self.setText( _('<b>Write concurrency warning:</b><br/>This document has been modified while you were editing it.') )
00161 self.addButton( _('Save anyway'), QMessageBox.AcceptRole )
00162 self.addButton( _('Compare'), QMessageBox.ActionRole )
00163 self.addButton( _('Do not save'), QMessageBox.RejectRole )
00164
00165
00166 def concurrencyError(model, id, context):
00167 QApplication.setOverrideCursor( Qt.ArrowCursor )
00168 dialog = ConcurrencyErrorDialog()
00169 result = dialog.exec_()
00170 QApplication.restoreOverrideCursor()
00171 if result == 0:
00172 return True
00173 if result == 1:
00174 Api.instance.createWindow( False, model, id, context=context )
00175
00176 return False
00177
00178 (ErrorDialogUi, ErrorDialogBase) = loadUiType( uiPath('error.ui') )
00179
00180
00181
00182
00183
00184
00185
00186 class ErrorDialog( QDialog, ErrorDialogUi ):
00187 def __init__(self, title, message, details='', parent=None):
00188 QDialog.__init__(self, parent)
00189 ErrorDialogUi.__init__(self)
00190 self.setupUi( self )
00191
00192 self.uiDetails.setText( details )
00193 self.uiErrorInfo.setText( message )
00194 self.uiErrorTitle.setText( title )
00195
00196 from Koo.Common import RemoteHelp
00197 self.pushRemoteHelp.setVisible( RemoteHelp.isRemoteHelpAvailable() )
00198
00199 self.connect( self.pushSend, SIGNAL('clicked()'), self.send )
00200 self.connect( self.pushRemoteHelp, SIGNAL('clicked()'), self.remoteHelp )
00201
00202 def done(self, r):
00203 QDialog.done(self, r)
00204
00205 def remoteHelp(self):
00206 from Koo.Common import RemoteHelp
00207 RemoteHelp.remoteHelp( self )
00208
00209 def send(self):
00210 to = Settings.value('koo.smtp_backtraces_to')
00211
00212 button = QMessageBox.question(self, _('Send Error Information'), _('You are about to send the details of this error, database name, user ID, and server URL to %s. Do you want to proceed?') % to, QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
00213 if button == QMessageBox.No:
00214 return
00215
00216 subject = 'Backtrace information: %s' % Rpc.session.databaseName
00217 body = ''
00218 body += 'Database: %s\n' % Rpc.session.databaseName
00219 body += 'User ID: %s\n' % Rpc.session.uid
00220 body += 'URL: %s\n\n' % Rpc.session.url
00221 body += 'Backtrace:\n\n'
00222 body += unicode( self.uiDetails.toPlainText() ).encode('ascii', 'replace')
00223 try:
00224 sendEMail( Settings.value('koo.smtp_backtraces_to'), subject, body)
00225 except:
00226 QMessageBox.warning( self, _('Send Error Information'), _('Error information could not be sent.') )
00227 return
00228
00229 QMessageBox.information( self, _('Send Error Information'), _('Error information was successfully sent.') )
00230 self.pushSend.setEnabled( False )
00231
00232
00233
00234
00235 def error(title, message, details=''):
00236 QApplication.setOverrideCursor( Qt.ArrowCursor )
00237 dialog = ErrorDialog( unicode(title), unicode(message), unicode(details) )
00238 dialog.exec_()
00239 QApplication.restoreOverrideCursor()
00240
00241
00242 (LostConnectionDialogUi, LostConnectionDialogBase) = loadUiType( uiPath('lostconnection.ui') )
00243
00244
00245
00246
00247
00248
00249 class LostConnectionDialog( QDialog, LostConnectionDialogUi ):
00250 def __init__(self, count, parent=None):
00251 QDialog.__init__(self, parent)
00252 LostConnectionDialogUi.__init__(self)
00253 self.setupUi( self )
00254
00255 self.count = count
00256 self.retry = True
00257 self.remaining = 10
00258 self.updateMessage()
00259 self.uiTitle.setText( _('<b>Connection Lost:</b> %s') % count )
00260
00261 self.timer = QTimer()
00262 self.timer.setInterval( 1000 )
00263 self.connect( self.timer, SIGNAL('timeout()'), self.updateMessage )
00264 self.connect( self, SIGNAL('rejected()'), self.stopTimer )
00265 self.timer.start()
00266
00267 def updateMessage(self):
00268 self.uiMessage.setText( _('Connection with the server has been lost. Will retry connection in %d seconds.') % self.remaining )
00269 self.remaining -= 1
00270 if self.remaining < 0:
00271 self.timer.stop()
00272 self.accept()
00273
00274 def stopTimer(self):
00275 self.timer.stop()
00276
00277
00278
00279 def lostConnectionError(count):
00280 QApplication.setOverrideCursor( Qt.ArrowCursor )
00281 dialog = LostConnectionDialog( count )
00282 if dialog.exec_() == QDialog.Rejected:
00283 result = QMessageBox.warning( None, _("Quit"), _("Leaving the application now will lose all unsaved changes. Are you sure you want to quit?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.No )
00284 if result == QMessageBox.Yes:
00285 QApplication.quit()
00286 sys.exit(0)
00287 QApplication.restoreOverrideCursor()
00288 return True
00289
00290
00291 (ProgressDialogUi, ProgressDialogBase) = loadUiType( uiPath('progress.ui') )
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 class ProgressDialog(QDialog, ProgressDialogUi):
00302 def __init__(self, parent=None):
00303 QDialog.__init__(self, parent)
00304 ProgressDialogUi.__init__(self)
00305 self.setupUi( self )
00306 self.progressBar.setMinimum( 0 )
00307 self.progressBar.setMaximum( 0 )
00308
00309 def start(self):
00310 self.timer = QTimer()
00311 self.connect( self.timer, SIGNAL('timeout()'), self.timeout )
00312 self.timer.start( 2000 )
00313
00314 def timeout(self):
00315 self.timer.stop()
00316 self.show()
00317
00318 def stop(self):
00319 self.timer.stop()
00320 self.accept()
00321
00322
00323 def openFile( fileName ):
00324 if os.name == 'nt':
00325 os.startfile(fileName)
00326 elif os.uname()[0] == 'Darwin':
00327 os.system('/usr/bin/open -a Preview %s' % fileName)
00328 else:
00329 os.spawnlp(os.P_NOWAIT, 'xdg-open', 'xdg-open', fileName)
00330
00331
00332
00333
00334
00335 def normalizeLabel( text ):
00336 res = ''
00337 underscore = False
00338 for x in text:
00339 if x == '_':
00340 if underscore:
00341 res += '_'
00342 underscore = False
00343 else:
00344 underscore = True
00345 else:
00346 if underscore:
00347 res += '&'
00348 underscore = False
00349 if x == '&':
00350 res += '&&'
00351 else:
00352 res += x
00353 return res
00354
00355
00356
00357
00358
00359
00360
00361 def stringToBool(text):
00362 if isinstance(text, str) or isinstance(text, unicode):
00363 text = text.strip()
00364 if text.lower() == 'true' or text == '1':
00365 return True
00366 if text.lower() == 'false' or text == '0':
00367 return False
00368 return bool(text)
00369
00370
00371
00372
00373 def simplifyHtml(html):
00374 if isinstance(html, QString):
00375 html = unicode( html )
00376 if '<p' in html:
00377 index = html.find('<p')
00378 html = html[index:]
00379 index = html.rfind('</p>') + 4
00380 html = html[:index]
00381 return html