Register Guidelines E-Books Today's Posts Search

Go Back   MobileRead Forums > E-Book Software > Calibre > Plugins

Notices

Reply
 
Thread Tools Search this Thread
Old 03-18-2021, 05:14 AM   #406
capink
Wizard
capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.
 
Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
Quote:
Originally Posted by ownedbycats View Post
Is it possible to toggle hiding a certain category in the tag browser using a module? (e.g. using the event manager to unhide "Kobo Collections" when a device is plugged in then hiding it again when it's ejected).
Making category visibility change based on events would be nice. But this seems more within the scope of the view manager plugin.

Quote:
Originally Posted by chaley View Post
There is no API, public or private, to hide and unhide tag browser categories.
I've played with gui.tags_view.context_menu_handler(action='hide', category='#genre') and it seems to working. Is there something that makes calling this non desirable?
capink is offline   Reply With Quote
Old 03-18-2021, 07:23 AM   #407
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Quote:
Originally Posted by capink View Post
I've played with gui.tags_view.context_menu_handler(action='hide', category='#genre') and it seems to working. Is there something that makes calling this non desirable?
I don't know. The problem is that the method is normally called when the tag browser is visible and a tag node has the focus. I don't know what happens if either isn't true, or more worrying if there are weird corner cases such as the focus being sometimes yanked to the tag browser. Your plugin could check for tag browser visible, but what do you do if it isn't visible? I don't know how to check for focus.

If you want to play with it then this might work. It uses "recount()' which is what calibre uses when the tag browser data has changed.
Code:
tag_browser = gui.tags_view
cats = tag_browser.hidden_categories
# modify cats as needed, adding or removing categories. It is a set()
self.db.new_api.set_pref('tag_browser_hidden_categories', list(cats))
tag_browser.recount()
EDIT: If the above does work then I could add it as a public API, something like
Code:
change_hidden_categories(operation, category_set)

Last edited by chaley; 03-18-2021 at 10:02 AM.
chaley is offline   Reply With Quote
Advert
Old 03-18-2021, 09:14 AM   #408
capink
Wizard
capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.
 
Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
This custom action seems to be working even when the tag browser has no focus and also when it is hidden

Code:
# python3 compatibility
from six.moves import range
from six import text_type as unicode

from PyQt5.Qt import (QApplication, Qt, QWidget, QVBoxLayout, QHBoxLayout,
                      QGroupBox, QTableWidget, QComboBox,  QToolButton,
                      QIcon, QSpacerItem, QSizePolicy, QAbstractItemView)

from calibre import prints
from calibre.constants import DEBUG, numeric_version
from calibre.gui2 import question_dialog

from calibre_plugins.action_chains.actions.base import ChainAction

class CategoryComboBox(QComboBox):

    def __init__(self, parent, categories, selected_text=None):
        QComboBox.__init__(self, parent)
        self.populate_combo(categories, selected_text)

    def populate_combo(self, categories, selected_text=None):
        self.blockSignals(True)
        self.clear()
        for category in categories:
            self.addItem(category)
        self.select_cateogry(selected_text)

    def select_cateogry(self, selected_text):
        self.blockSignals(True)
        if selected_text:
            idx = self.findText(selected_text)
            if idx == -1:
                self.addItem(selected_text)
                idx = self.findText(selected_text)
            self.setCurrentIndex(idx)
        else:
            self.setCurrentIndex(-1)
        self.blockSignals(False)

class CategoriesTable(QTableWidget):

    def __init__(self, plugin_action, data_items=[]):
        QTableWidget.__init__(self)
        self.plugin_action = plugin_action
        self.db = self.plugin_action.gui.current_db
        tag_browser = self.plugin_action.gui.tags_view
        self.all_categories = [ category.category_key for category \
                    in tag_browser._model.category_nodes if category.category_key.find('.') == -1 ]
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setAlternatingRowColors(True)
        self.populate_table(data_items)

    def populate_table(self, data_items):
        self.clear()
        self.setRowCount(len(data_items))
        header_labels = [_('Category'), _('Operation'), '']
        self.setColumnCount(len(header_labels))
        self.setHorizontalHeaderLabels(header_labels)
        self.verticalHeader().setDefaultSectionSize(24)

        for row, data in enumerate(data_items):
            self.populate_table_row(row, data)

        self.resizeColumnsToContents()

        for col in range(self.columnCount()):
            self.setMinimumColumnWidth(col, 150)        

        self.setSortingEnabled(False)
        self.setMinimumSize(800, 0)
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.selectRow(0)

    def populate_table_row(self, row, data):
        self.blockSignals(True)
        category_combo = CategoryComboBox(self, self.all_categories, data['category_key'])        
        operation_combo = CategoryComboBox(self, ['toggle','show','hide'], data['operation'])
        self.setCellWidget(row, 0, category_combo)
        self.setCellWidget(row, 1, operation_combo)
        self.blockSignals(False)

    def setMinimumColumnWidth(self, col, minimum):
        if self.columnWidth(col) < minimum:
            self.setColumnWidth(col, minimum)

    def add_data(self, data_items, append=False):
        if not append:
            self.setRowCount(0)
        for data in reversed(data_items):
            row = self.currentRow() + 1
            self.insertRow(row)
            self.populate_table_row(row, data)

    def get_data(self):
        data_items = []
        for row in range(self.rowCount()):
            data_item = self.convert_row_to_data(row)
            # filter out empty or incomplete rows
            if not (data_item['category_key'] and data_item['operation']):
                continue
            data_items.append(data_item)
        return data_items

    def convert_row_to_data(self, row):
        data = {}
        category_combo = self.cellWidget(row, 0)
        data['category_key'] = unicode(category_combo.currentText()).strip()
        operation_combo = self.cellWidget(row, 1)
        data['operation'] = unicode(operation_combo.currentText()).strip()
        return data      

    def create_blank_row_data(self):
        data = {}
        data['category_key'] = ''
        data['operation'] = ''
        return data

    def select_and_scroll_to_row(self, row):
        self.selectRow(row)
        self.scrollToItem(self.currentItem())

    def add_row(self):
        self.setFocus()
        # We will insert a blank row below the currently selected row
        row = self.currentRow() + 1
        self.insertRow(row)
        self.populate_table_row(row, self.create_blank_row_data())
        self.select_and_scroll_to_row(row)

    def delete_rows(self):
        self.setFocus()
        rows = self.selectionModel().selectedRows()
        rows = sorted(rows, key=lambda x: x.row())
        if len(rows) == 0:
            return
        message = '<p>Are you sure you want to delete this row?'
        if len(rows) > 1:
            message = '<p>Are you sure you want to delete the selected %d rows?'%len(rows)
        if not question_dialog(self, _('Are you sure?'), message, show_copy_button=False):
            return
        first_sel_row = self.currentRow()
        for selrow in reversed(rows):
            self.removeRow(selrow.row())
        if first_sel_row < self.rowCount():
            self.select_and_scroll_to_row(first_sel_row)
        elif self.rowCount() > 0:
            self.select_and_scroll_to_row(first_sel_row - 1)

class ConfigWidget(QWidget):

    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        self.gui = plugin_action.gui
        self.db = self.gui.current_db
        self._init_controls()

    def _init_controls(self):

        layout = QVBoxLayout()
        self.setLayout(layout)

        categories_group_box = QGroupBox(_('Category Operations'))
        layout.addWidget(categories_group_box)
        categories_group_box_layout = QHBoxLayout()
        categories_group_box.setLayout(categories_group_box_layout)
        self.table = CategoriesTable(self)
        categories_group_box_layout.addWidget(self.table)

        # Add a vertical layout containing the the buttons to move up/down etc.
        button_layout = QVBoxLayout()
        categories_group_box_layout.addLayout(button_layout)

        add_button = QToolButton(self)
        add_button.setToolTip(_('Add row'))
        add_button.setIcon(QIcon(I('plus.png')))
        button_layout.addWidget(add_button)
        spacerItem1 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        button_layout.addItem(spacerItem1)

        delete_button = QToolButton(self)
        delete_button.setToolTip(_('Delete row'))
        delete_button.setIcon(QIcon(I('minus.png')))
        button_layout.addWidget(delete_button)

        add_button.clicked.connect(self.table.add_row)
        delete_button.clicked.connect(self.table.delete_rows)
        
        layout.addStretch(1)

        self.setMinimumSize(600,300)

    def load_settings(self, settings):
        categories_config = settings.get('categories_config', [])
        self.table.add_data(categories_config)

    def save_settings(self):
        settings = {}
        settings['categories_config'] = self.table.get_data()
        return settings


class CategoryVisibility(ChainAction):

    name = 'Category Visibility'

    def apply_category_operations(self, category_operations):
        db = self.plugin_action.gui.current_db
        tag_browser = self.plugin_action.gui.tags_view
        all_categories = [ category.category_key for category \
                    in tag_browser._model.category_nodes if category.category_key.find('.') == -1 ]
        hidden_categories = tag_browser.hidden_categories
        for category_operation in category_operations:
            category_key = category_operation['category_key']
            operation = category_operation['operation']
            if category_key not in all_categories:
                continue
            if numeric_version < (5,14,0):
                is_category_hidden = category_key in hidden_categories
                if operation == 'toggle':
                    if is_category_hidden:
                        operation = 'show'
                    else:
                        operation = 'hide'
                tag_browser.context_menu_handler(action=operation, category=category_key)
            else:
                gui.tb_category_visibility(category_key, operation)

    def run(self, gui, settings, chain):
        category_operations = settings.get('categories_config', [])
        self.apply_category_operations(category_operations)

    def validate(self, settings):
        try:
            if not settings.get('categories_config'):
                raise Exception('Empty settings')
        except:
            return (_('Settings Error'), _('You must configure this action before running it'))
        for category_config in settings.get('categories_config'):
            category_key = category_config.get('category_key')
            operation = category_config.get('operation')
            if not (category_key and operation):
                   return (_('Missing values'), _('Empty values not allowed for name or action'))  
        gui = self.plugin_action.gui
        categories_config = settings['categories_config']
        available_category_keys = set([category.category_key for category in gui.tags_view._model.category_nodes])
        saved_category_keys = set([x['category_key'] for x in categories_config])
        missing_keys = saved_category_keys.difference(available_category_keys)
        if missing_keys:
            return (_('Missing Category(s)'), _('Catetory(s) ({}) not available in current library'.format(missing_keys)))
        return True

    def config_widget(self):
        return ConfigWidget

Last edited by capink; 03-23-2021 at 01:34 PM. Reason: Updated to include latest changes introduced by chaley
capink is offline   Reply With Quote
Old 03-18-2021, 10:57 AM   #409
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Quote:
Originally Posted by capink View Post
This custom action seems to be working even when the tag browser has no focus and also when it is hidden
I am adding API to do the task. Could you test it? It works for me.

Add this at line 438 of gui2.tag_browser.ui
Code:
    def change_tb_category_visibility(self, category, operation):
        '''
        Hide or show categories in the tag browser. 'category' is the lookup key
        to show or hide. Set operation == 'show' or 'hide' as needed.
        '''
        if category not in self.tags_view.model().categories:
            raise ValueError(_('change_tb_category_visibility: category %s does not exist') % category)
        cats = self.tags_view.hidden_categories
        if operation == 'hide':
            cats.add(category)
        elif operation == 'show':
            cats.discard(category)
        else:
            raise ValueError(_('change_tb_category_visibility: invalid operation %s') % operation)
        self.library_view.model().db.new_api.set_pref('tag_browser_hidden_categories', list(cats))
        self.tags_view.recount()
Change the code of your module at line 212 as follows:
Code:
            #tag_browser.context_menu_handler(action=visibility, category=category_key)
#            if visibility == 'show':
#                hidden_categories.discard(category_key)
#            else:
#                hidden_categories.add(category_key)
#        db.new_api.set_pref('tag_browser_hidden_categories', list(hidden_categories))
#        tag_browser.recount()
        gui.change_tb_category_visibility(category_key, visibility)
As you can see, the code that changed the hidden categories and the calls into the tag browser were replaced by
Code:
        gui.change_tb_category_visibility(category_key, visibility)
chaley is offline   Reply With Quote
Old 03-18-2021, 11:13 AM   #410
capink
Wizard
capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.
 
Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
I tested it and it is working. Thank you.
capink is offline   Reply With Quote
Advert
Old 03-18-2021, 11:14 AM   #411
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
Quote:
Originally Posted by capink View Post
I tested it and it is working. Thank you.
Good. I will submit it to Kovid.
chaley is offline   Reply With Quote
Old 03-18-2021, 12:28 PM   #412
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
The API method is now in source, with a new name and more functionality. Details are:
Code:
    def tb_category_visibility(self, category, operation):
        '''
        Hide or show categories in the tag browser. 'category' is the lookup key.
        Operation can be:
        - 'show' to show the category in the tag browser
        - 'hide' to hide the category
        - 'toggle' to invert its visibility
        - 'is_visible' returns True if the category is currently visible, False otherwise
        '''
I think you no longer need the variable hidden_categories.
chaley is offline   Reply With Quote
Old 03-18-2021, 04:17 PM   #413
ownedbycats
Custom User Title
ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.
 
ownedbycats's Avatar
 
Posts: 11,007
Karma: 75555555
Join Date: Oct 2018
Location: Canada
Device: Kobo Libra H2O, formerly Aura HD
Thank you!
ownedbycats is offline   Reply With Quote
Old 03-18-2021, 05:32 PM   #414
capink
Wizard
capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.
 
Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
Quote:
Originally Posted by chaley View Post
The API method is now in source, with a new name and more functionality. Details are:
Code:
    def tb_category_visibility(self, category, operation):
        '''
        Hide or show categories in the tag browser. 'category' is the lookup key.
        Operation can be:
        - 'show' to show the category in the tag browser
        - 'hide' to hide the category
        - 'toggle' to invert its visibility
        - 'is_visible' returns True if the category is currently visible, False otherwise
        '''
I think you no longer need the variable hidden_categories.
That is even better.
capink is offline   Reply With Quote
Old 03-18-2021, 05:48 PM   #415
ownedbycats
Custom User Title
ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.
 
ownedbycats's Avatar
 
Posts: 11,007
Karma: 75555555
Join Date: Oct 2018
Location: Canada
Device: Kobo Libra H2O, formerly Aura HD
Quote:
Originally Posted by capink View Post
Making category visibility change based on events would be nice. But this seems more within the scope of the view manager plugin.
I thought of that, but I don't think View Manager is really being actively developed except for bugfixes.
ownedbycats is offline   Reply With Quote
Old 03-22-2021, 04:46 AM   #416
ownedbycats
Custom User Title
ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.
 
ownedbycats's Avatar
 
Posts: 11,007
Karma: 75555555
Join Date: Oct 2018
Location: Canada
Device: Kobo Libra H2O, formerly Aura HD
This might've been asked before, but is there a way in Action Chains to "add file to selected book records" with a specified filepath? I keep a dummy.paperbook file in a folder for, well, paper books.

This is a bit of a corner case though and probably not practical to add something specifically for it.
ownedbycats is offline   Reply With Quote
Old 03-22-2021, 06:52 AM   #417
capink
Wizard
capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.
 
Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
Quote:
Originally Posted by ownedbycats View Post
This might've been asked before, but is there a way in Action Chains to "add file to selected book records" with a specified filepath? I keep a dummy.paperbook file in a folder for, well, paper books.

This is a bit of a corner case though and probably not practical to add something specifically for it.
Code:
from __future__ import (unicode_literals, division, absolute_import,
                        print_function)

import subprocess
import os

from PyQt5.Qt import (QApplication, Qt, QWidget, QHBoxLayout, QVBoxLayout,
                      QGroupBox, QToolButton)

from calibre import prints
from calibre.constants import DEBUG, iswindows
from calibre.gui2 import error_dialog, choose_files

from calibre_plugins.action_chains.actions.base import ChainAction
from calibre_plugins.action_chains.common_utils import DragDropComboBox, get_icon

class ConfigWidget(QWidget):
    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        self.gui = plugin_action.gui
        self.db = self.gui.current_db
        self.template = ''
        self._init_controls()

    def _init_controls(self):

        l = QVBoxLayout()
        self.setLayout(l)

        self.format_box = QGroupBox(_('&Choose format:'))
        l.addWidget(self.format_box)
        format_layout = QVBoxLayout()
        self.format_box.setLayout(format_layout)
        self.format_combo = DragDropComboBox(self, drop_mode='file')
        format_layout.addWidget(self.format_combo)
        hl1 = QHBoxLayout()
        format_layout.addLayout(hl1)
        hl1.addWidget(self.format_combo, 1)
        self.choose_format_button = QToolButton(self)
        self.choose_format_button.setToolTip(_('Choose format'))
        self.choose_format_button.setIcon(get_icon('document_open.png'))
        self.choose_format_button.clicked.connect(self._choose_file)
        hl1.addWidget(self.choose_format_button)

    def _choose_file(self):
        files = choose_files(None, _('Select format dialog'), _('Select a format'),
                             all_files=True, select_only_single_file=True)
        if not files:
            return
        format_path = files[0]
        if iswindows:
            format_path = os.path.normpath(format_path)

        self.block_events = True
        existing_index = self.format_combo.findText(format_path, Qt.MatchExactly)
        if existing_index >= 0:
            self.format_combo.setCurrentIndex(existing_index)
        else:
            self.format_combo.insertItem(0, format_path)
            self.format_combo.setCurrentIndex(0)
        self.block_events = False

    def load_settings(self, settings):
        if settings:
            self.format_combo.setCurrentText(settings['path_to_format'])

    def save_settings(self):
        settings = {}
        settings['path_to_format'] = self.format_combo.currentText().strip()
        return settings


class AddFormatAction(ChainAction):

    name = 'Add Format'
    support_scopes = True

    def run(self, gui, settings, chain):
        book_ids = chain.scope().get_book_ids()
        
        db = gui.current_db
        
        path = settings['path_to_format']
        try:
            fmt = os.path.splitext(path)[-1].lower().replace('.', '').upper()
        except:
            fmt = ''
        
        for book_id in book_ids:
            db.new_api.add_format(book_id, fmt, path)

    def validate(self, settings):
        if not settings:
            return (_('Settings Error'), _('You must configure this action before running it'))
        if not settings['path_to_format']:
            return (_('No Format'), _('You must specify a path to valid format'))
        return True

    def config_widget(self):
        return ConfigWidget

Last edited by capink; 07-16-2021 at 03:44 AM.
capink is offline   Reply With Quote
Old 03-22-2021, 03:04 PM   #418
chaley
Grand Sorcerer
chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.chaley ought to be getting tired of karma fortunes by now.
 
Posts: 12,447
Karma: 8012886
Join Date: Jan 2010
Location: Notts, England
Device: Kobo Libra 2
@capink: the changes to the template dialog broke action chains. Opening the template editor now silently dies.

The problem is in these lines of code at (I think) line 431 in templates.py:
Code:
        try:        
            self.gridLayout.setRowStretch(self.getWidgetRow(self.textbox), 2)
            self.gridLayout.setRowStretch(self.getWidgetRow(self.source_code), 1)
        except:
            if DEBUG:
                prints('Action chains: TemplateBox: Not able to modify stretch')
If I comment out the line:
Code:
            self.gridLayout.setRowStretch(self.getWidgetRow(self.source_code), 1)
the plugin works again.

I don't know why these lines are there.

While making the changes to add more result lines and ability to change the font, I cleaned up the layout of the dialog. In particular, the function reference stuff is now in its own unnamed grid layout put into a cell in the parent layout.

My recommendation is that unless there is a compelling reason you should remove the try/except block changing the stretch factor. You shouldn't need it. If you do then I can look at why and see if it is fixable in the TemplateDialog class itself.
chaley is offline   Reply With Quote
Old 03-22-2021, 03:17 PM   #419
capink
Wizard
capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.capink ought to be getting tired of karma fortunes by now.
 
Posts: 1,196
Karma: 1995558
Join Date: Aug 2015
Device: Kindle
They are unnecessary. I was experimenting with modifying stretch values and left them there. I will remove them before the next version of calibre is released.
capink is offline   Reply With Quote
Old 03-23-2021, 06:28 PM   #420
ownedbycats
Custom User Title
ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.ownedbycats ought to be getting tired of karma fortunes by now.
 
ownedbycats's Avatar
 
Posts: 11,007
Karma: 75555555
Join Date: Oct 2018
Location: Canada
Device: Kobo Libra H2O, formerly Aura HD
Question: Some of my chains have Kobo Utilities actions that disappear when device is not plugged in, so they appear as red errors in the editor. Is it safe to modify that chain without plugging in the device?

Click image for larger version

Name:	2021-03-23 19_28_12-Add actions.png
Views:	788
Size:	27.1 KB
ID:	186137
ownedbycats is offline   Reply With Quote
Reply


Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
[Editor Plugin] Editor Chains capink Plugins 106 06-17-2025 05:36 PM
Action Chains Resources capink Plugins 77 06-16-2025 12:45 PM
[GUI Plugin] Noosfere_util, a companion plugin to noosfere DB lrpirlet Plugins 2 08-18-2022 03:15 PM
[GUI Plugin] Save Virtual Libraries To Column (GUI) chaley Plugins 14 04-04-2021 05:25 AM


All times are GMT -4. The time now is 09:00 AM.


MobileRead.com is a privately owned, operated and funded community.