Skip to main content

Ralsina.Me — Roberto Alsina's website

uRSSus: now with configuration dialog goodness!

I felt that a "user-friend­ly" con­fig­u­ra­tion di­a­log for uRSSus was not a good way to spend ef­fort, be­cause I ex­pect op­tions to change of­ten for a while, and I did­n't want an out­dat­ed di­alog, ei­ther. The so­lu­tion? Au­to­gen­er­ate a medi­ocre con­fig­u­ra­tion di­alog!

First, de­fine what op­tions uRSSus sup­ports (Up­date: sug­ges­tion by Ale­jan­dro Cu­ra, us­ing tu­ples works much bet­ter!):

options = (
  ('ui',
    (
      ('alwaysShowFeed',  ('bool', False, "Always show a link to the post's feed when diplaying a post")),
      ('hideOnTrayClick', ('bool', True, "Hide the main window when clicking on the tray icon")),
    )
  ),
  ('options',
    (
      ('defaultRefresh'      ,  ('int', 1800, "How often feeds should be refreshed by default (in seconds).", 300, None )),
      ('maxPostsDisplayed'   ,  ('int', 1000, "Limit the display to this many posts. If set too high, opening 'All Feeds' may take forever", 0, None)),
      ('defaultExpiration'   ,  ('int',    7, "How long should articles be kept by default. (In days)", 0, 9999)),
    )
  ),
  ('twitter',
    (
      ('username',  ('string', None, 'Your Twitter user name.' )),
      ('password',  ('password', None, 'Your Twitter password.' )),
    )
  )
)

Then a lit­tle mag­ic, and this comes out:

urssus13

How mag­ic? This mag­ic:

class ConfigDialog(QtGui.QDialog):
  def __init__(self, parent):
    QtGui.QDialog.__init__(self, parent)
    # Set up the UI from designer
    self.ui=UI_ConfigDialog()
    self.ui.setupUi(self)
    pages=[]
    sections=[]
    self.values={}

    for sectionName, options in config.options:
      # Create a page widget/layout for this section:
      page=QtGui.QScrollArea()
      layout=QtGui.QGridLayout()
      row=-2
      for optionName, definition in options:
        row+=2
        if definition[0]=='bool':
          cb=QtGui.QCheckBox(optionName)
          cb.setChecked(config.getValue(sectionName, optionName, definition[1]))
          layout.addWidget(cb, row, 0, 1, 2)
          self.values[sectionName+'/'+optionName]=[cb, lambda(cb): cb.isChecked()]


        elif definition[0]=='int':
          label=QtGui.QLabel(optionName+":")
          label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
          spin=QtGui.QSpinBox()
          if definition[3] is not None:
            spin.setMinimum(definition[3])
          else:
            spin.setMinimum(-99999)
          if definition[4] is not None:
            spin.setMaximum(definition[4])
          else:
            spin.setMaximum(99999)
          spin.setValue(config.getValue(sectionName, optionName, definition[1]))
          layout.addWidget(label, row, 0, 1, 1)
          layout.addWidget(spin, row, 1, 1, 1)
          self.values[sectionName+'/'+optionName]=[spin, lambda(spin): spin.value()]

        elif definition[0]=='string':
          label=QtGui.QLabel(optionName+":")
          label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
          text=QtGui.QLineEdit()
          text.setText(config.getValue(sectionName, optionName, definition[1]))
          layout.addWidget(label, row, 0, 1, 1)
          layout.addWidget(text, row, 1, 1, 1)
          self.values[sectionName+'/'+optionName]=[text, lambda(text): unicode(text.text())]

        elif definition[0]=='password':
          label=QtGui.QLabel(optionName+":")
          label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)
          text=QtGui.QLineEdit()
          text.setEchoMode(QtGui.QLineEdit.Password)
          text.setText(config.getValue(sectionName, optionName, definition[1]))
          layout.addWidget(label, row, 0, 1, 1)
          layout.addWidget(text, row, 1, 1, 1)
          self.values[sectionName+'/'+optionName]=[text, lambda(text): unicode(text.text())]

        help=QtGui.QLabel(definition[2])
        help.setWordWrap(True)
        layout.addWidget(help, row, 2, 1, 1)
        separator=QtGui.QFrame()
        separator.setFrameStyle(QtGui.QFrame.HLine|QtGui.QFrame.Plain)
        layout.addWidget(separator, row+1, 0, 1, 3)
      page.setLayout(layout)
      pages.append(page)
      sections.append(sectionName)

    for page, name in zip(pages,sections) :
      # Make a tab out of it
      self.ui.tabs.addTab(page, name)
    self.ui.tabs.setCurrentIndex(1)
    self.ui.tabs.removeTab(0)

My first ev­er thing that I just don't see how it would work with­out a lamb­da ;-)

Urssus: Sorry about 0.2.9

Tru­ly a pa­perbag re­lease. But there's still hope!

While 0.2.9 had a num­ber of bugs and aw­ful per­for­mance, I have to say that the cur­rent svn re­vi­sions are much, much, bet­ter.

  • Snap­py per­­for­­mance (ok, not quite snap­py, but snap­pi­er than 0.2.0)

  • Fi­­nal­­ly a co­her­ent nex/pre­vi­ous/what­ev­er mech­a­nis­m. The on­­ly bro­ken piece is that posts may van­ish from view when the feed is up­­­dat­ed (and I can fix that, too).

  • Fixed is­­sues 16,14 and 22

So, 0.2.10, com­ing tonight, should be a pret­ty good one.

Urssus: 0.2.9 is out

Ver­sion 0.2.9 of uRSSus, my news agre­ga­tor is out. Many new fea­tures in­clud­ing:

  • Dif­fer­­ent lay­outs (reg­u­lar/widescreen/­­com­bined, aka river-of-news)

  • Twit­ter about things you see on uRSSus with a sin­­gle click

  • Many many bug­­fix­es

  • Lots of UI im­prove­­ments

And so on.

Urssus: import from google reader

It was rather easy be­cause I did­n't do the hard part (thanks au­thors of pyr­feed!)and now uRSSus has a sim­ple "im­port my sub­scrip­tions from Google Read­er" ac­tion.

All I can say is "it works for me" and "Google sure strips da­ta from the feed­s!".

It will im­port your tags as top-lev­el fold­ers (merged with what­ev­er you al­ready had).

Should be smart enough not to du­pli­cate feeds or fold­er­s.

If a feed is in more than one fold­er, it will show in the first list­ed by google (no idea what the or­der is).

Urssus: August 2nd - going small

Most­ly, I spent my two hours to­day refac­tor­ing. But al­so, test­ing how uRSSus looks on a small screen. Take a look:

urssus16

This is urssus in the con­fig­u­ra­tion I liked best on my 7", 800x480 eeeP­C's screen.

As you can see, a more com­pact tem­plate for the com­bined view is a must, and I will im­ple­ment a com­pact tem­plate. Or maybe just make a con­fig­u­ra­tion op­tion where you choose what tem­plate the com­bined view us­es, to avoid the mul­ti­pli­ca­tion of "mod­es" that are the ex­act same thing un­der the hood.

Us­ing com­bined view with all bars hid­den and fullscreen makes for a rather large read­ing area, which is nice.

The per­for­mance in that lim­it­ed com­put­er was good... un­til the mem­o­ry us­age bal­loon­s. While uRSSus is not too CPU hun­gry, it's pret­ty mem­o­ry in­ten­sive. There are ob­vi­ous ways to im­prove that, of course, and I am ex­plor­ing them.

BTW, I have not mea­sured this in a while: 1957 lines of code. And still quite fun!


Contents © 2000-2023 Roberto Alsina