Code snippet program

This is the place to post any code that you want to share with the community. Only completed scripts should be posted here.

Code snippet program

Postby hansn » Tue Jun 11, 2013 11:55 pm

I just finished this, or at least I just made it work like it should :)

It's a GUI program where you can write your own snippets or import snippets from your filesystem into the program and load them into a database.

External libraries: PyQt4
It's written in python 2.7 but I have not tried running it on 3.x
Code: Select all
import sys
import sqlite3
from PyQt4 import QtGui, QtCore

class NamePopup(QtGui.QMainWindow):
    ''' If the user forgot to enter a name for the snippet he/she tried
        to commit to the database this widget pops up requesting a name '''
    def __init__(self, snippet, parent=None):
        super(NamePopup, self).__init__(parent)
        self.reference_ = None

        self.cw = QtGui.QWidget(self)
        self.setCentralWidget(self.cw)

        self.snippet = snippet

        # Widgets
        lbl = QtGui.QLabel('Please enter a name for your snippet', self.cw)
        self.txt = QtGui.QLineEdit(self.cw)
        cancel_btn = QtGui.QPushButton('Cancel', self.cw)
        self.btn = QtGui.QPushButton('Commit snippet', self.cw)
        self.btn.setEnabled(False)
       
        # Signals
        self.txt.textChanged.connect(lambda: self.show_btn())
        cancel_btn.clicked.connect(lambda: self.cancel())
        self.btn.clicked.connect(lambda: self.commit_snippet())

        # Layout
        grid = QtGui.QGridLayout(self.cw)

        grid.addWidget(lbl, 0, 0, 1, 2)
        grid.addWidget(self.txt, 1, 0, 1, 2)
        grid.addWidget(cancel_btn, 2, 0)
        grid.addWidget(self.btn, 2, 1)

        qr = self.frameGeometry()
        cp = QtGui.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def show_btn(self):
        '''Make the user unable/able to commit the snippet
           depending on wether he has entered a name for it'''
        if self.txt.text() == '':
            self.btn.setEnabled(False)
        else:
            self.btn.setEnabled(True)

    def cancel(self):
        self.reference_.setEnabled(True)
        self.deleteLater()

    def commit_snippet(self):
        '''Commit the snippet to the database'''
        con = sqlite3.connect('snippets.db')

        with con:
            cur = con.cursor()
            try:
                cur.execute("INSERT INTO snippets VALUES(?,?)",
                        (str(self.txt.text()), self.snippet))
            except sqlite3.OperationalError, e:
                print 'ERROR LINE 61: %s' % e
                print 'If \'no such table\', table is being created now'
                cur.execute("CREATE TABLE snippets(name TEXT, script TEXT)")
                cur.execute("INSERT INTO snippets VALUES(?,?)",
                            (self.txt.text(), self.snippet))

        self.reference_.setEnabled(True)
        self.reference_.snippet_box.addItem(self.txt.text())
        self.deleteLater()

    def connect(self, reference):
        ''' Receieves a reference to another object '''
        self.reference_ = reference
       
class MainFrame(QtGui.QMainWindow):
    def __init__(self):
        super(MainFrame, self).__init__()
        self.name_popup = None

        # -------------------- WIDGETS --------------------------- #
        self.cw = QtGui.QWidget(self)
        self.setCentralWidget(self.cw)

        self.code = QtGui.QTextEdit(self.cw)

        self.code_name = QtGui.QLineEdit(self.cw)
        code_name_lbl = QtGui.QLabel('Snippet name', self.cw)

        self.commit_btn = QtGui.QPushButton('Commit', self.cw)
        commit_lbl = QtGui.QLabel('Commit snippet', self.cw)

        browse_btn = QtGui.QPushButton('Browse', self.cw)
        browse_lbl = QtGui.QLabel('Browse filesystem', self.cw)
       
        snippets = self.get_db()
        self.snippet_box = QtGui.QComboBox(self.cw)
        for snippet in snippets:
            self.snippet_box.addItem(snippet[0])         
        self.open_btn = QtGui.QPushButton('Open', self.cw)
        self.delete_btn = QtGui.QPushButton('Delete', self.cw)
        if self.snippet_box.currentText() == '':
            self.open_btn.setEnabled(False)
            self.delete_btn.setEnabled(False)

        self.code.setStatusTip('Write your snippet here')
        self.code_name.setStatusTip('Write your snippets name here')
        self.commit_btn.setStatusTip('Commit snippet to database')
        browse_btn.setStatusTip('Open a snippet from the filesystem')
        self.snippet_box.setStatusTip('Choose a snippet')
        self.open_btn.setStatusTip('Open snippet')
        self.delete_btn.setStatusTip('Delete snippet')

        # -------------------- SIGNALS ------------------------ #
        self.commit_btn.clicked.connect(lambda: self.commit_snippet( \
                str(self.code_name.text()), str(self.code.toPlainText())))
        self.open_btn.clicked.connect(lambda: self.show_snippet( \
                self.snippet_box.currentText()))
        self.delete_btn.clicked.connect(lambda: self.delete_snippet( \
                self.snippet_box.currentText()))
        self.snippet_box.currentIndexChanged.connect(lambda: \
                self.open_delete_enabled())
        browse_btn.clicked.connect(lambda: self.show_dialog())

        # -------------------- LAYOUT ----------------------- #
        grid = QtGui.QGridLayout()
        grid.setSpacing(5) # CHANGE THIS ?
        grid.addWidget(code_name_lbl, 0, 0)
        grid.addWidget(self.code_name, 0, 1)
        grid.addWidget(self.code, 1, 0, 4, 2)
        grid.addWidget(commit_lbl, 1, 2)
        grid.addWidget(self.commit_btn, 1, 3)
        grid.addWidget(browse_lbl, 2, 2)
        grid.addWidget(browse_btn, 2, 3)
        grid.addWidget(self.snippet_box, 4, 2, 1, 2)
        grid.addWidget(self.open_btn, 5, 3)
        grid.addWidget(self.delete_btn, 5, 2)
         
        self.cw.setLayout(grid)
        self.statusBar()
        self.setGeometry(300,300,800,400)
        self.setWindowTitle('Snippets')
        self.show()       


    def open_delete_enabled(self):
        ''' Set the clickability of the open/delete snippet buttons
            depending on wether the user has selected a snippet in the
            QComboBox or not '''
        if self.snippet_box.currentText() == '':
            self.open_btn.setEnabled(False)
            self.delete_btn.setEnabled(False)
        else:
            self.open_btn.setEnabled(True)
            self.delete_btn.setEnabled(True)

    def delete_snippet(self, name):
        ''' Delete the snippet 'name' from the database '''
        name = str(name)
        con = sqlite3.connect('snippets.db')

        with con:
            cur = con.cursor()
            cur.execute("DELETE FROM snippets WHERE name = '%s'" % name)
            self.snippet_box.removeItem(self.snippet_box.currentIndex())

    def show_snippet(self, name):
        ''' Open the snippet currently selected in the QComboBox in
            the QTextEdit (and its name in the QLineEdit) '''
        con = sqlite3.connect('snippets.db')

        with con:
            cur = con.cursor()
            cur.execute("SELECT script FROM snippets WHERE name = '%s'" % name)
            self.code.setText(cur.fetchall()[0][0])
            self.code_name.setText(name)
             

    def show_dialog(self):
        ''' Open a dialog requesting a name for the snippet.
            This method gets called if the user does not enter
            a name before trying to commit the snippet'''
        fname = QtGui.QFileDialog.getOpenFileName(self, 'Open file',
                '/home')
        try:
            f = open(str(fname), 'r')
            with f:
                snippet = f.read()
                self.code.setText(snippet)   
                self.code_name.setText('')
        except IOError:
            pass

    def get_db(self):
        ''' Returns the contents of the 'snippets' table in the
            'snippets.db' database '''
        con = sqlite3.connect('snippets.db')

        with con:
            try:
                cur = con.cursor()
                cur.execute("SELECT * FROM snippets")
                rows = cur.fetchall()
                return [row for row in rows]
            except sqlite3.OperationalError, e:
                print 'ERROR LINE 204: %s' %  e
                print 'Function get_db returned dummy value: []'
                print 'IGNORE if you have not commited a snippet yet'
                return []
           
    def commit_snippet(self, name, script):
        ''' Commit snippet 'script' to the database '''
        if self.code_name.text() == '':
            self.name_popup = NamePopup(str(self.code.toPlainText()))
            self.name_popup.connect(self)
            self.name_popup.show()

            self.setEnabled(False)
        else:
            con = sqlite3.connect('snippets.db')

            with con:
                cur = con.cursor()
                try:
                    cur.execute("INSERT INTO snippets VALUES(?, ?)",
                                (name,script))
                except sqlite3.OperationalError, e:
                    print 'ERROR LINE 127: %s' % e
                    print 'If \'no such table\', table is being created now.'
                    cur.execute("CREATE TABLE snippets(name TEXT, script TEXT)")
                    cur.execute("INSERT INTO snippets VALUES(?, ?)",
                                (name, script))
                self.snippet_box.addItem(name)

        def connect(self):
            ''' Connect self to the NamePopup object '''
            self.name_popup.connect(self)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MainFrame()
    sys.exit(app.exec_())

The program automatically creates a database with sqlite3 in the same directory that it's run from. I.E you have to always run it from the same directory.
I could probably fix this and improve on some other things. But I'm getting tired of the project and want to start working on something else in stead.

It's my first 'real' finished project, so I just wanted to share it with you.

Feedback on the program is appreciated. Feedback on the code is appreciated even more.
hansn
 
Posts: 87
Joined: Thu Feb 21, 2013 8:46 pm

Re: Code snippet program

Postby micseydel » Wed Jun 12, 2013 2:36 am

My biggest feedback is that I would put the database-related code in a separate module from the GUI code. What if I wanted to write a different interface for your program, such as terminal or web? Keeping the interface as separate from the code that does the dirty work is always a good habit.
Join the #python-forum IRC channel on irc.freenode.net!
User avatar
micseydel
 
Posts: 929
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA


Return to Completed Scripts

Who is online

Users browsing this forum: No registered users and 1 guest

cron