4 # Copyright (C) 2010 Stefanos Harhalakis
6 # This file is part of maegirls.
8 # maegirls is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # maegirls is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with maegirls. If not, see <http://www.gnu.org/licenses/>.
21 # $Id: 0.py 2265 2010-02-21 19:16:26Z v13 $
23 __version__ = "$Id: 0.py 2265 2010-02-21 19:16:26Z v13 $"
25 from PyQt4.QtGui import *
26 from PyQt4.QtCore import *
32 from graph import DaysGraph
39 class ConfigDialog(QDialog):
40 def __init__(self, *args, **kwargs):
41 QDialog.__init__(self, *args, **kwargs)
43 self.editName=QLineEdit(self)
44 self.editCycle=QSpinBox(self)
45 self.editCurrent=QSpinBox(self)
46 self.editCycle.setRange(10,50)
47 self.editCurrent.setRange(1,50)
48 self.editCurrent.setWrapping(True)
49 self.editCycle.setSuffix(self.tr(" days"))
51 self.editCycle.valueChanged.connect(self.slotEditCycleChanged)
53 self.l0=QHBoxLayout(self)
56 l1.addRow(self.tr("Name:"), self.editName)
57 l1.addRow(self.tr("Cycle length:"), self.editCycle)
58 l1.addRow(self.tr("Current day in cycle:"), self.editCurrent)
62 spacer=QSpacerItem(20, 20, QSizePolicy.Expanding)
63 self.l0.addItem(spacer)
68 self.buttonOk=QPushButton(self)
69 self.buttonOk.setText(self.tr("OK"))
70 self.buttonOk.clicked.connect(self.slotButOk)
71 l2.addWidget(self.buttonOk)
73 spacer=QSpacerItem(20, 20, QSizePolicy.Minimum,QSizePolicy.Expanding)
76 self.setWindowTitle(self.tr("Configuration"))
79 self.name=str(self.editName.text())
80 self.cycle=self.editCycle.value()
81 self.current=self.editCurrent.value()-1
85 def slotEditCycleChanged(self, value):
86 self.editCurrent.setMaximum(value)
88 # current starts from 0
89 def initValues(self, dt):
91 self.editName.setText(dt['name'])
92 self.editCycle.setValue(dt['cycle'])
93 self.editCurrent.setValue(dt['day0']+1)
95 class MyMsgDialog(QDialog):
97 A Dialog to show a finger-scrollable message
101 class Koko(MyMsgDialog):
103 MyMsgDialog.__init__(....)
106 self.setWindowTitle("My title")
108 l1=QLabel("koko", self.w)
112 self.l is a QVBoxLayout. Add everything there.
113 self.w is a QWidget. Use it as parent.
116 def __init__(self, *args, **kwargs):
117 QDialog.__init__(self, *args, **kwargs)
119 # This freaking thing is hard
120 # It needs two layouts, one extra widget, the fingerscrollable
121 # property set to true *and* setWidgetResizable(True)
122 self._mm_l0=QVBoxLayout(self)
124 self._mm_q=QScrollArea(self)
125 self._mm_q.setWidgetResizable(True)
126 self._mm_q.setProperty('FingerScrollable', True)
128 self.w=QWidget(self._mm_q)
130 self.l=QVBoxLayout(self.w)
131 self._mm_q.setWidget(self.w)
132 self._mm_l0.addWidget(self._mm_q)
134 class AboutDialog(MyMsgDialog):
135 def __init__(self, *args, **kwargs):
136 MyMsgDialog.__init__(self, *args, **kwargs)
139 <p> A program to monitor the women's cycle. Good for planning (or acting ;-).
140 Inspired by "MyGirls" app which is (was?) available for Java ME capable phones.
142 <p style="color: orange;">
143 WARNING!!! This is not accurate nor correct! You cannot trust
144 this program (or any other program) for accurate predictions!
145 (after all, this is about women... how can one be sure :-).
147 <p> Copyright © 2010, Stefanos Harhalakis <v13@v13.gr>
149 <p> Send comments and bug reports to the above address.
151 <p> This program can be distributed under the terms of the GNU public
152 license, version 3 or any later.
155 self.setWindowTitle(self.tr("About MaeGirls"))
157 self.ltitle=QLabel("MaeGirls v" + config.version, self.w)
158 self.ltitle.setObjectName("title")
159 self.ltitle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
160 self.ltitle.setAlignment(Qt.AlignCenter)
161 self.l.addWidget(self.ltitle)
163 self.label=QLabel(txt, self.w)
164 self.label.setWordWrap(True)
165 self.label.setTextFormat(Qt.RichText)
166 self.label.setAlignment(Qt.AlignJustify)
167 self.l.addWidget(self.label)
169 self.ltitle.setStyleSheet("""
172 color: rgb(192,192,192);
173 margin-bottom: 0.5ex;
177 class HelpDialog(MyMsgDialog):
178 def __init__(self, *args, **kwargs):
179 MyMsgDialog.__init__(self, *args, **kwargs)
182 <p> MaeGirls shows information about women's cycle using some generic
183 guidelines. It assumes that the ovulation happens 14 days before the start
184 of the next period and that the period cycle is constant. Also, it assumes
185 that sperm can live for 4 days, while an egg can live for 2 days.
187 <p style="color: orange;">
188 WARNING!!! This is not always correct. There are FAR TOO MANY exceptions
189 to the above rules!!!
191 <p> Assuming that you understand the risk of being wrong, you become
192 entitled to read the graph as follows:
193 <p> <span style="color: red">In red:</span> The days that menstruation
195 <p> <span style="color: green">In green:</span> The fertile days.
196 <p> <span style="color: blue">In blue:</span> The days of PMS
197 (Premenstrual Syndrome).
199 <p> Navigation is easy: Use left-right finger movement to move the calendar
200 view. Use up-down finger movement to zoom in/out.
203 self.setWindowTitle(self.tr("Help"))
205 self.label=QLabel(txt, self.w)
206 self.label.setWordWrap(True)
207 self.label.setTextFormat(Qt.RichText)
208 self.label.setAlignment(Qt.AlignJustify)
209 self.l.addWidget(self.label)
211 class GirlsDialog(QDialog):
212 def __init__(self, *args, **kwargs):
213 QDialog.__init__(self, *args, **kwargs)
215 self.l0=QHBoxLayout(self)
217 self.lstm=QStringListModel()
218 self.lst=QListView(self)
219 self.lst.setModel(self.lstm)
221 self.lst.setProperty("FingerScrollable", True)
223 self.l0.addWidget(self.lst)
225 self.buttonNew=QPushButton(self)
226 self.buttonNew.setText(self.tr("New"))
228 self.buttonSelect=QPushButton(self)
229 self.buttonSelect.setText(self.tr("Select"))
231 self.buttonDelete=QPushButton(self)
232 self.buttonDelete.setText(self.tr("Delete"))
234 spacer=QSpacerItem(20, 20, QSizePolicy.Minimum,QSizePolicy.Expanding)
236 self.l1=QVBoxLayout()
237 self.l0.addLayout(self.l1)
238 self.l1.addWidget(self.buttonNew)
239 self.l1.addWidget(self.buttonSelect)
240 self.l1.addWidget(self.buttonDelete)
241 self.l1.addItem(spacer)
243 self.buttonNew.clicked.connect(self.slotNew)
244 self.buttonDelete.clicked.connect(self.slotDelete)
245 self.buttonSelect.clicked.connect(self.slotSelect)
247 def _get_selection(self):
248 sel=self.lst.selectedIndexes()
251 ret=str(d.data().toString())
257 def exec_(self, current):
259 girls=config.loadGirls()
262 self.lstm.setStringList(dt)
267 # Set current selection
268 idx=dt.index(current)
270 # Either I'm doing something stupid, or this is a QT bug
271 # The selection works but isn't shown
272 idx2=self.lstm.index(idx, 0)
273 self.lst.setCurrentIndex(idx2)
274 # Give if focus to show the current selection - is this normal?
275 self.lst.setFocus(Qt.OtherFocusReason)
285 def slotDelete(self):
287 self.which=self._get_selection()
290 def slotSelect(self):
292 self.which=self._get_selection()
295 class MaeGirls(QMainWindow):
296 def __init__(self, algo):
297 QMainWindow.__init__(self)
301 # self.dlgConfig=ConfigDialog(self)
302 # self.dlgAbout=AboutDialog(self)
303 # self.dlgHelp=HelpDialog(self)
311 def setupUi(self, algo):
312 self.centralwidget=QWidget(self)
313 self.setCentralWidget(self.centralwidget)
315 self.l0=QVBoxLayout(self.centralwidget)
317 self.dg=DaysGraph(algo, self.centralwidget)
318 self.l0.addWidget(self.dg)
321 self.menuconfig=QAction(self.tr('Configure'), self)
322 self.menuconfig.triggered.connect(self.menuConfig)
324 self.menureset=QAction(self.tr('Go to today'), self)
325 self.menureset.triggered.connect(self.menuReset)
327 self.menugirls=QAction(self.tr('Girls'), self)
328 self.menugirls.triggered.connect(self.menuGirls)
330 self.menuabout=QAction(self.tr('About'), self)
331 self.menuabout.triggered.connect(self.menuAbout)
333 self.menuhelp=QAction(self.tr('Help'), self)
334 self.menuhelp.triggered.connect(self.menuHelp)
337 m.addAction(self.menureset)
338 m.addAction(self.menuconfig)
339 m.addAction(self.menugirls)
340 m.addAction(self.menuhelp)
341 m.addAction(self.menuabout)
343 self.setWindowTitle("MaeGirls")
345 def setAlgo(self, algo):
346 self.dg.setAlgo(algo)
348 def setGirl(self, name):
349 cfg=config.loadGirl(name)
351 self.algo.setReference(cfg['day0'], cfg['cycle'])
354 def menuConfig(self):
355 if self.dlgConfig==None:
356 self.dlgConfig=ConfigDialog(self)
360 'cycle': self.algo.cycleLength(),
361 'day0': self.algo.currentDayInCycle()
364 self.dlgConfig.initValues(dt)
366 ret=self.dlgConfig.exec_()
368 if ret==self.dlgConfig.Accepted:
371 name=self.dlgConfig.name
372 day0=today-self.dlgConfig.current
375 'cycle': self.dlgConfig.cycle,
379 config.storeGirl(name, dt)
380 config.setCurrentGirl(name)
382 # If this is a rename, remove the old one
384 config.removeGirl(self.girl)
391 if self.dlgGirls==None:
392 self.dlgGirls=GirlsDialog(self)
394 ret=self.dlgGirls.exec_(self.girl)
396 what=self.dlgGirls.what
397 which=self.dlgGirls.which
399 # Determine a unique name
403 while config.girlExists(name):
405 name="%s%d" % (base, idx)
409 config.setCurrentGirl(name)
413 elif what=='delete' and which!=None:
415 msg=QMessageBox(self)
416 msg.setText(self.tr('You cannot delete the current girl'))
419 config.removeGirl(which)
420 elif what=='select' and which!=None:
421 config.setCurrentGirl(which)
425 if self.dlgAbout==None:
426 self.dlgAbout=AboutDialog(self)
428 ret=self.dlgAbout.exec_()
431 if self.dlgHelp==None:
432 self.dlgHelp=HelpDialog(self)
434 ret=self.dlgHelp.exec_()
444 # Create the application
445 app=QApplication(sys.argv)
447 # This returns the country and *NOT* the required locale
448 # This means that if you have'set language==en_GB and countr==Greece
449 # it will return el_GR.
450 # IOW: If you want english messages this will not work
451 #loc=QLocale.system().name()
453 loc=locale.setlocale(locale.LC_MESSAGES, '')
459 qttr.load("qt_" + loc,
460 QLibraryInfo.location(QLibraryInfo.TranslationsPath))
461 app.installTranslator(qttr)
464 maetr.load("maegirls_" + loc,
465 "/usr/share/maegirls/translations")
467 # Install the translation
468 app.installTranslator(maetr)
470 # One day support portrait mode
471 #app.setAttribute(Qt.WA_Maemo5PortraitOrientation, True);
473 # Create the main window
489 # vim: set ts=8 sts=4 sw=4 noet formatoptions=r ai nocindent: