The two sections below are mutually exclusive.
Started doing this 4/22/20, 14:53.
- Fix bug where the "pre-break" pomodoro (short break) displayed a percentage relative to a long break.
- Add a break at the beginning of the session in order to "ease" into the work session.
The beginning of 2020 completed TODOs starts here.
- Figure out how to import appJar onto my PC.
- Run the following command:
$ pip3 install appjar
Now that I've got appJar installed, I should try creating a basic GUI app.
- Create a basic GUI app.
- Mold this basic GUI app into what I need for Pomodoro.
- Find out how to control the logic of the buttons
- Find out how to have changing display over time
Seems like I want to have basic input and output, so I'm going to check out input widgets followed by output widgets.
- Check out input widgets.
Seems like I've gotten all the "input" I need already just by
modifying the original gui.py
file. Now, let's see what I can do with
output widgets. Maybe I can output what I was outputting before, anyway?
- Check out output widgets.
So in order to display my timer, I want to find out what the right output widget actually is. I'm going to research a few possibilities, and write down a few that I find might be relevant:
- Research different output widgets.
- Is there a "timer" or "clock" output widget?
- Label: Maybe I can have an algorithm (lol, should I even call it this) that updates the label every second?
- Message: This seems just like what I already have, but it doesn't seem appropriate because 1) it seems to be a place that stores a lot of text, and I don't want to store a lot of text; 2) I want a small amount of text. I guess these two go hand in hand.
- Meter: I definitely want this. I put a TODO checkbox for this.
- Separator: Separates widgets, but I'm not sure I'll have multiple widgets, and it also looks as if Label already does that somewhat.
- Grip: "Clickable icon to drag the window around." I think I want this. Adding a TODO.
- Canvas: Looks cool, but I don't want to draw anything for this one. Maybe I'll use this in the future?
- Turtle: A turtle widget. Apparently, turtle graphics are a popular way for introducing programming to kids. Maybe I'll check that out later if I want to make educational material.
- Microbit: Microbit emulator.. Here's Microbit's main page. Seems cool. I don't really know much about it. Apparently it's educational.
- Google Maps: Honestly, this seems really cool, and I'd want to make some GUI app that uses this.
- PieChart: "Widget to depict a Pie Chart."
- MatPlotLib: Honestly, (lol, I write "honestly" a lot) I could use this to make a GUI app to replace my django-glicko2 website.
Sounds like my main output widgets are:
- Label
- Meter
- Grip
We'll work on these one at a time, and I already have TODOs made for the latter two.
I'll have to see if I can somehow "reset" the application display before I display a Label output widget.
- Find out if you can:
- "reset" the application display Frames
- repopulate with a single Label (and later, Meter and Grip) Start and stop Frames.
Looks like what I need are Grouping Widgets.
It's sometimes desirable to group widgets together within a window. Or to have multiple pages of widgets.
I'll probably want a Frame Stack to
"reset" the application display stack the timer on top of the the initial GUI.
But don't I want to just reset and resize the display?
Frames are what I want. I can start and stop frames.
So what I want is:
refactor everything so far into a frame
on button press "submit":
stop the current frame
start a new frame
new frame is populated with only (sample) timer text
-
Implement above pseudocode.This is the wrong approach. I need to open and close windows.
One thing I don't understand is how they stop frames before starting and stopping the app. Maybe I just need to start and stop the app itself?
I might need Multiple Windows.
-
Redefine existing GUI in terms of a window that I can show/hide.
I actually want to go to a different page upon starting the timer via Multiple Pages.
According to Emptying Containers:
It's possible to quickly delete all widgets in a container, and then recreate them:
It might be another thing to just put a frame on top. But then how can I resize the window?
Let's just try to launch a new window upon "Start".
- Go to a new page/window upon "Start".
Maybe I can delete all widgets in the current window, and then display one?
-
delete all widgets in theDestroyHide current window, and then display one.
Let's see if I can update a Label continuously over time (and subsequently, the meter).
- Try to update a Label continuously over time.
In this section, I'll cover how I implement the interface between the GUI and the Pomodoro, globaltimer, etc. classes.
According to the other scripts I've written, custom_pomodoro.py
and timedpomodoro.py
,
I'm actually creating a timer on top of the existing Pomodoro()
class. I'll probably
need to do the same thing in interact.py
.
I need to implement logic for breaks and longbreaks in interact.py
.
- Implement logic for breaks and longbreaks in
interact.py
.
It looks like integrating my existing Python classes won't be as simple as I initially thought. I have a bunch of classes that don't directly allow me to display and return a "timer," per se. I'll need to write a class file that does exactly what I just described.
- Write a Python class file that directly interacts with my Pomodoro.
- Ideally, all it does is allow me to do the following things:
- Input initial time required.
- Output time remaining (for current pomodoro / break and global).
- Allow me to decrement the time remaining (for each second that passes).
- Ideally, all it does is allow me to do the following things:
There are two aspects to this:
- "session" timer
- "global" timer
In the first one, we need to find out if we are on a break or Pomodoro work session. In the second, we need to find out the total time remaining.
The second one seems to be taken care of mostly by global_timer.py
.
The first one seems like it might be tricky, but we implemented what that would look like in custom_pomodoro.py
.
Let's see how it's implemented there.
So according to custom_pomodoro.py
, we'll want to make a session = Pomodoro()
and session.set_goal()
and session.set_pomo()
.
(The session.set_pomo()
may be optional, but we'll see if we need it when we define each one.)
At the same time, we'll want to make a globaltimer = GlobalTimer()
and then globaltimer.set_timer(seconds)
.
session.set_goal()
: "set the goal in minutes, takes customGoal in minutes."This is specifically to do with the "number of Pomodoro" remaining, but we can cover more details laterThis might mean that we can set how long we want our session to be? It seems not exactly right, so I'll do more research later.session.set_pomo()
: "set the length of a pomodoro in minutes, takes customPomo in minutes." This means that we can give it the number of minutes we want each Pomodoro to be.session.get_pomodoro()
: "returns pomodoro amount in seconds." Is this used to return whether we're on a break or long break? Yes.IfBut not in that way.session.get_pomodoro() % 4 == 0
, then we get a long break. Else, it's a regular break.
We also want to check timedpomodoro.py
because that has the execute_pomodoro
function, which takes in a session = Pomodoro()
and a globaltimer = GlobalTimer()
as parameters.
An important distinction is that Pomodoro()
itself only keeps track of a few things
- Pomodori so far
- Whether we're on break
How much time remains in a single pomodoro
Importantly, it doesn't keep track of how much time is left in a single pomodoro.
Let's try to output the global timer first.
- Output global timer values and display it on the GUI.
Next, we need to decrement the timer label over time.
- Decrement timer label over time.
The problem is that I can change it, but it doesn't show up until the end of the session.
I finally found from this StackOverflow answer that I need to think about appJar's Loops and Sleeps.
- Check out appJar's Loops and Sleeps.
So I'm able to update the Label continuously over time, but two new problems have arisen:
-
The updates don't actually correspond to one second.
-
It's impossible to stop the timer (even with red X or ctrl+C on the keyboard in the terminal) unless I stop the "Python" task in task manager.
-
Get the updates to correspond to one second. (
app.setPollTime(1000)
) -
Fix the unstoppable timer issue mentioned above.
Apparently fixing the above TODO also fixed this TODO. Ctrl + C works now. The actual fix was taking out the unnecessaryshowSubWindow
s.
Actually, the unstoppable timer issue isn't as important. What I really need to do now is to display the Pomodoro timer on top of the global timer, as well as a background corresponding to what the session is (pomodoro, break).
-
Display the Pomodoro timer
on top ofnext to theon top of the global timer. -
Display background corresponding to what the session is (pomodoro, break). Maybe red for pomodoro, green for break?
So I've implemented the main logic of interact.py
. Now I need to play sounds to start breaks, pomodori, and when the global timer ends.
- Play sounds to start breaks, pomodori, and when the global timer ends.
- global timer end
- pomodori end
- break end
Sound is only supported in Windows, using the Winsound API. Therefore, only .WAV files will work.
Well, that fucking blows.
- Implement
.bell()
,, and.soundError()
for if not on Windows. The latter two don't work on non-Windows, and even on Windows they don't "work."soundWarning()
One issue right now is that once I start the timer, if I press "close" on that window, it doesn't close the application (i.e. terminal hangs).
- See if can resize the app via normal user window resizing. Probably via Paned Frames.
I'll eventually also need sound for my alarms so I'll check out sound for that.
- Check out sound.
I also want to see if Toolbars, Menubars, and Statusbars would be applicable for my app--that is, I want to be able to see at all times what the status of my Pomodoro is.
- Check out and see if applicable: Toolbars, Menubars, and Statusbars The most applicable one would be statusbar, but I already have a DualMeter for that.
I want to have a progress bar that displays actual overall progress (unlike my jank setup that doesn't work in the script).
- Add a progress bar (meter) that is properly calculated.
Moreover, for this progress bar, I want it to be able to show a color depending on what I'm doing. For example, red for breaktime, green for worktime.
- Find out if you can change the color of the progress bar (given that you can update it continuously over time, like the Label).
app.setMeterFill("progress", "blue")
I want a grip that allows me to move this thing around wherever I want.
-
Add a grip output widget.
-
Keep timer on top using
.setOnTop(stay=True)
. Problem: it doesn't work properly. It'll only stay on top per update, and if I want to stay focused on a different application, it won't stay on top.
For the purpose of exporting the program as an executable binary, I might want to use PyInstaller on top of this appJar business.
- Try using PyInstaller to bundle the appJar Python GUI program as a Windows executable.
There's a bug in that the window constantly takes focus. We might be able to fix that by doing the following:
- See if you can't eliminate extra
app.showSubWindow("Pomodoro")
lines. This should only be needed once.
- In
topbar.py
, play sounds. - Add multithreading action!
- Use BitBar (already installed) to display the script on top bar on Mac.
It displays at the top, but the main problem is that it expects a one-line output. All I need to do is update a file over time, and it'll work.
-
Make a Python script that updates a file over time, then make another that only reads and prints the line from the file.
-
Allow custom settings, i.e., allow them to change the length of pomodoro, break, and longbreak.
- Just ask them at the beginning.
- Test to see if this works.
- Just ask them at the beginning.
-
Use Overcooked sounds as default. More details later.I decided that having custom sounds are just better overall, and isn't mutually exclusive from having Overcooked sounds. -
See if can resize the app via code.The app already takes minimal space.
- PowerPom - Pomodoro Timer: In this one, I don't see an option to make it a tiny part of the screen. Moreover, it has ads. Yuck.
- Focus Booster App: 30-day trial. Also yuck.
- Top 10 Free and Open Source Pomodoro Apps: The problem is that these don't do exactly what I want it to do, and the windows themselves (in the case of having any of them always-on-top) seem too big.
(4/21/2020, 20:43) It works! Top bar application works, but I need to write instructions and installation.
(4/20/2020, 20:53) There may be hope yet for that problem below! Check latest TODO.
(4/20/2020, 00:43) This doesn't quite work on Mac. The window keeps going to the front, but more importantly, steals focus from other apps.
(4/19/2020, 17:08) I've finished the main functionality of the GUI app. There are several issues and bugs I plan to fix, but since I mainly need to study material for job interviews (algorithms and such), I'll postpone the fixing and cross-platform release to another weekend. For now, I have a working application that is better than my previous iteration.
BIG caveat: Sounds only work on Windows. Sucks.
I use DeskPins to keep the window pinned on top.
The old README can be found here.
I've been trying to create a good, cross-platform GUI for this, as can be seen here and my research into QtCreator, and also the original README in which I talked about making a good GUI way back in 2015 or so. I figured that Python must have its own GUI-app type framework, so I found, from the Python Wiki, appJar, which is something like Tkinter (something that Andy, my old, flakey project partner put into the project specifications of a project that I ended up doing on my own).
So I'll be making an app using appJar to make this a reality. Hopefully, it will be a "double click this to run it" app that is easy to use for all kinds of people, whether they are technologically literate or not.
Small python scripts designed to help with productivity.
Uses Python 3! As far as I know, it still works with Python 2.
Usage:
python3 custom_pomodoro.py
OR
python custom_pomodoro.py
Running this requires installation of pygame.
- Here are the official pygame installation instructions.
Alternatives if that doesn't work:
- PyGame Installation Mac OS X
- Installing pygame (Mac) for Python 2
- Old Ask Ubuntu forum on installing Pygame
Wikipedia page about Pomodoro Technique.
TODO:
-
Add a separate thread for playing the sound
-
Make a Windows, Mac, Linux, and Android executable/app
- Windows
- Mac
- Linux
- Android
-
Account for breaks and global timer in determining #pomodori & percentage
-
Include functionality for smarter "break" times (e.g. if 3 hours, 6 pomodori, break after 3 instead of 4) <-- probably completely optional/unoptimal