Compare commits

...

27 commits

Author SHA1 Message Date
xiaoyifang e894bf6ae6
Merge c0697ecdda into 8ad7291147 2024-11-06 06:12:25 -05:00
shenleban tongying 8ad7291147
clean: deprecated QKeySequence[]->int; answer ikm's question from 2009
Some checks are pending
SonarCloud / Build and analyze (push) Waiting to run
2024-11-06 11:11:48 +00:00
xiaoyifang 8d0859b932
Merge pull request #1906 from xiaoyifang/opt/articleview-loadfinish
opt: rearrange some code execution order
2024-11-06 17:49:28 +08:00
shenleban tongying 349fcb6628
clean: fix all globalPosition deprecations to stop related warnings (#1911) 2024-11-06 09:11:07 +00:00
shenleban tongying 7a1df4b6c6 dev: fix changelog generation again
Some checks are pending
SonarCloud / Build and analyze (push) Waiting to run
2024-11-06 01:25:55 -05:00
xiaoyifang 285a0d8882
fix: remove some tabText() in groupWidget when rename group (#1897)
* fix: remove some tabText() in groupWidget rename group

* Update src/ui/groups_widgets.cc

Co-authored-by: shenleban tongying <shenlebantongying@gmail.com>

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: shenleban tongying <shenlebantongying@gmail.com>
2024-11-06 14:10:25 +08:00
shenleban tongying 8be7b65f29
Merge pull request #1908 from shenlebantongying/clean/tidy-using-using
clean: apply clang-tidy's `modernize-use-using` (replace most `typedef`)
2024-11-06 01:01:58 -05:00
shenleban tongying fb45d2e036 dev: add last commit to .git-blame-ignore-revs 2024-11-06 00:56:26 -05:00
shenleban tongying d15081e723 clean: apply clang-tidy's modernize-use-using (replace most typedef) 2024-11-06 00:48:35 -05:00
shenleban tongying 673911b1c5
feat: auto dark reader mode that sync with system theme 2024-11-05 23:39:08 -05:00
shenleban tongying b6fa66df92
refactor: prepare config code to implement auto dark (reader) mode
Some checks are pending
SonarCloud / Build and analyze (push) Waiting to run
2024-11-06 03:27:19 +00:00
xiaoyifang 2f48993594 opt: rearrange some code execution order 2024-11-06 10:11:21 +08:00
xiaoyifang 9315dda365
Merge pull request #1905 from xiaoyifang/opt/custom-js-defer
opt: make custom javascript delay execution
2024-11-06 09:57:43 +08:00
xiaoyifang 1418f9ab9e opt: make custom javascript delay execution 2024-11-06 09:09:18 +08:00
xiaoyifang c0697ecdda 1 2024-11-04 11:42:04 +08:00
autofix-ci[bot] 701a4effb3
[autofix.ci] apply automated fixes 2024-11-04 03:29:03 +00:00
xiaoyifang f9a3705942 1 2024-11-04 11:27:46 +08:00
YiFang Xiao 2c91b78e13 1 2024-11-03 17:42:51 +08:00
YiFang Xiao c6387df392 1 2024-11-03 17:42:50 +08:00
autofix-ci[bot] 43c982cf8a
[autofix.ci] apply automated fixes 2024-11-03 07:26:21 +00:00
YiFang Xiao e07e730a09 1 2024-11-03 15:19:32 +08:00
YiFang Xiao ab214cfb05 1 2024-11-03 14:20:10 +08:00
autofix-ci[bot] c00239a1b1 [autofix.ci] apply automated fixes 2024-11-03 14:20:03 +08:00
xiaoyifang 469896bbf1 1 2024-11-03 14:19:19 +08:00
xiaoyifang 0d89c4ab56 1 2024-11-03 14:19:19 +08:00
xiaoyifang 9e99389cc3 opt: website dictionary render html 2024-11-03 14:19:12 +08:00
xiaoyifang 6edfd15962 opt: add option about open website in seperate tab 2024-11-03 14:17:29 +08:00
35 changed files with 487 additions and 310 deletions

View file

@ -12,3 +12,6 @@ b5349478cfb0dc2dd0de8c8e8aeebdd24cf7ac6b
# mass apply clang-tidy's readability-braces-around-statements
a11c9e3aeca4329e1982d8fe26bacbb21ab50ddf
# mass apply clang-tidy's modernize-use-using
d15081e723756eef053550dc9e06e31d7828dec3

View file

@ -147,7 +147,7 @@ jobs:
if [[ '${{env.prerelease}}' == 'true' ]]
then
echo "This is a pre-release"
previousTag=$(git tag --sort=-creatordate | grep "^v" | head -n 1)
previousTag=$(git tag --sort=-creatordate | grep "^v" | grep -v "Release" | head -n 1)
else
echo "This is not a pre-release"
previousTag=$(git tag --sort=-creatordate | grep "^v" | grep -v "alpha" | head -n 1)

View file

@ -15,6 +15,7 @@
#include <QFile>
#include <QTextDocumentFragment>
#include <QUrl>
#include <QStyleHints>
#include "fmt/core.h"
#include "fmt/compile.h"
@ -151,7 +152,22 @@ std::string ArticleMaker::makeHtmlHeader( QString const & word, QString const &
result += R"(<script src="qrc:///scripts/gd-builtin.js"></script>)";
result += R"(<script src="qrc:///scripts/mark.min.js"></script>)";
if ( GlobalBroadcaster::instance()->getPreference()->darkReaderMode ) {
/// Handling Dark reader mode.
bool darkReaderModeEnabled = false;
if ( GlobalBroadcaster::instance()->getPreference()->darkReaderMode == Config::Dark::On ) {
darkReaderModeEnabled = true;
}
#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 )
if ( GlobalBroadcaster::instance()->getPreference()->darkReaderMode == Config::Dark::Auto
&& QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark ) {
darkReaderModeEnabled = true;
}
#endif
if ( darkReaderModeEnabled ) {
//only enable this darkmode on modern style.
if ( cfg.displayStyle == "modern" ) {
result += R"(<link href="qrc:///article-style-darkmode.css" media="all" rel="stylesheet" type="text/css">)";
@ -209,7 +225,7 @@ body { background: #242525; }
// load the `article-style.js` in user's config folder
if ( auto userJsFile = Config::getUserJsFileName(); userJsFile.has_value() ) {
result += fmt::format( FMT_COMPILE( R"(<script src="file://{}"></script>)" ), userJsFile.value() );
result += fmt::format( FMT_COMPILE( R"(<script src="file://{}" defer></script>)" ), userJsFile.value() );
}
result += "</head><body>";
@ -513,6 +529,22 @@ void ArticleRequest::altSearchFinished()
for ( const auto & activeDict : activeDicts ) {
try {
// if the dictionary is website dictionary and openinNewTab is enabled, emit a signal.
if ( GlobalBroadcaster::instance()->getPreference()->openWebsiteInNewTab ) {
if ( ( activeDict->getFeatures() | Dictionary::WebSite ) == Dictionary::WebSite ) {
//replace the word,and get the actual requested url
string url = activeDict->getProperties()[ Dictionary::Property::Url ];
if ( url.empty() ) {
continue;
}
QString requestUrl = Utils::WebSite::urlReplaceWord( QString::fromStdString( url ), word );
emit GlobalBroadcaster::instance()
-> websiteDictionary( QString::fromStdString( activeDict->getName() ), requestUrl );
continue;
}
}
sptr< Dictionary::DataRequest > r = activeDict->getArticle(
wordStd,
altsVector,

View file

@ -101,8 +101,8 @@ class ArticleRequest: public Dictionary::DataRequest
/// A sequence of words and spacings between them, including the initial
/// spacing before the first word and the final spacing after the last word.
typedef QList< QString > Words;
typedef QList< QString > Spacings;
using Words = QList< QString >;
using Spacings = QList< QString >;
/// Splits the given string into words and spacings between them.
std::pair< Words, Spacings > splitIntoWords( QString const & );

View file

@ -26,6 +26,6 @@ signals:
void error( QString message );
};
typedef QScopedPointer< AudioPlayerInterface > AudioPlayerPtr;
using AudioPlayerPtr = QScopedPointer< AudioPlayerInterface >;
#endif // AUDIOPLAYERINTERFACE_HH_INCLUDED

View file

@ -3,5 +3,5 @@
#include <QString>
typedef QMap< QString, QString > Contexts;
using Contexts = QMap< QString, QString >;
#endif // BASE_TYPE_H

View file

@ -46,6 +46,8 @@ signals:
void dictionaryClear( ActiveDictIds ad );
void indexingDictionary( QString );
void websiteDictionary( QString, QString );
};
#endif // GLOBAL_GLOBALBROADCASTER_H

View file

@ -12,6 +12,6 @@
///
namespace gd {
typedef char32_t wchar;
typedef std::u32string wstring;
using wchar = char32_t;
using wstring = std::u32string;
} // namespace gd

View file

@ -102,32 +102,24 @@ AnkiConnectServer::AnkiConnectServer():
{
}
HotKey::HotKey():
modifiers( 0 ),
key1( 0 ),
key2( 0 )
{
}
// Does anyone know how to separate modifiers from the keycode? We'll
// use our own mask.
uint32_t const keyMask = 0x01FFFFFF;
HotKey::HotKey( QKeySequence const & seq ):
modifiers( seq[ 0 ] & ~keyMask ),
key1( seq[ 0 ] & keyMask ),
key2( seq[ 1 ] & keyMask )
modifiers( seq[ 0 ].keyboardModifiers() ),
key1( seq[ 0 ].key() ),
key2( seq[ 1 ].key() )
{
}
QKeySequence HotKey::toKeySequence() const
{
int v2 = key2 ? ( key2 | modifiers ) : 0;
return QKeySequence( key1 | modifiers, v2 );
if ( key2 != 0 || key2 != Qt::Key::Key_unknown ) {
return { QKeyCombination( modifiers, static_cast< Qt::Key >( key1 ) ),
QKeyCombination( modifiers, static_cast< Qt::Key >( key2 ) ) };
}
return { QKeyCombination( modifiers, static_cast< Qt::Key >( key1 ) ) };
;
}
bool InternalPlayerBackend::anyAvailable()
{
#if defined( MAKE_FFMPEG_PLAYER ) || defined( MAKE_QTMULTIMEDIA_PLAYER )
@ -213,8 +205,6 @@ Preferences::Preferences():
selectWordBySingleClick( false ),
autoScrollToTargetArticle( true ),
escKeyHidesMainWindow( false ),
darkMode( false ),
darkReaderMode( false ),
alwaysOnTop( false ),
searchInDock( false ),
// on macOS, register hotkeys will override system shortcuts, disabled for now to avoid troubles.
@ -947,11 +937,12 @@ Class load()
}
if ( !preferences.namedItem( "darkMode" ).isNull() ) {
c.preferences.darkMode = ( preferences.namedItem( "darkMode" ).toElement().text() == "1" );
c.preferences.darkMode = static_cast< Dark >( preferences.namedItem( "darkMode" ).toElement().text().toInt() );
}
if ( !preferences.namedItem( "darkReaderMode" ).isNull() ) {
c.preferences.darkReaderMode = ( preferences.namedItem( "darkReaderMode" ).toElement().text() == "1" );
c.preferences.darkReaderMode =
static_cast< Dark >( preferences.namedItem( "darkReaderMode" ).toElement().text().toInt() );
}
if ( !preferences.namedItem( "zoomFactor" ).isNull() ) {
@ -1082,6 +1073,10 @@ Class load()
( preferences.namedItem( "removeInvalidIndexOnExit" ).toElement().text() == "1" );
}
if ( !preferences.namedItem( "openWebsiteInNewTab" ).isNull() ) {
c.preferences.openWebsiteInNewTab = ( preferences.namedItem( "openWebsiteInNewTab" ).toElement().text() == "1" );
}
if ( !preferences.namedItem( "maxStringsInHistory" ).isNull() ) {
c.preferences.maxStringsInHistory = preferences.namedItem( "maxStringsInHistory" ).toElement().text().toUInt();
}
@ -1882,11 +1877,11 @@ void save( Class const & c )
preferences.appendChild( opt );
opt = dd.createElement( "darkMode" );
opt.appendChild( dd.createTextNode( c.preferences.darkMode ? "1" : "0" ) );
opt.appendChild( dd.createTextNode( QString::number( static_cast< int >( c.preferences.darkMode ) ) ) );
preferences.appendChild( opt );
opt = dd.createElement( "darkReaderMode" );
opt.appendChild( dd.createTextNode( c.preferences.darkReaderMode ? "1" : "0" ) );
opt.appendChild( dd.createTextNode( QString::number( static_cast< int >( c.preferences.darkReaderMode ) ) ) );
preferences.appendChild( opt );
opt = dd.createElement( "zoomFactor" );
@ -2111,6 +2106,10 @@ void save( Class const & c )
opt.appendChild( dd.createTextNode( c.preferences.removeInvalidIndexOnExit ? "1" : "0" ) );
preferences.appendChild( opt );
opt = dd.createElement( "openWebsiteInNewTab" );
opt.appendChild( dd.createTextNode( c.preferences.openWebsiteInNewTab ? "1" : "0" ) );
preferences.appendChild( opt );
opt = dd.createElement( "maxStringsInHistory" );
opt.appendChild( dd.createTextNode( QString::number( c.preferences.maxStringsInHistory ) ) );
preferences.appendChild( opt );

View file

@ -28,8 +28,15 @@ enum GroupId : unsigned {
/// GoldenDict's configuration
namespace Config {
// Tri states enum for Dark and Dark reader mode
enum class Dark : std::uint8_t {
Off = 0,
On = 1,
Auto = 2,
};
/// Dictionaries which are temporarily disabled via the dictionary bar.
typedef QSet< QString > MutedDictionaries;
using MutedDictionaries = QSet< QString >;
/// A path where to search for the dictionaries
struct Path
@ -54,7 +61,7 @@ struct Path
};
/// A list of paths where to search for the dictionaries
typedef QList< Path > Paths;
using Paths = QList< Path >;
/// A directory holding bunches of audiofiles, which is indexed into a separate
/// dictionary.
@ -79,7 +86,7 @@ struct SoundDir
};
/// A list of SoundDirs
typedef QList< SoundDir > SoundDirs;
using SoundDirs = QList< SoundDir >;
struct DictionaryRef
{
@ -185,14 +192,11 @@ struct HotKey
Qt::KeyboardModifiers modifiers;
int key1, key2;
HotKey();
/// Hotkey's constructor, take a QKeySequence's first two keys
/// 1st key's modifier will be the `modifiers` above
/// 1st key without modifier will becomes `key1`
/// 2nd key without modifier will becomes `key2`
/// The relation between the int and qt's KeyCode should consult qt's doc
HotKey( QKeySequence const & );
QKeySequence toKeySequence() const;
@ -389,6 +393,7 @@ struct Preferences
int maxNetworkCacheSize;
bool clearNetworkCacheOnExit;
bool removeInvalidIndexOnExit = false;
bool openWebsiteInNewTab = false;
qreal zoomFactor;
qreal helpZoomFactor;
@ -420,8 +425,14 @@ struct Preferences
// Appearances
bool darkMode;
bool darkReaderMode;
Dark darkMode = Dark::Off;
Dark darkReaderMode =
#if defined( Q_OS_MACOS )
Dark::Auto;
#else
Dark::Off;
#endif
QString addonStyle;
QString displayStyle; // Article Display style (Which also affect interface style on windows)
@ -505,7 +516,7 @@ struct WebSite
};
/// All the WebSites
typedef QList< WebSite > WebSites;
using WebSites = QList< WebSite >;
/// Any DICT server
struct DictServer
@ -546,14 +557,14 @@ struct DictServer
};
/// All the DictServers
typedef QList< DictServer > DictServers;
using DictServers = QList< DictServer >;
/// Hunspell configuration
struct Hunspell
{
QString dictionariesPath;
typedef QList< QString > Dictionaries;
using Dictionaries = QList< QString >;
Dictionaries enabledDictionaries;
@ -569,7 +580,7 @@ struct Hunspell
};
/// All the MediaWikis
typedef QList< MediaWiki > MediaWikis;
using MediaWikis = QList< MediaWiki >;
/// Chinese transliteration configuration
@ -762,7 +773,7 @@ struct Program
}
};
typedef QList< Program > Programs;
using Programs = QList< Program >;
#ifndef NO_TTS_SUPPORT
struct VoiceEngine
@ -808,7 +819,7 @@ struct VoiceEngine
}
};
typedef QList< VoiceEngine > VoiceEngines;
using VoiceEngines = QList< VoiceEngine >;
#endif
struct HeadwordsDialog

View file

@ -115,20 +115,20 @@ const std::vector< std::string > bgl_charset = { "WINDOWS-1252", /*Default*/
const std::array< std::string, 11 > partOfSpeech = {
"n.", "adj.", "v.", "adv.", "interj.", "pron.", "prep.", "conj.", "suff.", "pref.", "art." };
typedef struct
struct bgl_block
{
unsigned type;
unsigned length;
char * data;
} bgl_block;
};
typedef struct
struct bgl_entry
{
std::string headword;
std::string definition;
std::string displayedHeadword;
std::vector< std::string > alternates;
} bgl_entry;
};
class Babylon
{

View file

@ -35,7 +35,8 @@ enum Property {
Author,
Copyright,
Description,
Email
Email,
Url,
};
DEF_EX( Ex, "Dictionary error", std::exception )

View file

@ -58,7 +58,7 @@ struct EpwingHeadword
class EpwingBook
{
typedef std::pair< int, int > EWPos;
using EWPos = std::pair< int, int >;
void setErrorString( QString const & func, EB_Error_Code code );

View file

@ -93,7 +93,7 @@ class ForvoArticleRequest: public Dictionary::DataRequest
}
};
typedef std::list< NetReply > NetReplies;
using NetReplies = std::list< NetReply >;
NetReplies netReplies;
QString apiKey, languageCode;
string dictionaryId;

View file

@ -33,7 +33,7 @@ class LinguaArticleRequest: public Dictionary::DataRequest
}
};
typedef std::list< NetReply > NetReplies;
using NetReplies = std::list< NetReply >;
NetReplies netReplies;
QString languageCode, langWikipediaID;
string dictionaryId;

View file

@ -112,9 +112,9 @@ public:
virtual void handleRecord( QString const & name, RecordInfo const & recordInfo ) = 0;
};
typedef vector< pair< qint64, qint64 > > BlockInfoVector;
typedef vector< pair< qint64, QString > > HeadWordIndex;
typedef map< qint32, pair< QString, QString > > StyleSheets;
using BlockInfoVector = vector< pair< qint64, qint64 > >;
using HeadWordIndex = vector< pair< qint64, QString > >;
using StyleSheets = map< qint32, pair< QString, QString > >;
inline QString const & title() const
{

View file

@ -389,7 +389,7 @@ void MediaWikiSectionsParser::closeListTags( int currentLevel )
class MediaWikiArticleRequest: public MediaWikiDataRequestSlots
{
typedef std::list< std::pair< QNetworkReply *, bool > > NetReplies;
using NetReplies = std::list< std::pair< QNetworkReply *, bool > >;
NetReplies netReplies;
QString url;
QString lang;

View file

@ -109,8 +109,8 @@ bool indexIsOldOrBad( string const & indexFile )
class SlobFile
{
public:
typedef std::pair< quint64, quint32 > RefEntryOffsetItem;
typedef QList< RefEntryOffsetItem > RefOffsetsVector;
using RefEntryOffsetItem = std::pair< quint64, quint32 >;
using RefOffsetsVector = QList< RefEntryOffsetItem >;
private:
enum Compressions {

View file

@ -24,7 +24,6 @@ class WebSiteDictionary: public Dictionary::Class
{
string name;
QByteArray urlTemplate;
bool experimentalIframe;
QString iconFilename;
bool inside_iframe;
QNetworkAccessManager & netMgr;
@ -41,14 +40,8 @@ public:
name( name_ ),
iconFilename( iconFilename_ ),
inside_iframe( inside_iframe_ ),
netMgr( netMgr_ ),
experimentalIframe( false )
netMgr( netMgr_ )
{
if ( urlTemplate_.startsWith( "http://" ) || urlTemplate_.startsWith( "https://" ) ) {
experimentalIframe = true;
}
//else file:/// local dictionary file path
urlTemplate = QUrl( urlTemplate_ ).toEncoded();
dictionaryDescription = urlTemplate_;
}
@ -60,7 +53,9 @@ public:
map< Property, string > getProperties() noexcept override
{
return map< Property, string >();
map< Property, string > properties;
properties.insert( { Property::Url, urlTemplate.toStdString() } );
return properties;
}
unsigned long getArticleCount() noexcept override
@ -321,7 +316,7 @@ void WebSiteArticleRequest::requestFinished( QNetworkReply * r )
sptr< DataRequest > WebSiteDictionary::getArticle( wstring const & str,
vector< wstring > const & /*alts*/,
wstring const & context,
wstring const & /*context*/,
bool /*ignoreDiacritics*/ )
{
QString urlString = Utils::WebSite::urlReplaceWord( QString( urlTemplate ), QString::fromStdU32String( str ) );
@ -335,24 +330,22 @@ sptr< DataRequest > WebSiteDictionary::getArticle( wstring const & str,
QUrl url( urlString );
GlobalBroadcaster::instance()->addWhitelist( url.host() );
QString encodeUrl;
if ( experimentalIframe ) {
encodeUrl = "ifr://localhost?url=" + QUrl::toPercentEncoding( urlString );
const QString & encodeUrl = urlString;
if ( GlobalBroadcaster::instance()->getPreference()->openWebsiteInNewTab ) {
result += string( "<div><span>this website dictionary is opened in the new tab</span></div>" );
}
else {
encodeUrl = urlString;
}
fmt::format_to( std::back_inserter( result ),
R"(<iframe id="gdexpandframe-{}" src="{}"
fmt::format_to( std::back_inserter( result ),
R"(<iframe id="gdexpandframe-{}" src="{}"
onmouseover="processIframeMouseOver('gdexpandframe-{}');"
onmouseout="processIframeMouseOut();" scrolling="no"
style="overflow:visible; width:100%; display:block; border:none;"
sandbox="allow-same-origin allow-scripts allow-popups"></iframe>)",
getId(),
encodeUrl.toStdString(),
getId() );
getId(),
encodeUrl.toStdString(),
getId() );
}
auto dr = std::make_shared< DataRequestInstant >( true );
dr->appendString( result );
return dr;

View file

@ -81,16 +81,16 @@ QGestureRecognizer::Result GDPinchGestureRecognizer::recognize( QGesture * state
case QEvent::TouchUpdate: {
gest->scaleChanged = false;
const QTouchEvent * const ev = static_cast< const QTouchEvent * >( event );
fewTouchPointsPresented = ( ev->touchPoints().size() > 1 );
if ( ev->touchPoints().size() == 2 ) {
QTouchEvent::TouchPoint p1 = ev->touchPoints().at( 0 );
QTouchEvent::TouchPoint p2 = ev->touchPoints().at( 1 );
fewTouchPointsPresented = ( ev->points().size() > 1 );
if ( ev->points().size() == 2 ) {
QTouchEvent::TouchPoint p1 = ev->points().at( 0 );
QTouchEvent::TouchPoint p2 = ev->points().at( 1 );
QPointF centerPoint = ( p1.screenPos() + p2.screenPos() ) / 2.0;
QPointF centerPoint = ( p1.globalPosition() + p2.globalPosition() ) / 2.0;
gest->setHotSpot( centerPoint );
if ( gest->isNewSequence ) {
gest->startPosition[ 0 ] = p1.screenPos();
gest->startPosition[ 1 ] = p2.screenPos();
gest->startPosition[ 0 ] = p1.globalPosition();
gest->startPosition[ 1 ] = p2.globalPosition();
gest->lastCenterPoint = centerPoint;
}
else {
@ -105,8 +105,8 @@ QGestureRecognizer::Result GDPinchGestureRecognizer::recognize( QGesture * state
}
else {
gest->lastScaleFactor = gest->scaleFactor;
QLineF line( p1.screenPos(), p2.screenPos() );
QLineF lastLine( p1.lastScreenPos(), p2.lastScreenPos() );
QLineF line( p1.globalPosition(), p2.globalPosition() );
QLineF lastLine( p1.globalLastPosition(), p2.globalLastPosition() );
gest->scaleFactor = line.length() / lastLine.length();
}
@ -210,28 +210,28 @@ QGestureRecognizer::Result GDSwipeGestureRecognizer::recognize( QGesture * state
}
case QEvent::TouchUpdate: {
const QTouchEvent * const ev = static_cast< const QTouchEvent * >( event );
fewTouchPointsPresented = ( ev->touchPoints().size() > 1 );
fewTouchPointsPresented = ( ev->points().size() > 1 );
if ( !swipe->started )
result = QGestureRecognizer::CancelGesture;
else if ( ev->touchPoints().size() == 2 ) {
else if ( ev->points().size() == 2 ) {
//2-point gesture
QTouchEvent::TouchPoint p1 = ev->touchPoints().at( 0 );
QTouchEvent::TouchPoint p2 = ev->touchPoints().at( 1 );
QTouchEvent::TouchPoint p1 = ev->points().at( 0 );
QTouchEvent::TouchPoint p2 = ev->points().at( 1 );
if ( swipe->lastPositions[ 0 ].isNull() ) {
swipe->lastPositions[ 0 ] = p1.startScreenPos().toPoint();
swipe->lastPositions[ 1 ] = p2.startScreenPos().toPoint();
swipe->lastPositions[ 0 ] = p1.globalPressPosition().toPoint();
swipe->lastPositions[ 1 ] = p2.globalPressPosition().toPoint();
}
if ( !swipe->hasHotSpot() ) {
swipe->setHotSpot( ( p1.startScreenPos() + p2.startScreenPos() ) / 2 );
swipe->setHotSpot( ( p1.globalPressPosition() + p2.globalPressPosition() ) / 2 );
}
int dx1 = p1.screenPos().toPoint().x() - swipe->lastPositions[ 0 ].x();
int dx2 = p2.screenPos().toPoint().x() - swipe->lastPositions[ 1 ].x();
int dy1 = p1.screenPos().toPoint().y() - swipe->lastPositions[ 0 ].y();
int dy2 = p2.screenPos().toPoint().y() - swipe->lastPositions[ 1 ].y();
int dx1 = p1.globalPosition().toPoint().x() - swipe->lastPositions[ 0 ].x();
int dx2 = p2.globalPosition().toPoint().x() - swipe->lastPositions[ 1 ].x();
int dy1 = p1.globalPosition().toPoint().y() - swipe->lastPositions[ 0 ].y();
int dy2 = p2.globalPosition().toPoint().y() - swipe->lastPositions[ 1 ].y();
if ( qAbs( ( dx1 + dx2 ) / 2.0 ) >= MOVE_X_TRESHOLD || qAbs( ( dy1 + dy2 ) / 2.0 ) >= MOVE_Y_TRESHOLD ) {
qreal angle1 = computeAngle( dx1, dy1 );
@ -255,8 +255,8 @@ QGestureRecognizer::Result GDSwipeGestureRecognizer::recognize( QGesture * state
swipe->vertDirection = vertDir;
swipe->horizDirection = horizDir;
swipe->lastPositions[ 0 ] = p1.screenPos().toPoint();
swipe->lastPositions[ 1 ] = p2.screenPos().toPoint();
swipe->lastPositions[ 0 ] = p1.globalPosition().toPoint();
swipe->lastPositions[ 1 ] = p2.globalPosition().toPoint();
result = QGestureRecognizer::TriggerGesture;
}

View file

@ -698,7 +698,7 @@ bool HotkeyWrapper::isKeyGrabbed( quint32 keyCode, quint32 modifiers ) const
namespace {
typedef int ( *X11ErrorHandler )( Display * display, XErrorEvent * event );
using X11ErrorHandler = int ( * )( Display * display, XErrorEvent * event );
class X11GrabUngrabErrorHandler
{

View file

@ -142,7 +142,7 @@ private:
/// Holds all the keys currently grabbed.
/// The first value is keycode, the second is modifiers
typedef std::set< std::pair< quint32, quint32 > > GrabbedKeys;
using GrabbedKeys = std::set< std::pair< quint32, quint32 > >;
GrabbedKeys grabbedKeys;
GrabbedKeys::iterator keyToUngrab; // Used for second stage grabs

View file

@ -11,7 +11,7 @@ namespace Language {
/// This identifies any language uniquely within the program. It also has
/// two special meanings - Unknown and Any.
typedef quint32 Id;
using Id = quint32;
enum {
/// Value for Id which signifies that the language is unknown or unspecified.

View file

@ -20,17 +20,9 @@ MultimediaAudioPlayer::MultimediaAudioPlayer()
player( 0, QMediaPlayer::StreamPlayback )
#endif
{
typedef void ( QMediaPlayer::*ErrorSignal )( QMediaPlayer::Error );
#if ( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
connect( &player,
static_cast< ErrorSignal >( &QMediaPlayer::error ),
this,
&MultimediaAudioPlayer::onMediaPlayerError );
#else
player.setAudioOutput( &audioOutput );
connect( &player, &QMediaPlayer::errorChanged, this, &MultimediaAudioPlayer::onMediaPlayerError );
#endif
#if ( QT_VERSION > QT_VERSION_CHECK( 6, 2, 0 ) )
connect( &mediaDevices, &QMediaDevices::audioOutputsChanged, this, &MultimediaAudioPlayer::audioOutputChange );

View file

@ -85,7 +85,154 @@ QString ArticleView::scrollToFromDictionaryId( QString const & dictionaryId )
Q_ASSERT( !isScrollTo( dictionaryId ) );
return scrollToPrefix + dictionaryId;
}
ArticleView::ArticleView( QWidget * parent,
ArticleNetworkAccessManager & nm,
AudioPlayerPtr const & audioPlayer_,
Config::Class const & cfg_ ):
QWidget( parent ),
articleNetMgr( nm ),
audioPlayer( audioPlayer_ ),
cfg( cfg_ )
{
// setup GUI
setupWebview();
}
void ArticleView::setupWebview()
{ // setup GUI
this->webview = new ArticleWebView( this );
this->ftsSearchPanel = new FtsSearchPanel( this );
this->searchPanel = new SearchPanel( this );
this->searchPanel->hide();
this->ftsSearchPanel->hide();
auto * baseLayout = new QVBoxLayout( this );
this->tabWidget = new QTabWidget( this );
baseLayout->addWidget( this->tabWidget );
QWidget * tab1 = new QWidget( tabWidget );
// Layout
auto * mainLayout = new QVBoxLayout( tab1 );
mainLayout->addWidget( this->webview );
mainLayout->addWidget( this->ftsSearchPanel );
mainLayout->addWidget( this->searchPanel );
this->webview->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
this->ftsSearchPanel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
this->searchPanel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
mainLayout->setContentsMargins( 0, 0, 0, 0 );
this->tabWidget->addTab( tab1, "Dictionaries" );
this->tabWidget->setTabBarAutoHide( true );
// end UI setup
connect( this->searchPanel->previous, &QPushButton::clicked, this, &ArticleView::on_searchPrevious_clicked );
connect( this->searchPanel->next, &QPushButton::clicked, this, &ArticleView::on_searchNext_clicked );
connect( this->searchPanel->close, &QPushButton::clicked, this, &ArticleView::on_searchCloseButton_clicked );
connect( this->searchPanel->caseSensitive, &QCheckBox::toggled, this, &ArticleView::on_searchCaseSensitive_clicked );
connect( this->searchPanel->lineEdit, &QLineEdit::textEdited, this, &ArticleView::on_searchText_textEdited );
connect( this->searchPanel->lineEdit, &QLineEdit::returnPressed, this, &ArticleView::on_searchText_returnPressed );
connect( this->ftsSearchPanel->next, &QPushButton::clicked, this, &ArticleView::on_ftsSearchNext_clicked );
connect( this->ftsSearchPanel->previous, &QPushButton::clicked, this, &ArticleView::on_ftsSearchPrevious_clicked );
//
this->webview->setUp( const_cast< Config::Class * >( &this->cfg ) );
this->syncBackgroundColorWithCfgDarkReader();
this->goBackAction.setShortcut( QKeySequence( "Alt+Left" ) );
this->webview->addAction( &this->goBackAction );
connect( &this->goBackAction, &QAction::triggered, this, &ArticleView::back );
this->goForwardAction.setShortcut( QKeySequence( "Alt+Right" ) );
this->webview->addAction( &this->goForwardAction );
connect( &this->goForwardAction, &QAction::triggered, this, &ArticleView::forward );
this->webview->pageAction( QWebEnginePage::Copy )->setShortcut( QKeySequence::Copy );
this->webview->addAction( this->webview->pageAction( QWebEnginePage::Copy ) );
QAction * selectAll = this->webview->pageAction( QWebEnginePage::SelectAll );
selectAll->setShortcut( QKeySequence::SelectAll );
selectAll->setShortcutContext( Qt::WidgetWithChildrenShortcut );
this->webview->addAction( selectAll );
this->webview->setContextMenuPolicy( Qt::CustomContextMenu );
connect( this->webview, &QWebEngineView::loadFinished, this, &ArticleView::loadFinished );
connect( this->webview, &ArticleWebView::linkClicked, this, &ArticleView::linkClicked );
connect( this->webview->page(), &QWebEnginePage::titleChanged, this, &ArticleView::handleTitleChanged );
connect( this->webview, &QWidget::customContextMenuRequested, this, &ArticleView::contextMenuRequested );
connect( this->webview->page(), &QWebEnginePage::linkHovered, this, &ArticleView::linkHovered );
connect( this->webview, &ArticleWebView::doubleClicked, this, &ArticleView::doubleClicked );
this->pasteAction.setShortcut( QKeySequence::Paste );
this->webview->addAction( &this->pasteAction );
connect( &this->pasteAction, &QAction::triggered, this, &ArticleView::pasteTriggered );
this->articleUpAction.setShortcut( QKeySequence( "Alt+Up" ) );
this->webview->addAction( &this->articleUpAction );
connect( &this->articleUpAction, &QAction::triggered, this, &ArticleView::moveOneArticleUp );
this->articleDownAction.setShortcut( QKeySequence( "Alt+Down" ) );
this->webview->addAction( &this->articleDownAction );
connect( &this->articleDownAction, &QAction::triggered, this, &ArticleView::moveOneArticleDown );
this->selectCurrentArticleAction.setShortcut( QKeySequence( "Ctrl+Shift+A" ) );
this->selectCurrentArticleAction.setText( tr( "Select Current Article" ) );
this->webview->addAction( &this->selectCurrentArticleAction );
connect( &this->selectCurrentArticleAction, &QAction::triggered, this, &ArticleView::selectCurrentArticle );
this->copyAsTextAction.setShortcut( QKeySequence( "Ctrl+Shift+C" ) );
this->copyAsTextAction.setText( tr( "Copy as text" ) );
this->webview->addAction( &this->copyAsTextAction );
connect( &this->copyAsTextAction, &QAction::triggered, this, &ArticleView::copyAsText );
this->inspectAction.setShortcut( QKeySequence( Qt::Key_F12 ) );
this->inspectAction.setText( tr( "Inspect" ) );
this->webview->addAction( &this->inspectAction );
connect( &this->inspectAction, &QAction::triggered, this, &ArticleView::inspectElement );
this->webview->installEventFilter( this );
this->searchPanel->installEventFilter( this );
this->ftsSearchPanel->installEventFilter( this );
QWebEngineSettings * settings = this->webview->settings();
settings->setUnknownUrlSchemePolicy( QWebEngineSettings::UnknownUrlSchemePolicy::DisallowUnknownUrlSchemes );
#if ( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
settings->defaultSettings()->setAttribute( QWebEngineSettings::LocalContentCanAccessRemoteUrls, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::LocalContentCanAccessFileUrls, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::ErrorPageEnabled, false );
settings->defaultSettings()->setAttribute( QWebEngineSettings::LinksIncludedInFocusChain, false );
settings->defaultSettings()->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, false );
settings->defaultSettings()->setAttribute( QWebEngineSettings::JavascriptCanAccessClipboard, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::PrintElementBackgrounds, false );
#else
settings->setAttribute( QWebEngineSettings::LocalContentCanAccessRemoteUrls, true );
settings->setAttribute( QWebEngineSettings::LocalContentCanAccessFileUrls, true );
settings->setAttribute( QWebEngineSettings::ErrorPageEnabled, false );
settings->setAttribute( QWebEngineSettings::LinksIncludedInFocusChain, false );
settings->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, false );
settings->setAttribute( QWebEngineSettings::JavascriptCanAccessClipboard, true );
settings->setAttribute( QWebEngineSettings::PrintElementBackgrounds, false );
#endif
this->expandOptionalParts = this->cfg.preferences.alwaysExpandOptionalParts;
#ifndef Q_OS_MACOS
this->webview->grabGesture( Gestures::GDPinchGestureType );
this->webview->grabGesture( Gestures::GDSwipeGestureType );
#endif
}
ArticleView::ArticleView( QWidget * parent,
ArticleNetworkAccessManager & nm,
AudioPlayerPtr const & audioPlayer_,
@ -115,133 +262,11 @@ ArticleView::ArticleView( QWidget * parent,
translateLine( translateLine_ )
{
// setup GUI
webview = new ArticleWebView( this );
ftsSearchPanel = new FtsSearchPanel( this );
searchPanel = new SearchPanel( this );
searchPanel->hide();
ftsSearchPanel->hide();
// Layout
auto * mainLayout = new QVBoxLayout( this );
mainLayout->addWidget( webview );
mainLayout->addWidget( ftsSearchPanel );
mainLayout->addWidget( searchPanel );
setupWebview();
webview->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
ftsSearchPanel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
searchPanel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
mainLayout->setContentsMargins( 0, 0, 0, 0 );
// end UI setup
connect( searchPanel->previous, &QPushButton::clicked, this, &ArticleView::on_searchPrevious_clicked );
connect( searchPanel->next, &QPushButton::clicked, this, &ArticleView::on_searchNext_clicked );
connect( searchPanel->close, &QPushButton::clicked, this, &ArticleView::on_searchCloseButton_clicked );
connect( searchPanel->caseSensitive, &QCheckBox::toggled, this, &ArticleView::on_searchCaseSensitive_clicked );
connect( searchPanel->lineEdit, &QLineEdit::textEdited, this, &ArticleView::on_searchText_textEdited );
connect( searchPanel->lineEdit, &QLineEdit::returnPressed, this, &ArticleView::on_searchText_returnPressed );
connect( ftsSearchPanel->next, &QPushButton::clicked, this, &ArticleView::on_ftsSearchNext_clicked );
connect( ftsSearchPanel->previous, &QPushButton::clicked, this, &ArticleView::on_ftsSearchPrevious_clicked );
//
webview->setUp( const_cast< Config::Class * >( &cfg ) );
syncBackgroundColorWithCfgDarkReader();
goBackAction.setShortcut( QKeySequence( "Alt+Left" ) );
webview->addAction( &goBackAction );
connect( &goBackAction, &QAction::triggered, this, &ArticleView::back );
goForwardAction.setShortcut( QKeySequence( "Alt+Right" ) );
webview->addAction( &goForwardAction );
connect( &goForwardAction, &QAction::triggered, this, &ArticleView::forward );
webview->pageAction( QWebEnginePage::Copy )->setShortcut( QKeySequence::Copy );
webview->addAction( webview->pageAction( QWebEnginePage::Copy ) );
QAction * selectAll = webview->pageAction( QWebEnginePage::SelectAll );
selectAll->setShortcut( QKeySequence::SelectAll );
selectAll->setShortcutContext( Qt::WidgetWithChildrenShortcut );
webview->addAction( selectAll );
webview->setContextMenuPolicy( Qt::CustomContextMenu );
connect( webview, &QWebEngineView::loadFinished, this, &ArticleView::loadFinished );
connect( webview, &ArticleWebView::linkClicked, this, &ArticleView::linkClicked );
connect( webview->page(), &QWebEnginePage::titleChanged, this, &ArticleView::handleTitleChanged );
connect( webview, &QWidget::customContextMenuRequested, this, &ArticleView::contextMenuRequested );
connect( webview->page(), &QWebEnginePage::linkHovered, this, &ArticleView::linkHovered );
connect( webview, &ArticleWebView::doubleClicked, this, &ArticleView::doubleClicked );
pasteAction.setShortcut( QKeySequence::Paste );
webview->addAction( &pasteAction );
connect( &pasteAction, &QAction::triggered, this, &ArticleView::pasteTriggered );
articleUpAction.setShortcut( QKeySequence( "Alt+Up" ) );
webview->addAction( &articleUpAction );
connect( &articleUpAction, &QAction::triggered, this, &ArticleView::moveOneArticleUp );
articleDownAction.setShortcut( QKeySequence( "Alt+Down" ) );
webview->addAction( &articleDownAction );
connect( &articleDownAction, &QAction::triggered, this, &ArticleView::moveOneArticleDown );
selectCurrentArticleAction.setShortcut( QKeySequence( "Ctrl+Shift+A" ) );
selectCurrentArticleAction.setText( tr( "Select Current Article" ) );
webview->addAction( &selectCurrentArticleAction );
connect( &selectCurrentArticleAction, &QAction::triggered, this, &ArticleView::selectCurrentArticle );
copyAsTextAction.setShortcut( QKeySequence( "Ctrl+Shift+C" ) );
copyAsTextAction.setText( tr( "Copy as text" ) );
webview->addAction( &copyAsTextAction );
connect( &copyAsTextAction, &QAction::triggered, this, &ArticleView::copyAsText );
inspectAction.setShortcut( QKeySequence( Qt::Key_F12 ) );
inspectAction.setText( tr( "Inspect" ) );
webview->addAction( &inspectAction );
connect( &inspectAction, &QAction::triggered, this, &ArticleView::inspectElement );
webview->installEventFilter( this );
searchPanel->installEventFilter( this );
ftsSearchPanel->installEventFilter( this );
QWebEngineSettings * settings = webview->settings();
settings->setUnknownUrlSchemePolicy( QWebEngineSettings::UnknownUrlSchemePolicy::DisallowUnknownUrlSchemes );
#if ( QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 ) )
settings->defaultSettings()->setAttribute( QWebEngineSettings::LocalContentCanAccessRemoteUrls, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::LocalContentCanAccessFileUrls, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::ErrorPageEnabled, false );
settings->defaultSettings()->setAttribute( QWebEngineSettings::LinksIncludedInFocusChain, false );
settings->defaultSettings()->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, false );
settings->defaultSettings()->setAttribute( QWebEngineSettings::JavascriptCanAccessClipboard, true );
settings->defaultSettings()->setAttribute( QWebEngineSettings::PrintElementBackgrounds, false );
#else
settings->setAttribute( QWebEngineSettings::LocalContentCanAccessRemoteUrls, true );
settings->setAttribute( QWebEngineSettings::LocalContentCanAccessFileUrls, true );
settings->setAttribute( QWebEngineSettings::ErrorPageEnabled, false );
settings->setAttribute( QWebEngineSettings::LinksIncludedInFocusChain, false );
settings->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, false );
settings->setAttribute( QWebEngineSettings::JavascriptCanAccessClipboard, true );
settings->setAttribute( QWebEngineSettings::PrintElementBackgrounds, false );
#endif
auto html = articleNetMgr.getHtml( ResourceType::UNTITLE );
webview->setHtml( QString::fromStdString( html ) );
expandOptionalParts = cfg.preferences.alwaysExpandOptionalParts;
#ifndef Q_OS_MACOS
webview->grabGesture( Gestures::GDPinchGestureType );
webview->grabGesture( Gestures::GDSwipeGestureType );
#endif
auto html = this->articleNetMgr.getHtml( ResourceType::UNTITLE );
this->webview->setHtml( QString::fromStdString( html ) );
connect( GlobalBroadcaster::instance(), &GlobalBroadcaster::dictionaryChanges, this, &ArticleView::setActiveDictIds );
connect( GlobalBroadcaster::instance(), &GlobalBroadcaster::dictionaryClear, this, &ArticleView::dictionaryClear );
@ -440,19 +465,16 @@ void ArticleView::inspectElement()
void ArticleView::loadFinished( bool result )
{
setZoomFactor( cfg.preferences.zoomFactor );
QUrl url = webview->url();
qDebug() << "article view loaded url:" << url.url().left( 200 ) << result;
webview->unsetCursor();
if ( url.url() == "about:blank" ) {
return;
}
if ( !result ) {
qWarning() << "article loaded unsuccessful";
return;
}
QUrl url = webview->url();
if ( url.url() == "about:blank" ) {
return;
}
qDebug() << "article view loaded url:" << url.url().left( 50 ) << result;
if ( cfg.preferences.autoScrollToTargetArticle ) {
QString const scrollTo = Utils::Url::queryItemValue( url, "scrollto" );
@ -1229,7 +1251,7 @@ void ArticleView::syncBackgroundColorWithCfgDarkReader() const
{
// Only works Qt6.6.3+ https://bugreports.qt.io/browse/QTBUG-112013
#if QT_VERSION >= QT_VERSION_CHECK( 6, 6, 3 )
if ( cfg.preferences.darkReaderMode ) {
if ( cfg.preferences.darkReaderMode == Config::Dark::On ) {
webview->page()->setBackgroundColor( QColor( 39, 40, 40 ) );
}
else {
@ -1238,6 +1260,17 @@ void ArticleView::syncBackgroundColorWithCfgDarkReader() const
#endif
}
void ArticleView::openWebsiteInNewTab( QString name, QString url )
{
QString escaped = Utils::escapeAmps( name );
//found existed QWebEngineView.
auto * view = new QWebEngineView( this );
view->load( QUrl( url ) );
tabWidget->addTab( view, escaped );
}
void ArticleView::back()
{
@ -2165,6 +2198,11 @@ void ArticleView::clearContent()
webview->setHtml( QString::fromStdString( html ) );
}
void ArticleView::load( QString url )
{
webview->load( QUrl( url ) );
}
ResourceToSaveHandler::ResourceToSaveHandler( ArticleView * view, QString fileName ):
QObject( view ),

View file

@ -96,7 +96,10 @@ public:
QLineEdit const * translateLine,
QAction * dictionaryBarToggled = nullptr,
unsigned currentGroupId = 0 );
explicit ArticleView( QWidget * parent,
ArticleNetworkAccessManager & nm,
AudioPlayerPtr const & audioPlayer_,
Config::Class const & cfg_ );
void setCurrentGroupId( unsigned currengGrgId );
unsigned getCurrentGroupId();
@ -109,7 +112,7 @@ public:
~ArticleView();
void load( QString url );
/// Returns "gdfrom-" + dictionaryId.
static QString scrollToFromDictionaryId( QString const & dictionaryId );
@ -168,9 +171,12 @@ public:
/// \brief Set background as black if darkreader mode is enabled.
void syncBackgroundColorWithCfgDarkReader() const;
void openWebsiteInNewTab( QString name, QString url );
private:
// widgets
ArticleWebView * webview;
QTabWidget * tabWidget;
SearchPanel * searchPanel;
FtsSearchPanel * ftsSearchPanel;
@ -412,6 +418,7 @@ private:
QString getMutedForGroup( unsigned group );
QStringList getMutedDictionaries( unsigned group );
void setupWebview();
};
class ResourceToSaveHandler: public QObject

View file

@ -29,7 +29,8 @@ DictGroupWidget::DictGroupWidget( QWidget * parent,
vector< sptr< Dictionary::Class > > const & dicts,
Config::Group const & group ):
QWidget( parent ),
groupId( group.id )
groupId( group.id ),
groupName( group.name )
{
ui.setupUi( this );
ui.dictionaries->populate( Instances::Group( group, dicts, Config::Group() ).dictionaries, dicts );
@ -139,6 +140,7 @@ Config::Group DictGroupWidget::makeGroup() const
g.favoritesFolder = ui.favoritesFolder->text().replace( '\\', '/' );
g.name = groupName;
return g.makeConfigGroup();
}
@ -558,8 +560,7 @@ void DictGroupsWidget::populate( Config::Groups const & groups,
connect( gr, &DictGroupWidget::showDictionaryInfo, this, &DictGroupsWidget::showDictionaryInfo );
connect( gr->getModel(), &DictListModel::contentChanged, this, &DictGroupsWidget::tabDataChanged );
QString toolTipStr =
"\"" + tabText( x ) + "\"\n" + tr( "Dictionaries: " ) + QString::number( getDictionaryCountAt( x ) );
QString toolTipStr = tr( "Dictionaries: " ) + QString::number( getDictionaryCountAt( x ) );
setTabToolTip( x, toolTipStr );
}
@ -577,7 +578,6 @@ Config::Groups DictGroupsWidget::makeGroups() const
for ( int x = 0; x < count(); ++x ) {
result.push_back( dynamic_cast< DictGroupWidget & >( *widget( x ) ).makeGroup() );
result.back().name = Utils::unescapeAmps( tabText( x ) );
}
return result;
@ -648,6 +648,7 @@ int DictGroupsWidget::addNewGroup( QString const & name )
Config::Group newGroup;
newGroup.id = nextId++;
newGroup.name = name;
const auto gr = new DictGroupWidget( this, *allDicts, newGroup );
const int idx = insertTab( currentIndex() + 1, gr, Utils::escapeAmps( name ) );
@ -655,8 +656,7 @@ int DictGroupsWidget::addNewGroup( QString const & name )
connect( gr->getModel(), &DictListModel::contentChanged, this, &DictGroupsWidget::tabDataChanged );
const QString toolTipStr =
"\"" + tabText( idx ) + "\"\n" + tr( "Dictionaries: " ) + QString::number( getDictionaryCountAt( idx ) );
const QString toolTipStr = tr( "Dictionaries: " ) + QString::number( getDictionaryCountAt( idx ) );
setTabToolTip( idx, toolTipStr );
return idx;
}
@ -910,13 +910,13 @@ void DictGroupsWidget::groupsByMetadata()
addGroupBasedOnMap( groupToDicts );
}
QString DictGroupsWidget::getCurrentGroupName() const
{
const int current = currentIndex();
if ( current >= 0 ) {
return Utils::unescapeAmps( tabText( current ) );
auto * w = qobject_cast< DictGroupWidget * >( widget( current ) );
return w->name();
}
return {};
@ -927,6 +927,8 @@ void DictGroupsWidget::renameCurrentGroup( QString const & name )
const int current = currentIndex();
if ( current >= 0 ) {
auto * w = dynamic_cast< DictGroupWidget * >( widget( current ) );
w->setName( name );
setTabText( current, Utils::escapeAmps( name ) );
}
}
@ -971,8 +973,7 @@ void DictGroupsWidget::combineGroups( int source, int target )
connect( model, &DictListModel::contentChanged, this, &DictGroupsWidget::tabDataChanged );
const QString toolTipStr = "\"" + tabText( target ) + "\"\n" + tr( "Dictionaries: " )
+ QString::number( model->getCurrentDictionaries().size() );
const QString toolTipStr = tr( "Dictionaries: " ) + QString::number( model->getCurrentDictionaries().size() );
setTabToolTip( target, toolTipStr );
}
@ -1124,8 +1125,8 @@ void DictGroupsWidget::contextMenu( QPoint const & pos )
void DictGroupsWidget::tabDataChanged()
{
const QString toolTipStr = "\"" + tabText( currentIndex() ) + "\"\n" + tr( "Dictionaries: " )
+ QString::number( getCurrentModel()->getCurrentDictionaries().size() );
const QString toolTipStr =
tr( "Dictionaries: " ) + QString::number( getCurrentModel()->getCurrentDictionaries().size() );
setTabToolTip( currentIndex(), toolTipStr );
}

View file

@ -121,9 +121,6 @@ class DictGroupWidget: public QWidget
public:
DictGroupWidget( QWidget * parent, std::vector< sptr< Dictionary::Class > > const &, Config::Group const & );
/// Makes the group's configuration out of the data currently held.
/// Since the group's name is not part of the widget by design right now
/// (it is known by the containing tab widget only), it is returned as empty.
Config::Group makeGroup() const;
DictListModel * getModel() const
@ -136,6 +133,16 @@ public:
return ui.dictionaries->selectionModel();
}
QString name()
{
return groupName;
}
void setName( const QString & name )
{
groupName = name;
}
private slots:
void groupIconActivated( int );
@ -145,6 +152,7 @@ private slots:
private:
Ui::DictGroupWidget ui;
unsigned groupId;
QString groupName;
signals:
void showDictionaryInfo( QString const & id );

View file

@ -36,6 +36,8 @@
#include <QThreadPool>
#include <QSslConfiguration>
#include <QStyleFactory>
#include <QStyleHints>
#include "weburlrequestinterceptor.hh"
#include "folding.hh"
@ -61,6 +63,7 @@
#include <windows.h>
#endif
#include <QGuiApplication>
#include <QWebEngineSettings>
#include <QProxyStyle>
@ -713,6 +716,10 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
&GlobalBroadcaster::indexingDictionary,
this,
&MainWindow::showFTSIndexingName );
connect( GlobalBroadcaster::instance(),
&GlobalBroadcaster::websiteDictionary,
this,
&MainWindow::openWebsiteInNewTab );
connect( &GlobalBroadcaster::instance()->pronounce_engine,
&PronounceEngine::emitAudio,
@ -1318,7 +1325,7 @@ QPrinter & MainWindow::getPrinter()
void MainWindow::updateAppearances( QString const & addonStyle,
QString const & displayStyle,
bool const & darkMode
Config::Dark darkMode
#if !defined( Q_OS_WIN )
,
const QString & interfaceStyle
@ -1326,7 +1333,7 @@ void MainWindow::updateAppearances( QString const & addonStyle,
)
{
#ifdef Q_OS_WIN32
if ( darkMode ) {
if ( darkMode == Config::Dark::On ) {
//https://forum.qt.io/topic/101391/windows-10-dark-theme
QPalette darkPalette;
@ -1381,7 +1388,7 @@ void MainWindow::updateAppearances( QString const & addonStyle,
// Load an additional stylesheet
// Dark Mode doesn't work nice with custom qt style sheets,
if ( !darkMode ) {
if ( darkMode == Config::Dark::Off ) {
QFile additionalStyle( QString( ":qt-%1.css" ).arg( displayStyle ) );
if ( additionalStyle.open( QFile::ReadOnly ) ) {
css += additionalStyle.readAll();
@ -1406,7 +1413,7 @@ void MainWindow::updateAppearances( QString const & addonStyle,
}
#ifdef Q_OS_WIN32
if ( darkMode ) {
if ( darkMode == Config::Dark::On ) {
css += "QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }";
}
#endif
@ -2169,7 +2176,7 @@ void MainWindow::updateBackForwardButtons()
{
ArticleView * view = getCurrentArticleView();
if ( view ) {
if ( view != nullptr ) {
navBack->setEnabled( view->canGoBack() );
navForward->setEnabled( view->canGoForward() );
}
@ -2178,7 +2185,12 @@ void MainWindow::updateBackForwardButtons()
void MainWindow::updatePronounceAvailability()
{
if ( ui.tabWidget->count() > 0 ) {
getCurrentArticleView()->hasSound( [ this ]( bool has ) {
ArticleView * pView = getCurrentArticleView();
if ( pView == nullptr ) {
return;
}
pView->hasSound( [ this ]( bool has ) {
navPronounce->setEnabled( has );
} );
}
@ -2321,6 +2333,7 @@ void MainWindow::editPreferences()
|| cfg.preferences.collapseBigArticles != p.collapseBigArticles
|| cfg.preferences.articleSizeLimit != p.articleSizeLimit
|| cfg.preferences.alwaysExpandOptionalParts != p.alwaysExpandOptionalParts // DSL format's special feature
|| p.darkReaderMode == Config::Dark::Auto // We cannot know if a reload is needed, just do it regardless.
);
// This line must be here because the components below require cfg's value to reconfigure
@ -2336,6 +2349,15 @@ void MainWindow::editPreferences()
if ( needReload ) {
view.reload();
}
#if QT_VERSION >= QT_VERSION_CHECK( 6, 5, 0 )
if ( cfg.preferences.darkReaderMode == Config::Dark::Auto ) {
connect( QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, &view, &ArticleView::reload );
}
else {
disconnect( QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, &view, &ArticleView::reload );
}
#endif
}
audioPlayerFactory.setPreferences( cfg.preferences );
@ -3705,7 +3727,13 @@ void MainWindow::messageFromAnotherInstanceReceived( QString const & message )
ArticleView * MainWindow::getCurrentArticleView()
{
if ( QWidget * cw = ui.tabWidget->currentWidget() ) {
return dynamic_cast< ArticleView * >( cw );
auto * pView = dynamic_cast< ArticleView * >( cw );
if ( pView != nullptr ) {
if ( pView->getParentView() != nullptr ) {
return pView->getParentView();
}
}
return pView;
}
return nullptr;
}
@ -4361,6 +4389,19 @@ void MainWindow::showFTSIndexingName( QString const & name )
}
}
void MainWindow::openWebsiteInNewTab( QString name, QString url )
{
// QString escaped = Utils::escapeAmps( name );
// auto * view = new ArticleView( this, articleNetMgr, audioPlayerFactory.player(), cfg );
// view->load( url );
// int index = cfg.preferences.newTabsOpenAfterCurrentOne ? ui.tabWidget->currentIndex() + 1 : ui.tabWidget->count();
// ui.tabWidget->insertTab( index, view, escaped );
// mruList.append( dynamic_cast< QWidget * >( view ) );
getCurrentArticleView()->addWebsiteTab( name, url );
}
QString MainWindow::unescapeTabHeader( QString const & header )
{
// Reset table header to original headword

View file

@ -190,7 +190,7 @@ private:
/// Applies Qt stylesheets, use Windows dark palette etc....
void updateAppearances( const QString & addonStyle,
const QString & displayStyle,
const bool & darkMode
Config::Dark darkMode
#if !defined( Q_OS_WIN )
,
const QString & interfaceStyle
@ -293,6 +293,7 @@ private slots:
void openDictionaryFolder( QString const & id );
void showFTSIndexingName( QString const & name );
void openWebsiteInNewTab( QString name, QString url );
void handleAddToFavoritesButton();

View file

@ -181,9 +181,27 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
ui.selectBySingleClick->setChecked( p.selectWordBySingleClick );
ui.autoScrollToTargetArticle->setChecked( p.autoScrollToTargetArticle );
ui.escKeyHidesMainWindow->setChecked( p.escKeyHidesMainWindow );
ui.darkMode->setChecked( p.darkMode );
ui.darkReaderMode->setChecked( p.darkReaderMode );
ui.darkMode->addItem( tr( "On" ), QVariant::fromValue( Config::Dark::On ) );
ui.darkMode->addItem( tr( "Off" ), QVariant::fromValue( Config::Dark::Off ) );
if ( auto i = ui.darkMode->findData( QVariant::fromValue( p.darkMode ) ); i != -1 ) {
ui.darkMode->setCurrentIndex( i );
}
ui.darkReaderMode->addItem( tr( "Auto" ), QVariant::fromValue( Config::Dark::Auto ) );
ui.darkReaderMode->setItemData( 0, tr( "Auto does nothing on some systems." ), Qt::ToolTipRole );
ui.darkReaderMode->addItem( tr( "On" ), QVariant::fromValue( Config::Dark::On ) );
ui.darkReaderMode->addItem( tr( "Off" ), QVariant::fromValue( Config::Dark::Off ) );
if ( auto i = ui.darkReaderMode->findData( QVariant::fromValue( p.darkReaderMode ) ); i != -1 ) {
ui.darkReaderMode->setCurrentIndex( i );
}
#ifndef Q_OS_WIN32
// TODO: make this availiable on other platforms
ui.darkModeLabel->hide();
ui.darkMode->hide();
#endif
@ -336,6 +354,7 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
//Misc
ui.removeInvalidIndexOnExit->setChecked( p.removeInvalidIndexOnExit );
ui.openWebsiteInNewTab->setChecked( p.openWebsiteInNewTab );
// Add-on styles
ui.addonStylesLabel->setVisible( ui.addonStyles->count() > 1 );
@ -413,8 +432,9 @@ Config::Preferences Preferences::getPreferences()
p.autoScrollToTargetArticle = ui.autoScrollToTargetArticle->isChecked();
p.escKeyHidesMainWindow = ui.escKeyHidesMainWindow->isChecked();
p.darkMode = ui.darkMode->isChecked();
p.darkReaderMode = ui.darkReaderMode->isChecked();
p.darkMode = ui.darkMode->currentData().value< Config::Dark >();
p.darkReaderMode = ui.darkReaderMode->currentData().value< Config::Dark >();
p.enableMainWindowHotkey = ui.enableMainWindowHotkey->isChecked();
p.mainWindowHotkey = ui.mainWindowHotkey->keySequence();
p.enableClipboardHotkey = ui.enableClipboardHotkey->isChecked();
@ -494,6 +514,7 @@ Config::Preferences Preferences::getPreferences()
p.clearNetworkCacheOnExit = ui.clearNetworkCacheOnExit->isChecked();
p.removeInvalidIndexOnExit = ui.removeInvalidIndexOnExit->isChecked();
p.openWebsiteInNewTab = ui.openWebsiteInNewTab->isChecked();
p.addonStyle = ui.addonStyles->getCurrentStyle();

View file

@ -397,24 +397,46 @@ the application.</string>
</layout>
</item>
<item>
<widget class="QCheckBox" name="darkMode">
<property name="toolTip">
<string>Turn the UI to dark.</string>
</property>
<property name="text">
<string>Dark Mode</string>
</property>
</widget>
<layout class="QHBoxLayout" name="darkModeLayout">
<item>
<widget class="QLabel" name="darkModeLabel">
<property name="toolTip">
<string>Turn the UI to dark.</string>
</property>
<property name="text">
<string>Dark Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="darkMode">
<property name="toolTip">
<string>Turn the UI to dark.</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="darkReaderMode">
<property name="toolTip">
<string>Turn the article display style to dark.</string>
</property>
<property name="text">
<string>Dark Reader Mode</string>
</property>
</widget>
<layout class="QHBoxLayout" name="darkReaderLayout">
<item>
<widget class="QLabel" name="darkReaderModeLabel">
<property name="toolTip">
<string>Turn the article display style to dark.</string>
</property>
<property name="text">
<string>Dark Reader Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="darkReaderMode">
<property name="toolTip">
<string>Turn the article display style to dark.</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_5">
@ -1916,6 +1938,13 @@ from Stardict, Babylon and GLS dictionaries</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="openWebsiteInNewTab">
<property name="text">
<string>Open website dictionary in seperate tab</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View file

@ -727,7 +727,7 @@ bool ScanPopup::eventFilter( QObject * watched, QEvent * event )
if ( event->type() == QEvent::MouseMove ) {
QMouseEvent * mouseEvent = (QMouseEvent *)event;
reactOnMouseMove( mouseEvent->globalPos() );
reactOnMouseMove( mouseEvent->globalPosition() );
}
}
@ -751,9 +751,9 @@ bool ScanPopup::eventFilter( QObject * watched, QEvent * event )
return QMainWindow::eventFilter( watched, event );
}
void ScanPopup::reactOnMouseMove( QPoint const & p )
void ScanPopup::reactOnMouseMove( QPointF const & p )
{
if ( geometry().contains( p ) ) {
if ( geometry().contains( p.toPoint() ) ) {
// GD_DPRINTF( "got inside\n" );
hideTimer.stop();
@ -773,7 +773,7 @@ void ScanPopup::reactOnMouseMove( QPoint const & p )
// receiving this event, meaning there's basically nothing under the
// cursor.
if ( /*watched == this &&*/
!frameGeometry().adjusted( -proximity, -proximity, proximity, proximity ).contains( p ) ) {
!frameGeometry().adjusted( -proximity, -proximity, proximity, proximity ).contains( p.toPoint() ) ) {
// We've way too far from the window -- hide the popup
// If the mouse never entered the popup, hide the window instantly --
@ -794,14 +794,14 @@ void ScanPopup::mousePressEvent( QMouseEvent * ev )
// With mouse grabs, the press can occur anywhere on the screen, which
// might mean hiding the window.
if ( !frameGeometry().contains( ev->globalPos() ) ) {
if ( !frameGeometry().contains( ev->globalPosition().toPoint() ) ) {
hideWindow();
return;
}
if ( ev->button() == Qt::LeftButton ) {
startPos = ev->globalPos();
startPos = ev->globalPosition();
setCursor( Qt::ClosedHandCursor );
}
@ -811,15 +811,13 @@ void ScanPopup::mousePressEvent( QMouseEvent * ev )
void ScanPopup::mouseMoveEvent( QMouseEvent * event )
{
if ( event->buttons() && cursor().shape() == Qt::ClosedHandCursor ) {
QPoint newPos = event->globalPos();
QPoint delta = newPos - startPos;
QPointF newPos = event->globalPosition();
QPointF delta = newPos - startPos;
startPos = newPos;
// Move the window
move( pos() + delta );
move( ( pos() + delta ).toPoint() );
}
QMainWindow::mouseMoveEvent( event );

View file

@ -148,7 +148,7 @@ private:
bool mouseEnteredOnce = false;
bool mouseIntercepted = false;
QPoint startPos; // For window moving
QPointF startPos; // For window moving
QByteArray pinnedGeometry;
QTimer hideTimer; // When mouse leaves the window, a grace period is
@ -169,7 +169,7 @@ private:
/// Called from event filter or from mouseGrabPoll to handle mouse event
/// while it is being intercepted.
void reactOnMouseMove( QPoint const & p );
void reactOnMouseMove( QPointF const & p );
virtual void mousePressEvent( QMouseEvent * );
virtual void mouseMoveEvent( QMouseEvent * );

View file

@ -60,8 +60,8 @@ private:
// Maps lowercased string to the original one. This catches all duplicates
// without case sensitivity. Made as an array and a map indexing that array.
typedef std::list< OneResult > ResultsArray;
typedef std::map< gd::wstring, ResultsArray::iterator > ResultsIndex;
using ResultsArray = std::list< OneResult >;
using ResultsIndex = std::map< gd::wstring, ResultsArray::iterator >;
ResultsArray resultsArray;
ResultsIndex resultsIndex;