diff --git a/.github/workflows/auto format.yml b/.github/workflows/auto format.yml index 68fade999..b63931b24 100644 --- a/.github/workflows/auto format.yml +++ b/.github/workflows/auto format.yml @@ -38,6 +38,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 2 - - run: npm ci + - run: | + npm install -g prettier - run: npx prettier . --write - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 9e26dfeeb..000000000 --- a/.prettierrc.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index c49f34dbd..000000000 --- a/package-lock.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "goldendict-ng", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "devDependencies": { - "prettier": "3" - } - }, - "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 80758a8b7..000000000 --- a/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "devDependencies": { - "prettier": "3" - } -} diff --git a/src/common/dictionary_icon_name.cc b/src/common/dictionary_icon_name.cc index add0fc7c4..d081f7deb 100644 --- a/src/common/dictionary_icon_name.cc +++ b/src/common/dictionary_icon_name.cc @@ -16,17 +16,16 @@ QString Icons::DictionaryIconName::getIconName( const QString & dictionaryName ) //get the first character of the dictionary name QString name = dictionaryName.at( 0 ).toUpper(); auto it1 = _iconDictionaryNames.contains( name ); - std::vector< QString > vector = {}; if ( it1 ) { - vector = _iconDictionaryNames.value( name ); - vector.emplace_back( dictionaryName ); + auto vector = _iconDictionaryNames.value( name ); + vector++; + _iconDictionaryNames.insert( name, vector ); } else { - vector.emplace_back( dictionaryName ); - _iconDictionaryNames.insert( name, vector ); + _iconDictionaryNames.insert( name, 1 ); } - name = name + QString::number( vector.size() ); + name = name + QString::number( _iconDictionaryNames.value( name ) ); _dictionaryIconNames.insert( dictionaryName, name ); return name; } \ No newline at end of file diff --git a/src/common/dictionary_icon_name.hh b/src/common/dictionary_icon_name.hh index 6906044b0..0f022ef6e 100644 --- a/src/common/dictionary_icon_name.hh +++ b/src/common/dictionary_icon_name.hh @@ -12,7 +12,7 @@ namespace Icons { class DictionaryIconName { //map icon name to dictionary names; - QMap< QString, std::vector< QString > > _iconDictionaryNames; + QMap< QString, int > _iconDictionaryNames; //map dictionary name to icon name; QMap< QString, QString > _dictionaryIconNames; diff --git a/src/common/utils.hh b/src/common/utils.hh index 15a4d35ee..69c7e133c 100644 --- a/src/common/utils.hh +++ b/src/common/utils.hh @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "filetype.hh" #include @@ -356,6 +357,45 @@ string basename( string const & ); void removeDirectory( QString const & directory ); void removeDirectory( string const & directory ); + +inline QString findFirstExistingFile( std::initializer_list< QString > filePaths ) +{ + for ( const QString & filePath : filePaths ) { + if ( QFileInfo::exists( filePath ) ) { + return filePath; + } + } + return QString(); +} + +inline std::string findFirstExistingFile( std::initializer_list< std::string > filePaths ) +{ + for ( const std::string & filePath : filePaths ) { + auto fp = QString::fromStdString( filePath ); + if ( QFileInfo::exists( fp ) ) { + return filePath; + } + } + return {}; +} + +inline bool anyExistingFile( std::initializer_list< std::string > filePaths ) +{ + for ( const std::string & filePath : filePaths ) { + auto fp = QString::fromStdString( filePath ); + if ( QFileInfo::exists( fp ) ) { + return true; + } + } + return false; +} + +// used for std::string and char* +inline bool exists( std::string_view filename ) noexcept +{ + return QFileInfo::exists( QString::fromUtf8( filename.data(), filename.size() ) ); +} + } // namespace Fs namespace WebSite { diff --git a/src/dict/dictionary.cc b/src/dict/dictionary.cc index d05df52c6..51772923d 100644 --- a/src/dict/dictionary.cc +++ b/src/dict/dictionary.cc @@ -310,7 +310,7 @@ bool Class::loadIconFromText( const QString & iconUrl, QString const & text ) QFont font = painter.font(); //the orderNum should be a little smaller than the icon - font.setPixelSize( iconSize * 0.6 ); + font.setPixelSize( iconSize * 0.8 ); font.setWeight( QFont::Bold ); painter.setFont( font ); @@ -328,12 +328,9 @@ bool Class::loadIconFromText( const QString & iconUrl, QString const & text ) font.setPixelSize( iconSize * 0.4 ); QFontMetrics fm1( font ); const QString & orderNum = abbrName.mid( 1 ); - int orderNumberWidth = fm1.horizontalAdvance( orderNum ); painter.setFont( font ); - painter.drawText( rectangle.x() + rectangle.width() - orderNumberWidth * 1.2, - rectangle.y() + rectangle.height(), - orderNum ); + painter.drawText( rectangle, Qt::AlignRight | Qt::AlignBottom, orderNum ); painter.end(); diff --git a/src/dict/dsl.cc b/src/dict/dsl.cc index eb5dc9785..ae6117171 100644 --- a/src/dict/dsl.cc +++ b/src/dict/dsl.cc @@ -1604,55 +1604,29 @@ void DslResourceRequest::run() string n = dict.getContainingFolder().toStdString() + Utils::Fs::separator() + resourceName; - qDebug( "dsl resource name is %s", n.c_str() ); - + auto fp = Utils::Fs::findFirstExistingFile( + { n, dict.getResourceDir1() + resourceName, dict.getResourceDir2() + resourceName } ); + qDebug( "found dsl resource name is %s", fp.c_str() ); try { - try { - QMutexLocker _( &dataMutex ); + QMutexLocker _( &dataMutex ); - File::loadFromFile( n, data ); + if ( !fp.empty() ) { + File::loadFromFile( fp, data ); } - catch ( File::exCantOpen & ) { - n = dict.getResourceDir1() + resourceName; - try { - QMutexLocker _( &dataMutex ); - - File::loadFromFile( n, data ); - } - catch ( File::exCantOpen & ) { - n = dict.getResourceDir2() + resourceName; - - try { - QMutexLocker _( &dataMutex ); - - File::loadFromFile( n, data ); - } - catch ( File::exCantOpen & ) { - // Try reading from zip file - - if ( dict.resourceZip.isOpen() ) { - QMutexLocker _( &dataMutex ); - - if ( !dict.resourceZip.loadFile( Text::toUtf32( resourceName ), data ) ) { - throw; // Make it fail since we couldn't read the archive - } - } - else { - throw; - } - } + else if ( dict.resourceZip.isOpen() ) { + if ( !dict.resourceZip.loadFile( Text::toUtf32( resourceName ), data ) ) { + throw std::runtime_error( "Failed to load file from resource zip" ); } } + else { + throw std::runtime_error( "Resource zip not opened" ); + } if ( Filetype::isNameOfTiff( resourceName ) ) { // Convert it - - QMutexLocker _( &dataMutex ); GdTiff::tiff2img( data ); } - QMutexLocker _( &dataMutex ); - hasAnyData = true; } catch ( std::exception & ex ) { @@ -1723,13 +1697,14 @@ vector< sptr< Dictionary::Class > > makeDictionaries( vector< string > const & f string baseName = ( fileName[ fileName.size() - 4 ] == '.' ) ? string( fileName, 0, fileName.size() - 4 ) : string( fileName, 0, fileName.size() - 7 ); - string abrvFileName; + string abrvFileName = Utils::Fs::findFirstExistingFile( { baseName + "_abrv.dsl", + baseName + "_abrv.dsl.dz", + baseName + "_ABRV.DSL", + baseName + "_ABRV.DSL.DZ", + baseName + "_ABRV.DSL.dz" } ); - if ( File::tryPossibleName( baseName + "_abrv.dsl", abrvFileName ) - || File::tryPossibleName( baseName + "_abrv.dsl.dz", abrvFileName ) - || File::tryPossibleName( baseName + "_ABRV.DSL", abrvFileName ) - || File::tryPossibleName( baseName + "_ABRV.DSL.DZ", abrvFileName ) - || File::tryPossibleName( baseName + "_ABRV.DSL.dz", abrvFileName ) ) { + //check empty string + if ( abrvFileName.size() ) { dictFiles.push_back( abrvFileName ); } @@ -1739,12 +1714,12 @@ vector< sptr< Dictionary::Class > > makeDictionaries( vector< string > const & f // See if there's a zip file with resources present. If so, include it. - string zipFileName; + string zipFileName = Utils::Fs::findFirstExistingFile( { baseName + ".dsl.files.zip", + baseName + ".dsl.dz.files.zip", + baseName + ".DSL.FILES.ZIP", + baseName + ".DSL.DZ.FILES.ZIP" } ); - if ( File::tryPossibleZipName( baseName + ".dsl.files.zip", zipFileName ) - || File::tryPossibleZipName( baseName + ".dsl.dz.files.zip", zipFileName ) - || File::tryPossibleZipName( baseName + ".DSL.FILES.ZIP", zipFileName ) - || File::tryPossibleZipName( baseName + ".DSL.DZ.FILES.ZIP", zipFileName ) ) { + if ( !zipFileName.empty() ) { dictFiles.push_back( zipFileName ); } diff --git a/src/dict/mdx.cc b/src/dict/mdx.cc index 35c769f3f..65404c590 100644 --- a/src/dict/mdx.cc +++ b/src/dict/mdx.cc @@ -1201,7 +1201,8 @@ void MdxDictionary::loadResourceFile( const std::u32string & resourceName, vecto newResourceName.insert( 0, 1, '\\' ); } // local file takes precedence - if ( string fn = getContainingFolder().toStdString() + Utils::Fs::separator() + u8ResourceName; File::exists( fn ) ) { + if ( string fn = getContainingFolder().toStdString() + Utils::Fs::separator() + u8ResourceName; + Utils::Fs::exists( fn ) ) { File::loadFromFile( fn, data ); return; } @@ -1342,7 +1343,7 @@ vector< sptr< Dictionary::Class > > makeDictionaries( vector< string > const & f initializing.indexingDictionary( title ); for ( vector< string >::const_iterator mddIter = dictFiles.begin() + 1; mddIter != dictFiles.end(); ++mddIter ) { - if ( File::exists( *mddIter ) ) { + if ( Utils::Fs::exists( *mddIter ) ) { sptr< MdictParser > mddParser = std::make_shared< MdictParser >(); if ( !mddParser->open( mddIter->c_str() ) ) { qWarning( "Broken mdd (resource) file: %s", mddIter->c_str() ); diff --git a/src/dict/stardict.cc b/src/dict/stardict.cc index d8c718c6c..941f55ca2 100644 --- a/src/dict/stardict.cc +++ b/src/dict/stardict.cc @@ -1658,20 +1658,21 @@ static void findCorrespondingFiles( string const & ifo, string & idx, string & d { string base( ifo, 0, ifo.size() - 3 ); - if ( !( File::tryPossibleName( base + "idx", idx ) || File::tryPossibleName( base + "idx.gz", idx ) - || File::tryPossibleName( base + "idx.dz", idx ) || File::tryPossibleName( base + "IDX", idx ) - || File::tryPossibleName( base + "IDX.GZ", idx ) || File::tryPossibleName( base + "IDX.DZ", idx ) ) ) { + idx = Utils::Fs::findFirstExistingFile( + { base + "idx", base + "idx.gz", base + "idx.dz", base + "IDX", base + "IDX.GZ", base + "IDX.DZ" } ); + if ( idx.empty() ) { throw exNoIdxFile( ifo ); } - if ( !( File::tryPossibleName( base + "dict", dict ) || File::tryPossibleName( base + "dict.dz", dict ) - || File::tryPossibleName( base + "DICT", dict ) || File::tryPossibleName( base + "dict.DZ", dict ) ) ) { + dict = Utils::Fs::findFirstExistingFile( { base + "dict", base + "dict.dz", base + "DICT", base + "dict.DZ" } ); + if ( dict.empty() ) { throw exNoDictFile( ifo ); } - if ( !( File::tryPossibleName( base + "syn", syn ) || File::tryPossibleName( base + "syn.gz", syn ) - || File::tryPossibleName( base + "syn.dz", syn ) || File::tryPossibleName( base + "SYN", syn ) - || File::tryPossibleName( base + "SYN.GZ", syn ) || File::tryPossibleName( base + "SYN.DZ", syn ) ) ) { + syn = Utils::Fs::findFirstExistingFile( + { base + "syn", base + "syn.gz", base + "syn.dz", base + "SYN", base + "SYN.GZ", base + "SYN.DZ" } ); + + if ( syn.empty() ) { syn.clear(); } } diff --git a/src/dict/utils/dictfile.cc b/src/dict/utils/dictfile.cc index 4a628df3a..c1094a22b 100644 --- a/src/dict/utils/dictfile.cc +++ b/src/dict/utils/dictfile.cc @@ -6,16 +6,16 @@ #include "zipfile.hh" #include -#include #ifdef __WIN32 #include #endif +#include "utils.hh" namespace File { bool tryPossibleName( std::string const & name, std::string & copyTo ) { - if ( File::exists( name ) ) { + if ( Utils::Fs::exists( name ) ) { copyTo = name; return true; } diff --git a/src/dict/utils/dictfile.hh b/src/dict/utils/dictfile.hh index c91056da4..d5996d89c 100644 --- a/src/dict/utils/dictfile.hh +++ b/src/dict/utils/dictfile.hh @@ -28,11 +28,6 @@ bool tryPossibleZipName( std::string const & name, std::string & copyTo ); void loadFromFile( std::string const & filename, std::vector< char > & data ); -// QFileInfo::exists but used for std::string and char* -inline bool exists( std::string_view filename ) noexcept -{ - return QFileInfo::exists( QString::fromUtf8( filename.data(), filename.size() ) ); -}; /// Exclusivly used for processing GD's index files class Index diff --git a/src/dict/utils/indexedzip.cc b/src/dict/utils/indexedzip.cc index c1aa4c60e..c4a88597c 100644 --- a/src/dict/utils/indexedzip.cc +++ b/src/dict/utils/indexedzip.cc @@ -84,7 +84,7 @@ bool IndexedZip::loadFile( uint32_t offset, vector< char > & data ) return (size_t)zip.read( &data.front(), data.size() ) == data.size(); case ZipFile::Deflated: { - // Now do the deflation + // Decompress the data using the zlib library QByteArray compressedData = zip.read( header.compressedSize ); @@ -94,9 +94,7 @@ bool IndexedZip::loadFile( uint32_t offset, vector< char > & data ) data.resize( header.uncompressedSize ); - z_stream stream; - - memset( &stream, 0, sizeof( stream ) ); + z_stream stream = {}; stream.next_in = (Bytef *)compressedData.data(); stream.avail_in = compressedData.size(); @@ -108,17 +106,29 @@ bool IndexedZip::loadFile( uint32_t offset, vector< char > & data ) return false; } - if ( inflate( &stream, Z_FINISH ) != Z_STREAM_END ) { - qDebug( "Not zstream end!" ); + int ret = inflate( &stream, Z_FINISH ); + if ( ret != Z_STREAM_END ) { + qDebug() << "Not zstream end! Stream total_in:" << stream.total_in << "total_out:" << stream.total_out + << "msg:" << ( stream.msg ? stream.msg : "none" ); data.clear(); - inflateEnd( &stream ); + int endRet = inflateEnd( &stream ); + if ( endRet != Z_OK ) { + qDebug() << "inflateEnd failed after inflate! msg:" << ( stream.msg ? stream.msg : "none" ); + } return false; } - inflateEnd( &stream ); + ret = inflateEnd( &stream ); + if ( ret != Z_OK ) { + qDebug() << "inflateEnd failed! msg:" << ( stream.msg ? stream.msg : "none" ); + + data.clear(); + + return false; + } return true; } diff --git a/src/stylesheets/article-style.css b/src/stylesheets/article-style.css index c7fc6f062..2dc2c80af 100644 --- a/src/stylesheets/article-style.css +++ b/src/stylesheets/article-style.css @@ -6,8 +6,8 @@ html { body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, - Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Arial, "Apple Color Emoji", - "Segoe UI Emoji", "Segoe UI Symbol", sans-serif; + Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Arial, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif; } .ipa, diff --git a/src/stylesheets/qt-modern.css b/src/stylesheets/qt-modern.css index 8e5355a2f..38e829863 100644 --- a/src/stylesheets/qt-modern.css +++ b/src/stylesheets/qt-modern.css @@ -1,34 +1,3 @@ -/* WARNING: hides all separators! */ -#navToolbar::separator { - width: 0px; -} - -/* Another way to hide specific separators */ -#navToolbar #beforeOptionsSeparator, -#navToolbar #beforeScanPopupSeparator, -#navToolbar #afterScanPopupSeparator, -#navToolbar #separatorBeforeZoom, -#navToolbar #separatorBeforeSave { - background: rgba(0, 0, 0, 0%); - width: 0px; - margin: -3px; -} - -/* Hide various buttons in the toolbar: */ -#navToolbar #menuButtonXX, -#navToolbar #soundButtonXX, -#navToolbar #backButtonXX, -#navToolbar #forwardButtonXX, -#navToolbar #zoomInButtonXX, -#navToolbar #zoomOutButtonXX, -#navToolbar #zoomBaseButtonXX, -#navToolbar #saveArticleButton, -#navToolbar #printButton { - width: 0px; - height: 0px; - margin: -3px; -} - /* remove the main toolbar handle */ #navToolbar::handle, #dictionaryBar::handle { @@ -54,16 +23,3 @@ QMainWindow::separator { width: 1px; /* when vertical */ height: 1px; /* when horizontal */ } - -ScanPopup #goBackButtonAA, -/* ScanPopup #queryError, */ -ScanPopup #goForwardButtonAA, -ScanPopup #wordListButtonXX, -ScanPopup #pronounceButtonAA, -ScanPopup #sendWordButtonXX -/* ScanPopup #showDictionaryBar, */ -/* ScanPopup #pinButton */ { - width: 0px; - height: 0px; - margin: -4px; -} diff --git a/src/ui/articleview.cc b/src/ui/articleview.cc index f0d8292f2..b1e8d30b1 100644 --- a/src/ui/articleview.cc +++ b/src/ui/articleview.cc @@ -1286,6 +1286,11 @@ void ArticleView::toHtml( const std::function< void( QString & ) > & callback ) } ); } +QWebEnginePage * ArticleView::page() +{ + return webview->page(); +} + void ArticleView::setHtml( const QString & content, const QUrl & baseUrl ) { webview->page()->setHtml( content, baseUrl ); diff --git a/src/ui/articleview.hh b/src/ui/articleview.hh index 144d6d439..d1c21190b 100644 --- a/src/ui/articleview.hh +++ b/src/ui/articleview.hh @@ -217,6 +217,7 @@ public: void toHtml( const std::function< void( QString & ) > & callback ); void setHtml( const QString & content, const QUrl & baseUrl ); + QWebEnginePage * page(); void setContent( const QByteArray & data, const QString & mimeType = QString(), const QUrl & baseUrl = QUrl() ); /// Returns current article's title diff --git a/src/ui/favoritespanewidget.cc b/src/ui/favoritespanewidget.cc index f726ba997..897f099b0 100644 --- a/src/ui/favoritespanewidget.cc +++ b/src/ui/favoritespanewidget.cc @@ -946,16 +946,8 @@ QModelIndex FavoritesModel::addNewFolder( const QModelIndex & idx ) QString name = baseName; if ( findItemInFolder( name, TreeItem::Folder, parentIdx ).isValid() ) { - int i; - for ( i = 1; i < 1000; i++ ) { - name = baseName + QString::number( i ); - if ( !findItemInFolder( name, TreeItem::Folder, parentIdx ).isValid() ) { - break; - } - } - if ( i >= 1000 ) { - return QModelIndex(); - } + //name, with date as part of the name + name = baseName + QString::number( QDateTime::currentDateTime().toSecsSinceEpoch() ); } // Create folder with unique name diff --git a/src/ui/mainwindow.cc b/src/ui/mainwindow.cc index 1f8f7484f..11448b681 100644 --- a/src/ui/mainwindow.cc +++ b/src/ui/mainwindow.cc @@ -240,12 +240,14 @@ MainWindow::MainWindow( Config::Class & cfg_ ): // translate box groupListInToolbar = new GroupComboBox( navToolbar ); - groupListInToolbar->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::MinimumExpanding ); + groupListInToolbar->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ); groupListInToolbar->setSizeAdjustPolicy( QComboBox::AdjustToContents ); + groupListInToolbar->setStyleSheet( "QComboBox { padding: 0px; margin: 0px; }" ); translateBoxLayout->addWidget( groupListInToolbar ); translateBox = new TranslateBox( navToolbar ); - translateBox->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding ); + translateBox->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ); + translateBox->setStyleSheet( "QComboBox { padding: 0px; margin: 0px; }" ); translateBoxLayout->addWidget( translateBox ); translateBoxToolBarAction = navToolbar->addWidget( translateBoxWidget ); @@ -3122,17 +3124,35 @@ void MainWindow::showDictBarNamesTriggered() cfg.showingDictBarNames = show; } -void MainWindow::iconSizeActionTriggered( QAction * /*action*/ ) +int MainWindow::getIconSize() { bool useLargeIcons = useLargeIconsInToolbarsAction.isChecked(); int extent = QApplication::style()->pixelMetric( QStyle::PM_ToolBarIconSize ); + if ( useLargeIcons ) { + extent = QApplication::style()->pixelMetric( QStyle::PM_LargeIconSize ); + } + else if ( useSmallIconsInToolbarsAction.isChecked() ) { + extent = QApplication::style()->pixelMetric( QStyle::PM_SmallIconSize ); + } + else { + //empty + } + return extent; +} + +void MainWindow::iconSizeActionTriggered( QAction * /*action*/ ) +{ + //reset word zoom + cfg.preferences.wordsZoomLevel = 0; + wordsZoomBase->setEnabled( false ); + + bool useLargeIcons = useLargeIconsInToolbarsAction.isChecked(); + int extent = getIconSize(); if ( useLargeIcons ) { cfg.usingToolbarsIconSize = Config::ToolbarsIconSize::Large; - extent = QApplication::style()->pixelMetric( QStyle::PM_LargeIconSize ); } else if ( useSmallIconsInToolbarsAction.isChecked() ) { cfg.usingToolbarsIconSize = Config::ToolbarsIconSize::Small; - extent = QApplication::style()->pixelMetric( QStyle::PM_SmallIconSize ); } else { cfg.usingToolbarsIconSize = Config::ToolbarsIconSize::Normal; @@ -3144,6 +3164,15 @@ void MainWindow::iconSizeActionTriggered( QAction * /*action*/ ) updateDictionaryBar(); scanPopup->setDictionaryIconSize(); + + //adjust the font size as well + auto font = translateBox->translateLine()->font(); + font.setWeight( QFont::Normal ); + //arbitrary value to make it look good + font.setPixelSize( extent * 0.8 ); + // translateBox->completerWidget()->setFont( font ); + //only set the font in toolbar + translateBox->translateLine()->setFont( font ); } void MainWindow::toggleMenuBarTriggered( bool announce ) @@ -3351,8 +3380,10 @@ void MainWindow::on_saveArticle_triggered() QFileDialog::Options options = QFileDialog::HideNameFilterDetails; QString selectedFilter; QStringList filters; - filters.push_back( tr( "Article, Complete (*.html)" ) ); - filters.push_back( tr( "Article, HTML Only (*.html)" ) ); + filters.push_back( tr( "Complete Html (*.html *.htm)" ) ); + filters.push_back( tr( "Single Html (*.html *.htm)" ) ); + filters.push_back( tr( "Pdf (*.pdf)" ) ); + filters.push_back( tr( "Mime Html (*.mhtml)" ) ); fileName = savePath + "/" + fileName; fileName = QFileDialog::getSaveFileName( this, @@ -3362,6 +3393,7 @@ void MainWindow::on_saveArticle_triggered() &selectedFilter, options ); + qDebug() << "selected filter: " << selectedFilter; // The " (*.html)" part of filters[i] is absent from selectedFilter in Qt 5. bool const complete = filters.at( 0 ).startsWith( selectedFilter ); @@ -3369,6 +3401,36 @@ void MainWindow::on_saveArticle_triggered() return; } + //Pdf + if ( filters.at( 2 ).startsWith( selectedFilter ) ) { + // Create a QWebEnginePage object + QWebEnginePage * page = view->page(); + + // Connect the printFinished signal to handle operations after printing is complete + connect( page, &QWebEnginePage::pdfPrintingFinished, [ = ]( const QString & filePath, bool success ) { + if ( success ) { + qDebug() << "PDF exported successfully to:" << filePath; + } + else { + qDebug() << "Failed to export PDF."; + } + } ); + + // Print to PDF file + page->printToPdf( fileName ); + + return; + } + + //mime html + if ( filters.at( 3 ).startsWith( selectedFilter ) ) { + // Create a QWebEnginePage object + QWebEnginePage * page = view->page(); + page->save( fileName, QWebEngineDownloadRequest::MimeHtmlSaveFormat ); + + return; + } + view->toHtml( [ = ]( QString & html ) mutable { QFile file( fileName ); if ( !file.open( QIODevice::WriteOnly ) ) { @@ -3571,14 +3633,14 @@ void MainWindow::scaleArticlesByCurrentZoomFactor() void MainWindow::doWordsZoomIn() { - ++cfg.preferences.wordsZoomLevel; + cfg.preferences.wordsZoomLevel = cfg.preferences.wordsZoomLevel + 2; applyWordsZoomLevel(); } void MainWindow::doWordsZoomOut() { - --cfg.preferences.wordsZoomLevel; + cfg.preferences.wordsZoomLevel = cfg.preferences.wordsZoomLevel - 2; applyWordsZoomLevel(); } @@ -3592,68 +3654,19 @@ void MainWindow::doWordsZoomBase() void MainWindow::applyWordsZoomLevel() { - QFont font( wordListDefaultFont ); - - int ps = font.pointSize(); - - if ( cfg.preferences.wordsZoomLevel != 0 ) { - ps += cfg.preferences.wordsZoomLevel; - - if ( ps < 1 ) { - ps = 1; - } - - font.setPointSize( ps ); - } - - if ( ui.wordList->font().pointSize() != ps ) { - ui.wordList->setFont( font ); - } - - font = translateLineDefaultFont; - - ps = font.pointSize(); - - if ( cfg.preferences.wordsZoomLevel != 0 ) { - ps += cfg.preferences.wordsZoomLevel; - - if ( ps < 1 ) { - ps = 1; - } + QFont font = translateBox->translateLine()->font(); - font.setPointSize( ps ); - } - - if ( translateLine->font().pointSize() != ps ) { - translateLine->setFont( font ); - - translateBox->completerWidget()->setFont( font ); - } - - font = groupListDefaultFont; - - ps = font.pointSize(); - - if ( cfg.preferences.wordsZoomLevel != 0 ) { - ps += cfg.preferences.wordsZoomLevel; + int ps = getIconSize(); - if ( ps < 1 ) { - ps = 1; - } - - font.setPointSize( ps ); - } - - if ( groupList->font().pointSize() != ps ) { - disconnect( groupList, &GroupComboBox::currentIndexChanged, this, &MainWindow::currentGroupChanged ); - int n = groupList->currentIndex(); - groupList->clear(); - groupList->setFont( font ); - groupList->fill( groupInstances ); - groupList->setCurrentIndex( n ); - connect( groupList, &GroupComboBox::currentIndexChanged, this, &MainWindow::currentGroupChanged ); + ps += cfg.preferences.wordsZoomLevel; + if ( ps < 12 ) { + ps = 12; } + font.setPixelSize( ps * 0.8 ); + font.setWeight( QFont::Normal ); + translateBox->translateLine()->setFont( font ); + // translateBox->completerWidget()->setFont( font ); wordsZoomBase->setEnabled( cfg.preferences.wordsZoomLevel != 0 ); if ( !cfg.preferences.searchInDock ) { @@ -3932,80 +3945,46 @@ void MainWindow::on_exportFavorites_triggered() QString fileName = QFileDialog::getSaveFileName( this, tr( "Export Favorites to file" ), exportPath, - tr( "XML files (*.xml);;All files (*.*)" ) ); + tr( "Text files (*.txt);;XML files (*.xml)" ) ); if ( fileName.size() == 0 ) { return; } - cfg.historyExportPath = QDir::toNativeSeparators( QFileInfo( fileName ).absoluteDir().absolutePath() ); QFile file( fileName ); - - if ( !file.open( QFile::WriteOnly | QIODevice::Text ) ) { errorMessageOnStatusBar( QString( tr( "Export error: " ) ) + file.errorString() ); return; } + if ( fileName.endsWith( ".xml", Qt::CaseInsensitive ) ) { + QByteArray data; + ui.favoritesPaneWidget->getDataInXml( data ); - QByteArray data; - ui.favoritesPaneWidget->getDataInXml( data ); - - if ( file.write( data ) != data.size() ) { - errorMessageOnStatusBar( QString( tr( "Export error: " ) ) + file.errorString() ); - return; - } - - file.close(); - mainStatusBar->showMessage( tr( "Favorites export complete" ), 5000 ); -} - -void MainWindow::on_ExportFavoritesToList_triggered() -{ - QString exportPath; - if ( cfg.historyExportPath.isEmpty() ) { - exportPath = QDir::homePath(); + if ( file.write( data ) != data.size() ) { + errorMessageOnStatusBar( QString( tr( "Export error: " ) ) + file.errorString() ); + return; + } } else { - exportPath = QDir::fromNativeSeparators( cfg.historyExportPath ); - if ( !QDir( exportPath ).exists() ) { - exportPath = QDir::homePath(); + // Write UTF-8 BOM + QByteArray line; + line.append( 0xEF ).append( 0xBB ).append( 0xBF ); + if ( file.write( line ) != line.size() ) { + errorMessageOnStatusBar( QString( tr( "Export error: " ) ) + file.errorString() ); + return; } - } - QString fileName = QFileDialog::getSaveFileName( this, - tr( "Export Favorites to file as plain list" ), - exportPath, - tr( "Text files (*.txt);;All files (*.*)" ) ); - if ( fileName.size() == 0 ) { - return; - } - - cfg.historyExportPath = QDir::toNativeSeparators( QFileInfo( fileName ).absoluteDir().absolutePath() ); - QFile file( fileName ); - - if ( !file.open( QFile::WriteOnly | QIODevice::Text ) ) { - errorMessageOnStatusBar( QString( tr( "Export error: " ) ) + file.errorString() ); - return; - } + // Write Favorites + QString data; + ui.favoritesPaneWidget->getDataInPlainText( data ); - // Write UTF-8 BOM - QByteArray line; - line.append( 0xEF ).append( 0xBB ).append( 0xBF ); - if ( file.write( line ) != line.size() ) { - errorMessageOnStatusBar( QString( tr( "Export error: " ) ) + file.errorString() ); - return; - } - - // Write Favorites - QString data; - ui.favoritesPaneWidget->getDataInPlainText( data ); - - line = data.toUtf8(); - if ( file.write( line ) != line.size() ) { - errorMessageOnStatusBar( QString( tr( "Export error: " ) ) + file.errorString() ); - return; + line = data.toUtf8(); + if ( file.write( line ) != line.size() ) { + errorMessageOnStatusBar( QString( tr( "Export error: " ) ) + file.errorString() ); + return; + } } - file.close(); + mainStatusBar->showMessage( tr( "Favorites export complete" ), 5000 ); } diff --git a/src/ui/mainwindow.hh b/src/ui/mainwindow.hh index 831cc268d..3fb494c50 100644 --- a/src/ui/mainwindow.hh +++ b/src/ui/mainwindow.hh @@ -267,6 +267,7 @@ private: void changeWebEngineViewFont() const; bool isWordPresentedInFavorites( QString const & word, unsigned groupId ); void errorMessageOnStatusBar( const QString & errStr ); + int getIconSize(); private slots: @@ -429,7 +430,6 @@ private slots: void on_exportFavorites_triggered(); void on_importFavorites_triggered(); - void on_ExportFavoritesToList_triggered(); void updateSearchPaneAndBar( bool searchInDock ); diff --git a/src/ui/mainwindow.ui b/src/ui/mainwindow.ui index ec76f207d..17b73447f 100644 --- a/src/ui/mainwindow.ui +++ b/src/ui/mainwindow.ui @@ -125,7 +125,6 @@ - @@ -557,11 +556,6 @@ Ctrl+E - - - Export to list - - diff --git a/src/ui/scanpopup.cc b/src/ui/scanpopup.cc index f94ad9e6b..bcb955920 100644 --- a/src/ui/scanpopup.cc +++ b/src/ui/scanpopup.cc @@ -348,56 +348,19 @@ void ScanPopup::applyZoomFactor() const void ScanPopup::applyWordsZoomLevel() { - QFont font( wordListDefaultFont ); - int ps = font.pointSize(); + QFont font = ui.translateBox->translateLine()->font(); - if ( cfg.preferences.wordsZoomLevel != 0 ) { - ps += cfg.preferences.wordsZoomLevel; - if ( ps < 1 ) { - ps = 1; - } - font.setPointSize( ps ); - } - - if ( ui.translateBox->completerWidget()->font().pointSize() != ps ) { - ui.translateBox->completerWidget()->setFont( font ); - } - - font = translateLineDefaultFont; - ps = font.pointSize(); + int ps = dictionaryBar.iconSize().height(); if ( cfg.preferences.wordsZoomLevel != 0 ) { ps += cfg.preferences.wordsZoomLevel; - if ( ps < 1 ) { - ps = 1; + if ( ps < 12 ) { + ps = 12; } - font.setPointSize( ps ); - } - - if ( ui.translateBox->translateLine()->font().pointSize() != ps ) { - ui.translateBox->translateLine()->setFont( font ); - } - - font = groupListDefaultFont; - ps = font.pointSize(); - - if ( cfg.preferences.wordsZoomLevel != 0 ) { - ps += cfg.preferences.wordsZoomLevel; - if ( ps < 1 ) { - ps = 1; - } - font.setPointSize( ps ); - } - - if ( ui.groupList->font().pointSize() != ps ) { - disconnect( ui.groupList, &GroupComboBox::currentIndexChanged, this, &ScanPopup::currentGroupChanged ); - int n = ui.groupList->currentIndex(); - ui.groupList->clear(); - ui.groupList->setFont( font ); - ui.groupList->fill( groups ); - ui.groupList->setCurrentIndex( n ); - connect( ui.groupList, &GroupComboBox::currentIndexChanged, this, &ScanPopup::currentGroupChanged ); + font.setPixelSize( ps * 0.8 ); } + ui.translateBox->completerWidget()->setFont( font ); + // ui.translateBox->translateLine()->setFont( font ); ui.outerFrame->layout()->activate(); } @@ -1151,6 +1114,8 @@ void ScanPopup::setDictionaryIconSize() else if ( cfg.usingToolbarsIconSize == Config::ToolbarsIconSize::Large ) { dictionaryBar.setDictionaryIconSize( DictionaryBar::IconSize::Large ); } + + applyWordsZoomLevel(); } diff --git a/src/ui/scanpopup.ui b/src/ui/scanpopup.ui index e9550651c..1031fed21 100644 --- a/src/ui/scanpopup.ui +++ b/src/ui/scanpopup.ui @@ -70,7 +70,7 @@ - + 0 0 @@ -83,7 +83,7 @@ - + 0 0 diff --git a/tools/scripts/Build ffmpeg on macos.md b/tools/scripts/Build ffmpeg on macos.md deleted file mode 100644 index 5a3a172a8..000000000 --- a/tools/scripts/Build ffmpeg on macos.md +++ /dev/null @@ -1,194 +0,0 @@ -``` -brew install automake fdk-aac git lame libass libtool libvorbis libvpx opus sdl shtool texi2html theora wget x264 x265 xvid nasm -brew install speex -git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg -cd ffmpeg -./configure --prefix=../build/ \ ---enable-shared \ ---disable-static \ ---disable-debug \ ---disable-programs \ ---disable-network \ ---disable-avdevice \ ---disable-avfilter \ ---disable-swscale \ ---disable-network \ ---disable-muxers \ ---disable-demuxers \ ---enable-rdft \ ---enable-demuxer=aac \ ---enable-demuxer=ac3 \ ---enable-demuxer=aiff \ ---enable-demuxer=ape \ ---enable-demuxer=asf \ ---enable-demuxer=flac \ ---enable-demuxer=matroska \ ---enable-demuxer=mp3 \ ---enable-demuxer=mpc \ ---enable-demuxer=mov \ ---enable-demuxer=mpc8 \ ---enable-demuxer=ogg \ ---enable-demuxer=tta \ ---enable-demuxer=wav \ ---enable-demuxer=wv \ ---disable-bsfs \ ---disable-filters \ ---disable-parsers \ ---enable-parser=aac \ ---enable-parser=ac3 \ ---enable-parser=mpegaudio \ ---disable-protocols \ ---disable-indevs \ ---disable-outdevs \ ---disable-encoders \ ---disable-decoders \ ---enable-decoder=eightsvx_exp \ ---enable-decoder=eightsvx_fib \ ---enable-decoder=aac \ ---enable-decoder=aac_latm \ ---enable-decoder=ac3 \ ---enable-decoder=adpcm_4xm \ ---enable-decoder=adpcm_adx \ ---enable-decoder=adpcm_afc \ ---enable-decoder=adpcm_ct \ ---enable-decoder=adpcm_ea \ ---enable-decoder=adpcm_ea_maxis_xa \ ---enable-decoder=adpcm_ea_r1 \ ---enable-decoder=adpcm_ea_r2 \ ---enable-decoder=adpcm_ea_r3 \ ---enable-decoder=adpcm_ea_xas \ ---enable-decoder=adpcm_g722 \ ---enable-decoder=adpcm_g726 \ ---enable-decoder=adpcm_ima_amv \ ---enable-decoder=adpcm_ima_apc \ ---enable-decoder=adpcm_ima_dk3 \ ---enable-decoder=adpcm_ima_dk4 \ ---enable-decoder=adpcm_ima_ea_eacs \ ---enable-decoder=adpcm_ima_ea_sead \ ---enable-decoder=adpcm_ima_iss \ ---enable-decoder=adpcm_ima_oki \ ---enable-decoder=adpcm_ima_qt \ ---enable-decoder=adpcm_ima_smjpeg \ ---enable-decoder=adpcm_ima_wav \ ---enable-decoder=adpcm_ima_ws \ ---enable-decoder=adpcm_ms \ ---enable-decoder=adpcm_sbpro_2 \ ---enable-decoder=adpcm_sbpro_3 \ ---enable-decoder=adpcm_sbpro_4 \ ---enable-decoder=adpcm_swf \ ---enable-decoder=adpcm_thp \ ---enable-decoder=adpcm_xa \ ---enable-decoder=adpcm_yamaha \ ---enable-decoder=alac \ ---enable-decoder=amrnb \ ---enable-decoder=libopencore_amrnb \ ---enable-decoder=amrwb \ ---enable-decoder=libopencore_amrwb \ ---enable-decoder=ape \ ---enable-decoder=atrac1 \ ---enable-decoder=atrac3 \ ---enable-decoder=binkaudio_dct \ ---enable-decoder=binkaudio_rdft \ ---enable-decoder=bmv_audio \ ---enable-decoder=comfortnoise \ ---enable-decoder=cook \ ---enable-decoder=dsicinaudio \ ---enable-decoder=dca \ ---enable-decoder=eac3 \ ---enable-decoder=flac \ ---enable-decoder=g723_1 \ ---enable-decoder=g729 \ ---enable-decoder=gsm \ ---enable-decoder=libgsm \ ---enable-decoder=gsm_ms \ ---enable-decoder=libgsm_ms \ ---enable-decoder=iac \ ---enable-decoder=imc \ ---enable-decoder=interplay_dpcm \ ---enable-decoder=mace3 \ ---enable-decoder=mace6 \ ---enable-decoder=mlp \ ---enable-decoder=mp1 \ ---enable-decoder=mp1float \ ---enable-decoder=mp2 \ ---enable-decoder=mp2float \ ---enable-decoder=mp3 \ ---enable-decoder=mp3float \ ---enable-decoder=mp3adu \ ---enable-decoder=mp3adufloat \ ---enable-decoder=mp3on4 \ ---enable-decoder=mp3on4float \ ---enable-decoder=als \ ---enable-decoder=mpc7 \ ---enable-decoder=mpc8 \ ---enable-decoder=nellymoser \ ---enable-decoder=libopus \ ---enable-decoder=paf_audio \ ---enable-decoder=pcm_alaw \ ---enable-decoder=pcm_bluray \ ---enable-decoder=pcm_dvd \ ---enable-decoder=pcm_f32be \ ---enable-decoder=pcm_f32le \ ---enable-decoder=pcm_f64be \ ---enable-decoder=pcm_f64le \ ---enable-decoder=pcm_lxf \ ---enable-decoder=pcm_mulaw \ ---enable-decoder=pcm_s16be \ ---enable-decoder=pcm_s16be_planar \ ---enable-decoder=pcm_s16le \ ---enable-decoder=pcm_s16le_planar \ ---enable-decoder=pcm_s24be \ ---enable-decoder=pcm_s24daud \ ---enable-decoder=pcm_s24le \ ---enable-decoder=pcm_s24le_planar \ ---enable-decoder=pcm_s32be \ ---enable-decoder=pcm_s32le \ ---enable-decoder=pcm_s32le_planar \ ---enable-decoder=pcm_s8 \ ---enable-decoder=pcm_s8_planar \ ---enable-decoder=pcm_u16be \ ---enable-decoder=pcm_u16le \ ---enable-decoder=pcm_u24be \ ---enable-decoder=pcm_u24le \ ---enable-decoder=pcm_u32be \ ---enable-decoder=pcm_u32le \ ---enable-decoder=pcm_u8 \ ---enable-decoder=pcm_zork \ ---enable-decoder=qcelp \ ---enable-decoder=qdm2 \ ---enable-decoder=ra_144 \ ---enable-decoder=ra_288 \ ---enable-decoder=ralf \ ---enable-decoder=roq_dpcm \ ---enable-decoder=s302m \ ---enable-decoder=shorten \ ---enable-decoder=sipr \ ---enable-decoder=smackaud \ ---enable-decoder=sol_dpcm \ ---enable-decoder=sonic \ ---enable-decoder=libspeex \ ---enable-decoder=tak \ ---enable-decoder=truehd \ ---enable-decoder=truespeech \ ---enable-decoder=tta \ ---enable-decoder=twinvq \ ---enable-decoder=vima \ ---enable-decoder=vmdaudio \ ---enable-decoder=vorbis \ ---enable-decoder=ffwavesynth \ ---enable-decoder=wavpack \ ---enable-decoder=ws_snd1 \ ---enable-decoder=wmalossless \ ---enable-decoder=wmapro \ ---enable-decoder=wmav1 \ ---enable-decoder=wmav2 \ ---enable-decoder=wmavoice \ ---enable-decoder=xan_dpcm \ ---enable-libspeex -make -sudo make install - -ls -al ../build -# otool -L build/*.dylib - -``` \ No newline at end of file