Build a Multi‑Book PDF Reader with Python, Qt, and SQLite

This article walks through the development of PyReadon, a Python‑based PDF reader that supports adding, deleting, reading, and tracking multiple books, with left‑click page turning and persistent storage using SQLite.

Python Crawling & Data Mining
Python Crawling & Data Mining
Python Crawling & Data Mining
Build a Multi‑Book PDF Reader with Python, Qt, and SQLite

After two weeks of iteration, PyReadon now provides basic PDF reader functions such as adding, deleting, reading books, saving reading records, and viewing book information.

The latest version optimizes the book data structure, enabling simultaneous reading of multiple books, left‑click page turning, and interaction with an SQLite database to store library and book details (path, page, flag).

Book Class

The Book class stores metadata, page number, and reading status, and implements the __eq__ method to compare two book instances.

class Book:
    def __init__(self, fname):
        # filename
        self.fname = fname
        # reading flag
        self.flag = None
        self._info = None
        self._page = 0
        self.get_meta_data(self.fname)

    def __eq__(self, other):
        if hasattr(other, 'fname'):
            return self.fname == other.fname
        return False

Simultaneous Reading

PyReadon maintains a read_list list that stores Book objects, each with a page attribute, allowing the program to remember the current page of each open book.

self.read_list = [None]
self.read_list.extend(book for book in self.booklist if book.flag)

Left‑Click Page Turning

The mousePressEvent method of the custom MyArea widget captures mouse coordinates; clicking in the left third of the widget turns the page backward, while clicking in the right third turns it forward.

# Mouse left‑click page turning
def mousePressEvent(self, event):
    pos = event.pos().x()
    width = self.size().width()
    if event.button() == Qt.LeftButton:
        if pos > width * 2 / 3:
            self.right()
        elif pos < width / 3:
            self.left()

SQLite Integration

SQLite provides a lightweight, server‑less database. On startup, read_db creates PDF.db and a book_info table if they do not exist, then yields Book objects populated with stored data.

book_db = 'PDF.db'
book_info = namedtuple('info', 'path page flag')

def read_db():
    os.chdir(os.path.dirname(os.path.realpath(__file__)))
    if not os.path.exists(book_db):
        conn = sqlite3.connect(book_db)
        conn.execute("CREATE TABLE book_info(path, page, flag)")
        conn.close()
    conn = sqlite3.connect(book_db)
    for row in conn.execute('SELECT * FROM book_info'):
        info = book_info(*row)
        book = Book(info.path)
        book.page = info.page
        book.flag = info.flag
        yield book
    conn.close()

Saving data uses save2db, which inserts each book’s path, page, and flag into the database via executemany. The remove_db function clears the table before a new save.

def save2db(booklist):
    conn = sqlite3.connect(book_db)
    conn.executemany("INSERT INTO book_info Values (?,?,?)",
        ((book.fname, book.page, book.flag) for book in booklist))
    conn.commit()
    conn.close()

def remove_db():
    conn = sqlite3.connect(book_db)
    conn.execute('DELETE FROM book_info')
    conn.commit()
    conn.close()

Viewing Book Information

Right‑clicking a book triggers a QMessageBox that displays its metadata (path, format, title, author, creator, producer).

elif action == item3:
    index = row_num * 8 + col_num
    book = self.booklist[index]
    info = book.info
    fmt = f'路径:{info.path}

' \
          f'格式:{info.format}

' \
          f'标题:{info.title}

' \
          f'作者:{info.author}

' \
          f'Creator:{info.creator}

' \
          f'Producer:{info.producer}

'
    QMessageBox.about(self, '文档信息', fmt)

The complete source code is available on GitHub at https://github.com/cassieeric/Python-Application for further study.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Code ExampleQtpdf-readerdesktop-application
Python Crawling & Data Mining
Written by

Python Crawling & Data Mining

Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.