Posts Tagged ‘Python’

A Little Python Fun

Sunday, January 4th, 2009

When I last touched Python, I wrote a snippet to steal the latest comic off xkcd.com. Like most of the things that I do (this only applies to individual projects, not teamwork), there are long breaks until I make any progress. Probably it’s because I multi-task too much. At the same time, I never run out of things to do. Recently I’ve been blessed with a couple hours of fre etime, and so I’ve touched Python again, and decided it was time to learn some GUI.

Which toolkit? The Qt one of course (pronouned ‘cute’)! Powerful, cross-platform, native to KDE. Here’s my first (well first mentionable) GUI application coded with Python and the PyQt4 bindings. (Last mentionable GUI stuff was with VB6 – Yes, I did do application programming when I was 9 years old, childish programs they were, but mentionable).

The application is a simple text editor which supports opening/saving files, and warns you if you’ve made changes but haven’t saved yet. Yes, the process of making it was from a tutorial, though each step was figured out myself. Basically the tutorial says “Ok, now we’ll add a save button”, then I search the Python and PyQt4 documentation to figure out how, then cross reference my code with the tutorial. Here’s a screenshot:

2008-12-28-175239_1280x800_scrot

For the geeky, here is the code:

import sys

from PyQt4 import QtCore, QtGui
from editor import Ui_notepad

class StartQT4(QtGui.QMainWindow):

  def __init__(self, parent=None):

    QtGui.QWidget.__init__(self, parent)
    self.ui = Ui_notepad()
    self.ui.setupUi(self)

    # Connect signals

    QtCore.QObject.connect(self.ui.button_open,QtCore.SIGNAL("clicked()"), self.file_dialog)
    QtCore.QObject.connect(self.ui.button_save,QtCore.SIGNAL("clicked()"), self.file_save)
    QtCore.QObject.connect(self.ui.editor_window,QtCore.SIGNAL("textChanged()"), self.enable_save)

  def file_dialog(self):

    response = False

    if self.ui.button_save.isEnabled() and self.filename:

      message = QtGui.QMessageBox(self)

      message.setIcon(QtGui.QMessageBox.Question)
      message.addButton('Save', QtGui.QMessageBox.AcceptRole)
      message.addButton('Discard', QtGui.QMessageBox.DestructiveRole)
      message.addButton('Cancel', QtGui.QMessageBox.RejectRole)
      message.setText('Do you want to save changes?')
      message.setDetailedText('Unsaved changes in file: ' + str(self.filename))
      message.setWindowTitle('Notepad')

      message.exec_()

      response = message.clickedButton().text()

      if response == 'Save':

        self.file_save()
        self.ui.button_save.setEnabled(False)

      elif response == 'Discard':

        self.ui.button_save.setEnabled(False)

    if response != 'Cancel':

      fd = QtGui.QFileDialog(self)
      self.filename = fd.getOpenFileName()

      from os.path import isfile

      if isfile(self.filename):

        plik = open(self.filename).read()
        self.ui.editor_window.setText(plik)

        self.ui.button_save.setEnabled(False)

  def file_save(self):

    fd = QtGui.QFileDialog(self)
    self.filename = fd.getSaveFileName()

    from os.path import isfile

    if isfile(self.filename):

      plik = open(self.filename, 'w').write(self.ui.editor_window.toPlainText())

      self.ui.button_save.setEnabled(False)

  def enable_save(self):

    self.ui.button_save.setEnabled(True)

if __name__ == "__main__":

  app = QtGui.QApplication(sys.argv)
  myapp = StartQT4()
  myapp.show()
  sys.exit(app.exec_())

Tada. You will also need another file called editor.py (click to download) in the same directory from which the UI information will be grabbed from.

Ok, next Python project will be more advanced, which’ll be a graphical game of solitaire featuring custom widgets and drag and drop functionality. Oooh. Tough.

Python steals XKCD Comics – snippet

Monday, July 21st, 2008

Useful information stuff:
After 70-640, the students who are enrolled for 640-822 start preparing for their 70-236 as well as 640-863 so that they can be exempted from 642-436 and 1Y0-259 and can appear directly in 70-536, saving time and resources.

When somebody asks a programmer:XKCD Comics

Dude, why do you program? There’s nothing useful that you can make that hasn’t been made already. It’s like making your own hand-phone when you could just buy it at a shop. Go get a life and do something productive.

Then of course, the programmer smiles and replies:

Why, for:

  • The money
  • The girls (“ooh that looks terribly complex…”, oh yes, it is…“)
  • Nobody can check whether or not you’re really doing your work.

However, I personally think that programmers do it because they like to communicate with their computer. Since I’m learning Python, I like to learn it through making small things to speed up my day. I’ve made a blackjack game (OK, that slows down my day), a program that executes series of shell commands to speed up boring tasks, a to-do list program, and my latest creation:

“Something-that-finds-the-latest-comic-on-xkcd.com-and-downloads-it-to-a-file”

Of course, all you need to do is setup a cron-job to execute the snippet every time XKCD updates (Mondays, Wednesdays, Fridays) and bingo, you’ve just got yourself a personal archive of missed XKCD comics!

Here there be snippet:

#!/usr/bin/env python
import urllib
source = urllib.urlopen('http://xkcd.com/').read()
linebyline = source.splitlines()
found = 0
for value in linebyline:
    if found == 0:
        check = value.find('http://imgs.xkcd.com/comics/')

        if check != -1:
            found = 1
            # find the next occurance of the " to find end of URL.
            next = value.find('"', 10)
            image = value[check:next]
            length = len('http://imgs.xkcd.com/comics/')
            print 'Comic found: ' + image
            length = length + check
            filename = value[length:next]
            print 'Saved under: ' + filename
            path = '/home/dion/documents/Projects/Python/' # change this!
            image_file = urllib.urlretrieve(image, path + filename)

    else:
        break

Amazing, isn’t it? Here’s the latest one I grabbed:

…and oh yes, it was terribly complicated.