class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(937, 562)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
        self.centralwidget.setSizePolicy(sizePolicy)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setContentsMargins(6, 6, 6, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.bookInfoSplitter = QtWidgets.QSplitter(self.centralwidget)
        self.bookInfoSplitter.setOrientation(QtCore.Qt.Horizontal)
        self.bookInfoSplitter.setChildrenCollapsible(False)
        self.bookInfoSplitter.setObjectName("bookInfoSplitter")
        self.treeFileList = QtWidgets.QTreeWidget(self.bookInfoSplitter)
        self.treeFileList.setAcceptDrops(False)
        self.treeFileList.setDragDropMode(QtWidgets.QAbstractItemView.NoDragDrop)
        self.treeFileList.setDefaultDropAction(QtCore.Qt.IgnoreAction)
        self.treeFileList.setAlternatingRowColors(True)
        self.treeFileList.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
        self.treeFileList.setRootIsDecorated(False)
        self.treeFileList.setObjectName("treeFileList")
        self.treeFileList.header().setVisible(True)
        self.scrollBookInfo = QtWidgets.QScrollArea(self.bookInfoSplitter)
        self.scrollBookInfo.setWidgetResizable(True)
        self.scrollBookInfo.setObjectName("scrollBookInfo")
        self.scrollAreaWidgetContents = QtWidgets.QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 409, 501))
        self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
        self.verticalLayout.setContentsMargins(8, 8, 8, 8)
        self.verticalLayout.setSpacing(3)
        self.verticalLayout.setObjectName("verticalLayout")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setSpacing(0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.imgBookCover = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.imgBookCover.sizePolicy().hasHeightForWidth())
        self.imgBookCover.setSizePolicy(sizePolicy)
        self.imgBookCover.setMinimumSize(QtCore.QSize(120, 160))
        self.imgBookCover.setMaximumSize(QtCore.QSize(120, 160))
        self.imgBookCover.setBaseSize(QtCore.QSize(120, 160))
        self.imgBookCover.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.imgBookCover.setText("")
        self.imgBookCover.setAlignment(QtCore.Qt.AlignCenter)
        self.imgBookCover.setObjectName("imgBookCover")
        self.horizontalLayout_2.addWidget(self.imgBookCover)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.labelAuthor = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        self.labelAuthor.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
        self.labelAuthor.setObjectName("labelAuthor")
        self.verticalLayout.addWidget(self.labelAuthor)
        self.editAuthor = QtWidgets.QLineEdit(self.scrollAreaWidgetContents)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.editAuthor.sizePolicy().hasHeightForWidth())
        self.editAuthor.setSizePolicy(sizePolicy)
        self.editAuthor.setObjectName("editAuthor")
        self.verticalLayout.addWidget(self.editAuthor)
        self.labelBookTitle = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        self.labelBookTitle.setObjectName("labelBookTitle")
        self.verticalLayout.addWidget(self.labelBookTitle)
        self.editTitle = QtWidgets.QLineEdit(self.scrollAreaWidgetContents)
        self.editTitle.setObjectName("editTitle")
        self.verticalLayout.addWidget(self.editTitle)
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setSpacing(4)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.labelSeries = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        self.labelSeries.setObjectName("labelSeries")
        self.gridLayout_2.addWidget(self.labelSeries, 0, 0, 1, 1)
        self.labelSeriesNumber = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        self.labelSeriesNumber.setObjectName("labelSeriesNumber")
        self.gridLayout_2.addWidget(self.labelSeriesNumber, 0, 1, 1, 1)
        self.editSeries = QtWidgets.QLineEdit(self.scrollAreaWidgetContents)
        self.editSeries.setObjectName("editSeries")
        self.gridLayout_2.addWidget(self.editSeries, 1, 0, 1, 1)
        self.editSeriesNumber = QtWidgets.QLineEdit(self.scrollAreaWidgetContents)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.editSeriesNumber.sizePolicy().hasHeightForWidth())
        self.editSeriesNumber.setSizePolicy(sizePolicy)
        self.editSeriesNumber.setMaximumSize(QtCore.QSize(50, 16777215))
        self.editSeriesNumber.setObjectName("editSeriesNumber")
        self.gridLayout_2.addWidget(self.editSeriesNumber, 1, 1, 1, 1)
        self.verticalLayout.addLayout(self.gridLayout_2)
        self.label = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        self.label.setObjectName("label")
        self.verticalLayout.addWidget(self.label)
        self.comboGenres = QtWidgets.QComboBox(self.scrollAreaWidgetContents)
        self.comboGenres.setObjectName("comboGenres")
        self.verticalLayout.addWidget(self.comboGenres)
        self.labelBookLanguage = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        self.labelBookLanguage.setObjectName("labelBookLanguage")
        self.verticalLayout.addWidget(self.labelBookLanguage)
        self.editBookLanguage = QtWidgets.QLineEdit(self.scrollAreaWidgetContents)
        self.editBookLanguage.setObjectName("editBookLanguage")
        self.verticalLayout.addWidget(self.editBookLanguage)
        self.label_2 = QtWidgets.QLabel(self.scrollAreaWidgetContents)
        self.label_2.setObjectName("label_2")
        self.verticalLayout.addWidget(self.label_2)
        self.editTranslator = QtWidgets.QLineEdit(self.scrollAreaWidgetContents)
        self.editTranslator.setObjectName("editTranslator")
        self.verticalLayout.addWidget(self.editTranslator)
        spacerItem1 = QtWidgets.QSpacerItem(20, 37, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem1)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setContentsMargins(-1, -1, 0, 0)
        self.horizontalLayout.setSpacing(0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem2)
        self.buttonSaveBookInfo = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.buttonSaveBookInfo.sizePolicy().hasHeightForWidth())
        self.buttonSaveBookInfo.setSizePolicy(sizePolicy)
        self.buttonSaveBookInfo.setObjectName("buttonSaveBookInfo")
        self.horizontalLayout.addWidget(self.buttonSaveBookInfo)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.scrollBookInfo.setWidget(self.scrollAreaWidgetContents)
        self.gridLayout.addWidget(self.bookInfoSplitter, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 937, 21))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")
        self.menu_2 = QtWidgets.QMenu(self.menubar)
        self.menu_2.setObjectName("menu_2")
        self.menu_3 = QtWidgets.QMenu(self.menubar)
        self.menu_3.setObjectName("menu_3")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.toolBar = QtWidgets.QToolBar(MainWindow)
        self.toolBar.setMovable(False)
        self.toolBar.setFloatable(False)
        self.toolBar.setObjectName("toolBar")
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.actionAddFile = QtWidgets.QAction(MainWindow)
        self.actionAddFile.setObjectName("actionAddFile")
        self.actionExit = QtWidgets.QAction(MainWindow)
        self.actionExit.setMenuRole(QtWidgets.QAction.QuitRole)
        self.actionExit.setObjectName("actionExit")
        self.actionOpenForumURL = QtWidgets.QAction(MainWindow)
        self.actionOpenForumURL.setObjectName("actionOpenForumURL")
        self.actionAbout = QtWidgets.QAction(MainWindow)
        self.actionAbout.setMenuRole(QtWidgets.QAction.AboutRole)
        self.actionAbout.setObjectName("actionAbout")
        self.actionViewLog = QtWidgets.QAction(MainWindow)
        self.actionViewLog.setObjectName("actionViewLog")
        self.actionDelete = QtWidgets.QAction(MainWindow)
        self.actionDelete.setObjectName("actionDelete")
        self.actionSettings = QtWidgets.QAction(MainWindow)
        self.actionSettings.setMenuRole(QtWidgets.QAction.PreferencesRole)
        self.actionSettings.setObjectName("actionSettings")
        self.toolAdd = QtWidgets.QAction(MainWindow)
        self.toolAdd.setObjectName("toolAdd")
        self.toolInfo = QtWidgets.QAction(MainWindow)
        self.toolInfo.setObjectName("toolInfo")
        self.toolSettings = QtWidgets.QAction(MainWindow)
        self.toolSettings.setObjectName("toolSettings")
        self.toolSaveToDisk = QtWidgets.QAction(MainWindow)
        self.toolSaveToDisk.setObjectName("toolSaveToDisk")
        self.toolSendToKindle = QtWidgets.QAction(MainWindow)
        self.toolSendToKindle.setObjectName("toolSendToKindle")
        self.toolSendMail = QtWidgets.QAction(MainWindow)
        self.toolSendMail.setObjectName("toolSendMail")
        self.actionConvertToDisk = QtWidgets.QAction(MainWindow)
        self.actionConvertToDisk.setObjectName("actionConvertToDisk")
        self.actionSendToKindle = QtWidgets.QAction(MainWindow)
        self.actionSendToKindle.setObjectName("actionSendToKindle")
        self.actionSendViaMail = QtWidgets.QAction(MainWindow)
        self.actionSendViaMail.setObjectName("actionSendViaMail")
        self.actionOpenHelpURL = QtWidgets.QAction(MainWindow)
        self.actionOpenHelpURL.setObjectName("actionOpenHelpURL")
        self.actionAddGDirve = QtWidgets.QAction(MainWindow)
        self.actionAddGDirve.setIconVisibleInMenu(False)
        self.actionAddGDirve.setObjectName("actionAddGDirve")
        self.actionRename = QtWidgets.QAction(MainWindow)
        self.actionRename.setIconVisibleInMenu(False)
        self.actionRename.setObjectName("actionRename")
        self.actionDeleteAll = QtWidgets.QAction(MainWindow)
        self.actionDeleteAll.setObjectName("actionDeleteAll")
        self.menu.addAction(self.actionAddFile)
        self.menu.addAction(self.actionAddGDirve)
        self.menu.addSeparator()
        self.menu.addAction(self.actionConvertToDisk)
        self.menu.addAction(self.actionSendToKindle)
        self.menu.addAction(self.actionSendViaMail)
        self.menu.addSeparator()
        self.menu.addAction(self.actionSettings)
        self.menu.addSeparator()
        self.menu.addAction(self.actionExit)
        self.menu_2.addAction(self.actionOpenHelpURL)
        self.menu_2.addAction(self.actionOpenForumURL)
        self.menu_2.addSeparator()
        self.menu_2.addAction(self.actionAbout)
        self.menu_3.addAction(self.actionDelete)
        self.menu_3.addAction(self.actionDeleteAll)
        self.menu_3.addSeparator()
        self.menu_3.addAction(self.actionRename)
        self.menu_3.addSeparator()
        self.menu_3.addAction(self.actionViewLog)
        self.menubar.addAction(self.menu.menuAction())
        self.menubar.addAction(self.menu_3.menuAction())
        self.menubar.addAction(self.menu_2.menuAction())

        self.retranslateUi(MainWindow)
        self.actionExit.triggered.connect(MainWindow.closeApp)
        self.actionAddFile.triggered.connect(MainWindow.addFilesAction)
        self.actionDelete.triggered.connect(MainWindow.deleteRecAction)
        self.actionOpenForumURL.triggered.connect(MainWindow.openSupportURL)
        self.actionViewLog.triggered.connect(MainWindow.openLog)
        self.actionAbout.triggered.connect(MainWindow.about)
        self.actionSettings.triggered.connect(MainWindow.settings)
        self.toolAdd.triggered.connect(MainWindow.addFilesAction)
        self.toolSettings.triggered.connect(MainWindow.settings)
        self.treeFileList.itemSelectionChanged.connect(MainWindow.changeBook)
        self.buttonSaveBookInfo.clicked.connect(MainWindow.saveBookInfo)
        self.toolInfo.triggered.connect(MainWindow.switchInfoPanel)
        self.toolSaveToDisk.triggered.connect(MainWindow.convertToDisk)
        self.toolSendToKindle.triggered.connect(MainWindow.sendToKindle)
        self.toolSendMail.triggered.connect(MainWindow.sendViaMail)
        self.actionConvertToDisk.triggered.connect(MainWindow.convertToDisk)
        self.actionSendToKindle.triggered.connect(MainWindow.sendToKindle)
        self.actionSendViaMail.triggered.connect(MainWindow.sendViaMail)
        self.actionOpenHelpURL.triggered.connect(MainWindow.openHelpURL)
        self.actionAddGDirve.triggered.connect(MainWindow.openFromGDrive)
        self.actionRename.triggered.connect(MainWindow.rename)
        self.actionDeleteAll.triggered.connect(MainWindow.deleteAllAction)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "fb2mobi"))
        self.treeFileList.headerItem().setText(0, _translate("MainWindow", "Title"))
        self.treeFileList.headerItem().setText(1, _translate("MainWindow", "Author"))
        self.treeFileList.headerItem().setText(2, _translate("MainWindow", "Series"))
        self.treeFileList.headerItem().setText(3, _translate("MainWindow", "Genre"))
        self.treeFileList.headerItem().setText(4, _translate("MainWindow", "File"))
        self.labelAuthor.setText(_translate("MainWindow", "Author"))
        self.labelBookTitle.setText(_translate("MainWindow", "Title"))
        self.labelSeries.setText(_translate("MainWindow", "Series"))
        self.labelSeriesNumber.setText(_translate("MainWindow", "#"))
        self.label.setText(_translate("MainWindow", "Genre"))
        self.labelBookLanguage.setText(_translate("MainWindow", "Book language"))
        self.label_2.setText(_translate("MainWindow", "Translator"))
        self.buttonSaveBookInfo.setText(_translate("MainWindow", "Save"))
        self.menu.setTitle(_translate("MainWindow", "File"))
        self.menu_2.setTitle(_translate("MainWindow", "Help"))
        self.menu_3.setTitle(_translate("MainWindow", "Edit"))
        self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
        self.actionAddFile.setText(_translate("MainWindow", "Add..."))
        self.actionAddFile.setShortcut(_translate("MainWindow", "Ctrl+O"))
        self.actionExit.setText(_translate("MainWindow", "Exit"))
        self.actionOpenForumURL.setText(_translate("MainWindow", "Support forum"))
        self.actionAbout.setText(_translate("MainWindow", "About..."))
        self.actionViewLog.setText(_translate("MainWindow", "View log"))
        self.actionDelete.setText(_translate("MainWindow", "Delete"))
        self.actionSettings.setText(_translate("MainWindow", "Settings..."))
        self.toolAdd.setText(_translate("MainWindow", "Add"))
        self.toolInfo.setText(_translate("MainWindow", "Info"))
        self.toolSettings.setText(_translate("MainWindow", "Settings"))
        self.toolSaveToDisk.setText(_translate("MainWindow", "Convert to disk"))
        self.toolSaveToDisk.setToolTip(_translate("MainWindow", "Convert to disk"))
        self.toolSendToKindle.setText(_translate("MainWindow", "Send to Kindle"))
        self.toolSendMail.setText(_translate("MainWindow", "Send via Gmail"))
        self.actionConvertToDisk.setText(_translate("MainWindow", "Convert to disk"))
        self.actionSendToKindle.setText(_translate("MainWindow", "Send to Kindle"))
        self.actionSendViaMail.setText(_translate("MainWindow", "Send via Gmail"))
        self.actionOpenHelpURL.setText(_translate("MainWindow", "Help"))
        self.actionAddGDirve.setText(_translate("MainWindow", "Add from Google Drive..."))
        self.actionAddGDirve.setToolTip(_translate("MainWindow", "Add files from Google Drive.."))
        self.actionAddGDirve.setShortcut(_translate("MainWindow", "Ctrl+G"))
        self.actionRename.setText(_translate("MainWindow", "Rename..."))
        self.actionRename.setToolTip(_translate("MainWindow", "Rename selected files"))
        self.actionDeleteAll.setText(_translate("MainWindow", "Delete all")) class Ui_AboutDialog(object):
    def setupUi(self, AboutDialog):
        AboutDialog.setObjectName("AboutDialog")
        AboutDialog.setWindowModality(QtCore.Qt.ApplicationModal)
        AboutDialog.resize(481, 196)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(AboutDialog.sizePolicy().hasHeightForWidth())
        AboutDialog.setSizePolicy(sizePolicy)
        AboutDialog.setAutoFillBackground(False)
        AboutDialog.setSizeGripEnabled(False)
        AboutDialog.setModal(True)
        self.gridLayout_2 = QtWidgets.QGridLayout(AboutDialog)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.labelImage = QtWidgets.QLabel(AboutDialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.labelImage.sizePolicy().hasHeightForWidth())
        self.labelImage.setSizePolicy(sizePolicy)
        self.labelImage.setText("")
        self.labelImage.setPixmap(QtGui.QPixmap("128.png"))
        self.labelImage.setScaledContents(False)
        self.labelImage.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
        self.labelImage.setObjectName("labelImage")
        self.horizontalLayout.addWidget(self.labelImage)
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setSpacing(6)
        self.verticalLayout.setObjectName("verticalLayout")
        self.label_2 = QtWidgets.QLabel(AboutDialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())
        self.label_2.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setPointSize(24)
        font.setBold(True)
        font.setWeight(75)
        self.label_2.setFont(font)
        self.label_2.setObjectName("label_2")
        self.verticalLayout.addWidget(self.label_2)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
        self.gridLayout.setHorizontalSpacing(10)
        self.gridLayout.setVerticalSpacing(5)
        self.gridLayout.setObjectName("gridLayout")
        self.label_8 = QtWidgets.QLabel(AboutDialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.label_8.sizePolicy().hasHeightForWidth())
        self.label_8.setSizePolicy(sizePolicy)
        self.label_8.setObjectName("label_8")
        self.gridLayout.addWidget(self.label_8, 2, 1, 1, 1)
        spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.gridLayout.addItem(spacerItem, 4, 1, 1, 1)
        self.label_3 = QtWidgets.QLabel(AboutDialog)
        font = QtGui.QFont()
        font.setBold(True)
        font.setWeight(75)
        self.label_3.setFont(font)
        self.label_3.setObjectName("label_3")
        self.gridLayout.addWidget(self.label_3, 0, 0, 1, 1)
        self.labelVersion = QtWidgets.QLabel(AboutDialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.labelVersion.sizePolicy().hasHeightForWidth())
        self.labelVersion.setSizePolicy(sizePolicy)
        self.labelVersion.setObjectName("labelVersion")
        self.gridLayout.addWidget(self.labelVersion, 0, 1, 1, 1)
        self.label_4 = QtWidgets.QLabel(AboutDialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth())
        self.label_4.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setBold(True)
        font.setWeight(75)
        self.label_4.setFont(font)
        self.label_4.setObjectName("label_4")
        self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1)
        self.labelUIVersion = QtWidgets.QLabel(AboutDialog)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.labelUIVersion.sizePolicy().hasHeightForWidth())
        self.labelUIVersion.setSizePolicy(sizePolicy)
        self.labelUIVersion.setObjectName("labelUIVersion")
        self.gridLayout.addWidget(self.labelUIVersion, 1, 1, 1, 1)
        self.label_5 = QtWidgets.QLabel(AboutDialog)
        font = QtGui.QFont()
        font.setBold(True)
        font.setWeight(75)
        self.label_5.setFont(font)
        self.label_5.setObjectName("label_5")
        self.gridLayout.addWidget(self.label_5, 2, 0, 1, 1)
        self.label = QtWidgets.QLabel(AboutDialog)
        font = QtGui.QFont()
        font.setBold(True)
        font.setWeight(75)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 3, 0, 1, 1)
        self.label_6 = QtWidgets.QLabel(AboutDialog)
        self.label_6.setOpenExternalLinks(True)
        self.label_6.setObjectName("label_6")
        self.gridLayout.addWidget(self.label_6, 3, 1, 1, 1)
        self.verticalLayout.addLayout(self.gridLayout)
        self.horizontalLayout.addLayout(self.verticalLayout)
        self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 1)

        self.retranslateUi(AboutDialog)
        QtCore.QMetaObject.connectSlotsByName(AboutDialog)

    def retranslateUi(self, AboutDialog):
        _translate = QtCore.QCoreApplication.translate
        AboutDialog.setWindowTitle(_translate("AboutDialog", "About"))
        self.label_2.setText(_translate("AboutDialog", "fb2mobi"))
        self.label_8.setText(_translate("AboutDialog", "rupor, dnk_dz, gmk57"))
        self.label_3.setText(_translate("AboutDialog", "Version:"))
        self.labelVersion.setText(_translate("AboutDialog", "TextLabel"))
        self.label_4.setText(_translate("AboutDialog", "UI version:"))
        self.labelUIVersion.setText(_translate("AboutDialog", "TextLabel"))
        self.label_5.setText(_translate("AboutDialog", "Authors:"))
        self.label.setText(_translate("AboutDialog", "Toolbar icons:"))
        self.label_6.setText(_translate("AboutDialog", "<a href=\'https://icons8.com/\'>Icons8</a>")) class Ui_SettingsDialog(object):
    def setupUi(self, SettingsDialog):
        SettingsDialog.setObjectName("SettingsDialog")
        SettingsDialog.resize(546, 523)
        self.verticalLayout_3 = QtWidgets.QVBoxLayout(SettingsDialog)
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.tabWidget = QtWidgets.QTabWidget(SettingsDialog)
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.gridLayout_6 = QtWidgets.QGridLayout(self.tab)
        self.gridLayout_6.setContentsMargins(8, 8, 8, 8)
        self.gridLayout_6.setObjectName("gridLayout_6")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.label = QtWidgets.QLabel(self.tab)
        self.label.setObjectName("label")
        self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
        self.label_2 = QtWidgets.QLabel(self.tab)
        self.label_2.setObjectName("label_2")
        self.gridLayout_2.addWidget(self.label_2, 0, 1, 1, 1)
        self.comboProfile = QtWidgets.QComboBox(self.tab)
        self.comboProfile.setObjectName("comboProfile")
        self.gridLayout_2.addWidget(self.comboProfile, 1, 0, 1, 1)
        self.comboFormat = QtWidgets.QComboBox(self.tab)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.comboFormat.sizePolicy().hasHeightForWidth())
        self.comboFormat.setSizePolicy(sizePolicy)
        self.comboFormat.setObjectName("comboFormat")
        self.gridLayout_2.addWidget(self.comboFormat, 1, 1, 1, 1)
        self.verticalLayout.addLayout(self.gridLayout_2)
        self.groupBox_3 = QtWidgets.QGroupBox(self.tab)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth())
        self.groupBox_3.setSizePolicy(sizePolicy)
        self.groupBox_3.setObjectName("groupBox_3")
        self.gridLayout = QtWidgets.QGridLayout(self.groupBox_3)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.radioHypYes = QtWidgets.QRadioButton(self.groupBox_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.radioHypYes.sizePolicy().hasHeightForWidth())
        self.radioHypYes.setSizePolicy(sizePolicy)
        self.radioHypYes.setObjectName("radioHypYes")
        self.horizontalLayout.addWidget(self.radioHypYes)
        self.radioHypNo = QtWidgets.QRadioButton(self.groupBox_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.radioHypNo.sizePolicy().hasHeightForWidth())
        self.radioHypNo.setSizePolicy(sizePolicy)
        self.radioHypNo.setObjectName("radioHypNo")
        self.horizontalLayout.addWidget(self.radioHypNo)
        self.radioHypProfile = QtWidgets.QRadioButton(self.groupBox_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.radioHypProfile.sizePolicy().hasHeightForWidth())
        self.radioHypProfile.setSizePolicy(sizePolicy)
        self.radioHypProfile.setObjectName("radioHypProfile")
        self.horizontalLayout.addWidget(self.radioHypProfile)
        self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
        self.verticalLayout.addWidget(self.groupBox_3)
        self.label_10 = QtWidgets.QLabel(self.tab)
        self.label_10.setObjectName("label_10")
        self.verticalLayout.addWidget(self.label_10)
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        self.lineDestFolder = QtWidgets.QLineEdit(self.tab)
        self.lineDestFolder.setObjectName("lineDestFolder")
        self.horizontalLayout_4.addWidget(self.lineDestFolder)
        self.btnSelectDestFolder = QtWidgets.QPushButton(self.tab)
        self.btnSelectDestFolder.setObjectName("btnSelectDestFolder")
        self.horizontalLayout_4.addWidget(self.btnSelectDestFolder)
        self.verticalLayout.addLayout(self.horizontalLayout_4)
        self.label_5 = QtWidgets.QLabel(self.tab)
        self.label_5.setObjectName("label_5")
        self.verticalLayout.addWidget(self.label_5)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.comboFont = QtWidgets.QComboBox(self.tab)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.comboFont.sizePolicy().hasHeightForWidth())
        self.comboFont.setSizePolicy(sizePolicy)
        self.comboFont.setObjectName("comboFont")
        self.horizontalLayout_2.addWidget(self.comboFont)
        self.btnOpenFontsFolder = QtWidgets.QPushButton(self.tab)
        self.btnOpenFontsFolder.setObjectName("btnOpenFontsFolder")
        self.horizontalLayout_2.addWidget(self.btnOpenFontsFolder)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        spacerItem1 = QtWidgets.QSpacerItem(20, 19, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem1)
        self.gridLayout_6.addLayout(self.verticalLayout, 0, 0, 1, 1)
        self.tabWidget.addTab(self.tab, "")
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.gridLayout_5 = QtWidgets.QGridLayout(self.tab_2)
        self.gridLayout_5.setContentsMargins(8, 8, 8, 8)
        self.gridLayout_5.setObjectName("gridLayout_5")
        self.verticalLayout_6 = QtWidgets.QVBoxLayout()
        self.verticalLayout_6.setObjectName("verticalLayout_6")
        self.groupBox_2 = QtWidgets.QGroupBox(self.tab_2)
        self.groupBox_2.setObjectName("groupBox_2")
        self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox_2)
        self.gridLayout_4.setObjectName("gridLayout_4")
        self.verticalLayout_5 = QtWidgets.QVBoxLayout()
        self.verticalLayout_5.setObjectName("verticalLayout_5")
        self.label_4 = QtWidgets.QLabel(self.groupBox_2)
        self.label_4.setObjectName("label_4")
        self.verticalLayout_5.addWidget(self.label_4)
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.lineKindlePath = QtWidgets.QLineEdit(self.groupBox_2)
        self.lineKindlePath.setObjectName("lineKindlePath")
        self.horizontalLayout_3.addWidget(self.lineKindlePath)
        self.btnSelectKindlePath = QtWidgets.QPushButton(self.groupBox_2)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.btnSelectKindlePath.sizePolicy().hasHeightForWidth())
        self.btnSelectKindlePath.setSizePolicy(sizePolicy)
        self.btnSelectKindlePath.setObjectName("btnSelectKindlePath")
        self.horizontalLayout_3.addWidget(self.btnSelectKindlePath)
        self.verticalLayout_5.addLayout(self.horizontalLayout_3)
        self.checkSyncCovers = QtWidgets.QCheckBox(self.groupBox_2)
        self.checkSyncCovers.setObjectName("checkSyncCovers")
        self.verticalLayout_5.addWidget(self.checkSyncCovers)
        self.label_9 = QtWidgets.QLabel(self.groupBox_2)
        self.label_9.setObjectName("label_9")
        self.verticalLayout_5.addWidget(self.label_9)
        self.lineKindleDocsSubfolder = QtWidgets.QLineEdit(self.groupBox_2)
        self.lineKindleDocsSubfolder.setObjectName("lineKindleDocsSubfolder")
        self.verticalLayout_5.addWidget(self.lineKindleDocsSubfolder)
        self.gridLayout_4.addLayout(self.verticalLayout_5, 0, 0, 1, 1)
        self.verticalLayout_6.addWidget(self.groupBox_2)
        self.groupBox = QtWidgets.QGroupBox(self.tab_2)
        self.groupBox.setObjectName("groupBox")
        self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox)
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.label_3 = QtWidgets.QLabel(self.groupBox)
        self.label_3.setObjectName("label_3")
        self.verticalLayout_2.addWidget(self.label_3)
        self.lineGoogleMail = QtWidgets.QLineEdit(self.groupBox)
        self.lineGoogleMail.setObjectName("lineGoogleMail")
        self.verticalLayout_2.addWidget(self.lineGoogleMail)
        self.label_8 = QtWidgets.QLabel(self.groupBox)
        self.label_8.setObjectName("label_8")
        self.verticalLayout_2.addWidget(self.label_8)
        self.lineGooglePassword = QtWidgets.QLineEdit(self.groupBox)
        self.lineGooglePassword.setEchoMode(QtWidgets.QLineEdit.Password)
        self.lineGooglePassword.setObjectName("lineGooglePassword")
        self.verticalLayout_2.addWidget(self.lineGooglePassword)
        self.label_7 = QtWidgets.QLabel(self.groupBox)
        self.label_7.setObjectName("label_7")
        self.verticalLayout_2.addWidget(self.label_7)
        self.lineKindleMail = QtWidgets.QLineEdit(self.groupBox)
        self.lineKindleMail.setObjectName("lineKindleMail")
        self.verticalLayout_2.addWidget(self.lineKindleMail)
        self.gridLayout_3.addLayout(self.verticalLayout_2, 0, 0, 1, 1)
        self.verticalLayout_6.addWidget(self.groupBox)
        spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_6.addItem(spacerItem2)
        self.gridLayout_5.addLayout(self.verticalLayout_6, 0, 0, 1, 1)
        self.tabWidget.addTab(self.tab_2, "")
        self.tab_3 = QtWidgets.QWidget()
        self.tab_3.setObjectName("tab_3")
        self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.tab_3)
        self.verticalLayout_4.setContentsMargins(8, 8, 8, 8)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        self.checkWriteLog = QtWidgets.QCheckBox(self.tab_3)
        self.checkWriteLog.setObjectName("checkWriteLog")
        self.verticalLayout_4.addWidget(self.checkWriteLog)
        self.checkClearLogAfterExit = QtWidgets.QCheckBox(self.tab_3)
        self.checkClearLogAfterExit.setObjectName("checkClearLogAfterExit")
        self.verticalLayout_4.addWidget(self.checkClearLogAfterExit)
        self.label_6 = QtWidgets.QLabel(self.tab_3)
        self.label_6.setObjectName("label_6")
        self.verticalLayout_4.addWidget(self.label_6)
        self.comboLogLevel = QtWidgets.QComboBox(self.tab_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.comboLogLevel.sizePolicy().hasHeightForWidth())
        self.comboLogLevel.setSizePolicy(sizePolicy)
        self.comboLogLevel.setObjectName("comboLogLevel")
        self.comboLogLevel.addItem("")
        self.comboLogLevel.addItem("")
        self.comboLogLevel.addItem("")
        self.comboLogLevel.addItem("")
        self.verticalLayout_4.addWidget(self.comboLogLevel)
        spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout_4.addItem(spacerItem3)
        self.tabWidget.addTab(self.tab_3, "")
        self.verticalLayout_3.addWidget(self.tabWidget)
        self.buttonBox = QtWidgets.QDialogButtonBox(SettingsDialog)
        self.buttonBox.setLocale(QtCore.QLocale(QtCore.QLocale.Russian, QtCore.QLocale.Russia))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout_3.addWidget(self.buttonBox)

        self.retranslateUi(SettingsDialog)
        self.tabWidget.setCurrentIndex(0)
        self.buttonBox.accepted.connect(SettingsDialog.accept)
        self.buttonBox.rejected.connect(SettingsDialog.reject)
        SettingsDialog.accepted.connect(SettingsDialog.closeAccept)
        self.btnSelectKindlePath.clicked.connect(SettingsDialog.selectKindlePath)
        self.btnOpenFontsFolder.clicked.connect(SettingsDialog.OpenFontsFolder)
        self.btnSelectDestFolder.clicked.connect(SettingsDialog.selectDestPath)
        QtCore.QMetaObject.connectSlotsByName(SettingsDialog)

    def retranslateUi(self, SettingsDialog):
        _translate = QtCore.QCoreApplication.translate
        SettingsDialog.setWindowTitle(_translate("SettingsDialog", "Settings"))
        self.label.setText(_translate("SettingsDialog", "Profile"))
        self.label_2.setText(_translate("SettingsDialog", "Output format"))
        self.groupBox_3.setTitle(_translate("SettingsDialog", "Insert soft hyphens"))
        self.radioHypYes.setText(_translate("SettingsDialog", "Yes"))
        self.radioHypNo.setText(_translate("SettingsDialog", "No"))
        self.radioHypProfile.setText(_translate("SettingsDialog", "Profile default"))
        self.label_10.setText(_translate("SettingsDialog", "Destination folder"))
        self.btnSelectDestFolder.setText(_translate("SettingsDialog", "Select"))
        self.label_5.setText(_translate("SettingsDialog", "Embed font family"))
        self.btnOpenFontsFolder.setText(_translate("SettingsDialog", "Open fonts folder..."))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("SettingsDialog", "Converter"))
        self.groupBox_2.setTitle(_translate("SettingsDialog", "Send To Kindle"))
        self.label_4.setText(_translate("SettingsDialog", "Kindle mount point (if not detected on connect)"))
        self.btnSelectKindlePath.setText(_translate("SettingsDialog", "Select"))
        self.checkSyncCovers.setText(_translate("SettingsDialog", "Syncronize covers"))
        self.label_9.setText(_translate("SettingsDialog", "Place files in folder"))
        self.groupBox.setTitle(_translate("SettingsDialog", "Send via Gmail"))
        self.label_3.setText(_translate("SettingsDialog", "Gmail address"))
        self.label_8.setText(_translate("SettingsDialog", "Gmail password"))
        self.label_7.setText(_translate("SettingsDialog", "Kindle address"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("SettingsDialog", "Kindle"))
        self.checkWriteLog.setText(_translate("SettingsDialog", "Write log"))
        self.checkClearLogAfterExit.setText(_translate("SettingsDialog", "Clear log after exit"))
        self.label_6.setText(_translate("SettingsDialog", "Log level"))
        self.comboLogLevel.setItemText(0, _translate("SettingsDialog", "DEBUG"))
        self.comboLogLevel.setItemText(1, _translate("SettingsDialog", "INFO"))
        self.comboLogLevel.setItemText(2, _translate("SettingsDialog", "ERROR"))
        self.comboLogLevel.setItemText(3, _translate("SettingsDialog", "CRITICAL"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("SettingsDialog", "Log")) class Ui_GDriveDialog(object):
    def setupUi(self, GDriveDialog):
        GDriveDialog.setObjectName("GDriveDialog")
        GDriveDialog.resize(528, 348)
        self.gridLayout = QtWidgets.QGridLayout(GDriveDialog)
        self.gridLayout.setObjectName("gridLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.tree = QtWidgets.QTreeView(GDriveDialog)
        self.tree.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.tree.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
        self.tree.setObjectName("tree")
        self.tree.header().setVisible(False)
        self.verticalLayout.addWidget(self.tree)
        self.buttonBox = QtWidgets.QDialogButtonBox(GDriveDialog)
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Open)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)
        self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)

        self.retranslateUi(GDriveDialog)
        self.buttonBox.accepted.connect(GDriveDialog.accept)
        self.buttonBox.rejected.connect(GDriveDialog.reject)
        QtCore.QMetaObject.connectSlotsByName(GDriveDialog)

    def retranslateUi(self, GDriveDialog):
        _translate = QtCore.QCoreApplication.translate
        GDriveDialog.setWindowTitle(_translate("GDriveDialog", "Open from Google Drive")) class Ui_RenameDialog(object):
    def setupUi(self, RenameDialog):
        RenameDialog.setObjectName("RenameDialog")
        RenameDialog.resize(443, 359)
        self.gridLayout = QtWidgets.QGridLayout(RenameDialog)
        self.gridLayout.setObjectName("gridLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.label = QtWidgets.QLabel(RenameDialog)
        self.label.setObjectName("label")
        self.verticalLayout.addWidget(self.label)
        self.lineAuthorPattern = QtWidgets.QLineEdit(RenameDialog)
        self.lineAuthorPattern.setObjectName("lineAuthorPattern")
        self.verticalLayout.addWidget(self.lineAuthorPattern)
        self.label_3 = QtWidgets.QLabel(RenameDialog)
        self.label_3.setObjectName("label_3")
        self.verticalLayout.addWidget(self.label_3)
        self.lineFilenamePattern = QtWidgets.QLineEdit(RenameDialog)
        self.lineFilenamePattern.setObjectName("lineFilenamePattern")
        self.verticalLayout.addWidget(self.lineFilenamePattern)
        self.radioSameDir = QtWidgets.QRadioButton(RenameDialog)
        self.radioSameDir.setChecked(True)
        self.radioSameDir.setObjectName("radioSameDir")
        self.verticalLayout.addWidget(self.radioSameDir)
        self.radioRenameTo = QtWidgets.QRadioButton(RenameDialog)
        self.radioRenameTo.setObjectName("radioRenameTo")
        self.verticalLayout.addWidget(self.radioRenameTo)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.lineDestFolder = QtWidgets.QLineEdit(RenameDialog)
        self.lineDestFolder.setObjectName("lineDestFolder")
        self.horizontalLayout.addWidget(self.lineDestFolder)
        self.buttonSelectFolder = QtWidgets.QPushButton(RenameDialog)
        self.buttonSelectFolder.setObjectName("buttonSelectFolder")
        self.horizontalLayout.addWidget(self.buttonSelectFolder)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.checkDeleteAfterRename = QtWidgets.QCheckBox(RenameDialog)
        self.checkDeleteAfterRename.setObjectName("checkDeleteAfterRename")
        self.verticalLayout.addWidget(self.checkDeleteAfterRename)
        self.label_2 = QtWidgets.QLabel(RenameDialog)
        self.label_2.setObjectName("label_2")
        self.verticalLayout.addWidget(self.label_2)
        self.textSamples = QtWidgets.QTextEdit(RenameDialog)
        self.textSamples.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
        self.textSamples.setReadOnly(True)
        self.textSamples.setObjectName("textSamples")
        self.verticalLayout.addWidget(self.textSamples)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.btnTest = QtWidgets.QPushButton(RenameDialog)
        self.btnTest.setObjectName("btnTest")
        self.horizontalLayout_2.addWidget(self.btnTest)
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem)
        self.buttonBox = QtWidgets.QDialogButtonBox(RenameDialog)
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.horizontalLayout_2.addWidget(self.buttonBox)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)

        self.retranslateUi(RenameDialog)
        self.buttonBox.accepted.connect(RenameDialog.accept)
        self.buttonBox.rejected.connect(RenameDialog.reject)
        self.radioSameDir.clicked.connect(RenameDialog.switch_copy_to)
        self.radioRenameTo.clicked.connect(RenameDialog.switch_copy_to)
        self.buttonSelectFolder.clicked.connect(RenameDialog.select_dest_dir)
        self.btnTest.clicked.connect(RenameDialog.test)
        QtCore.QMetaObject.connectSlotsByName(RenameDialog)

    def retranslateUi(self, RenameDialog):
        _translate = QtCore.QCoreApplication.translate
        RenameDialog.setWindowTitle(_translate("RenameDialog", "Rename"))
        self.label.setText(_translate("RenameDialog", "Author pattern"))
        self.label_3.setText(_translate("RenameDialog", "Filename pattern"))
        self.radioSameDir.setText(_translate("RenameDialog", "Rename in same directory"))
        self.radioRenameTo.setText(_translate("RenameDialog", "Copy to:"))
        self.buttonSelectFolder.setText(_translate("RenameDialog", "Select"))
        self.checkDeleteAfterRename.setText(_translate("RenameDialog", "Delete source files after rename"))
        self.label_2.setText(_translate("RenameDialog", "Samples:"))
        self.btnTest.setText(_translate("RenameDialog", "Test")) class GuiConfig():
    def __init__(self, config_file):
        self.config_file = os.path.normpath(os.path.abspath(config_file))

        self.converterConfig = {}
        self.currentProfile = None
        self.currentFormat = None
        self.outputFolder = None
        self.lastUsedTargetPath = None
        self.hyphens = None
        self.kindlePath = None
        self.kindleSyncCovers = False
        self.kindleDocsSubfolder = None
        self.lastUsedPath = None
        self.GoogleMail = None
        self.GooglePassword = None
        self.KindleMail = None
        self.embedFontFamily = None
        self.fontDb = None
        self.writeLog = True
        self.logLevel = 'DEBUG'
        self.clearLogAfterExit = False
        self.bookInfoVisible = True
        self.bookInfoSplitterState = None

        self.columns = {}
        self.authorPattern = '#l, #f'
        self.filenamePattern = '#author. #title{ (пер. #translator)}'
        self.renameDestDir = ''
        self.deleteAfterRename = False

        self.geometry = {}
        self.geometry['x'] = None
        self.geometry['y'] = None
        self.geometry['width'] = None
        self.geometry['height'] = None

        if not os.path.exists(self.config_file):
            self.write()

        self.load()


    def load(self):
        config = etree.parse(self.config_file)
        for e in config.getroot():
            if e.tag == 'currentProfile':
                self.currentProfile = e.text

            elif e.tag == 'currentFormat':
                self.currentFormat = e.text

            elif e.tag == 'outputFolder':
                self.outputFolder = e.text

            elif e.tag == 'lastUsedTargetPath':
                self.lastUsedTargetPath = e.text

            elif e.tag == 'embedFontFamily':
                self.embedFontFamily = e.text

            elif e.tag == 'hyphens':
                self.hyphens = e.text

            elif e.tag == 'lastUsedPath':
                self.lastUsedPath = e.text

            elif e.tag == 'kindlePath':
                self.kindlePath = e.text

            elif e.tag == 'kindleDocsSubfolder':
                self.kindleDocsSubfolder = e.text

            elif e.tag == 'writeLog':
                self.writeLog = e.text.lower() == 'true'

            elif e.tag == 'bookInfoVisible':
                self.bookInfoVisible = e.text.lower() == 'true'

            elif e.tag == 'bookInfoSplitterState':
                self.bookInfoSplitterState = e.text

            elif e.tag == 'clearLogAfterExit':
                self.clearLogAfterExit = e.text.lower() == 'true'

            elif e.tag == 'GoogleMail':
                self.GoogleMail = e.text

            elif e.tag == 'GooglePassword':
                self.GooglePassword = e.text

            elif e.tag == 'KindleMail':
                self.KindleMail = e.text

            elif e.tag == 'logLevel':
                self.logLevel = e.text    

            elif e.tag == 'kindleSyncCovers':
                self.kindleSyncCovers = e.text.lower() == 'true'

            elif e.tag == 'columns':
                for c in e:
                    if c.tag == 'column':
                        self.columns[c.attrib['number']] = int(c.text) if c.text else 100
                    
            elif e.tag == 'geometry':
                for g in e:
                    self.geometry[g.tag] = int(g.text) if g.text else None

            elif e.tag == 'authorPattern':
                self.authorPattern = e.text

            elif e.tag == 'filenamePattern':
                self.filenamePattern = e.text

            elif e.tag == 'renameDestDir':
                self.renameDestDir = e.text

            elif e.tag == 'deleteAfterRename':
                self.deleteAfterRename = e.text.lower() == 'true'

    def write(self):
        def number(v):
            return {'number': str(v)}

        E = ElementMaker()

        config = E.settings(
                    E.currentProfile(self.currentProfile) if self.currentProfile else E.currentProfile(),
                    E.currentFormat(self.currentFormat) if self.currentFormat else E.currentFormat(),
                    E.embedFontFamily(self.embedFontFamily) if self.embedFontFamily else E.embedFontFamily(),
                    E.hyphens(self.hyphens) if self.hyphens else E.hyphens(),
                    E.outputFolder(self.outputFolder) if self.outputFolder else E.outputFolder(),
                    E.lastUsedTargetPath(self.lastUsedTargetPath) if self.lastUsedTargetPath else E.lastUsedTargetPath(),
                    E.lastUsedPath(self.lastUsedPath) if self.lastUsedPath else E.lastUsedPath(),
                    E.writeLog(str(self.writeLog)),
                    E.clearLogAfterExit(str(self.clearLogAfterExit)),
                    E.logLevel(self.logLevel) if self.logLevel else E.logLevel(),
                    E.kindlePath(self.kindlePath) if self.kindlePath else E.kindlePath(),
                    E.kindleSyncCovers(str(self.kindleSyncCovers)),
                    E.kindleDocsSubfolder(self.kindleDocsSubfolder) if self.kindleDocsSubfolder else E.kindleDocsSubfolder(),
                    E.GoogleMail(self.GoogleMail) if self.GoogleMail else E.GoogleMail(),
                    E.GooglePassword(self.GooglePassword) if self.GooglePassword else E.GooglePassword(),
                    E.KindleMail(self.KindleMail) if self.KindleMail else E.KindleMail(),
                    E.bookInfoVisible(str(self.bookInfoVisible)),
                    E.bookInfoSplitterState(self.bookInfoSplitterState) if self.bookInfoSplitterState else E.bookInfoSplitterState(),
                    E.authorPattern(self.authorPattern) if self.authorPattern else E.authorPattern(),
                    E.filenamePattern(self.filenamePattern) if self.filenamePattern else E.filenamePattern(),
                    E.renameDestDir(self.renameDestDir) if self.renameDestDir else E.renameDestDir(),
                    E.deleteAfterRename(str(self.deleteAfterRename)),
                    E.columns(
                        *[E.column(str(self.columns[col]), number(col)) for col in self.columns.keys()]
                    ),
                    E.geometry(
                        E.x(str(self.geometry['x'])) if self.geometry['x'] else E.x(),
                        E.y(str(self.geometry['y'])) if self.geometry['y'] else E.y(),
                        E.width(str(self.geometry['width'])) if self.geometry['width'] else E.width(),
                        E.height(str(self.geometry['height'])) if self.geometry['height'] else E.height()
                    )

        )
        config_dir = os.path.dirname(self.config_file)
        if not os.path.exists(config_dir):
            os.makedirs(config_dir)
            
        with codecs.open(self.config_file, "wb") as f:
            f.write(etree.tostring(config, encoding="utf-8", pretty_print=True, xml_declaration=True))
            f.close() class EbookMeta():
    def __init__(self, file):
        self.file = file
        self.book_type = ''

        self.genre = []
        self.author = []
        self.book_title = ''
        self.annotation = None
        self.keywords = None
        self.date = None
        self.coverpage = ''
        self.lang = 'ru'
        self.src_lang = ''
        self.translator = []
        self.sequence = []

        self.coverdata = None
        self.coverpage_href = ''
        self.is_zip = False
        self.encoding = ''
        self.zip_info = ZipInfo()

        if self.file.lower().endswith(('.fb2', '.fb2.zip', '.zip')):
            self.book_type = 'fb2'
        elif self.file.lower().endswith('.epub'):
            self.book_type = 'epub'

        if os.path.splitext(self.file)[1].lower() == '.zip':
            self.is_zip = True

        try:
            if self.book_type == 'fb2':
                if self.is_zip:
                    with ZipFile(self.file) as myzip:
                        # TODO - warn here if len(myzip.infolist) > 1?
                        self.zip_info = myzip.infolist()[0]
                        with myzip.open(self.zip_info, 'r') as myfile:
                            self.tree = etree.parse(BytesIO(myfile.read()), parser=etree.XMLParser(recover=True))
                            self.encoding = self.tree.docinfo.encoding
                else:
                    self.tree = etree.parse(self.file, parser=etree.XMLParser(recover=True))
                    self.encoding = self.tree.docinfo.encoding
            elif self.book_type == 'epub':
                pass
        except:
            self.book_type = ''

    def get_first_genre_name(self):
        genre_name = ''
        genre = self.get_first_genre()
        if genre in genres.keys():
            genre_name = genres[genre]

        return genre_name

    def get_first_genre(self):
        genre_name = ''
        for g in self.genre:
            genre_name = g
            break

        return genre_name

    def get_first_series(self):
        series_name = ''
        series_num = ''

        if self.book_type == 'fb2':
            for series in self.sequence:
                series_name = series.name
                series_num = series.number
                break

        return (series_name, series_num)

    def get_first_series_str(self):
        series = ''
        (name, num) = self.get_first_series()
        if name:
            series = name
        if num and series:
            series = series + ' [{}]'.format(num)

        return series

    def set_series(self, series_name, series_num):
        if self.book_type == 'fb2':
            self.sequence = []
            if series_name:
                cur_series = Sequence()
                cur_series.name = series_name
                cur_series.number = series_num
                self.sequence.append(cur_series)

    def set_authors(self, author_str):
        if self.book_type == 'fb2':
            self.author = []
            if author_str:
                for cur_author_str in author_str.split(','):
                    author_elements = cur_author_str.strip().split()
                    cur_author = Author()
                    if len(author_elements) == 3:
                        cur_author.first_name = author_elements[0]
                        cur_author.middle_name = author_elements[1]
                        cur_author.last_name = author_elements[2]
                    elif len(author_elements) == 2:
                        cur_author.first_name = author_elements[0]
                        cur_author.last_name = author_elements[1]
                    else:
                        cur_author.last_name = cur_author_str.strip()

                    self.author.append(cur_author)

    def set_translators(self, translator_str):
        if self.book_type == 'fb2':
            self.translator = []
            if translator_str:
                for cur_tr_str in translator_str.split(','):
                    tr_elements = cur_tr_str.strip().split()
                    cur_tr = Author()
                    if len(tr_elements) == 3:
                        cur_tr.first_name = tr_elements[0]
                        cur_tr.middle_name = tr_elements[1]
                        cur_tr.last_name = tr_elements[2]
                    elif len(tr_elements) == 2:
                        cur_tr.first_name = tr_elements[0]
                        cur_tr.last_name = tr_elements[1]
                    else:
                        cur_tr.last_name = cur_tr_str.strip()

                    self.translator.append(cur_tr)

    def set_genre(self, genre):
        self.genre = []
        if genre and genre != 'empty':
            self.genre.append(genre)
        
    def get_translators(self):
        author_str = ''

        if self.book_type == 'fb2':
            for author in self.translator:
                if len(author_str) > 0:
                    author_str += ', '

                if author.first_name:
                    author_str += author.first_name
                if author.middle_name:
                    author_str += ' ' + author.middle_name
                if author.last_name:
                    author_str += ' ' + author.last_name

        return author_str.replace('  ', ' ').strip()

    def get_first_translator_lastname(self):
        translator = ''
        for t in self.translator:
            translator = t.last_name
            break
        return translator

    def get_autors(self):
        author_str = ''

        if self.book_type == 'fb2':
            for author in self.author:
                if len(author_str) > 0:
                    author_str += ', '

                if author.first_name:
                    author_str += author.first_name
                if author.middle_name:
                    author_str += ' ' + author.middle_name
                if author.last_name:
                    author_str += ' ' + author.last_name
        elif self.book_type == 'epub':
            author_str = ', '.join(self.author)

        return author_str.replace('  ', ' ').strip()


    def get(self):
        try:
            if self.book_type == 'fb2':
                self._get_fb2_metadata()
            elif self.book_type == 'epub':
                self._get_epub_metadata()
        except:
            self.book_type = ''


    def _get_epub_metadata(self):
        ns = {
            'n':'urn:oasis:names:tc:opendocument:xmlns:container',
            'pkg':'http://www.idpf.org/2007/opf',
            'dc':'http://purl.org/dc/elements/1.1/'
        }

        # prepare to read from the .epub file
        zip = ZipFile(self.file)

        # find the contents metafile
        txt = zip.read('META-INF/container.xml')
        tree = etree.fromstring(txt)
        cfname = tree.xpath('n:rootfiles/n:rootfile/@full-path',namespaces=ns)[0]

        # grab the metadata block from the contents metafile
        cf = zip.read(cfname)
        tree = etree.fromstring(cf)
        p = tree.xpath('/pkg:package/pkg:metadata',namespaces=ns)[0]

        self.author = []

        for e in p:
            if QName(e).localname == 'title':
                self.book_title = e.text
            elif QName(e).localname == 'creator':
                self.author.append(e.text)
            elif QName(e).localname == 'language':
                self.lang = e.text

        # get cover image
        p = tree.xpath('/pkg:package/pkg:manifest',namespaces=ns)[0]
        for e in p:
            if QName(e).localname == 'item':
                if 'id' in e.attrib:
                    if e.attrib['id'] in ['cover.jpg', 'cover-image', 'coverimage']:
                        if 'href' in e.attrib:
                            cover_file = e.attrib['href']
                            try:
                                self.coverdata = zip.read(os.path.join(os.path.split(cfname)[0], cover_file))
                            except:
                                null
                            break


    def _get_fb2_metadata(self):
        ns = {'fb': 'http://www.gribuser.ru/xml/fictionbook/2.0'}
        for title_info in self.tree.xpath('//fb:description/fb:title-info', namespaces=ns):
            for elem in title_info:
                if QName(elem).localname == 'genre':
                    self.genre.append(elem.text)
                elif QName(elem).localname == 'author':
                    author = Author()
                    for e in elem:
                        if QName(e).localname == 'first-name':
                            author.first_name = e.text
                        elif QName(e).localname == 'middle-name':
                            author.middle_name = e.text
                        elif QName(e).localname == 'last-name':
                            author.last_name = e.text
                    self.author.append(author)
                elif QName(elem).localname == 'book-title':
                    self.book_title = elem.text
                elif QName(elem).localname == 'annotation':
                    self.annotation = elem
                elif QName(elem).localname == 'keywords':
                    self.keywords = elem
                elif QName(elem).localname == 'date':
                    self.date = elem
                elif QName(elem).localname == 'coverpage':
                    for e in elem:
                        if QName(e).localname == 'image':
                            for attrib in e.attrib:
                                if QName(attrib).localname == 'href':
                                    self.coverpage = e.attrib[attrib][1:]
                                    self.coverpage_href = attrib
                elif QName(elem).localname == 'lang':
                    self.lang = elem.text
                elif QName(elem).localname == 'src-lang':
                    self.src_lang = elem.text
                elif QName(elem).localname == 'translator':
                    translator = Author()
                    for e in elem:
                        if QName(e).localname == 'first-name':
                            translator.first_name = e.text
                        elif QName(e).localname == 'middle-name':
                            translator.middle_name = e.text
                        elif QName(e).localname == 'last-name':
                            translator.last_name = e.text
                    self.translator.append(translator)                    
                elif QName(elem).localname == 'sequence':
                    seq = Sequence()
                    for a in elem.attrib:
                        if a == 'name':
                            seq.name = elem.attrib[a]
                        elif a == 'number':
                            seq.number = elem.attrib[a]
                    self.sequence.append(seq)

        if self.coverpage:
            for tag in self.tree.xpath('//fb:binary[@id="{0}"]'.format(self.coverpage), namespaces=ns):
                self.coverdata = base64.b64decode(tag.text.encode('ascii'))

    def _create_title_info(self):
        ns = {'fb': 'http://www.gribuser.ru/xml/fictionbook/2.0'}

        title_info = etree.Element('title-info')

        for genre in self.genre:
            etree.SubElement(title_info, 'genre').text = genre

        for author in self.author:
            author_elem = etree.Element('author')
            if author.first_name:
                elem = etree.Element('first-name')
                elem.text = author.first_name
                author_elem.append(elem)
            if author.middle_name:
                elem = etree.Element('middle-name')
                elem.text = author.middle_name
                author_elem.append(elem)
            if author.last_name:
                elem = etree.Element('last-name')
                elem.text = author.last_name
                author_elem.append(elem)
            title_info.append(author_elem)

        etree.SubElement(title_info, 'book-title').text = self.book_title
        if self.annotation is not None:
            title_info.append(self.annotation)
        if self.keywords is not None:
            title_info.append(self.keywords)
        if self.date is not None:
            title_info.append(self.date)
        if self.coverpage:
            elem = etree.SubElement(title_info, 'coverpage')
            etree.SubElement(elem, 'image').attrib[self.coverpage_href] = '#{0}'.format(self.coverpage)
        etree.SubElement(title_info, 'lang').text = self.lang
        if self.src_lang:
            etree.SubElement(title_info, 'src-lang').text = self.src_lang
        for translator in self.translator:            
            tr_elem = etree.Element('translator')
            if translator.first_name:
                elem = etree.Element('first-name')
                elem.text = translator.first_name
                tr_elem.append(elem)
            if translator.middle_name:
                elem = etree.Element('middle-name')
                elem.text = translator.middle_name
                tr_elem.append(elem)
            if translator.last_name:
                elem = etree.Element('last-name')
                elem.text = translator.last_name
                tr_elem.append(elem)
            title_info.append(tr_elem)
        for sequence in self.sequence:
            elem = etree.SubElement(title_info, 'sequence')
            if sequence.name:
                elem.attrib['name'] = sequence.name
            if sequence.number:
                elem.attrib['number'] = sequence.number

        for elem in self.tree.xpath('//fb:description/fb:title-info', namespaces=ns):
            elem.getparent().replace(elem, title_info)

        if self.coverpage and self.coverdata is not None:
            image_elem = None
            for elem in self.tree.xpath('//fb:binary[@id="{0}"]'.format(self.coverpage), namespaces=ns):
                image_elem = elem
                break

            if image_elem is None:
                image_elem = etree.SubElement(self.tree.getroot(), 'binary')
                image_elem.attrib['id'] = self.coverpage
                image_elem.attrib['content-type'] = 'image/jpeg'

            image_elem.text = base64.encodebytes(self.coverdata)

    def write(self):
        if self.book_type == 'fb2':
            self._write_fb2_metadata()

    def _write_fb2_metadata(self):
        self._create_title_info()
        if self.is_zip:
            with ZipFile(self.file, 'w') as myzip:
                myzip.writestr(self.zip_info, etree.tostring(self.tree, encoding=self.encoding, method='xml', xml_declaration=True, pretty_print=True))
        else:
            self.tree.write(self.file, encoding=self.encoding, method='xml', xml_declaration=True, pretty_print=True)

    def get_formatted_authors(self, format_str, short=False):
        authors = []
        if len(self.author) > 0:
            for a in self.author:
                author = format_pattern(format_str, [
                        ('#fi', '' if not a.first_name else a.first_name[0] + '.'),
                        ('#mi', '' if not a.middle_name else a.middle_name[0] + '.'),
                        ('#f', '' if not a.first_name else a.first_name.strip()),
                        ('#m', '' if not a.middle_name else a.middle_name.strip()),
                        ('#l', '' if not a.last_name else a.last_name.strip())                    
                    ])
                authors.append(author)
                if short:
                    break

            if short and len(self.author) > 1:
                return authors[0] + ' и др' if self.lang.lower() == 'ru' else ', et al'
            else:
                return ', '.join(authors)
        else:
            return ''

    def get_file_ext(self):
        if self.file.lower().endswith('.fb2.zip'):
            return 'fb2.zip'
        elif self.file.lower().endswith('.zip'):
            return 'zip'
        elif self.file.lower().endswith('.fb2'):
            return 'fb2'
        return ''

    def replace_na_symbols(self, text):
        for c in ':/\\*?"<>|':
            text = text.replace(c, '_')

        return text

    def meta_to_filename(self, author_format, filename_format, dest_path=None):
        if author_format and filename_format and self.book_type == 'fb2':
            (series_name, series_num) = self.get_first_series()

            name = format_pattern(filename_format, 
                [
                    ('#title', self.replace_na_symbols('' if not self.book_title else self.book_title.strip())),
                    ('#series', self.replace_na_symbols(series_name.strip())),
                    ('#abbrseries', ''.join(word[0] for word in series_name.split()).lower() if series_name else ''),
                    ('#number', str(series_num).strip()),
                    ('#authors', self.get_formatted_authors(author_format, short=False)),
                    ('#author', self.get_formatted_authors(author_format, short=True)),
                    ('#translator', self.get_first_translator_lastname()),
                ])
            ext = self.get_file_ext()
            if not dest_path:
                dest_path = os.path.split(self.file)[0]
            return os.path.normpath(os.path.join(dest_path, '{0}.{1}'.format(name, ext)))
        else:
            return '' class FontDb(object):	
	def __init__(self, path):
		self.fonts_path = path
		self.families = {}
		self.update_db()

	def update_db(self):
		self.families = {}
		
		if os.path.isdir(self.fonts_path):
			for file in os.listdir(self.fonts_path):
				if os.path.splitext(file)[1].lower() in ['.ttf', '.otf']:
					font_file = os.path.join(self.fonts_path, file)
					try:
						font = ImageFont.truetype(font_file, 10)
						if font.font.family not in self.families:
							self.families[font.font.family] = {}
						self.families[font.font.family][font.font.style] = file
					except:
						# Not a font file
						pass class GoogleDrive():
    def __init__(self, credential_file, executable_path):
        self.credential_file = credential_file
        self.executable_path = executable_path

        self.http = httplib2.Http(ca_certs=os.path.join(self.executable_path, 'cacerts.txt'))
        credentials = self.get_credentials()
        self.http = credentials.authorize(self.http)
        self.service = discovery.build('drive', 'v3', http=self.http)

    def list(self, dir_id):
        result = self.service.files().list(
            q="'{0}' in parents and trashed=false".format(dir_id),
            orderBy='folder,name',
            fields='nextPageToken, files(id, name, mimeType)'
            ).execute()

        items = result.get('files', [])
        return items

    def get_credentials(self):
        credential_dir = os.path.split(self.credential_file)[0]
        if not os.path.exists(credential_dir):
            os.makedirs(credential_dir)

        store = Storage(self.credential_file)
        credentials = store.get()
        if not credentials or credentials.invalid:
            flow = client.flow_from_clientsecrets(os.path.join(self.executable_path, CLIENT_SECRET_FILE), SCOPES)
            flow.user_agent = APPLICATION_NAME           
            credentials = tools.run_flow(flow, store, http=self.http)

        return credentials

    def download(self, file_id, path):
        if not os.path.exists(path):
            os.makedirs(path)

        request = self.service.files().get_media(fileId=file_id)
        name = self.service.files().get(fileId=file_id).execute()['name']

        fh = io.BytesIO()
        downloader = MediaIoBaseDownload(fh, request)
        done = False
        while done is False:
            status, done = downloader.next_chunk()

        file_name = os.path.join(path, name)
        f = open(file_name, 'wb')
        f.write(fh.getvalue())

        return file_name class ConverterConfig:

    def __init__(self, config_file):
        self.config_file = config_file

        self.debug = False
        self.log_file = None
        # self.log_file = 'aaaa.log'
        self.original_log_file = None
        # self.log_level = 'Debug'
        self.log_level = 'Info'
        self.console_level = 'Info'
        self.output_format = 'epub'
        self.kindle_compression_level = 1
        self.no_dropcaps_symbols = '\'"-.…0123456789‒–—«»'
        self.transliterate = False
        self.transliterate_author_and_title = False
        self.noMOBIoptimization = False
        self.screen_height = 800
        self.screen_width = 573
        self.default_profile = 'default'

        self.input_dir = None
        self.output_dir = None
        self.output_pattern = None
        self.save_structure = None
        self.delete_source_file = None

        self.apnx = None
        self.characters_per_page = 2300

        self.log = None

        self.profiles = {}
        self.profiles['default'] = {}
        self.profiles['default']['name'] = 'default'
        self.profiles['default']['description'] = 'Default profile'
        self.profiles['default']['outputFormat'] = None
        self.profiles['default']['transliterate'] = None
        self.profiles['default']['screenHeight'] = None
        self.profiles['default']['screenWidth'] = None
        self.profiles['default']['transliterateAuthorAndTitle'] = None
        self.profiles['default']['hyphens'] = True
        self.profiles['default']['hyphensReplaceNBSP'] = True
        self.profiles['default']['dropcaps'] = 'None'
        self.profiles['default']['tocMaxLevel'] = 1000
        self.profiles['default']['tocKindleLevel'] = 2
        self.profiles['default']['tocBeforeBody'] = False
        self.profiles['default']['tocType'] = 'Normal'
        self.profiles['default']['originalcss'] = 'default.css'
        self.profiles['default']['css'] = 'default.css'
        self.profiles['default']['parse_css'] = True
        self.profiles['default']['chapterOnNewPage'] = True
        self.profiles['default']['chapterLevel'] = 100
        self.profiles['default']['authorFormat'] = '#l #f #m'
        self.profiles['default']['bookTitleFormat'] = '(#abbrseries #number) #title'
        self.profiles['default']['annotationTitle'] = 'Annotation'
        self.profiles['default']['tocTitle'] = 'Content'
        self.profiles['default']['notesMode'] = 'default'
        self.profiles['default']['notesBodies'] = 'notes'
        self.profiles['default']['vignettes'] = {}
        self.profiles['default']['vignettes_save'] = {}
        self.profiles['default']['generateTOCPage'] = True
        self.profiles['default']['generateAnnotationPage'] = True
        self.profiles['default']['generateOPFGuide'] = True
        self.profiles['default']['kindleRemovePersonalLabel'] = True
        self.profiles['default']['removePngTransparency'] = False
        self.profiles['default']['generateAPNX'] = None
        self.profiles['default']['charactersPerPage'] = 2300
        self.profiles['default']['seriesPositions'] = 2
        self.profiles['default']['openBookFromCover'] = False
        self.profiles['default']['scaleImages'] = 0.0
        self.profiles['default']['coverDefault'] = 'default_cover.jpg'
        self.profiles['default']['coverStamp'] = 'None'
        self.profiles['default']['outputPattern'] = None

        self.current_profile = {}
        self.mhl = False
        self.recursive = False

        self.send_to_kindle = {}
        self.send_to_kindle['send'] = False
        self.send_to_kindle['deleteSendedBook'] = True
        self.send_to_kindle['smtpServer'] = 'smtp.gmail.com'
        self.send_to_kindle['smtpPort'] = 465
        self.send_to_kindle['smtpLogin'] = '[Your Google Email]'
        self.send_to_kindle['smtpPassword'] = '[Your Google Password]'
        self.send_to_kindle['fromUserEmail'] = '[Your Google Email]'
        self.send_to_kindle['toKindleEmail'] = '[Your Kindle Email]'

        # if no configuration - provide minimum defaults
        if not os.path.exists(self.config_file):

            # configuration
            self.write()

            # default css
            default_css = import_module('modules.default_css')
            default_css_path = os.path.abspath(os.path.join(os.path.dirname(self.config_file), 'default.css'))
            make_dir(default_css_path)
            with codecs.open(default_css_path, "w", 'utf-8') as f:
                f.write(default_css.default_css)
                f.close()

            # default cover
            default_cover_path = os.path.join(get_executable_path(), 'default_cover.jpg')
            if os.path.exists(default_cover_path):
                copy_file(default_cover_path, os.path.abspath(os.path.join(os.path.dirname(self.config_file), 'default_cover.jpg')))

        self._load()

    def _load(self):
        config = etree.parse(self.config_file)
        for e in config.getroot():
            if e.tag == 'debug':
                self.debug = e.text.lower() == 'true'

            elif e.tag == 'logFile':
                if e.text:
                    self.original_log_file = e.text
                    self.log_file = os.path.abspath(os.path.join(os.path.dirname(self.config_file), e.text))

            elif e.tag == 'logLevel':
                self.log_level = e.text

            elif e.tag == 'consoleLevel':
                self.console_level = e.text

            elif e.tag == 'outputFormat':
                self.output_format = e.text

            elif e.tag == 'outputPattern':
                self.output_pattern = e.text

            elif e.tag == 'kindleCompressionLevel':
                self.kindle_compression_level = int(e.text)

            elif e.tag == 'noDropcapsSymbols':
                self.no_dropcaps_symbols = e.text

            elif e.tag == 'transliterate':
                self.transliterate = e.text.lower() == 'true'

            elif e.tag == 'screenWidth':
                self.screen_width = int(e.text)

            elif e.tag == 'screenHeight':
                self.screen_height = int(e.text)

            elif e.tag == 'defaultProfile':
                self.default_profile = e.text

            elif e.tag == 'noMOBIoptimization':
                self.noMOBIoptimization = e.text.lower() == 'true'

            elif e.tag == 'sendToKindle':
                for s in e:
                    if s.tag == 'send':
                        self.send_to_kindle['send'] = s.text.lower() == 'true'

                    elif s.tag == 'deleteSendedBook':
                        self.send_to_kindle['deleteSendedBook'] = s.text.lower() == 'true'

                    elif s.tag == 'smtpServer':
                        self.send_to_kindle['smtpServer'] = s.text

                    elif s.tag == 'smtpPort':
                        self.send_to_kindle['smtpPort'] = int(s.text)

                    elif s.tag == 'smtpLogin':
                        self.send_to_kindle['smtpLogin'] = s.text

                    elif s.tag == 'smtpPassword':
                        self.send_to_kindle['smtpPassword'] = s.text

                    elif s.tag == 'fromUserEmail':
                        self.send_to_kindle['fromUserEmail'] = s.text

                    elif s.tag == 'toKindleEmail':
                        self.send_to_kindle['toKindleEmail'] = s.text

            elif e.tag == 'profiles':
                self.profiles = {}
                for prof in e:
                    prof_name = prof.attrib['name']
                    self.profiles[prof_name] = {}
                    self.profiles[prof_name]['name'] = prof.attrib['name']
                    self.profiles[prof_name]['description'] = prof.attrib['description']
                    self.profiles[prof_name]['vignettes'] = {}
                    self.profiles[prof_name]['generateTOCPage'] = True
                    self.profiles[prof_name]['generateAnnotationPage'] = True
                    self.profiles[prof_name]['generateOPFGuide'] = True
                    self.profiles[prof_name]['tocType'] = 'Normal'
                    self.profiles[prof_name]['kindleRemovePersonalLabel'] = True
                    self.profiles[prof_name]['removePngTransparency'] = False
                    self.profiles[prof_name]['generateAPNX'] = None
                    self.profiles[prof_name]['charactersPerPage'] = 2300
                    self.profiles[prof_name]['tocMaxLevel'] = 1000
                    self.profiles[prof_name]['tocKindleLevel'] = 2
                    self.profiles[prof_name]['seriesPositions'] = 2
                    self.profiles[prof_name]['chapterLevel'] = 100
                    self.profiles[prof_name]['openBookFromCover'] = False
                    self.profiles[prof_name]['coverStamp'] = 'None'
                    self.profiles[prof_name]['coverTextFont'] = None
                    self.profiles[prof_name]['scaleImages'] = 0.0
                    self.profiles[prof_name]['coverDefault'] = os.path.abspath(os.path.join(os.path.dirname(self.config_file), 'default_cover.jpg'))

                    for p in prof:
                        if p.tag == 'hyphens':
                            self.profiles[prof_name]['hyphens'] = p.text.lower() == 'true'

                        elif p.tag == 'hyphensReplaceNBSP':
                            self.profiles[prof_name]['hyphensReplaceNBSP'] = p.text.lower() == 'true'

                        elif p.tag == 'dropcaps':
                            self.profiles[prof_name]['dropcaps'] = p.text

                        elif p.tag == 'outputFormat':
                            self.profiles[prof_name]['outputFormat'] = p.text

                        elif p.tag == 'outputPattern':
                            self.profiles[prof_name]['outputPattern'] = p.text

                        elif p.tag == 'transliterate':
                            self.profiles[prof_name]['transliterate'] = p.text.lower() == 'true'

                        elif p.tag == 'screenWidth':
                            self.profiles[prof_name]['screenWidth'] = int(p.text)

                        elif p.tag == 'screenHeight':
                            self.profiles[prof_name]['screenHeight'] = int(p.text)

                        elif p.tag == 'transliterateAuthorAndTitle':
                            self.profiles[prof_name]['transliterateAuthorAndTitle'] = p.text.lower() == 'true'

                        elif p.tag == 'tocMaxLevel':
                            self.profiles[prof_name]['tocMaxLevel'] = int(p.text)

                        elif p.tag == 'tocKindleLevel':
                            self.profiles[prof_name]['tocKindleLevel'] = int(p.text)

                        elif p.tag == 'generateTOCPage':
                            self.profiles[prof_name]['generateTOCPage'] = p.text.lower() == 'true'

                        elif p.tag == 'flatTOC':
                            print("***WARNING: <flatTOC> is ignored, use <tocType> instead!")

                        elif p.tag == 'tocType':
                            if p.text.lower() in ['flat', 'kindle', 'normal']:
                                self.profiles[prof_name]['tocType'] = p.text.lower()

                        elif p.tag == 'kindleRemovePersonalLabel':
                            self.profiles[prof_name]['kindleRemovePersonalLabel'] = p.text.lower() == 'true'

                        elif p.tag == 'removePngTransparency':
                            self.profiles[prof_name]['removePngTransparency'] = p.text.lower() == 'true'

                        elif p.tag == 'generateAPNX':
                            if p.text.lower() in ['eink', 'pc']:
                                self.profiles[prof_name]['generateAPNX'] = p.text.lower()

                        elif p.tag == 'charactersPerPage':
                            self.profiles[prof_name]['charactersPerPage'] = int(p.text)

                        elif p.tag == 'seriesPositions':
                            self.profiles[prof_name]['seriesPositions'] = int(p.text)

                        elif p.tag == 'generateAnnotationPage':
                            self.profiles[prof_name]['generateAnnotationPage'] = p.text.lower() == 'true'

                        elif p.tag == 'generateOPFGuide':
                            self.profiles[prof_name]['generateOPFGuide'] = p.text.lower() == 'true'

                        elif p.tag == 'tocBeforeBody':
                            self.profiles[prof_name]['tocBeforeBody'] = p.text.lower() == 'true'

                        elif p.tag == 'css':
                            self.profiles[prof_name]['originalcss'] = p.text
                            self.profiles[prof_name]['css'] = os.path.abspath(os.path.join(os.path.dirname(self.config_file), p.text))
                            if 'parse' in p.attrib:
                                self.profiles[prof_name]['parse_css'] = p.attrib['parse'].lower() == 'true'
                            else:
                                self.profiles[prof_name]['parse_css'] = True

                        elif p.tag == 'xslt':
                            self.profiles[prof_name]['xslt'] = os.path.abspath(os.path.join(os.path.dirname(self.config_file), p.text))

                        elif p.tag == 'chapterOnNewPage':
                            self.profiles[prof_name]['chapterOnNewPage'] = p.text.lower() == 'true'

                        elif p.tag == 'chapterLevel':
                            self.profiles[prof_name]['chapterLevel'] = int(p.text)

                        elif p.tag == 'authorFormat':
                            self.profiles[prof_name]['authorFormat'] = p.text

                        elif p.tag == 'bookTitleFormat':
                            self.profiles[prof_name]['bookTitleFormat'] = p.text

                        elif p.tag == 'annotationTitle':
                            self.profiles[prof_name]['annotationTitle'] = p.text

                        elif p.tag == 'tocTitle':
                            self.profiles[prof_name]['tocTitle'] = p.text

                        elif p.tag == 'notesMode':
                            self.profiles[prof_name]['notesMode'] = p.text

                        elif p.tag == 'notesBodies':
                            self.profiles[prof_name]['notesBodies'] = p.text

                        elif p.tag == 'vignettes':
                            self.profiles[prof_name]['vignettes'] = {}
                            self.profiles[prof_name]['vignettes_save'] = {}

                            for vignettes in p:
                                vignettes_level = vignettes.attrib['level']
                                vign_arr = {}
                                vign_arr_save = {}

                                for v in vignettes:
                                    vign_arr[v.tag] = None if v.text.lower() == 'none' else os.path.abspath(os.path.join(os.path.dirname(self.config_file), v.text))
                                    vign_arr_save[v.tag] = None if v.text.lower() == 'none' else v.text

                                self.profiles[prof_name]['vignettes'][vignettes_level] = vign_arr
                                self.profiles[prof_name]['vignettes_save'][vignettes_level] = vign_arr_save

                        elif p.tag == 'openBookFromCover':
                            self.profiles[prof_name]['openBookFromCover'] = p.text.lower() == 'true'

                        elif p.tag == 'coverStamp':
                            self.profiles[prof_name]['coverStamp'] = p.text

                        elif p.tag == 'coverDefault':
                            self.profiles[prof_name]['coverDefault'] = os.path.abspath(os.path.join(os.path.dirname(self.config_file), p.text))

                        elif p.tag == 'coverTextFont':
                            self.profiles[prof_name]['coverTextFont'] = os.path.abspath(os.path.join(os.path.dirname(self.config_file), p.text))

                        elif p.tag == 'scaleImages':
                            self.profiles[prof_name]['scaleImages'] = float(p.text)

    def _getVignette(self, vignette_arr):
        for v in vignette_arr:
            print(v)

    def _getVignettes(self, profile):
        result = []

        try:
            for v in self.profiles[profile]['vignettes_save']:
                result.append(
                    E('vignette',
                      E('beforeTitle', self.profiles[profile]['vignettes_save'][v]['beforeTitle'] if self.profiles[profile]['vignettes_save'][v]['beforeTitle'] else 'None'),
                      E('afterTitle', self.profiles[profile]['vignettes_save'][v]['afterTitle'] if self.profiles[profile]['vignettes_save'][v]['afterTitle'] else 'None'),
                      E('chapterEnd', self.profiles[profile]['vignettes_save'][v]['chapterEnd'] if self.profiles[profile]['vignettes_save'][v]['chapterEnd'] else 'None'),
                      level=v))

        except:
            pass

        return result

    def _getProfiles(self):
        result = []
        for p in self.profiles:
            result.append(
                E('profile',
                  E('hyphens', str(self.profiles[p]['hyphens'])),
                  E('hyphensReplaceNBSP', str(self.profiles[p]['hyphensReplaceNBSP'])),
                  E('dropcaps', str(self.profiles[p]['dropcaps'])),
                  E('tocMaxLevel', str(self.profiles[p]['tocMaxLevel'])),
                  E('tocKindleLevel', str(self.profiles[p]['tocKindleLevel'])),
                  E('tocBeforeBody', str(self.profiles[p]['tocBeforeBody'])),
                  E('tocType', str(self.profiles[p]['tocType'])),
                  E('css', self.profiles[p]['originalcss'], parse=str(self.profiles[p]['parse_css'])),
                  E('chapterOnNewPage', str(self.profiles[p]['chapterOnNewPage'])),
                  E('chapterLevel', str(self.profiles[p]['chapterLevel'])),
                  E('authorFormat', self.profiles[p]['authorFormat']),
                  E('bookTitleFormat', self.profiles[p]['bookTitleFormat']),
                  E('annotationTitle', self.profiles[p]['annotationTitle']),
                  E('tocTitle', self.profiles[p]['tocTitle']),
                  E('notesMode', self.profiles[p]['notesMode']),
                  E('notesBodies', self.profiles[p]['notesBodies']),
                  E('generateTOCPage', str(self.profiles[p]['generateTOCPage'])),
                  E('generateAnnotationPage', str(self.profiles[p]['generateAnnotationPage'])),
                  E('generateOPFGuide', str(self.profiles[p]['generateOPFGuide'])),
                  E('kindleRemovePersonalLabel', str(self.profiles[p]['kindleRemovePersonalLabel'])),
                  E('removePngTransparency', str(self.profiles[p]['removePngTransparency'])),
                  E('charactersPerPage', str(self.profiles[p]['charactersPerPage'])),
                  E('seriesPositions', str(self.profiles[p]['seriesPositions'])),
                  E('openBookFromCover', str(self.profiles[p]['openBookFromCover'])),
                  E('coverDefault', str(self.profiles[p]['coverDefault'])),
                  E('coverStamp', str(self.profiles[p]['coverStamp'])),
                  E('vignettes', *self._getVignettes(p)),
                  name=p,
                  description=self.profiles[p]['description']))

        return result

    def setCurrentProfile(self, profile_name):
        try:
            self.current_profile = self.profiles[profile_name]
        except:
            print('***WARNING: Unable to locate profile "{0}". Using default one.'.format(profile_name))
            self.current_profile = self.profiles[self.default_profile]

        if 'outputFormat' in self.current_profile:
            self.output_format = self.current_profile['outputFormat']

        if 'outputPattern' in self.current_profile:
            self.output_pattern = self.current_profile['outputPattern']

        if 'transliterate' in self.current_profile:
            self.transliterate = self.current_profile['transliterate']

        if 'screenWidth' in self.current_profile:
            self.screen_width = self.current_profile['screenWidth']

        if 'screenHeight' in self.current_profile:
            self.screen_height = self.current_profile['screenHeight']

        if 'transliterateAuthorAndTitle' in self.current_profile:
            self.transliterate_author_and_title = self.current_profile['transliterateAuthorAndTitle']

        if 'generateAPNX' in self.current_profile:
            self.apnx = self.current_profile['generateAPNX']

        if 'charactersPerPage' in self.current_profile:
            self.characters_per_page = self.current_profile['charactersPerPage']

    def write(self):
        # yapf: disable
        config = E('settings',
            # pylint: disable=C0330
            E('debug', str(self.debug)),
            E('logFile', self.original_log_file) if self.original_log_file else E('logFile'),
            E('logLevel', self.log_level),
            E('consoleLevel', self.console_level),
            E('outputFormat', self.output_format),
            E('kindleCompressionLevel', str(self.kindle_compression_level)),
            E('noDropcapsSymbols', self.no_dropcaps_symbols),
            E('transliterate', str(self.transliterate)),
            E('screenWidth', str(self.screen_width)),
            E('screenHeight', str(self.screen_height)),
            E('defaultProfile', self.default_profile),
            E('noMOBIoptimization', str(self.noMOBIoptimization)),
            E('profiles', *self._getProfiles()),
            E('sendToKindle',
                E('send', str(self.send_to_kindle['send'])),
                E('deleteSendedBook', str(self.send_to_kindle['deleteSendedBook'])),
                E('smtpServer', self.send_to_kindle['smtpServer']),
                E('smtpPort', str(self.send_to_kindle['smtpPort'])),
                E('smtpLogin', self.send_to_kindle['smtpLogin']),
                E('smtpPassword', self.send_to_kindle['smtpPassword']) if self.send_to_kindle['smtpPassword'] else E('smtpPassword'),
                E('fromUserEmail', self.send_to_kindle['fromUserEmail']),
                E('toKindleEmail', self.send_to_kindle['toKindleEmail'])))
        # yapf: enable

        config_dir = os.path.dirname(self.config_file)
        if not os.path.exists(config_dir):
            os.makedirs(config_dir)

        with codecs.open(self.config_file, "w", 'utf-8') as f:
            f.write(str(etree.tostring(config, encoding="utf-8", pretty_print=True, xml_declaration=True), 'utf-8'))
            f.close() class SendToKindle:
    def __init__(self):
        self.smtp_server = None
        self.smtp_port = 0
        self.smtp_login = None
        self.user_email = None
        self.kindle_email = None
        self.smtp_password = None
        self.convert = False

        self.parser = None

    def send_mail(self, files):
        msg = MIMEMultipart()
        msg['From'] = self.user_email
        msg['To'] = self.kindle_email
        msg['Subject'] = 'Convert' if self.convert else 'Sent to Kindle'
        msg.preamble = 'This email has been automatically sent by fb2mobi tool'

        for file_path in files:
            fname = os.path.basename(file_path)
            msg.attach(MIMEApplication(open(file_path, 'rb').read(), Content_Disposition='attachment; filename="%s"' % fname, Name=fname))

        mail_server = smtplib.SMTP(host=self.smtp_server, port=self.smtp_port)
        mail_server.starttls()
        mail_server.login(self.smtp_login, self.smtp_password)
        mail_server.sendmail(self.user_email, self.kindle_email, msg.as_string())
        mail_server.quit() def format_pattern(s, seq):

    def replace_keyword(pict, k, v):
        if pict.count(k) > 0:
            return pict.replace(k, v), True if v else False
        return pict, False

    def replace_keywords(pict, seq):
        expanded = False
        for (k, v) in seq:
            pict, ok = replace_keyword(pict, k, v)
            expanded = expanded or ok
        if not expanded:
            return ''
        return pict

    p_o = -1
    p_c = -1

    # Hack - I do not want to write real parser
    pps = s.replace(r'\{', chr(1)).replace(r'\}', chr(2))

    for i, sym in enumerate(pps):
        if sym == '{':
            p_o = i
        elif sym == '}':
            p_c = i
            break

    if p_o >= 0 and p_c > 0 and p_o < p_c:
        pps = format_pattern(pps[0:p_o] + replace_keywords(pps[p_o + 1:p_c], seq) + pps[p_c + 1:], seq)
    else:
        pps = replace_keywords(pps, seq)

    return pps.replace(chr(1), '{').replace(chr(2), '}') def copy_file(src, dest):
    make_dir(dest)
    shutil.copyfile(src, dest)
import sys
import os
import cssutils
import codecs
import time
import subprocess
import webbrowser
import logging
import tempfile
import shutil
import ui.images_rc
import ui.ui_version
import ui.genres
import modules.default_css
import fb2mobi
import synccovers
import version
            import psutil
from PyQt5.QtWidgets import (QApplication, QMainWindow, QFileDialog, QTreeWidgetItem, 
                            QMessageBox, QDialog, QWidget, QLabel, QAbstractItemView, 
                            QSizePolicy, QAction, QMenu, QProgressDialog)
from PyQt5.QtGui import (QIcon, QPixmap, QPainter, QFont, QFontMetrics, 
                        QStandardItem, QStandardItemModel)
from PyQt5.QtCore import (QObject, QThread, pyqtSignal, QEvent, Qt, QTranslator, 
                        QLocale, QCoreApplication, QTimer, QSize, QRectF, QByteArray, 
                        QBuffer, QPoint)
from ui.MainWindow import Ui_MainWindow
from ui.AboutDialog import Ui_AboutDialog
from ui.SettingsDialog import Ui_SettingsDialog
from ui.OpenGDriveDialog import Ui_GDriveDialog
from ui.RenameDialog import Ui_RenameDialog
from ui.gui_config import GuiConfig
from ui.ebookmeta import EbookMeta
from ui.fontdb import FontDb
from ui.gdrive import GoogleDrive
from modules.config import ConverterConfig
from modules.sendtokindle import SendToKindle
from modules.utils import format_pattern, copy_file

            if action == actionLoad:
                fileDialog = QFileDialog(self, _translate('fb2mobi-gui', 'Select book cover'))
                fileDialog.setFileMode(QFileDialog.ExistingFile)
                fileDialog.setNameFilters([_translate('fb2mobi-gui', 'Image files (*.png *.jpg *.bmp)')])

                if fileDialog.exec_():
                    file_list = fileDialog.selectedFiles()
                    self.loadNewCoverFormFile(file_list[0])
            elif action == actionSave:
                fileDialog = QFileDialog(self, _translate('fb2mobi-gui', 'Save cover as'))
                fileDialog.setAcceptMode(QFileDialog.AcceptSave)
                fileDialog.setFileMode(QFileDialog.AnyFile)
                fileDialog.setNameFilters([_translate('fb2mobi-gui', 'Image files (*.png *.jpg *.bmp)')])

                if fileDialog.exec_():
                    file_list = fileDialog.selectedFiles()
                    self.book_cover.save(file_list[0],
                                         os.path.splitext(file_list[0])[1][1:].upper())

            elif action == actionClear:
                self.book_cover = None
                self.imgBookCover.clear()

    def selectAllAction(self):
        self.treeFileList.selectAll()

    def deleteRecAction(self):
        for item in self.treeFileList.selectedItems():
            self.rootFileList.removeChild(item)

    def deleteAllAction(self):
        if self.treeFileList.topLevelItemCount() > 0:
            msg = QMessageBox(self)
            msg.setIcon(QMessageBox.Question)
            msg.setWindowTitle(_translate('fb2mobi', 'Delete from list'))
            msg.setText(_translate('fb2mobi', 'Delete all files from list?'))
            msg.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
            if msg.exec_() == QMessageBox.Yes:
                self.treeFileList.clear()

    def openLog(self):
        self.openFile(self.log_file)

    def generateFontCSS(self):
        # Список стилей для встраивания шрифтов
        style_rules = ['.titleblock', '.text-author', 'p', 'p.title', '.cite', '.poem', '.table th', '.table td', '.annotation', 'body']

        css_string = modules.default_css.gui_default_css
        css = cssutils.parseString(css_string)

        font_regular = ''
        font_italic = ''
        font_bold = ''
        font_bolditalic = ''

        if 'Regular' in self.gui_config.fontDb.families[self.gui_config.embedFontFamily]:
            font_regular = self.gui_config.fontDb.families[self.gui_config.embedFontFamily]['Regular']

        if 'Italic' in self.gui_config.fontDb.families[self.gui_config.embedFontFamily]:
            font_italic = self.gui_config.fontDb.families[self.gui_config.embedFontFamily]['Italic']
        else:
            font_italic = font_regular

        if 'Bold' in self.gui_config.fontDb.families[self.gui_config.embedFontFamily]:
            font_bold = self.gui_config.fontDb.families[self.gui_config.embedFontFamily]['Bold']
        else:
            font_bold = font_regular

        if 'Bold Italic' in self.gui_config.fontDb.families[self.gui_config.embedFontFamily]:
            font_bolditalic = self.gui_config.fontDb.families[self.gui_config.embedFontFamily]['Bold Italic']
        else:
            font_bolditalic = font_italic

        css.add('@font-face {{ font-family: "para"; src: url("fonts/{0}"); }}'.format(font_regular))
        css.add('@font-face {{ font-family: "para"; src: url("fonts/{0}"); font-style: italic; }}'.format(font_italic))
        css.add('@font-face {{ font-family: "para"; src: url("fonts/{0}"); font-weight: bold; }}'.format(font_bold))
        css.add('@font-face {{ font-family: "para"; src: url("fonts/{0}"); font-style: italic; font-weight: bold; }}'.format(font_bolditalic))

        found_body = False

        for rule in css:
            if rule.type == rule.STYLE_RULE:
                if rule.selectorText in style_rules:
                    rule.style['font-family'] = '"para"'
                if rule.selectorText == 'body':
                    found_body = True

        # Добавим стиль для
        if not found_body:
            css.add('body {font-family: "para"; line-height: 100%; }')

        css_path = os.path.join(os.path.dirname(self.config_file), 'profiles')
        if not os.path.exists(css_path):
            os.makedirs(css_path)

        with codecs.open(os.path.join(css_path, '_font.css'), 'w', 'utf-8') as f:
            f.write(str(css.cssText, 'utf-8'))

    def loadNewCoverFormFile(self, img_file):
        self.book_cover = QPixmap(img_file)
        self.displayCoverThumbmail(self.book_cover)

    def clearBookInfo(self):
        self.book_cover = None
        self.imgBookCover.clear()
        self.editAuthor.clear()
        self.editTitle.clear()
        self.editSeries.clear()
        self.comboGenres.setCurrentIndex(0)
        self.editSeriesNumber.clear()
        self.editBookLanguage.clear()
        self.editTranslator.clear()

    def saveBookInfo(self):
        selected_items = self.treeFileList.selectedItems()
        if len(selected_items) == 1:
            QApplication.setOverrideCursor(Qt.BusyCursor)

            item = selected_items[0]

            meta = EbookMeta(item.text(4))