mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-27 15:24:05 +00:00
Compare commits
27 commits
665a891778
...
e894bf6ae6
Author | SHA1 | Date | |
---|---|---|---|
e894bf6ae6 | |||
8ad7291147 | |||
8d0859b932 | |||
349fcb6628 | |||
7a1df4b6c6 | |||
285a0d8882 | |||
8be7b65f29 | |||
fb45d2e036 | |||
d15081e723 | |||
673911b1c5 | |||
b6fa66df92 | |||
2f48993594 | |||
9315dda365 | |||
1418f9ab9e | |||
c0697ecdda | |||
701a4effb3 | |||
f9a3705942 | |||
2c91b78e13 | |||
c6387df392 | |||
43c982cf8a | |||
e07e730a09 | |||
ab214cfb05 | |||
c00239a1b1 | |||
469896bbf1 | |||
0d89c4ab56 | |||
9e99389cc3 | |||
6edfd15962 |
|
@ -12,3 +12,6 @@ b5349478cfb0dc2dd0de8c8e8aeebdd24cf7ac6b
|
|||
|
||||
# mass apply clang-tidy's readability-braces-around-statements
|
||||
a11c9e3aeca4329e1982d8fe26bacbb21ab50ddf
|
||||
|
||||
# mass apply clang-tidy's modernize-use-using
|
||||
d15081e723756eef053550dc9e06e31d7828dec3
|
||||
|
|
2
.github/workflows/Release-all.yml
vendored
2
.github/workflows/Release-all.yml
vendored
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 & );
|
||||
|
|
|
@ -26,6 +26,6 @@ signals:
|
|||
void error( QString message );
|
||||
};
|
||||
|
||||
typedef QScopedPointer< AudioPlayerInterface > AudioPlayerPtr;
|
||||
using AudioPlayerPtr = QScopedPointer< AudioPlayerInterface >;
|
||||
|
||||
#endif // AUDIOPLAYERINTERFACE_HH_INCLUDED
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
|
||||
#include <QString>
|
||||
|
||||
typedef QMap< QString, QString > Contexts;
|
||||
using Contexts = QMap< QString, QString >;
|
||||
#endif // BASE_TYPE_H
|
||||
|
|
|
@ -46,6 +46,8 @@ signals:
|
|||
void dictionaryClear( ActiveDictIds ad );
|
||||
|
||||
void indexingDictionary( QString );
|
||||
|
||||
void websiteDictionary( QString, QString );
|
||||
};
|
||||
|
||||
#endif // GLOBAL_GLOBALBROADCASTER_H
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
///
|
||||
|
||||
namespace gd {
|
||||
typedef char32_t wchar;
|
||||
typedef std::u32string wstring;
|
||||
using wchar = char32_t;
|
||||
using wstring = std::u32string;
|
||||
} // namespace gd
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -35,7 +35,8 @@ enum Property {
|
|||
Author,
|
||||
Copyright,
|
||||
Description,
|
||||
Email
|
||||
Email,
|
||||
Url,
|
||||
};
|
||||
|
||||
DEF_EX( Ex, "Dictionary error", std::exception )
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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( ©AsTextAction );
|
||||
connect( ©AsTextAction, &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 ),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 * );
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue