kindle manager

This commit is contained in:
gavin
2020-06-07 17:48:28 +08:00
parent 76cc0d8c6d
commit 32d9f53897
7 changed files with 324 additions and 63 deletions

8
1.htm Normal file
View File

@@ -0,0 +1,8 @@
<html>
<span style='font-size:22pt;color:maroon'><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD></span>
<span style='font-size:22pt;color:maroon'><EFBFBD><EFBFBD><EFBFBD><EFBFBD></span>
<span style='font-size:22pt;color:maroon'>ʱ<EFBFBD><EFBFBD></span>
<span style='font-size:11pt;color:maroon'><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD></span><br>
<span>********************************************************</span><br>
<span style='font-size:11.0pt;color:#31849B'><EFBFBD><EFBFBD><EFBFBD>ݷ缱<EFBFBD>˴󼡷<EFBFBD><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD>ϴ<EFBFBD><EFBFBD>Ͽξͷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʴ<EFBFBD><EFBFBD><EFBFBD></span><span style='font-size:14pt;color:maroon'><EFBFBD><EFBFBD>P123-126<32><36></span><br>
</html>

12
kman.py
View File

@@ -70,6 +70,7 @@ DEBUG = 1 # 0 - INFO; 1 - DEBUG
LOG2FILE = 1 # 0 - to stdio; 1 - to file LOG2FILE = 1 # 0 - to stdio; 1 - to file
LOGFILE = 'log' LOGFILE = 'log'
DELIMITER= '|' DELIMITER= '|'
#HEADER = {0:'type',1:'bookname',2:'author',3:'position',4:'date',5:'content'}
# log info # log info
logger = logging.getLogger() logger = logging.getLogger()
@@ -357,9 +358,13 @@ class kMan:
bks: books dict bks: books dict
info: filter by bookname or author information info: filter by bookname or author information
tp: type to be filter tp: type to be filter
0: top/root item clicked 0: root item clicked
1: bookname item clicked 1: bookname item clicked
2: author item clicked 2: author item clicked
Return: list:
[[Type,Bookname,Author,Position,Date,content],
[Type,Bookname,Author,Position,Date,content]
....]
""" """
nbks = defaultdict(dict) nbks = defaultdict(dict)
@@ -378,9 +383,10 @@ class kMan:
if ks in ['author', 'lines']: continue if ks in ['author', 'lines']: continue
tm = self.format_time(' '.join([vs['day'],vs['week'], \ tm = self.format_time(' '.join([vs['day'],vs['week'], \
vs['meridiem'],vs['time']])) vs['meridiem'],vs['time']]))
tp = '标注' if vs['type']=='HL' else '笔记' nttype = '标注' if vs['type']=='HL' else '笔记'
seclist.append((vs['content'],tp,kb,vb['author'],vs['position'],tm)) seclist.append([nttype,kb,vb['author'],vs['position'],tm,vs['content']])
idx += 1 idx += 1
return seclist return seclist
def add_note_to_highlight(self,bks): def add_note_to_highlight(self,bks):

View File

@@ -1,12 +1,17 @@
#########################################################
## @file : kmanapp.py
## @desc : kindle note managerment tool GUI
## @create : 2020/06/03
## @author : Chengan
## @email : douboer@gmail.com
#########################################################
import sys import sys
from time import sleep from time import sleep
import pandas as pd
from PySide2.QtWidgets import QApplication from PySide2.QtWidgets import *
from PySide2.QtWidgets import QMainWindow
from PySide2.QtWidgets import QLabel
from PySide2.QtWidgets import QMessageBox
from PySide2.QtWidgets import QFileDialog
from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject, from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
QAbstractTableModel, QObject, QPoint, QRect, QSize, QTime, QAbstractTableModel, QObject, QPoint, QRect, QSize, QTime,
@@ -14,7 +19,6 @@ from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter, QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
QPixmap, QRadialGradient, QStandardItem, QStandardItemModel) QPixmap, QRadialGradient, QStandardItem, QStandardItemModel)
#from PySide2.QtWidgets import *
from mainwindow import Ui_MainWindow from mainwindow import Ui_MainWindow
from kman import * from kman import *
@@ -40,6 +44,7 @@ class kmanWindow(QMainWindow):
self.km = kMan() self.km = kMan()
self.books = self.km.import_clips() self.books = self.km.import_clips()
self.filter_data = self.km.filter_clips(self.books)
self.add_ui_component() self.add_ui_component()
@@ -65,26 +70,41 @@ class kmanWindow(QMainWindow):
ui.searchToolButton.clicked.connect(self.search_button_clicked) 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.tableView.clicked.connect(self.table_item_clicked) ui.tableView.clicked.connect(self.table_item_clicked)
ui.tableView.setColumnWidth(0, 40) # type
ui.tableView.setColumnWidth(2, 50) # author
ui.tableView.selectRow(0)
def add_ui_component(self): def add_ui_component(self):
self.ui.searchComboBox.addItems(['ALL','bookname','content','author']) self.ui.searchComboBox.addItems(['ALL','bookname','content','author'])
self.ui.treeView.resize(200,200)
# status bar # status bar
self.ui.status_label = QLabel() self.ui.status_label = QLabel()
self.ui.pe = QPalette() self.ui.pe = QPalette()
# table # table view
#self.ui.tablemodel=QStandardItemModel(100,5) self.ui.tablemodel = nTableModel(self.convert_to_panda(self.filter_data))
self.ui.tablemodel= nTableModel(100,5)
self.ui.tablemodel.setHorizontalHeaderLabels(
[u'Content',u'Type',u'Bookname',u'Author',u'Position',u'Date'])
self.ui.tablemodel.update(self.km.filter_clips(self.books))
self.ui.tableView.verticalHeader().hide() self.ui.tableView.verticalHeader().hide()
for row in range(5):
for column in range(5):
i=QStandardItem("row %s,column %s"%(row,column))
self.ui.tablemodel.setItem(row,column,i)
self.ui.tableView.setModel(self.ui.tablemodel) self.ui.tableView.setModel(self.ui.tablemodel)
self.ui.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
# fit window
#headerView = self.ui.tableView.horizontalHeader()
#headerView.setSectionResizeMode(QHeaderView.Stretch)
self.ui.tableView.horizontalHeader().setStretchLastSection(True)
self.ui.tablemodel.tabledata_update.connect(self.tabledata_update_slot)
# initial textedit content
[stype,sbookname,sauthor,sposition,stime,scontent] = self.filter_data[0]
self.ui.textEdit.setHtml("""<span style='font-size:22pt;color:maroon'>《{bookname}》</span>
<span style='font-size:22pt;color:maroon'>{author}</span>
<span style='font-size:22pt;color:maroon'>{time}</span>
<span style='font-size:11pt;color:maroon'>【{note}】</span><br><br>
<span>********************************************************</span><br><br>
<span style='font-size:22pt;color:#31849B'>{content}</span>
<span style='font-size:11pt;color:maroon'>【P{position}】</span><br>""".
format(bookname=sbookname, author=sauthor, time=stime,
note=stype, content=scontent, position=sposition))
""" """
if not ONLY_TEST: # XXXXXXXXXXXXX if not ONLY_TEST: # XXXXXXXXXXXXX
@@ -129,22 +149,60 @@ class kmanWindow(QMainWindow):
self.ui.treeView.setModel(model) self.ui.treeView.setModel(model)
""" """
def convert_to_panda(self, seclist):
pdframe = pd.DataFrame(seclist, \
columns = ['Type','Bookname','Author','Position','Date','Content'])
return pdframe
def tabledata_update_slot(self, s):
print('call tabledata_update_slot() {}'.format(s))
def tree_item_clicked(self, modelidx): def tree_item_clicked(self, modelidx):
model_index_list = self.ui.treeView.selectedIndexes() # QModelIndexList model_index_list = self.ui.treeView.selectedIndexes() # QModelIndexList
model_index = model_index_list[0] # QModelIndex model_index = model_index_list[0] # QModelIndex
itemmodel = model_index.model() #QAbstractItemModel/QStandardItemModel itemmodel = model_index.model() #QAbstractItemModel/QStandardItemModel
item = itemmodel.itemFromIndex(modelidx) #QStandardItem item = itemmodel.itemFromIndex(modelidx) #QStandardItem
print(item.text()) description = item.accessibleDescription()
print(description, item.text())
# filter clips # filter clips
self.filter_data = None
if description in ['root', 'bookname', 'author']:
self.filter_data = self.km.filter_clips(self.books)
elif description == 'bleaf': # bookname leaf
info = re.split(r'\s+',item.text())[0]
self.filter_data = self.km.filter_clips(self.books, info, 1)
else: # author leaf
info = re.split(r'\s+',item.text())[0]
self.filter_data = self.km.filter_clips(self.books, info, 2)
#item = self.ui.treeView.selectedIndexes()[0] data = self.convert_to_panda(self.filter_data)
#print(item.model().itemFromIndex(modelidx).text()) self.ui.tablemodel= nTableModel(data)
self.ui.tableView.verticalHeader().hide()
self.ui.tableView.setModel(self.ui.tablemodel)
def table_item_clicked(self, item): def table_item_clicked(self, index):
content = item.data() if index.isValid():
#print('call table_item_clicked() {}'.format(content)) row = index.row()
stype = index.sibling(row, 0).data()
sbookname = index.sibling(row, 1).data()
sauthor = index.sibling(row, 2).data()
sposition = index.sibling(row, 3).data()
stime = index.sibling(row, 4).data()
scontent = index.sibling(row, 5).data()
else: return
self.ui.textEdit.setHtml("""<span style='font-size:22pt;color:maroon'>《{bookname}》</span>
<span style='font-size:22pt;color:maroon'>{author}</span>
<span style='font-size:22pt;color:maroon'>{time}</span>
<span style='font-size:11pt;color:maroon'>【{note}】</span><br><br>
<span>********************************************************</span><br><br>
<span style='font-size:22pt;color:#31849B'>{content}</span>
<span style='font-size:11pt;color:maroon'>【P{position}】</span><br>""".
format(bookname=sbookname, author=sauthor, time=stime,
note=stype, content=scontent, position=sposition))
def search_button_clicked(self): def search_button_clicked(self):
print( 'call search_button_clicked()' ) print( 'call search_button_clicked()' )
@@ -213,7 +271,7 @@ class kmanWindow(QMainWindow):
icon = QIcon() icon = QIcon()
icon.addFile(u":/icons/emblem_library.png", QSize(), QIcon.Normal, QIcon.Off) icon.addFile(u":/icons/emblem_library.png", QSize(), QIcon.Normal, QIcon.Off)
item.setIcon(icon) item.setIcon(icon)
item.setAccessibleDescription('top') item.setAccessibleDescription('root')
rootItem.appendRow(item) rootItem.appendRow(item)
parent_item = item parent_item = item
@@ -223,7 +281,7 @@ class kmanWindow(QMainWindow):
icon = QIcon() icon = QIcon()
icon.addFile(u":/icons/book_open.png", QSize(), QIcon.Normal, QIcon.Off) icon.addFile(u":/icons/book_open.png", QSize(), QIcon.Normal, QIcon.Off)
bookname_item.setIcon(icon) bookname_item.setIcon(icon)
bookname_item.setAccessibleDescription('root') bookname_item.setAccessibleDescription('bookname')
parent_item.appendRow(bookname_item) parent_item.appendRow(bookname_item)
if totalnum > 0: if totalnum > 0:
@@ -232,7 +290,7 @@ class kmanWindow(QMainWindow):
icon = QIcon() icon = QIcon()
icon.addFile(u":/icons/book_open_bookmark.png", QSize(), QIcon.Normal, QIcon.Off) icon.addFile(u":/icons/book_open_bookmark.png", QSize(), QIcon.Normal, QIcon.Off)
item.setIcon(icon) item.setIcon(icon)
item.setAccessibleDescription('leaf') item.setAccessibleDescription('bleaf')
bookname_item.appendRow(item) bookname_item.appendRow(item)
# add author tree # add author tree
@@ -241,7 +299,7 @@ class kmanWindow(QMainWindow):
icon = QIcon() icon = QIcon()
icon.addFile(u":/icons/person.png", QSize(), QIcon.Normal, QIcon.Off) icon.addFile(u":/icons/person.png", QSize(), QIcon.Normal, QIcon.Off)
author_item.setIcon(icon) author_item.setIcon(icon)
author_item.setAccessibleDescription('root') author_item.setAccessibleDescription('author')
parent_item.appendRow(author_item) parent_item.appendRow(author_item)
parent_item = author_item parent_item = author_item
@@ -251,7 +309,7 @@ class kmanWindow(QMainWindow):
icon = QIcon() icon = QIcon()
icon.addFile(u":/icons/user.png", QSize(), QIcon.Normal, QIcon.Off) icon.addFile(u":/icons/user.png", QSize(), QIcon.Normal, QIcon.Off)
item.setIcon(icon) item.setIcon(icon)
item.setAccessibleDescription('leaf') item.setAccessibleDescription('aleaf')
author_item.appendRow(item) author_item.appendRow(item)
self.ui.treeView.setModel(self.ui.model) self.ui.treeView.setModel(self.ui.model)
@@ -313,46 +371,42 @@ class kmanWindow(QMainWindow):
# stop check thread # stop check thread
self.flag = False self.flag = False
## thanks 勤奋的小青蛙 ^_^ - http://www.jyguagua.com/?p=2615 # thanks Martin Fitzpatrick ^_^
#class nTableModel(QAbstractTableModel): # https://www.learnpyqt.com/courses/model-views/qtableview-modelviews-numpy-pandas/
class nTableModel(QStandardItemModel): class nTableModel(QAbstractTableModel):
def __init__(self, parent=None, seclist=None, *args): tabledata_update = Signal(str)
def __init__(self, data):
super(nTableModel, self).__init__() super(nTableModel, self).__init__()
self.seclist = None self._data = data
def update(self, seclist):
self.seclist = seclist
def rowCount(self, parent):
if not self.seclist: return 0
return len(self.seclist)
def columnCount(self, parent):
if not self.seclist: return 0
return len(self.seclist[0])
def data(self, index, role): def data(self, index, role):
if not index.isValid(): if role == Qt.DisplayRole:
return None value = self._data.iloc[index.row(), index.column()]
elif role != Qt.DisplayRole: self.tabledata_update[str].emit('{} {}'.format(index.row(),index.column()))
return None return str(value)
return self.seclist[index.row()][index.column()]
def sort(self, col, order):
"""sort table by given column number col"""
self.emit(SIGNAL("layoutAboutToBeChanged()"))
self.seclist = sorted(self.seclist, key=operator.itemgetter(col)) def rowCount(self, index):
if order == Qt.DescendingOrder: return self._data.shape[0]
self.seclist.reverse()
def columnCount(self, index):
return self._data.shape[1]
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])
if orientation == Qt.Vertical:
return str(self._data.index[section])
self.emit(SIGNAL("layoutChanged()"))
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)
kmw = kmanWindow() kmw = kmanWindow()
kmw.resize(900, 600) #kmw.resize(900, 600)
kmw.showFullScreen()
kmw.show() kmw.show()
# loop check kindle is connected or not # loop check kindle is connected or not
@@ -364,6 +418,5 @@ if __name__ == "__main__":
except: except:
print ("Error: can not start thread") print ("Error: can not start thread")
""" """
app.exec_() app.exec_()

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.2, 2020-06-06T20:00:44. --> <!-- Written by QtCreator 4.11.2, 2020-06-07T15:50:36. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>

81
tdataframe.py Normal file
View File

@@ -0,0 +1,81 @@
import pandas as pd
from kman import *
data = {
'state':['Ohio','Ohio','Ohio','Nevada','Nevada'],
'year':[2000,2001,2002,2001,2002],
'pop':[1.5,1.7,3.6,2.4,2.9],
'xx':[1.5,1.7,3.6,2.4,2.9]
}
"""
year state pop debt
one 2000 Ohio 1.5 16.5
two 2001 Ohio 1.7 16.5
three 2002 Ohio 3.6 16.5
four 2001 Nevada 2.4 16.5
five 2002 Nevada 2.9 16.5
"""
frame = pd.DataFrame(data,
index = ['one', 'two','three','four','five'],
columns = ['year','state','pop','debt','xx'])
print(frame.iat[0, 0])
print(frame.iat[1, 1])
print(frame.iat[2, 2])
print(frame.iat[2, 1])
'''
print('\n---------------------')
print(frame)
print('\n---------------------')
frame['debt']=16.5
print(frame)
print('\n---------------------')
print(frame.iloc[2]) #line 2
print('\n---------------------')
print(frame.iloc[[2,3],0:2])
print('\n---------------------')
print(frame.iloc[[2,3],0:2])
print('\n---------------------')
print(frame.iat[1, 1])
print('\n---------------------')
for index, row in frame.iterrows():
print(index)
print(row)
print('\n---------------------')
for row in frame.iterrows():
print(row)
#print(row[0], row[1])
print('\n---------------------')
print(frame.head(2))
print('\n---------------------')
print(frame.columns)
print('\n---------------------')
print(frame.index)
print('\n---------------------')
print(frame.to_dict())
print('\n---------------------')
'''
km = kMan()
books = km.import_clips()
print(books)
print('\n---------------------')
frame = pd.DataFrame(books)
print(frame)
print('\n---------------------')
data = [['Ohio','Ohio','Ohio','Nevada','Nevada'],
[2000,2001,2002,2001,2002],
[1.5,1.7,3.6,2.4,2.9],
[1.5,1.7,3.6,2.4,2.9],
[1.5,1.7,3.6,2.4,2.9],
]
frame = pd.DataFrame(data,
columns = ['year','state','pop','debt','xx'])
print(frame)

88
tqtableview.py Normal file
View File

@@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
"""
@author: Taar
"""
#conversion of https://github.com/openwebos/qt/tree/master/examples/tutorials/modelview/5_edit
#I work with ints for values instead of strings (less cumbersome to add)
import sys
import pandas as pd
from PySide2.QtWidgets import *
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
QPixmap, QRadialGradient, QStandardItem, QStandardItemModel)
from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
QAbstractTableModel, QObject, QPoint, QRect, QSize, QTime,
QUrl, Qt, QThread, Signal, QTimer)
class TableModel(QAbstractTableModel):
def __init__(self, data):
super(TableModel, self).__init__()
self._data = data
def data(self, index, role):
if role == Qt.DisplayRole:
value = self._data.iloc[index.row(), index.column()]
return str(value)
def rowCount(self, index):
return self._data.shape[0]
def columnCount(self, index):
return self._data.shape[1]
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])
if orientation == Qt.Vertical:
return str(self._data.index[section])
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.table = QTableView()
data = pd.DataFrame([
[1, 9, 2],
[1, 0, -1],
[3, 5, 2],
[3, 3, 2],
[5, 8, 9],
],
columns = ['A', 'B', 'C'],
index=['Row 1', 'Row 2', 'Row 3', 'Row 4', 'Row 5'])
self.model = TableModel(data)
self.table.setModel(self.model)
data = pd.DataFrame([
[1, 5, 5, 9],
[1, 5, 5, 9],
[1, 2, 1, 3],
[1, 1, 0, -1],
[1, 5, 5, 2],
[1, 5, 5, 8],
[1, 5, 5, 9],
],
columns = ['Aa', 'Bb', 'Cc', 'dd'],
index=['Row 1', 'Row 3', 'Row 4', 'Row 4', 'Row 5', '6', '7'])
self.model = TableModel(data)
self.table.setModel(self.model)
self.setCentralWidget(self.table)
if __name__ == '__main__':
app=QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec_()

25
x Normal file
View File

@@ -0,0 +1,25 @@
class TableModel(QAbstractTableModel):
def __init__(self, data):
super(TableModel, self).__init__()
self._data = data
def data(self, index, role):
if role == Qt.DisplayRole:
value = self._data.iloc[index.row(), index.column()]
return str(value)
def rowCount(self, index):
return self._data.shape[0]
def columnCount(self, index):
return self._data.shape[1]
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])
if orientation == Qt.Vertical:
return str(self._data.index[section])