From f37ae5235dba470cf02e25a885b83a2bc9c78694 Mon Sep 17 00:00:00 2001 From: Harishankar Date: Tue, 30 Nov 2010 15:57:14 +0530 Subject: [PATCH] Website exporter in progress - completed home page Exporter in progress. Currently completed the export of the main index.html file and the style sheet style.css --- biaweb_db.py | 28 +++++++++ biaweb_exporter.py | 141 ++++++++++++++++++++++++++++++++++++++++++ biaweb_strings.py | 22 ++++++- generate_dialog.py | 24 +++++++ generate_dialog.ui | 8 +-- main_window.py | 2 +- ui_generate_dialog.py | 10 +-- ui_main_window.py | 2 +- 8 files changed, 225 insertions(+), 12 deletions(-) create mode 100644 biaweb_exporter.py diff --git a/biaweb_db.py b/biaweb_db.py index b310972..9b7cb10 100644 --- a/biaweb_db.py +++ b/biaweb_db.py @@ -207,6 +207,34 @@ def get_configuration (dbname): except sqlite3.Error: return False +# Function to get the latest articles (inner join with categories to get category stub) +def site_latest_articles (dbname, num_arts): + try: + conn = sqlite3.connect (dbname) + c = conn.cursor () + c.execute ("SELECT * FROM articles INNER JOIN categories ON articles.cid=categories.cid \ + ORDER BY cdate DESC LIMIT ?;", (num_arts,)) + conn.commit () + rows = c.fetchall () + conn.close () + return rows + except sqlite3.Error: + return False + +# Function to get the best rated articles (inner join with categories to get category stub) +def site_get_bestrated (dbname): + try: + conn = sqlite3.connect (dbname) + c = conn.cursor () + c.execute ("SELECT * FROM articles INNER JOIN categories ON articles.cid=categories.cid \ + ORDER BY rating DESC LIMIT 5;") + conn.commit () + rows = c.fetchall () + conn.close () + return rows + except sqlite3.Error: + return False + # Function to get list of articles (either full list or just in a category def get_articles (dbname, category_id=None): try: diff --git a/biaweb_exporter.py b/biaweb_exporter.py new file mode 100644 index 0000000..5bbe32b --- /dev/null +++ b/biaweb_exporter.py @@ -0,0 +1,141 @@ +# BiaWeb Website content manager (c) 2010 V.Harishankar +# Site exporter/generator class + +import os +import os.path +import time +import sqlite3 +import string +import shutil +import biaweb_db + +# to format the best rated articles in a HTML link list +def html_format_best_rated (best_rated): + items = [ "\n") + str_items = "".join (items) + return str_items + +# to format categories in a HTML link list +def html_format_categories (cats): + items = [ "\n") + str_items = "".join (items) + return str_items + +# function to generate main index file and stylesheet +def generate_home_page (dbname, conf, templates, category_str, bestrated_str): + # main template + tpl_main = string.Template (templates[0][1]) + # index bit + tpl_indexbit = string.Template (templates[6][1]) + # news bits + tpl_newsbit = string.Template (templates[2][1]) + + # get the latest articles - conf[4] is num of rss entries to be used also + latest_arts = biaweb_db.site_latest_articles (dbname, conf[4]) + if latest_arts == False: + return False + + news_items = [] + + # Run through the latest articles + # for the num of latest news items on index + for art in latest_arts: + # url is Category/Article.html + url = art[13] + "/" + art[8] + ".html" + # art[5] is creation time + strdate = time.ctime (art[5]) + # now populate the template variables. art[1] is title, art[2] is summary + strnews = tpl_newsbit.safe_substitute (news_title = art[1], + news_link = url, + news_datetime = strdate, + news_description = art[2] + ) + news_items.append (strnews) + # now convert it into a string + newsbit_str = "".join (news_items) + + # now populate the index template + indexbit_str = tpl_indexbit.safe_substitute (site_name = conf[1], + news_updates = newsbit_str + ) + # now populate the main page template + main_str = tpl_main.safe_substitute (site_title = conf[1], + site_url = "http://" + conf[0], + meta_keywords = conf[2], + meta_description = conf[3], + page_title = conf[1], + page_desc = conf[3], + contents_bit = indexbit_str, + list_of_categories = category_str, + list_best_rated = bestrated_str, + copyright = conf[6]) + + # write the index.html file in the destination directory + try: + findex = open (os.path.join (conf[5], "index.html"), "w+") + findex.write (main_str) + findex.close () + except IOError, OSError: + return False + + # write the style.css file in the destination directory + try: + fstyle = open (os.path.join (conf[5], "style.css"), "w+") + fstyle.write (templates[5][1]) + fstyle.close () + print "error" + except IOError, OSError: + return False + + return True + +# superfunction to generate the site +def generate_site (dbname, files_to_copy, folders_to_copy, search_type_full=True): + # get the configuration + conf = biaweb_db.get_configuration (dbname) + # get the templates + tpls = biaweb_db.get_templates (dbname) + + # get the list of categories + cats = biaweb_db.get_categories (dbname) + # cannot get categories return false + if cats == False: + return False + + # format the categories as a html bulleted list + cats_str = html_format_categories (cats) + + # get the best rated articles + best_rated = biaweb_db.site_get_bestrated (dbname) + # if cannot retrieve + if best_rated == False: + return False + # format the best rated articles as a html bulleted list + best_rated_str = html_format_best_rated (best_rated) + + # remove the destination tree and recreate it + try: + if os.path.exists (conf[5]): + shutil.rmtree (conf[5]) + os.mkdir (conf[5]) + except OSError: + return False + + # generate the index page including style sheet + ret = generate_home_page (dbname, conf, tpls, cats_str, best_rated_str) + if ret == False: + return False + + # finally when all is successfully done return true + return True diff --git a/biaweb_strings.py b/biaweb_strings.py index 62d1f5e..da2a227 100644 --- a/biaweb_strings.py +++ b/biaweb_strings.py @@ -187,4 +187,24 @@ a:visited { } a:active, a:hover { color: #0000ff; -}""" \ No newline at end of file +}""" + +template_rss = """ + + + ${title} + ${link} + ${description} + BiaWeb + ${rss_items} + +""" + +template_rss_item = """ + + ${item_title} + ${item_link} + ${description} + ${item_link} + +""" \ No newline at end of file diff --git a/generate_dialog.py b/generate_dialog.py index d1882d2..dc0448b 100644 --- a/generate_dialog.py +++ b/generate_dialog.py @@ -5,6 +5,7 @@ import PyQt4 import os import os.path import ui_generate_dialog +import biaweb_exporter class GenerateDialog (PyQt4.QtGui.QDialog, ui_generate_dialog.Ui_SiteGenerateDialog): def __init__ (self, master, currentdb): @@ -38,6 +39,29 @@ class GenerateDialog (PyQt4.QtGui.QDialog, ui_generate_dialog.Ui_SiteGenerateDia def onSiteGenerate (self): files_list = self.get_list_from_tree (self.additional_files) folder_list = self.get_list_from_tree (self.additional_folders) + if self.fulltextindex.isChecked (): + searchtype = True + else: + searchtype = False + + # confirm whether to delete the destination tree and work afresh + ans = PyQt4.QtGui.QMessageBox.question (self, "Confirm", + "This will delete the destination tree completely \ +and recreate the website. Are you sure you wish to proceed?", + PyQt4.QtGui.QMessageBox.Yes, PyQt4.QtGui.QMessageBox.No) + + # if confirmed + if ans == PyQt4.QtGui.QMessageBox.Yes: + # call the main exporter to do our work + ret = biaweb_exporter.generate_site (self.current_db, files_list, folder_list, searchtype) + + # if failed to generate site or any part thereof + if ret == False: + PyQt4.QtGui.QMessageBox.critical (self, "Error", + "System or SQLite 3 error in generating website or parts thereof") + else: + PyQt4.QtGui.QMessageBox.information (self, "Success", + "Successfully generated website in destination path!") # when folder add is clicked def onFolderAdd (self): diff --git a/generate_dialog.ui b/generate_dialog.ui index ce8a88e..4544906 100644 --- a/generate_dialog.ui +++ b/generate_dialog.ui @@ -33,10 +33,10 @@ <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; color:#005500;">Important Information</span></p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This will generate your website in the destination directory specified in the site configuration dialog. The entire directory tree will be re-created from scratch and any manual changes you made to the generated files will be gone!</p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> -<p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">You need to re-copy additional files/folders you require in the destination folder (e.g. image files or directories) every time you generate the site. Specify additional files/folders to copy below.</span></p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; color:#55007f;">Important Information</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This will generate your website in the destination directory specified in the site configuration dialog. The entire directory tree will be re-created from scratch and any manual changes you made to the generated files will be gone!</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">You need to re-copy the additional files/folders you require in the destination folder (e.g. the rating (star) image files or directories, the search.py CGI script) every time you generate the site. Specify the files/folders to copy to generated site.</span></p></body></html> true diff --git a/main_window.py b/main_window.py index 02eaa8b..86e9b12 100644 --- a/main_window.py +++ b/main_window.py @@ -377,7 +377,7 @@ class MainWindow (PyQt4.QtGui.QMainWindow, ui_main_window.Ui_MainWindow): def onAbout (self): PyQt4.QtGui.QMessageBox.about (self, "BiaWeb Qt", "A static website/weblog content management system

\ -Copyright (C) 2010 Harishankar
\ +Copyright © 2010 Harishankar
\ Licensed under GNU/GPL v3") # file quit is clicked diff --git a/ui_generate_dialog.py b/ui_generate_dialog.py index c81bb6f..fab5abf 100644 --- a/ui_generate_dialog.py +++ b/ui_generate_dialog.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'generate_dialog.ui' # -# Created: Tue Nov 30 12:38:46 2010 +# Created: Tue Nov 30 14:05:23 2010 # by: PyQt4 UI code generator 4.7.4 # # WARNING! All changes made in this file will be lost! @@ -105,10 +105,10 @@ class Ui_SiteGenerateDialog(object): "\n" -"

Important Information

\n" -"

This will generate your website in the destination directory specified in the site configuration dialog. The entire directory tree will be re-created from scratch and any manual changes you made to the generated files will be gone!

\n" -"

\n" -"

You need to re-copy additional files/folders you require in the destination folder (e.g. image files or directories) every time you generate the site. Specify additional files/folders to copy below.

", None, QtGui.QApplication.UnicodeUTF8)) +"

Important Information

\n" +"

This will generate your website in the destination directory specified in the site configuration dialog. The entire directory tree will be re-created from scratch and any manual changes you made to the generated files will be gone!

\n" +"

\n" +"

You need to re-copy the additional files/folders you require in the destination folder (e.g. the rating (star) image files or directories, the search.py CGI script) every time you generate the site. Specify the files/folders to copy to generated site.

", None, QtGui.QApplication.UnicodeUTF8)) self.label_2.setText(QtGui.QApplication.translate("SiteGenerateDialog", "Additional files to add to destination", None, QtGui.QApplication.UnicodeUTF8)) self.addfile.setText(QtGui.QApplication.translate("SiteGenerateDialog", "&Add file", None, QtGui.QApplication.UnicodeUTF8)) self.removefile.setText(QtGui.QApplication.translate("SiteGenerateDialog", "&Remove", None, QtGui.QApplication.UnicodeUTF8)) diff --git a/ui_main_window.py b/ui_main_window.py index e7b4bfb..fbc36c5 100644 --- a/ui_main_window.py +++ b/ui_main_window.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'main_window.ui' # -# Created: Tue Nov 30 13:15:20 2010 +# Created: Tue Nov 30 13:50:40 2010 # by: PyQt4 UI code generator 4.7.4 # # WARNING! All changes made in this file will be lost! -- 2.20.1