4 # Copyright (C) 2010 Stefanos Harhalakis
6 # This file is part of mydays.
8 # mydays 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 # mydays 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 mydays. 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 *
31 from graph import DaysGraph
38 class ConfigDialog(QDialog):
39 def __init__(self, *args, **kwargs):
40 QDialog.__init__(self, *args, **kwargs)
42 self.editName=QLineEdit(self)
43 self.editCycle=QSpinBox(self)
44 self.editCurrent=QSpinBox(self)
45 self.editCycle.setRange(10,50)
46 self.editCurrent.setRange(1,50)
47 self.editCurrent.setWrapping(True)
48 self.editCycle.setSuffix(" days")
50 self.editCycle.valueChanged.connect(self.slotEditCycleChanged)
52 self.l0=QHBoxLayout(self)
55 l1.addRow("Name:", self.editName)
56 l1.addRow("Cycle length:", self.editCycle)
57 l1.addRow("Current day in cycle:", self.editCurrent)
61 spacer=QSpacerItem(20, 20, QSizePolicy.Expanding)
62 self.l0.addItem(spacer)
67 self.buttonOk=QPushButton(self)
68 self.buttonOk.setText("OK")
69 self.buttonOk.clicked.connect(self.slotButOk)
70 l2.addWidget(self.buttonOk)
72 spacer=QSpacerItem(20, 20, QSizePolicy.Minimum,QSizePolicy.Expanding)
75 self.setWindowTitle("Configuration")
78 self.name=str(self.editName.text())
79 self.cycle=self.editCycle.value()
80 self.current=self.editCurrent.value()-1
84 def slotEditCycleChanged(self, value):
85 self.editCurrent.setMaximum(value)
87 # current starts from 0
88 def initValues(self, dt):
90 self.editName.setText(dt['name'])
91 self.editCycle.setValue(dt['cycle'])
92 self.editCurrent.setValue(dt['day0']+1)
94 class MyMsgDialog(QDialog):
96 A Dialog to show a finger-scrollable message
100 class Koko(MyMsgDialog):
102 MyMsgDialog.__init__(....)
105 self.setWindowTitle("My title")
107 l1=QLabel("koko", self.w)
111 self.l is a QVBoxLayout. Add everything there.
112 self.w is a QWidget. Use it as parent.
115 def __init__(self, *args, **kwargs):
116 QDialog.__init__(self, *args, **kwargs)
118 # This freaking thing is hard
119 # It needs two layouts, one extra widget, the fingerscrollable
120 # property set to true *and* setWidgetResizable(True)
121 self._mm_l0=QVBoxLayout(self)
123 self._mm_q=QScrollArea(self)
124 self._mm_q.setWidgetResizable(True)
125 self._mm_q.setProperty('FingerScrollable', True)
127 self.w=QWidget(self._mm_q)
129 self.l=QVBoxLayout(self.w)
130 self._mm_q.setWidget(self.w)
131 self._mm_l0.addWidget(self._mm_q)
133 class AboutDialog(MyMsgDialog):
134 def __init__(self, *args, **kwargs):
135 MyMsgDialog.__init__(self, *args, **kwargs)
138 <p> A program to monitor the women's cycle. Good for planning (or acting ;-).
139 Inspired by "MyGirls" app which is (was?) available for Java ME capable phones.
141 <p style="color: orange;">
142 WARNING!!! This is not accurate nor correct! You cannot trust
143 this program (or any other program) for accurate predictions!
144 (after all, this is about women... how can one be sure :-).
146 <p> Copyright © 2010, Stefanos Harhalakis <v13@v13.gr>
148 <p> Send comments and bug reports to the above address.
150 <p> This program can be distributed under the terms of the GNU public
151 license, version 3 or any later.
154 self.setWindowTitle("About MaeGirls")
156 self.ltitle=QLabel("MaeGirls", self.w)
157 self.ltitle.setObjectName("title")
158 self.ltitle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
159 self.ltitle.setAlignment(Qt.AlignCenter)
160 self.l.addWidget(self.ltitle)
162 self.label=QLabel(txt, self.w)
163 self.label.setWordWrap(True)
164 self.label.setTextFormat(Qt.RichText)
165 self.label.setAlignment(Qt.AlignJustify)
166 self.l.addWidget(self.label)
168 self.ltitle.setStyleSheet("""
171 color: rgb(192,192,192);
172 margin-bottom: 0.5ex;
176 class HelpDialog(MyMsgDialog):
177 def __init__(self, *args, **kwargs):
178 MyMsgDialog.__init__(self, *args, **kwargs)
181 <p> MaeGirls shows information about women's cycle using some generic
182 guidelines. It assumes that the ovolution happens 14 days before the start
183 of the next period and that the period cycle is constant. Also, it assumes
184 that sperm can live for 4 days, while an egg can live for 2 days.
186 <p style="color: orange;">
187 WARNING!!! This is not always correct. There are FAR TOO MANY exceptions
188 to the above rules!!!
190 <p> Assuming that you understand the risk of being wrong, you become
191 entitled to read the graph as follows:
192 <p> <span style="color: red">In red:</span> The days that menstruation
194 <p> <span style="color: green">In green:</span> The fertile days.
195 <p> <span style="color: blue">In blue:</span> The days of PMS
196 (Premenstrual Syndrome).
198 <p> Navigation is easy: Use left-right finger movement to move the calendar
199 view. Use up-down finger movement to zoom in/out.
202 self.setWindowTitle("Help")
204 self.label=QLabel(txt, self.w)
205 self.label.setWordWrap(True)
206 self.label.setTextFormat(Qt.RichText)
207 self.label.setAlignment(Qt.AlignJustify)
208 self.l.addWidget(self.label)
210 class GirlsDialog(QDialog):
211 def __init__(self, *args, **kwargs):
212 QDialog.__init__(self, *args, **kwargs)
214 self.l0=QHBoxLayout(self)
216 self.lstm=QStringListModel()
217 self.lst=QListView(self)
218 self.lst.setModel(self.lstm)
220 self.l0.addWidget(self.lst)
222 self.buttonNew=QPushButton(self)
223 self.buttonNew.setText("New")
225 self.buttonSelect=QPushButton(self)
226 self.buttonSelect.setText("Select")
228 self.buttonDelete=QPushButton(self)
229 self.buttonDelete.setText("Delete")
231 spacer=QSpacerItem(20, 20, QSizePolicy.Minimum,QSizePolicy.Expanding)
233 self.l1=QVBoxLayout()
234 self.l0.addLayout(self.l1)
235 self.l1.addWidget(self.buttonNew)
236 self.l1.addWidget(self.buttonSelect)
237 self.l1.addWidget(self.buttonDelete)
238 self.l1.addItem(spacer)
240 self.buttonNew.clicked.connect(self.slotNew)
241 self.buttonDelete.clicked.connect(self.slotDelete)
242 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)
264 # Set current selection
265 idx=dt.index(current)
266 self.lst.setCurrentIndex(self.lstm.index(idx))
276 def slotDelete(self):
278 self.which=self._get_selection()
281 def slotSelect(self):
283 self.which=self._get_selection()
286 class MaeGirls(QMainWindow):
287 def __init__(self, algo):
288 QMainWindow.__init__(self)
292 self.dlgConfig=ConfigDialog(self)
293 self.dlgAbout=AboutDialog(self)
294 self.dlgHelp=HelpDialog(self)
299 def setupUi(self, algo):
300 self.centralwidget=QWidget(self)
301 self.setCentralWidget(self.centralwidget)
303 self.l0=QVBoxLayout(self.centralwidget)
305 self.dg=DaysGraph(algo, self.centralwidget)
306 self.l0.addWidget(self.dg)
309 self.menuconfig=QAction('Configure', self)
310 self.menuconfig.triggered.connect(self.menuConfig)
312 self.menureset=QAction('Go to today', self)
313 self.menureset.triggered.connect(self.menuReset)
315 self.menugirls=QAction('Girls', self)
316 self.menugirls.triggered.connect(self.menuGirls)
318 self.menuabout=QAction('About', self)
319 self.menuabout.triggered.connect(self.menuAbout)
321 self.menuhelp=QAction('Help', self)
322 self.menuhelp.triggered.connect(self.menuHelp)
325 m.addAction(self.menuconfig)
326 m.addAction(self.menureset)
327 m.addAction(self.menugirls)
328 m.addAction(self.menuhelp)
329 m.addAction(self.menuabout)
331 self.setWindowTitle("MaeGirls")
333 def setAlgo(self, algo):
334 self.dg.setAlgo(algo)
336 def setGirl(self, name):
337 cfg=config.loadGirl(name)
339 self.algo.setReference(cfg['day0'], cfg['cycle'])
342 def menuConfig(self):
343 if self.dlgConfig==None:
344 self.dlgConfig=ConfigDialog(self)
348 'cycle': self.algo.cycleLength(),
349 'day0': self.algo.currentDayInCycle()
352 self.dlgConfig.initValues(dt)
354 ret=self.dlgConfig.exec_()
356 if ret==self.dlgConfig.Accepted:
359 name=self.dlgConfig.name
360 day0=today-self.dlgConfig.current
363 'cycle': self.dlgConfig.cycle,
367 config.storeGirl(name, dt)
368 config.setCurrentGirl(name)
370 # If this is a rename, remove the old one
372 config.removeGirl(self.girl)
379 if self.dlgGirls==None:
380 self.dlgGirls=GirlsDialog(self)
382 ret=self.dlgGirls.exec_(self.girl)
384 what=self.dlgGirls.what
385 which=self.dlgGirls.which
387 # Determine a unique name
391 while config.girlExists(name):
393 name="%s%d" % (base, idx)
397 config.setCurrentGirl(name)
401 elif what=='delete' and which!=None:
403 msg=QMessageBox(self)
404 msg.setText("You cannot delete the current girl")
407 config.removeGirl(which)
408 elif what=='select' and which!=None:
409 config.setCurrentGirl(which)
413 if self.dlgAbout==None:
414 self.dlgAbout=AboutDialog(self)
416 ret=self.dlgAbout.exec_()
419 if self.dlgHelp==None:
420 self.dlgHelp=HelpDialog(self)
422 ret=self.dlgHelp.exec_()
431 app=QApplication(sys.argv)
432 #app.setAttribute(Qt.WA_Maemo5PortraitOrientation, True);
448 # vim: set ts=8 sts=4 sw=4 noet formatoptions=r ai nocindent: