Only show application title once in window title (or none if window title is set to result); Fixes for translations handling; Set some window titles; Implement custom expression tooltip label to avoid some issues; Improvements/fixes for currency flags; Compatibility fixes for different Qt versions; Add About Qt menu item; Add man file; Add appdata file; Add missing translations.qrc; Update README

This commit is contained in:
Hanna K 2021-07-28 19:12:32 +02:00
parent d4aa3c11e1
commit 12fe1469c6
27 changed files with 6228 additions and 5607 deletions

32
README Normal file
View File

@ -0,0 +1,32 @@
Qalculate! Qt UI
Qalculate! is a multi-purpose cross-platform desktop calculator. It is simple
to use but provides power and versatility normally reserved for complicated
math packages, as well as useful tools for everyday needs (such as currency
conversion and percent calculation). Features include a large library of
customizable functions, unit calculations and conversion, symbolic calculations
(including integrals and equations), arbitrary precision, uncertainty
propagation, interval arithmetic, plotting, and a user-friendly interface (GTK,
Qt, and CLI).
1. Requirements
* Qt (>= 5.6)
* libqalculate (>= 3.19.0)
2. Installation
Instructions and download links for installers, binaries packages, and the
source code of released versions of Qalculate! are available at
https://qalculate.github.io/downloads.html.
In a terminal window in the top source code directory run
* qmake
* lrelease qalculate-qt.pro
(not required if using a release source tarball, only if using the git
version)
* make
* make install (as root, e.g. sudo make install)
The resulting executable is named qalculate-qt.

View File

@ -1 +1,20 @@
# qalculate-qt
# Qalculate! Qt UI
<a href="https://raw.githubusercontent.com/Qalculate/qalculate.github.io/master/images/qalculate-qt.png"><img src="https://raw.githubusercontent.com/Qalculate/qalculate.github.io/master/images/qalculate-qt.png" width="552"></a>
Qalculate! is a multi-purpose cross-platform desktop calculator. It is simple to use but provides power and versatility normally reserved for complicated math packages, as well as useful tools for everyday needs (such as currency conversion and percent calculation). Features include a large library of customizable functions, unit calculations and conversion, symbolic calculations (including integrals and equations), arbitrary precision, uncertainty propagation, interval arithmetic, plotting, and a user-friendly interface (GTK, Qt, and CLI).
## Requirements
* Qt (>= 5.6)
* libqalculate (>= 3.20.0)
## Installation
Instructions and download links for installers, binaries packages, and the source code of released versions of Qalculate! are available at https://qalculate.github.io/downloads.html.
In a terminal window in the top source code directory run
* `lrelease qalculate-qt.pro` *(not required if using a release source tarball, only if using the git version)*
* `qmake`
* `make`
* `make install` *(as root, e.g. `sudo make install`)*
The resulting executable is named `qalculate-qt`.

48
data/qalculate-qt.1 Normal file
View File

@ -0,0 +1,48 @@
.TH QALCULATE\-QT 1 "18 July 2021"
.SH NAME
qalculate-qt \- Powerful and easy to use desktop calculator
.SH SYNOPSIS
.B qalculate-qt
.RI [ options ]
.RI [ expression ]
.SH DESCRIPTION
Qalculate! is a multi-purpose cross-platform desktop calculator. It is simple
to use but provides power and versatility normally reserved for complicated
math packages, as well as useful tools for everyday needs (such as currency
conversion and percent calculation). Features include a large library of
customizable functions, unit calculations and conversion, physical constants,
symbolic calculations (including integrals and equations), arbitrary precision,
uncertainty propagation, interval arithmetic, plotting, and a user-friendly
interface.
.PP
\fBqalculate-qt\fP is the graphical user interface of Qalculate!.
.SH OPTIONS
.PP
.TP 8
.B \-f, \-\-file \fIFILE\fP
execute expressions and commands from a file
.PP
.TP 8
.B \-n, \-\-new\-instance
start a new instance of the application
.PP
.TP 8
.B \-\-title \fITITLE\fP
specify the window title
.PP
.TP 8
.B \-v, \-\-version
show application version and exit
.PP
There are additional general options (not specific for the application) which
can be listed with
.B \-\-help
.SH "SEE ALSO"
Full documentation at
.I https://qalculate.github.io/manual/
or in the Help menu
.SH BUGS
Please report any bugs at
.I https://github.com/Qalculate/qalculate-qt/issues
.SH AUTHORS
qalculate-qt was written by Hanna Knutsson <hanna.knutsson@protonmail.com>.

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>qalculate-gtk.desktop</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0+</project_license>
<name>Qalculate! (Qt UI)</name>
<name xml:lang="ca">Qalculate! (Qt UI)</name>
<name xml:lang="de">Qalculate! (Qt UI)</name>
<name xml:lang="es">Qalculate! (Qt UI)</name>
<name xml:lang="fr">Qalculate! (Qt UI)</name>
<name xml:lang="pt_BR">Qalculate! (Qt UI)</name>
<name xml:lang="ru">Qalculate! (Интерфейс GTK)</name>
<name xml:lang="sl">Qalculate! (vmesnik GTK)</name>
<name xml:lang="sv">Qalculate! (Qt UI)</name>
<name xml:lang="zh_CN">Qalculate! (Qt UI)</name>
<summary>Powerful and easy to use calculator</summary>
<summary xml:lang="ca">Calculadora poderosa i fàcil a usar</summary>
<summary xml:lang="de">Leistungsstarker und einfach zu bedienender Taschenrechner</summary>
<summary xml:lang="es">Calculadora poderosa y fácil de usar</summary>
<summary xml:lang="fr">Une calculatrice puissante et facile d'utilisation</summary>
<summary xml:lang="nl">Gemakkelijk te gebruiken rekenmachine met veel mogelijkheden</summary>
<summary xml:lang="pt_BR">Calculadora potente e fácil de usar</summary>
<summary xml:lang="ru">Мощный и простой в использовании калькулятор</summary>
<summary xml:lang="sl">Zmogljivo računalo, preprosto za uporabo</summary>
<summary xml:lang="sv">Kraftfull och användarvänlig miniräknare</summary>
<summary xml:lang="zh_CN">强大而易用的计算器</summary>
<description>
<p>Qalculate! is a multi-purpose cross-platform desktop calculator. It is simple to use but provides power and versatility normally reserved for complicated math packages, as well as useful tools for everyday needs (such as currency conversion and percent calculation).</p>
<p xml:lang="ca">El Qalculate! és una calculadora d'escriptori per a diverses plataformes i finalitats. És senzill a usar però proporciona poder i versatilitat que normalment es reserva als paquets de matemàtica complicats, així com eines útils per a necessitats diàries (com la conversió de monedes i calculació de percentatge).</p>
<p xml:lang="de">Qalculate! ist ein vielseitig einsetzbarer, plattformübergreifender Desktop-Rechner. Er ist einfach zu bedienen, bietet aber Leistung und Vielseitigkeit die normalerweise nur für komplizierte mathematische Pakete vorbehalten sind, sowie nützliche ls auch für den täglichen Bedarf (wie Währungsumrechnung und Prozentrechnung).</p>
<p xml:lang="es">Qalculate! es una calculadora para escritorio multiplataforma y multiuso. Es simple de usar pero dispone de poder y versatilidad normalmente reservada para paquetes de matemática complicados, así como herramientas útiles para necesidades diarias (como conversión de monedas y cálculo de porcentajes).</p>
<p xml:lang="fr">Qalculate! est une calculatrice de bureau polyvalente et multi-plateforme. Elle est simple d'utilisation mais offre une puissance et une polyvalence normalement réservées aux logiciels de mathématique complexe, ainsi que d'outils utiles au quotidien (tels que la conversion de devises et le calcul de pourcentages).</p>
<p xml:lang="pt_BR">Qalculate! é uma calculadora para desktop multiplataforma e multiuso. É simples de usar, mas fornece poder e versatilidade normalmente vistas em pacotes de matemática complicados, além de ferramentas úteis para as necessidades diárias (como conversão de moeda e cálculo de porcentagem).</p>
<p xml:lang="ru">Qalculate! - это универсальный кроссплатформенный настольный калькулятор. Он прост в использовании, но обеспечивает мощность и универсальность, обычно присущие сложным математическим программам, а также полезные инструменты для повседневных нужд (таких как конвертация валют и расчёт процентов).</p>
<p xml:lang="sl">Qalculate! je večnamensko namizno računalo, ki deluje na več platformah. Je preprosto za uporabo, prinaša pa tako napredna orodja, ponavadi značilna le za kompleksno matematično programje, kot tudi uporabna orodja za vsakodnevne potrebe (npr. pretvorbe valut ali izračun odstotkov).</p>
<p xml:lang="zh_CN">Qalculate!是一款多功能的跨平台桌面计算器。它简单易用,但却具有通常复杂的数学软件包所需的强大功能和多样性,以及满足日常所需的实用工具(如货币换算和百分比计算)。</p>
<p>Features include a large library of customizable functions, unit calculations and conversion, physical constants, symbolic calculations (including integrals and equations), arbitrary precision, uncertainty propagation, interval arithmetic, plotting, and a user-friendly interface.</p>
<p xml:lang="ca">Les característiques inclouen una biblioteca amplia de funcions personalitzables, calculació i conversió d'unitat, constants físics, càlculs simbòlics (incloent integrals i equacions), precisió arbitrària, propagació d'incertesa, aritmètica d'interval, dibuix i una interfície fàcil d'emprar.</p>
<p xml:lang="de">Zu den Leistungsmerkmalen gehören eine große Bibliothek anpassbarer Funktionen, Einheiten-berechnungen und -umrechnungen, physikalische Konstanten, symbolische Berechnungen (einschließlich Integrale und Gleichungen), beliebige Genauigkeit, Unsicherheits-fortpflanzung, Intervallarithmetik, Plotten und eine benutzerfreundliche Oberfläche.</p>
<p xml:lang="es">Las características incluyen una gran librería de funciones personalizables, cálculo y conversión de unidades, constantes físicas, cálculos simbólicos (incluyendo integrales y ecuaciones), precisión arbitraria, propagación de incertidumbre, aritmética de intervalos, graficado, y una interfaz amigable.</p>
<p xml:lang="fr">Les fonctionnalités incluent une grande bibliothèque de fonctions personnalisables, d'unités de calculs et de conversion, de constantes physiques, de calculs symboliques (y compris les intégrales et équations), de précision arbitraire, de propagation des incertitudes, d'arithmétique d'intervalle, de traçage et une interface facile d'utilisation.</p>
<p xml:lang="pt_BR">Os recursos incluem uma grande biblioteca de funções personalizáveis, cálculos e conversão de unidades, constantes físicas, cálculos simbólicos (incluindo integrais e equações), precisão arbitrária, propagação de erros, aritmética de intervalos, plotagem e uma interface amigável.</p>
<p xml:lang="ru">Возможности включают большую библиотеку настраиваемых функций, расчёт и преобразование единиц измерения, физические константы, символьные вычисления, включая интегралы и уравнения, произвольную точность, распространение неопределенности, интервальную арифметику, построение графиков и удобный интерфейс.</p>
<p xml:lang="sl">Program vsebuje obsežno knjižnjico prilagodljivih funkcij, enot, izračunov in pretvorb, fizikalnih konstant, simbolnih izračunov (tudi integrale in enačbe), poljubno natančnost, statistično negotovost, intervalno aritmetiko, grafe in uporabniku prijazen vmesnik.</p>
<p xml:lang="zh_CN">功能包括大量可定制函数库、单位计算与换算、物理常数、符号计算(包括积分和方程)、高精度计算、误差传递、区间运算、绘图和用户友好的界面。</p>
</description>
<screenshots>
<screenshot type="default">
<image>https://github.com/Qalculate/qalculate-gtk/raw/master/data/qalculate-qt-appdata-1.png</image>
<caption>The main window with keypad visible</caption>
</screenshot>
</screenshots>
<url type="homepage">https://qalculate.github.io</url>
<url type="bugtracker">https://github.com/Qalculate/qalculate-qt/issues</url>
<url type="help">https://qalculate.github.io/manual/index.html</url>
<url type="donation">https://www.paypal.me/HannaKnutsson</url>
<url type="translate">https://github.com/Qalculate/libqalculate/blob/master/README.translate</url>
<developer_name>Hanna Knutsson</developer_name>
<content_rating type="oars-1.0"/>
<kudos>
<kudo>HiDpiIcon</kudo>
<kudo>ModernToolkit</kudo>
<kudo>UserDocs</kudo>
</kudos>
<launchable type="desktop-id">qalculate-qt.desktop</launchable>
<provides>
<binary>qalculate-qt</binary>
</provides>
<translation type="qt">qalculate-qt</translation>
<releases>
<release version="3.20.0" date="2021-07-28">
<description>
<p>Initial version of the Qt user interface.</p>
</description>
</release>
</releases>
</component>

View File

@ -1,11 +1,41 @@
[Desktop Entry]
Version=1.0
Name=Qalculate! (Qt)
GenericName=Calculator
Exec=qalculate-qt
Icon=qalculate
Type=Application
Categories=Qt;Utility;Calculator;Science;Math;
X-KDE-StartupNotify=true
Terminal=false
GenericName[ca]=Calculadora
GenericName[de]=Taschenrechner
GenericName[es]=Calculadora
GenericName[fr]=Calculatrice
GenericName[pt_BR]=Calculadora
GenericName[ru]=Калькулятор
GenericName[sl]=Računalo
GenericName[sv]=Kalkylator
GenericName[zh_CN]=
Comment=Powerful and easy to use calculator
Comment[ca]=Calculadora poderosa i fàcil a usar
Comment[de]=Leistungsstarker und einfach zu bedienender Taschenrechner
Comment[es]=Calculadora poderosa y fácil de usar
Comment[fr]=Une calculatrice puissante et facile d'utilisation
Comment[nl]=Gemakkelijk te gebruiken rekenmachine met veel mogelijkheden
Comment[pt_BR]=Calculadora potente e fácil de usar
Comment[ru]=Мощный и простой в использовании калькулятор
Comment[sl]=Zmogljivo računalo, preprosto za uporabo
Comment[sv]=Kraftfull och användarvänlig miniräknare
Comment[zh_CN]=
TryExec=qalculate-qt
Exec=qalculate-qt
Icon=qalculate-qt
Terminal=false
Type=Application
StartupNotify=true
StartupWMClass=qalculate-qt
Categories=Qt;Utility;Calculator;Science;Math;
Keywords=calculation;arithmetic;scientific;financial;
Keywords[ca]=calculation;arithmetic;scientific;financial;
Keywords[de]=Berechnung;Arithmetik; Wissenschaft;Finanzen;
Keywords[es]=calculadora;aritmética;científica;financiera;
Keywords[fr]=calcul;arithmétique;scientifique;financier;
Keywords[pt_BR]=calculadora;aritmética;científica;financeira;
Keywords[ru]=расчёт;расчет;арифметика;научный;финансовый
Keywords[sl]=izračun;aritmetika;znanstveno;finančno;računalo;kalkulator;
Keywords[zh_CN]=;;;;

View File

@ -19,7 +19,6 @@
<file alias="actions/scalable/go-up.svg">data/scalable/go-up.svg</file>
<file alias="actions/scalable/function.svg">data/scalable/function.svg</file>
<file alias="actions/scalable/keypad.svg">data/scalable/input-dialpad.svg</file>
<file alias="actions/scalable/link.svg">data/scalable/link.svg</file>
<file alias="actions/scalable/number-bases.svg">data/scalable/number-bases.svg</file>
<file alias="actions/scalable/menu.svg">data/scalable/open-menu.svg</file>
<file alias="actions/scalable/rpn-swap.svg">data/scalable/rpn-swap.svg</file>
@ -42,7 +41,6 @@
<file alias="dark/actions/scalable/go-up.svg">data/scalable/go-up-dark.svg</file>
<file alias="dark/actions/scalable/function.svg">data/scalable/function-dark.svg</file>
<file alias="dark/actions/scalable/keypad.svg">data/scalable/input-dialpad-dark.svg</file>
<file alias="dark/actions/scalable/link.svg">data/scalable/link-dark.svg</file>
<file alias="dark/actions/scalable/number-bases.svg">data/scalable/number-bases-dark.svg</file>
<file alias="dark/actions/scalable/menu.svg">data/scalable/open-menu-dark.svg</file>
<file alias="dark/actions/scalable/rpn-swap.svg">data/scalable/rpn-swap-dark.svg</file>

View File

@ -8,29 +8,24 @@ isEmpty(DESKTOP_DIR) {
isEmpty(DESKTOP_ICON_DIR) {
DESKTOP_ICON_DIR = $$PREFIX/share/icons
}
equals(INSTALL_THEME_ICONS,"no") {
DEFINES += LOAD_QALCULATEICONS_FROM_FILE=1
}
unix:!equals(COMPILE_RESOURCES,"yes"):!android:!macx {
isEmpty(ICON_DIR) {
equals(INSTALL_THEME_ICONS,"no") {
ICON_DIR = $$PREFIX/share/qalculate-qt/icons
} else {
ICON_DIR = $$PREFIX/share/icons
}
isEmpty(TRANSLATIONS_DIR) {
TRANSLATIONS_DIR = $$PREFIX/share/qalculate-qt/translations
}
} else {
ICON_DIR = ":/icons"
DEFINES += RESOURCES_COMPILED=1
DEFINES += TRANSLATIONS_DIR=\\\"$$TRANSLATIONS_DIR\\\"
}
isEmpty(MAN_DIR) {
MAN_DIR = $$PREFIX/share/man
}
isEmpty(APPDATA_DIR) {
APPDATA_DIR = $$PREFIX/share/metainfo
}
TEMPLATE = app
TARGET = qalculate-qt
INCLUDEPATH += src
win32: {
LIBS += -lqalculate -lxml2 -lmpfr -liconv -lintl -lgmp -licuuc -lcurl
CONFIG += c++17
} else {
CONFIG += link_pkgconfig
PKGCONFIG += libqalculate
@ -39,6 +34,7 @@ CONFIG += qt
QT += widgets network
MOC_DIR = build
OBJECTS_DIR = build
DEFINES += VERSION=\\\"$$VERSION\\\"
HEADERS += src/calendarconversiondialog.h src/csvdialog.h src/expressionedit.h src/fpconversiondialog.h src/functioneditdialog.h src/functionsdialog.h src/historyview.h src/itemproxymodel.h src/keypadwidget.h src/matrixwidget.h src/plotdialog.h src/preferencesdialog.h src/qalculateqtsettings.h src/qalculatewindow.h src/unitsdialog.h src/unknowneditdialog.h src/variableeditdialog.h src/variablesdialog.h
@ -48,33 +44,55 @@ TRANSLATIONS = translations/qalculate-qt_ca.ts translations/qalculate-qt_de.ts t
unix:!equals(COMPILE_RESOURCES,"yes"):!android:!macx {
TRANSLATIONS = translations/qalculate-qt_ca.ts \
translations/qalculate-qt_de.ts \
translations/qalculate-qt_es.ts \
translations/qalculate-qt_fr.ts \
translations/qalculate-qt_nl.ts \
translations/qalculate-qt_pt_BR.ts \
translations/qalculate-qt_ru.ts \
translations/qalculate-qt_sl.ts \
translations/qalculate-qt_sv.ts \
translations/qalculate-qt_zh_CN.ts
target.path = $$PREFIX/bin
qm.files = translations/qalculate-qt_ca.qm \
translations/qalculate-qt_de.qm \
translations/qalculate-qt_es.qm \
translations/qalculate-qt_fr.qm \
translations/qalculate-qt_nl.qm \
translations/qalculate-qt_pt_BR.qm \
translations/qalculate-qt_ru.qm \
translations/qalculate-qt_sl.qm \
translations/qalculate-qt_sv.qm \
translations/qalculate-qt_zh_CN.qm
qm.path = $$TRANSLATIONS_DIR
desktop.files = data/qalculate-qt.desktop
desktop.path = $$DESKTOP_DIR
appicon16.files = data/16/qalculate-qt.png
appicon16.path = $$ICON_DIR/hicolor/16x16/apps
appicon22.files = data/22/qalculate-qt.png
appicon22.path = $$ICON_DIR/hicolor/22x22/apps
appicon32.files = data/32/qalculate-qt.png
appicon32.path = $$ICON_DIR/hicolor/32x32/apps
appicon64.files = data/64/qalculate-qt.png
appicon64.path = $$ICON_DIR/hicolor/64x64/apps
appicon128.files = data/128/qalculate-qt.png
appicon128.path = $$ICON_DIR/hicolor/128x128/apps
appiconsvg.files = data/scalable/qalculate-qt.svg
appiconsvg.path = $$ICON_DIR/hicolor/scalable/apps
appdata.files = data/qalculate-qt.appdata.xml
appdata.path = $$APPDATA_DIR
INSTALLS += target desktop \
appicon16.files = data/16/qalculate-qt.png
appicon16.path = $$DESKTOP_ICON_DIR/hicolor/16x16/apps
appicon22.files = data/22/qalculate-qt.png
appicon22.path = $$DESKTOP_ICON_DIR/hicolor/22x22/apps
appicon32.files = data/32/qalculate-qt.png
appicon32.path = $$DESKTOP_ICON_DIR/hicolor/32x32/apps
appicon64.files = data/64/qalculate-qt.png
appicon64.path = $$DESKTOP_ICON_DIR/hicolor/64x64/apps
appicon128.files = data/128/qalculate-qt.png
appicon128.path = $$DESKTOP_ICON_DIR/hicolor/128x128/apps
appiconsvg.files = data/scalable/qalculate-qt.svg
appiconsvg.path = $$DESKTOP_ICON_DIR/hicolor/scalable/apps
INSTALLS += target desktop appdata qm \
appicon16 appicon22 appicon32 appicon64 appicon128 appiconsvg
!equals($$DESKTOP_ICON_DIR, $$ICON_DIR) {
desktopappicon64.files = data/64/qalculate-qt.png
desktopappicon64.path = $$DESKTOP_ICON_DIR/hicolor/64x64/apps
INSTALLS += desktopappicon64
}
RESOURCES = icons.qrc flags.qrc translations.qrc
RESOURCES = icons.qrc flags.qrc
} else {
RESOURCES = icons.qrc flags.qrc translations.qrc
target.path = $$PREFIX/bin
@ -85,5 +103,11 @@ unix:!equals(COMPILE_RESOURCES,"yes"):!android:!macx {
INSTALLS += target desktop appicon64
}
unix:!android:!macx {
man.files = data/qalculate-qt.1
man.path = $$MAN_DIR/man1
INSTALLS += man
}
win32: RC_FILE = winicon.rc

View File

@ -30,6 +30,7 @@
#include "csvdialog.h"
CSVDialog::CSVDialog(bool do_import, QWidget *parent, MathStructure *current_result, KnownVariable *var) : QDialog(parent), b_import(do_import), o_variable(var), m_result(current_result) {
setWindowTitle(do_import ? tr("Import CSV File") : tr("Export CSV File"));
if(m_result && !m_result->isVector()) m_result = NULL;
QVBoxLayout *box = new QVBoxLayout(this);
QGridLayout *grid = new QGridLayout();

View File

@ -23,13 +23,21 @@
#include <QPainter>
#include <QToolTip>
#include <QTimer>
#include <QBasicTimer>
#include <QAction>
#include <QActionGroup>
#include <QMenu>
#include <QCalendarWidget>
#include <QDialog>
#include <QLabel>
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QStylePainter>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
# include <QScreen>
#else
# include <QDesktopWidget>
#endif
#include <QPushButton>
#include <QDebug>
@ -42,6 +50,163 @@
#define MATCH_ROLE (Qt::UserRole + 12)
#define IMATCH_ROLE (Qt::UserRole + 13)
class ExpressionTipLabel : public QLabel {
public:
QBasicTimer hideTimer, expireTimer;
ExpressionTipLabel(const QString &text, const QPoint &pos);
~ExpressionTipLabel();
void adjustTooltipScreen(const QPoint &pos);
void updateSize(const QPoint &pos);
bool eventFilter(QObject *, QEvent *) override;
void reuseTip(const QString &text, const QPoint &pos);
void hideTip();
void hideTipImmediately();
void restartExpireTimer();
void placeTip(const QPoint &pos, QWidget *w);
protected:
void timerEvent(QTimerEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
};
ExpressionTipLabel::ExpressionTipLabel(const QString &text, const QPoint &pos) : QLabel(NULL, Qt::ToolTip | Qt::BypassGraphicsProxyWidget) {
setForegroundRole(QPalette::ToolTipText);
setBackgroundRole(QPalette::ToolTipBase);
setPalette(QToolTip::palette());
ensurePolished();
setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, this));
setFrameStyle(QFrame::NoFrame);
setAlignment(Qt::AlignLeft);
setIndent(1);
qApp->installEventFilter(this);
setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0);
setMouseTracking(true);
reuseTip(text, pos);
}
void ExpressionTipLabel::restartExpireTimer() {
int time = 10000 + 40 * qMax(0, text().length()-100);
expireTimer.start(time, this);
hideTimer.stop();
}
void ExpressionTipLabel::reuseTip(const QString &text, const QPoint &pos) {
setText(text);
updateSize(pos);
restartExpireTimer();
}
void ExpressionTipLabel::updateSize(const QPoint &pos) {
QFontMetrics fm(font());
QSize extra(1, 0);
if(fm.descent() == 2 && fm.ascent() >= 11) ++extra.rheight();
setWordWrap(Qt::mightBeRichText(text()));
QSize sh = sizeHint();
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
QScreen *screen = QGuiApplication::screenAt(pos);
if(!screen) screen = QGuiApplication::primaryScreen();
if(screen) {
const qreal screenWidth = screen->geometry().width();
if(!wordWrap() && sh.width() > screenWidth) {
setWordWrap(true);
sh = sizeHint();
}
}
#endif
resize(sh + extra);
}
void ExpressionTipLabel::paintEvent(QPaintEvent *ev) {
QStylePainter p(this);
QStyleOptionFrame opt;
opt.initFrom(this);
p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
p.end();
QLabel::paintEvent(ev);
}
void ExpressionTipLabel::resizeEvent(QResizeEvent *e) {
QStyleHintReturnMask frameMask;
QStyleOption option;
option.initFrom(this);
if(style()->styleHint(QStyle::SH_ToolTip_Mask, &option, this, &frameMask)) setMask(frameMask.region);
QLabel::resizeEvent(e);
}
ExpressionTipLabel::~ExpressionTipLabel() {}
void ExpressionTipLabel::hideTip() {
if(!hideTimer.isActive()) hideTimer.start(300, this);
}
void ExpressionTipLabel::hideTipImmediately() {
close();
}
void ExpressionTipLabel::timerEvent(QTimerEvent *e) {
if(e->timerId() == hideTimer.timerId() || e->timerId() == expireTimer.timerId()) {
hideTimer.stop();
expireTimer.stop();
hideTipImmediately();
}
}
#if defined (Q_OS_QNX)
bool ExpressionTipLabel::eventFilter(QObject *o, QEvent *e) {
switch(e->type()) {
case QEvent::WindowActivate:
case QEvent::FocusIn:
return false;
case QEvent::WindowDeactivate:
if(o != this) return false;
hideTipImmediately();
break;
case QEvent::FocusOut:
if(reinterpret_cast<QWindow*>(o) != windowHandle()) return false;
hideTipImmediately();
break;
#else
bool ExpressionTipLabel::eventFilter(QObject*, QEvent *e) {
switch(e->type()) {
case QEvent::WindowActivate:
case QEvent::WindowDeactivate:
case QEvent::FocusIn:
case QEvent::FocusOut:
#endif
case QEvent::Close:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::Wheel:
hideTipImmediately();
break;
case QEvent::MouseMove:
hideTip();
break;
default:
break;
}
return false;
}
void ExpressionTipLabel::placeTip(const QPoint &pos, QWidget *w) {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
# if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QScreen *scr = w->screen();
# else
QScreen *scr = QGuiApplication::screenAt(pos);
# endif
if(!scr) scr = QGuiApplication::primaryScreen();
QRect screen = scr->geometry();
#else
QRect screen = QApplication::desktop()->screenGeometry(w);
#endif
QPoint p = pos;
p += QPoint(2, 16);
if(p.x() + this->width() > screen.x() + screen.width()) p.rx() -= 4 + this->width();
if(p.y() + this->height() > screen.y() + screen.height()) p.ry() -= 24 + this->height();
if(p.y() < screen.y()) p.setY(screen.y());
if(p.x() + this->width() > screen.x() + screen.width()) p.setX(screen.x() + screen.width() - this->width());
if(p.x() < screen.x()) p.setX(screen.x());
if(p.y() + this->height() > screen.y() + screen.height()) p.setY(screen.y() + screen.height() - this->height());
this->move(p);
}
bool last_is_operator(std::string str, bool allow_exp) {
remove_blank_ends(str);
if(str.empty()) return false;
@ -347,7 +512,6 @@ QSize HTMLDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd
QTextDocument doc;
doc.setDefaultFont(optionV4.font);
doc.setHtml(optionV4.text);
if(!index.data(Qt::DecorationRole).isNull()) return QSize(doc.idealWidth() + 32, doc.size().height() > 32 ? doc.size().height() : 32);
return QSize(doc.idealWidth(), doc.size().height());
}
@ -638,6 +802,7 @@ ExpressionEdit::ExpressionEdit(QWidget *parent) : QPlainTextEdit(parent) {
setAttribute(Qt::WA_InputMethodEnabled, settings->enable_input_method);
#endif
cmenu = NULL;
tipLabel = NULL;
completion_blocked = 0;
parse_blocked = 0;
block_add_to_undo = 0;
@ -752,9 +917,8 @@ ExpressionEdit::~ExpressionEdit() {}
item->setData(QVariant::fromValue(0), MATCH_ROLE); \
item->setData(QVariant::fromValue(0), IMATCH_ROLE); \
items.append(item); \
item = new QStandardItem(y); \
item = new QStandardItem(y + "&nbsp;&nbsp;<img height=\"16\" src=\"" + ":/data/flags/" + QString::fromStdString(u->referenceName()) + "\"/>"); \
item->setData(ifont, Qt::FontRole); \
item->setData(QIcon(":/data/flags/" + QString::fromStdString(u->referenceName()) + ".png"), Qt::DecorationRole); \
items.append(item); \
sourceModel->appendRow(items);
@ -1590,9 +1754,10 @@ void ExpressionEdit::blockCompletion(bool b) {
completion_blocked--;
}
}
#define HIDE_TOOLTIP if(tipLabel) {tipLabel->hideTipImmediately(); tipLabel->deleteLater(); tipLabel = NULL;}
void ExpressionEdit::blockParseStatus(bool b) {
if(b) {
QToolTip::hideText();
HIDE_TOOLTIP
if(toolTipTimer) toolTipTimer->stop();
parse_blocked++;
} else {
@ -1605,29 +1770,33 @@ void ExpressionEdit::blockUndo(bool b) {
}
void ExpressionEdit::showCurrentStatus() {
if(!expression_has_changed || completionView->isVisible() || current_status_text.isEmpty()) {
QToolTip::hideText();
HIDE_TOOLTIP
} else {
// fool QToolTip with zero width space
if(current_status_text == QToolTip::text()) current_status_text += QChar(0x200b);
QToolTip::showText(mapToGlobal(cursorRect().bottomRight()), current_status_text);
if(tipLabel && tipLabel->isVisible()) {
tipLabel->reuseTip(current_status_text, mapToGlobal(cursorRect().bottomRight()));
tipLabel->placeTip(mapToGlobal(cursorRect().bottomRight()), this);
} else {
if(tipLabel) tipLabel->deleteLater();
tipLabel = new ExpressionTipLabel(current_status_text, mapToGlobal(cursorRect().bottomRight()));
tipLabel->placeTip(mapToGlobal(cursorRect().bottomRight()), this);
tipLabel->showNormal();
}
}
}
void ExpressionEdit::setStatusText(const QString &text) {
if(toolTipTimer) toolTipTimer->stop();
if(text.isEmpty()) {
QToolTip::hideText();
HIDE_TOOLTIP
} else if(settings->display_expression_status) {
if(text.length() >= 30) {
current_status_text = "<font size=\"-1\">";
current_status_text += text;
current_status_text += text.toHtmlEscaped();
current_status_text += "</font>";
current_status_text.replace("\n", "<br>");
} else {
current_status_text = text;
}
// fool QToolTip with zero width space
current_status_text += QChar(0x200b);
if(settings->expression_status_delay > 0 && !QToolTip::isVisible()) {
if(settings->expression_status_delay > 0 && (!tipLabel || !tipLabel->isVisible())) {
if(!toolTipTimer) {
toolTipTimer = new QTimer(this);
toolTipTimer->setSingleShot(true);
@ -2103,9 +2272,6 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
}
parsed_had_errors = had_errors; parsed_had_warnings = had_warnings;
if(!str_f.empty()) {str_f += " "; parsed_expression.insert(0, str_f);}
gsub("&", "&amp;", parsed_expression);
gsub(">", "&gt;", parsed_expression);
gsub("<", "&lt;", parsed_expression);
if(had_errors) prev_parsed_expression = QString::fromStdString(parsed_expression_tooltip);
else prev_parsed_expression = QString::fromStdString(parsed_expression);
if(!b_func && show_tooltip) setStatusText(settings->chain_mode ? "" : prev_parsed_expression);
@ -2414,6 +2580,7 @@ void ExpressionEdit::highlightParentheses() {
if(textCursor().hasSelection()) return;
int pos = textCursor().position(), ipar2;
QString text = toPlainText();
if(pos >= text.length()) pos = text.length() - 1;
bool b = text.at(pos) == ')';
if(!b && pos > 0 && text.at(pos - 1) == ')') {
pos--;

View File

@ -24,6 +24,7 @@ class QTableView;
class QMenu;
class QAction;
class QTimer;
class ExpressionTipLabel;
struct CompletionData;
@ -62,6 +63,7 @@ class ExpressionEdit : public QPlainTextEdit {
QMenu *cmenu;
QAction *undoAction, *redoAction, *cutAction, *copyAction, *pasteAction, *deleteAction, *selectAllAction, *clearAction;
QTimer *completionTimer, *toolTipTimer;
ExpressionTipLabel *tipLabel;
QStringList expression_undo_buffer;
QList<int> expression_undo_pos;

View File

@ -45,7 +45,7 @@ int main(int argc, char **argv) {
QApplication app(argc, argv);
app.setApplicationName("qalculate-qt");
app.setApplicationDisplayName("Qalculate! (Qt)");
app.setApplicationDisplayName("Qalculate!");
app.setOrganizationName("qalculate");
app.setApplicationVersion(VERSION);
@ -54,7 +54,10 @@ int main(int argc, char **argv) {
QalculateTranslator eqtr;
app.installTranslator(&eqtr);
if(!settings->ignore_locale) {
if(translator.load(QLocale(), QLatin1String("qalculate-qt"), QLatin1String("_"), QLatin1String(":/translations"))) app.installTranslator(&translator);
#ifndef TRANSLATIONS_DIR
# define TRANSLATIONS_DIR ":/translations"
#endif
if(translator.load(QLocale(), QLatin1String("qalculate-qt"), QLatin1String("_"), QLatin1String(TRANSLATIONS_DIR))) app.installTranslator(&translator);
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
if(translator_qt.load(QLocale(), QLatin1String("qt"), QLatin1String("_"), QLibraryInfo::path(QLibraryInfo::TranslationsPath))) app.installTranslator(&translator_qt);
if(translator_qtbase.load(QLocale(), QLatin1String("qtbase"), QLatin1String("_"), QLibraryInfo::path(QLibraryInfo::TranslationsPath))) app.installTranslator(&translator_qtbase);

View File

@ -348,6 +348,7 @@ void PlotDialog::generatePlotSeries(MathStructure **x_vector, MathStructure **y_
i = 0;
if(plot_busy && plotThread->running) {
dialog = new QProgressDialog(tr("Calculating…"), tr("Cancel"), 0, 0, this);
dialog->setWindowTitle(tr("Calculating…"));
connect(dialog, SIGNAL(canceled()), this, SLOT(abort()));
dialog->setWindowModality(Qt::WindowModal);
dialog->show();

View File

@ -42,6 +42,7 @@ QString font_string(std::string str) {
}
PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) {
setWindowTitle(tr("Preferences"));
QVBoxLayout *topbox = new QVBoxLayout(this);
QTabWidget *tabs = new QTabWidget(this);
tabs->setUsesScrollButtons(false);

View File

@ -1043,6 +1043,7 @@ void QalculateQtSettings::fetchExchangeRates(int timeout, int n, QWidget *parent
if(fetch_thread.start() && fetch_thread.write(timeout) && fetch_thread.write(n)) {
if(fetch_thread.running) {
QProgressDialog *dialog = new QProgressDialog(tr("Fetching exchange rates…"), QString(), 0, 0, parent);
dialog->setWindowTitle(tr("Fetching exchange rates…"));
dialog->setWindowModality(Qt::WindowModal);
dialog->setMinimumDuration(200);
while(fetch_thread.running) {

View File

@ -22,8 +22,6 @@ class QByteArray;
bool can_display_unicode_string_function(const char *str, void *w);
#define VERSION "3.20.0"
#define EQUALS_IGNORECASE_AND_LOCAL(x,y,z) (equalsIgnoreCase(x, y) || equalsIgnoreCase(x, z.toStdString()))
#define EQUALS_IGNORECASE_AND_LOCAL_NR(x,y,z,a) (equalsIgnoreCase(x, y a) || (x.length() == z.length() + strlen(a) && equalsIgnoreCase(x.substr(0, x.length() - strlen(a)), z.toStdString()) && equalsIgnoreCase(x.substr(x.length() - strlen(a)), a)))
@ -118,8 +116,8 @@ class QalculateQtSettings : QObject {
std::string last_found_version;
std::vector<std::string> v_expression;
std::vector<std::vector<std::string>> v_result;
std::vector<std::vector<int>> v_exact;
std::vector<std::vector<std::string> > v_result;
std::vector<std::vector<int> > v_exact;
};

View File

@ -324,7 +324,8 @@ QalculateWindow::QalculateWindow() : QMainWindow() {
menu->addAction(tr("Help"), this, SLOT(help()), QKeySequence::HelpContents);
menu->addAction(tr("Report a Bug"), this, SLOT(reportBug()));
menu->addAction(tr("Check for Updates"), this, SLOT(checkVersion()));
menu->addAction(tr("About %1").arg(qApp->applicationDisplayName()), this, SLOT(showAbout()));
menu->addAction(tr("About %1").arg("Qt"), qApp, SLOT(aboutQt()));
menu->addAction(tr("About %1").arg("Qalculate!"), this, SLOT(showAbout()));
menu->addSeparator();
menu->addAction(tr("Quit"), qApp, SLOT(closeAllWindows()), QKeySequence::Quit);
tb->addWidget(menuAction);
@ -3181,6 +3182,7 @@ void QalculateWindow::calculateExpression(bool force, bool do_mathoperation, Mat
if(CALCULATOR->busy() && !was_busy) {
if(updateWindowTitle(tr("Calculating…"))) title_set = true;
dialog = new QProgressDialog(tr("Calculating…"), tr("Cancel"), 0, 0, this);
dialog->setWindowTitle(tr("Calculating…"));
connect(dialog, SIGNAL(canceled()), this, SLOT(abort()));
dialog->setWindowModality(Qt::WindowModal);
dialog->show();
@ -3566,6 +3568,7 @@ void QalculateWindow::executeCommand(int command_type, bool show_result, std::st
}
if(updateWindowTitle(progress_str)) title_set = true;
dialog = new QProgressDialog(progress_str, tr("Cancel"), 0, 0, this);
dialog->setWindowTitle(progress_str);
connect(dialog, SIGNAL(canceled()), this, SLOT(abortCommand()));
dialog->setWindowModality(Qt::WindowModal);
dialog->show();
@ -4060,6 +4063,7 @@ void QalculateWindow::setResult(Prefix *prefix, bool update_history, bool update
if(b_busy && viewThread->running) {
if(updateWindowTitle(tr("Processing…"))) title_set = true;
dialog = new QProgressDialog(tr("Processing…"), tr("Cancel"), 0, 0, this);
dialog->setWindowTitle(tr("Processing…"));
connect(dialog, SIGNAL(canceled()), this, SLOT(abort()));
dialog->setWindowModality(Qt::WindowModal);
dialog->show();
@ -4468,17 +4472,18 @@ bool QalculateWindow::updateWindowTitle(const QString &str, bool is_result) {
switch(settings->title_type) {
case TITLE_RESULT: {
if(str.isEmpty()) return false;
qApp->setApplicationDisplayName(QString());
if(!str.isEmpty()) setWindowTitle(str);
break;
}
case TITLE_APP_RESULT: {
if(!str.isEmpty()) setWindowTitle("Qalculate! (" + str + ")");
if(!str.isEmpty()) setWindowTitle(str);
break;
}
default: {
if(is_result) return false;
if(!str.isEmpty()) setWindowTitle("Qalculate! " + str);
else setWindowTitle("Qalculate!");
if(!str.isEmpty()) setWindowTitle(str);
else setWindowTitle(QString());
}
}
return true;

14
translations.qrc Normal file
View File

@ -0,0 +1,14 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>translations/qalculate-qt_ca.qm</file>
<file>translations/qalculate-qt_de.qm</file>
<file>translations/qalculate-qt_es.qm</file>
<file>translations/qalculate-qt_fr.qm</file>
<file>translations/qalculate-qt_nl.qm</file>
<file>translations/qalculate-qt_pt_BR.qm</file>
<file>translations/qalculate-qt_ru.qm</file>
<file>translations/qalculate-qt_sl.qm</file>
<file>translations/qalculate-qt_sv.qm</file>
<file>translations/qalculate-qt_zh_CN.qm</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff