2020-09-27 04:54:49 -06:00
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
2015-03-13 01:16:59 -06:00
2020-09-27 04:54:49 -06:00
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
2015-09-13 23:12:22 -06:00
2020-09-27 04:54:49 -06:00
from PyQt5 . Qt import ( Qt , QGroupBox , QListWidget , QLineEdit , QDialogButtonBox , QWidget , QLabel , QDialog , QVBoxLayout , QAbstractItemView , QIcon , QHBoxLayout , QComboBox , QListWidgetItem , QFileDialog )
from PyQt5 import Qt as QtGui
2015-09-13 23:12:22 -06:00
from calibre . gui2 import ( error_dialog , question_dialog , info_dialog , open_url )
2015-03-13 01:16:59 -06:00
from calibre . utils . config import JSONConfig , config_dir
plugin_prefs = JSONConfig ( ' plugins/obok_dedrm_prefs ' )
plugin_prefs . defaults [ ' finding_homes_for_formats ' ] = ' Ask '
2015-09-13 23:12:22 -06:00
plugin_prefs . defaults [ ' kobo_serials ' ] = [ ]
2019-07-05 21:01:28 -06:00
plugin_prefs . defaults [ ' kobo_directory ' ] = u ' '
2015-03-13 01:16:59 -06:00
2015-09-16 08:01:29 -06:00
from calibre_plugins . obok_dedrm . __init__ import PLUGIN_NAME , PLUGIN_VERSION
2015-03-13 01:16:59 -06:00
from calibre_plugins . obok_dedrm . utilities import ( debug_print )
try :
debug_print ( " obok::config.py - loading translations " )
load_translations ( )
except NameError :
debug_print ( " obok::config.py - exception when loading translations " )
pass # load_translations() added in calibre 1.9
class ConfigWidget ( QWidget ) :
def __init__ ( self , plugin_action ) :
QWidget . __init__ ( self )
self . plugin_action = plugin_action
layout = QVBoxLayout ( self )
self . setLayout ( layout )
2015-09-13 23:12:22 -06:00
# copy of preferences
self . tmpserials = plugin_prefs [ ' kobo_serials ' ]
2019-07-05 21:01:28 -06:00
self . kobodirectory = plugin_prefs [ ' kobo_directory ' ]
2015-09-13 23:12:22 -06:00
2015-03-13 01:16:59 -06:00
combo_label = QLabel ( _ ( ' When should Obok try to insert EPUBs into existing calibre entries? ' ) , self )
layout . addWidget ( combo_label )
self . find_homes = QComboBox ( )
self . find_homes . setToolTip ( _ ( ' <p>Default behavior when duplicates are detected. None of the choices will cause calibre ebooks to be overwritten ' ) )
layout . addWidget ( self . find_homes )
2022-10-19 09:14:26 -06:00
self . find_homes . addItems ( [ _ ( ' Ask ' ) , _ ( ' Always ' ) , _ ( ' Never ' ) , _ ( ' Add new entry ' ) ] )
2015-03-13 01:16:59 -06:00
index = self . find_homes . findText ( plugin_prefs [ ' finding_homes_for_formats ' ] )
2022-10-19 09:14:26 -06:00
if index == - 1 :
index = self . find_homes . findText ( _ ( plugin_prefs [ ' finding_homes_for_formats ' ] ) )
2015-03-13 01:16:59 -06:00
self . find_homes . setCurrentIndex ( index )
2015-09-13 23:12:22 -06:00
self . serials_button = QtGui . QPushButton ( self )
2020-09-27 04:54:49 -06:00
self . serials_button . setToolTip ( _ ( " Click to manage Kobo serial numbers for Kobo ebooks " ) )
self . serials_button . setText ( " Kobo devices serials " )
2015-09-13 23:12:22 -06:00
self . serials_button . clicked . connect ( self . edit_serials )
layout . addWidget ( self . serials_button )
2019-07-05 21:01:28 -06:00
self . kobo_directory_button = QtGui . QPushButton ( self )
2020-09-27 04:54:49 -06:00
self . kobo_directory_button . setToolTip ( _ ( " Click to specify the Kobo directory " ) )
self . kobo_directory_button . setText ( " Kobo directory " )
2019-07-05 21:01:28 -06:00
self . kobo_directory_button . clicked . connect ( self . edit_kobo_directory )
layout . addWidget ( self . kobo_directory_button )
2015-09-13 23:12:22 -06:00
def edit_serials ( self ) :
2020-09-27 04:54:49 -06:00
d = ManageKeysDialog ( self , " Kobo device serial number " , self . tmpserials , AddSerialDialog )
2015-09-13 23:12:22 -06:00
d . exec_ ( )
2019-07-05 21:01:28 -06:00
def edit_kobo_directory ( self ) :
2022-07-13 07:34:47 -06:00
tmpkobodirectory = QFileDialog . getExistingDirectory ( self , " Select Kobo directory " , self . kobodirectory or " /home " , QFileDialog . Option . ShowDirsOnly )
2019-07-05 21:01:28 -06:00
if tmpkobodirectory != u " " and tmpkobodirectory is not None :
self . kobodirectory = tmpkobodirectory
2015-03-13 01:16:59 -06:00
def save_settings ( self ) :
2022-10-19 09:14:26 -06:00
# Make sure the config file string is *always* english.
find_homes = None
if self . find_homes . currentText ( ) == _ ( ' Ask ' ) :
find_homes = ' Ask '
elif self . find_homes . currentText ( ) == _ ( ' Always ' ) :
find_homes = ' Always '
elif self . find_homes . currentText ( ) == _ ( ' Never ' ) :
find_homes = ' Never '
elif self . find_homes . currentText ( ) == _ ( ' Add new entry ' ) :
find_homes = ' Add new entry '
if find_homes is None :
# Fallback
find_homes = self . find_homes . currentText ( )
plugin_prefs [ ' finding_homes_for_formats ' ] = find_homes
2015-09-13 23:12:22 -06:00
plugin_prefs [ ' kobo_serials ' ] = self . tmpserials
2019-07-05 21:01:28 -06:00
plugin_prefs [ ' kobo_directory ' ] = self . kobodirectory
2015-09-13 23:12:22 -06:00
class ManageKeysDialog ( QDialog ) :
def __init__ ( self , parent , key_type_name , plugin_keys , create_key , keyfile_ext = u " " ) :
QDialog . __init__ ( self , parent )
self . parent = parent
self . key_type_name = key_type_name
self . plugin_keys = plugin_keys
self . create_key = create_key
self . keyfile_ext = keyfile_ext
2020-09-27 04:54:49 -06:00
self . json_file = ( keyfile_ext == " k4i " )
2015-09-13 23:12:22 -06:00
self . setWindowTitle ( " {0} {1} : Manage {2} s " . format ( PLUGIN_NAME , PLUGIN_VERSION , self . key_type_name ) )
# Start Qt Gui dialog layout
layout = QVBoxLayout ( self )
self . setLayout ( layout )
2020-09-27 04:54:49 -06:00
keys_group_box = QGroupBox ( _ ( " {0} s " . format ( self . key_type_name ) ) , self )
2015-09-13 23:12:22 -06:00
layout . addWidget ( keys_group_box )
keys_group_box_layout = QHBoxLayout ( )
keys_group_box . setLayout ( keys_group_box_layout )
self . listy = QListWidget ( self )
2020-09-27 04:54:49 -06:00
self . listy . setToolTip ( " {0} s that will be used to decrypt ebooks " . format ( self . key_type_name ) )
2015-09-13 23:12:22 -06:00
self . listy . setSelectionMode ( QAbstractItemView . SingleSelection )
self . populate_list ( )
keys_group_box_layout . addWidget ( self . listy )
button_layout = QVBoxLayout ( )
keys_group_box_layout . addLayout ( button_layout )
self . _add_key_button = QtGui . QToolButton ( self )
self . _add_key_button . setIcon ( QIcon ( I ( ' plus.png ' ) ) )
2020-09-27 04:54:49 -06:00
self . _add_key_button . setToolTip ( " Create new {0} " . format ( self . key_type_name ) )
2015-09-13 23:12:22 -06:00
self . _add_key_button . clicked . connect ( self . add_key )
button_layout . addWidget ( self . _add_key_button )
self . _delete_key_button = QtGui . QToolButton ( self )
2020-09-27 04:54:49 -06:00
self . _delete_key_button . setToolTip ( _ ( " Delete highlighted key " ) )
2015-09-13 23:12:22 -06:00
self . _delete_key_button . setIcon ( QIcon ( I ( ' list_remove.png ' ) ) )
self . _delete_key_button . clicked . connect ( self . delete_key )
button_layout . addWidget ( self . _delete_key_button )
2022-01-02 13:18:13 -07:00
try :
# QT 6
spacerItem = QtGui . QSpacerItem ( 20 , 40 , QtGui . QSizePolicy . Policy . Minimum , QtGui . QSizePolicy . Policy . Expanding )
except AttributeError :
# QT 5
spacerItem = QtGui . QSpacerItem ( 20 , 40 , QtGui . QSizePolicy . Minimum , QtGui . QSizePolicy . Expanding )
2015-09-13 23:12:22 -06:00
button_layout . addItem ( spacerItem )
layout . addSpacing ( 5 )
migrate_layout = QHBoxLayout ( )
layout . addLayout ( migrate_layout )
migrate_layout . addStretch ( )
self . button_box = QDialogButtonBox ( QDialogButtonBox . Close )
self . button_box . rejected . connect ( self . close )
migrate_layout . addWidget ( self . button_box )
self . resize ( self . sizeHint ( ) )
def populate_list ( self ) :
if type ( self . plugin_keys ) == dict :
for key in self . plugin_keys . keys ( ) :
self . listy . addItem ( QListWidgetItem ( key ) )
else :
for key in self . plugin_keys :
self . listy . addItem ( QListWidgetItem ( key ) )
def add_key ( self ) :
d = self . create_key ( self )
d . exec_ ( )
if d . result ( ) != d . Accepted :
# New key generation cancelled.
return
new_key_value = d . key_value
if new_key_value in self . plugin_keys :
info_dialog ( None , " {0} {1} : Duplicate {2} " . format ( PLUGIN_NAME , PLUGIN_VERSION , self . key_type_name ) ,
2020-09-27 04:54:49 -06:00
" This {0} is already in the list of {0} s has not been added. " . format ( self . key_type_name ) , show = True )
2015-09-13 23:12:22 -06:00
return
self . plugin_keys . append ( d . key_value )
self . listy . clear ( )
self . populate_list ( )
def delete_key ( self ) :
if not self . listy . currentItem ( ) :
return
2020-09-26 14:22:47 -06:00
keyname = self . listy . currentItem ( ) . text ( )
2020-09-27 04:54:49 -06:00
if not question_dialog ( self , " {0} {1} : Confirm Delete " . format ( PLUGIN_NAME , PLUGIN_VERSION ) , " Do you really want to delete the {1} <strong> {0} </strong>? " . format ( keyname , self . key_type_name ) , show_copy_button = False , default_yes = False ) :
2015-09-13 23:12:22 -06:00
return
self . plugin_keys . remove ( keyname )
self . listy . clear ( )
self . populate_list ( )
class AddSerialDialog ( QDialog ) :
def __init__ ( self , parent = None , ) :
QDialog . __init__ ( self , parent )
self . parent = parent
2020-09-27 04:54:49 -06:00
self . setWindowTitle ( " {0} {1} : Add New eInk Kobo Serial Number " . format ( PLUGIN_NAME , PLUGIN_VERSION ) )
2015-09-13 23:12:22 -06:00
layout = QVBoxLayout ( self )
self . setLayout ( layout )
data_group_box = QGroupBox ( u " " , self )
layout . addWidget ( data_group_box )
data_group_box_layout = QVBoxLayout ( )
data_group_box . setLayout ( data_group_box_layout )
key_group = QHBoxLayout ( )
data_group_box_layout . addLayout ( key_group )
2020-09-27 04:54:49 -06:00
key_group . addWidget ( QLabel ( " EInk Kobo Serial Number: " , self ) )
2015-09-13 23:12:22 -06:00
self . key_ledit = QLineEdit ( " " , self )
2020-09-27 04:54:49 -06:00
self . key_ledit . setToolTip ( " Enter an eInk Kobo serial number. EInk Kobo serial numbers are 13 characters long and usually start with a ' N ' . Kobo Serial Numbers are case-sensitive, so be sure to enter the upper and lower case letters unchanged. " )
2015-09-13 23:12:22 -06:00
key_group . addWidget ( self . key_ledit )
self . button_box = QDialogButtonBox ( QDialogButtonBox . Ok | QDialogButtonBox . Cancel )
self . button_box . accepted . connect ( self . accept )
self . button_box . rejected . connect ( self . reject )
layout . addWidget ( self . button_box )
self . resize ( self . sizeHint ( ) )
@property
def key_name ( self ) :
2020-09-26 14:22:47 -06:00
return self . key_ledit . text ( ) . strip ( )
2015-09-13 23:12:22 -06:00
@property
def key_value ( self ) :
2020-09-26 14:22:47 -06:00
return self . key_ledit . text ( ) . strip ( )
2015-09-13 23:12:22 -06:00
def accept ( self ) :
if len ( self . key_name ) == 0 or self . key_name . isspace ( ) :
2021-11-16 13:22:09 -07:00
errmsg = " Please enter an eInk Kobo Serial Number or click Cancel in the dialog. "
2015-09-13 23:12:22 -06:00
return error_dialog ( None , " {0} {1} " . format ( PLUGIN_NAME , PLUGIN_VERSION ) , errmsg , show = True , show_copy_button = False )
if len ( self . key_name ) != 13 :
2020-09-27 04:54:49 -06:00
errmsg = " EInk Kobo Serial Numbers must be 13 characters long. This is {0:d} characters long. " . format ( len ( self . key_name ) )
2015-09-13 23:12:22 -06:00
return error_dialog ( None , " {0} {1} " . format ( PLUGIN_NAME , PLUGIN_VERSION ) , errmsg , show = True , show_copy_button = False )
QDialog . accept ( self )