kindle manager

This commit is contained in:
douboer
2020-06-30 12:06:47 +08:00
36 changed files with 22841 additions and 27699 deletions

View File

@@ -9,11 +9,17 @@
import sys
import os
import operator
from time import sleep
import pandas as pd
#import pandas as pd
from mtable import mTable
import threading
from PySide2.QtWidgets import (QMainWindow, QApplication, QLabel, QAbstractItemView, QHeaderView)
#if hasattr(sys, 'frozen'):
# os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH']
from PySide2.QtWidgets import (QMainWindow, QApplication, QMessageBox,
QFileDialog, QLabel, QAbstractItemView, QHeaderView, QMenu)
from PySide2.QtCore import (QAbstractTableModel, Signal, QSize, QTimer, Qt)
from PySide2.QtGui import (QPalette, QStandardItemModel, QStandardItem, QIcon)
@@ -60,6 +66,7 @@ words_temp = """<br><span style='font-size:18pt;color:#31849B'>{usage}</span><br
ONLY_TEST = 1
class kmanWindow(QMainWindow):
"""
def __init__(self, *args, **kwargs):
super(kmanWindow, self).__init__(*args, **kwargs)
@@ -68,6 +75,8 @@ class kmanWindow(QMainWindow):
def __init__(self, parent=None):
super(kmanWindow, self).__init__(parent)
self.copyinfo = ''
# create ui and initial it
ui = Ui_MainWindow()
ui.setupUi(self)
@@ -81,6 +90,13 @@ class kmanWindow(QMainWindow):
self.km = kMan()
self.spide = bookInfoSpide()
<<<<<<< HEAD
=======
### in order to smaller the package,
### substitute pandas table with mTable
self.mt = mTable()
>>>>>>> 2d53124ab9aa26c9733646348174311d0967c8c0
self.books_info = defaultdict(dict)
# initial check order:
# 1. backup file bk.data ->
@@ -90,9 +106,8 @@ class kmanWindow(QMainWindow):
if os.path.exists(BACKUPNOTEFN) and os.path.exists(BACKUPWORDFN):
self.books_data = self.km.json2dict(BACKUPNOTEFN)
self.words_data = self.km.json2dict(BACKUPWORDFN)
if (len(self.books_data)*len(self.words_data[0]))>=1:
self.books_data = self.km.json2dict(BACKUPNOTEFN)
self.words_data = self.km.json2dict(BACKUPWORDFN)
if self.books_data and len(self.books_data) >=1 and \
self.words_data and len(self.words_data[0])>=1:
flg = 1
if not flg:
@@ -114,7 +129,10 @@ class kmanWindow(QMainWindow):
# if the information exist in backup file, initial with this file,
# and grap new book's information from douban
# else grap all book information from douban
<<<<<<< HEAD
"""
=======
>>>>>>> 2d53124ab9aa26c9733646348174311d0967c8c0
try:
if os.path.exists(BACKUPINFOFN):
self.books_info = self.km.json2dict(BACKUPINFOFN)
@@ -155,7 +173,8 @@ class kmanWindow(QMainWindow):
#ui.searchLineEdit.returnPressed.connect(self.search_return_press())
ui.searchComboBox.currentIndexChanged.connect(self.search_scope_change)
ui.searchToolButton.clicked.connect(self.search_button_clicked)
ui.treeView.clicked.connect(self.tree_item_clicked)
#ui.treeView.clicked.connect(self.tree_item_clicked)
ui.treeView.selectionModel().selectionChanged.connect(self.tree_item_selectionchanged)
ui.tableView.clicked.connect(self.table_item_clicked)
ui.tableView.horizontalHeader().setStretchLastSection(True)
#ui.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
@@ -170,7 +189,11 @@ class kmanWindow(QMainWindow):
ui.tablemodel = nTableModel(data)
ui.tableView.verticalHeader().hide()
ui.tableView.setModel(self.ui.tablemodel)
ui.tableView.setSortingEnabled(True)
ui.tableView.selectionModel().selectionChanged.connect(self.table_item_selectionchanged)
#ui.tableView.contextMenuEvent().selectionChanged.connect(self.table_item_selectionchanged)
# XXXX
self.ui.textEdit.installEventFilter(self)
# XXXX
@@ -190,21 +213,6 @@ class kmanWindow(QMainWindow):
else:
super(kmanWindow, self).eventFilter(source, event)
"""
app = QApplication(sys.argv)
editor = MyWidget()
cursor = editor.textCursor()
fmt = cursor.charFormat()
fmt.setForeground(QColor('blue'))
address = 'http://example.com'
fmt.setAnchor(True)
fmt.setAnchorHref(address)
fmt.setToolTip(address)
cursor.insertText("Hello world again", fmt)
editor.show()
app.exec_()
"""
def check_increase_books(self, bks, bksinfo):
new_list = list(bks.keys()) # kindle's books with note
new_list = [re.split(r'[\(\-\:_\s]',nn.strip())[0] for nn in new_list]
@@ -252,6 +260,7 @@ class kmanWindow(QMainWindow):
self.ui.tableView.verticalHeader().hide()
self.ui.tableView.setModel(self.ui.tablemodel)
#self.ui.tablemodel.tabledata_update.connect(self.tabledata_update_slot)
self.ui.tableView.selectionModel().selectionChanged.connect(self.table_item_selectionchanged)
# refresh textedit content
if comp in [1,2]:
@@ -261,6 +270,11 @@ class kmanWindow(QMainWindow):
note=stype, content=scontent, position=sposition)
print(re.split(r'[\(\-\:_\s]',sbookname.strip())[0])
self.ui.textEdit.setHtml(tt)
self.copyinfo = \
""" {content} \n\n--《{bookname}{author} ({time}) 【{note} P{position}""". \
format( content=scontent, bookname=sbookname, author=sauthor, time=stime,
note=stype, position=sposition )
elif comp in [3,4]:
self.render_textedit_words(self.words_data)
elif comp == 5:
@@ -278,6 +292,7 @@ class kmanWindow(QMainWindow):
word = index.sibling(index.row(), 0).data()
txt = ""
self.copyinfo = ''
for row in lookups:
if words[row[1]]['word'] == word:
[susage, stimestamp, sbookname, sauthor, scategory, sposition] = \
@@ -289,6 +304,12 @@ class kmanWindow(QMainWindow):
author=sauthor,category=scategory,
timestamp=stimestamp,position=sposition)
self.copyinfo += \
"""{usage} \n\n-- {bookname} {author} {category} {timestamp} {position} \n """ \
.format( usage=susage,bookname=sbookname, \
author=sauthor,category=scategory, \
timestamp=stimestamp,position=sposition)
self.ui.textEdit.setHtml(txt)
'''
@@ -317,30 +338,58 @@ class kmanWindow(QMainWindow):
self.ui.textEdit.setOpenExternalLinks(True)
self.ui.textEdit.setHtml(infos_temp.format(link=vv['link'],
bookname=vv['bookname'],
author=vv['author'], ratenum=vv['ratenum'],
score=vv['score'], publisher=vv['publisher'],
publishing=vv['publishing'],description=vv['description'],
author=vv['author'],
ratenum=vv['ratenum'],
score=vv['score'],
publisher=vv['publisher'],
publishing=vv['publishing'],
description=vv['description'],
img=vv['img'].split('/')[-1]))
self.copyinfo = """ 1 | :green_book: | [{bookname}]({link}) | """ \
"""{author}/{score}/{publisher}/{publishing} {description}""" \
.format( bookname=vv['bookname'], \
link=vv['link'],
author=vv['author'],
score=vv['score'],
publisher=vv['publisher'],
publishing=vv['publishing'],
description=vv['description'],)
else: pass
def convert_to_panda(self, mlist, tp=0):
if tp==0:
pdframe = pd.DataFrame(mlist, \
#### XXX remove pandas
#pdframe = pd.DataFrame(mlist, \
# columns = ['Type','Bookname','Author','Position','Date','Content'])
self.mt.dataframe(mlist, \
columns = ['Type','Bookname','Author','Position','Date','Content'])
else:
pdframe = pd.DataFrame(mlist, \
#pdframe = pd.DataFrame(mlist, \
# columns = ['Word','Bookname','Author','Category'])
self.mt.dataframe(mlist, \
columns = ['Word','Bookname','Author','Category'])
return pdframe
return self.mt
def tabledata_update_slot(self, s):
print('call tabledata_update_slot() {}'.format(s))
def tree_item_selectionchanged(self, selected, deselected):
# selected, deselected are QItemSelection objects
model_index_list = selected.indexes() # QModelIndexList
if not model_index_list: return 0
model_index = model_index_list[0] # QModelIndex
self.tree_item_clicked(model_index)
def tree_item_clicked(self, modelidx):
# modelidx is a QModelIndex object
model_index_list = self.ui.treeView.selectedIndexes() # QModelIndexList
model_index = model_index_list[0] # QModelIndex
itemmodel = model_index.model() #QAbstractItemModel/QStandardItemModel
item = itemmodel.itemFromIndex(modelidx) #QStandardItem
item = itemmodel.itemFromIndex(model_index) #QStandardItem
self.tree_selected = item.accessibleDescription()
print(self.tree_selected, item.text())
@@ -351,6 +400,7 @@ class kmanWindow(QMainWindow):
comp = 0
if self.tree_selected.split('_')[0] == 'info':
self.ui.tableView.setVisible(False)
self.ui.tableView.clearSelection()
self.render_textedit_infos(self.books_info, item.text())
comp = 5
else:
@@ -389,6 +439,13 @@ class kmanWindow(QMainWindow):
self.refresh_ui_component(comp)
def table_item_selectionchanged(self, selected, deselected):
# selected, deselected are QItemSelection objects
model_index_list = selected.indexes() # QModelIndexList
if not model_index_list: return 0
model_index = model_index_list[0] # QModelIndex
self.table_item_clicked(model_index)
def table_item_clicked(self, index):
"""
print('tableView.currentIndex().row() {} tableView.currentIndex().column() {}'
@@ -410,7 +467,11 @@ class kmanWindow(QMainWindow):
self.ui.textEdit.setHtml(notes_temp.format(
bookname=sbookname, author=sauthor, time=stime,
note=stype, content=scontent, position=sposition))
elif ss=='note':
self.copyinfo = \
""" {content} \n\n-- 《{bookname}{author} ({time}) 【{note} P{position}""". \
format( content=scontent, bookname=sbookname, author=sauthor, time=stime,
note=stype, position=sposition )
elif ss=='word':
self.render_textedit_words(self.words_data)
def search_button_clicked(self):
@@ -434,6 +495,58 @@ class kmanWindow(QMainWindow):
print('call keyPressEvent() {} '.format(event.key()))
self.search_button_clicked()
def contextMenuEvent(self, event):
# do not work!?
#if(self.ui.tableView.geometry().contains(event.pos())):
# print('contextMenuEvent pos {}'.format(event.globalPos()))
tree_index_list = self.ui.treeView.selectedIndexes() # QModelIndexList
table_index_list = self.ui.tableView.selectedIndexes()
# tableview item selected
if table_index_list:
model_index = table_index_list[0] # QModelIndex
menu = QMenu()
copy_action = menu.addAction(u"Copy")
action = menu.exec_(self.mapToGlobal(event.pos()))
if action ==copy_action:
self.copy_action(model_index.row(), model_index.column())
elif tree_index_list:
model_index = tree_index_list[0] # QModelIndex
itemmodel = model_index.model() #QAbstractItemModel/QStandardItemModel
item = itemmodel.itemFromIndex(model_index) #QStandardItem
pp = self.tree_selected.split('_')[0]
menu = QMenu()
[copy_info_action, export_note_action, export_word_action] = \
[None, None, None]
if pp=='info':
copy_info_action = menu.addAction(u"Copy")
elif pp=='note':
export_note_action = menu.addAction(u"Export Notes")
elif pp=='word':
export_word_action = menu.addAction(u"Export Notes")
else: pass
action = menu.exec_(self.mapToGlobal(event.pos()))
fn = self.tree_selected+item.text().split('(')[0].strip()
if action==copy_info_action:
action = menu.exec_(self.mapToGlobal(event.pos()))
self.copy_action(model_index.row(), model_index.column())
elif action==export_note_action: self.export_filter_notes(fn)
elif action==export_word_action: self.export_filter_words(fn)
else: pass
else: pass
print('contextMenuEvent pos {}'.format(event.globalPos()))
def copy_action(self, row, column):
import clipboard
clipboard.copy(self.copyinfo)
print('copy_action row {} column {}'.format(row, column))
def search_return_press(self):
self.search_button_clicked()
@@ -478,8 +591,8 @@ class kmanWindow(QMainWindow):
self.messagebox(ico=2, info='\n\n kindle is not connected')
return 0
self.books_data = self.km.import_clips(fp+'documents/'+CLIPFN)
self.words_data = self.km.import_words(fp+'system/vocabulary/'+WORDFN)
self.books_data = self.km.import_clips(os.path.join(fp,'documents',CLIPFN))
self.words_data = self.km.import_words(os.path.join(fp,'system','vocabulary',WORDFN))
[self.filter_books, self.filter_list] = self.km.filter_clips(self.books_data)
self.filter_wordlist = self.km.filter_words(self.words_data)
@@ -649,18 +762,22 @@ class kmanWindow(QMainWindow):
pass
def export(self):
if self.tree_selected.split('_')[0]=='note':
self.export_filter_notes()
else:
self.export_filter_words()
pp = self.tree_selected.split('_')[0]
if pp=='note':
self.export_filter_notes('export')
elif pp=='word':
self.export_filter_words('export')
else: # info
pass
print("call export()")
def export_filter_notes(self):
self.km.export_notes(self.filter_books, 'export', ft='MD')
def export_filter_notes(self, fn):
self.km.export_notes(self.filter_books, fn, ft='MD')
pass
def export_filter_words(self):
self.km.export_words(self.words_data, self.filter_list, 'export', ft='MD')
def export_filter_words(self, fn):
self.km.export_words(self.words_data, self.filter_list, fn, ft='MD')
pass
def messagebox(self, ico=1, info=''):
@@ -687,6 +804,8 @@ class kmanWindow(QMainWindow):
# backup file when kman closed
# so we can read backup file when kman start
def closeEvent(self, e):
if not os.path.exists(BACKUPFOLDER): os.mkdir(BACKUPFOLDER)
with open(BACKUPNOTEFN, 'w', encoding='utf8', errors='ignore') as fw:
fw.write(self.km.dict2json(self.books_data))
with open(BACKUPWORDFN, 'w', encoding='utf8', errors='ignore') as fw:
@@ -749,24 +868,46 @@ class nTableModel(QAbstractTableModel):
def data(self, index, role):
if role == Qt.DisplayRole:
value = self._data.iloc[index.row(), index.column()]
#### XXX remove pandas
#value = self._data.iloc[index.row(), index.column()]
value = self._data.get_iat(index.row(), index.column())
self.tabledata_update[str].emit('{} {}'.format(index.row(),index.column()))
return str(value)
def rowCount(self, index):
return self._data.shape[0]
#### XXX remove pandas
#return self._data.shape[1]
return self._data.get_num_rows()
def columnCount(self, index):
return self._data.shape[1]
#### XXX remove pandas
#return self._data.shape[1]
return self._data.get_num_columns()
def headerData(self, section, orientation, role):
# section is the index of the column/row.
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal:
return str(self._data.columns[section])
#### XXX remove pandas
#return str(self._data.columns[section])
return str(self._data.get_columns()[section])
if orientation == Qt.Vertical:
return str(self._data.index[section])
#### XXX remove pandas
#return str(self._data.index[section])
return str(self._data.get_index()[section])
# cheer!!!
def sort(self, column, order):
"""Sort table by given column number.
"""
self.layoutAboutToBeChanged.emit()
self._data.set_data(sorted(self._data.get_data(), key=operator.itemgetter(column)))
if order == Qt.DescendingOrder:
self._data.reverse()
self.layoutChanged.emit()
if __name__ == "__main__":
@@ -795,7 +936,7 @@ if __name__ == "__main__":
"""
# loop check kindle is connected or not
# BUG to be implement XXXX
# BUG, to be implement XXXX
"""
try:
t = threading.Thread(target=kmw.check_kindle_status)
@@ -804,4 +945,5 @@ if __name__ == "__main__":
print ("Error: can not start thread")
"""
app.exec_()
#sys.exit(app.exec_())