pax_global_header00006660000000000000000000000064142302005660014510gustar00rootroot0000000000000052 comment=b71e7f382660068d6fef2b830263db01bf8bcb5e deepin-calculator-5.7.21/000077500000000000000000000000001423020056600151775ustar00rootroot00000000000000deepin-calculator-5.7.21/.clog.toml000066400000000000000000000001721423020056600170760ustar00rootroot00000000000000[clog] repository = "https://github.com/linuxdeepin/deepin-calculator" from-latest-tag = true changelog = "CHANGELOG.md" deepin-calculator-5.7.21/.github/000077500000000000000000000000001423020056600165375ustar00rootroot00000000000000deepin-calculator-5.7.21/.github/workflows/000077500000000000000000000000001423020056600205745ustar00rootroot00000000000000deepin-calculator-5.7.21/.github/workflows/backup-to-gitlab.yml000066400000000000000000000040441423020056600244460ustar00rootroot00000000000000name: backup to gitlab on: [push] concurrency: group: ${{ github.workflow }} cancel-in-progress: true jobs: backup-to-gitlab: if: github.repository_owner == 'linuxdeepin' name: backup-to-gitlab runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: repository: "linuxdeepin/jenkins-bridge-client" path: jenkins-bridge-client - name: Install Client run: | cd $GITHUB_WORKSPACE/jenkins-bridge-client go build . sudo install -Dvm755 jenkins-bridge-client -t /usr/bin/ - name: Trigger sync id: generate-runid run: | echo "::set-output name=RUN_ID::$(jenkins-bridge-client -triggerSync -token '${{ secrets.BRIDGETOKEN }}')" - name: Print log run: | jenkins-bridge-client -printlog -token "${{ secrets.BRIDGETOKEN }}" -runid "${{ steps.generate-runid.outputs.RUN_ID }}" backup-to-gitee: if: github.repository_owner == 'linuxdeepin' runs-on: ubuntu-latest steps: - name: create-repo run: | repo=${{ github.event.repository.name }} homepage="https://github.com/linuxdeepin/${repo}" description="mirror of ${homepage}" # remove '.' prefix repo=${repo#"."} curl -X POST --header 'Content-Type: application/json;charset=UTF-8' 'https://gitee.com/api/v5/enterprises/linuxdeepin/repos' -d '{"private": 1,"access_token":"${{ secrets.GITEE_SYNC_TOKEN }}","name":"'"$repo"'","description":"'"$description"'","homepage":"'"$homepage"'","has_issues":"false","has_wiki":"false","can_comment":"false"}' || true - name: push run: | git clone --bare https://github.com/linuxdeepin/${{ github.event.repository.name }}.git .git repo=${{ github.event.repository.name }} # remove '.' prefix repo=${repo#"."} git remote set-url origin https://myml:${{ secrets.GITEE_SYNC_TOKEN }}@gitee.com/linuxdeepin/${repo}.git git push -f --all --prune origin git push --tags origin deepin-calculator-5.7.21/.github/workflows/call-build-deb.yml000066400000000000000000000005361423020056600240630ustar00rootroot00000000000000name: Call build-deb on: pull_request_target: paths-ignore: - ".github/workflows/**" concurrency: group: ${{ github.workflow }}-pull/${{ github.event.number }} cancel-in-progress: true jobs: check_job: uses: linuxdeepin/.github/.github/workflows/build-deb.yml@master secrets: BridgeToken: ${{ secrets.BridgeToken }} deepin-calculator-5.7.21/.github/workflows/call-chatOps.yml000066400000000000000000000003201423020056600236240ustar00rootroot00000000000000name: chatOps on: issue_comment: types: [created] jobs: chatopt: uses: linuxdeepin/.github/.github/workflows/chatOps.yml@master secrets: APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} deepin-calculator-5.7.21/.github/workflows/call-commitlint.yml000066400000000000000000000003641423020056600244120ustar00rootroot00000000000000name: Call commitlint on: pull_request_target: concurrency: group: ${{ github.workflow }}-pull/${{ github.event.number }} cancel-in-progress: true jobs: check_job: uses: linuxdeepin/.github/.github/workflows/commitlint.yml@master deepin-calculator-5.7.21/.github/workflows/cppcheck.yml000066400000000000000000000012651423020056600231030ustar00rootroot00000000000000name: cppcheck on: pull_request_target: paths-ignore: - ".github/workflows/**" concurrency: group: ${{ github.workflow }}-pull/${{ github.event.number }} cancel-in-progress: true jobs: cppchceck: name: cppcheck runs-on: ubuntu-latest steps: - run: export - uses: actions/checkout@v2 with: ref: ${{ github.event.pull_request.head.sha }} persist-credentials: false - uses: linuxdeepin/action-cppcheck@main with: github_token: ${{ secrets.GITHUB_TOKEN }} repository: ${{ github.repository }} pull_request_id: ${{ github.event.pull_request.number }} allow_approve: false deepin-calculator-5.7.21/.gitignore000066400000000000000000000000661423020056600171710ustar00rootroot00000000000000Makefile moc_*.o moc_*.cpp *.o *.qm build/ *.pro.user deepin-calculator-5.7.21/.project.json000066400000000000000000000001551423020056600176170ustar00rootroot00000000000000{ "type": "homebrew", "3rdparty": ["3rdparty"], "ignore": ["assets"], "license": ["GPLv3"] } deepin-calculator-5.7.21/.tx/000077500000000000000000000000001423020056600157105ustar00rootroot00000000000000deepin-calculator-5.7.21/.tx/config000066400000000000000000000006411423020056600171010ustar00rootroot00000000000000[main] host = https://www.transifex.com minimum_perc = 80 mode = developer [deepin-calculator.deepin-calculator] file_filter = translations/deepin-calculator_.ts source_file = translations/deepin-calculator.ts source_lang = en type = QT [deepin-calculator.deepin-calculator-desktop] file_filter = translations/desktop/desktop_.ts source_file = translations/desktop/desktop.ts source_lang = en type = QT deepin-calculator-5.7.21/.tx/ts2desktop000066400000000000000000000002551423020056600177370ustar00rootroot00000000000000DESKTOP_TEMP_FILE=deepin-calculator.desktop.tmp DESKTOP_SOURCE_FILE=deepin-calculator.desktop DESKTOP_DEST_FILE=deepin-calculator.desktop DESKTOP_TS_DIR=translations/desktopdeepin-calculator-5.7.21/3rdparty/000077500000000000000000000000001423020056600167475ustar00rootroot00000000000000deepin-calculator-5.7.21/3rdparty/core/000077500000000000000000000000001423020056600176775ustar00rootroot00000000000000deepin-calculator-5.7.21/3rdparty/core/book.cpp000066400000000000000000000425021423020056600213400ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2013, 2014 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "book.h" #define STYLE \ "" /*#define BEGIN QString("" STYLE "")+ #define SECTION(s) "

"+(s)+"

" #define BR "
" #define INDEX_LINK ""+Book::tr("Index")+"" #define LINK(link,text) ""+text+"" #define TITLE(s) "

"+(s)+"

" #define SUBTITLE(s) "

"#s+"

" #define FORMULA(link,text) ""#text"
" #define FORMULA_UNIT(link,text,unit) ""#text" "#unit"
" #define TABLE "" #define ROW "" #define _TABLE "
" #define VARIABLE(s) ""#s"" #define CAPTION(s) ""+(s)+"" #define END "" static QString makeIndexPage() { return BEGIN TITLE(Book::tr("Index")) SECTION(Book::tr("Algebra")) LINK(algebra/quadratic-equation, Book::tr("Quadratic Equation")) BR LINK(algebra/log-base-conversion, Book::tr("Logarithmic Base Conversion")) BR SECTION(Book::tr("Geometry")) LINK(geometry/circle, Book::tr("Circle")) BR LINK(geometry/sector, Book::tr("Sector")) BR LINK(geometry/sphere, Book::tr("Sphere")) BR LINK(geometry/cube, Book::tr("Cube")) BR LINK(geometry/cone, Book::tr("Cone")) BR LINK(geometry/cylinder, Book::tr("Cylinder")) BR SECTION(Book::tr("Unit Conversions")) LINK(units/temperature, Book::tr("Temperature")) BR SECTION(Book::tr("Electronics")) LINK(electronics/ohmslaw, Book::tr("Ohm's Law")) BR LINK(electronics/power, Book::tr("Power")) BR LINK(electronics/reactance, Book::tr("Reactance")) BR LINK(electronics/resonance, Book::tr("Resonance")) BR SECTION(Book::tr("Radio Frequency")) LINK(rf/antennas, Book::tr("Antennas")) BR LINK(rf/impedance, Book::tr("Characteristic Impedance (coax)")) BR LINK(rf/propagation, Book::tr("Velocity of Propagation (coax)")) BR LINK(rf/swr, Book::tr("Standing Wave Ratio & Return Loss")) BR LINK(rf/wavelength, Book::tr("Free Space Wavelength")) BR END; } static QString makeAlgebraQuadraticEquationPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Quadratic Equation")) SUBTITLE(a⋅x2 + b⋅x + c = 0) FORMULA(x1 = (-b + sqrt(b%5e2 - 4*a*c))/(2*a), x1 = (-b + √(b2 - 4⋅a⋅c)) / (2⋅a)) FORMULA(x2 = (-b - sqrt(b%5e2 - 4*a*c))/(2*a), x2 = (-b - √(b2 - 4⋅a⋅c)) / (2⋅a)) END; } static QString makeAlgebraLogBaseConversionPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Logarithmic Base Conversion")) FORMULA(y = log(x) / log(a), logax = log(x) / log(a)) END; } static QString makeElectronicsOhmsLawPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Ohm's Law")) FORMULA_UNIT(R = V / I, R = V / I, Ω) FORMULA_UNIT(V = I * R, V = I⋅R, V) FORMULA_UNIT(I = V / R, I = V / R, A) TABLE VARIABLE(R) CAPTION(Book::tr("resistance")) ROW VARIABLE(V) CAPTION(Book::tr("voltage")) ROW VARIABLE(I) CAPTION(Book::tr("current")) ROW _TABLE END; } static QString makeElectronicsPowerPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Power")) FORMULA_UNIT(P = I * V, P = I⋅V, W) FORMULA_UNIT(P = I%5e2 * R, P = I2⋅R, W) FORMULA_UNIT(P = V%5e2 / R, P = V2 / R, W) FORMULA_UNIT(I = P / V, I = P / V, A) FORMULA_UNIT(I = sqrt(P / R), I = √(P / R), A) FORMULA_UNIT(V = P / I, V = P / I, V) FORMULA_UNIT(V = sqrt(P * R), V = √(P⋅R), V) FORMULA_UNIT(R = V%5e2 / P, R = V2 / P, Ω) FORMULA_UNIT(R = P / I%5e2, R = P / I2, Ω) TABLE VARIABLE(P) CAPTION(Book::tr("power")) ROW VARIABLE(I) CAPTION(Book::tr("current")) ROW VARIABLE(V) CAPTION(Book::tr("voltage")) ROW VARIABLE(R) CAPTION(Book::tr("resistance")) ROW _TABLE END; } static QString makeElectronicsReactancePage() { return BEGIN INDEX_LINK TITLE(Book::tr("Reactance")) FORMULA_UNIT(Xl = 2 * pi * f * L, XL = 2⋅π⋅f⋅L, Ω) FORMULA_UNIT(Xc = 1 / (2 * pi * f * C), XC = 1 / (2⋅π⋅f⋅C), Ω) FORMULA_UNIT(L = Xl / (2 * pi * f), L = XL / (2⋅π⋅f), H) FORMULA_UNIT(C = 1 / (2 * pi * f * Xc), C = 1 / (2⋅π⋅f⋅XC), F) FORMULA_UNIT(f = Xl / (2 * pi * L), f = XL / (2⋅π⋅L), Hz) FORMULA_UNIT(f = 1 / (Xc * 2 * pi * C), f = 1 / (XC⋅2⋅π⋅C), Hz) TABLE VARIABLE(XL) CAPTION(Book::tr("inductive reactance")) ROW VARIABLE(XC) CAPTION(Book::tr("capacitive reactance")) ROW VARIABLE(L) CAPTION(Book::tr("inductance")) ROW VARIABLE(C) CAPTION(Book::tr("capacitance")) ROW VARIABLE(f) CAPTION(Book::tr("frequency")) ROW _TABLE END; } static QString makeElectronicsResonancePage() { return BEGIN INDEX_LINK TITLE(Book::tr("Resonance")) FORMULA_UNIT(f = 1 / (2 * pi * sqrt(L * C)), f = 1 / (2⋅π⋅√(L⋅C)), Hz) FORMULA_UNIT(L = 1 / (4 * pi%5e2 * f%5e2 * C), L = 1 / (4⋅π2⋅f2⋅C), H) FORMULA_UNIT(C = 1 / (4 * pi%5e2 * f%5e2 * L), C = 1 / (4⋅π2⋅f2⋅L), F) TABLE VARIABLE(f) CAPTION(Book::tr("resonance frequency")) ROW VARIABLE(L) CAPTION(Book::tr("inductance")) ROW VARIABLE(C) CAPTION(Book::tr("capacitance")) ROW _TABLE END; } static QString makeGeometryCirclePage() { return BEGIN INDEX_LINK TITLE(Book::tr("Circle")) FORMULA(A = pi * r^2, A = π⋅r2) FORMULA(A = pi * (d/2)^2, A = π⋅(d/2)2) FORMULA(P = 2 * pi * r, P = 2⋅π⋅r) FORMULA(P = pi * d, P = π⋅d) TABLE VARIABLE(A) CAPTION(Book::tr("area")) ROW VARIABLE(P) CAPTION(Book::tr("perimeter")) ROW VARIABLE(d) CAPTION(Book::tr("diameter")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) _TABLE END; } static QString makeGeometryConePage() { return BEGIN INDEX_LINK TITLE(Book::tr("Cone")) FORMULA(V = 1/3 * pi * r%5e2 * h, V = (1/3)⋅pi⋅r2⋅h) FORMULA(A = pi * r%5e2 + pi * r * s, A = π⋅r2 + π⋅r⋅s) FORMULA(A = pi * r%5e2 + pi * r * sqrt(r%5e2+h%5e2), A = π⋅r2 + π⋅r⋅√(r2+h2)) TABLE VARIABLE(V) CAPTION(Book::tr("volume")) ROW VARIABLE(A) CAPTION(Book::tr("surface area")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) ROW VARIABLE(h) CAPTION(Book::tr("height")) ROW VARIABLE(s) CAPTION(Book::tr("slant height")) _TABLE END; } static QString makeGeometryCubePage() { return BEGIN INDEX_LINK TITLE(Book::tr("Cube")) FORMULA(V = l%5e3, V = l3) FORMULA(A = 6 * l%5e2, A = 6⋅l2) FORMULA(Df = sqrt(2) * l, Df = √2⋅l) FORMULA(Ds = sqrt(3) * l, Ds = √3⋅l) TABLE VARIABLE(V) CAPTION(Book::tr("volume")) ROW VARIABLE(A) CAPTION(Book::tr("surface area")) ROW VARIABLE(Df) CAPTION(Book::tr("face diagonal")) ROW VARIABLE(Ds) CAPTION(Book::tr("space diagonal")) ROW VARIABLE(l) CAPTION(Book::tr("edge length")) _TABLE END; } static QString makeGeometryCylinderPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Cylinder")) FORMULA(V = pi * r%5e2 * h, V = π⋅r2⋅h) FORMULA(A = (2 * pi * r%5e2) + (2 * pi * r * h), A = 2⋅π⋅r2 + 2⋅π⋅r⋅h) TABLE VARIABLE(V) CAPTION(Book::tr("volume")) ROW VARIABLE(A) CAPTION(Book::tr("area")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) ROW VARIABLE(h) CAPTION(Book::tr("height")) _TABLE END; } static QString makeGeometrySectorPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Sector")) FORMULA(A = 1/2 * L * r, A = 1/2⋅L⋅r) FORMULA(A = theta/360 * pi * r^2, A = θ/360⋅π⋅r2) FORMULA(L = theta/180 * pi * r, L = θ/180⋅π⋅r) TABLE VARIABLE(A) CAPTION(Book::tr("area")) ROW VARIABLE(L) CAPTION(Book::tr("arc length")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) ROW VARIABLE(θ) CAPTION(Book::tr("central angle (degrees)")) _TABLE END; } static QString makeGeometrySpherePage() { return BEGIN INDEX_LINK TITLE(Book::tr("Sphere")) FORMULA(A = 4 * pi * r^2, A = 4⋅π⋅r2) FORMULA(A = pi *d^2, A = π⋅d2) FORMULA(V = 4/3 * pi * r^3, V = 4/3⋅π⋅r3) FORMULA(V = 1/6 * pi * d^3, V = 1/6⋅π⋅d3) TABLE VARIABLE(A) CAPTION(Book::tr("area")) ROW VARIABLE(V) CAPTION(Book::tr("volume")) ROW VARIABLE(r) CAPTION(Book::tr("radius")) ROW VARIABLE(d) CAPTION(Book::tr("diameter")) _TABLE END; } static QString makeRFAntennasPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Radio Frequency")) FORMULA_UNIT(Pd = Pin / (4 * pi * r%5e2), Pd = Pin / (4⋅π⋅r2), W⋅m-2) FORMULA_UNIT(E = sqrt(Pd * 120 * pi), E = √(Pd⋅120⋅π), V⋅m-1) FORMULA_UNIT(E = sqrt((Pin * 120 * pi) / (4 * pi * r%5e2)), E = √[(Pin⋅120⋅π) / (4⋅π⋅r2)], V⋅m-1) FORMULA_UNIT(E = sqrt(30 * Pin) / r, E = √(30⋅Pin) / r, V⋅m-1) FORMULA_UNIT(Ed = E * sqrt(D), Ed = E⋅√D, V⋅m-1) FORMULA_UNIT(Edp = E * sqrt(1.64), Edp = E⋅√1.64, V⋅m-1) END; } static QString makeRFImpedancePage() { return BEGIN INDEX_LINK TITLE(Book::tr("Characteristic Impedance (coax)")) FORMULA_UNIT(Zo = 59.959 / sqrt(er) * ln(d1/d2), Z0 = 59.959 / √er ⋅ ln(d1/d2), Ω) TABLE VARIABLE(er) CAPTION(Book::tr("dielectric constant")) ROW VARIABLE(d1) CAPTION(Book::tr("outer conductor's inner diameter")) ROW VARIABLE(d2) CAPTION(Book::tr("inner conductor's outer diameter")) _TABLE END; } static QString makeRFPropagationPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Velocity of Propagation (coax)")) SUBTITLE(Vp = c / √er) FORMULA_UNIT(Vp = 3e8 / sqrt(er), Vp = 3e8 / √er, m⋅s-1) FORMULA_UNIT(Vp = 299792458 / sqrt(er), Vp = 299792458 / √er, m⋅s-1) FORMULA_UNIT(Vp = 983571056.43045 / sqrt(er), Vp = 983571056.43045 / √er, ft⋅s-1) TABLE VARIABLE(c) CAPTION(Book::tr("speed of light")) ROW VARIABLE(e) CAPTION(Book::tr("dielectric constant")) ROW _TABLE END; } static QString makeRFSWRPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Standing Wave Ratio & Return Loss")) FORMULA(SWR = (1+r) / (1-r), SWR = (1 + ρ) / (1 - ρ)) FORMULA(r = (SWR-1) / (SWR+1), ρ = (SWR - 1) / (SWR + 1)) FORMULA(r = (Z-1) / (Z+1), ρ = (Z - 1) / (Z + 1)) FORMULA_UNIT(Z = (1+r) / (1-r), Z = (1 + ρ) / (1 - ρ), Ω) FORMULA_UNIT(RL = -20 * log(r), RL = -20⋅log(ρ), dB) FORMULA_UNIT(RL = -20 * log((SWR-1)/(SWR+1)), RL = -20⋅log[(SWR - 1) / (SWR + 1)], dB) FORMULA_UNIT(Pr = Pin * r%5e2, Pr = Pin⋅ρ2, W) FORMULA_UNIT(Pt = Pin * (1-r%5e2), Pt = Pin⋅(1-ρ2), W) TABLE VARIABLE(Pin) CAPTION(Book::tr("input power") + " (W)") ROW VARIABLE(Pr) CAPTION(Book::tr("reflected power") + " (W)") ROW VARIABLE(Pt) CAPTION(Book::tr("transmitted power") + " (W)") ROW VARIABLE(RL) CAPTION(Book::tr("return loss") + " (dB)") ROW VARIABLE(ρ) CAPTION(Book::tr("reflection coefficient")) ROW VARIABLE(SWR) CAPTION(Book::tr("standing wave ratio")) ROW VARIABLE(Z) CAPTION(Book::tr("normalized impedance")) ROW _TABLE END; } static QString makeRFWavelengthPage() { return BEGIN INDEX_LINK TITLE(Book::tr("Free Space Wavelength")) SUBTITLE(λ0 = c / f) FORMULA_UNIT(L = 3e8 / f, L = 3×108 / f, m) FORMULA_UNIT(L = 299792458 / f, L = 299792458 / f, m) FORMULA_UNIT(L = 983571056.43045 / f, L = 983571056.43045 / f, ft) TABLE VARIABLE(f) CAPTION(Book::tr("frequency (Hz)")) ROW _TABLE END; } static QString makeUnitsTemperaturePage() { return BEGIN INDEX_LINK TITLE(Book::tr("Temperature")) FORMULA(Tf = 1.8 * Tc + 32, Tf = 1.8 * Tc + 32) FORMULA(Tk = Tc + 273.15, Tk = Tc + 273.15) FORMULA(Tc = (Tf - 32) / 1.8, Tc = (Tf - 32) / 1.8) FORMULA(Tc = Tk - 273.15, Tc = Tk - 273.15) TABLE VARIABLE(Tc) CAPTION(Book::tr("temperature") + QString::fromUtf8(" (°C)")) ROW VARIABLE(Tf) CAPTION(Book::tr("temperature") + QString::fromUtf8(" (°F)")) ROW VARIABLE(Tk) CAPTION(Book::tr("temperature") + " (K)") _TABLE END; } void Book::createPages() { addPage("index", &makeIndexPage); addPage("algebra/quadratic-equation", &makeAlgebraQuadraticEquationPage); addPage("algebra/log-base-conversion", &makeAlgebraLogBaseConversionPage); addPage("electronics/ohmslaw", &makeElectronicsOhmsLawPage); addPage("electronics/power", &makeElectronicsPowerPage); addPage("electronics/reactance", &makeElectronicsReactancePage); addPage("electronics/resonance", &makeElectronicsResonancePage); addPage("geometry/circle", &makeGeometryCirclePage); addPage("geometry/cone", &makeGeometryConePage); addPage("geometry/cube", &makeGeometryCubePage); addPage("geometry/cylinder", &makeGeometryCylinderPage); addPage("geometry/sector", &makeGeometrySectorPage); addPage("geometry/sphere", &makeGeometrySpherePage); addPage("rf/antennas", &makeRFAntennasPage); addPage("rf/impedance", &makeRFImpedancePage); addPage("rf/propagation", &makeRFPropagationPage); addPage("rf/swr", &makeRFSWRPage); addPage("rf/wavelength", &makeRFWavelengthPage); addPage("units/temperature", &makeUnitsTemperaturePage); }*/ deepin-calculator-5.7.21/3rdparty/core/book.h000066400000000000000000000021711423020056600210030ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2013, 2014 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. /*#ifndef CORE_BOOK_H #define CORE_BOOK_H #include "src/core/pageserver.h" class Book : public PageServer { Q_OBJECT public: explicit Book(QObject* parent = 0) : PageServer(parent) { createPages(); } virtual void createPages(); private: Q_DISABLE_COPY(Book) }; #endif // CORE_BOOK_H*/ deepin-calculator-5.7.21/3rdparty/core/constants.cpp000066400000000000000000001656501423020056600224340ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2007, 2009, 2011, 2013, 2016 @heldercorreia // Copyright (C) 2009 Andreas Scherer // Copyright (C) 2016 Hadrien Theveneau // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. /*#include "src/core/constants.h" #include "src/core/numberformatter.h" #include "../math/hmath.h" #include #include static Constants* s_constantsInstance = nullptr; static void s_deleteConstants() { delete s_constantsInstance; } struct Constants::Private { QStringList categories; QList list; void populate(); void retranslateText(); }; // UNCERTAINTY and CHECKEC reserved for future use #define PUSH_CONSTANT_CODATA(NAME,VALUE,UNIT,UNCERTAINTY,CHECKED) \ c.value = QLatin1String(VALUE); \ c.unit = QString::fromUtf8(UNIT); \ list << c; #define PUSH_CONSTANT(NAME,VALUE,UNIT) \ c.value = QLatin1String(VALUE); \ c.unit = QString::fromUtf8(UNIT); \ list << c; #define PUSH_CONSTANT_NO_UNIT(NAME,VALUE) \ c.value = QLatin1String(VALUE); \ list << c; #define I18N_CONSTANT(NAME) \ i->name = NAME; \ i->category = cat; \ ++i; #define I18N_CONSTANT_DAYS(NAME) \ i->unit = days; \ I18N_CONSTANT(NAME) void Constants::Private::populate() { Constant c; // CODATA Internationally recommended values of the Fundamental Physical Constants // Constants not yet included, to be included in future releases (TODO) // From: http://physics.nist.gov/cuu/Constants/ // Date: 2016-03-28 // Quantity Value Uncertainty Unit // ----------------------------------------------------------------------------------------------------------------------------- // alpha particle-electron mass ratio 7294.299 541 36 0.000 000 24 // alpha particle mass 6.644 657 230 e-27 0.000 000 082 e-27 kg // alpha particle mass energy equivalent 5.971 920 097 e-10 0.000 000 073 e-10 J // alpha particle mass energy equivalent in MeV 3727.379 378 0.000 023 MeV // alpha particle mass in u 4.001 506 179 127 0.000 000 000 063 u // alpha particle molar mass 4.001 506 179 127 e-3 0.000 000 000 063 e-3 kg mol^-1 // alpha particle-proton mass ratio 3.972 599 689 07 0.000 000 000 36 // Angstrom star 1.000 014 95 e-10 0.000 000 90 e-10 m // atomic mass constant energy equivalent 1.492 418 062 e-10 0.000 000 018 e-10 J // atomic mass constant energy equivalent in MeV 931.494 0954 0.000 0057 MeV // atomic mass unit-electron volt relationship 931.494 0954 e6 0.000 0057 e6 eV // atomic mass unit-hartree relationship 3.423 177 6902 e7 0.000 000 0016 e7 E_h // atomic mass unit-hertz relationship 2.252 342 7206 e23 0.000 000 0010 e23 Hz // atomic mass unit-inverse meter relationship 7.513 006 6166 e14 0.000 000 0034 e14 m^-1 // atomic mass unit-joule relationship 1.492 418 062 e-10 0.000 000 018 e-10 J // atomic mass unit-kelvin relationship 1.080 954 38 e13 0.000 000 62 e13 K // atomic mass unit-kilogram relationship 1.660 539 040 e-27 0.000 000 020 e-27 kg // atomic unit of 1st hyperpolarizability 3.206 361 329 e-53 0.000 000 020 e-53 C^3 m^3 J^-2 // atomic unit of 2nd hyperpolarizability 6.235 380 085 e-65 0.000 000 077 e-65 C^4 m^4 J^-3 // atomic unit of action 1.054 571 800 e-34 0.000 000 013 e-34 J s // atomic unit of charge 1.602 176 6208 e-19 0.000 000 0098 e-19 C // atomic unit of charge density 1.081 202 3770 e12 0.000 000 0067 e12 C m^-3 // atomic unit of current 6.623 618 183 e-3 0.000 000 041 e-3 A // atomic unit of electric dipole mom. 8.478 353 552 e-30 0.000 000 052 e-30 C m // atomic unit of electric field 5.142 206 707 e11 0.000 000 032 e11 V m^-1 // atomic unit of electric field gradient 9.717 362 356 e21 0.000 000 060 e21 V m^-2 // atomic unit of electric polarizability 1.648 777 2731 e-41 0.000 000 0011 e-41 C^2 m^2 J^-1 // atomic unit of electric potential 27.211 386 02 0.000 000 17 V // atomic unit of electric quadrupole mom. 4.486 551 484 e-40 0.000 000 028 e-40 C m^2 // atomic unit of energy 4.359 744 650 e-18 0.000 000 054 e-18 J // atomic unit of force 8.238 723 36 e-8 0.000 000 10 e-8 N // atomic unit of length 0.529 177 210 67 e-10 0.000 000 000 12 e-10 m // atomic unit of mag. dipole mom. 1.854 801 999 e-23 0.000 000 011 e-23 J T^-1 // atomic unit of mag. flux density 2.350 517 550 e5 0.000 000 014 e5 T // atomic unit of magnetizability 7.891 036 5886 e-29 0.000 000 0090 e-29 J T^-2 // atomic unit of mass 9.109 383 56 e-31 0.000 000 11 e-31 kg // atomic unit of mom.um 1.992 851 882 e-24 0.000 000 024 e-24 kg m s^-1 // atomic unit of permittivity 1.112 650 056... e-10 (exact) F m^-1 // atomic unit of time 2.418 884 326 509 e-17 0.000 000 000 014 e-17 s // atomic unit of velocity 2.187 691 262 77 e6 0.000 000 000 50 e6 m s^-1 // Bohr magneton in eV/T 5.788 381 8012 e-5 0.000 000 0026 e-5 eV T^-1 // Bohr magneton in Hz/T 13.996 245 042 e9 0.000 000 086 e9 Hz T^-1 // Bohr magneton in inverse meters per tesla 46.686 448 14 0.000 000 29 m^-1 T^-1 // Bohr magneton in K/T 0.671 714 05 0.000 000 39 K T^-1 // Boltzmann constant in eV/K 8.617 3303 e-5 0.000 0050 e-5 eV K^-1 // Boltzmann constant in Hz/K 2.083 6612 e10 0.000 0012 e10 Hz K^-1 // Boltzmann constant in inverse meters per kelvin 69.503 457 0.000 040 m^-1 K^-1 // classical electron radius 2.817 940 3227 e-15 0.000 000 0019 e-15 m // Cu x unit 1.002 076 97 e-13 0.000 000 28 e-13 m // deuteron-electron mag. mom. ratio -4.664 345 535 e-4 0.000 000 026 e-4 // deuteron-electron mass ratio 3670.482 967 85 0.000 000 13 // deuteron g factor 0.857 438 2311 0.000 000 0048 // deuteron mag. mom. 0.433 073 5040 e-26 0.000 000 0036 e-26 J T^-1 // deuteron mag. mom. to Bohr magneton ratio 0.466 975 4554 e-3 0.000 000 0026 e-3 // deuteron mag. mom. to nuclear magneton ratio 0.857 438 2311 0.000 000 0048 // deuteron mass 3.343 583 719 e-27 0.000 000 041 e-27 kg // deuteron mass energy equivalent 3.005 063 183 e-10 0.000 000 037 e-10 J // deuteron mass energy equivalent in MeV 1875.612 928 0.000 012 MeV // deuteron mass in u 2.013 553 212 745 0.000 000 000 040 u // deuteron molar mass 2.013 553 212 745 e-3 0.000 000 000 040 e-3 kg mol^-1 // deuteron-neutron mag. mom. ratio -0.448 206 52 0.000 000 11 // deuteron-proton mag. mom. ratio 0.307 012 2077 0.000 000 0015 // deuteron-proton mass ratio 1.999 007 500 87 0.000 000 000 19 // deuteron rms charge radius 2.1413 e-15 0.0025 e-15 m // electron charge to mass quotient -1.758 820 024 e11 0.000 000 011 e11 C kg^-1 // electron-deuteron mag. mom. ratio -2143.923 499 0.000 012 // electron-deuteron mass ratio 2.724 437 107 484 e-4 0.000 000 000 096 e-4 // electron g factor -2.002 319 304 361 82 0.000 000 000 000 52 // electron gyromag. ratio 1.760 859 644 e11 0.000 000 011 e11 s^-1 T^-1 // electron gyromag. ratio over 2 pi 28 024.951 64 0.000 17 MHz T^-1 // electron-helion mass ratio 1.819 543 074 854 e-4 0.000 000 000 088 e-4 // electron mag. mom. -928.476 4620 e-26 0.000 0057 e-26 J T^-1 // electron mag. mom. anomaly 1.159 652 180 91 e-3 0.000 000 000 26 e-3 // electron mag. mom. to Bohr magneton ratio -1.001 159 652 180 91 0.000 000 000 000 26 // electron mag. mom. to nuclear magneton ratio -1838.281 972 34 0.000 000 17 // electron mass energy equivalent 8.187 105 65 e-14 0.000 000 10 e-14 J // electron mass in u 5.485 799 090 70 e-4 0.000 000 000 16 e-4 u // electron molar mass 5.485 799 090 70 e-7 0.000 000 000 16 e-7 kg mol^-1 // electron-muon mag. mom. ratio 206.766 9880 0.000 0046 // electron-muon mass ratio 4.836 331 70 e-3 0.000 000 11 e-3 // electron-neutron mag. mom. ratio 960.920 50 0.000 23 // electron-neutron mass ratio 5.438 673 4428 e-4 0.000 000 0027 e-4 // electron-proton mag. mom. ratio -658.210 6866 0.000 0020 // electron-proton mass ratio 5.446 170 213 52 e-4 0.000 000 000 52 e-4 // electron-tau mass ratio 2.875 92 e-4 0.000 26 e-4 // electron to alpha particle mass ratio 1.370 933 554 798 e-4 0.000 000 000 045 e-4 // electron to shielded helion mag. mom. ratio 864.058 257 0.000 010 // electron to shielded proton mag. mom. ratio -658.227 5971 0.000 0072 // electron-triton mass ratio 1.819 200 062 203 e-4 0.000 000 000 084 e-4 // electron volt-atomic mass unit relationship 1.073 544 1105 e-9 0.000 000 0066 e-9 u // electron volt-hartree relationship 3.674 932 248 e-2 0.000 000 023 e-2 E_h // electron volt-hertz relationship 2.417 989 262 e14 0.000 000 015 e14 Hz // electron volt-inverse meter relationship 8.065 544 005 e5 0.000 000 050 e5 m^-1 // electron volt-joule relationship 1.602 176 6208 e-19 0.000 000 0098 e-19 J // electron volt-kelvin relationship 1.160 452 21 e4 0.000 000 67 e4 K // electron volt-kilogram relationship 1.782 661 907 e-36 0.000 000 011 e-36 kg // elementary charge over h 2.417 989 262 e14 0.000 000 015 e14 A J^-1 // hartree-atomic mass unit relationship 2.921 262 3197 e-8 0.000 000 0013 e-8 u // hartree-electron volt relationship 27.211 386 02 0.000 000 17 eV // hartree-hertz relationship 6.579 683 920 711 e15 0.000 000 000 039 e15 Hz // hartree-inverse meter relationship 2.194 746 313 702 e7 0.000 000 000 013 e7 m^-1 // hartree-joule relationship 4.359 744 650 e-18 0.000 000 054 e-18 J // hartree-kelvin relationship 3.157 7513 e5 0.000 0018 e5 K // hartree-kilogram relationship 4.850 870 129 e-35 0.000 000 060 e-35 kg // helion-electron mass ratio 5495.885 279 22 0.000 000 27 // helion g factor -4.255 250 616 0.000 000 050 // helion mag. mom. -1.074 617 522 e-26 0.000 000 014 e-26 J T^-1 // helion mag. mom. to Bohr magneton ratio -1.158 740 958 e-3 0.000 000 014 e-3 // helion mag. mom. to nuclear magneton ratio -2.127 625 308 0.000 000 025 // helion mass 5.006 412 700 e-27 0.000 000 062 e-27 kg // helion mass energy equivalent 4.499 539 341 e-10 0.000 000 055 e-10 J // helion mass energy equivalent in MeV 2808.391 586 0.000 017 MeV // helion mass in u 3.014 932 246 73 0.000 000 000 12 u // helion molar mass 3.014 932 246 73 e-3 0.000 000 000 12 e-3 kg mol^-1 // helion-proton mass ratio 2.993 152 670 46 0.000 000 000 29 // hertz-atomic mass unit relationship 4.439 821 6616 e-24 0.000 000 0020 e-24 u // hertz-electron volt relationship 4.135 667 662 e-15 0.000 000 025 e-15 eV // hertz-hartree relationship 1.519 829 846 0088 e-16 0.000 000 000 0090 e-16 E_h // hertz-inverse meter relationship 3.335 640 951... e-9 (exact) m^-1 // hertz-joule relationship 6.626 070 040 e-34 0.000 000 081 e-34 J // hertz-kelvin relationship 4.799 2447 e-11 0.000 0028 e-11 K // hertz-kilogram relationship 7.372 497 201 e-51 0.000 000 091 e-51 kg // inverse fine-structure constant 137.035 999 139 0.000 000 031 // inverse meter-atomic mass unit relationship 1.331 025 049 00 e-15 0.000 000 000 61 e-15 u // inverse meter-electron volt relationship 1.239 841 9739 e-6 0.000 000 0076 e-6 eV // inverse meter-hartree relationship 4.556 335 252 767 e-8 0.000 000 000 027 e-8 E_h // inverse meter-hertz relationship 299 792 458 (exact) Hz // inverse meter-joule relationship 1.986 445 824 e-25 0.000 000 024 e-25 J // inverse meter-kelvin relationship 1.438 777 36 e-2 0.000 000 83 e-2 K // inverse meter-kilogram relationship 2.210 219 057 e-42 0.000 000 027 e-42 kg // joule-atomic mass unit relationship 6.700 535 363 e9 0.000 000 082 e9 u // joule-electron volt relationship 6.241 509 126 e18 0.000 000 038 e18 eV // joule-hartree relationship 2.293 712 317 e17 0.000 000 028 e17 E_h // joule-hertz relationship 1.509 190 205 e33 0.000 000 019 e33 Hz // joule-inverse meter relationship 5.034 116 651 e24 0.000 000 062 e24 m^-1 // joule-kelvin relationship 7.242 9731 e22 0.000 0042 e22 K // joule-kilogram relationship 1.112 650 056... e-17 (exact) kg // kelvin-atomic mass unit relationship 9.251 0842 e-14 0.000 0053 e-14 u // kelvin-electron volt relationship 8.617 3303 e-5 0.000 0050 e-5 eV // kelvin-hartree relationship 3.166 8105 e-6 0.000 0018 e-6 E_h // kelvin-hertz relationship 2.083 6612 e10 0.000 0012 e10 Hz // kelvin-inverse meter relationship 69.503 457 0.000 040 m^-1 // kelvin-joule relationship 1.380 648 52 e-23 0.000 000 79 e-23 J // kelvin-kilogram relationship 1.536 178 65 e-40 0.000 000 88 e-40 kg // kilogram-atomic mass unit relationship 6.022 140 857 e26 0.000 000 074 e26 u // kilogram-electron volt relationship 5.609 588 650 e35 0.000 000 034 e35 eV // kilogram-hartree relationship 2.061 485 823 e34 0.000 000 025 e34 E_h // kilogram-hertz relationship 1.356 392 512 e50 0.000 000 017 e50 Hz // kilogram-inverse meter relationship 4.524 438 411 e41 0.000 000 056 e41 m^-1 // kilogram-joule relationship 8.987 551 787... e16 (exact) J // kilogram-kelvin relationship 6.509 6595 e39 0.000 0037 e39 K // lattice parameter of silicon 543.102 0504 e-12 0.000 0089 e-12 m // molar mass constant 1 e-3 (exact) kg mol^-1 // molar mass of carbon-12 12 e-3 (exact) kg mol^-1 // molar Planck constant times c 0.119 626 565 582 0.000 000 000 054 J m mol^-1 // molar volume of ideal gas (273.15 K, 100 kPa) 22.710 947 e-3 0.000 013 e-3 m^3 mol^-1 // molar volume of ideal gas (273.15 K, 101.325 kPa) 22.413 962 e-3 0.000 013 e-3 m^3 mol^-1 // molar volume of silicon 12.058 832 14 e-6 0.000 000 61 e-6 m^3 mol^-1 // Mo x unit 1.002 099 52 e-13 0.000 000 53 e-13 m // muon Compton wavelength 11.734 441 11 e-15 0.000 000 26 e-15 m // muon Compton wavelength over 2 pi 1.867 594 308 e-15 0.000 000 042 e-15 m // muon-electron mass ratio 206.768 2826 0.000 0046 // muon g factor -2.002 331 8418 0.000 000 0013 // muon mag. mom. -4.490 448 26 e-26 0.000 000 10 e-26 J T^-1 // muon mag. mom. anomaly 1.165 920 89 e-3 0.000 000 63 e-3 // muon mag. mom. to Bohr magneton ratio -4.841 970 48 e-3 0.000 000 11 e-3 // muon mag. mom. to nuclear magneton ratio -8.890 597 05 0.000 000 20 // muon mass energy equivalent 1.692 833 774 e-11 0.000 000 043 e-11 J // muon mass in u 0.113 428 9257 0.000 000 0025 u // muon molar mass 0.113 428 9257 e-3 0.000 000 0025 e-3 kg mol^-1 // muon-neutron mass ratio 0.112 454 5167 0.000 000 0025 // muon-proton mag. mom. ratio -3.183 345 142 0.000 000 071 // muon-proton mass ratio 0.112 609 5262 0.000 000 0025 // muon-tau mass ratio 5.946 49 e-2 0.000 54 e-2 // natural unit of action 1.054 571 800 e-34 0.000 000 013 e-34 J s // natural unit of action in eV s 6.582 119 514 e-16 0.000 000 040 e-16 eV s // natural unit of energy 8.187 105 65 e-14 0.000 000 10 e-14 J // natural unit of energy in MeV 0.510 998 9461 0.000 000 0031 MeV // natural unit of length 386.159 267 64 e-15 0.000 000 18 e-15 m // natural unit of mass 9.109 383 56 e-31 0.000 000 11 e-31 kg // natural unit of mom.um 2.730 924 488 e-22 0.000 000 034 e-22 kg m s^-1 // natural unit of mom.um in MeV/c 0.510 998 9461 0.000 000 0031 MeV/c // natural unit of time 1.288 088 667 12 e-21 0.000 000 000 58 e-21 s // natural unit of velocity 299 792 458 (exact) m s^-1 // neutron Compton wavelength 1.319 590 904 81 e-15 0.000 000 000 88 e-15 m // neutron Compton wavelength over 2 pi 0.210 019 415 36 e-15 0.000 000 000 14 e-15 m // neutron-electron mag. mom. ratio 1.040 668 82 e-3 0.000 000 25 e-3 // neutron-electron mass ratio 1838.683 661 58 0.000 000 90 // neutron g factor -3.826 085 45 0.000 000 90 // neutron gyromag. ratio 1.832 471 72 e8 0.000 000 43 e8 s^-1 T^-1 // neutron gyromag. ratio over 2 pi 29.164 6933 0.000 0069 MHz T^-1 // neutron mag. mom. -0.966 236 50 e-26 0.000 000 23 e-26 J T^-1 // neutron mag. mom. to Bohr magneton ratio -1.041 875 63 e-3 0.000 000 25 e-3 // neutron mag. mom. to nuclear magneton ratio -1.913 042 73 0.000 000 45 // neutron mass energy equivalent 1.505 349 739 e-10 0.000 000 019 e-10 J // neutron mass energy equivalent in MeV 939.565 4133 0.000 0058 MeV // neutron mass in u 1.008 664 915 88 0.000 000 000 49 u // neutron molar mass 1.008 664 915 88 e-3 0.000 000 000 49 e-3 kg mol^-1 // neutron-muon mass ratio 8.892 484 08 0.000 000 20 // neutron-proton mag. mom. ratio -0.684 979 34 0.000 000 16 // neutron-proton mass difference 2.305 573 77 e-30 0.000 000 85 e-30 // neutron-proton mass difference energy equivalent 2.072 146 37 e-13 0.000 000 76 e-13 // neutron-proton mass difference energy equivalent in MeV 1.293 332 05 0.000 000 48 // neutron-proton mass difference in u 0.001 388 449 00 0.000 000 000 51 // neutron-proton mass ratio 1.001 378 418 98 0.000 000 000 51 // neutron-tau mass ratio 0.528 790 0.000 048 // neutron to shielded proton mag. mom. ratio -0.684 996 94 0.000 000 16 // Newtonian constant of gravitation over h-bar c 6.708 61 e-39 0.000 31 e-39 (GeV/c^2)^-2 // nuclear magneton in eV/T 3.152 451 2550 e-8 0.000 000 0015 e-8 eV T^-1 // nuclear magneton in inverse meters per tesla 2.542 623 432 e-2 0.000 000 016 e-2 m^-1 T^-1 // nuclear magneton in K/T 3.658 2690 e-4 0.000 0021 e-4 K T^-1 // nuclear magneton in MHz/T 7.622 593 285 0.000 000 047 MHz T^-1 // Planck constant in eV s 4.135 667 662 e-15 0.000 000 025 e-15 eV s // Planck constant over 2 pi in eV s 6.582 119 514 e-16 0.000 000 040 e-16 eV s // Planck constant over 2 pi times c in MeV fm 197.326 9788 0.000 0012 MeV fm // Planck length 1.616 229 e-35 0.000 038 e-35 m // Planck mass 2.176 470 e-8 0.000 051 e-8 kg // Planck mass energy equivalent in GeV 1.220 910 e19 0.000 029 e19 GeV // Planck temperature 1.416 808 e32 0.000 033 e32 K // Planck time 5.391 16 e-44 0.000 13 e-44 s // proton charge to mass quotient 9.578 833 226 e7 0.000 000 059 e7 C kg^-1 // proton Compton wavelength 1.321 409 853 96 e-15 0.000 000 000 61 e-15 m // proton Compton wavelength over 2 pi 0.210 308 910 109 e-15 0.000 000 000 097 e-15 m // proton-electron mass ratio 1836.152 673 89 0.000 000 17 // proton g factor 5.585 694 702 0.000 000 017 // proton gyromag. ratio 2.675 221 900 e8 0.000 000 018 e8 s^-1 T^-1 // proton gyromag. ratio over 2 pi 42.577 478 92 0.000 000 29 MHz T^-1 // proton mag. mom. 1.410 606 7873 e-26 0.000 000 0097 e-26 J T^-1 // proton mag. mom. to Bohr magneton ratio 1.521 032 2053 e-3 0.000 000 0046 e-3 // proton mag. mom. to nuclear magneton ratio 2.792 847 3508 0.000 000 0085 // proton mag. shielding correction 25.691 e-6 0.011 e-6 // proton mass energy equivalent 1.503 277 593 e-10 0.000 000 018 e-10 J // proton mass energy equivalent in MeV 938.272 0813 0.000 0058 MeV // proton mass in u 1.007 276 466 879 0.000 000 000 091 u // proton molar mass 1.007 276 466 879 e-3 0.000 000 000 091 e-3 kg mol^-1 // proton-muon mass ratio 8.880 243 38 0.000 000 20 // proton-neutron mag. mom. ratio -1.459 898 05 0.000 000 34 // proton-neutron mass ratio 0.998 623 478 44 0.000 000 000 51 // proton rms charge radius 0.8751 e-15 0.0061 e-15 m // proton-tau mass ratio 0.528 063 0.000 048 // Rydberg constant times c in Hz 3.289 841 960 355 e15 0.000 000 000 019 e15 Hz // Rydberg constant times hc in eV 13.605 693 009 0.000 000 084 eV // Rydberg constant times hc in J 2.179 872 325 e-18 0.000 000 027 e-18 J // Sackur-Tetrode constant (1 K, 100 kPa) -1.151 7084 0.000 0014 // Sackur-Tetrode constant (1 K, 101.325 kPa) -1.164 8714 0.000 0014 // shielded helion gyromag. ratio 2.037 894 585 e8 0.000 000 027 e8 s^-1 T^-1 // shielded helion gyromag. ratio over 2 pi 32.434 099 66 0.000 000 43 MHz T^-1 // shielded helion mag. mom. -1.074 553 080 e-26 0.000 000 014 e-26 J T^-1 // shielded helion mag. mom. to Bohr magneton ratio -1.158 671 471 e-3 0.000 000 014 e-3 // shielded helion mag. mom. to nuclear magneton ratio -2.127 497 720 0.000 000 025 // shielded helion to proton mag. mom. ratio -0.761 766 5603 0.000 000 0092 // shielded helion to shielded proton mag. mom. ratio -0.761 786 1313 0.000 000 0033 // shielded proton gyromag. ratio 2.675 153 171 e8 0.000 000 033 e8 s^-1 T^-1 // shielded proton gyromag. ratio over 2 pi 42.576 385 07 0.000 000 53 MHz T^-1 // shielded proton mag. mom. 1.410 570 547 e-26 0.000 000 018 e-26 J T^-1 // shielded proton mag. mom. to Bohr magneton ratio 1.520 993 128 e-3 0.000 000 017 e-3 // shielded proton mag. mom. to nuclear magneton ratio 2.792 775 600 0.000 000 030 // standard atmosphere 101 325 (exact) Pa // standard-state pressure 100 000 (exact) Pa // tau Compton wavelength 0.697 787 e-15 0.000 063 e-15 m // tau Compton wavelength over 2 pi 0.111 056 e-15 0.000 010 e-15 m // tau-electron mass ratio 3477.15 0.31 // tau mass energy equivalent 2.846 78 e-10 0.000 26 e-10 J // tau mass in u 1.907 49 0.000 17 u // tau molar mass 1.907 49 e-3 0.000 17 e-3 kg mol^-1 // tau-muon mass ratio 16.8167 0.0015 // tau-neutron mass ratio 1.891 11 0.000 17 // tau-proton mass ratio 1.893 72 0.000 17 // triton-electron mass ratio 5496.921 535 88 0.000 000 26 // triton g factor 5.957 924 920 0.000 000 028 // triton mag. mom. 1.504 609 503 e-26 0.000 000 012 e-26 J T^-1 // triton mag. mom. to Bohr magneton ratio 1.622 393 6616 e-3 0.000 000 0076 e-3 // triton mag. mom. to nuclear magneton ratio 2.978 962 460 0.000 000 014 // triton mass 5.007 356 665 e-27 0.000 000 062 e-27 kg // triton mass energy equivalent 4.500 387 735 e-10 0.000 000 055 e-10 J // triton mass energy equivalent in MeV 2808.921 112 0.000 017 MeV // triton mass in u 3.015 500 716 32 0.000 000 000 11 u // triton molar mass 3.015 500 716 32 e-3 0.000 000 000 11 e-3 kg mol^-1 // triton-proton mass ratio 2.993 717 033 48 0.000 000 000 22 // unified atomic mass unit 1.660 539 040 e-27 0.000 000 020 e-27 kg // Wien frequency displacement law constant 5.878 9238 e10 0.000 0034 e10 Hz K^-1 // Wien wavelength displacement law constant 2.897 7729 e-3 0.000 0017 e-3 m K // Universal. PUSH_CONSTANT_NO_UNIT("π (Archimedes' constant pi)", "3.1415926535897932"); PUSH_CONSTANT_NO_UNIT("e (Euler's number)", "2.7182818284590452"); PUSH_CONSTANT_NO_UNIT("φ (golden ratio)", "1.6180339887498948"); // General Physics. PUSH_CONSTANT_CODATA("Characteristic Impedance of Vacuum", "376.730313461", "Ω", "exact", "2016-03-28"); PUSH_CONSTANT_CODATA("Dirac's Constant", "1.054571800e-34", "J·s", "0.000000013e-34", "2016-03-28"); // CODATA name: Planck constant over 2 pi PUSH_CONSTANT_CODATA("Electric Constant", "8.854187817e-12", "F/m", "exact", "2016-03-28"); PUSH_CONSTANT_CODATA("Gravitation Constant", "6.67408e-11", "m³/(kg·s²)", "0.00031e-11", "2016-03-28"); PUSH_CONSTANT_CODATA("Magnetic Constant", "12.566370614e-7", "N/A²", "exact", "2016-03-28"); // TODO: Put more figures ! PUSH_CONSTANT_CODATA("Planck's Constant", "6.626070040e-34", "J·s", "0.000000081e-34", "2016-03-28"); PUSH_CONSTANT_CODATA("Speed of Light in Vacuum", "299792458", "m/s", "exact", "2016-03-28"); PUSH_CONSTANT_CODATA("Standard Gravity", "9.80665", "m/s²", "exact", "2016-03-28"); // Electromagnetic. PUSH_CONSTANT_CODATA("Bohr-Procopiu Magneton", "927.4009994e-26", "J/T", "0.0000057e-26", "2016-03-28"); PUSH_CONSTANT_CODATA("Conductance Quantum", "7.7480917310e-5", "S", "0.0000000018e-5", "2016-03-28"); PUSH_CONSTANT("Coulomb's Constant", "8.987742438e9", "N·m²/C²"); PUSH_CONSTANT_CODATA("Elementary Charge", "1.602 176 6208 e-19", "C", "0.0000000098e-19", "2016-03-28"); PUSH_CONSTANT_CODATA("Conventional value of Josephson Constant", "483597.9e9", "Hz/V", "exact", "2016-03-28"); PUSH_CONSTANT_CODATA("Josephson Constant", "483597.8525e9", "Hz/V", "0.0030e9", "2016-03-28"); PUSH_CONSTANT_CODATA("Magnetic Flux Quantum", "2.06783383e-15", "Wb", "0.000000013e-15", "2016-03-28"); PUSH_CONSTANT_CODATA("Nuclear Magneton", "5.050783699e-27", "J/T", "0.000000031e-27", "2016-03-28"); PUSH_CONSTANT_CODATA("Resistance Quantum", "12906.4037278", "Ω", "0.0000029", "2016-03-28"); // CODATA name: inverse of conductance quantum PUSH_CONSTANT_CODATA("Conventional value of von Klitzing Constant", "25812.807", "Ω", "exact", "2016-03-28"); PUSH_CONSTANT_CODATA("von Klitzing Constant", "25812.8074555", "Ω", "0.0000059", "2016-03-28"); // Atomic & Nuclear. PUSH_CONSTANT_CODATA("Bohr Radius", "0.52917721067e-10", "m", "0.00000000012e-10", "2016-03-28"); PUSH_CONSTANT_CODATA("Fermi Coupling Constant", "1.1663787e-5", "Ge/V²", "0.0000006e-5", "2016-03-28"); PUSH_CONSTANT_CODATA("Fine-structure Constant", "7.2973525664e-3", "", "0.0000000017e-3", "2016-03-28"); PUSH_CONSTANT_CODATA("Hartree Energy", "4.359744650e-18", "J", "0.000000054e-18", "2016-03-28"); PUSH_CONSTANT_CODATA("Hartree Energy in eV", "27.21138602", "eV", "0.00000017", "2016-03-28"); PUSH_CONSTANT_CODATA("Quantum of Circulation", "3.6369475486e-4", "m²/s", "0.0000000017e-4", "2016-03-28"); PUSH_CONSTANT_CODATA("Quantum of Circulation times 2", "7.2738950972e-4", "m²/s", "0.0000000033e-4", "2016-03-28"); // I don't know why it is useful, but it is present in CODATA constants, so I added it -- Hadrien Theveneau, 2016-03-28 PUSH_CONSTANT_CODATA("Rydberg Constant", "10973731.568508", "1/m", "0.000065", "2016-03-28"); PUSH_CONSTANT_CODATA("Thomson Cross Section", "0.66524587158e-28", "m²", "0.00000000091e-28", "2016-03-28"); PUSH_CONSTANT_CODATA("Weak Mixing Angle", "0.2223", "", "0.0021", "2016-03-28"); // Physico-chemical. PUSH_CONSTANT_CODATA("Atomic Mass Unit", "1.660539040e-27", "kg", "0.000000020e-27", "2016-03-28"); // CODATA name: atomic mass constant PUSH_CONSTANT_CODATA("Avogadro's Number", "6.022140857e23", "1/mol", "0.000000074e23", "2016-03-28"); // CODATA name: Avogadro constant PUSH_CONSTANT_CODATA("Boltzmann Constant", "1.38064852e-23", "J/K", "0.00000079e-23", "2016-03-28"); PUSH_CONSTANT_CODATA("Compton wavelength", "2.4263102367e-12", "m", "0.0000000011e-12", "2016-03-28"); PUSH_CONSTANT_CODATA("Compton wavelength over 2 pi", "386.15926764e-15", "m", "0.00000018e-15", "2016-03-28"); PUSH_CONSTANT_CODATA("Electron-volt", "1.6021766208e-19", "J", "0.0000000098e-19", "2016-03-28"); PUSH_CONSTANT_CODATA("Faraday Constant", "96485.33289", "C/mol", "0.00059", "2016-03-28"); // PUSH_CONSTANT_CODATA("Faraday constant for conventional electric current", "96 485.3251", "C_90_mol^-1", "0.0012", "2016-03-28"); // TODO: Handle C_90_mol PUSH_CONSTANT_CODATA("First Radiation Constant", "3.741771790e-16", "W·m²", "0.000000046e-16", "2016-03-28"); PUSH_CONSTANT_CODATA("First Radiation Constant for Spectral Radiance", "1.191042953e-16", "(W·m²)/sr", "0.000000015e-16", "2016-03-28"); PUSH_CONSTANT_CODATA("Gas Constant", "8.3144598", "J/(K·mol)", "0.0000048", "2016-03-28"); PUSH_CONSTANT_CODATA("Loschmidt constant (273.15 K, 100 kPa)", "2.6516467e25", "1/m³", "0.0000015e25", "2016-03-28"); PUSH_CONSTANT_CODATA("Loschmidt constant (273.15 K, 101.325 kPa)", "2.6867811e25", "1/m³", "0.0000015e25", "2016-03-28"); PUSH_CONSTANT_CODATA("Molar Planck Constant", "3.9903127110e-10", "J·s/mol", "0.0000000018e-10", "2016-03-28"); PUSH_CONSTANT_CODATA("Second Radiation Constant", "1.43877736e-2", "m·K", "0.00000083e-2", "2016-03-28"); PUSH_CONSTANT_CODATA("Stefan-Boltzmann Constant", "5.670367e-8", "W/(m²·K⁴)", "0.000013e-8", "2016-03-28"); PUSH_CONSTANT_CODATA("{220} Lattice Spacing of Silicon", "192.0155714e-12", "m", "0.0000032e-12", "2016-03-28"); // Astronomy. PUSH_CONSTANT("Astronomical Unit", "149597870691", "m"); PUSH_CONSTANT("Light Year", "9.4607304725808e15", "m"); PUSH_CONSTANT("Parsec", "3.08567802e16", "m"); PUSH_CONSTANT_NO_UNIT("Gregorian Year", "365.2425"); PUSH_CONSTANT_NO_UNIT("Julian Year", "365.25"); PUSH_CONSTANT_NO_UNIT("Sidereal Year", "365.2564"); PUSH_CONSTANT_NO_UNIT("Tropical Year", "365.2422"); PUSH_CONSTANT("Earth Mass", "5.9736e24", "kg"); PUSH_CONSTANT("Mean Earth Radius", "6371000", "m"); PUSH_CONSTANT("Sun Mass", "1.9891e30", "kg"); PUSH_CONSTANT("Sun Radius", "6.96265e8", "m"); PUSH_CONSTANT("Sun Luminosity", "3.827e26", "W"); // Molar Masses PUSH_CONSTANT("Aluminium", "26.9815386", "g/mol"); PUSH_CONSTANT("Antimony", "121.760", "g/mol"); PUSH_CONSTANT("Argon", "39.948", "g/mol"); PUSH_CONSTANT("Arsenic", "74.92160", "g/mol"); PUSH_CONSTANT("Barium", "137.327", "g/mol"); PUSH_CONSTANT("Beryllium", "9.012182", "g/mol"); PUSH_CONSTANT("Bismuth", "208.98040", "g/mol"); PUSH_CONSTANT("Boron", "10.811", "g/mol"); PUSH_CONSTANT("Bromine", "79.904", "g/mol"); PUSH_CONSTANT("Cadmium", "112.411", "g/mol"); PUSH_CONSTANT("Caesium", "132.9054519", "g/mol"); PUSH_CONSTANT("Calcium", "40.078", "g/mol"); PUSH_CONSTANT("Carbon", "12.0107", "g/mol"); PUSH_CONSTANT("Cerium", "140.116", "g/mol"); PUSH_CONSTANT("Chlorine", "35.453", "g/mol"); PUSH_CONSTANT("Chromium", "51.9961", "g/mol"); PUSH_CONSTANT("Cobalt", "58.933195", "g/mol"); PUSH_CONSTANT("Copper", "63.546", "g/mol"); PUSH_CONSTANT("Dysprosium", "162.500", "g/mol"); PUSH_CONSTANT("Erbium", "167.259", "g/mol"); PUSH_CONSTANT("Europium", "151.964", "g/mol"); PUSH_CONSTANT("Fluorine", "18.9984032", "g/mol"); PUSH_CONSTANT("Gadolinium", "157.25", "g/mol"); PUSH_CONSTANT("Gallium", "69.723", "g/mol"); PUSH_CONSTANT("Germanium", "72.64", "g/mol"); PUSH_CONSTANT("Gold", "196.966569", "g/mol"); PUSH_CONSTANT("Hafnium", "178.49", "g/mol"); PUSH_CONSTANT("Helium", "4.002602", "g/mol"); PUSH_CONSTANT("Holmium", "164.93032", "g/mol"); PUSH_CONSTANT("Hydrogen", "1.00794", "g/mol"); PUSH_CONSTANT("Indium", "114.818", "g/mol"); PUSH_CONSTANT("Iodine", "126.90447", "g/mol"); PUSH_CONSTANT("Iridium", "192.217", "g/mol"); PUSH_CONSTANT("Iron", "55.845", "g/mol"); PUSH_CONSTANT("Krypton", "83.798", "g/mol"); PUSH_CONSTANT("Lanthanum", "138.90547", "g/mol"); PUSH_CONSTANT("Lead", "207.2", "g/mol"); PUSH_CONSTANT("Lithium", "6.941", "g/mol"); PUSH_CONSTANT("Lutetium", "174.9668", "g/mol"); PUSH_CONSTANT("Magnesium", "24.3050", "g/mol"); PUSH_CONSTANT("Manganese", "54.938045", "g/mol"); PUSH_CONSTANT("Mercury", "200.59", "g/mol"); PUSH_CONSTANT("Molybdenum", "95.96", "g/mol"); PUSH_CONSTANT("Neodymium", "144.242", "g/mol"); PUSH_CONSTANT("Neon", "20.1797", "g/mol"); PUSH_CONSTANT("Nickel", "58.6934", "g/mol"); PUSH_CONSTANT("Niobium", "92.90638", "g/mol"); PUSH_CONSTANT("Nitrogen", "14.0067", "g/mol"); PUSH_CONSTANT("Osmium", "190.23", "g/mol"); PUSH_CONSTANT("Oxygen", "15.9994", "g/mol"); PUSH_CONSTANT("Palladium", "106.42", "g/mol"); PUSH_CONSTANT("Phosphorus", "30.973762", "g/mol"); PUSH_CONSTANT("Platinum", "192.084", "g/mol"); PUSH_CONSTANT("Potassium", "39.0983", "g/mol"); PUSH_CONSTANT("Praseodymium", "140.90765", "g/mol"); PUSH_CONSTANT("Protactinium", "231.03588", "g/mol"); PUSH_CONSTANT("Rhenium", "186.207", "g/mol"); PUSH_CONSTANT("Rubidium", "85.4678", "g/mol"); PUSH_CONSTANT("Ruthenium", "101.07", "g/mol"); PUSH_CONSTANT("Samarium", "150.36", "g/mol"); PUSH_CONSTANT("Scandium", "44.955912", "g/mol"); PUSH_CONSTANT("Selenium", "78.96", "g/mol"); PUSH_CONSTANT("Silicon", "28.0855", "g/mol"); PUSH_CONSTANT("Silver", "107.8682", "g/mol"); PUSH_CONSTANT("Sodium", "22.98976928", "g/mol"); PUSH_CONSTANT("Strontium", "87.62", "g/mol"); PUSH_CONSTANT("Sulfur", "32.065", "g/mol"); PUSH_CONSTANT("Tantalum", "180.94788", "g/mol"); PUSH_CONSTANT("Tellurium", "127.60", "g/mol"); PUSH_CONSTANT("Terbium", "158.92535", "g/mol"); PUSH_CONSTANT("Thallium", "204.3833", "g/mol"); PUSH_CONSTANT("Thorium", "232.03806", "g/mol"); PUSH_CONSTANT("Thulium", "168.93421", "g/mol"); PUSH_CONSTANT("Tin", "118.710", "g/mol"); PUSH_CONSTANT("Titanium", "47.867", "g/mol"); PUSH_CONSTANT("Tungsten", "183.84", "g/mol"); PUSH_CONSTANT("Uranium", "238.02891", "g/mol"); PUSH_CONSTANT("Vanadium", "51.9961", "g/mol"); PUSH_CONSTANT("Xenon", "131.293", "g/mol"); PUSH_CONSTANT("Ytterbium", "173.054", "g/mol"); PUSH_CONSTANT("Yttrium", "88.90585", "g/mol"); PUSH_CONSTANT("Zinc", "65.38", "g/mol"); PUSH_CONSTANT("Zirconium", "91.224", "g/mol"); // Particle Masses // Leptons PUSH_CONSTANT_CODATA("Electron Mass", "0.5109989461", "MeV/c²", "0.0000000031", "2016-03-28"); PUSH_CONSTANT_CODATA("Muon Mass", "105.6583745", "MeV/c²", "0.0000024", "2016-03-28"); PUSH_CONSTANT_CODATA("Tau Mass", "1776.82", "MeV/c²", "0.16", "2016-03-28"); // Quarks PUSH_CONSTANT("Up-Quark Mass", "2.3", "MeV/c²"); PUSH_CONSTANT("Down-Quark Mass", "4.8", "MeV/c²"); PUSH_CONSTANT("Charm-Quark Mass", "1.275", "GeV/c²"); PUSH_CONSTANT("Strange-Quark Mass", "95", "MeV/c²"); PUSH_CONSTANT("Top-Quark Mass", "173.21", "GeV/c²"); PUSH_CONSTANT("Bottom-Quark Mass", "4.18", "GeV/c²"); // Bosons PUSH_CONSTANT("W-Boson Mass", "80.385" , "GeV/c²"); PUSH_CONSTANT("Z-Boson Mass", "91.1876", "GeV/c²"); PUSH_CONSTANT("Higgs-Boson Mass", "125.7", "GeV/c²"); // Hadrons PUSH_CONSTANT_CODATA("Proton Mass", "938.2720813", "MeV/c²", "0.0000058", "2016-03-28"); PUSH_CONSTANT_CODATA("Neutron Mass", "939.5654133", "MeV/c²", "0.0000058", "2016-03-28"); // SI-Units PUSH_CONSTANT_CODATA("Electron Mass (SI)", "9.10938356e-31", "kg", "0.00000011e-31", "2016-03-28"); PUSH_CONSTANT_CODATA("Proton Mass (SI)", "1.672621898e-27", "kg", "0.000000021e-27", "2016-03-28"); PUSH_CONSTANT_CODATA("Neutron Mass (SI)", "1.674927471e-27", "kg", "0.000000021e-27", "2016-03-28"); } void Constants::Private::retranslateText() { auto i = list.begin(); QString cat; // http://en.wikipedia.org/wiki/Mathematical_constant cat = Constants::tr("Universal"); I18N_CONSTANT(Constants::tr("Archimedes' constant Pi") + QString::fromUtf8(" (π)")); I18N_CONSTANT(Constants::tr("Euler's number") + QString::fromUtf8(" (ℯ)")); I18N_CONSTANT(Constants::tr("Golden ratio") + QString::fromUtf8(" (φ)")); // http://en.wikipedia.org/wiki/Physical_constant#Table_of_universal_constants cat = Constants::tr("General Physics"); I18N_CONSTANT(Constants::tr("Characteristic Impedance of Vacuum")); I18N_CONSTANT(Constants::tr("Dirac's Constant")); I18N_CONSTANT(Constants::tr("Electric Constant")); I18N_CONSTANT(Constants::tr("Gravitation Constant")); I18N_CONSTANT(Constants::tr("Magnetic Constant")); I18N_CONSTANT(Constants::tr("Planck's Constant")); I18N_CONSTANT(Constants::tr("Speed of Light in Vacuum")); I18N_CONSTANT(Constants::tr("Standard Gravity")); // http://en.wikipedia.org/wiki/Physical_constant#Table_of_electromagnetic_constants cat = Constants::tr("Electromagnetic"); I18N_CONSTANT(Constants::tr("Bohr-Procopiu Magneton")); I18N_CONSTANT(Constants::tr("Conductance Quantum")); I18N_CONSTANT(Constants::tr("Coulomb's Constant")); I18N_CONSTANT(Constants::tr("Elementary Charge")); I18N_CONSTANT(Constants::tr("Conventional value of Josephson Constant")); I18N_CONSTANT(Constants::tr("Josephson Constant")); I18N_CONSTANT(Constants::tr("Magnetic Flux Quantum")); I18N_CONSTANT(Constants::tr("Nuclear Magneton")); I18N_CONSTANT(Constants::tr("Resistance Quantum")); I18N_CONSTANT(Constants::tr("Conventional value of von Klitzing Constant")); I18N_CONSTANT(Constants::tr("von Klitzing Constant")); // CODATA cat = Constants::tr("Atomic & Nuclear"); I18N_CONSTANT(Constants::tr("Bohr Radius")); I18N_CONSTANT(Constants::tr("Fermi Coupling Constant")); I18N_CONSTANT(Constants::tr("Fine-structure Constant")); I18N_CONSTANT(Constants::tr("Hartree Energy")); I18N_CONSTANT(Constants::tr("Hartree Energy in eV")); I18N_CONSTANT(Constants::tr("Quantum of Circulation")); I18N_CONSTANT(Constants::tr("Quantum of Circulation times 2")); I18N_CONSTANT(Constants::tr("Rydberg Constant")); I18N_CONSTANT(Constants::tr("Thomson Cross Section")); I18N_CONSTANT(Constants::tr("Weak Mixing Angle")); // CODATA cat = Constants::tr("Physico-chemical"); I18N_CONSTANT(Constants::tr("Atomic Mass Unit")); I18N_CONSTANT(Constants::tr("Avogadro's Number")); I18N_CONSTANT(Constants::tr("Boltzmann Constant")); I18N_CONSTANT(Constants::tr("Compton wavelength")); I18N_CONSTANT(Constants::tr("Compton wavelength over 2 pi")); I18N_CONSTANT(Constants::tr("Electron volt")); I18N_CONSTANT(Constants::tr("Faraday Constant")); I18N_CONSTANT(Constants::tr("First Radiation Constant")); I18N_CONSTANT(Constants::tr("First Radiation Constant for Spectral Radiance")); I18N_CONSTANT(Constants::tr("Gas Constant")); I18N_CONSTANT(Constants::tr("Loschmidt constant (273.15 K, 100 kPa)")); I18N_CONSTANT(Constants::tr("Loschmidt constant (273.15 K, 101.325 kPa)")); I18N_CONSTANT(Constants::tr("Molar Planck Constant")); I18N_CONSTANT(Constants::tr("Second Radiation Constant")); I18N_CONSTANT(Constants::tr("Stefan-Boltzmann Constant")); I18N_CONSTANT(Constants::tr("{220} Lattice Spacing of Silicon")); // http://www.astronomynotes.com/tables/tablesa.htm cat = Constants::tr("Astronomy"); I18N_CONSTANT(Constants::tr("Astronomical Unit")); I18N_CONSTANT(Constants::tr("Light Year")); I18N_CONSTANT(Constants::tr("Parsec")); const QString days = Constants::tr("days"); I18N_CONSTANT_DAYS(Constants::tr("Gregorian Year")); I18N_CONSTANT_DAYS(Constants::tr("Julian Year")); I18N_CONSTANT_DAYS(Constants::tr("Sidereal Year")); I18N_CONSTANT_DAYS(Constants::tr("Tropical Year")); I18N_CONSTANT(Constants::tr("Earth Mass")); I18N_CONSTANT(Constants::tr("Mean Earth Radius")); I18N_CONSTANT(Constants::tr("Sun Mass")); I18N_CONSTANT(Constants::tr("Sun Radius")); I18N_CONSTANT(Constants::tr("Sun Luminosity")); // http://www.ptable.com/ // Only known constants of accuracy more than an integer are included. cat = Constants::tr("Molar Mass"); I18N_CONSTANT(Constants::tr("Aluminium")); I18N_CONSTANT(Constants::tr("Antimony")); I18N_CONSTANT(Constants::tr("Argon")); I18N_CONSTANT(Constants::tr("Arsenic")); I18N_CONSTANT(Constants::tr("Barium")); I18N_CONSTANT(Constants::tr("Beryllium")); I18N_CONSTANT(Constants::tr("Bismuth")); I18N_CONSTANT(Constants::tr("Boron")); I18N_CONSTANT(Constants::tr("Bromine")); I18N_CONSTANT(Constants::tr("Cadmium")); I18N_CONSTANT(Constants::tr("Caesium")); I18N_CONSTANT(Constants::tr("Calcium")); I18N_CONSTANT(Constants::tr("Carbon")); I18N_CONSTANT(Constants::tr("Cerium")); I18N_CONSTANT(Constants::tr("Chlorine")); I18N_CONSTANT(Constants::tr("Chromium")); I18N_CONSTANT(Constants::tr("Cobalt")); I18N_CONSTANT(Constants::tr("Copper")); I18N_CONSTANT(Constants::tr("Dysprosium")); I18N_CONSTANT(Constants::tr("Erbium")); I18N_CONSTANT(Constants::tr("Europium")); I18N_CONSTANT(Constants::tr("Fluorine")); I18N_CONSTANT(Constants::tr("Gadolinium")); I18N_CONSTANT(Constants::tr("Gallium")); I18N_CONSTANT(Constants::tr("Germanium")); I18N_CONSTANT(Constants::tr("Gold")); I18N_CONSTANT(Constants::tr("Hafnium")); I18N_CONSTANT(Constants::tr("Helium")); I18N_CONSTANT(Constants::tr("Holmium")); I18N_CONSTANT(Constants::tr("Hydrogen")); I18N_CONSTANT(Constants::tr("Indium")); I18N_CONSTANT(Constants::tr("Iodine")); I18N_CONSTANT(Constants::tr("Iridium")); I18N_CONSTANT(Constants::tr("Iron")); I18N_CONSTANT(Constants::tr("Krypton")); I18N_CONSTANT(Constants::tr("Lanthanum")); I18N_CONSTANT(Constants::tr("Lead")); I18N_CONSTANT(Constants::tr("Lithium")); I18N_CONSTANT(Constants::tr("Lutetium")); I18N_CONSTANT(Constants::tr("Magnesium")); I18N_CONSTANT(Constants::tr("Manganese")); I18N_CONSTANT(Constants::tr("Mercury")); I18N_CONSTANT(Constants::tr("Molybdenum")); I18N_CONSTANT(Constants::tr("Neodymium")); I18N_CONSTANT(Constants::tr("Neon")); I18N_CONSTANT(Constants::tr("Nickel")); I18N_CONSTANT(Constants::tr("Niobium")); I18N_CONSTANT(Constants::tr("Nitrogen")); I18N_CONSTANT(Constants::tr("Osmium")); I18N_CONSTANT(Constants::tr("Oxygen")); I18N_CONSTANT(Constants::tr("Palladium")); I18N_CONSTANT(Constants::tr("Phosphorus")); I18N_CONSTANT(Constants::tr("Platinum")); I18N_CONSTANT(Constants::tr("Potassium")); I18N_CONSTANT(Constants::tr("Praseodymium")); I18N_CONSTANT(Constants::tr("Protactinium")); I18N_CONSTANT(Constants::tr("Rhenium")); I18N_CONSTANT(Constants::tr("Rubidium")); I18N_CONSTANT(Constants::tr("Ruthenium")); I18N_CONSTANT(Constants::tr("Samarium")); I18N_CONSTANT(Constants::tr("Scandium")); I18N_CONSTANT(Constants::tr("Selenium")); I18N_CONSTANT(Constants::tr("Silicon")); I18N_CONSTANT(Constants::tr("Silver")); I18N_CONSTANT(Constants::tr("Sodium")); I18N_CONSTANT(Constants::tr("Strontium")); I18N_CONSTANT(Constants::tr("Sulfur")); I18N_CONSTANT(Constants::tr("Tantalum")); I18N_CONSTANT(Constants::tr("Tellurium")); I18N_CONSTANT(Constants::tr("Terbium")); I18N_CONSTANT(Constants::tr("Thallium")); I18N_CONSTANT(Constants::tr("Thorium")); I18N_CONSTANT(Constants::tr("Thulium")); I18N_CONSTANT(Constants::tr("Tin")); I18N_CONSTANT(Constants::tr("Titanium")); I18N_CONSTANT(Constants::tr("Tungsten")); I18N_CONSTANT(Constants::tr("Uranium")); I18N_CONSTANT(Constants::tr("Vanadium")); I18N_CONSTANT(Constants::tr("Xenon")); I18N_CONSTANT(Constants::tr("Ytterbium")); I18N_CONSTANT(Constants::tr("Yttrium")); I18N_CONSTANT(Constants::tr("Zinc")); I18N_CONSTANT(Constants::tr("Zirconium")); // K.A. Olive et al. (Particle Data Group), Chin. Phys. C, 38, 090001 (2014). // http://pdg.lbl.gov/index.html // CODATA constants cat = Constants::tr("Particle Masses"); I18N_CONSTANT(Constants::tr("Electron Mass")); // CODATA, 2016-03-28 I18N_CONSTANT(Constants::tr("Muon Mass")); // CODATA, 2016-03-28 I18N_CONSTANT(Constants::tr("Tau Mass")); // CODATA, 2016-03-28 I18N_CONSTANT(Constants::tr("Up-Quark Mass")); // Particle Data Group I18N_CONSTANT(Constants::tr("Down-Quark Mass")); // Particle Data Group I18N_CONSTANT(Constants::tr("Charm-Quark Mass")); // Particle Data Group I18N_CONSTANT(Constants::tr("Strange-Quark Mass")); // Particle Data Group I18N_CONSTANT(Constants::tr("Top-Quark Mass")); // Particle Data Group I18N_CONSTANT(Constants::tr("Bottom-Quark Mass")); // Particle Data Group I18N_CONSTANT(Constants::tr("W-Boson Mass")); // Particle Data Group I18N_CONSTANT(Constants::tr("Z-Boson Mass")); // Particle Data Group I18N_CONSTANT(Constants::tr("Higgs-Boson Mass")); // Particle Data Group I18N_CONSTANT(Constants::tr("Proton Mass")); // CODATA, 2016-03-28 I18N_CONSTANT(Constants::tr("Neutron Mass")); // CODATA, 2016-03-28 I18N_CONSTANT(Constants::tr("Electron Mass (SI)")); // CODATA, 2016-03-28 I18N_CONSTANT(Constants::tr("Proton Mass (SI)")); // CODATA, 2016-03-28 I18N_CONSTANT(Constants::tr("Neutron Mass (SI)")); // CODATA, 2016-03-28 categories.clear(); for (int k = 0; k < list.count(); ++k) if (!categories.contains(list.at(k).category)) categories += list.at(k).category; categories.sort(); } Constants* Constants::instance() { if (!s_constantsInstance) { s_constantsInstance = new Constants; qAddPostRoutine(s_deleteConstants); } return s_constantsInstance; } Constants::Constants() : d(new Constants::Private) { setObjectName("Constants"); d->populate(); d->retranslateText(); } const QList& Constants::list() const { return d->list; } const QStringList& Constants::categories() const { return d->categories; } void Constants::retranslateText() { d->retranslateText(); } Constants::~Constants() { }*/ deepin-calculator-5.7.21/3rdparty/core/constants.h000066400000000000000000000030651423020056600220700ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2007 Ariya Hidayat // Copyright (C) 2008-2009, 2016 @heldercorreia // Copyright (C) 2009 Andreas Scherer // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. /*#ifndef CORE_CONSTANTS_H #define CORE_CONSTANTS_H #include #include #include struct Constant { QString category; QString name; QString unit; QString value; }; class Constants : public QObject { Q_OBJECT public: ~Constants(); // For unique_ptr, define after Private is complete. static Constants* instance(); const QStringList& categories() const; const QList& list() const; public slots: void retranslateText(); private: struct Private; std::unique_ptr d; Constants(); Q_DISABLE_COPY(Constants) }; #endif*/ deepin-calculator-5.7.21/3rdparty/core/errors.h000066400000000000000000000115621423020056600213710ustar00rootroot00000000000000/* errors.h global list of error codes Copyright (C) 2007, 2008 Wolf Lammen ookami1 gmx de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _ERRORS_H #define _ERRORS_H #ifdef __cplusplus extern "C"{ #endif typedef enum { Success = 0, /* a NaN or an empty Variant was submitted as a parameter. Only a few functions in the math engine accept such a value. All arithmetic functions fail on such an operand */ NoOperand, /* This error is returned if a result is mathematically defined, but cannot be computed reliably without extending the working precision considerably and/or requiring considerable computing time */ EvalUnstable, /* the result is in absolute value smaller than the smallest non-zero value the math engine can handle */ Underflow, /* the result is in absolute value bigger than the biggest number the math engine can handle */ Overflow, /* operation requests a division by zero, or a function was evaluated at a pole */ ZeroDivide, /* One or more parameters to a function lie outside of the function's domain */ OutOfDomain, /* a number exceeds the logic number range, so logic operations cannot be applied */ OutOfLogicRange, /* a number or a result exceeds the integer range */ OutOfIntegerRange, /* This error indicates a failed conversion from an ASCII string. Functions setting this error may also report a more detailed IO... error code*/ BadLiteral, /* A request to calculate something to more places than is (currently) acceptable */ InvalidPrecision, /* A parameter violates the limitations of the engine, or is completely meaningless, e.g. the evaluation of a quotient and a remainder in the same variable. This error indicates a bug, because the calling program should never submit such a parameter (combinations) */ InvalidParam, /* returned when an operation request is mathematically valid, but would require too much time */ TooExpensive, /* For correct conversion of a digit sequence, the IO routines need information about the radix to use. This error is returned if none was specified. This error indicates a bug, because a calling routine should always supply this information */ IONoBase, /* This error occurs if you request a two's complement conversion, and either additionally specify a sign, or gave a non-zero fraction */ IOInvalidComplement, /* You must specify at least one digit of the significant */ IONoSignificand, /* invalid characters in exponent, e.g. a decimal dot */ IOBadExp, /* the exponent exceeds the allowed range */ IOExpOverflow, /* internal (string) buffer overflow in a conversion. This indicates a bug because range checking should be done in advance */ IOBufferOverflow, /* request to convert more digits to another base than internal buffers can hold. This occurs when you try to convert huge values in fixpoint format */ IOConversionOverflow, /* request to convert a tiny number in fixpoint format, so that only leading zeros are displayed. */ IOConversionUnderflow, /* a function was called with the wrong count of parameters e.g. sin(12;13) (sin takes only 1 parameter) */ InvalidParamCount, /* parameter type mismatch */ TypeMismatch, /* occurs if quantities of different dimensions are compared, added, converted, etc. */ DimensionMismatch, /* occurs if a non dimensionless quantity is fed to a function that requires dimensoinless arguments, or if an invalid unit is specified */ InvalidDimension, /* cannot overwrite an existing key in a table */ // KeyExists, /* could not retrieve a symbol by the submitted key */ // SymbolNotFound, /* no matching close token for an open token */ // CloseSymbolMissing, /* unable to clone a symbol, most probably because it was of a special type, like a close parenthesis */ // SymbolCloneError, /* unable to perform a requested type cast */ // BadCast, /* used with variants, when an operation is not implemented for a particular data type. used with formats to indicate a not implemented property */ NotImplemented, /* this value is used internally to indicate the absence of any error information altogether */ NotAnError, /* */ } Error; #ifdef __cplusplus } #endif #endif /* _ERRORS_H */ deepin-calculator-5.7.21/3rdparty/core/evaluator.cpp000066400000000000000000002602001423020056600224050ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2005, 2006 Johan Thelin // Copyright (C) 2007-2016 @heldercorreia // Copyright (C) 2009 Wolf Lammen // Copyright (C) 2014 Tey // Copyright (C) 2015 Pol Welter // Copyright (C) 2015 Hadrien Theveneau // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "evaluator.h" #include "session.h" #include "settings.h" #include "../math/rational.h" #include "../math/units.h" #include #include #include #include #define ALLOW_IMPLICIT_MULT static constexpr int MAX_PRECEDENCE = INT_MAX; static constexpr int INVALID_PRECEDENCE = INT_MIN; #ifdef EVALUATOR_DEBUG #include #include #include QTextStream &operator<<(QTextStream &s, Quantity num) { s << DMath::format(num, Quantity::Format::Fixed()); return s; } #endif // EVALUATOR_DEBUG static Evaluator *s_evaluatorInstance = 0; static void s_deleteEvaluator() { delete s_evaluatorInstance; } bool isMinus(const QChar &ch) { return ch == QLatin1Char('-') || ch == QChar(0x2212); } bool isExponent(const QChar &ch, int base) { switch (base) { case 2: return ch == QLatin1Char('b') || ch == QLatin1Char('B'); case 8: return ch == QLatin1Char('o') || ch == QLatin1Char('O') || ch == QLatin1Char('C'); case 10: return ch == QLatin1Char('e') || ch == QLatin1Char('E'); case 16: return ch == QLatin1Char('h') || ch == QLatin1Char('H'); default: return false; } } const Quantity &Evaluator::checkOperatorResult(const Quantity &n) { switch (n.error()) { case Success: break; case NoOperand: if (!m_assignFunc) // The arguments are still NaN, so ignore this error. m_error = /*Evaluator::tr*/("cannot operate on a NaN"); break; case Underflow: m_error = /*Evaluator::tr*/("underflow - tiny result is out " "of SpeedCrunch's number range"); break; case Overflow: m_error = /*Evaluator::tr*/("overflow - huge result is out of " "SpeedCrunch's number range"); break; case ZeroDivide: m_error = /*Evaluator::tr*/("division by zero"); break; case OutOfLogicRange: m_error = /*Evaluator::tr*/("overflow - logic result exceeds " "maximum of 256 bits"); break; case OutOfIntegerRange: m_error = /*Evaluator::tr*/("overflow - integer result exceeds " "maximum limit for integers"); break; case TooExpensive: m_error = /*Evaluator::tr*/("too time consuming - " "computation was rejected"); break; case DimensionMismatch: // We cannot make any assumptions about the dimension of the arguments, // so ignore this error when assigning a function. if (!m_assignFunc) m_error = /*Evaluator::tr*/("dimension mismatch - quantities with " "different dimensions cannot be " "compared, added, etc."); break; case InvalidDimension: m_error = /*Evaluator::tr*/("invalid dimension - operation might " "require dimensionless arguments"); break; case EvalUnstable: m_error = /*Evaluator::tr*/("Computation aborted - encountered " "numerical instability"); break; default:; } return n; } QString Evaluator::stringFromFunctionError(Function *function) { if (!function->error()) return QString(); QString result = QString::fromLatin1("%1: "); switch (function->error()) { case Success: break; case InvalidParamCount: result += /*Evaluator::tr*/("wrong number of arguments"); break; case NoOperand: result += /*Evaluator::tr*/("does not take NaN as an argument"); break; case Overflow: result += /*Evaluator::tr*/("overflow - huge result is out of " "SpeedCrunch's number range"); break; case Underflow: result += /*Evaluator::tr*/("underflow - tiny result is out of " "SpeedCrunch's number range"); break; case OutOfLogicRange: result += /*Evaluator::tr*/("overflow - logic result exceeds " "maximum of 256 bits"); break; case OutOfIntegerRange: result += /*Evaluator::tr*/("result out of range"); break; case ZeroDivide: result += /*Evaluator::tr*/("division by zero"); break; case EvalUnstable: result += /*Evaluator::tr*/("Computation aborted - " "encountered numerical instability"); break; case OutOfDomain: result += /*Evaluator::tr*/("undefined for argument domain"); break; case TooExpensive: result += /*Evaluator::tr*/("computation too expensive"); break; case InvalidDimension: result += /*Evaluator::tr*/("invalid dimension - function " "might require dimensionless arguments"); break; case DimensionMismatch: result += /*Evaluator::tr*/("dimension mismatch - quantities with " "different dimensions cannot be compared, " "added, etc."); break; case IONoBase: case BadLiteral: case InvalidPrecision: case InvalidParam: result += /*Evaluator::tr*/("internal error, please report a bug"); break; default: result += /*Evaluator::tr*/("error"); break; }; return result.arg(function->identifier()); } class TokenStack : public QVector { public: TokenStack(); bool isEmpty() const; unsigned itemCount() const; Token pop(); void push(const Token &token); const Token &top(); const Token &top(unsigned index); bool hasError() const { return !m_error.isEmpty(); } QString error() const { return m_error; } void reduce(int count, int minPrecedence = INVALID_PRECEDENCE); void reduce(int count, Token &&top, int minPrecedence = INVALID_PRECEDENCE); void reduce(QList tokens, Token &&top, int minPrecedence = INVALID_PRECEDENCE); private: void ensureSpace(); int topIndex; QString m_error; }; const Token Token::null; static Token::Operator matchOperator(const QString &text) { Token::Operator result = Token::Invalid; if (text.length() == 1) { QChar p = text.at(0); switch (p.unicode()) { case '+': result = Token::Addition; break; case 0x2212: // − MINUS SIGN case '-': result = Token::Subtraction; break; case 0x00D7: // × MULTIPLICATION SIGN case 0x22C5: // ⋅ DOT OPERATOR case '*': result = Token::Multiplication; break; case 0x00F7: // ÷ DIVISION SIGN case '/': if (Settings::instance()->programmerBase != 0) result = Token::IntegerDivision; else result = Token::Division; break; case '%': result = Token::Percent; break; case '^': result = Token::Exponentiation; break; case ';': result = Token::ListSeparator; break; case '(': result = Token::AssociationStart; break; case ')': result = Token::AssociationEnd; break; case '!': result = Token::Factorial; break; case '=': result = Token::Assignment; break; case '\\': result = Token::IntegerDivision; break; case '&': result = Token::BitwiseLogicalAND; break; case '|': result = Token::BitwiseLogicalOR; break; default: result = Token::Invalid; } } else if (text.length() == 2) { if (text == "**") result = Token::Exponentiation; else if (text == "<<") result = Token::ArithmeticLeftShift; else if (text == ">>") result = Token::ArithmeticRightShift; else if (text == "->" || text == "in") result = Token::UnitConversion; else if (text == "or") result = Token::BitwiseLogicalOR; } else if (text.length() == 3) { //edit jingzhou 20200720 增加mod、yroot、log if (text == "mod") result = Token::Modulo; if (text == "log") result = Token::Log; if (text == "xor") result = Token::BitwiseLogicalXOR; if (text == "nor") result = Token::BitwiseLogicalNOR; if (text == "and") result = Token::BitwiseLogicalAND; if (text == "shl") result = Token::LogicalLeftShift; if (text == "shr") result = Token::LogicalRightShift; if (text == "sal") result = Token::ArithmeticLeftShift; if (text == "sar") result = Token::ArithmeticRightShift; if (text == "rol") result = Token::CircularLeftShift; if (text == "ror") result = Token::CircularRightShift; if (text == "rcl") result = Token::RotateCarryLeftShift; if (text == "rcr") result = Token::RotateCarryRightShift; } else if (text.length() == 4) { if (text == "nand") result = Token::BitwiseLogicalNAND; } else if (text.length() == 5) { if (text == "yroot") result = Token::Yroot; } return result; } // Helper function: give operator precedence e.g. "+" is 300 while "*" is 500. static int opPrecedence(Token::Operator op) { int prec; switch (op) { case Token::Factorial: prec = 800; break; case Token::Exponentiation: prec = 700; break; case Token::Function: // Not really operator but needed for managing shift/reduce conflicts. prec = 600; break; //edit jingzhou 20200831 取余的优先级与乘除相同 case Token::Modulo: case Token::Multiplication: case Token::Division: case Token::IntegerDivision: prec = 500; break; //add jingzhou 20200720 case Token::Yroot: case Token::Log: prec = 600; break; case Token::Percent: prec = 800; break; case Token::Addition: case Token::Subtraction: prec = 300; break; case Token::ArithmeticLeftShift: case Token::ArithmeticRightShift: case Token::LogicalLeftShift: case Token::LogicalRightShift: case Token::CircularLeftShift: case Token::CircularRightShift: case Token::RotateCarryLeftShift: case Token::RotateCarryRightShift: prec = 200; break; //逻辑运算优先级:&与 > ^异或 > |或 case Token::BitwiseLogicalAND: case Token::BitwiseLogicalNAND: prec = 100; break; case Token::BitwiseLogicalXOR: prec = 75; break; case Token::BitwiseLogicalOR: case Token::BitwiseLogicalNOR: prec = 50; break; case Token::UnitConversion: prec = 0; break; case Token::AssociationEnd: case Token::ListSeparator: prec = -100; break; case Token::AssociationStart: prec = -200; break; default: prec = -200; break; } return prec; } Token::Token(Type type, const QString &text, int pos, int size) { m_type = type; m_text = text; m_pos = pos; m_size = size; m_minPrecedence = MAX_PRECEDENCE; } Token::Token(const Token &token) { m_type = token.m_type; m_text = token.m_text; m_pos = token.m_pos; m_size = token.m_size; m_minPrecedence = token.m_minPrecedence; } Token &Token::operator=(const Token &token) { m_type = token.m_type; m_text = token.m_text; m_pos = token.m_pos; m_size = token.m_size; m_minPrecedence = token.m_minPrecedence; return*this; } Quantity Token::asNumber() const { QString text = m_text; return isNumber() ? Quantity(CNumber((const char *)text.toLatin1())) : Quantity(0); } Token::Operator Token::asOperator() const { return isOperator() ? matchOperator(m_text) : Invalid; } QString Token::description() const { QString desc; switch (m_type) { case stxNumber: desc = "Number"; break; case stxIdentifier: desc = "Identifier"; break; case stxOpenPar: case stxClosePar: case stxSep: case stxOperator: desc = "Operator"; break; default: desc = "Unknown"; break; } while (desc.length() < 10) desc.prepend(' '); QString header; header.append(QString::number(m_pos) + "," + QString::number(m_pos + m_size - 1)); header.append("," + (m_minPrecedence == MAX_PRECEDENCE ? "MAX" : QString::number(m_minPrecedence))); header.append(" "); while (header.length() < 10) header.append(' '); desc.prepend(header); desc.append(" : ").append(m_text); return desc; } static bool tokenPositionCompare(const Token &a, const Token &b) { return (a.pos() < b.pos()); } TokenStack::TokenStack() : QVector() { topIndex = 0; m_error = ""; ensureSpace(); } bool TokenStack::isEmpty() const { return topIndex == 0; } unsigned TokenStack::itemCount() const { return topIndex; } void TokenStack::push(const Token &token) { ensureSpace(); (*this)[topIndex++] = token; } Token TokenStack::pop() { if (topIndex > 0) return Token(at(--topIndex)); m_error = "token stack is empty (BUG)"; return Token(); } const Token &TokenStack::top() { return top(0); } const Token &TokenStack::top(unsigned index) { return (topIndex > (int)index) ? at(topIndex - index - 1) : Token::null; } void TokenStack::ensureSpace() { int length = size(); while (topIndex >= length) { length += 10; resize(length); } } /** Remove \a count tokens from the top of the stack, add a stxAbstract token * to the top and adjust its text position and minimum precedence. * * \param minPrecedence minimum precedence to set the top token, or * \c INVALID_PRECEDENCE if this method should use the minimum value from * the removed tokens. */ void TokenStack::reduce(int count, int minPrecedence) { // assert(itemCount() > count); QList tokens; for (int i = 0 ; i < count ; ++i) tokens.append(pop()); reduce(tokens, Token(Token::stxAbstract), minPrecedence); } /** Remove \a count tokens from the top of the stack, push \a top to the top * and adjust its text position and minimum precedence. * * \param minPrecedence minimum precedence to set the top token, or * \c INVALID_PRECEDENCE if this method should use the minimum value * from the removed tokens. */ void TokenStack::reduce(int count, Token &&top, int minPrecedence) { // assert(itemCount() >= count); QList tokens; for (int i = 0 ; i < count ; ++i) tokens.append(pop()); reduce(tokens, std::forward(top), minPrecedence); } /** Push \a top to the top and adjust its text position and minimum precedence * using \a tokens. * * \param minPrecedence minimum precedence to set the top token, or * \c INVALID_PRECEDENCE if this method should use the minimum value from the * removed tokens. */ void TokenStack::reduce(QList tokens, Token &&top, int minPrecedence) { #ifdef EVALUATOR_DEBUG { const auto &_tokens = tokens; qDebug() << "reduce(" << _tokens.size() << ", " << top.description() << ", " << minPrecedence << ")"; for (const auto &t : _tokens) qDebug() << t.description(); } #endif // EVALUATOR_DEBUG qSort(tokens.begin(), tokens.end(), tokenPositionCompare); bool computeMinPrec = (minPrecedence == INVALID_PRECEDENCE); int min_prec = computeMinPrec ? MAX_PRECEDENCE : minPrecedence; int start = -1, end = -1; const auto &_tokens = tokens; for (auto &token : _tokens) { if (computeMinPrec) { Token::Operator op = token.asOperator(); if (op != Token::Invalid) { int prec = opPrecedence(op); if (prec < min_prec) min_prec = prec; } } if (token.pos() == -1 && token.size() == -1) continue; if (token.pos() == -1 || token.size() == -1) { #ifdef EVALUATOR_DEBUG qDebug() << "BUG: found token with either pos or size not set, " "but not both."; #endif // EVALUATOR_DEBUG continue; } if (start == -1) { start = token.pos(); } else { #ifdef EVALUATOR_DEBUG if (token.pos() != end) qDebug() << "BUG: tokens expressions are not successive."; #endif // EVALUATOR_DEBUG } end = token.pos() + token.size(); } if (start != -1) { top.setPos(start); top.setSize(end - start); } top.setMinPrecedence(min_prec); #ifdef EVALUATOR_DEBUG qDebug() << "=> " << top.description(); #endif // EVALUATOR_DEBUG push(top); } #ifdef EVALUATOR_DEBUG void Tokens::append(const Token &token) { qDebug() << QString("tokens.append: type=%1 text=%2") .arg(token.type()) .arg(token.text()); QVector::append(token); } #endif // EVALUATOR_DEBUG // Helper function: return true for valid identifier character. static bool isIdentifier(QChar ch) { return ch.unicode() == '_' || ch.unicode() == '$' || ch.isLetter(); } // Helper function: return true for valid radix characters. bool Evaluator::isRadixChar(const QChar &ch) { if (Settings::instance()->isRadixCharacterBoth()) return ch.unicode() == '.' || ch.unicode() == ','; // There are more than 2 radix characters, actually: // U+0027 ' apostrophe // U+002C , comma // U+002E . full stop // U+00B7 · middle dot // U+066B ٫ arabic decimal separator // U+2396 ⎖ decimal separator key symbol return ch.unicode() == Settings::instance()->radixCharacter(); } // Helper function: return true for valid thousand separator characters. bool Evaluator::isSeparatorChar(const QChar &ch) { // Match everything that is not alphanumeric or an operator or NUL. static const QRegExp s_separatorRE( "[^a-zA-Z0-9\\+\\-−\\*×⋅÷/\\^;\\(\\)%!=\\\\&\\|<>\\?#\\x0000]" ); if (isRadixChar(ch)) return false; return s_separatorRE.exactMatch(ch); } QString Evaluator::fixNumberRadix(const QString &number) { int dotCount = 0; int commaCount = 0; QChar lastRadixChar; // First pass: count the number of dot and comma characters. for (int i = 0 ; i < number.size() ; ++i) { QChar c = number[i]; if (isRadixChar(c)) { lastRadixChar = c; if (c == '.') ++dotCount; else if (c == ',') ++commaCount; else return QString(); // Should not happen. } } // Decide which radix characters to ignore based on their occurence count. bool ignoreDot = dotCount != 1; bool ignoreComma = commaCount != 1; if (!ignoreDot && !ignoreComma) { // If both radix characters are present once, // consider the last one as the radix point. ignoreDot = lastRadixChar != '.'; ignoreComma = lastRadixChar != ','; } QChar radixChar; // Null character by default. if (!ignoreDot) radixChar = '.'; else if (!ignoreComma) radixChar = ','; // Second pass: write the result. QString result = ""; for (int i = 0 ; i < number.size() ; ++i) { QChar c = number[i]; if (isRadixChar(c)) { if (c == radixChar) result.append('.'); } else result.append(c); } return result; } Evaluator *Evaluator::instance() { if (!s_evaluatorInstance) { s_evaluatorInstance = new Evaluator; qAddPostRoutine(s_deleteEvaluator); } return s_evaluatorInstance; } Evaluator::Evaluator() { reset(); } #define ADD_UNIT(name) \ setVariable(QString::fromUtf8(#name), Units::name(), Variable::BuiltIn) void Evaluator::initializeBuiltInVariables() { setVariable(QLatin1String("e"), DMath::e(), Variable::BuiltIn); //edit 20200805 jingzhou for bug--41371,重新替换回小写e setVariable(QString::fromUtf8("ℯ"), DMath::e(), Variable::BuiltIn); setVariable(QLatin1String("pi"), DMath::pi(), Variable::BuiltIn); setVariable(QString::fromUtf8("π"), DMath::pi(), Variable::BuiltIn); if (Settings::instance()->complexNumbers) { setVariable(QLatin1String("j"), DMath::i(), Variable::BuiltIn); } else if (hasVariable("j")) { unsetVariable("j", ForceBuiltinVariableErasure(true)); } QList unitList(Units::getList()); for (Unit &u : unitList) { setVariable(u.name, u.value, Variable::BuiltIn); } initializeAngleUnits(); } void Evaluator::initializeAngleUnits() { if (Settings::instance()->angleUnit == 'r') { setVariable("radian", 1, Variable::BuiltIn); setVariable("degree", HMath::pi() / HNumber(180), Variable::BuiltIn); setVariable("gradian", HMath::pi() / HNumber(200), Variable::BuiltIn); setVariable("gon", HMath::pi() / HNumber(200), Variable::BuiltIn); } else if (Settings::instance()->angleUnit == 'g') { setVariable("radian", HNumber(200) / HMath::pi(), Variable::BuiltIn); setVariable("degree", HNumber(200) / HNumber(180), Variable::BuiltIn); setVariable("gradian", 1, Variable::BuiltIn); setVariable("gon", 1, Variable::BuiltIn); } else { // d setVariable("radian", HNumber(180) / HMath::pi(), Variable::BuiltIn); setVariable("degree", 1, Variable::BuiltIn); setVariable("gradian", HNumber(180) / HNumber(200), Variable::BuiltIn); setVariable("gon", HNumber(180) / HNumber(200), Variable::BuiltIn); } } void Evaluator::setExpression(const QString &expr) { m_expression = expr; m_dirty = true; m_valid = false; m_error = QString(); } QString Evaluator::expression() const { return m_expression; } // Returns the validity. Note: empty expression is always invalid. bool Evaluator::isValid() { if (m_dirty) { Tokens tokens = scan(m_expression); if (!tokens.valid()) compile(tokens); else m_valid = false; } return m_valid; } void Evaluator::reset() { m_expression = QString(); m_dirty = true; m_valid = false; m_error = QString(); m_constants.clear(); m_codes.clear(); m_assignId = QString(); m_assignFunc = false; m_assignArg.clear(); m_session = nullptr; m_functionsInUse.clear(); initializeBuiltInVariables(); } void Evaluator::setSession(Session *s) { m_session = s; } const Session *Evaluator::session() { return m_session; } QString Evaluator::error() const { return m_error; } // Returns list of token for the expression. // This triggers again the lexical analysis step. It is however preferable // (even when there's small performance penalty) because otherwise we need to // store parsed tokens all the time which serves no good purpose. Tokens Evaluator::tokens() const { return scan(m_expression); } Tokens Evaluator::scan(const QString &expr) const { // Associate character codes with the highest number base // they might belong to. constexpr unsigned DIGIT_MAP_COUNT = 128; static unsigned char s_digitMap[DIGIT_MAP_COUNT] = { 0 }; if (s_digitMap[0] == 0) { // Initialize the digits map. std::fill_n(s_digitMap, DIGIT_MAP_COUNT, 255); for (int i = '0' ; i <= '9' ; ++i) s_digitMap[i] = i - '0' + 1; for (int i = 'a' ; i <= 'z' ; ++i) s_digitMap[i] = i - 'a' + 11; for (int i = 'A' ; i <= 'Z' ; ++i) s_digitMap[i] = i - 'A' + 11; } // Result. Tokens tokens; // Parsing state. enum { Init, Start, Finish, Bad, InNumberPrefix, InNumber, InExpIndicator, InExponentBase, InExponent, InIdentifier, InNumberEnd } state; // Initialize variables. state = Init; int i = 0; QString ex = expr; QString tokenText; int tokenStart = 0; // Includes leading spaces. Token::Type type; int numberBase = 10; int expBase = 0; int expStart = -1; // Index of the exponent part in the expression. QString expText; // Start of the exponent text matching /E[\+\-]*/ // Force a terminator. ex.append(QChar()); #ifdef EVALUATOR_DEBUG qDebug() << "Scanning" << ex; #endif // EVALUATOR_DEBUG // Main loop. while (state != Bad && state != Finish && i < ex.length()) { QChar ch = ex.at(i); #ifdef EVALUATOR_DEBUG qDebug() << QString("state=%1 ch=%2 i=%3 tokenText=%4") .arg(state).arg(ch).arg(i).arg(tokenText); #endif // EVALUATOR_DEBUG switch (state) { case Init: tokenStart = i; tokenText = ""; state = Start; // State variables reset expStart = -1; expText = ""; numberBase = 10; expBase = 0; // No break here on purpose (make sure Start is the next case) case Start: // Skip any whitespaces. if (ch.isSpace()) ++i; else if (ch == '?') // Comment. state = Finish; else if (ch.isDigit()) { // Check for number state = InNumberPrefix; } else if (ch == '#') { // Simple hexadecimal notation tokenText.append("0x"); numberBase = 16; state = InNumber; ++i; } else if (isRadixChar(ch)) { // Radix character? tokenText.append(ch); numberBase = 10; state = InNumber; ++i; } else if (isSeparatorChar(ch)) { // Leading separator, probably a number state = InNumberPrefix; } else if (ch.isNull()) // Terminator character. state = Finish; else if (isIdentifier(ch)) // Identifier or alphanumeric operator state = InIdentifier; else { // Look for operator match. int op; QString s; s = QString(ch).append(ex.at(i + 1)); op = matchOperator(s); // Check for one-char operator. if (op == Token::Invalid) { s = QString(ch); op = matchOperator(s); } // Any matched operator? if (op != Token::Invalid) { switch (op) { case Token::AssociationStart: type = Token::stxOpenPar; break; case Token::AssociationEnd: type = Token::stxClosePar; break; case Token::ListSeparator: type = Token::stxSep; break; default: type = Token::stxOperator; } int len = s.length(); i += len; int tokenSize = i - tokenStart; tokens.append(Token(type, s.left(len), tokenStart, tokenSize)); state = Init; } else state = Bad; } break; // Manage both identifier and alphanumeric operators. case InIdentifier: // Consume as long as alpha, dollar sign, underscore, or digit. //edit jingzhou 20200720 mod直接作为%取余使用,yroot,log处理方式同上 if ((isIdentifier(ch) || ch.isDigit()) && tokenText != "mod" && tokenText != "yroot" && tokenText != "log" && tokenText != "and" && tokenText != "or" && tokenText != "xor" && tokenText != "nand" && tokenText != "nor" && tokenText != "shl" && tokenText != "shr" && tokenText != "sal" && tokenText != "sar" && tokenText != "rol" && tokenText != "ror" && tokenText != "rcl" && tokenText != "rcr") tokenText.append(ex.at(i++)); else { // We're done with identifier. int tokenSize = i - tokenStart; if (matchOperator(tokenText)) { tokens.append(Token(Token::stxOperator, tokenText, tokenStart, tokenSize)); } else { // Normal identifier. tokens.append(Token(Token::stxIdentifier, tokenText, tokenStart, tokenSize)); } state = Init; } break; // Find out the number base. case InNumberPrefix: if (ch.isDigit()) { // Only consume the first digit and the second digit // if the first was 0. tokenText.append(ex.at(i++)); if (tokenText != "0") { numberBase = 10; state = InNumber; } } else if (isExponent(ch, numberBase)) { if (tokenText.endsWith("0")) { // Maybe exponent (tokenText is "0" or "-0"). numberBase = 10; expText = ch.toUpper(); expStart = i; ++i; state = InExpIndicator; } else { // Only leading separators. state = Bad; } } else if (isRadixChar(ch)) { // Might be a radix point or a separator. // Collect it and decide later. tokenText.append(ch); numberBase = 10; state = InNumber; ++i; } else if (ch.toUpper() == 'X' && tokenText == "0" && Settings::instance()->programmerBase != 10) { // Hexadecimal number. numberBase = 16; tokenText.append('x'); ++i; state = InNumber; } else if (ch.toUpper() == 'B' && tokenText == "0" && Settings::instance()->programmerBase != 10) { // Binary number. numberBase = 2; tokenText.append('b'); ++i; state = InNumber; } else if (ch.toUpper() == 'O' && tokenText == "0" && Settings::instance()->programmerBase != 10) { // Octal number. numberBase = 8; tokenText.append('o'); ++i; state = InNumber; } else if (ch.toUpper() == 'D' && tokenText == "0") { // Decimal number (with prefix). numberBase = 10; tokenText.append('d'); ++i; state = InNumber; } else if (isSeparatorChar(ch)) { // Ignore thousand separators. ++i; } else if (tokenText.isEmpty() && (ch == '+' || isMinus(ch))) { // Allow expressions like "$-10" or "$+10". if (isMinus(ch)) tokenText.append('-'); ++i; } else { if (tokenText.endsWith("0")) { // Done with integer number (tokenText is "0" or "-0"). numberBase = 10; state = InNumberEnd; } else { // Only leading separators. state = Bad; } } break; // Parse the number digits. case InNumber: { ushort c = ch.unicode(); bool isDigit = c < DIGIT_MAP_COUNT && (s_digitMap[c] <= numberBase); if (isDigit) { // Consume as long as it's a digit tokenText.append(ex.at(i++).toUpper()); } else if (isExponent(ch, numberBase)) { // Maybe exponent expText = ch.toUpper(); expStart = i; ++i; tokenText = fixNumberRadix(tokenText); if (!tokenText.isNull()) { state = InExpIndicator; } else state = Bad; } else if (isRadixChar(ch)) { // Might be a radix point or a separator. // Collect it and decide later. tokenText.append(ch); ++i; } else if (isSeparatorChar(ch)) { // Ignore thousand separators. ++i; } else { // We're done with number. tokenText = fixNumberRadix(tokenText); if (!tokenText.isNull()) state = InNumberEnd; else state = Bad; } break; } // Validate exponent start. case InExpIndicator: { ushort c = ch.unicode(); bool isDigit = c < DIGIT_MAP_COUNT && (s_digitMap[c] <= numberBase); if (expBase == 0) { // Set the default exponent base (same as number) expBase = numberBase; } if (expText.length() == 1 && (ch == '+' || isMinus(ch))) { // Possible + or - right after E. expText.append(ch == QChar(0x2212) ? '-' : ch); ++i; } else if (isDigit) { if (ch == '0') { // Might be a base prefix expText.append(ch); ++i; state = InExponentBase; } else { // Parse the exponent absolute value. tokenText.append(expText); state = InExponent; } } else if (isSeparatorChar(ch)) { // Ignore thousand separators. ++i; } else { // Invalid thing here. Rollback: might be an identifier // used in implicit multiplication. i = expStart; state = InNumberEnd; } break; } // Detect exponent base. case InExponentBase: { int base = -1; switch (ch.toUpper().unicode()) { case 'B': base = 2; break; case 'O': base = 8; break; case 'D': base = 10; break; case 'X': base = 16; break; } if (base != -1) { // Specific exponent base found expBase = base; tokenText.append(expText); tokenText.append(ch.toLower()); ++i; } else { // No exponent base specified, use the default one tokenText.append(expText); } state = InExponent; break; } // Parse exponent. case InExponent: { ushort c = ch.unicode(); bool isDigit = c < DIGIT_MAP_COUNT && (s_digitMap[c] <= expBase); if (isDigit) { // Consume as long as it's a digit. tokenText.append(ex.at(i++)); } else if (isSeparatorChar(ch)) { // Ignore thousand separators. ++i; } else { // We're done with floating-point number. state = InNumberEnd; }; break; } case InNumberEnd: { int tokenSize = i - tokenStart; tokens.append(Token(Token::stxNumber, tokenText, tokenStart, tokenSize)); // Make sure a number cannot be followed by another number. if (ch.isDigit() || isRadixChar(ch) || ch == '#') state = Bad; else state = Init; break; } case Bad: tokens.setValid(false); break; default: break; }; } if (state == Bad) // Invalidating here too, because usually when we set state to Bad, // the case Bad won't be run. tokens.setValid(false); return tokens; } void Evaluator::compile(const Tokens &tokens) { #ifdef EVALUATOR_DEBUG QFile debugFile("eval.log"); debugFile.open(QIODevice::WriteOnly); QTextStream dbg(&debugFile); #endif // Initialize variables. m_dirty = false; m_valid = false; m_codes.clear(); m_constants.clear(); m_identifiers.clear(); m_error = QString(); // Sanity check. if (tokens.count() == 0) return; TokenStack syntaxStack; QStack argStack; unsigned argCount = 1; for (int i = 0; i <= tokens.count() && !syntaxStack.hasError(); ++i) { // Helper token: Invalid is end-of-expression. auto token = (i < tokens.count()) ? tokens.at(i) : Token(Token::stxOperator); auto tokenType = token.type(); if (tokenType >= Token::stxOperator) tokenType = Token::stxOperator; #ifdef EVALUATOR_DEBUG dbg << "\nToken: " << token.description() << "\n"; #endif // Unknown token is invalid. if (tokenType == Token::stxUnknown) break; // Try to apply all parsing rules. #ifdef EVALUATOR_DEBUG dbg << "\tChecking rules..." << "\n"; #endif // Repeat until no more rule applies. bool argHandled = false; while (!syntaxStack.hasError()) { bool ruleFound = false; // Rule for function last argument: id (arg) -> arg. if (!ruleFound && syntaxStack.itemCount() >= 4) { Token par2 = syntaxStack.top(); Token arg = syntaxStack.top(1); Token par1 = syntaxStack.top(2); Token id = syntaxStack.top(3); if (par2.asOperator() == Token::AssociationEnd && arg.isOperand() && par1.asOperator() == Token::AssociationStart && id.isIdentifier()) { ruleFound = true; syntaxStack.reduce(4, MAX_PRECEDENCE); m_codes.append(Opcode(Opcode::Function, argCount)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for function last argument " << argCount << " \n"; #endif argCount = argStack.empty() ? 0 : argStack.pop(); } } // Are we entering a function? If token is operator, // and stack already has: id (arg. if (!ruleFound && !argHandled && tokenType == Token::stxOperator && syntaxStack.itemCount() >= 3) { Token arg = syntaxStack.top(); Token par = syntaxStack.top(1); Token id = syntaxStack.top(2); if (arg.isOperand() && par.asOperator() == Token::AssociationStart && id.isIdentifier()) { ruleFound = true; argStack.push(argCount); #ifdef EVALUATOR_DEBUG dbg << "\tEntering new function, pushing argcount=" << argCount << " of parent function\n"; #endif argCount = 1; break; } } // Rule for postfix operators: Y POSTFIX -> Y. // Condition: Y is not an operator, POSTFIX is a postfix op. // Since we evaluate from left to right, // we need not check precedence at this point. if (!ruleFound && syntaxStack.itemCount() >= 2) { Token postfix = syntaxStack.top(); Token y = syntaxStack.top(1); if (postfix.isOperator() && y.isOperand()) { switch (postfix.asOperator()) { case Token::Factorial: ruleFound = true; syntaxStack.reduce(2); m_codes.append(Opcode(Opcode::Fact)); break; case Token::Percent: m_singleNumPercent = false; if (syntaxStack.top(2).type() == Token::stxOpenPar) m_singleNumPercent = true; ruleFound = true; syntaxStack.reduce(2); m_codes.append(Opcode(Opcode::Pct)); break; default:; } } #ifdef EVALUATOR_DEBUG if (ruleFound) { dbg << "\tRule for postfix operator " << postfix.text() << "\n"; } #endif } // Rule for parenthesis: (Y) -> Y. if (!ruleFound && syntaxStack.itemCount() >= 3) { Token right = syntaxStack.top(); Token y = syntaxStack.top(1); Token left = syntaxStack.top(2); if (y.isOperand() && right.asOperator() == Token::AssociationEnd && left.asOperator() == Token::AssociationStart) { ruleFound = true; syntaxStack.reduce(3, MAX_PRECEDENCE); #ifdef EVALUATOR_DEBUG dbg << "\tRule for (Y) -> Y" << "\n"; #endif } } // Rule for simplified syntax for function, // e.g. "sin pi" or "cos 1.2". Conditions: // *precedence of function reduction >= precedence of next token. // *or next token is not an operator. if (!ruleFound && syntaxStack.itemCount() >= 2) { Token arg = syntaxStack.top(); Token id = syntaxStack.top(1); if (arg.isOperand() && isFunction(id) && (!token.isOperator() || opPrecedence(Token::Function) >= opPrecedence(token.asOperator()))) { ruleFound = true; m_codes.append(Opcode(Opcode::Function, 1)); syntaxStack.reduce(2); #ifdef EVALUATOR_DEBUG dbg << "\tRule for simplified function syntax; function " << id.text() << "\n"; #endif } } // Rule for unary operator in simplified function syntax. // This handles cases like "sin -90". if (!ruleFound && syntaxStack.itemCount() >= 3) { Token x = syntaxStack.top(); Token op = syntaxStack.top(1); Token id = syntaxStack.top(2); if (x.isOperand() && isFunction(id) && (op.asOperator() == Token::Addition || op.asOperator() == Token::Subtraction)) { ruleFound = true; syntaxStack.reduce(2); if (op.asOperator() == Token::Subtraction) m_codes.append(Opcode(Opcode::Neg)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for unary operator in simplified " "function syntax; function " << id.text() << "\n"; #endif } } // Rule for function arguments. If token is ; or ): // id (arg1 ; arg2 -> id (arg. // Must come before binary op rule, special case of the latter. if (!ruleFound && syntaxStack.itemCount() >= 5 && token.isOperator() && (token.asOperator() == Token::AssociationEnd || token.asOperator() == Token::ListSeparator)) { Token arg2 = syntaxStack.top(); Token sep = syntaxStack.top(1); Token arg1 = syntaxStack.top(2); Token par = syntaxStack.top(3); Token id = syntaxStack.top(4); if (arg2.isOperand() && sep.asOperator() == Token::ListSeparator && arg1.isOperand() && par.asOperator() == Token::AssociationStart && id.isIdentifier()) { ruleFound = true; argHandled = true; syntaxStack.reduce(3, MAX_PRECEDENCE); ++argCount; #ifdef EVALUATOR_DEBUG dbg << "\tRule for function argument " << argCount << " \n"; #endif } } // Rule for function call with parentheses, // but without argument, e.g. "2*PI()". if (!ruleFound && syntaxStack.itemCount() >= 3) { Token par2 = syntaxStack.top(); Token par1 = syntaxStack.top(1); Token id = syntaxStack.top(2); if (par2.asOperator() == Token::AssociationEnd && par1.asOperator() == Token::AssociationStart && id.isIdentifier()) { ruleFound = true; syntaxStack.reduce(3, MAX_PRECEDENCE); m_codes.append(Opcode(Opcode::Function, 0)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for function call with parentheses, " "but without argument\n"; #endif } } // Rule for binary operator: A (op) B -> A. // Conditions: precedence of op >= precedence of token. // Action: push (op) to result e.g. // "A * B" becomes "A" if token is operator "+". // Exception: for caret (power operator), if op is another caret // then it doesn't apply, e.g. "2^3^2" is evaluated as "2^(3^2)". // Exception: doesn't apply if B is a function name (to manage // shift/reduce conflict with simplified function syntax // (issue #600). if (!ruleFound && syntaxStack.itemCount() >= 3) { Token b = syntaxStack.top(); Token op = syntaxStack.top(1); Token a = syntaxStack.top(2); if (a.isOperand() && b.isOperand() && op.isOperator() && ( // Normal operator. (token.isOperator() && opPrecedence(op.asOperator()) >= opPrecedence(token.asOperator()) && !(b.isIdentifier() && token.asOperator() == Token::AssociationStart) && token.asOperator() != Token::Exponentiation) || ( // May represent implicit multiplication. token.isOperand() && opPrecedence(op.asOperator()) >= opPrecedence(Token::Multiplication))) && !(isFunction(b))) { ruleFound = true; switch (op.asOperator()) { // Simple binary operations. case Token::Addition: m_codes.append(Opcode::Add); break; case Token::Subtraction: m_codes.append(Opcode::Sub); break; case Token::Multiplication: m_codes.append(Opcode::Mul); break; case Token::Division: m_codes.append(Opcode::Div); break; case Token::Exponentiation: m_codes.append(Opcode::Pow); break; case Token::Modulo: m_codes.append(Opcode::Modulo); break; //add jingzhou 20200720 增加yroot、log case Token::Yroot: m_codes.append(Opcode::Yroot); break; case Token::Log: m_codes.append(Opcode::Log); break; case Token::IntegerDivision: m_codes.append(Opcode::IntDiv); break; case Token::ArithmeticLeftShift: m_codes.append(Opcode::Sal); break; case Token::ArithmeticRightShift: m_codes.append(Opcode::Sar); break; case Token::LogicalLeftShift: m_codes.append(Opcode::Shl); break; case Token::LogicalRightShift: m_codes.append(Opcode::Shr); break; case Token::CircularLeftShift: m_codes.append(Opcode::Rol); break; case Token::CircularRightShift: m_codes.append(Opcode::Ror); break; case Token::RotateCarryLeftShift: m_codes.append(Opcode::Rcl); break; case Token::RotateCarryRightShift: m_codes.append(Opcode::Rcr); break; case Token::BitwiseLogicalAND: m_codes.append(Opcode::BAnd); break; case Token::BitwiseLogicalOR: m_codes.append(Opcode::BOr); break; //add jingzhou 20201201 增加逻辑运算nand,nor,xor case Token::BitwiseLogicalNAND: m_codes.append(Opcode::BNand); break; case Token::BitwiseLogicalNOR: m_codes.append(Opcode::BNor); break; case Token::BitwiseLogicalXOR: m_codes.append(Opcode::BXor); break; case Token::UnitConversion: { static const QRegExp unitNameNumberRE( "(^[0-9e\\+\\-\\.,]|[0-9e\\.,]$)", Qt::CaseInsensitive); QString unitName = m_expression.mid(b.pos(), b.size()).simplified(); // Make sure the whole unit name can be used // as a single operand in multiplications. if (b.minPrecedence() < opPrecedence(Token::Multiplication)) { unitName = "(" + unitName + ")"; } // Protect the unit name // if it starts or ends with a number. else if (unitNameNumberRE.indexIn(unitName) != -1) unitName = "(" + unitName + ")"; m_codes.append(Opcode(Opcode::Conv, unitName)); break; } default: break; }; syntaxStack.reduce(3); #ifdef EVALUATOR_DEBUG dbg << "\tRule for binary operator" << "\n"; #endif } } #ifdef ALLOW_IMPLICIT_MULT // Rule for implicit multiplication. // Action: Treat as A * B. // Exception: doesn't apply if B is a function name // (to manage shift/reduce conflict with simplified // function syntax (fixes issue #600). if (!ruleFound && syntaxStack.itemCount() >= 2) { Token b = syntaxStack.top(); Token a = syntaxStack.top(1); if (a.isOperand() && b.isOperand() && token.asOperator() != Token::AssociationStart && ( // Token is normal operator. (token.isOperator() && opPrecedence(Token::Multiplication) >= opPrecedence(token.asOperator())) || token.isOperand()) // Implicit multiplication. && !isFunction(b)) { ruleFound = true; syntaxStack.reduce(2, opPrecedence(Token::Multiplication)); m_codes.append(Opcode::Mul); #ifdef EVALUATOR_DEBUG dbg << "\tRule for implicit multiplication" << "\n"; #endif } } #endif // Rule for unary operator: (op1) (op2) X -> (op1) X. // Conditions: op2 is unary. // Current token has lower precedence than multiplication. if (!ruleFound && token.asOperator() != Token::AssociationStart && syntaxStack.itemCount() >= 3) { Token x = syntaxStack.top(); Token op2 = syntaxStack.top(1); Token op1 = syntaxStack.top(2); if (x.isOperand() && op1.isOperator() && (op2.asOperator() == Token::Addition || op2.asOperator() == Token::Subtraction) && (token.isOperand() || opPrecedence(token.asOperator()) <= opPrecedence(Token::Multiplication))) { ruleFound = true; if (op2.asOperator() == Token::Subtraction) m_codes.append(Opcode(Opcode::Neg)); syntaxStack.reduce(2); #ifdef EVALUATOR_DEBUG dbg << "\tRule for unary operator" << op2.text() << "\n"; #endif } } // Auxiliary rule for unary prefix operator: (op) X -> X. // Conditions: op is unary, op is first in syntax stack. // Action: create code for (op). Unary MINUS or PLUS are // treated with the precedence of multiplication. if (!ruleFound && token.asOperator() != Token::AssociationStart && syntaxStack.itemCount() == 2) { Token x = syntaxStack.top(); Token op = syntaxStack.top(1); if (x.isOperand() && (op.asOperator() == Token::Addition || op.asOperator() == Token::Subtraction) && ((token.isOperator() && opPrecedence(token.asOperator()) <= opPrecedence(Token::Multiplication)) || token.isOperand())) { ruleFound = true; if (op.asOperator() == Token::Subtraction) m_codes.append(Opcode(Opcode::Neg)); #ifdef EVALUATOR_DEBUG dbg << "\tRule for unary operator (auxiliary)" << "\n"; #endif syntaxStack.reduce(2); } } if (!ruleFound) break; } // Can't apply rules anymore, push the token. syntaxStack.push(token); // For identifier, generate code to load from reference. if (tokenType == Token::stxIdentifier) { m_identifiers.append(token.text()); m_codes.append(Opcode(Opcode::Ref, m_identifiers.count() - 1)); #ifdef EVALUATOR_DEBUG dbg << "\tPush " << token.text() << " to identifier pools" << "\n"; #endif } // For constants, generate code to load from a constant. if (tokenType == Token::stxNumber) { m_constants.append(token.asNumber()); m_codes.append(Opcode(Opcode::Load, m_constants.count() - 1)); #ifdef EVALUATOR_DEBUG dbg << "\tPush " << token.asNumber() << " to constant pools" << "\n"; #endif } } m_valid = false; if (syntaxStack.hasError()) m_error = syntaxStack.error(); // syntaxStack must left only one operand // and end-of-expression (i.e. Invalid). else if (syntaxStack.itemCount() == 2 && syntaxStack.top().isOperator() && syntaxStack.top().asOperator() == Token::Invalid && !syntaxStack.top(1).isOperator()) { m_valid = true; } #ifdef EVALUATOR_DEBUG dbg << "Dump: " << dump() << "\n"; debugFile.close(); #endif // Bad parsing? Clean-up everything. if (!m_valid) { m_constants.clear(); m_codes.clear(); m_identifiers.clear(); } } Quantity Evaluator::evalNoAssign() { Quantity result; if (m_dirty) { // Reset. m_assignId = QString(); m_assignFunc = false; m_assignArg.clear(); Tokens tokens = scan(m_expression); // Invalid expression? if (!tokens.valid()) { m_error = /*tr*/("invalid expression"); return Quantity(0); } // Variable assignment? if (tokens.count() > 2 && tokens.at(0).isIdentifier() && tokens.at(1).asOperator() == Token::Assignment) { m_assignId = tokens.at(0).text(); tokens.erase(tokens.begin()); tokens.erase(tokens.begin()); } else if (tokens.count() > 2 && tokens.at(0).isIdentifier() && tokens.at(1).asOperator() == Token::AssociationStart) { // Check for function assignment. // Syntax: // ident opLeftPar (ident (opSemiColon ident)*)? opRightPar opEqual int t; if (tokens.count() > 4 && tokens.at(2).asOperator() == Token::AssociationEnd) { // Functions with no argument. t = 3; if (tokens.at(3).asOperator() == Token::Assignment) m_assignFunc = true; } else { for (t = 2; t + 1 < tokens.count(); t += 2) { if (!tokens.at(t).isIdentifier()) break; m_assignArg.append(tokens.at(t).text()); if (tokens.at(t + 1).asOperator() == Token::AssociationEnd) { t += 2; if (t < tokens.count() && tokens.at(t).asOperator() == Token::Assignment) { m_assignFunc = true; } break; } else if (tokens.at(t + 1) .asOperator() != Token::ListSeparator) break; } } if (m_assignFunc) { m_assignId = tokens.at(0).text(); for (; t >= 0; --t) tokens.erase(tokens.begin()); } else m_assignArg.clear(); } compile(tokens); if (!m_valid) { if (m_error.isEmpty()) m_error = /*tr*/("compile error"); return CNumber(0); } } result = exec(m_codes, m_constants, m_identifiers); return result; } Quantity Evaluator::exec(const QVector &opcodes, const QVector &constants, const QStringList &identifiers) { QStack stack; QHash refs; int index; Quantity val1, val2; QVector args; QString fname; Function *function; const UserFunction *userFunction = nullptr; for (int pc = 0; pc < opcodes.count(); ++pc) { const Opcode &opcode = opcodes.at(pc); index = opcode.index; switch (opcode.type) { // No operation. case Opcode::Nop: break; // Load a constant, push to stack. case Opcode::Load: val1 = constants.at(index); stack.push(val1); break; // Unary operation. case Opcode::Neg: if (stack.count() < 1) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val1 = checkOperatorResult(-val1); stack.push(val1); break; // Binary operation: take two values from stack, // do the operation, push the result to stack. case Opcode::Add: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 = checkOperatorResult(val2 + val1); stack.push(val2); break; case Opcode::Sub: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 = checkOperatorResult(val2 - val1); stack.push(val2); break; case Opcode::Mul: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 = checkOperatorResult(val2 * val1); stack.push(val2); break; case Opcode::Div: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); //对于 A^(X/Y)类型的表达式,当X为偶数时,将A变为正数 if ((pc + 1) < opcodes.count() && opcodes.at(pc + 1).type == Opcode::Pow) { if (val2.isEven()) { Quantity temp = stack.pop(); temp *= temp.isNegative() ? -1 : 1; stack.push(temp); } } val2 = checkOperatorResult(val2 / val1); stack.push(val2); break; case Opcode::Pow: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 = checkOperatorResult(DMath::raise(val2, val1)); stack.push(val2); break; //add jingzhou 20200720 case Opcode::Yroot: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 = checkOperatorResult(DMath::raise(val2, Quantity(1) / val1)); stack.push(val2); break; case Opcode::Log: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 = checkOperatorResult(DMath::log(val1, val2)); stack.push(val2); break; case Opcode::Fact: if (stack.count() < 1) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val1 = checkOperatorResult(DMath::factorial(val1)); stack.push(val1); break; case Opcode::Modulo: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 = checkOperatorResult(val2 % val1); stack.push(val2); break; case Opcode::IntDiv: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 = checkOperatorResult(val2 / val1); stack.push(DMath::integer(val2)); break; case Opcode::Sal: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); if (val1.isNegative()) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val2 = checkOperatorResult(DMath::ashr(val2, -val1)); stack.push(val2); break; case Opcode::Sar: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); if (val1.isNegative()) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val2 = checkOperatorResult(DMath::ashr(val2, val1)); stack.push(val2); break; case Opcode::Shl: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); if (val1.isNegative()) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val2 = checkOperatorResult(DMath::lshr(val2, -val1)); stack.push(val2); break; case Opcode::Shr: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); if (val1.isNegative()) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val2 = checkOperatorResult(DMath::lshr(val2, val1)); stack.push(val2); break; case Opcode::Rol: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); if (val1.isNegative()) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val2 = checkOperatorResult(DMath::rosh(val2, -val1)); stack.push(val2); break; case Opcode::Ror: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); if (val1.isNegative()) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val2 = checkOperatorResult(DMath::rosh(val2, val1)); stack.push(val2); break; case Opcode::Rcl: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); if (val1.isNegative()) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val2 = checkOperatorResult(DMath::rcsh(val2, -val1)); stack.push(val2); break; case Opcode::Rcr: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); if (val1.isNegative()) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val2 = checkOperatorResult(DMath::rcsh(val2, val1)); stack.push(val2); break; case Opcode::BAnd: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 &= val1; stack.push(val2); break; case Opcode::BOr: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 |= val1; stack.push(val2); break; case Opcode::BNand: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 &= val1; val2 = ~ val2; stack.push(val2); break; case Opcode::BNor: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 |= val1; val2 = ~ val2; stack.push(val2); break; case Opcode::BXor: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return DMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); val2 ^= val1; stack.push(val2); break; case Opcode::Pct: if (stack.count() < 1) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } val1 = stack.pop(); switch (((pc + 1) < opcodes.count() && !m_singleNumPercent) ? opcodes.at(pc + 1).type : Opcode::Nop) { case Opcode::Add: case Opcode::Sub: val2 = stack.pop(); stack.push(val2); break; default: val2 = Quantity(1); } val1 = checkOperatorResult(val2 * (val1 * HNumber("0.01"))); m_standardPercent = val1; stack.push(val1); break; case Opcode::Conv: if (stack.count() < 2) { m_error = /*tr*/("invalid expression"); return HMath::nan(); } val1 = stack.pop(); val2 = stack.pop(); if (val1.isZero()) { m_error = /*tr*/("unit must not be zero"); return HMath::nan(); } if (!val1.sameDimension(val2)) { m_error = /*tr*/("Conversion failed - dimension mismatch"); return HMath::nan(); } val2.setDisplayUnit(val1.numericValue(), opcode.text); stack.push(val2); break; // Reference. case Opcode::Ref: fname = identifiers.at(index); if (m_assignArg.contains(fname)) { // Argument. stack.push(CMath::nan()); } else if (hasVariable(fname)) { // Variable. stack.push(getVariable(fname).value()); } else { // Function. function = FunctionRepo::instance()->find(fname); if (function) { stack.push(CMath::nan()); refs.insert(stack.count(), fname); } else if (m_assignFunc) { // Allow arbitrary identifiers // when declaring user functions. stack.push(CMath::nan()); refs.insert(stack.count(), fname); } else if (hasUserFunction(fname)) { stack.push(CMath::nan()); refs.insert(stack.count(), fname); } else { m_error = "" + fname + ": " + /*tr*/("unknown function or variable"); return CMath::nan(); } } break; // Calling function. case Opcode::Function: // Must do this first to avoid crash // when using vars like functions. if (refs.isEmpty()) break; fname = refs.take(stack.count() - index); function = FunctionRepo::instance()->find(fname); userFunction = nullptr; if (!function) { // Check if this is a valid user function call. userFunction = getUserFunction(fname); } if (!function && !userFunction && !m_assignFunc) { m_error = "" + fname + ": " + /*tr*/("unknown function or variable"); return CMath::nan(); } if (stack.count() < index) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } args.clear(); for (; index; --index) args.insert(args.begin(), stack.pop()); // Remove the NaN we put on the stack (needed to make the user // functions declaration work with arbitrary identifiers). stack.pop(); // Show function signature if user has given no argument (yet). if (userFunction) { if (!args.count() && userFunction->arguments().count() != 0) { m_error = QString::fromLatin1("%1(%2)").arg( userFunction->name(), userFunction->arguments().join(";") ); return CMath::nan(); } } else if (function) { if (!args.count()) { m_error = QString::fromLatin1("%1(%2)").arg( fname, function->usage() ); return CMath::nan(); } } if (m_assignFunc) { // Allow arbitrary identifiers for declaring user functions. stack.push(CMath::nan()); } else if (userFunction) { stack.push(execUserFunction(userFunction, args)); if (!m_error.isEmpty()) return CMath::nan(); } else { stack.push(function->exec(args)); if (function->error()) { m_error = stringFromFunctionError(function); return CMath::nan(); } } break; default: break; } } // More than one value in stack? Unsuccessful execution. if (stack.count() != 1) { m_error = /*tr*/("invalid expression"); return CMath::nan(); } return stack.pop(); } Quantity Evaluator::execUserFunction(const UserFunction *function, QVector &arguments) { // TODO: Replace user variables by user functions (with no argument)? if (arguments.count() != function->arguments().count()) { m_error = "" + function->name() + ": " + /*tr*/("wrong number of arguments"); return CMath::nan(); } if (m_functionsInUse.contains(function->name())) { m_error = "" + function->name() + ": " + /*tr*/("recursion not supported"); return CMath::nan(); } m_functionsInUse.insert(function->name()); QVector newOpcodes; auto newConstants = function->constants; // Copy. // Replace references to function arguments by constants. for (int i = 0; i < function->opcodes.count(); ++i) { Opcode opcode = function->opcodes.at(i); if (opcode.type == Opcode::Ref) { // Check if the identifier is an argument name. QString name = function->identifiers.at(opcode.index); int argIdx = function->arguments().indexOf(name); if (argIdx >= 0) { // Replace the reference by a constant value. opcode = Opcode(Opcode::Load, newConstants.count()); newConstants.append(arguments.at(argIdx)); } } newOpcodes.append(opcode); } auto result = exec(newOpcodes, newConstants, function->identifiers); if (!m_error.isEmpty()) { // Tell the user where the error happened. m_error = "" + function->name() + ": " + m_error; } m_functionsInUse.remove(function->name()); return result; } bool Evaluator::isUserFunctionAssign() const { return m_assignFunc; } bool Evaluator::isBuiltInVariable(const QString &id) const { // Defining variables with the same name as existing functions // is not supported for now. if (FunctionRepo::instance()->find(id)) return true; if (!m_session || !m_session->hasVariable(id)) return false; return m_session->getVariable(id).type() == Variable::BuiltIn; } Quantity Evaluator::eval() { Quantity result = evalNoAssign(); // This sets m_assignId. if (!m_error.isEmpty()) return result; if (isBuiltInVariable(m_assignId)) { //m_error = tr("%1 is a reserved name, " // "please choose another").arg(m_assignId); return CMath::nan(); } // Handle user variable or function assignment. if (!m_assignId.isEmpty()) { if (m_assignFunc) { if (hasVariable(m_assignId)) { // m_error = tr("%1 is a variable name, please choose another " // "or delete the variable").arg(m_assignId); return CMath::nan(); } // Check that each argument is unique and not a reserved identifier. for (int i = 0; i < m_assignArg.count() - 1; ++i) { const QString &argName = m_assignArg.at(i); if (m_assignArg.indexOf(argName, i + 1) != -1) { // m_error = tr("argument %1 is used " // "more than once").arg(argName); return CMath::nan(); } if (isBuiltInVariable(argName)) { // m_error = tr("%1 is a reserved name, " // "please choose another").arg(argName); return CMath::nan(); } } if (m_codes.isEmpty()) return CMath::nan(); UserFunction userFunction(m_assignId, m_assignArg, m_expression.section("=", 1, 1).trimmed()); userFunction.constants = m_constants; userFunction.identifiers = m_identifiers; userFunction.opcodes = m_codes; setUserFunction(userFunction); } else { if (hasUserFunction(m_assignId)) { //m_error = tr("%1 is a user function name, please choose " // "another or delete the function").arg(m_assignId); return CMath::nan(); } setVariable(m_assignId, result); } } return result; } Quantity Evaluator::evalUpdateAns() { Settings::instance()->proRotateCarry.front() = Settings::instance()->proRotateCarry.at(1); auto result = eval(); if (m_error.isEmpty() && !m_assignFunc) setVariable(QLatin1String("ans"), result, Variable::BuiltIn); return result; } void Evaluator::setVariable(const QString &id, Quantity value, Variable::Type type) { if (!m_session) m_session = new Session(this); m_session->addVariable(Variable(id, value, type)); } Variable Evaluator::getVariable(const QString &id) const { if (id.isEmpty() || !m_session) return Variable(QLatin1String(""), Quantity(0)); return m_session->getVariable(id); } bool Evaluator::hasVariable(const QString &id) const { if (id.isEmpty() || !m_session) return false; else return m_session->hasVariable(id); } void Evaluator::unsetVariable(const QString &id, ForceBuiltinVariableErasure force) { if (!m_session || (m_session->isBuiltInVariable(id) && !force)) return; m_session->removeVariable(id); } QList Evaluator::getVariables() const { return m_session ? m_session->variablesToList() : QList(); } QList Evaluator::getUserDefinedVariables() const { auto result = getVariables(); auto iter = result.begin(); while (iter != result.end()) { if ((*iter).type() == Variable::BuiltIn) iter = result.erase(iter); else ++iter; } return result; } QList Evaluator::getUserDefinedVariablesPlusAns() const { auto result = getUserDefinedVariables(); auto ans = getVariable(QLatin1String("ans")); if (!ans.identifier().isEmpty()) result.append(ans); return result; } void Evaluator::unsetAllUserDefinedVariables() { if (!m_session) return; auto ansBackup = getVariable(QLatin1String("ans")).value(); m_session->clearVariables(); setVariable(QLatin1String("ans"), ansBackup, Variable::BuiltIn); initializeBuiltInVariables(); } static void replaceSuperscriptPowersWithCaretEquivalent(QString &expr) { static const QRegularExpression s_superscriptPowersRE( "(\\x{207B})?[\\x{2070}¹²³\\x{2074}-\\x{2079}]+" ); static const QHash s_superscriptPowersHash { {L'\u207B', '-'}, {L'\u2070', '0'}, {L'\u00B9', '1'}, {L'\u00B2', '2'}, {L'\u00B3', '3'}, {L'\u2074', '4'}, {L'\u2075', '5'}, {L'\u2076', '6'}, {L'\u2077', '7'}, {L'\u2078', '8'}, {L'\u2079', '9'}, }; int offset = 0; while (true) { QRegularExpressionMatch match = s_superscriptPowersRE.match(expr, offset); if (!match.hasMatch()) break; QString power = match.captured(); for (int pos = power.size() - 1; pos >= 0; --pos) { QChar c = power.at(pos); power.replace(pos, 1, s_superscriptPowersHash.value(c, c)); } bool isNegative = match.capturedStart(1) != -1; if (isNegative) power = "^(" + power + ")"; else power = "^" + power; expr.replace(match.capturedStart(), match.capturedLength(), power); offset = match.capturedStart() + power.size(); } } QList Evaluator::getUserFunctions() const { return m_session ? m_session->UserFunctionsToList() : QList(); } void Evaluator::setUserFunction(const UserFunction &f) { if (!m_session) m_session = new Session; m_session->addUserFunction(f); } void Evaluator::unsetUserFunction(const QString &fname) { m_session->removeUserFunction(fname); } void Evaluator::unsetAllUserFunctions() { m_session->clearUserFunctions(); } bool Evaluator::hasUserFunction(const QString &fname) const { bool invalid = fname.isEmpty() || !m_session; return (invalid) ? false : m_session->hasUserFunction(fname); } Quantity Evaluator::getStandardPercentAns() { return m_standardPercent; } const UserFunction *Evaluator::getUserFunction(const QString &fname) const { if (hasUserFunction(fname)) return m_session->getUserFunction(fname); else return nullptr; } QString Evaluator::autoFix(const QString &expr) { int par = 0; QString result; // Strip off all funny characters. for (int c = 0; c < expr.length(); ++c) if (expr.at(c) >= QChar(32)) result.append(expr.at(c)); // No extra whitespaces at the beginning and at the end. result = result.trimmed(); // Strip trailing equal sign (=). while (result.endsWith("=")) result = result.left(result.length() - 1); replaceSuperscriptPowersWithCaretEquivalent(result); // Automagically close all parenthesis. Tokens tokens = Evaluator::scan(result); if (tokens.count()) { for (int i = 0; i < tokens.count(); ++i) if (tokens.at(i).asOperator() == Token::AssociationStart) ++par; else if (tokens.at(i).asOperator() == Token::AssociationEnd) --par; if (par < 0) par = 0; // If the scanner stops in the middle, do not bother to apply fix. const Token &lastToken = tokens.at(tokens.count() - 1); if (lastToken.pos() + lastToken.size() >= result.length()) while (par--) result.append(')'); } // Special treatment for simple function // e.g. "cos" is regarded as "cos(ans)". if (!result.isEmpty()) { Tokens tokens = Evaluator::scan(result); if (tokens.count() == 1 && tokens.at(0).isIdentifier() && FunctionRepo::instance()->find(tokens.at(0).text())) { result.append("(ans)"); } } return result; } QString Evaluator::dump() { QString result; int c; if (m_dirty) { Tokens tokens = scan(m_expression); compile(tokens); } result = QString("Expression: [%1]\n").arg(m_expression); result.append(" Constants:\n"); for (c = 0; c < m_constants.count(); ++c) { auto val = m_constants.at(c); result += QString(" #%1 = %2\n").arg(c).arg( DMath::format(val, Quantity::Format::Fixed()) ); } result.append("\n"); result.append(" Identifiers:\n"); for (c = 0; c < m_identifiers.count(); ++c) { result += QString(" #%1 = %2\n").arg(c).arg(m_identifiers.at(c)); } result.append("\n"); result.append(" Code:\n"); for (int i = 0; i < m_codes.count(); ++i) { QString code; switch (m_codes.at(i).type) { case Opcode::Load: code = QString("Load #%1").arg(m_codes.at(i).index); break; case Opcode::Ref: code = QString("Ref #%1").arg(m_codes.at(i).index); break; case Opcode::Function: code = QString("Function (%1)").arg(m_codes.at(i).index); break; case Opcode::Add: code = "Add"; break; case Opcode::Sub: code = "Sub"; break; case Opcode::Mul: code = "Mul"; break; case Opcode::Div: code = "Div"; break; case Opcode::Neg: code = "Neg"; break; case Opcode::Pow: code = "Pow"; break; case Opcode::Fact: code = "Fact"; break; case Opcode::Sal: code = "LSh"; break; case Opcode::Sar: code = "RSh"; break; case Opcode::BAnd: code = "BAnd"; break; case Opcode::BOr: code = "BOr"; break; case Opcode::Pct: code = "Pct"; break; default: code = "Unknown"; break; } result.append(" ").append(code).append("\n"); } return result; } deepin-calculator-5.7.21/3rdparty/core/evaluator.h000066400000000000000000000155541423020056600220640ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2008-2016 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_EVALUATOR_H #define CORE_EVALUATOR_H #include "functions.h" #include "opcode.h" #include "variable.h" #include "userfunction.h" #include "../math/hmath.h" #include "../math/cmath.h" #include "../math/quantity.h" #include #include #include #include #include #include class Session; class Token { public: enum Operator { Invalid = 0, Addition, Subtraction, Multiplication, Division, IntegerDivision, Exponentiation, Super0, Super1, Super2, Super3, Super4, Super5, Super6, Super7, Super8, Super9, AssociationStart, AssociationEnd, Percent, ListSeparator, Factorial, Assignment, Modulo, ArithmeticLeftShift, ArithmeticRightShift, BitwiseLogicalAND, BitwiseLogicalOR, UnitConversion, Function, // For managing shift/reduce conflicts. Yroot, Log,//add jingzhou 20200720 BitwiseLogicalXOR, BitwiseLogicalNAND, BitwiseLogicalNOR,//add jingzhou 20201201 LogicalLeftShift, LogicalRightShift, // add 20201204 CircularLeftShift, CircularRightShift, RotateCarryLeftShift, RotateCarryRightShift//add 20201205 }; enum Type { stxUnknown, stxNumber, stxIdentifier, stxAbstract, // isOperand stxOperator, stxOpenPar, stxClosePar, stxSep // isOperator }; static const Token null; Token(Type = stxUnknown, const QString & = QString::null, int pos = -1, int size = -1); Token(const Token &); Quantity asNumber() const; Operator asOperator() const; QString description() const; bool isNumber() const { return m_type == stxNumber; } bool isOperator() const { return m_type >= stxOperator; } bool isIdentifier() const { return m_type == stxIdentifier; } bool isAbstract() const { return m_type == stxAbstract; } bool isOperand() const { return isNumber() || isIdentifier() || isAbstract(); } int pos() const { return m_pos; } void setPos(int pos) { m_pos = pos; } int size() const { return m_size; } void setSize(int size) { m_size = size; } QString text() const { return m_text; } Type type() const { return m_type; } int minPrecedence() const { return m_minPrecedence; } void setMinPrecedence(int value) { m_minPrecedence = value; } Token &operator=(const Token &); protected: // Start position of the text that token represents in the expression // (might include extra space characters). int m_pos; // Size of text that token represents in the expression // (might include extra space characters). int m_size; // Precedence of the operator with the lowest precedence contained // in this token. int m_minPrecedence; // Normalized version of that token text (only valid when the token // represents a single token). QString m_text; Type m_type; }; class Tokens : public QVector { public: Tokens() : QVector() , m_valid(true) { } bool valid() const { return m_valid; } void setValid(bool v) { m_valid = v; } #ifdef EVALUATOR_DEBUG void append(const Token &); #endif /* EVALUATOR_DEBUG */ protected: bool m_valid; }; class Evaluator : public QObject { Q_OBJECT using ForceBuiltinVariableErasure = bool; public: static Evaluator *instance(); void reset(); void setSession(Session *); const Session *session(); static bool isSeparatorChar(const QChar &); static bool isRadixChar(const QChar &); static QString fixNumberRadix(const QString &); QString autoFix(const QString &); QString dump(); QString error() const; Quantity eval(); Quantity evalNoAssign(); Quantity evalUpdateAns(); QString expression() const; bool isValid(); Tokens scan(const QString &) const; void setExpression(const QString &); Tokens tokens() const; bool isUserFunctionAssign() const; Variable getVariable(const QString &) const; QList getVariables() const; QList getUserDefinedVariables() const; QList getUserDefinedVariablesPlusAns() const; void setVariable(const QString &, Quantity, Variable::Type = Variable::UserDefined); void unsetVariable(const QString &, ForceBuiltinVariableErasure = false); void unsetAllUserDefinedVariables(); bool isBuiltInVariable(const QString &) const; bool hasVariable(const QString &) const; void initializeBuiltInVariables(); void initializeAngleUnits(); QList getUserFunctions() const; void setUserFunction(const UserFunction &); void unsetUserFunction(const QString &); void unsetAllUserFunctions(); bool hasUserFunction(const QString &) const; Quantity getStandardPercentAns(); //获取标准模式下的百分号处理 protected: void compile(const Tokens &); private: Q_DISABLE_COPY(Evaluator) Evaluator(); bool m_dirty; QString m_error; QString m_expression; bool m_valid; QString m_assignId; bool m_assignFunc; QStringList m_assignArg; QVector m_codes; QVector m_constants; QStringList m_identifiers; Session *m_session; QSet m_functionsInUse; Quantity m_standardPercent = Quantity(); //标准模式下的百分号结果 bool m_singleNumPercent = false;//true:100-(50%) = 100 - 0.5; const Quantity &checkOperatorResult(const Quantity &); static QString stringFromFunctionError(Function *); Quantity exec(const QVector &opcodes, const QVector &constants, const QStringList &identifiers); Quantity execUserFunction(const UserFunction *function, QVector &arguments); const UserFunction *getUserFunction(const QString &) const; bool isFunction(Token token) { return token.isIdentifier() && (FunctionRepo::instance()->find(token.text()) || hasUserFunction(token.text())); } }; #endif deepin-calculator-5.7.21/3rdparty/core/functions.cpp000066400000000000000000001156401423020056600224220ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2004-2006 Ariya Hidayat // Copyright (C) 2007, 2009 Wolf Lammen // Copyright (C) 2007-2009, 2013, 2014 @heldercorreia // Copyright (C) 2009 Andreas Scherer // Copyright (C) 2011 Enrico Rós // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "functions.h" #include "settings.h" #include "../math/hmath.h" #include "../math/cmath.h" #include #include #include #include #include #include #include #define FUNCTION_INSERT(ID) insert(new Function(#ID, function_ ## ID, this)) #define FUNCTION_USAGE(ID, USAGE) find(#ID)->setUsage(QString::fromLatin1(USAGE)); #define FUNCTION_USAGE_TR(ID, USAGE) find(#ID)->setUsage(USAGE); #define FUNCTION_NAME(ID, NAME) find(#ID)->setName(NAME) #define ENSURE_MINIMUM_ARGUMENT_COUNT(i) \ if (args.count() < i) { \ f->setError(InvalidParamCount); \ return CMath::nan(InvalidParamCount); \ } #define ENSURE_ARGUMENT_COUNT(i) \ if (args.count() != (i)) { \ f->setError(InvalidParamCount); \ return CMath::nan(InvalidParamCount); \ } #define ENSURE_EITHER_ARGUMENT_COUNT(i, j) \ if (args.count() != (i) && args.count() != (j)) { \ f->setError(InvalidParamCount); \ return CMath::nan(InvalidParamCount); \ } #define ENSURE_SAME_DIMENSION() \ for(int i=0; isetError(OutOfDomain); \ return CMath::nan(); \ } #define ENSURE_REAL_ARGUMENTS() \ for (int i = 0; i < args.count(); i++) { \ ENSURE_REAL_ARGUMENT(i); \ } #define CONVERT_ARGUMENT_ANGLE(angle) \ if (Settings::instance()->angleUnit == 'd') { \ if (angle.isReal()) \ angle = DMath::deg2rad(angle); \ else { \ f->setError(OutOfDomain); \ return DMath::nan(); \ } \ } \ else if (Settings::instance()->angleUnit == 'g') { \ if (angle.isReal()) \ angle = DMath::gon2rad(angle); \ else { \ f->setError(OutOfDomain); \ return DMath::nan(); \ } \ } #define CONVERT_RESULT_ANGLE(result) \ if (Settings::instance()->angleUnit == 'd') \ result = DMath::rad2deg(result); \ else if (Settings::instance()->angleUnit == 'g') \ result = DMath::rad2gon(result); static FunctionRepo *s_FunctionRepoInstance = 0; // FIXME: destructor seems not to be called static void s_deleteFunctions() { delete s_FunctionRepoInstance; } Quantity Function::exec(const Function::ArgumentList &args) { if (!m_ptr) return CMath::nan(); setError(Success); Quantity result = (*m_ptr)(this, args); if (result.error()) setError(result.error()); return result; } Quantity function_abs(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::abs(args.at(0)); } Quantity function_average(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin() + 1, args.end(), *args.begin()) / Quantity(args.count()); } Quantity function_absdev(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); Quantity mean = function_average(f, args); if (mean.isNan()) return mean; // pass the error along Quantity acc = 0; for (int i = 0; i < args.count(); ++i) acc += DMath::abs(args.at(i) - mean); return acc / Quantity(args.count()); } Quantity function_int(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::integer(args[0]); } Quantity function_trunc(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_EITHER_ARGUMENT_COUNT(1, 2); Quantity num = args.at(0); if (args.count() == 2) { Quantity argprec = args.at(1); if (argprec != 0) { if (!argprec.isInteger()) { f->setError(OutOfDomain); return DMath::nan(); } int prec = argprec.numericValue().toInt(); if (prec) return DMath::trunc(num, prec); // The second parameter exceeds the integer limits. if (argprec < 0) return Quantity(0); return num; } } return DMath::trunc(num); } Quantity function_frac(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::frac(args[0]); } Quantity function_floor(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::floor(args[0]); } Quantity function_ceil(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::ceil(args[0]); } Quantity function_gcd(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); for (int i = 0; i < args.count(); ++i) if (!args[i].isInteger()) { f->setError(OutOfDomain); return DMath::nan(); } return std::accumulate(args.begin() + 1, args.end(), args.at(0), DMath::gcd); } Quantity function_round(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_EITHER_ARGUMENT_COUNT(1, 2); Quantity num = args.at(0); if (args.count() == 2) { Quantity argPrecision = args.at(1); if (argPrecision != 0) { if (!argPrecision.isInteger()) { f->setError(OutOfDomain); return DMath::nan(); } int prec = argPrecision.numericValue().toInt(); if (prec) return DMath::round(num, prec); // The second parameter exceeds the integer limits. if (argPrecision < 0) return Quantity(0); return num; } } return DMath::round(num); } Quantity function_sqrt(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::sqrt(args[0]); } Quantity function_variance(Function *f, const Function::ArgumentList &args) { ENSURE_MINIMUM_ARGUMENT_COUNT(2); Quantity mean = function_average(f, args); if (mean.isNan()) return mean; Quantity acc(DMath::real(args[0] - mean)*DMath::real(args[0] - mean) + DMath::imag(args[0] - mean)*DMath::imag(args[0] - mean)); for (int i = 1; i < args.count(); ++i) { Quantity q(args[i] - mean); acc += DMath::real(q) * DMath::real(q) + DMath::imag(q) * DMath::imag(q); } return acc / Quantity(args.count()); } Quantity function_stddev(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); return DMath::sqrt(function_variance(f, args)); } Quantity function_cbrt(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::cbrt(args[0]); } Quantity function_exp(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::exp(args[0]); } Quantity function_ln(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::ln(args[0]); } Quantity function_lg(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::lg(args[0]); } Quantity function_lb(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::lb(args[0]); } Quantity function_log(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::log(args.at(0), args.at(1)); } Quantity function_real(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::real(args.at(0)); } Quantity function_imag(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::imag(args.at(0)); } Quantity function_conj(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::conj(args.at(0)); } Quantity function_phase(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = DMath::phase(args.at(0)); CONVERT_RESULT_ANGLE(angle); return angle; } Quantity function_sin(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); return DMath::sin(angle); } Quantity function_cos(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); return DMath::cos(angle); } Quantity function_tan(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); return DMath::tan(angle); } Quantity function_cot(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); return DMath::cot(angle); } Quantity function_sec(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); return DMath::sec(angle); } Quantity function_csc(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity angle = args.at(0); CONVERT_ARGUMENT_ANGLE(angle); return DMath::csc(angle); } Quantity function_arcsin(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity result; result = DMath::arcsin(args.at(0)); CONVERT_RESULT_ANGLE(result); return result; } Quantity function_arccos(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity result; result = DMath::arccos(args.at(0)); CONVERT_RESULT_ANGLE(result); return result; } Quantity function_arctan(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity result; result = DMath::arctan(args.at(0)); CONVERT_RESULT_ANGLE(result); return result; } Quantity function_arctan2(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(2); Quantity result; result = DMath::arctan2(args.at(0), args.at(1)); CONVERT_RESULT_ANGLE(result); return result; } //add 20200619 arccot(x) Quantity function_arccot(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); Quantity result; result = DMath::arctan(args.at(0)); result = (DMath::pi() / Quantity(2)) - result; CONVERT_RESULT_ANGLE(result); return result; } Quantity function_sinh(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::sinh(args[0]); } Quantity function_cosh(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::cosh(args[0]); } Quantity function_tanh(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::tanh(args[0]); } Quantity function_arsinh(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::arsinh(args[0]); } Quantity function_arcosh(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::arcosh(args[0]); } Quantity function_artanh(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::artanh(args[0]); } Quantity function_erf(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::erf(args[0]); } Quantity function_erfc(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::erfc(args[0]); } Quantity function_gamma(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::gamma(args[0]); } Quantity function_lngamma(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); ENSURE_REAL_ARGUMENT(0); return DMath::lnGamma(args[0]); } Quantity function_sgn(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::sgn(args[0]); } Quantity function_ncr(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::nCr(args.at(0), args.at(1)); } Quantity function_npr(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::nPr(args.at(0), args.at(1)); } Quantity function_degrees(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::rad2deg(args[0]); } Quantity function_radians(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::deg2rad(args[0]); } Quantity function_gradians(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return DMath::rad2gon(args[0]); } Quantity function_max(Function *f, const Function::ArgumentList &args) { ENSURE_MINIMUM_ARGUMENT_COUNT(2); ENSURE_REAL_ARGUMENTS() ENSURE_SAME_DIMENSION() return *std::max_element(args.begin(), args.end()); } Quantity function_median(Function *f, const Function::ArgumentList &args) { ENSURE_MINIMUM_ARGUMENT_COUNT(2); ENSURE_REAL_ARGUMENTS() ENSURE_SAME_DIMENSION() Function::ArgumentList sortedArgs = args; std::sort(sortedArgs.begin(), sortedArgs.end()); if ((args.count() & 1) == 1) return sortedArgs.at((args.count() - 1) / 2); const int centerLeft = args.count() / 2 - 1; return (sortedArgs.at(centerLeft) + sortedArgs.at(centerLeft + 1)) / Quantity(2); } Quantity function_min(Function *f, const Function::ArgumentList &args) { ENSURE_MINIMUM_ARGUMENT_COUNT(2); ENSURE_REAL_ARGUMENTS() ENSURE_SAME_DIMENSION() return *std::min_element(args.begin(), args.end()); } Quantity function_sum(Function *f, const Function::ArgumentList &args) { ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin(), args.end(), Quantity(0)); } Quantity function_product(Function *f, const Function::ArgumentList &args) { ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin(), args.end(), Quantity(1), std::multiplies()); } Quantity function_geomean(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); Quantity result = std::accumulate(args.begin(), args.end(), Quantity(1), std::multiplies()); if (result <= Quantity(0)) return DMath::nan(OutOfDomain); if (args.count() == 1) return result; if (args.count() == 2) return DMath::sqrt(result); return DMath::raise(result, Quantity(1) / Quantity(args.count())); } Quantity function_dec(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Decimal() + Quantity(args.at(0)).format()); } Quantity function_hex(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Fixed() + Quantity::Format::Hexadecimal() + Quantity(args.at(0)).format()); } Quantity function_oct(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Fixed() + Quantity::Format::Octal() + Quantity(args.at(0)).format()); } Quantity function_bin(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Fixed() + Quantity::Format::Binary() + Quantity(args.at(0)).format()); } Quantity function_cart(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Cartesian() + Quantity(args.at(0)).format()); } Quantity function_polar(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(1); return Quantity(args.at(0)).setFormat(Quantity::Format::Polar() + Quantity(args.at(0)).format()); } Quantity function_binompmf(Function *f, const Function::ArgumentList &args) { ENSURE_ARGUMENT_COUNT(3); return DMath::binomialPmf(args.at(0), args.at(1), args.at(2)); } Quantity function_binomcdf(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(3); return DMath::binomialCdf(args.at(0), args.at(1), args.at(2)); } Quantity function_binommean(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::binomialMean(args.at(0), args.at(1)); } Quantity function_binomvar(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::binomialVariance(args.at(0), args.at(1)); } Quantity function_hyperpmf(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(4); return DMath::hypergeometricPmf(args.at(0), args.at(1), args.at(2), args.at(3)); } Quantity function_hypercdf(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(4); return DMath::hypergeometricCdf(args.at(0), args.at(1), args.at(2), args.at(3)); } Quantity function_hypermean(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(3); return DMath::hypergeometricMean(args.at(0), args.at(1), args.at(2)); } Quantity function_hypervar(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(3); return DMath::hypergeometricVariance(args.at(0), args.at(1), args.at(2)); } Quantity function_poipmf(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::poissonPmf(args.at(0), args.at(1)); } Quantity function_poicdf(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::poissonCdf(args.at(0), args.at(1)); } Quantity function_poimean(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::poissonMean(args.at(0)); } Quantity function_poivar(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::poissonVariance(args.at(0)); } Quantity function_mask(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::mask(args.at(0), args.at(1)); } Quantity function_unmask(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::sgnext(args.at(0), args.at(1)); } Quantity function_not(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return ~args.at(0); } Quantity function_and(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin(), args.end(), Quantity(-1), std::mem_fun_ref(&Quantity::operator&)); } Quantity function_or(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin(), args.end(), Quantity(0), std::mem_fun_ref(&Quantity::operator|)); } Quantity function_xor(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_MINIMUM_ARGUMENT_COUNT(2); return std::accumulate(args.begin(), args.end(), Quantity(0), std::mem_fun_ref(&Quantity::operator^)); } Quantity function_shl(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::ashr(args.at(0), -args.at(1)); } Quantity function_shr(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::ashr(args.at(0), args.at(1)); } Quantity function_idiv(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::idiv(args.at(0), args.at(1)); } Quantity function_mod(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return args.at(0) % args.at(1); } Quantity function_ieee754_decode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_EITHER_ARGUMENT_COUNT(3, 4); if (args.count() == 3) { return DMath::decodeIeee754(args.at(0), args.at(1), args.at(2)); } else { return DMath::decodeIeee754(args.at(0), args.at(1), args.at(2), args.at(3)); } } Quantity function_ieee754_encode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_EITHER_ARGUMENT_COUNT(3, 4); if (args.count() == 3) { return DMath::encodeIeee754(args.at(0), args.at(1), args.at(2)); } else { return DMath::encodeIeee754(args.at(0), args.at(1), args.at(2), args.at(3)); } } Quantity function_ieee754_half_decode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::decodeIeee754(args.at(0), 5, 10); } Quantity function_ieee754_half_encode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::encodeIeee754(args.at(0), 5, 10); } Quantity function_ieee754_single_decode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::decodeIeee754(args.at(0), 8, 23); } Quantity function_ieee754_single_encode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::encodeIeee754(args.at(0), 8, 23); } Quantity function_ieee754_double_decode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::decodeIeee754(args.at(0), 11, 52); } Quantity function_ieee754_double_encode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::encodeIeee754(args.at(0), 11, 52); } Quantity function_ieee754_quad_decode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::decodeIeee754(args.at(0), 15, 112); } Quantity function_ieee754_quad_encode(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(1); return DMath::encodeIeee754(args.at(0), 15, 112); } //add 20200604 yroot(x) Quantity function_yroot(Function *f, const Function::ArgumentList &args) { /* TODO : complex mode switch for this function */ ENSURE_ARGUMENT_COUNT(2); return DMath::raise(args.at(0), Quantity(1) / args.at(1)); } void FunctionRepo::createFunctions() { // Analysis. FUNCTION_INSERT(abs); FUNCTION_INSERT(absdev); FUNCTION_INSERT(average); FUNCTION_INSERT(bin); FUNCTION_INSERT(cbrt); FUNCTION_INSERT(ceil); FUNCTION_INSERT(dec); FUNCTION_INSERT(floor); FUNCTION_INSERT(frac); FUNCTION_INSERT(gamma); FUNCTION_INSERT(geomean); FUNCTION_INSERT(hex); FUNCTION_INSERT(int); FUNCTION_INSERT(lngamma); FUNCTION_INSERT(max); FUNCTION_INSERT(min); FUNCTION_INSERT(oct); FUNCTION_INSERT(product); FUNCTION_INSERT(round); FUNCTION_INSERT(sgn); FUNCTION_INSERT(sqrt); FUNCTION_INSERT(stddev); FUNCTION_INSERT(sum); FUNCTION_INSERT(trunc); FUNCTION_INSERT(variance); FUNCTION_INSERT(yroot); //add 20200604 yroot(x) // Complex. FUNCTION_INSERT(real); FUNCTION_INSERT(imag); FUNCTION_INSERT(conj); FUNCTION_INSERT(phase); FUNCTION_INSERT(polar); FUNCTION_INSERT(cart); // Discrete. FUNCTION_INSERT(gcd); FUNCTION_INSERT(ncr); FUNCTION_INSERT(npr); // Probability. FUNCTION_INSERT(binomcdf); FUNCTION_INSERT(binommean); FUNCTION_INSERT(binompmf); FUNCTION_INSERT(binomvar); FUNCTION_INSERT(erf); FUNCTION_INSERT(erfc); FUNCTION_INSERT(hypercdf); FUNCTION_INSERT(hypermean); FUNCTION_INSERT(hyperpmf); FUNCTION_INSERT(hypervar); FUNCTION_INSERT(median); FUNCTION_INSERT(poicdf); FUNCTION_INSERT(poimean); FUNCTION_INSERT(poipmf); FUNCTION_INSERT(poivar); // Trigonometry. FUNCTION_INSERT(arccos); FUNCTION_INSERT(arcosh); FUNCTION_INSERT(arsinh); FUNCTION_INSERT(artanh); FUNCTION_INSERT(arcsin); FUNCTION_INSERT(arctan); FUNCTION_INSERT(arctan2); FUNCTION_INSERT(arccot); FUNCTION_INSERT(cos); FUNCTION_INSERT(cosh); FUNCTION_INSERT(cot); FUNCTION_INSERT(csc); FUNCTION_INSERT(degrees); FUNCTION_INSERT(exp); FUNCTION_INSERT(gradians); FUNCTION_INSERT(lb); FUNCTION_INSERT(lg); FUNCTION_INSERT(ln); FUNCTION_INSERT(log); FUNCTION_INSERT(radians); FUNCTION_INSERT(sec); FUNCTION_INSERT(sin); FUNCTION_INSERT(sinh); FUNCTION_INSERT(tan); FUNCTION_INSERT(tanh); // Logic. FUNCTION_INSERT(mask); FUNCTION_INSERT(unmask); FUNCTION_INSERT(not); FUNCTION_INSERT( and); FUNCTION_INSERT( or); FUNCTION_INSERT(xor); FUNCTION_INSERT(shl); FUNCTION_INSERT(shr); FUNCTION_INSERT(idiv); FUNCTION_INSERT(mod); // IEEE-754. FUNCTION_INSERT(ieee754_decode); FUNCTION_INSERT(ieee754_encode); FUNCTION_INSERT(ieee754_half_decode); FUNCTION_INSERT(ieee754_half_encode); FUNCTION_INSERT(ieee754_single_decode); FUNCTION_INSERT(ieee754_single_encode); FUNCTION_INSERT(ieee754_double_decode); FUNCTION_INSERT(ieee754_double_encode); FUNCTION_INSERT(ieee754_quad_decode); FUNCTION_INSERT(ieee754_quad_encode); } FunctionRepo *FunctionRepo::instance() { if (!s_FunctionRepoInstance) { s_FunctionRepoInstance = new FunctionRepo; qAddPostRoutine(s_deleteFunctions); } return s_FunctionRepoInstance; } FunctionRepo::FunctionRepo() { createFunctions(); setNonTranslatableFunctionUsages(); retranslateText(); } void FunctionRepo::insert(Function *function) { if (!function) return; m_functions.insert(function->identifier().toUpper(), function); } Function *FunctionRepo::find(const QString &identifier) const { if (identifier.isNull()) return 0; return m_functions.value(identifier.toUpper(), 0); } QStringList FunctionRepo::getIdentifiers() const { QStringList result = m_functions.keys(); std::transform(result.begin(), result.end(), result.begin(), [](const QString & s) { return s.toLower(); }); return result; } void FunctionRepo::setNonTranslatableFunctionUsages() { FUNCTION_USAGE(abs, "x"); FUNCTION_USAGE(absdev, "x1; x2; ..."); FUNCTION_USAGE(arccos, "x"); FUNCTION_USAGE( and, "x1; x2; ..."); FUNCTION_USAGE(arcosh, "x"); FUNCTION_USAGE(arsinh, "x"); FUNCTION_USAGE(artanh, "x"); FUNCTION_USAGE(arcsin, "x"); FUNCTION_USAGE(arctan, "x"); FUNCTION_USAGE(arctan2, "x; y"); FUNCTION_USAGE(arccot, "x"); FUNCTION_USAGE(average, "x1; x2; ..."); FUNCTION_USAGE(bin, "n"); FUNCTION_USAGE(cart, "x"); FUNCTION_USAGE(cbrt, "x"); FUNCTION_USAGE(ceil, "x"); FUNCTION_USAGE(conj, "x"); FUNCTION_USAGE(cos, "x"); FUNCTION_USAGE(cosh, "x"); FUNCTION_USAGE(cot, "x"); FUNCTION_USAGE(csc, "x"); FUNCTION_USAGE(dec, "x"); FUNCTION_USAGE(degrees, "x"); FUNCTION_USAGE(erf, "x"); FUNCTION_USAGE(erfc, "x"); FUNCTION_USAGE(exp, "x"); FUNCTION_USAGE(floor, "x"); FUNCTION_USAGE(frac, "x"); FUNCTION_USAGE(gamma, "x"); FUNCTION_USAGE(gcd, "n1; n2; ..."); FUNCTION_USAGE(geomean, "x1; x2; ..."); FUNCTION_USAGE(gradians, "x"); FUNCTION_USAGE(hex, "n"); FUNCTION_USAGE(ieee754_half_decode, "x"); FUNCTION_USAGE(ieee754_half_encode, "x"); FUNCTION_USAGE(ieee754_single_decode, "x"); FUNCTION_USAGE(ieee754_single_encode, "x"); FUNCTION_USAGE(ieee754_double_decode, "x"); FUNCTION_USAGE(ieee754_double_encode, "x"); FUNCTION_USAGE(ieee754_quad_decode, "x"); FUNCTION_USAGE(ieee754_quad_encode, "x"); FUNCTION_USAGE(int, "x"); FUNCTION_USAGE(imag, "x"); FUNCTION_USAGE(lb, "x"); FUNCTION_USAGE(lg, "x"); FUNCTION_USAGE(ln, "x"); FUNCTION_USAGE(lngamma, "x"); FUNCTION_USAGE(max, "x1; x2; ..."); FUNCTION_USAGE(median, "x1; x2; ..."); FUNCTION_USAGE(min, "x1; x2; ..."); FUNCTION_USAGE(ncr, "x1; x2"); FUNCTION_USAGE(not, "n"); FUNCTION_USAGE(npr, "x1; x2"); FUNCTION_USAGE(oct, "n"); FUNCTION_USAGE( or, "x1; x2; ..."); FUNCTION_USAGE(polar, "x"); FUNCTION_USAGE(product, "x1; x2; ..."); FUNCTION_USAGE(phase, "x"); FUNCTION_USAGE(radians, "x"); FUNCTION_USAGE(real, "x"); FUNCTION_USAGE(sec, "x)"); FUNCTION_USAGE(sgn, "x"); FUNCTION_USAGE(sin, "x"); FUNCTION_USAGE(sinh, "x"); FUNCTION_USAGE(sqrt, "x"); FUNCTION_USAGE(stddev, "x1; x2; ..."); FUNCTION_USAGE(sum, "x1; x2; ..."); FUNCTION_USAGE(tan, "x"); FUNCTION_USAGE(tanh, "x"); FUNCTION_USAGE(trunc, "x"); FUNCTION_USAGE(variance, "x1; x2; ..."); FUNCTION_USAGE(xor, "x1; x2; ..."); } void FunctionRepo::setTranslatableFunctionUsages() { FUNCTION_USAGE_TR(binomcdf, /*tr*/("max; trials; probability")); FUNCTION_USAGE_TR(binommean, /*tr*/("trials; probability")); FUNCTION_USAGE_TR(binompmf, /*tr*/("hits; trials; probability")); FUNCTION_USAGE_TR(binomvar, /*tr*/("trials; probability")); FUNCTION_USAGE_TR(hypercdf, /*tr*/("max; total; hits; trials")); FUNCTION_USAGE_TR(hypermean, /*tr*/("total; hits; trials")); FUNCTION_USAGE_TR(hyperpmf, /*tr*/("count; total; hits; trials")); FUNCTION_USAGE_TR(hypervar, /*tr*/("total; hits; trials")); FUNCTION_USAGE_TR(idiv, /*tr*/("dividend; divisor")); FUNCTION_USAGE_TR(ieee754_decode, /*tr*/("x; exponent_bits; significand_bits [; exponent_bias]")); FUNCTION_USAGE_TR(ieee754_encode, /*tr*/("x; exponent_bits; significand_bits [; exponent_bias]")); FUNCTION_USAGE_TR(log, /*tr*/("base; x")); FUNCTION_USAGE_TR(mask, /*tr*/("n; bits")); FUNCTION_USAGE_TR(mod, /*tr*/("value; modulo")); FUNCTION_USAGE_TR(poicdf, /*tr*/("events; average_events")); FUNCTION_USAGE_TR(poimean, /*tr*/("average_events")); FUNCTION_USAGE_TR(poipmf, /*tr*/("events; average_events")); FUNCTION_USAGE_TR(poivar, /*tr*/("average_events")); FUNCTION_USAGE_TR(round, /*tr*/("x [; precision]")); FUNCTION_USAGE_TR(shl, /*tr*/("n; bits")); FUNCTION_USAGE_TR(shr, /*tr*/("n; bits")); FUNCTION_USAGE_TR(unmask, /*tr*/("n; bits")); FUNCTION_USAGE_TR(yroot, ("x; y"));//add 20200604 yroot(x) } void FunctionRepo::setFunctionNames() { FUNCTION_NAME(abs, /*tr*/("Absolute Value")); FUNCTION_NAME(absdev, /*tr*/("Absolute Deviation")); FUNCTION_NAME(arccos, /*tr*/("Arc Cosine")); FUNCTION_NAME( and, /*tr*/("Logical AND")); FUNCTION_NAME(arcosh, /*tr*/("Area Hyperbolic Cosine")); FUNCTION_NAME(arsinh, /*tr*/("Area Hyperbolic Sine")); FUNCTION_NAME(artanh, /*tr*/("Area Hyperbolic Tangent")); FUNCTION_NAME(arcsin, /*tr*/("Arc Sine")); FUNCTION_NAME(arctan, /*tr*/("Arc Tangent")); FUNCTION_NAME(arctan2, /*tr*/("Arc Tangent with two Arguments")); FUNCTION_NAME(arccot, /*tr*/("Arc Cotangent")); FUNCTION_NAME(average, /*tr*/("Average (Arithmetic Mean)")); FUNCTION_NAME(bin, /*tr*/("Convert to Binary Representation")); FUNCTION_NAME(binomcdf, /*tr*/("Binomial Cumulative Distribution Function")); FUNCTION_NAME(binommean, /*tr*/("Binomial Distribution Mean")); FUNCTION_NAME(binompmf, /*tr*/("Binomial Probability Mass Function")); FUNCTION_NAME(binomvar, /*tr*/("Binomial Distribution Variance")); FUNCTION_NAME(cart, /*tr*/("Convert to Cartesian Notation")); FUNCTION_NAME(cbrt, /*tr*/("Cube Root")); FUNCTION_NAME(ceil, /*tr*/("Ceiling")); FUNCTION_NAME(conj, /*tr*/("Complex Conjugate")); FUNCTION_NAME(cos, /*tr*/("Cosine")); FUNCTION_NAME(cosh, /*tr*/("Hyperbolic Cosine")); FUNCTION_NAME(cot, /*tr*/("Cotangent")); FUNCTION_NAME(csc, /*tr*/("Cosecant")); FUNCTION_NAME(dec, /*tr*/("Convert to Decimal Representation")); FUNCTION_NAME(degrees, /*tr*/("Degrees of Arc")); FUNCTION_NAME(erf, /*tr*/("Error Function")); FUNCTION_NAME(erfc, /*tr*/("Complementary Error Function")); FUNCTION_NAME(exp, /*tr*/("Exponential")); FUNCTION_NAME(floor, /*tr*/("Floor")); FUNCTION_NAME(frac, /*tr*/("Fractional Part")); FUNCTION_NAME(gamma, /*tr*/("Extension of Factorials [= (x-1)!]")); FUNCTION_NAME(gcd, /*tr*/("Greatest Common Divisor")); FUNCTION_NAME(geomean, /*tr*/("Geometric Mean")); FUNCTION_NAME(gradians, /*tr*/("Gradians of arc")); FUNCTION_NAME(hex, /*tr*/("Convert to Hexadecimal Representation")); FUNCTION_NAME(hypercdf, /*tr*/("Hypergeometric Cumulative Distribution Function")); FUNCTION_NAME(hypermean, /*tr*/("Hypergeometric Distribution Mean")); FUNCTION_NAME(hyperpmf, /*tr*/("Hypergeometric Probability Mass Function")); FUNCTION_NAME(hypervar, /*tr*/("Hypergeometric Distribution Variance")); FUNCTION_NAME(idiv, /*tr*/("Integer Quotient")); FUNCTION_NAME(int, /*tr*/("Integer Part")); FUNCTION_NAME(imag, /*tr*/("Imaginary Part")); FUNCTION_NAME(ieee754_decode, /*tr*/("Decode IEEE-754 Binary Value")); FUNCTION_NAME(ieee754_encode, /*tr*/("Encode IEEE-754 Binary Value")); FUNCTION_NAME(ieee754_half_decode, /*tr*/("Decode 16-bit Half-Precision Value")); FUNCTION_NAME(ieee754_half_encode, /*tr*/("Encode 16-bit Half-Precision Value")); FUNCTION_NAME(ieee754_single_decode, /*tr*/("Decode 32-bit Single-Precision Value")); FUNCTION_NAME(ieee754_single_encode, /*tr*/("Encode 32-bit Single-Precision Value")); FUNCTION_NAME(ieee754_double_decode, /*tr*/("Decode 64-bit Double-Precision Value")); FUNCTION_NAME(ieee754_double_encode, /*tr*/("Encode 64-bit Double-Precision Value")); FUNCTION_NAME(ieee754_quad_decode, /*tr*/("Decode 128-bit Quad-Precision Value")); FUNCTION_NAME(ieee754_quad_encode, /*tr*/("Encode 128-bit Quad-Precision Value")); FUNCTION_NAME(lb, /*tr*/("Binary Logarithm")); FUNCTION_NAME(lg, /*tr*/("Common Logarithm")); FUNCTION_NAME(ln, /*tr*/("Natural Logarithm")); FUNCTION_NAME(lngamma, "ln(abs(Gamma))"); FUNCTION_NAME(log, /*tr*/("Logarithm to Arbitrary Base")); FUNCTION_NAME(mask, /*tr*/("Mask to a bit size")); FUNCTION_NAME(max, /*tr*/("Maximum")); FUNCTION_NAME(median, /*tr*/("Median Value (50th Percentile)")); FUNCTION_NAME(min, /*tr*/("Minimum")); FUNCTION_NAME(mod, /*tr*/("Modulo")); FUNCTION_NAME(ncr, /*tr*/("Combination (Binomial Coefficient)")); FUNCTION_NAME(not, /*tr*/("Logical NOT")); FUNCTION_NAME(npr, /*tr*/("Permutation (Arrangement)")); FUNCTION_NAME(oct, /*tr*/("Convert to Octal Representation")); FUNCTION_NAME( or, /*tr*/("Logical OR")); FUNCTION_NAME(phase, /*tr*/("Phase of Complex Number")); FUNCTION_NAME(poicdf, /*tr*/("Poissonian Cumulative Distribution Function")); FUNCTION_NAME(poimean, /*tr*/("Poissonian Distribution Mean")); FUNCTION_NAME(poipmf, /*tr*/("Poissonian Probability Mass Function")); FUNCTION_NAME(poivar, /*tr*/("Poissonian Distribution Variance")); FUNCTION_NAME(polar, /*tr*/("Convert to Polar Notation")); FUNCTION_NAME(product, /*tr*/("Product")); FUNCTION_NAME(radians, /*tr*/("Radians")); FUNCTION_NAME(real, /*tr*/("Real Part")); FUNCTION_NAME(round, /*tr*/("Rounding")); FUNCTION_NAME(sec, /*tr*/("Secant")); FUNCTION_NAME(shl, /*tr*/("Arithmetic Shift Left")); FUNCTION_NAME(shr, /*tr*/("Arithmetic Shift Right")); FUNCTION_NAME(sgn, /*tr*/("Signum")); FUNCTION_NAME(sin, /*tr*/("Sine")); FUNCTION_NAME(sinh, /*tr*/("Hyperbolic Sine")); FUNCTION_NAME(sqrt, /*tr*/("Square Root")); FUNCTION_NAME(stddev, /*tr*/("Standard Deviation (Square Root of Variance)")); FUNCTION_NAME(sum, /*tr*/("Sum")); FUNCTION_NAME(tan, /*tr*/("Tangent")); FUNCTION_NAME(tanh, /*tr*/("Hyperbolic Tangent")); FUNCTION_NAME(trunc, /*tr*/("Truncation")); FUNCTION_NAME(unmask, /*tr*/("Sign-extend a value")); FUNCTION_NAME(variance, /*tr*/("Variance")); FUNCTION_NAME(xor, /*tr*/("Logical XOR")); FUNCTION_NAME(yroot, /*tr*/("Y Root")); } void FunctionRepo::retranslateText() { setFunctionNames(); setTranslatableFunctionUsages(); } deepin-calculator-5.7.21/3rdparty/core/functions.h000066400000000000000000000050521423020056600220620ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2008-2009, 2013 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_FUNCTION_H #define CORE_FUNCTION_H #include "errors.h" #include "../math/quantity.h" #include #include #include #include class Function; class Function : public QObject { Q_OBJECT public: typedef QVector ArgumentList; typedef Quantity(*FunctionImpl)(Function *, const ArgumentList &); Function(const QString &identifier, FunctionImpl ptr, QObject *parent = 0) : QObject(parent) , m_identifier(identifier) , m_ptr(ptr) { m_error = Success; } const QString &identifier() const { return m_identifier; } const QString &name() const { return m_name; } const QString &usage() const { return m_usage; } Error error() const { return m_error; } Quantity exec(const ArgumentList &); void setName(const QString &name) { m_name = name; } void setUsage(const QString &usage) { m_usage = usage; } void setError(Error error) { m_error = error; } private: Q_DISABLE_COPY(Function) Function(); QString m_identifier; QString m_name; QString m_usage; Error m_error; FunctionImpl m_ptr; }; class FunctionRepo : public QObject { Q_OBJECT public: static FunctionRepo *instance(); void insert(Function *); QStringList getIdentifiers() const; Function *find(const QString &identifier) const; public slots: void retranslateText(); private: Q_DISABLE_COPY(FunctionRepo) FunctionRepo(); void createFunctions(); void setFunctionNames(); void setNonTranslatableFunctionUsages(); void setTranslatableFunctionUsages(); QHash m_functions; }; #endif // CORE_FUNCTION_H deepin-calculator-5.7.21/3rdparty/core/manualserver.cpp000066400000000000000000000102071423020056600231070ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2016 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. //#include "manualserver.h" //#include "settings.h" //#include //#include //#include //#include //#include //#include //#include //#define FALLBACK_LANG "en_US" /* * #define COPY_OVERWRITE(source, dest) \ if (QFile::exists(dest)) \ QFile::remove(dest); \ QFile::copy(source, dest); */ //#define QHC_NAME(lang) ("manual-" + QString(lang) + ".qhc") //#define QCH_NAME(lang) ("manual-" + QString(lang) + ".qch") //#define QHC_RES_PATH(lang) (":/manual/" + QHC_NAME(lang)) //#define QCH_RES_PATH(lang) (":/manual/" + QCH_NAME(lang)) //ManualServer *ManualServer::s_instance = NULL; //QString ManualServer::deployDocs() //{ // QString dest = Settings::getCachePath() + "/manual/"; // QDir qdir; // qdir.mkpath(dest); // QString lang = Settings::instance()->language; // m_deployedLanguage = lang; // if (lang == "C") // lang = QLocale().name(); // if (!isSupportedLanguage(lang)) { // // Extract the language from the locale and try to find a generic translation for it // QStringList languages = QLocale((QLocale(lang).language())).uiLanguages(); // lang = FALLBACK_LANG; // for (int i = 0; i < languages.size(); ++i) { // QString extra_lang = languages[i].replace('-', '_'); // if (isSupportedLanguage(extra_lang)) { // lang = extra_lang; // break; // } // } // } // QFile::remove(dest + QHC_NAME(lang)); // QFile::remove(dest + QCH_NAME(lang)); // QFile::copy(QHC_RES_PATH(lang), dest + QHC_NAME(lang)); // QFile::copy(QCH_RES_PATH(lang), dest + QCH_NAME(lang)); // QFile qhc(dest + QHC_NAME(lang)); // qhc.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner); // QFile qch(dest + QCH_NAME(lang)); // qch.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner); // return dest + "manual-" + lang + ".qhc"; //} //bool ManualServer::isSupportedLanguage(const QString &lang) //{ // return (QFile(QHC_RES_PATH(lang)).exists() && QFile(QCH_RES_PATH(lang)).exists()); //} //void ManualServer::setupHelpEngine() //{ // QString collectionFile = deployDocs() ; // m_helpEngine = new QHelpEngineCore(collectionFile, this); // QStringList filters = m_helpEngine->customFilters(); // if (!filters.isEmpty()) // m_helpEngine->setCurrentFilter(filters.first()); //} //ManualServer *ManualServer::instance() //{ // if (!s_instance) // s_instance = new ManualServer(); // return s_instance; //} //bool ManualServer::URLforKeyword(const QString id, QUrl &result) //{ // ensureCorrectLanguage(); // result = ""; // if (!m_helpEngine) // return 0; // QMap l; // l = m_helpEngine->linksForIdentifier(id); // if (l.isEmpty()) // return 0; // result = l.first(); // return 1; //} //QByteArray ManualServer::fileData(const QUrl &url) //{ // ensureCorrectLanguage(); // return m_helpEngine->fileData(url); //} //void ManualServer::languageChanged() //{ // setupHelpEngine(); //} //void ManualServer::ensureCorrectLanguage() //{ // if (Settings::instance()->language != m_deployedLanguage) // languageChanged(); //} //ManualServer::ManualServer() //{ // m_helpEngine = NULL; //} deepin-calculator-5.7.21/3rdparty/core/manualserver.h000066400000000000000000000032211423020056600225520ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2016 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. //#ifndef CORE_MANUALSERVER_H //#define CORE_MANUALSERVER_H //#include //#include //class QHelpEngineCore; //class QCloseEvent; //class QUrl; //class QString; //class QByteArray; //class ManualServer : public QObject //{ // Q_OBJECT //private: // QString deployDocs(); // void setupHelpEngine(); //public: // static ManualServer *instance(); // bool URLforKeyword(const QString id, QUrl &result); // QByteArray fileData(const QUrl &url); // bool isSupportedLanguage(const QString &); //public slots: // void ensureCorrectLanguage(); //private: // ManualServer(); // Q_DISABLE_COPY(ManualServer) // void languageChanged(); // QHelpEngineCore *m_helpEngine; // static ManualServer *s_instance; // QString m_deployedLanguage; //}; //#endif // CORE_MANUALSERVER_H deepin-calculator-5.7.21/3rdparty/core/numberformatter.cpp000066400000000000000000000066671423020056600236360ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2013 @heldercorreia // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "numberformatter.h" #include "settings.h" #include "../math/quantity.h" QString NumberFormatter::format(Quantity q) { Settings *settings = Settings::instance(); Quantity::Format format = q.format(); if (format.base == Quantity::Format::Base::Null) { switch (settings->resultFormat) { case 'b': format.base = Quantity::Format::Base::Binary; break; case 'o': format.base = Quantity::Format::Base::Octal; break; case 'h': format.base = Quantity::Format::Base::Hexadecimal; break; case 'n': format.base = Quantity::Format::Base::Decimal; break; case 'f': format.base = Quantity::Format::Base::Decimal; break; case 'e': format.base = Quantity::Format::Base::Decimal; break; case 'g': default: format.base = Quantity::Format::Base::Decimal; break; } } if (format.mode == Quantity::Format::Mode::Null) { if (format.base == Quantity::Format::Base::Decimal) { switch (settings->resultFormat) { case 'n': format.mode = Quantity::Format::Mode::Engineering; break; case 'f': format.mode = Quantity::Format::Mode::Fixed; break; case 'e': format.mode = Quantity::Format::Mode::Scientific; break; case 'g': default: format.mode = Quantity::Format::Mode::General; break; } } else { format.mode = Quantity::Format::Mode::Fixed; } } if (format.precision == Quantity::Format::PrecisionNull) format.precision = settings->resultPrecision; if (format.notation == Quantity::Format::Notation::Null) { if (settings->resultFormatComplex == 'c') format.notation = Quantity::Format::Notation::Cartesian; else if (settings->resultFormatComplex == 'p') format.notation = Quantity::Format::Notation::Polar; } QString result = DMath::format(q, format); if (settings->radixCharacter() == ',') result.replace('.', ','); result.replace('-', QString::fromUtf8("−")); // Replace all spaces between units with dot operator. int emptySpaces = 0; for (auto &ch : result) { if (ch.isSpace()) { ++emptySpaces; if (emptySpaces > 1) ch = u'⋅'; } } return result; } deepin-calculator-5.7.21/3rdparty/core/numberformatter.h000066400000000000000000000023161423020056600232660ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2013 @heldercorreia // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_NUMBERFORMATTER_H #define CORE_NUMBERFORMATTER_H #include "../math/quantity.h" #include struct NumberFormatter { static QString format(HNumber &num) { return format(Quantity(num)); } static QString format(CNumber &num) { return format(Quantity(num)); } static QString format(Quantity); }; #endif deepin-calculator-5.7.21/3rdparty/core/opcode.cpp000066400000000000000000000000241423020056600216500ustar00rootroot00000000000000#include "opcode.h" deepin-calculator-5.7.21/3rdparty/core/opcode.h000066400000000000000000000032451423020056600213250ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2008, 2009, 2010, 2013 @heldercorreia // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_OPCODE_H #define CORE_OPCODE_H #include class Opcode { public: enum Type { Nop, Load, Ref, Function, Add, Sub, Neg, Mul, Div, Pow, Fact, Modulo, IntDiv, Sal, Sar, BAnd, BOr, Conv, Pct, Yroot, Log, BNand, BNor, BXor, Shl, Shr, Rol, Ror, Rcl, Rcr }; Type type; unsigned index; // TODO: this is only needed for Conv Op. Maybe refactor this to a smarter place? // TODO: only keep a pointer to the string QString text; Opcode() : type(Nop), index(0) {} Opcode(Type t) : type(t), index(0) {} Opcode(Type t, QString txt) : type(t), index(0), text(txt) {} Opcode(Type t, unsigned i): type(t), index(i) {} }; #endif // CORE_OPCODE_H deepin-calculator-5.7.21/3rdparty/core/pageserver.cpp000066400000000000000000000022541423020056600225510ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2014 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "pageserver.h" QString PageServer::getPageContent(const QString &id) { PageMaker maker = m_toc.value(id); if (!maker) return QString(); m_currentPageID = id; return maker(); } QString PageServer::getCurrentPageContent() { if (m_currentPageID.isNull()) return QString(); return getPageContent(m_currentPageID); } deepin-calculator-5.7.21/3rdparty/core/pageserver.h000066400000000000000000000026561423020056600222240ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2014-2016 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_PAGESERVER_H #define CORE_PAGESERVER_H #include #include #include class PageServer : public QObject { Q_OBJECT public: explicit PageServer(QObject* parent = 0) : QObject(parent) { } QString getPageContent(const QString& id); QString getCurrentPageContent(); protected: typedef QString (*PageMaker)(); void addPage(const QString& id, PageMaker maker) { m_toc[id] = maker; } virtual void createPages() = 0; private: Q_DISABLE_COPY(PageServer) QHash m_toc; QString m_currentPageID; }; #endif // CORE_PAGESERVER_H deepin-calculator-5.7.21/3rdparty/core/session.cpp000066400000000000000000000126161423020056600220740ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "session.h" #include "sessionhistory.h" #include "variable.h" #include "evaluator.h" #include "functions.h" #include #include Session::Session(QObject *p) : QObject (p) { } void Session::serialize(QJsonObject &json) const { json["version"] = QString("1.0"); // history QJsonArray hist_entries; for(int i=0; i i(m_variables); while(i.hasNext()) { i.next(); QJsonObject curr_entry_obj; //ignore builtin variables if(i.value().type()==Variable::BuiltIn && i.value().identifier()!="ans") continue; i.value().serialize(curr_entry_obj); var_entries.append(curr_entry_obj); } json["variables"] = var_entries; // functions QJsonArray func_entries; QHashIterator j(m_userFunctions); while(j.hasNext()) { j.next(); QJsonObject curr_entry_obj; j.value().serialize(curr_entry_obj); func_entries.append(curr_entry_obj); } json["functions"] = func_entries; } int Session::deSerialize(const QJsonObject &json, bool merge=false) { QString version = json["version"].toString(); if(!merge) { m_history.clear(); m_variables.clear(); } Evaluator::instance()->initializeBuiltInVariables(); if (json.contains("history")) { QJsonArray hist_obj = json["history"].toArray(); int n = hist_obj.size(); for(int i=0; i Session::variablesToList() const { return m_variables.values(); } bool Session::isBuiltInVariable(const QString & id) const { // Defining variables with the same name as existing functions is not supported for now. if(FunctionRepo::instance()->find(id)) return true; if(!m_variables.contains(id)) return false; return m_variables.value(id).type() == Variable::BuiltIn; } void Session::addHistoryEntry(const HistoryEntry &entry) { m_history.append(entry); } void Session::insertHistoryEntry(const int index, const HistoryEntry &entry) { m_history.insert(index, entry); } void Session::removeHistoryEntryAt(const int index) { m_history.removeAt(index); } HistoryEntry Session::historyEntryAt(const int index) const { return m_history.at(index); } void Session::clearHistory() { m_history.clear(); } void Session::addUserFunction(const UserFunction &func) { if(func.opcodes.isEmpty()) { // We need to compile the function, so pretend the user typed it. Evaluator::instance()->setExpression(func.name() + "(" + func.arguments().join(";") + ")=" + func.expression()); Evaluator::instance()->eval(); } else { QString name = func.name(); m_userFunctions[name] = func; } } void Session::removeUserFunction(const QString &str) { m_userFunctions.remove(str); } void Session::clearUserFunctions() { m_userFunctions.clear(); } bool Session::hasUserFunction(const QString &str) const { return m_userFunctions.contains(str); } QList Session::UserFunctionsToList() const { return m_userFunctions.values(); } const UserFunction * Session::getUserFunction(const QString &fname) const { return &*m_userFunctions.find(fname); } deepin-calculator-5.7.21/3rdparty/core/session.h000066400000000000000000000050251423020056600215350ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_SESSION_H #define CORE_SESSION_H #include "../math/hmath.h" #include "sessionhistory.h" #include "variable.h" #include "userfunction.h" #include #include #include #include #include class Session : public QObject { private: typedef QList History ; typedef QHash VariableContainer; typedef QHash FunctionContainer; History m_history; VariableContainer m_variables; FunctionContainer m_userFunctions; public: Session(QObject *p = nullptr); // Session(QJsonObject & json); void load(); void save(); void serialize(QJsonObject &json) const; int deSerialize(const QJsonObject &json, bool merge); void addVariable(const Variable &var); bool hasVariable(const QString &id) const; void removeVariable(const QString &id); void clearVariables(); Variable getVariable(const QString &id) const; QList variablesToList() const; bool isBuiltInVariable(const QString &id) const; void addHistoryEntry(const HistoryEntry &entry); void insertHistoryEntry(const int index, const HistoryEntry &entry); void removeHistoryEntryAt(const int index); HistoryEntry historyEntryAt(const int index) const; QList historyToList() const {return m_history;} void clearHistory(); void addUserFunction(const UserFunction &func); void removeUserFunction(const QString &str); void clearUserFunctions(); bool hasUserFunction(const QString &str) const; QList UserFunctionsToList() const; const UserFunction *getUserFunction(const QString &fname) const; }; #endif // CORE_SESSION_H deepin-calculator-5.7.21/3rdparty/core/sessionhistory.cpp000066400000000000000000000032331423020056600235110ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "sessionhistory.h" HistoryEntry::HistoryEntry(const QJsonObject & json) { deSerialize(json); } QString HistoryEntry::expr() const { return m_expr; } Quantity HistoryEntry::result() const { return m_result; } void HistoryEntry::setExpr(const QString & e) { m_expr = e; } void HistoryEntry::setResult(const Quantity & n) { m_result = n; } void HistoryEntry::serialize(QJsonObject & json) const { json["expression"] = m_expr; QJsonObject result; m_result.serialize(result); json["result"] = result; return; } void HistoryEntry::deSerialize(const QJsonObject & json) { *this = HistoryEntry(); if (json.contains("expression")) m_expr = json["expression"].toString(); if (json.contains("result")) m_result = Quantity(json["result"].toObject()); return; } deepin-calculator-5.7.21/3rdparty/core/sessionhistory.h000066400000000000000000000031321423020056600231540ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_SESSIONHISTORY_H #define CORE_SESSIONHISTORY_H #include #include #include #include "../math/quantity.h" class HistoryEntry { private: QString m_expr; Quantity m_result; public: HistoryEntry() : m_expr(""), m_result(0) {} HistoryEntry(const QJsonObject &json); HistoryEntry(const QString &expr, const Quantity &num) : m_expr(expr), m_result(num) {} HistoryEntry(const HistoryEntry &other) : m_expr(other.m_expr), m_result(other.m_result) {} void setExpr(const QString &e); void setResult(const Quantity &n); QString expr() const; Quantity result() const; void serialize(QJsonObject &json) const; void deSerialize(const QJsonObject &json); }; #endif // CORE_SESSIONHISTORY_H deepin-calculator-5.7.21/3rdparty/core/settings.cpp000066400000000000000000000366171423020056600222600ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2004, 2005, 2007, 2008 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2016 @heldercorreia // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "settings.h" #include "../math/floatconfig.h" #include #include #include #include #include #include #ifdef Q_OS_WIN # define WIN32_LEAN_AND_MEAN # ifndef NOMINMAX # define NOMINMAX # endif # include # include #endif // The current config revision. Based on the application version number // ('1200' corresponds to 0.12.0, '10300' would be 1.3.0 etc.). When making // a backwards-incompatible change to the config format, bump this number to // the next release (if not already happened), then update the migration code // in createQSettings. Don't bump the config version unnecessarily for // releases that don't contain incompatible changes. static const int ConfigVersion = 1200; static const char *DefaultColorScheme = "Terminal"; QString Settings::getConfigPath() { #ifdef SPEEDCRUNCH_PORTABLE return QApplication::applicationDirPath(); #elif defined(Q_OS_WIN) // On Windows, use AppData/Roaming/SpeedCrunch, the same path as getDataPath. return getDataPath(); #else // Everywhere else, use `QStandardPaths::ConfigLocation`/SpeedCrunch: // * OSX: ~/Library/Preferences/SpeedCrunch // * Linux: ~/.config/SpeedCrunch return QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), QCoreApplication::applicationName()); #endif } QString Settings::getDataPath() { #ifdef SPEEDCRUNCH_PORTABLE return QApplication::applicationDirPath(); #elif QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); #elif defined(Q_OS_WIN) // We can't use AppDataLocation, so we simply use the Win32 API to emulate it. WCHAR w32path[MAX_PATH]; HRESULT result = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, w32path); Q_ASSERT(SUCCEEDED(result)); QString path = QString::fromWCharArray(w32path); QString orgName = QCoreApplication::organizationName(); QString appName = QCoreApplication::applicationName(); if (!orgName.isEmpty()) { path.append('\\'); path.append(orgName); } if (!appName.isEmpty()) { path.append('\\'); path.append(appName); } return QDir::fromNativeSeparators(path); #else // Any non-Windows with Qt < 5.4. Since DataLocation and AppDataLocation are // equivalent outside of Windows, that should be fine. return QStandardPaths::writableLocation(QStandardPaths::DataLocation); #endif } QString Settings::getCachePath() { #ifdef SPEEDCRUNCH_PORTABLE return QApplication::applicationDirPath(); #else return QStandardPaths::writableLocation(QStandardPaths::CacheLocation); #endif } static Settings *s_settingsInstance = 0; static char s_radixCharacter = 0; static void s_deleteSettings() { delete s_settingsInstance; } static QSettings *createQSettings(const QString &key); Settings *Settings::instance() { if (!s_settingsInstance) { s_settingsInstance = new Settings; s_settingsInstance->load(); qAddPostRoutine(s_deleteSettings); } return s_settingsInstance; } Settings::Settings() { } void Settings::load() { const char *KEY = "SpeedCrunch"; QSettings *settings = createQSettings(KEY); if (!settings) return; QString key = QString::fromLatin1(KEY) + QLatin1String("/General/"); // Angle mode special case. QString angleUnitStr; angleUnitStr = settings->value(key + QLatin1String("AngleMode"), "r").toString(); if (angleUnitStr != QLatin1String("r") && angleUnitStr != QLatin1String("d") && angleUnitStr != QLatin1String("g")) angleUnit = 'r'; else angleUnit = angleUnitStr.at(0).toLatin1(); //进制转换 add jingzhou 20201104,默认进制是10进制 programmerBase = settings->value(key + QLatin1String("ProgrammerBase"), 0).toInt(); //改变数据类型 add jingzhou 20201119,默认为QWORD proBitLength = settings->value(key + QLatin1String("proBitLength"), 64).toInt(); //带进位循环移位标志位 add jingzhou 20201205,默认为0 proRotateCarry = settings->value(key + QLatin1String("proRotateCarry"), "00").toString(); // Radix character special case. QString radixCharStr; radixCharStr = settings->value(key + QLatin1String("RadixCharacter"), "*").toString(); setRadixCharacter(radixCharStr.at(0).toLatin1()); autoAns = settings->value(key + QLatin1String("AutoAns"), true).toBool(); autoCalc = settings->value(key + QLatin1String("AutoCalc"), true).toBool(); autoCompletion = settings->value(key + QLatin1String("AutoCompletion"), true).toBool(); sessionSave = settings->value(key + QLatin1String("SessionSave"), true).toBool(); leaveLastExpression = settings->value(key + QLatin1String("LeaveLastExpression"), false).toBool(); language = settings->value(key + QLatin1String("Language"), "C").toString(); syntaxHighlighting = settings->value(key + QLatin1String("SyntaxHighlighting"), true).toBool(); autoResultToClipboard = settings->value(key + QLatin1String("AutoResultToClipboard"), false).toBool(); windowPositionSave = settings->value(key + QLatin1String("WindowPositionSave"), true).toBool(); complexNumbers = settings->value(key + QLatin1String("ComplexNumbers"), false).toBool(); digitGrouping = settings->value(key + QLatin1String("DigitGrouping"), 0).toInt(); digitGrouping = std::min(3, std::max(0, digitGrouping)); key = KEY + QLatin1String("/Format/"); // Format special case. QString format; format = settings->value(key + QLatin1String("Type"), 'f').toString(); if (format != "g" && format != "f" && format != "e" && format != "n" && format != "h" && format != "o" && format != "b") resultFormat = 'f'; else resultFormat = format.at(0).toLatin1(); // Complex format special case. QString cmplxFormat; cmplxFormat = settings->value(key + QLatin1String("ComplexForm"), 'c').toString(); if (cmplxFormat != "c" && cmplxFormat != "p") resultFormatComplex = 'c'; else resultFormatComplex = cmplxFormat.at(0).toLatin1(); resultPrecision = settings->value(key + QLatin1String("Precision"), -1).toInt(); if (resultPrecision > DECPRECISION) resultPrecision = DECPRECISION; key = KEY + QLatin1String("/Layout/"); windowOnfullScreen = settings->value(key + QLatin1String("WindowOnFullScreen"), false).toBool(); historyDockVisible = settings->value(key + QLatin1String("HistoryDockVisible"), false).toBool(); keypadVisible = settings->value(key + QLatin1String("KeypadVisible"), false).toBool(); statusBarVisible = settings->value(key + QLatin1String("StatusBarVisible"), false).toBool(); functionsDockVisible = settings->value(key + QLatin1String("FunctionsDockVisible"), false).toBool(); variablesDockVisible = settings->value(key + QLatin1String("VariablesDockVisible"), false).toBool(); userFunctionsDockVisible = settings->value(key + QLatin1String("UserFunctionsDockVisible"), false).toBool(); formulaBookDockVisible = settings->value(key + QLatin1String("FormulaBookDockVisible"), false).toBool(); constantsDockVisible = settings->value(key + QLatin1String("ConstantsDockVisible"), false).toBool(); windowAlwaysOnTop = settings->value(key + QLatin1String("WindowAlwaysOnTop"), false).toBool(); bitfieldVisible = settings->value(key + QLatin1String("BitfieldVisible"), false).toBool(); windowState = settings->value(key + QLatin1String("State")).toByteArray(); windowGeometry = settings->value(key + QLatin1String("WindowGeometry")).toByteArray(); manualWindowGeometry = settings->value(key + QLatin1String("ManualWindowGeometry")).toByteArray(); key = KEY + QLatin1String("/Display/"); displayFont = settings->value(key + QLatin1String("DisplayFont"), QFont().toString()).toString(); colorScheme = settings->value(key + QLatin1String("ColorSchemeName"), DefaultColorScheme).toString(); delete settings; } void Settings::save() { const QString KEY = QString::fromLatin1("SpeedCrunch"); QSettings *settings = createQSettings(KEY); if (!settings) return; QString key = KEY + QLatin1String("/General/"); settings->setValue(key + QLatin1String("SessionSave"), sessionSave); settings->setValue(key + QLatin1String("LeaveLastExpression"), leaveLastExpression); settings->setValue(key + QLatin1String("AutoCompletion"), autoCompletion); settings->setValue(key + QLatin1String("AutoAns"), autoAns); settings->setValue(key + QLatin1String("AutoCalc"), autoCalc); settings->setValue(key + QLatin1String("SyntaxHighlighting"), syntaxHighlighting); settings->setValue(key + QLatin1String("DigitGrouping"), digitGrouping); settings->setValue(key + QLatin1String("AutoResultToClipboard"), autoResultToClipboard); settings->setValue(key + QLatin1String("Language"), language); settings->setValue(key + QLatin1String("WindowPositionSave"), windowPositionSave); settings->setValue(key + QLatin1String("ComplexNumbers"), complexNumbers); settings->setValue(key + QLatin1String("AngleMode"), QString(QChar(angleUnit))); settings->setValue(key + QLatin1String("ProgrammerBase"), programmerBase); settings->setValue(key + QLatin1String("proBitLength"), proBitLength); settings->setValue(key + QLatin1String("proRotateCarry"), proRotateCarry); char c = 'C'; if (s_radixCharacter != 0) c = s_radixCharacter; settings->setValue(key + QLatin1String("RadixCharacter"), QString(QChar(c))); key = KEY + QLatin1String("/Format/"); settings->setValue(key + QLatin1String("Type"), QString(QChar(resultFormat))); settings->setValue(key + QLatin1String("ComplexForm"), QString(QChar(resultFormatComplex))); settings->setValue(key + QLatin1String("Precision"), resultPrecision); key = KEY + QLatin1String("/Layout/"); settings->setValue(key + QLatin1String("FormulaBookDockVisible"), formulaBookDockVisible); settings->setValue(key + QLatin1String("ConstantsDockVisible"), constantsDockVisible); settings->setValue(key + QLatin1String("FunctionsDockVisible"), functionsDockVisible); settings->setValue(key + QLatin1String("HistoryDockVisible"), historyDockVisible); settings->setValue(key + QLatin1String("WindowOnFullScreen"), windowOnfullScreen); settings->setValue(key + QLatin1String("KeypadVisible"), keypadVisible); settings->setValue(key + QLatin1String("StatusBarVisible"), statusBarVisible); settings->setValue(key + QLatin1String("VariablesDockVisible"), variablesDockVisible); settings->setValue(key + QLatin1String("UserFunctionsDockVisible"), userFunctionsDockVisible); settings->setValue(key + QLatin1String("WindowAlwaysOnTop"), windowAlwaysOnTop); settings->setValue(key + QLatin1String("State"), windowState); settings->setValue(key + QLatin1String("WindowGeometry"), windowGeometry); settings->setValue(key + QLatin1String("ManualWindowGeometry"), manualWindowGeometry); settings->setValue(key + QLatin1String("BitfieldVisible"), bitfieldVisible); key = KEY + QLatin1String("/Display/"); settings->setValue(key + QLatin1String("DisplayFont"), displayFont); settings->setValue(key + QLatin1String("ColorSchemeName"), colorScheme); delete settings; } char Settings::radixCharacter() const { if (isRadixCharacterAuto() || isRadixCharacterBoth()) return QLocale().decimalPoint().toLatin1(); return s_radixCharacter; } bool Settings::isRadixCharacterAuto() const { return s_radixCharacter == 0; } bool Settings::isRadixCharacterBoth() const { return s_radixCharacter == '*'; } void Settings::setRadixCharacter(char c) { s_radixCharacter = (c != ',' && c != '.' && c != '*') ? 0 : c; } // Settings migration from legacy (0.11 and before) to 0.12 (ConfigVersion 1200). static void migrateSettings_legacyTo1200(QSettings *settings, const QString &KEY) { #ifdef SPEEDCRUNCH_PORTABLE // This is the same as the new path, but let's cut down QSettings *legacy = new QSettings(Settings::getConfigPath() + "/" + KEY + ".ini", QSettings::IniFormat); #else QSettings *legacy = new QSettings(QSettings::NativeFormat, QSettings::UserScope, KEY, KEY); #endif QString legacyFile = legacy->fileName(); if (legacyFile != settings->fileName()) { // If the file names are different, we assume the legacy settings were in a // different location (most were, but e.g. not on the portable version) so we // copy everything over, then delete the old settings. On Windows, the file // name may also be a registry path, but the same reasoning applies. for (auto &key : legacy->allKeys()) settings->setValue(key, legacy->value(key)); #ifdef Q_OS_WIN // On Windows, check if the legacy settings were in the registry; if so, just clear() // them. if (legacy->format() == QSettings::NativeFormat) { legacy->clear(); delete legacy; } else { delete legacy; QFile::remove(legacyFile); } #else // On other platforms, delete the legacy settings file. delete legacy; QFile::remove(legacyFile); #endif } else { // If both settings objects point to the same location, removing the old stuff // may well break the new settings. delete legacy; } // ColorScheme -> ColorSchemeName QString colorSchemeName; switch (settings->value("SpeedCrunch/Display/ColorScheme", -1).toInt()) { case 0: colorSchemeName = "Terminal"; break; case 1: colorSchemeName = "Standard"; break; case 2: colorSchemeName = "Sublime"; break; default: colorSchemeName = DefaultColorScheme; break; } settings->setValue("SpeedCrunch/Display/ColorSchemeName", colorSchemeName); settings->remove("SpeedCrunch/Display/ColorScheme"); // DigitGrouping (bool) -> DigitGrouping (int) bool groupDigits = settings->value("SpeedCrunch/General/DigitGrouping", false).toBool(); settings->setValue("SpeedCrunch/General/DigitGrouping", groupDigits ? 1 : 0); } QSettings *createQSettings(const QString &KEY) { QSettings *settings = new QSettings(Settings::getConfigPath() + "/" + KEY + ".ini", QSettings::IniFormat); int ver = settings->value("ConfigVersion", 0).toInt(); switch (ver) { case 0: migrateSettings_legacyTo1200(settings, KEY); break; } settings->setValue("ConfigVersion", ConfigVersion); return settings; } deepin-calculator-5.7.21/3rdparty/core/settings.h000066400000000000000000000053041423020056600217120ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2005-2006 Johan Thelin // Copyright (C) 2007-2016 @heldercorreia // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_SETTINGS_H #define CORE_SETTINGS_H #include #include #include #include class Settings { public: static Settings *instance(); static QString getConfigPath(); static QString getDataPath(); static QString getCachePath(); void load(); void save(); char radixCharacter() const; // 0 or '*': Automatic. void setRadixCharacter(char c = 0); bool isRadixCharacterAuto() const; bool isRadixCharacterBoth() const; bool complexNumbers; char angleUnit; // 'r': radian; 'd': degree; 'g': gradian. int programmerBase; //进制转换-2,8,10,16,非程序员计算器为0 int proBitLength; //数据的长度byte-8 word-16 Dword-32 Qword-64 QString proRotateCarry; //带进位循环移位标志位 char resultFormat; int resultPrecision; // See HMath documentation. char resultFormatComplex; // 'c' cartesian; 'p' polar. bool autoAns; bool autoCalc; bool autoCompletion; int digitGrouping; bool sessionSave; bool leaveLastExpression; bool syntaxHighlighting; bool windowAlwaysOnTop; bool autoResultToClipboard; bool windowPositionSave; bool constantsDockVisible; bool functionsDockVisible; bool historyDockVisible; bool keypadVisible; bool formulaBookDockVisible; bool statusBarVisible; bool variablesDockVisible; bool userFunctionsDockVisible; bool windowOnfullScreen; bool bitfieldVisible; QString colorScheme; QString displayFont; QString language; QByteArray windowState; QByteArray windowGeometry; QByteArray manualWindowGeometry; private: Q_DISABLE_COPY(Settings) Settings(); }; #endif deepin-calculator-5.7.21/3rdparty/core/userfunction.cpp000066400000000000000000000107211423020056600231300ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "userfunction.h" #include "evaluator.h" #include "opcode.h" #include //#define SAVE_COMPILED_FORM UserFunction::UserFunction(const QJsonObject &json) : UserFunction() { if (json.contains("name")) m_name = json["name"].toString(); if (json.contains("args")) { const QJsonArray args_json = json["args"].toArray(); int n = json["args"].toArray().size(); for (int i = 0; i < n; ++i) m_arguments.append(args_json.at(i).toString()); } if (json.contains("expression")) m_expression = json["expression"].toString(); if (json.contains("description")) m_description = json["description"].toString(); if (json.contains("opcodes")) { const QJsonArray &codes_json = json["opcodes"].toArray(); for (int i = 0; i < codes_json.size(); ++i) { Opcode opcode(static_cast(codes_json[i].toObject()["t"].toInt()), codes_json[i].toObject()["i"].toInt()); if (codes_json[i].toObject().contains("text")) opcode.text = codes_json[i].toObject()["text"].toString(); opcodes.append(opcode); } const QJsonArray &const_json = json["constants"].toArray(); for (int i = 0; i < const_json.size(); ++i) { CNumber hn(const_json[i].toObject()); constants.append(hn); } const QJsonArray &id_json = json["identifiers"].toArray(); for (int i = 0; i < id_json.size(); ++i) { identifiers.append(id_json[i].toString()); } } } QString UserFunction::name() const { return m_name; } QStringList UserFunction::arguments() const { return m_arguments; } QString UserFunction::expression() const { return m_expression; } QString UserFunction::description() const { return m_description; } void UserFunction::setName(const QString &str) { m_name = str; } void UserFunction::setArguments(const QStringList &args) { m_arguments = args; } void UserFunction::setExpression(const QString &expr) { m_expression = expr; } void UserFunction::setDescription(const QString &expr) { m_description = expr; } void UserFunction::serialize(QJsonObject &json) const { json["name"] = m_name; QJsonArray args; for (int i = 0; i < m_arguments.count(); ++i) args.append(m_arguments[i]); json["args"] = args; json["expression"] = m_expression; if (m_description != "") json["description"] = m_description; #ifdef SAVE_COMPILED_FORM // if compiled form is available, save it as well if (!opcodes.isEmpty()) { QJsonArray opcodes_json; for (int i = 0; i < opcodes.size(); ++i) { QJsonObject curr_code_json; const Opcode &curr_code = opcodes.at(i); curr_code_json["t"] = curr_code.type; curr_code_json["i"] = int(curr_code.index); if (curr_code.text != "") curr_code_json["text"] = curr_code.text; opcodes_json.append(curr_code_json); } json["opcodes"] = opcodes_json; QJsonArray constants_json; for (int i = 0; i < constants.size(); ++i) { QJsonObject curr_const_json; constants.at(i).serialize(curr_const_json); constants_json.append(curr_const_json); } json["constants"] = constants_json; QJsonArray identifiers_json; for (int i = 0; i < identifiers.size(); ++i) { identifiers_json.append(identifiers.at(i)); } json["identifiers"] = identifiers_json; } #endif } void UserFunction::deSerialize(const QJsonObject &json) { *this = UserFunction(json); } deepin-calculator-5.7.21/3rdparty/core/userfunction.h000066400000000000000000000035531423020056600226020ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_USERFUNCTION_H #define CORE_USERFUNCTION_H #include #include #include #include "opcode.h" #include "../math/quantity.h" class UserFunction { private: QString m_name; QStringList m_arguments; QString m_expression; QString m_description; public: QVector constants; QStringList identifiers; QVector opcodes; UserFunction(QString name, QStringList arguments, QString expression) : m_name(name), m_arguments(arguments), m_expression(expression) {} UserFunction() {} UserFunction(const QJsonObject &json); QString name() const; QStringList arguments() const; QString expression() const; QString description() const; void setName(const QString &str); void setArguments(const QStringList &args); void setExpression(const QString &expr); void setDescription(const QString &expr); void serialize(QJsonObject &json) const; void deSerialize(const QJsonObject &json); }; #endif // CORE_USERFUNCTION_H deepin-calculator-5.7.21/3rdparty/core/variable.cpp000066400000000000000000000032601423020056600221710ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2004, 2005, 2007 Ariya Hidayat // Copyright (C) 2007-2009, 2013, 2014 @heldercorreia // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "variable.h" Variable::Variable(const QJsonObject &json) { deSerialize(json); } void Variable::serialize(QJsonObject &json) const { json["identifier"] = m_identifier; QJsonObject value; m_value.serialize(value); json["value"] = value; json["type"] = (m_type==UserDefined) ? QStringLiteral("User") : QStringLiteral("BuiltIn"); } void Variable::deSerialize(const QJsonObject &json) { if (json.contains("identifier")) m_identifier = json["identifier"].toString(); if (json.contains("type")) { QString str = json["type"].toString(); m_type = (str=="User") ? UserDefined : BuiltIn; } if (json.contains("value")) m_value = Quantity(json["value"].toObject()); } deepin-calculator-5.7.21/3rdparty/core/variable.h000066400000000000000000000041201423020056600216320ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2004, 2005, 2007 Ariya Hidayat // Copyright (C) 2007-2009, 2013, 2014 @heldercorreia // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef CORE_VARIABLE_H #define CORE_VARIABLE_H #include #include #include #include "../math/quantity.h" class Variable { public: enum Type { BuiltIn, UserDefined }; private: QString m_identifier; Quantity m_value; Type m_type; public: Variable() : m_identifier(""), m_value(0), m_type(UserDefined) {} Variable(const QJsonObject &json); Variable(const QString &id, const Quantity &val, Type t = UserDefined) : m_identifier(id), m_value(val), m_type(t) {} Variable(const Variable &other) : m_identifier(other.m_identifier), m_value(other.m_value), m_type(other.m_type) {} Quantity value() const {return m_value;} QString identifier() const {return m_identifier;} Type type() const {return m_type;} void setValue(const Quantity &val) {m_value = val;} void set_identifier(const QString &str) {m_identifier = str;} void set_type(const Type t) {m_type = t;} void serialize(QJsonObject &json) const; void deSerialize(const QJsonObject &json); bool operator==(const Variable &other) const { return m_identifier == other.m_identifier; } }; #endif // CORE_VARIABLE_H deepin-calculator-5.7.21/3rdparty/math/000077500000000000000000000000001423020056600177005ustar00rootroot00000000000000deepin-calculator-5.7.21/3rdparty/math/cmath.cpp000066400000000000000000000543121423020056600215050ustar00rootroot00000000000000// cmath.cpp // Complex number support : type definition and function for complex numbers. // // This file is part of the SpeedCrunch project // Copyright (C) 2013, 2015-2016 Hadrien Theveneau . // Copyright (C) 2015-2016 Pol Welter. // Copyright (C) 2016 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "cmath.h" #include "cnumberparser.h" #include "floatconvert.h" #include "hmath.h" #include #include #include #include /** * Creates a new complex number. */ CNumber::CNumber() : real(0) , imag(0) {} /** * Creates a new complex number from one real number */ CNumber::CNumber(const HNumber &hn) : real(hn), imag(0) { } /** * Creates a new complex number from the real and imaginary parts */ CNumber::CNumber(const HNumber &x, const HNumber &y) : real(x) , imag(y) { } /** * Copies from another complex number. */ CNumber::CNumber(const CNumber &cn) : real(cn.real) , imag(cn.imag) { } /** * Creates a new number from an integer value. */ CNumber::CNumber(int i) : real(i) , imag(0) { } /** * Creates a new number from a string. */ CNumber::CNumber(const char *str) { CNumberParser parser(str); parser.parse(this); // FIXME: Exception management. } CNumber::CNumber(const QJsonObject &json) { *this = deSerialize(json); } /** * Returns true if this number is Not a Number (NaN). */ bool CNumber::isNan() const { return real.isNan() || imag.isNan(); } /** * Returns true if this number is zero. */ bool CNumber::isZero() const { return real.isZero() && imag.isZero(); } /** * Returns true if this number is a positive REAL */ bool CNumber::isPositive() const { return real.isPositive() && imag.isZero(); } /** * Returns true if this number is a negative REAL */ bool CNumber::isNegative() const { return real.isNegative() && imag.isZero(); } /** * Returns true if this number is integer and REAL */ bool CNumber::isInteger() const { return real.isInteger() && imag.isZero(); } /** * Returns true if this number is a Gaussian integer */ bool CNumber::isGaussian() const { return real.isInteger() && imag.isInteger(); } /** * Returns true if this number is a real number */ bool CNumber::isReal() const { return imag.isZero(); } /** * Returns true if this number is approximately a real number */ bool CNumber::isNearReal() const { return imag.isNearZero(); } void CNumber::serialize(QJsonObject &json) const { json["value"] = CMath::format(*this, CNumber::Format::Fixed() + CNumber::Format::Precision(DECPRECISION)); } CNumber CNumber::deSerialize(const QJsonObject &json) { CNumber result; if (json.contains("value")) { QString str = json["value"].toString(); str.replace(",", "."); result = CNumber(str.toLatin1().constData()); } return result; } /** * Returns a NaN (Not a Number) with error set to * passed parameter. */ CNumber CMath::nan(Error error) { // We must always ensure that both numbers have the same NaN error. CNumber result; result.real = HMath::nan(error); result.imag = HMath::nan(error); return result; } /** * Returns the error code kept with a NaN. */ Error CNumber::error() const { // real and imag have always the same NaN error. return real.error(); } /** * Assigns from another complex number. */ CNumber &CNumber::operator=(const CNumber &cn) { real = cn.real; imag = cn.imag; return *this; } /** * Adds another complex number. */ CNumber CNumber::operator+(const CNumber &num) const { CNumber result; result.real = real + num.real; result.imag = imag + num.imag; return result; } /** * Adds another complex number. */ CNumber &CNumber::operator+=(const CNumber &num) { return operator=(*this + num); } /** * Subtract from another complex number. */ CNumber operator-(const CNumber &n1, const CNumber &n2) { CNumber result; result.real = n1.real - n2.real; result.imag = n1.imag - n2.imag; return result; } /** * Subtract from another complex number. */ CNumber &CNumber::operator-=(const CNumber &num) { return operator=(*this - num); } /** * Multiplies with another complex number. */ CNumber CNumber::operator*(const CNumber &num) const { CNumber result; result.real = real * num.real - imag * num.imag; result.imag = imag * num.real + real * num.imag; return result; } /** * Multiplies with another REAL number. */ CNumber CNumber::operator*(const HNumber &num) const { CNumber result; result.real = real * num; result.imag = imag * num; return result; } /** * Multiplies with another number. */ CNumber &CNumber::operator*=(const CNumber &num) { return operator=(*this * num); } /** * Divides with another complex number. */ CNumber CNumber::operator/(const CNumber &num) const { if (num.isZero()) return CMath::nan(ZeroDivide); else { CNumber result; HNumber divider = num.real * num.real + num.imag * num.imag; result.real = (real * num.real + imag * num.imag) / divider; result.imag = (imag * num.real - real * num.imag) / divider; return result; } } /** * Divides with another REAL number. */ CNumber CNumber::operator/(const HNumber &num) const { if (num.isZero()) return CMath::nan(ZeroDivide); else return CNumber(real / num, imag / num) ; } /** * Divides with another number. */ CNumber &CNumber::operator/=(const CNumber &num) { return operator=(*this / num); } /** * Returns -1, 0, 1 if n1 is less than, equal to, or more than n2. * Only valid for real numbers, since complex ones are not an ordered field. */ int CNumber::compare(const CNumber &other) const { if (isReal() && other.isReal()) return real.compare(other.real); else return false; // FIXME: Return something better. } /** * Returns true if l is greater than r. */ bool operator>(const CNumber &l, const CNumber &r) { return l.compare(r) > 0; } /** * Returns true if l is less than r. */ bool operator<(const CNumber &l, const CNumber &r) { return l.compare(r) < 0; } /** * Returns true if l is greater than or equal to r. */ bool operator>=(const CNumber &l, const CNumber &r) { return l.compare(r) >= 0; } /** * Returns true if l is less than or equal to r. */ bool operator<=(const CNumber &l, const CNumber &r) { return l.compare(r) <= 0; } /** * Returns true if l is equal to r. */ bool operator==(const CNumber &l, const CNumber &r) { return l.compare(r) == 0; } /** * Returns true if l is not equal to r. */ bool operator!=(const CNumber &l, const CNumber &r) { return l.compare(r) != 0; } /** * Changes the sign. */ CNumber operator-(const CNumber &x) { return CNumber(-x.real, -x.imag); } CNumber::Format::Format() : HNumber::Format() , notation(Format::Notation::Null) { } CNumber::Format::Format(const Format &other) : HNumber::Format(static_cast(other)) , notation(other.notation) { } CNumber::Format::Format(const HNumber::Format &other) : HNumber::Format(other) , notation(Notation::Null) { } CNumber::Format CNumber::Format::operator+(const CNumber::Format &other) const { Format result(HNumber::Format::operator+(static_cast(other))); result.notation = (this->notation != Notation::Null) ? this->notation : other.notation; return result; } CNumber::Format CNumber::Format::Polar() { Format result; result.notation = Format::Notation::Polar; return result; } CNumber::Format CNumber::Format::Cartesian() { Format result; result.notation = Format::Notation::Cartesian; return result; } /** * Returns the constant e (Euler's number). */ CNumber CMath::e() { return CNumber(HMath::e()); } /** * Returns the constant pi. */ CNumber CMath::pi() { return CNumber(HMath::pi()); } /** * Returns the constant phi (golden number). */ CNumber CMath::phi() { return CNumber(HMath::phi()); } /** * Returns the constant i. */ CNumber CMath::i() { return CNumber(0, 1); } // TODO: Improve complex number formatting. /** * Formats the given number as string. */ QString CMath::format(const CNumber &cn, CNumber::Format format) { if (cn.isNan()) return "NaN"; else if (cn.imag.isNearZero()) // Number is real. return HMath::format(cn.real, format); if (format.notation == CNumber::Format::Notation::Polar) { QString strRadius = HMath::format(CMath::abs(cn).real, format); HNumber phase = CMath::phase(cn).real; if (phase.isZero()) return strRadius; QString strPhase = HMath::format(phase, format); return QString("%1 * exp(j*%2)").arg(strRadius, strPhase); } else { QString real_part = cn.real.isZero() ? "" : HMath::format(cn.real, format); QString imag_part = ""; QString separator = ""; QString prefix = ""; // TODO: Insert two modes, one for a+jb and one for a+bj. QString postfix = "j"; // TODO: Insert two modes, one for a+bi and one for a+bj. if (cn.imag.isPositive()) { separator = cn.real.isZero() ? "" : "+"; imag_part = HMath::format(cn.imag, format); } else { separator = "-"; imag_part = HMath::format(-cn.imag, format); } return real_part + separator + prefix + imag_part + postfix; } } /** * Returns the norm of n. */ CNumber CMath::abs(const CNumber &n) { return HMath::sqrt(n.real * n.real + n.imag * n.imag); } /* * Returns the complex conjugate of n */ CNumber CMath::conj(const CNumber &n) { return CNumber(n.real, -n.imag); } /** * Returns the square root of n. */ CNumber CMath::sqrt(const CNumber &n) { CNumber result; HNumber s = (n.imag.isPositive() || n.imag.isZero()) ? 1 : -1; // cf https://en.wikipedia.org/wiki/Square_root#Square_roots_of_negative_and_complex_numbers. result.real = HMath::sqrt((abs(n).real + n.real) / 2); result.imag = s * HMath::sqrt((abs(n).real - n.real) / 2); return result; } /** * Raises n1 to an integer n. */ CNumber CMath::raise(const CNumber &n1, int n) { return CMath::exp(CMath::ln(n1) * n); } /** * Raises n1 to n2. */ CNumber CMath::raise(const CNumber &n1, const CNumber &n2) { if (n1.isZero() && (n2.real > 0)) return CNumber(0); return CMath::exp(CMath::ln(n1) * n2); } /** * Returns e raised to x. */ CNumber CMath::exp(const CNumber &x) { HNumber abs = HMath::exp(x.real); return CNumber(abs * HMath::cos(x.imag), abs * HMath::sin(x.imag)); } /** * Returns the complex natural logarithm of x. */ CNumber CMath::ln(const CNumber &x) { CNumber result; // If real number if (x.imag.isZero()) { // If zero number, out of domain if (x.real.isZero()) return CMath::nan(OutOfDomain); // Here, non-zero number // Real part result.real = HMath::ln(HMath::abs(x.real)); // If NaN, ensures NaN and same error in both imag and real parts if (result.real.isNan()) { result.imag = result.real; return result; } // Imag part according to sign of real part result.imag = x.real.isPositive() ? 0 : HMath::pi(); } // Else, complex number else { HNumber abs = CMath::abs(x).real; result.real = HMath::ln(abs); // Principal Value logarithm // https://en.wikipedia.org/wiki/Complex_logarithm#Definition_of_principal_value auto imag = HMath::arccos(x.real / abs); result.imag = (x.imag.isPositive() || x.imag.isZero()) ? imag : -imag; } return result; } /** * Returns the common logarithm of x. */ CNumber CMath::lg(const CNumber &x) { return CMath::ln(x) / HMath::ln(10); } /** * Returns the binary logarithm of x. */ CNumber CMath::lb(const CNumber &x) { return CMath::ln(x) / HMath::ln(2); } /** * Returns the logarithm of x to base. * If x is non positive, returns NaN. */ CNumber CMath::log(const CNumber &base, const CNumber &x) { return CMath::ln(x) / CMath::ln(base); } /** * Returns the complex sine of x. Note that x must be in radians. */ CNumber CMath::sin(const CNumber &x) { // cf. https://en.wikipedia.org/wiki/Sine#Sine_with_a_complex_argument. return CNumber(HMath::sin(x.real) * HMath::cosh(x.imag), HMath::cos(x.real) * HMath::sinh(x.imag)); } /** * Returns the cosine of x. Note that x must be in radians. */ CNumber CMath::cos(const CNumber &x) { // Expanded using Wolfram Mathematica 9.0. return CNumber(HMath::cos(x.real) * HMath::cosh(x.imag), -HMath::sin(x.real) * HMath::sinh(x.imag)); } /** * Returns the tangent of x. Note that x must be in radians. */ CNumber CMath::tan(const CNumber &x) { return CMath::sin(x) / CMath::cos(x); } /** * Returns the hyperbolic sine of x. */ CNumber CMath::sinh(const CNumber &x) { return (exp(x) - exp(-x)) / HNumber(2); } /** * Returns the hyperbolic cosine of x. */ CNumber CMath::cosh(const CNumber &x) { return (exp(x) + exp(-x)) / HNumber(2); } /** * Returns the hyperbolic tangent of x. */ CNumber CMath::tanh(const CNumber &x) { return sinh(x) / cosh(x); } /** * Returns the cotangent of x. Note that x must be in radians. */ CNumber CMath::cot(const CNumber &x) { return cos(x) / sin(x); } /** * Returns the secant of x. Note that x must be in radians. */ CNumber CMath::sec(const CNumber &x) { return CNumber(1) / cos(x); } /** * Returns the cosecant of x. Note that x must be in radians. */ CNumber CMath::csc(const CNumber &x) { return CNumber(1) / sin(x); } /** * Returns the area hyperbolic sine of x. */ CNumber CMath::arsinh(const CNumber &x) { return CMath::ln(x + CMath::sqrt(x * x + CNumber(1))); } /** * Returns the area hyperbolic cosine of x. */ CNumber CMath::arcosh(const CNumber &x) { return CMath::ln(x + CMath::sqrt(x + CNumber(1)) * CMath::sqrt(x - CNumber(1))); } /** * Returns the area hyperbolic tangent of x. */ CNumber CMath::artanh(const CNumber &x) { return (CNumber("0.5") * CMath::ln(CNumber(1) + x)) - (CNumber("0.5") * CMath::ln(CNumber(1) - x)); } /** * Returns the phase of x. */ CNumber CMath::phase(const CNumber &x) { return HMath::arctan2(x.real, x.imag); } /** * Returns the arc tangent of x. */ CNumber CMath::arctan(const CNumber &x) { return CMath::i() * (CMath::ln(CNumber(1) - CMath::i() * x) - CMath::ln(CNumber(1) + CMath::i() * x)) / 2; } /** * Returns the arc sine of x. */ CNumber CMath::arcsin(const CNumber &x) { return -CMath::i() * CMath::ln(CMath::i() * x + sqrt(CNumber(1) - x * x)); } /** * Returns the arc cosine of x. */ CNumber CMath::arccos(const CNumber &x) { return -CMath::i() * CMath::ln(x + sqrt(x * x - CNumber(1))); } /** * Converts an angle from radians to degrees. * Also accepts complex arguments. */ CNumber CMath::rad2deg(const CNumber &x) { return CNumber(HMath::rad2deg(x.real), HMath::rad2deg(x.imag)); } /** * Converts an angle from degrees to radians. * Also accepts complex arguments. */ CNumber CMath::deg2rad(const CNumber &x) { return CNumber(HMath::deg2rad(x.real), HMath::deg2rad(x.imag)); } /** * Converts an angle from radians to gons. * Also accepts complex arguments. */ CNumber CMath::rad2gon(const CNumber &x) { return CNumber(HMath::rad2gon(x.real), HMath::rad2gon(x.imag)); } /** * Converts an angle from gons to radians. * Also accepts complex arguments. */ CNumber CMath::gon2rad(const CNumber &x) { return CNumber(HMath::gon2rad(x.real), HMath::gon2rad(x.imag)); } // Wrappers towards functions defined only on real numbers // ======================================================= // NaN is treated like real numbers for the purposes of wrappers. #define ENSURE_REAL(number, error) \ if((number).isNan() || !(number).isNearReal()) \ return CMath::nan(error); #define REAL_WRAPPER_CNUMBER_1(fct, error) \ CNumber CNumber::fct() const \ { \ ENSURE_REAL(*this, error); \ return CNumber(this->real.fct()); \ } #define REAL_WRAPPER_CNUMBER_2(fct, error) \ CNumber CNumber::fct(const CNumber& x) const \ { \ ENSURE_REAL(*this, error); \ ENSURE_REAL(x, error); \ return CNumber(this->real.fct(x.real)); \ } #define REAL_WRAPPER_CNUMBER_3(fct, error) \ CNumber& CNumber::fct(const CNumber& x) \ { \ if(!this->isReal()) { \ *this = CMath::nan(error); \ return *this; \ } \ if (!x.isReal()) { \ *this = CMath::nan(error); \ return *this; \ } \ this->real.fct(x.real); \ return *this; \ } #define REAL_WRAPPER_CNUMBER_4(fct, error) \ int CNumber::fct() const \ { \ if (!this->isNearReal()) \ return 0; /* FIXME: Better fail value. */ \ return this->real.fct(); \ } #define REAL_WRAPPER_CMATH_NUM(fct, error) \ CNumber CMath::fct(const CNumber& x) \ { \ ENSURE_REAL(x, error); \ return CNumber(HMath::fct(x.real)); \ } #define REAL_WRAPPER_CMATH_NUM_NUM(fct, error) \ CNumber CMath::fct(const CNumber& x1, const CNumber& x2) \ { \ ENSURE_REAL(x1, error); \ ENSURE_REAL(x2, error); \ return CNumber(HMath::fct(x1.real, x2.real)); \ } #define REAL_WRAPPER_CMATH_NUM_INT(fct, error) \ CNumber CMath::fct(const CNumber& x1, int n) \ { \ ENSURE_REAL(x1, error); \ return CNumber(HMath::fct(x1.real, n)); \ } #define REAL_WRAPPER_CMATH_NUM_NUM_NUM(fct, error) \ CNumber CMath::fct(const CNumber& x1, const CNumber& x2, const CNumber& x3) \ { \ ENSURE_REAL(x1, error); \ ENSURE_REAL(x2, error); \ ENSURE_REAL(x3, error); \ return CNumber(HMath::fct(x1.real, x2.real, x3.real)); \ } #define REAL_WRAPPER_CMATH_NUM_NUM_NUM_NUM(fct, error) \ CNumber CMath::fct(const CNumber& x1, const CNumber& x2, const CNumber& x3, const CNumber& x4) \ { \ ENSURE_REAL(x1, error); \ ENSURE_REAL(x2, error); \ ENSURE_REAL(x3, error); \ ENSURE_REAL(x4, error); \ return CNumber(HMath::fct(x1.real, x2.real, x3.real, x4.real)); \ } // CNumber REAL_WRAPPER_CNUMBER_4(toInt, OutOfDomain) REAL_WRAPPER_CNUMBER_2(operator%, OutOfDomain) REAL_WRAPPER_CNUMBER_2(operator&, OutOfLogicRange) REAL_WRAPPER_CNUMBER_3(operator&=, OutOfLogicRange) REAL_WRAPPER_CNUMBER_2(operator|, OutOfLogicRange) REAL_WRAPPER_CNUMBER_3(operator|=, OutOfLogicRange) REAL_WRAPPER_CNUMBER_2(operator^, OutOfLogicRange) REAL_WRAPPER_CNUMBER_3(operator^=, OutOfLogicRange) REAL_WRAPPER_CNUMBER_1(operator~, OutOfLogicRange) REAL_WRAPPER_CNUMBER_2(operator>>, OutOfLogicRange) REAL_WRAPPER_CNUMBER_2(operator<<, OutOfLogicRange) // CMath GENERAL MATH REAL_WRAPPER_CMATH_NUM(integer, OutOfDomain) REAL_WRAPPER_CMATH_NUM(frac, OutOfDomain) REAL_WRAPPER_CMATH_NUM(floor, OutOfDomain) REAL_WRAPPER_CMATH_NUM(ceil, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(gcd, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(idiv, OutOfDomain) REAL_WRAPPER_CMATH_NUM_INT(round, OutOfDomain) REAL_WRAPPER_CMATH_NUM_INT(trunc, OutOfDomain) REAL_WRAPPER_CMATH_NUM(cbrt, OutOfDomain) REAL_WRAPPER_CMATH_NUM(sgn, OutOfDomain) // CMath EXPONENTIAL FUNCTION AND RELATED REAL_WRAPPER_CMATH_NUM_NUM(arctan2, OutOfDomain) // CMath TRIGONOMETRY /* All trigonometry functions accept complex numbers */ // CMath HIGHER MATH FUNCTIONS REAL_WRAPPER_CMATH_NUM_NUM(factorial, NotImplemented) REAL_WRAPPER_CMATH_NUM(erf, OutOfDomain) REAL_WRAPPER_CMATH_NUM(erfc, OutOfDomain) REAL_WRAPPER_CMATH_NUM(gamma, NotImplemented) REAL_WRAPPER_CMATH_NUM(lnGamma, NotImplemented) // CMath PROBABILITY REAL_WRAPPER_CMATH_NUM_NUM(nCr, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(nPr, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM(binomialPmf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM(binomialCdf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(binomialMean, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(binomialVariance, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM_NUM(hypergeometricPmf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM_NUM(hypergeometricCdf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM(hypergeometricMean, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM(hypergeometricVariance, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(poissonPmf, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM(poissonCdf, OutOfDomain) REAL_WRAPPER_CMATH_NUM(poissonMean, OutOfDomain) REAL_WRAPPER_CMATH_NUM(poissonVariance, OutOfDomain) // CMath LOGIC REAL_WRAPPER_CMATH_NUM_NUM(mask, OutOfLogicRange) REAL_WRAPPER_CMATH_NUM_NUM(sgnext, OutOfLogicRange) REAL_WRAPPER_CMATH_NUM_NUM(ashr, OutOfLogicRange) REAL_WRAPPER_CMATH_NUM_NUM(lshr, OutOfLogicRange) REAL_WRAPPER_CMATH_NUM_NUM(rosh, OutOfLogicRange) REAL_WRAPPER_CMATH_NUM_NUM(rcsh, OutOfLogicRange) // CMath IEEE-754 CONVERSION REAL_WRAPPER_CMATH_NUM_NUM_NUM(decodeIeee754, OutOfDomain) REAL_WRAPPER_CMATH_NUM_NUM_NUM_NUM(decodeIeee754, OutOfDomain) CNumber CMath::encodeIeee754(const CNumber &val, const CNumber &exp_bits, const CNumber &significand_bits, const CNumber &exp_bias) { ENSURE_REAL(exp_bits, OutOfDomain); ENSURE_REAL(significand_bits, OutOfDomain); ENSURE_REAL(exp_bias, OutOfDomain); if (!val.isNan() && !val.isNearReal()) return CMath::nan(OutOfDomain); return CNumber(HMath::encodeIeee754(val.real, exp_bits.real, significand_bits.real, exp_bias.real)); } CNumber CMath::encodeIeee754(const CNumber &val, const CNumber &exp_bits, const CNumber &significand_bits) { ENSURE_REAL(exp_bits, OutOfDomain); ENSURE_REAL(significand_bits, OutOfDomain); if (!val.isNan() && !val.isNearReal()) return CMath::nan(OutOfDomain); return CNumber(HMath::encodeIeee754(val.real, exp_bits.real, significand_bits.real)); } deepin-calculator-5.7.21/3rdparty/math/cmath.h000066400000000000000000000211711423020056600211470ustar00rootroot00000000000000// cmath.h // Complex number support : type definition and function for complex numbers. // // This file is part of the SpeedCrunch project // Copyright (C) 2013, 2015-2016 Hadrien Theveneau . // Copyright (C) 2015-2016 Pol Welter. // Copyright (C) 2016 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef MATH_CMATH_H #define MATH_CMATH_H #include "hmath.h" #include "rational.h" #include #include class CMath; class CNumber { friend class CMath; friend CNumber operator-(const CNumber &); friend CNumber operator-(const CNumber &, const CNumber &); friend bool operator>(const CNumber &, const CNumber &); friend bool operator<(const CNumber &, const CNumber &); friend bool operator>=(const CNumber &, const CNumber &); friend bool operator<=(const CNumber &, const CNumber &); friend bool operator==(const CNumber &, const CNumber &); friend bool operator!=(const CNumber &, const CNumber &); public: CNumber(); CNumber(const HNumber &); CNumber(const HNumber &, const HNumber &); CNumber(const CNumber &); CNumber(int); CNumber(const char *); CNumber(const QJsonObject &); ~CNumber() { } bool isNan() const; bool isZero() const; bool isPositive() const; bool isNegative() const; bool isInteger() const; bool isGaussian() const; bool isReal() const; bool isNearReal() const; void serialize(QJsonObject &) const; static CNumber deSerialize(const QJsonObject &); int toInt() const; // Removed, too problematic for complex numbers. Error error() const; CNumber &operator=(const CNumber &); CNumber operator+(const CNumber &) const; CNumber &operator+=(const CNumber &); CNumber &operator-=(const CNumber &); CNumber operator*(const CNumber &) const; CNumber operator*(const HNumber &) const; CNumber operator*(int x) { return operator * (HNumber(x)); } // Overload ambiguity resolution. CNumber &operator*=(const CNumber &); CNumber operator/(const CNumber &) const; CNumber operator/(const HNumber &) const; CNumber operator/(int x) { return operator / (HNumber(x)); } // Overload ambiguity resolution. CNumber &operator/=(const CNumber &); CNumber operator%(const CNumber &) const; CNumber operator&(const CNumber &) const; CNumber &operator&=(const CNumber &); CNumber operator|(const CNumber &) const; CNumber &operator|=(const CNumber &); CNumber operator^(const CNumber &) const; CNumber &operator^=(const CNumber &); CNumber operator~() const; CNumber operator>>(const CNumber &) const; CNumber operator<<(const CNumber &) const; private: int compare(const CNumber &) const; public: HNumber real; HNumber imag; // FIXME: Better access control to real and imag. // Invariants: // - real and imag are neither or both NaN. // - real and imag have the same NaN error. struct Format : public HNumber::Format { enum class Notation {Null, Cartesian, Polar}; Notation notation; Format(); Format(const Format &); Format(const HNumber::Format &); Format operator+(const Format &) const; static Format Polar(); static Format Cartesian(); }; }; class CMath { public: // FORMAT static QString format(const CNumber &, CNumber::Format = CNumber::Format()); // CONSTANTS static CNumber e(); static CNumber phi(); static CNumber pi(); static CNumber nan(Error error = Success); static CNumber i(); // GENERAL MATH static CNumber rad2deg(const CNumber &); static CNumber deg2rad(const CNumber &); static CNumber rad2gon(const CNumber &); static CNumber gon2rad(const CNumber &); static CNumber abs(const CNumber &); static CNumber integer(const CNumber &); static CNumber frac(const CNumber &); static CNumber floor(const CNumber &); static CNumber ceil(const CNumber &); static CNumber gcd(const CNumber &, const CNumber &); static CNumber idiv(const CNumber &, const CNumber &); static CNumber round(const CNumber &, int prec = 0); static CNumber trunc(const CNumber &, int prec = 0); static CNumber sqrt(const CNumber &); static CNumber cbrt(const CNumber &); static CNumber raise(const CNumber &, int); static CNumber raise(const CNumber &, const CNumber &); static CNumber sgn(const CNumber &); // EXPONENTIAL FUNCTION AND RELATED static CNumber exp(const CNumber &); static CNumber ln(const CNumber &); static CNumber lg(const CNumber &); static CNumber lb(const CNumber &); static CNumber log(const CNumber &base, const CNumber &x); static CNumber sinh(const CNumber &); static CNumber cosh(const CNumber &); static CNumber tanh(const CNumber &); static CNumber arsinh(const CNumber &); static CNumber arcosh(const CNumber &); static CNumber artanh(const CNumber &); // COMPLEX SPECIFIC static CNumber real(const CNumber &x) {return x.real;} static CNumber imag(const CNumber &x) {return x.imag;} static CNumber conj(const CNumber &x); static CNumber phase(const CNumber &); // TRIGONOMETRY static CNumber sin(const CNumber &); static CNumber cos(const CNumber &); static CNumber tan(const CNumber &); static CNumber cot(const CNumber &); static CNumber sec(const CNumber &); static CNumber csc(const CNumber &); static CNumber arcsin(const CNumber &); static CNumber arccos(const CNumber &); static CNumber arctan(const CNumber &); static CNumber arctan2(const CNumber &, const CNumber &); // HIGHER MATH FUNCTIONS static CNumber factorial(const CNumber &, const CNumber &base = CNumber(1)); static CNumber gamma(const CNumber &); static CNumber lnGamma(const CNumber &); static CNumber erf(const CNumber &); static CNumber erfc(const CNumber &); // PROBABILITY static CNumber nCr(const CNumber &, const CNumber &); static CNumber nPr(const CNumber &, const CNumber &); static CNumber binomialPmf(const CNumber &k, const CNumber &n, const CNumber &p); static CNumber binomialCdf(const CNumber &k, const CNumber &n, const CNumber &p); static CNumber binomialMean(const CNumber &n, const CNumber &p); static CNumber binomialVariance(const CNumber &n, const CNumber &p); static CNumber hypergeometricPmf(const CNumber &k, const CNumber &N, const CNumber &M, const CNumber &n); static CNumber hypergeometricCdf(const CNumber &k, const CNumber &N, const CNumber &M, const CNumber &n); static CNumber hypergeometricMean(const CNumber &N, const CNumber &M, const CNumber &n); static CNumber hypergeometricVariance(const CNumber &N, const CNumber &M, const CNumber &n); static CNumber poissonPmf(const CNumber &k, const CNumber &l); static CNumber poissonCdf(const CNumber &k, const CNumber &l); static CNumber poissonMean(const CNumber &l); static CNumber poissonVariance(const CNumber &l); // LOGIC static CNumber mask(const CNumber &, const CNumber &bits); static CNumber sgnext(const CNumber &, const CNumber &bits); static CNumber ashr(const CNumber &, const CNumber &bits); static CNumber lshr(const CNumber &, const CNumber &bits); static CNumber rosh(const CNumber &, const CNumber &bits); static CNumber rcsh(const CNumber &, const CNumber &bits); // IEEE-754 CONVERSION static CNumber decodeIeee754(const CNumber &, const CNumber &exp_bits, const CNumber &significand_bits); static CNumber decodeIeee754(const CNumber &, const CNumber &exp_bits, const CNumber &significand_bits, const CNumber &exp_bias); static CNumber encodeIeee754(const CNumber &, const CNumber &exp_bits, const CNumber &significand_bits); static CNumber encodeIeee754(const CNumber &, const CNumber &exp_bits, const CNumber &significand_bits, const CNumber &exp_bias); }; std::ostream &operator<<(std::ostream &, const CNumber &); #endif // CMATH_CMATH_H deepin-calculator-5.7.21/3rdparty/math/cnumberparser.cpp000066400000000000000000000077051423020056600232650ustar00rootroot00000000000000// cnumberparser.cpp // Complex number support : complex number parser using a recursive // descent approach. // // This file is part of the SpeedCrunch project // Copyright (C) 2013, 2015-2016 Hadrien Theveneau . // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. // This complex number parser currently recognizes the following forms : // // a // a+ib // a+jb // a+bi // a+bj // ib // jb // bi // bj // // The grammar describing one complex number is: // // complex_number -> part suite // suite -> [] // suite -> + part suite // // part -> prefixed_part // part -> postfixed_part // // part_prefixed -> i base_number // part_prefixed -> j base_number // // part_postfixed -> base_number postfix // // postfix -> i // postfix -> j // postfix -> [] #include "cnumberparser.h" using namespace CNumberParserExceptions; CNumberParser::CNumberParser(const char * _str) : str(_str) { } /* Parses a complex number using a recursive-desent approach. * * If successfull, stores the result into *Number. * * See header file for details. */ void CNumberParser::parse (CNumber * Number) { /* Parsing */ CNumber a = part(); CNumber b = suite(); /* Processing */ *Number = a + b; } /* Null string or empty string. strlen(NULL) is undefined. */ static char _isempty(const char* p){ return p == NULL || *p == '\0'; } /* Parsing functions. * * Each of the following function parses one producion of the grammar */ CNumber CNumberParser::part () { if (_isempty(str)) { return CMath::nan(); } else if (strncmp(str, "NaN", 3) == 0) { return CMath::nan(); } else if (*str == 'i' || *str == 'j') { return part_prefixed(); } else if (isdigit (*str) || *str == '-' || *str == '+' || *str == '.') { /* Example cases : 1.0 -1.0 +1.0 .5 */ return part_postfixed(); } else { return CMath::nan(); } } CNumber CNumberParser::suite () { if (_isempty(str)) { return CNumber(0); } else if (*str == '+') { accept(); CNumber a = part(); CNumber b = suite(); return a + b; } else if (*str == '-') { accept(); CNumber a = part(); CNumber b = suite(); return (-a) + b; } else { return CNumber(0); } } CNumber CNumberParser::part_prefixed () { if (*str == 'i' || *str == 'j') { /* Parsing */ accept(); HNumber y = base_number(); /* Processing */ HNumber x = HNumber(0); CNumber res = CNumber(x, y); return res; } else { throw UnexpectedSymbol(*str); } } HNumber CNumberParser::base_number () { /* FIXME ! Error checking ! */ HNumber x = HMath::parse_str(str, &str); return x; } CNumber CNumberParser::part_postfixed () { /* Parsing */ HNumber x = base_number(); postfix_t p = postfix(); /* Processing */ if (p == REAL) /* If real part of a complex number */ return CNumber(x, 0); else if (p == IMAG) /* If imaginary part */ return CNumber(0, x); else { /* Should never happen */ throw LogicError(); } } CNumberParser::postfix_t CNumberParser::postfix () { if (*str == 'i' || *str == 'j') { accept(); return IMAG; } else { return REAL; } } deepin-calculator-5.7.21/3rdparty/math/cnumberparser.h000066400000000000000000000050711423020056600227240ustar00rootroot00000000000000// cnumberparser.h // Complex number support : complex number parser using a recursive // descent approach. // // This file is part of the SpeedCrunch project // Copyright (C) 2013, 2015-2016 Hadrien Theveneau . // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. // This complex number parser currently recognizes the following forms : // // a // a+ib // a+jb // a+bi // a+bj // ib // jb // bi // bj // // The grammar describing one complex number is: // // complex_number -> part suite // suite -> [] // suite -> + part suite // // part -> prefixed_part // part -> postfixed_part // // part_prefixed -> i base_number // part_prefixed -> j base_number // // part_postfixed -> base_number postfix // // postfix -> i // postfix -> j // postfix -> [] #ifndef CNUMBER_PARSER_HXX #define CNUMBER_PARSER_HXX #include #include #include "hmath.h" #include "cmath.h" class CNumberParser { private: const char * str; /* Remaining of the string to parse */ /* Parsing functions. */ void accept () {str++;} /* Each of the following function parses one producion of the grammar. */ CNumber part (); CNumber suite (); CNumber part_prefixed (); HNumber base_number (); CNumber part_postfixed (); typedef enum {IMAG, REAL} postfix_t; postfix_t postfix (); public: CNumberParser (const char * _str); void parse (CNumber * number); }; namespace CNumberParserExceptions { class Exception : public std::exception {}; class UnexpectedSymbol : public Exception { private: char symbol; public: char get_symbol () {return symbol;} UnexpectedSymbol (char _symbol) : symbol(_symbol) {} /* FIXME ! Error message ! */ }; class LogicError : Exception {}; class UnexpectedEnd : public Exception {}; } #endif // CNUMBER_PARSER_HXX deepin-calculator-5.7.21/3rdparty/math/floatcommon.c000066400000000000000000000233241423020056600223660ustar00rootroot00000000000000/* floatcommon.c: convenience functions, based on floatnum. */ /* Copyright (C) 2007 - 2009 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatcommon.h" #include "floatconst.h" #include "floatlong.h" #include #include #define MSB (1 << (sizeof(unsigned)*8 - 1)) #define LOGMSB ((301*(sizeof(unsigned)*8-1))/1000) static char _chckparam1( cfloatnum x, int digits, int limit, int specialval) { if (float_isnan(x)) { float_seterror(NoOperand); return 0; } if ((digits <= 0 || digits > limit) && digits != specialval) { float_seterror(InvalidPrecision); return 0; } return 1; } static char _chckparam( floatnum x, int digits, int limit, int specialval) { if (!_chckparam1(x, digits, limit, specialval)) return _setnan(x); return 1; } char chckmathparam( floatnum x, int digits) { return _chckparam(x, digits, MATHPRECISION, 1); } int logexp( cfloatnum x) { int expx, result; expx = float_getexponent(x); if (expx < 0) expx = -expx; result = -1; while (expx != 0) { expx <<= 1; ++result; } return result; } void float_setasciiz( floatnum x, const char* asciiz) { float_setscientific(x, asciiz, NULLTERMINATED); } char float_divi( floatnum quotient, cfloatnum dividend, int divisor, int digits) { floatstruct tmp; int result, expx; if (!_chckparam1(dividend, digits, maxdigits, INTQUOT)) return _setnan(quotient); if (digits != INTQUOT && (divisor == 1 || divisor == -1)) return float_muli(quotient, dividend, divisor, digits); if (divisor == 10 || divisor == -10) { expx = float_getexponent(dividend)-1; if (expx < -float_getrange() - 1) return _seterror(quotient, Underflow); } float_create(&tmp); float_setinteger(&tmp, divisor); result = float_div(quotient, dividend, &tmp, digits); float_free(&tmp); return result; } char float_addi( floatnum sum, cfloatnum summand1, int summand2, int digits) { floatstruct tmp; int result; if (!_chckparam1(summand1, digits, maxdigits, EXACT)) return _setnan(sum); if (summand2 == 0) return float_copy(sum, summand1, digits); float_create(&tmp); float_setinteger(&tmp, summand2); result = float_add(sum, summand1, &tmp, digits); float_free(&tmp); return result; } char float_muli( floatnum product, cfloatnum factor1, int factor2, int digits) { floatstruct tmp; int result; int expx; if (!_chckparam1(factor1, digits, maxdigits, EXACT)) return _setnan(product); switch(factor2) { case 0: return _setzero(product); case 1: case -1: case 10: case -10: expx = float_getexponent(factor1); if (factor2 != 1 && factor2 != -1 && ++expx > float_getrange()) return _seterror(product, Overflow); result = float_copy(product, factor1, digits); if (factor2 < 0) float_neg(product); float_setexponent(product, expx); return result; case 2: case -2: result = float_add(product, factor1, factor1, digits); if (factor2 < 0) float_neg(product); return result; } float_create(&tmp); float_setinteger(&tmp, factor2); result = float_mul(product, factor1, &tmp, digits); float_free(&tmp); return result; } int leadingdigits( cfloatnum x, int digits) { int i; unsigned tmp, ovfl; char buf[LOGMSB+1]; const unsigned msb = MSB; if (digits <= 0 || digits > (int)LOGMSB+1 || float_isnan(x) || float_iszero(x)) return 0; memset(buf, '0', digits); float_getsignificand(buf, digits, x); tmp = 0; for(i = 0; i < digits; ++i) { ovfl = 10; if (_longmul(&tmp, &ovfl)) { ovfl = buf[i] - '0'; _longadd(&tmp, &ovfl); } if (ovfl != 0) return 0; } if (float_getsign(x) < 0) { if (tmp > msb) return 0; if (tmp == msb) return (int)tmp; return -(int)tmp; } if (tmp >= msb) return 0; return (int)tmp; } int float_abscmp( floatnum x, floatnum y) { signed char sx, sy; int result; sx = float_getsign(x); sy = float_getsign(y); float_abs(x); float_abs(y); result = float_cmp(x, y); float_setsign(x, sx); float_setsign(y, sy); return result; } int float_relcmp( floatnum x, floatnum y, int digits) { /* do not simply use float_sub, because of overflow/underflow */ floatstruct tmp; int result; int expx, expy, expdiff; result = float_cmp(x, y); if (result == 0 || float_getlength(x) == 0 || float_getlength(y) == 0 || float_getsign(x) != float_getsign(y)) return result; expx = float_getexponent(x); expy = float_getexponent(y); expdiff = expx - expy; if (expdiff >= 2 || expdiff < -2) return result; float_create(&tmp); if (result > 0) float_setexponent(x, 0); float_setexponent(y, expy - expx); float_sub(&tmp, x, y, 2); if ((result * float_getsign(x)) > 0) float_div(&tmp, &tmp, x, 2); else float_div(&tmp, &tmp, y, 2); if (float_getexponent(&tmp) < -digits) result = 0; float_setexponent(x, expx); float_setexponent(y, expy); float_free(&tmp); return result; } char float_reciprocal( floatnum x, int digits) { return float_div(x, &c1, x, digits); } char float_isinteger( cfloatnum x) { return !float_isnan(x) && float_getlength(x) <= float_getexponent(x) + 1; } int float_asinteger( cfloatnum x) { return leadingdigits(x, float_getexponent(x)+1); } void float_checkedround( floatnum x, int digits) { floatstruct tmp; int saveerr; saveerr = float_geterror(); float_create(&tmp); if (float_round(&tmp, x, digits, TONEAREST)) float_move(x, &tmp); float_free(&tmp); float_geterror(); float_seterror(saveerr); } void float_addexp( floatnum x, int smd) { float_setexponent(x, float_getexponent(x) + smd); } char float_isodd( floatnum x) { return (float_getdigit(x, float_getexponent(x)) & 1) != 0; } char float_roundtoint( floatnum x, roundmode mode) { signed char value = 0; signed char sign; char digit; if (float_isnan(x)) return float_int(x); /* sets float_error */ if (float_getexponent(x) >= 0) return float_round(x, x, float_getexponent(x) + 1, mode); sign = float_getsign(x); switch (mode) { case TONEAREST: digit = float_getdigit(x, 0); if (digit < 5 || (digit == 5 && float_getlength(x) == 1)) value = 0; else value = sign; break; case TOINFINITY: value = sign; break; case TOPLUSINFINITY: value = sign > 0? 1 : 0; break; case TOMINUSINFINITY: value = sign > 0? 0 : -1; break; case TOZERO: value = 0; break; } switch (value) { case 0: float_setzero(x); break; case 1: float_copy(x, &c1, EXACT); break; case -1: float_copy(x, &cMinus1, EXACT); break; } return 1; } static float _ipwr(float x, int exp){ int e = exp < 0? -exp : exp; double pwr = x; if ((e & 1) == 0) x = 1; while (e >>= 1){ pwr *= pwr; if ((exp & 1) != 0) x *= pwr; } return exp < 0? 1/x : x; } /* returns x as a float. Only the first 6 digits contribute to the result. The exponent has to be in the valid range of a float */ float float_asfloat(cfloatnum x){ return leadingdigits(x, 6)/100000.0 * _ipwr(10, float_getexponent(x)); } void float_setfloat(floatnum dest, float x){ int exp = aprxlog10(x); // use two assignments to avoid overflow x *= _ipwr(10, -exp); x *= 100000000; float_setinteger(dest, (int)x); float_addexp(dest, exp - 8); } /* Somehow math.h cannot always be included with the full set of ISO C99 math functions enabled. So use the approximations below. These functions are used to get first guess start values for iterative algorithms, or to estimate round off errors, or to find the approximative size of a summand. They need not be accurate to more than, say, 0.1% */ float aprxsqrt(float x){ int exp, i; float x2 = 2 * frexp(x, &exp) - 1; float result = (0.5 - 0.125 * x2) * x2 + 1; x2 += 1; for (i = 0; ++i <= 2;) result = 0.5 * (result + x2 / result); if ((exp & 1) == 0) result *= M_SQRT2; return result * _ipwr(2, (exp - 1) >> 1); } float aprxln(float x){ /* The evaluation of approxlog(x) is based on an approximation suggested by Abramowitz, Stegun, Handbook of mathematical functions. The returned logarithm is valid to 5 (decimal) digits after the decimal point. */ int exp; x = 2 * frexpf(fabs(x), &exp) - 1; return ((((0.03215845 * x - 0.13606275) * x + 0.28947478) * x - 0.49190896) * x + 0.99949556) * x + (exp - 1) * M_LN2; } float aprxlog2(float x){ return aprxln(x) * M_LOG2E; } float aprxlog10(float x){ return aprxln(x) * M_LOG10E; } float aprxlog10fn(cfloatnum x){ return float_getexponent(x) + aprxlog10(leadingdigits(x, 5)) - 4; } float aprxlngamma(float x){ return (x-0.5) * aprxln(x) - x + 0.9189385332f; } deepin-calculator-5.7.21/3rdparty/math/floatcommon.h000066400000000000000000000101161423020056600223660ustar00rootroot00000000000000/* floatcommon.h: header file for convenience functions, based on floatnum. */ /* Copyright (C) 2007 - 2009 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATCOMMON_H # define FLOATCOMMON_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif /* helper, checks parameters. Sets float_error to NaNOperand or InvalidPrecision and sets to NaN, if the parameters do not meet the requirements of routines for higher mathematical functions, and returns 0 in this case */ char chckmathparam(floatnum x, int digits); /* helper, determines, how many decimal digits the exponent of has. If the exponent is 0, -1 is returned */ int logexp(cfloatnum x); /* helper, returns the first decimal digits and the sign of a significand, encoded in an integer. */ int leadingdigits(cfloatnum x, int digits); /* convenience wrapper for float_setscientific, setting the last parameter to NULLTERMINATED */ void float_setasciiz(floatnum x, const char* asciiz); /* convenience wrapper for float_add, adds a signed integer to and places the result in */ char float_addi(floatnum sum, cfloatnum summand1, int summand2, int digits); /* convenience wrapper for float_mul, multiplies a signed integer with and places the result in */ char float_muli(floatnum product, cfloatnum factor1, int factor2, int digits); /* convenience wrapper for float_div, divides by a signed integer and places the result in */ char float_divi(floatnum quotient, cfloatnum dividend, int divisor, int digits); /* convenience wrapper for float_cmp: compares the absolute value of both operands */ int float_abscmp(floatnum x, floatnum y); /* convenience wrapper for float_div, returns 1/ */ char float_reciprocal(floatnum x, int digits); /* compares two numbers in a normal fashion, but returns equal, if their relative difference is less than 1e-, i.e. |(x-y)/max(x,y)| < 1e- */ int float_relcmp(floatnum x, floatnum y, int digits); /* returns whether x is an integer */ char float_isinteger(cfloatnum x); /* returns the integer part of x as integer. If x exceeds the integer range, 0 is returned */ int float_asinteger(cfloatnum x); /* rounds x in TONEAREST mode. If x overflows, the rounding is reverted. Does not report errors */ void float_checkedround(floatnum x, int digits); /* a fast way to multiply with a power of ten, does not set float_error on overflow or NaN, returns silently NaN instead*/ void float_addexp(floatnum x, int smd); /* returns 0, if the integer part of x is even */ char float_isodd(floatnum x); /* an extension of float_int: you can choose the round mode errors: FLOAT_NANOPERAND FLOAT_OVERFLOW (if EXP_MAX is really small) */ char float_roundtoint(floatnum x, roundmode mode); float float_asfloat(cfloatnum x); void float_setfloat(floatnum dest, float x); float aprxsqrt(float x); float aprxln(float x); float aprxlog10(float x); float aprxlog2(float x); float aprxlngamma(float x); float aprxlog10fn(cfloatnum x); #ifdef __cplusplus } #endif #endif /* FLOATCOMMON_H */ deepin-calculator-5.7.21/3rdparty/math/floatconfig.h000066400000000000000000000157241423020056600223550ustar00rootroot00000000000000/* floatdefines.h: basic settings in floatnum. */ /* Copyright (C) 2007 - 2009 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ /* this file contains the basic settings, that control the overall behaviour of floatnum and derivates. Uncomment or set any of the following defines according to your needs. */ #ifndef _FLOATCONFIG_H #define _FLOATCONFIG_H /* FLOATDEBUG introduces some extensions to floatnum, so you can easily follow operations of floatnum in a debugger like ddd. Uncomment this, if you develop code based on floatnum, and if you want to look into floatnum variables during a debugger session. */ // #define FLOATDEBUG /* enables a pre-defined set of macros so that a regression test suite of floatnum can be executed. These settings are such that corner cases can easily be triggered. The settings are not useful in a real application of floatnum. Uncomment this if you want to run the standard regression test suite of floatnum */ // #define _FLOATNUMTEST /* floatnum uses bc's bc_num format to store and operate on data. Since bc_num is an arbitrary precision format, operands may grow to extreme sizes, where complex operations take considerable time to execute, up to an hour or more. floatconfig defines a guard value to avoid extreme long operands. Any request to produce a result of more than MAXDIGITS digits is considered an error and yields a NaN result. When setting this value, bear in mind, this is a global value that effects internal operations as well as 'user' requests. When using the routines for transcendent mathematical functions, you should allow extra 14 digits, so that operations like float_exp do not fail when they compute something near maximum precision. */ #define MAXDIGITS 250 /* the number of bits into which an exponent of a floatnum is encoded. In order to avoid integer overflow, this should be at least two bits less than the bits in the integer type chosen for the exponent. The default is two bit less than the size of an int */ // #define BITS_IN_EXP 30 /* floatnum puts an upper limit on the base 10 exponent of its numbers that is based on the size of an integer, but even for 16 bit integers this limit is as big as 4095. Real applications usually do not need such big numbers. If you want to limit the range of possible numbers, set this value accordingly. An operation result exceeding this limit is converted into a NaN, and an overflow/underflow is reported. The default is the maximum positive value that can be encoded in BITS_IN_EXP bits. If you change EXPMAX, you might want to reduce BITS_IN_EXP as well. */ /* #define EXPMAX 5000 */ /* The precision of basic operations like + or * is limited by MAXDIGITS. In addition, some higher mathematical functions involve constants, that, of course, are stored to a limited precision only. This puts another bound on floatnum, described by the value MATHPRECISION. Since procedures for higher mathematical functions employ basic operations to determine their result, MATHPRECISION is <= MAXDIGITS. The current math library version of floatnum limits higher mathematical functions to 100 digits precision. One can say, MATHPRECISION describes the granularity of the number space, because higher functions do not (reliably) produce different results for values closer to each other than this granularity. You may re-define granularity by setting DECPRECISION. This will never bypass MATHPRECISION, being always the limit for the math library, but basic operations may benefit from finer granularity, up to the overall limit MAXDIGITS. If you lower granularity, that saves some memory and evaluation time in a few places. Granularity means that integers with more than DECPRECISION digits might not be saved without loss of digits. So DECPRECISION defines the integer range of floatnum. Because base conversion and logic operations are integer based, both are limited by DECPRECISION as well. By default, DECPRECISION is set to MATHPRECISION */ #define DECPRECISION 78 /* The integer domain of logical functions is a true subset of the integer range, because, according to their nature, they operate modulo a power of two, so the limit on their input is best chosen to be a power of 2. If you do not declare a limit here, an appropriate value is derived from DECPRECISION. If you change this value, make sure 2^LOGICRANGE is less than 10^DECPRECISION */ #define LOGICRANGE 256 /*************************************************************************** END OF USER SETABLE DEFINES ***************************************************************************/ /* the limit of the math library */ #define MATHPRECISION (2*DECPRECISION + 3) #if defined(_FLOATNUMTEST) # undef MAXDIGITS # undef MATHPRECISION # undef DECPRECISION # undef LOGICRANGE # define MAXDIGITS 130 # define MATHPRECISION 130 # define LOGICRANGE 96 #endif #define MAXBITS_IN_EXP (sizeof(int)*8-2) #define MAXEXP ((1 << MAXBITS_IN_EXP) - 1) #ifndef BITS_IN_EXP /* we need 2 extra bits during conversion, so that the exponent does not overflow while computing a base 2 expression */ # define BITS_IN_EXP MAXBITS_IN_EXP #endif /* necessary width of an integer to hold all possible exponents after a conversion to another base */ #define BITS_IN_HEXEXP BITS_IN_EXP #define BITS_IN_OCTEXP (BITS_IN_EXP + 1) #define BITS_IN_BINEXP (BITS_IN_EXP + 2) #ifndef MAXDIGITS # define MAXDIGITS 500 #endif /* MAXDIGITS */ #ifndef EXPMAX # define EXPMAX ((1 << (BITS_IN_EXP-1)) - 1) #endif /* EXPMAX */ #define EXPMIN (-EXPMAX - 1) #define EXPZERO ((int)((-1) << (sizeof(int)*8-1))) #define EXPNAN ((int)(~EXPZERO)) #ifndef DECPRECISION #define DECPRECISION MATHPRECISION #endif #define BINPRECISION ((33219*DECPRECISION)/10000 + 1) #define OCTPRECISION ((11073*DECPRECISION)/10000 + 1) #define HEXPRECISION ((8305*DECPRECISION)/10000 + 1) #ifndef LOGICRANGE # define LOGICRANGE (16*((BINPRECISION-2)/16)) #endif #endif /* _FLOATCONFIG_H */ deepin-calculator-5.7.21/3rdparty/math/floatconst.c000066400000000000000000000274251423020056600222320ustar00rootroot00000000000000/* floatconst.c: constants for higher math functions */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatconst.h" static char sExp[] = "2.7182818284""5904523536""0287471352""6624977572""4709369995" "9574966967""6277240766""3035354759""4571382178""5251664274" "2746639193""2003059921""8174135966""2904357290""0334295260" "5956307381""3232862794""3490763233""8298807531""9525101901" "1573834187"; static char sLn2[] = "0.6931471805""5994530941""7232121458""1765680755""0013436025" "5254120680""0094933936""2196969471""5605863326""9964186875" "4200148102""0570685734"; static char sLn3[] = "1.0986122886""6810969139""5245236922""5257046474""9055782274" "9451734694""3336374942""9321860896""6873615754""8137320887" "8797002906""5957865742"; static char sLn7[] = "1.9459101490""5531330510""5352743443""1797296370""8472958186" "1188459390""1499375798""6275206926""7787658498""5878715269" "9306169420""5851140912"; static char sLn10[] = "2.3025850929""9404568401""7991454684""3642076011""0148862877" "2976033327""9009675726""0967735248""0235997205""0895982983" "4196778404""2286248633"; static char sPhi[] = "1.6180339887""4989484820""4586834365""6381177203""0917980576" "2862135448""6227052604""6281890244""9707207204""1893911374" "8475408807""5386891752""1266338622""2353693179""3180060766" "7263544333""8908659593""9582905638""3226613199""2829026788" "0675208766"; static char sPi[] = "3.1415926535""8979323846""2643383279""5028841971""6939937510" "5820974944""5923078164""0628620899""8628034825""3421170679" "8214808651""3282306647""0938446095""5058223172""5359408128" "4811174502""8410270193""8521105559""6446229489""5493038196" "4428810976"; static char sPiDiv2[] = "1.5707963267""9489661923""1321691639""7514420985""8469968755" "2910487472""2961539082""0314310449""9314017412""6710585339" "9107404325""6641153324"; static char sPiDiv4[] = "0.7853981633""9744830961""5660845819""8757210492""9234984377" "6455243736""1480769541""0157155224""9657008706""3355292669" "9553702162""8320576662"; static char s2Pi[] = "6.2831853071""7958647692""5286766559""0057683943""3879875021" "1641949889""1846156328""1257241799""7256069650""6842341359" "6429617302""6564613294"; static char s1DivPi[] = "0.3183098861""8379067153""7767526745""0287240689""1929148091" "2897495334""6881177935""9526845307""0180227605""5325061719" "1214568545""3515916074"; static char sLnSqrt2PiMinusHalf[] = "0.4189385332""0467274178""0329736405""6176398613""9747363778" "3412817151""5404827656""9592726039""7694743298""6359541976" "2200564662""4634337446"; static char sSqrtPi[] = "1.7724538509""0551602729""8167483341""1451827975""4945612238" "7128213807""7898529112""8459103218""1374950656""7385446654" "1622682362""4282570666"; static char s1DivSqrtPi[] = "0.5641895835""4775628694""8079451560""7725858440""5062932899" "8856844085""7217106424""6844149341""4486743660""2021073634" "4302834790""6361707352"; static char s2DivSqrtPi[] = "1.1283791670""9551257389""6158903121""5451716881""0125865799" "7713688171""4434212849""3688298682""8973487320""4042147268" "8605669581""2723414703"; static char* sBernoulli[] = { "1", "6", "1", "-30", "1", "42", "1", "-30", "5", "66", "691", "-2730", "7", "6", "3617", "-510", "43867", "798", "174611", "-330", "854513", "138", "236364091", "-2730", "8553103", "6", "23749461029", "-870", "8615841276005", "14322", "7709321041217", "-510", "2577687858367", "6", "26315271553053477373", "-1919190", "2929993913841559", "6", "261082718496449122051", "-13530", "1520097643918070802691", "1806", "27833269579301024235023", "-690", "596451111593912163277961", "282", "5609403368997817686249127547", "-46410", "495057205241079648212477525", "66", "801165718135489957347924991853", "-1590", "29149963634884862421418123812691", "798", "2479392929313226753685415739663229", "-870", "84483613348880041862046775994036021", "354", "1215233140483755572040304994079820246041491", "-56786730", "12300585434086858541953039857403386151", "6", "106783830147866529886385444979142647942017", "-510", "1472600022126335654051619428551932342241899101", "64722", "78773130858718728141909149208474606244347001", "-30", "1505381347333367003803076567377857208511438160235", "4686", "5827954961669944110438277244641067365282488301844260429", "-140100870", "34152417289221168014330073731472635186688307783087", "6", "24655088825935372707687196040585199904365267828865801", "-30", "414846365575400828295179035549542073492199375372400483487", "3318", "4603784299479457646935574969019046849794257872751288919656867", "-230010", "1677014149185145836823154509786269900207736027570253414881613", "498", "2024576195935290360231131160111731009989917391198090877281083932477", "-3404310", "660714619417678653573847847426261496277830686653388931761996983", "6", "1311426488674017507995511424019311843345750275572028644296919890574047", "-61410", "1179057279021082799884123351249215083775254949669647116231545215727922535", "272118", "1295585948207537527989427828538576749659341483719435143023316326829946247", "-1410", "1220813806579744469607301679413201203958508415202696621436215105284649447", "6", "-4.70038339580357310785752555350060606545967373697590579151397635641e73", "1", "1.13180434454842492706751862577339342678903659547507479181789935417e76", "1", "-2.83822495706937069592641563364817647382846809280128821282285317145e78", "1", "7.40642489796788506297508271409209841768797317880887066731161003487e80", "1", "-2.00964548027566044834656196727153631868672708225328766243461301989e83", "1", "5.66571700508059414457193460305193569614194682875104206213875644522e85", "1", "-1.65845111541362169158237133743199123014949626147254647274024668156e88", "1", "5.03688599504923774192894219151801548124423742649032141415256513225e90", "1", "-1.58614682376581863693634015729664387827409784127789638804728645143e93", "1", "5.17567436175456269840732406825071225612408492359305508590621669403e95", "1", "-1.74889218402171173396900258776181591451414761618265448726273472159e98", "1", "6.11605199949521852558245252642641677807677268467832007168432401127e100", "1", "-2.2122776912707834942288323456712932445573185054987780150566552693e103", "1", "8.27227767987709698542210624599845957312046505184335662838488529886e105", "1", "-3.19589251114157095835916343691808148735262766710991122731845042431e108", "1", "1.27500822233877929823100243029266798669571917963897732951605857354e111", "1", "-5.25009230867741338994028246245651754469198940377552432607801345222e113", "1", "2.2301817894241625209869298198838728143738272150875878542490550781e116", "1", "-9.76845219309552044386335133989802393011669026749856789710001706619e118", "1", "4.40983619784529542722726228748131691918757542655281147353197591401e121", "1", "-2.05085708864640888397293377275830154864565966904008359530873982755e124", "1" }; floatstruct cBernoulliNum[68]; floatstruct cBernoulliDen[68]; floatstruct c1; floatstruct c2; floatstruct c3; floatstruct c12; floatstruct c16; floatstruct cExp; floatstruct cMinus1; floatstruct cMinus20; floatstruct c1Div2; floatstruct cLn2; floatstruct cLn3; floatstruct cLn7; floatstruct cLn10; floatstruct cPhi; floatstruct cPi; floatstruct cPiDiv2; floatstruct cPiDiv4; floatstruct c2Pi; floatstruct c1DivPi; floatstruct cSqrtPi; floatstruct cLnSqrt2PiMinusHalf; floatstruct c1DivSqrtPi; floatstruct c2DivSqrtPi; floatstruct cMinus0_4; floatstruct cUnsignedBound; int erfcdigits = 0; floatstruct erfccoeff[MAXERFCIDX]; floatstruct erfcalpha; floatstruct erfcalphasqr; floatstruct erfct2; floatstruct erfct3; void floatmath_init() { int i, save; floatnum_init(); save = float_setprecision(MAXDIGITS); float_create(&c1); float_setinteger(&c1, 1); float_create(&c2); float_setinteger(&c2, 2); float_create(&c3); float_setinteger(&c3, 3); float_create(&c12); float_setinteger(&c12, 12); float_create(&c16); float_setinteger(&c16, 16); float_create(&cMinus1); float_setinteger(&cMinus1, -1); float_create(&cMinus20); float_setinteger(&cMinus20, -20); float_create(&c1Div2); float_setscientific(&c1Div2, ".5", NULLTERMINATED); float_create(&cExp); float_setscientific(&cExp, sExp, NULLTERMINATED); float_create(&cLn2); float_setscientific(&cLn2, sLn2, NULLTERMINATED); float_create(&cLn3); float_setscientific(&cLn3, sLn3, NULLTERMINATED); float_create(&cLn7); float_setscientific(&cLn7, sLn7, NULLTERMINATED); float_create(&cLn10); float_setscientific(&cLn10, sLn10, NULLTERMINATED); float_create(&cPhi); float_setscientific(&cPhi, sPhi, NULLTERMINATED); float_create(&cPi); float_setscientific(&cPi, sPi, NULLTERMINATED); float_create(&cPiDiv2); float_setscientific(&cPiDiv2, sPiDiv2, NULLTERMINATED); float_create(&cPiDiv4); float_setscientific(&cPiDiv4, sPiDiv4, NULLTERMINATED); float_create(&c2Pi); float_setscientific(&c2Pi, s2Pi, NULLTERMINATED); float_create(&c1DivPi); float_setscientific(&c1DivPi, s1DivPi, NULLTERMINATED); float_create(&cSqrtPi); float_setscientific(&cSqrtPi, sSqrtPi, NULLTERMINATED); float_create(&cLnSqrt2PiMinusHalf); float_setscientific(&cLnSqrt2PiMinusHalf, sLnSqrt2PiMinusHalf, NULLTERMINATED); float_create(&c1DivSqrtPi); float_setscientific(&c1DivSqrtPi, s1DivSqrtPi, NULLTERMINATED); float_create(&c2DivSqrtPi); float_setscientific(&c2DivSqrtPi, s2DivSqrtPi, NULLTERMINATED); float_create(&cMinus0_4); float_setscientific(&cMinus0_4, "-.4", NULLTERMINATED); for (i = -1; ++i < MAXBERNOULLIIDX;) { float_create(&cBernoulliNum[i]); float_create(&cBernoulliDen[i]); float_setscientific(&cBernoulliNum[i], sBernoulli[2*i], NULLTERMINATED); float_setscientific(&cBernoulliDen[i], sBernoulli[2*i+1], NULLTERMINATED); } float_create(&cUnsignedBound); float_copy(&cUnsignedBound, &c1, EXACT); for (i = -1; ++i < 2*(int)sizeof(unsigned);) float_mul(&cUnsignedBound, &c16, &cUnsignedBound, EXACT); for (i = -1; ++i < MAXERFCIDX;) float_create(&erfccoeff[i]); float_create(&erfcalpha); float_create(&erfcalphasqr); float_create(&erfct2); float_create(&erfct3); float_setprecision(save); } void floatmath_exit() { int i; float_free(&c1); float_free(&c2); float_free(&c3); float_free(&c12); float_free(&c16); float_free(&cMinus1); float_free(&cMinus20); float_free(&c1Div2); float_free(&cExp); float_free(&cLn2); float_free(&cLn3); float_free(&cLn7); float_free(&cLn10); float_free(&cPhi); float_free(&cPi); float_free(&cPiDiv2); float_free(&cPiDiv4); float_free(&c2Pi); float_free(&c1DivPi); float_free(&cSqrtPi); float_free(&cLnSqrt2PiMinusHalf); float_free(&c1DivSqrtPi); float_free(&c2DivSqrtPi); float_free(&cMinus0_4); for (i = -1; ++i < MAXBERNOULLIIDX;) { float_free(&cBernoulliNum[i]); float_free(&cBernoulliDen[i]); } float_free(&cUnsignedBound); for (i = -1; ++i < MAXERFCIDX;) float_free(&erfccoeff[i]); float_free(&erfcalpha); float_free(&erfcalphasqr); float_free(&erfct2); float_free(&erfct3); } deepin-calculator-5.7.21/3rdparty/math/floatconst.h000066400000000000000000000043651423020056600222350ustar00rootroot00000000000000/* floatconst.h: constants for higher math functions */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATCONST_H #define FLOATCONST_H #include "floatnum.h" #define MAXBERNOULLIIDX 68 #define MAXERFCIDX 80 #ifdef __cplusplus extern "C" { #endif extern floatstruct c1; extern floatstruct c2; extern floatstruct c3; extern floatstruct c12; extern floatstruct cExp; extern floatstruct cMinus1; extern floatstruct cMinus20; extern floatstruct c1Div2; extern floatstruct cLn2; extern floatstruct cLn3; extern floatstruct cLn7; extern floatstruct cLn10; extern floatstruct cPhi; extern floatstruct cPi; extern floatstruct cPiDiv2; extern floatstruct cPiDiv4; extern floatstruct c2Pi; extern floatstruct c1DivPi; extern floatstruct cSqrtPi; extern floatstruct c1DivSqrtPi; extern floatstruct cLnSqrt2PiMinusHalf; extern floatstruct c2DivSqrtPi; extern floatstruct cMinus0_4; extern floatstruct cBernoulliNum[68]; extern floatstruct cBernoulliDen[68]; extern floatstruct cUnsignedBound; extern int erfcdigits; extern floatstruct erfccoeff[MAXERFCIDX]; extern floatstruct erfcalpha; extern floatstruct erfcalphasqr; extern floatstruct erfct2; extern floatstruct erfct3; void floatmath_init(); void floatmath_exit(); #ifdef __cplusplus } #endif #endif /* FLOATCONST_H */ deepin-calculator-5.7.21/3rdparty/math/floatconvert.c000066400000000000000000000445111423020056600225570ustar00rootroot00000000000000/* floatconvert.c: radix conversion, based on floatnum. */ /* Copyright (C) 2007 - 2009 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatconvert.h" #include "floatcommon.h" #include "floatconst.h" #include "floatipower.h" #include typedef struct { t_number_desc n; t_longint l; floatnum f; int bitlength; int trailing0; int lgbase; } t_ext_number; typedef t_ext_number *p_ext_number; /************************ conversion to/from longint *******************/ static unsigned _digitblock( floatnum f, int ofs, int count) { unsigned result; result = 0; for (; --count >= 0;) result = 10 * result + float_getdigit(f, ofs++); return result; } Error _floatnum2longint( t_longint *longint, floatnum f) { int digits; int i; unsigned factor; longint->length = 0; digits = float_getexponent(f) + 1; i = digits % 9; _longintadd(longint, _digitblock(f, 0, i)); factor = 1000000000; while (i < digits) { if (_longintmul(longint, factor) || _longintadd(longint, _digitblock(f, i, 9))) return IOConversionOverflow; i += 9; } /* extra element for floatlong operations */ *(longint->value + longint->length) = 0; return Success; } static void _setunsigned( floatnum f, unsigned value) { float_setinteger(f, value); if ((int)value < 0) float_add(f, f, &cUnsignedBound, EXACT); } void _longint2floatnum( floatnum f, t_longint *longint) { floatstruct tmp; int idx; float_setzero(f); if (longint->length == 0) return; float_create(&tmp); idx = longint->length - 1; for (; idx >= 0; --idx) { _setunsigned(&tmp, longint->value[idx]); float_mul(f, f, &cUnsignedBound, EXACT); float_add(f, f, &tmp, EXACT); } float_free(&tmp); } /************************** io routines **************************/ static int _max( int a, int b) { return a > b ? a : b; } static char _validmode( char mode) { return mode >= IO_MODE_SCIENTIFIC && mode <= IO_MODE_COMPLEMENT; } static int lgbase( signed char base) { switch (base) { case 2: return 1; case 8: return 3; case 16: return 4; } return 0; } static char _getfnintdigit( int ofs, p_seq_desc n) { if (ofs <= n->digits) return float_getdigit((floatnum)(n->param), ofs); return 0; } static char _getfnfracdigit( int ofs, p_seq_desc n) { floatnum x; int exp; x = (floatnum)(n->param); exp = float_getexponent(x); if (ofs >= 0) return float_getdigit(x, ofs + exp + 1); return 0; } static void _setfndesc( p_number_desc n, floatnum x) { int digits; n->intpart.seq.base = 10; digits = _max(float_getexponent(x) + 1, 0); n->intpart.seq.digits = digits; n->intpart.seq.trailing0 = _max(digits - float_getlength(x), 0); n->intpart.seq.param = x; n->intpart.getdigit = _getfnintdigit; n->fracpart.seq.base = 10; n->fracpart.seq.leadingSignDigits = _max(-float_getexponent(x) - 1, 0); n->fracpart.seq.digits = float_getlength(x) - digits + n->fracpart.seq.leadingSignDigits; n->fracpart.seq.param = x; n->fracpart.getdigit = _getfnfracdigit; } static Error _pack2longint( t_longint *l, p_ext_seq_desc n) { int bitofs; int ofs; int logbase; logbase = lgbase(n->seq.base); ofs = n->seq.leadingSignDigits; if (_significantdigits(&n->seq) == 0) /* can be true in complement case: 0xFF00 */ --ofs; bitofs = (n->seq.digits - ofs) * logbase; if (!_longintsetsize(l, bitofs)) return IOBufferOverflow; for (; bitofs > 0;) { bitofs -= logbase; _orsubstr(l->value, bitofs, n->getdigit(ofs++, &n->seq)); } return Success; } static char _getlongintdigit( int ofs, p_seq_desc n) { if (ofs < 0 || ofs >= n->digits) return 0; return _bitsubstr(((t_longint *)(n->param))->value, (n->digits - ofs - 1) * lgbase(n->base)) & (n->base - 1); } static char _getlongintofsdigit( int ofs, p_seq_desc n) { p_number_desc nmb; int digits; nmb = (p_number_desc)(n->param); digits = n->digits; if (ofs < 0 || ofs >= digits) return 0; digits += nmb->fracpart.seq.digits; return _bitsubstr(((t_longint *)(nmb->fracpart.seq.param))->value, (digits - ofs - 1) * lgbase(n->base)) & (n->base - 1); } static void _setlongintdesc( p_ext_seq_desc n, t_longint *l, signed char base) { int lg; n->seq.base = base; lg = lgbase(base); n->seq.digits = (_bitlength(l) + lg - 1) / lg; n->seq.leadingSignDigits = 0; n->seq.trailing0 = _lastnonzerobit(l) / lg; n->seq.param = l; n->getdigit = _getlongintdigit; } static Error _packdec2int( floatnum x, p_ext_seq_desc n) { int ofs; int exp; int bufsz; int i; char buf[DECPRECISION]; float_setnan(x); ofs = n->seq.leadingSignDigits; exp = n->seq.trailing0; bufsz = n->seq.digits - ofs - exp; if (bufsz > DECPRECISION) return IOBufferOverflow; if (bufsz == 0) float_setzero(x); else for (i = -1; ++i < bufsz;) buf[i] = n->getdigit(ofs++, &n->seq) + '0'; float_setsignificand(x, NULL, buf, bufsz); float_setexponent(x, exp + bufsz - 1); return Success; } static Error _packbin2int( floatnum x, p_ext_seq_desc n) { t_longint l; Error result; float_setnan(x); if ((result = _pack2longint(&l, n)) != Success) return result; _longint2floatnum(x, &l); return Success; } static char _signextendbin( t_longint* longint, int bitlength) { unsigned mask; signed char sign; int maxidx = ((bitlength-1) / BITS_IN_UNSIGNED); int signbit = (bitlength - 1 - maxidx * BITS_IN_UNSIGNED); sign = (longint->value[maxidx] & (1 << signbit)) != 0? -1:1; mask = (~0) << signbit; if (sign < 0) longint->value[maxidx] |= mask; else longint->value[maxidx] &= ~mask; return sign; } static void _negbin( t_longint* longint, int bitlength) { int idx = -1; const int maxidx = ((bitlength-1) / BITS_IN_UNSIGNED); while (++idx <= maxidx && longint->value[idx] == 0); if (idx <= maxidx) longint->value[idx] = - longint->value[idx]; while (++idx <= maxidx) longint->value[idx] = ~longint->value[idx]; } static Error _packsignedbin2int( floatnum x, p_ext_seq_desc n, int bitlength) { t_longint l; Error result; for (int i = 0;i<5;i++) { l.value[i] = 0; } float_setnan(x); if ((result = _pack2longint(&l, n)) != Success) return result; int idx; signed char sign; sign = _signextendbin(&l,bitlength); if (sign < 0) _negbin(&l,bitlength); idx = (bitlength-1) / BITS_IN_UNSIGNED; while (idx >= 0 && l.value[idx] == 0) --idx; if (idx < 0) l.length = 0; else l.length = idx + 1; _longint2floatnum(x, &l); float_setsign(x, sign); return Success; } static Error _pack2int( floatnum x, p_ext_seq_desc n, int bitlength, signed char b) { switch (n->seq.base) { case IO_BASE_NAN: float_setnan(x); break; case IO_BASE_ZERO: float_setzero(x); break; case 10: return _packdec2int(x, n); default: if(b > 0) { return _packsignedbin2int(x, n, bitlength); } return _packbin2int(x, n); } return Success; } static Error _pack2frac( floatnum x, p_ext_seq_desc n, int digits, int bitlength, signed char b) { floatstruct tmp; int exp; Error result; n->seq.digits -= n->seq.trailing0; n->seq.trailing0 = 0; switch (n->seq.base) { case IO_BASE_NAN: float_setnan(x); break; case IO_BASE_ZERO: float_setzero(x); break; default: if ((result = _pack2int(x, n, bitlength, b)) != Success) return result; float_create(&tmp); float_setinteger(&tmp, n->seq.base); _raiseposi(&tmp, &exp, n->seq.digits, digits + 2); float_div(x, x, &tmp, digits + 2); float_setexponent(x, float_getexponent(x) - exp); float_free(&tmp); } n->seq.digits += n->seq.trailing0; return Success; } Error pack2floatnum( floatnum x, p_number_desc n, int bitlength, signed char b) { floatstruct tmp; int digits; int saveerr; int saverange; Error result; signed char base; if ((result = _pack2int(x, &n->intpart, bitlength, b)) != Success) return result; if (float_isnan(x)) return Success; saveerr = float_geterror(); saverange = float_setrange(MAXEXP); float_create(&tmp); float_move(&tmp, x); float_setzero(x); digits = DECPRECISION - float_getexponent(&tmp); if (digits <= 0 || (result = _pack2frac(x, &n->fracpart, digits, bitlength, b)) == Success) float_add(x, x, &tmp, DECPRECISION); if (result != Success) return result; if ((!float_getlength(x)) == 0) { /* no zero, no NaN? */ base = n->prefix.base; float_setinteger(&tmp, base); if (n->exp >= 0) { _raiseposi_(&tmp, n->exp, DECPRECISION + 2); float_mul(x, x, &tmp, DECPRECISION + 2); } else { _raiseposi_(&tmp, -n->exp, DECPRECISION + 2); float_div(x, x, &tmp, DECPRECISION + 2); } } float_free(&tmp); float_setsign(x, n->prefix.sign == IO_SIGN_COMPLEMENT ? -1 : n->prefix.sign); float_geterror(); float_seterror(saveerr); float_setrange(saverange); if (!float_isvalidexp(float_getexponent(x))) float_setnan(x); return float_isnan(x) ? IOExpOverflow : Success; } static Error _outscidec( p_otokens tokens, floatnum x, p_number_desc n, int scale) { float_checkedround(x, scale + 1); n->exp = float_getexponent(x); float_setexponent(x, 0); _setfndesc(n, x); return desc2str(tokens, n, scale); } static int _checkbounds( floatnum x, int digits, signed char base) { if (float_getexponent(x) < 0) { float_muli(x, x, base, digits); return -1; } else if (float_asinteger(x) >= base) { float_divi(x, x, base, digits); return 1; } return 0; } static void _scale2int( floatnum x, int scale, signed char base) { floatstruct pwr; int pwrexp; (void)scale; if (scale != 0) { float_create(&pwr); float_setinteger(&pwr, base); _raiseposi(&pwr, &pwrexp, scale, DECPRECISION + 4); float_mul(x, x, &pwr, DECPRECISION + 4); float_addexp(x, pwrexp); float_free(&pwr); } float_roundtoint(x, TONEAREST); } static Error _fixp2longint( p_number_desc n, t_longint *l, floatnum x, int scale) { Error result; _scale2int(x, scale, n->prefix.base); result = _floatnum2longint(l, x); if (result != Success) return result; _setlongintdesc(&n->fracpart, l, n->prefix.base); return Success; } static int _extractexp( floatnum x, int scale, signed char base) { floatstruct pwr; floatstruct fbase; int decprec; int pwrexp; int exp; int logbase; (void)scale; logbase = lgbase(base); decprec = DECPRECISION + 3; exp = (int)(aprxlog10fn(x) * 3.321928095f); if (float_getexponent(x) < 0) exp -= 3; exp /= logbase; if (exp != 0) { float_create(&fbase); float_setinteger(&fbase, base); float_create(&pwr); float_copy(&pwr, &fbase, EXACT); _raiseposi(&pwr, &pwrexp, exp < 0 ? -exp : exp, decprec); if (float_getexponent(x) < 0) { float_addexp(x, pwrexp); float_mul(x, x, &pwr, decprec); } else { float_addexp(x, -pwrexp); float_div(x, x, &pwr, decprec); } float_free(&pwr); float_free(&fbase); } exp += _checkbounds(x, decprec, base); return exp; } static void _setscale( p_number_desc n, t_longint *l, int scale) { (void)l; n->intpart.seq.leadingSignDigits = 0; n->intpart.seq.trailing0 = n->fracpart.seq.trailing0 - scale; if (n->intpart.seq.trailing0 < 0) n->intpart.seq.trailing0 = 0; n->intpart.seq.base = n->fracpart.seq.base; n->intpart.seq.digits = n->fracpart.seq.digits - scale; n->intpart.getdigit = _getlongintofsdigit; n->intpart.seq.param = n; n->fracpart.seq.digits = scale; if (n->fracpart.seq.trailing0 >= scale) { n->fracpart.seq.base = IO_BASE_ZERO; n->fracpart.seq.trailing0 = scale; } } static Error _outscihex( p_otokens tokens, floatnum x, p_number_desc n, int scale) { t_longint l; Error result; n->exp = _extractexp(x, scale, n->prefix.base); result = _fixp2longint(n, &l, x, scale); if (result != Success) return result; /* rounding in _fixp2longint may have increased the exponent */ n->exp += n->fracpart.seq.digits - 1 - scale; _setscale(n, &l, n->fracpart.seq.digits - 1); return desc2str(tokens, n, scale); } static char _isvalidbase( signed char base) { return base == 10 || lgbase(base) != 0; } static Error _outsci( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (n->prefix.base == 10) return _outscidec(tokens, x, n, scale); return _outscihex(tokens, x, n, scale); } static Error _outfixpdec( p_otokens tokens, floatnum x, p_number_desc n, int scale) { //edit for bug-19653 float_checkedround(x, scale + 1); int digits; digits = float_getexponent(x) + scale + 1; if (digits <= 0) /* underflow */ return IOConversionUnderflow; if (float_round(x, x, digits, TONEAREST) != TRUE) /* float_round() can err if the number contains too many digits */ return float_geterror(); _setfndesc(n, x); return desc2str(tokens, n, scale); } static Error _outfixphex( p_otokens tokens, floatnum x, p_number_desc n, int scale) { t_longint l; Error result; float_copy(x, x, DECPRECISION + 1); result = _fixp2longint(n, &l, x, scale); if (result != Success) return result; if (l.length == 0) { result = float_geterror(); return result != Success ? result : IOConversionUnderflow; } _setscale(n, &l, scale); return desc2str(tokens, n, scale); } static Error _outfixp( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (n->prefix.base == 10) return _outfixpdec(tokens, x, n, scale); return _outfixphex(tokens, x, n, scale); } static Error _outengdec( p_otokens tokens, floatnum x, p_number_desc n, int scale) { int shift; float_checkedround(x, scale + 1); n->exp = float_getexponent(x); if (n->exp < 0) shift = 2 - (-n->exp - 1) % 3; else shift = n->exp % 3; float_setexponent(x, shift); n->exp -= shift; _setfndesc(n, x); return desc2str(tokens, n, scale - shift); } static Error _outeng( p_otokens tokens, floatnum x, p_number_desc n, int scale) { if (n->prefix.base != 10 || scale < 2) return InvalidParam; return _outengdec(tokens, x, n, scale); } static Error _outcompl( p_otokens tokens, floatnum x, p_number_desc n, int scale) { (void)scale; if (!float_isinteger(x)) return IOInvalidComplement; if (n->prefix.sign == IO_SIGN_MINUS) n->prefix.sign = IO_SIGN_COMPLEMENT; else n->prefix.sign = IO_SIGN_NONE; return _outfixphex(tokens, x, n, 0); } static void _emptybuffer( p_buffer token) { if (token->sz > 0) *(token->buf) = '\0'; else token->buf = NULL; } static void _emptytokens( p_otokens tokens) { _emptybuffer(&tokens->intpart); _emptybuffer(&tokens->fracpart); tokens->sign = IO_SIGN_NONE; tokens->base = IO_BASE_NAN; tokens->exp = 0; } Error float_out( p_otokens tokens, floatnum x, int scale, signed char base, char outmode) { t_number_desc n; _emptytokens(tokens); /* do some sanity checks first */ if (!_validmode(outmode) || scale < 0 || !_isvalidbase(base)) return InvalidParam; _clearnumber(&n); if (float_iszero(x)) n.prefix.base = IO_BASE_ZERO; else if (!float_isnan(x)) n.prefix.base = base; if (!_isvalidbase(n.prefix.base)) /* NaN and 0 are handled here */ return desc2str(tokens, &n, 0); n.prefix.sign = float_getsign(x); float_abs(x); switch (outmode) { case IO_MODE_FIXPOINT: return _outfixp(tokens, x, &n, scale); case IO_MODE_ENG: return _outeng(tokens, x, &n, scale); case IO_MODE_COMPLEMENT: return _outcompl(tokens, x, &n, 0); default: return _outsci(tokens, x, &n, scale); } } /** * 新增入参 bitlength:数据长度 8,16,32,64 * 新增入参 b:当2进制转换8,16进制时不考虑符号位 */ Error float_in(floatnum x, p_itokens tokens, int bitlength, signed char b) { t_number_desc n; Error result; if ((result = str2desc(&n, tokens)) == Success) result = pack2floatnum(x, &n, bitlength, b); if (result != Success) { _seterror(x, BadLiteral); float_setnan(x); } return result; } deepin-calculator-5.7.21/3rdparty/math/floatconvert.h000066400000000000000000000055101423020056600225600ustar00rootroot00000000000000/* floatconvert.h: radix conversion, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATCONVERT_H # define FLOATCONVERT_H #include "floatnum.h" #include "floatlong.h" #ifdef __cplusplus extern "C" { #endif #define IO_MODE_SCIENTIFIC 0 #define IO_MODE_FIXPOINT 1 #define IO_MODE_ENG 2 #define IO_MODE_COMPLEMENT 3 /* converts the integer part of f to a binary coded bigint. Returns IOConversionOverflow, if the bigint overflows */ Error _floatnum2longint(t_longint *longint, floatnum f); /* converts a binary coded bigint into a floatnum */ void _longint2floatnum(floatnum f, t_longint *longint); /* the output process destroys x 'digits' are the number of digits after the dot. Regardless of the value of 'digits', a conversion is always done to DECPRECISION places Before reducing to 'digits' places the (converted) value is rounded. Trailing zeros are padded, if necessary, to fill to the right size. Errors: InvalidParam (if any of the parameters makes no sense like digits <= 0, or a not supported base) IOBufferOverflow (if the caller does not provide enough buffer in tokens) IOConversionOverflow (request requires too much buffer space for radix conversion) IOConversionUnderflow (request would produce leading zeros only) IOInvalidComplement (two's complement cannot be generated) */ Error float_out(p_otokens tokens, floatnum x, int digits, signed char base, char outmode); /* returns Success or one of the IO... codes Errors: BadLiteral, set in addition to the returned result */ Error float_in(floatnum x, p_itokens tokens, int bitlength, signed char b); #ifdef __cplusplus } #endif #endif /* FLOATCONVERT_H */ deepin-calculator-5.7.21/3rdparty/math/floaterf.c000066400000000000000000000256711423020056600216610ustar00rootroot00000000000000/* floaterf.c: normal distribution integrals erf and the like */ /* Copyright (C) 2007 - 2009 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floaterf.h" #include "floatconst.h" #include "floatcommon.h" #include "floatexp.h" #include "math.h" /* The Taylor expansion of sqrt(pi)*erf(x)/2 around x = 0. converges only for small |x| < 1 sufficiently. erf(x) = SUM[i>=0] (x^(2*i+1)/(i! * (2*i+1))) relative error for 100-digit evaluation: < 3e-100 */ char erfseries(floatnum x, int digits) { floatstruct xsqr, smd, pwr; int i, workprec, expx; expx = float_getexponent(x); workprec = digits + 2*expx + 2; if (workprec <= 0 || float_iszero(x)) /* for tiny arguments approx. == x */ return 1; float_create(&xsqr); float_create(&smd); float_create(&pwr); float_mul(&xsqr, x, x, workprec + 1); workprec = digits + float_getexponent(&xsqr) + 1; float_copy(&pwr, x, workprec + 1); i = 1; while (workprec > 0) { float_mul(&pwr, &pwr, &xsqr, workprec + 1); float_divi(&pwr, &pwr, -i, workprec + 1); float_divi(&smd, &pwr, 2 * i++ + 1, workprec); float_add(x, x, &smd, digits + 3); workprec = digits + float_getexponent(&smd) + expx + 2; } float_free(&pwr); float_free(&smd); float_free(&xsqr); return 1; } /* the asymptotic expansion of erfc, the bigger x is, the better. returns sum( (2*i+1)! /i! / x^(2*i) Relative error for x >= 16 and 100-digit evaluation is less than 9e-100 */ char erfcasymptotic(floatnum x, int digits) { floatstruct smd, fct; int i, workprec, newprec; float_create(&smd); float_create(&fct); workprec = digits - 2 * float_getexponent(x) + 1; if (workprec <= 0) { float_copy(x, &c1, EXACT); return 1; } float_mul(&fct, x, x, digits + 1); float_div(&fct, &c1Div2, &fct, digits); float_neg(&fct); float_copy(&smd, &c1, EXACT); float_setzero(x); newprec = digits; workprec = newprec; i = 1; while (newprec > 0 && newprec <= workprec) { workprec = newprec; float_add(x, x, &smd, digits + 4); float_muli(&smd, &smd, i, workprec + 1); float_mul(&smd, &smd, &fct, workprec + 2); newprec = digits + float_getexponent(&smd) + 1; i += 2; } float_free(&fct); float_free(&smd); return newprec <= workprec; } /* this algorithm is based on a paper from Crandall, who in turn attributes to Chiarella and Reichel. Found this in a paper from Borwein, Bailey and Girgensohn, and added minor improvements such as the adaptive working precision. There is a restriction with this algorithm not mentioned in the paper: x must not be too large, because the correcting term 2/(1-exp(2*pi*x/alpha)) becomes dominant and renders the result incorrect for large x. Fortunately, the valid range seems to overlap with the range of the asymptotic formula. Picks a fixed alpha suitable for the desired precision and evaluates the sum f(t, alpha) = Sum[k>0](exp(-k*k*alpha*alpha)/(k*k*alpha*alpha + t) f(t, alpha) is used in the evaluation of erfc(sqrt(t)) alpha is dependent on the desired precision; For a precision of p places, alpha should be < pi/sqrt(p*ln 10). Unfortunately, the smaller alpha is, the worse is the convergence rate, so alpha is usually approximately its upper limit. relative error for 100-digit evaluation < 5e-100 */ char erfcsum(floatnum x, /* should be the square of the parameter to erfc */ int digits) { int i; int workprec = 0; floatstruct sum, smd; floatnum Ei; if (digits > erfcdigits) { /* cannot re-use last evaluation's intermediate results */ for (i = MAXERFCIDX; --i >= 0;) /* clear all exp(-k*k*alpha*alpha) to indicate their absence */ float_free(&erfccoeff[i]); /* current precision */ erfcdigits = digits; /* create new alpha appropriate for the desired precision This alpha need not be high precision, any alpha near the one evaluated here would do */ float_setfloat(&erfcalpha, M_PI / aprxsqrt((digits + 4) * M_LN10)); float_round(&erfcalpha, &erfcalpha, 3, TONEAREST); float_mul(&erfcalphasqr, &erfcalpha, &erfcalpha, EXACT); /* the exp(-k*k*alpha*alpha) are later evaluated iteratively. Initiate the iteration here */ float_copy(&erfct2, &erfcalphasqr, EXACT); float_neg(&erfct2); _exp(&erfct2, digits + 3); /* exp(-alpha*alpha) */ float_copy(erfccoeff, &erfct2, EXACT); /* start value */ float_mul(&erfct3, &erfct2, &erfct2, digits + 3); /* exp(-2*alpha*alpha) */ } float_create(&sum); float_create(&smd); float_setzero(&sum); for (i = 0; ++i < MAXERFCIDX;) { Ei = &erfccoeff[i-1]; if (float_isnan(Ei)) { /* if exp(-i*i*alpha*alpha) is not available, evaluate it from the coefficient of the last summand */ float_mul(&erfct2, &erfct2, &erfct3, workprec + 3); float_mul(Ei, &erfct2, &erfccoeff[i-2], workprec + 3); } /* Ei finally decays rapidly. save some time by adjusting the working precision */ workprec = digits + float_getexponent(Ei) + 1; if (workprec <= 0) break; /* evaluate the summand exp(-i*i*alpha*alpha)/(i*i*alpha*alpha+x) */ float_muli(&smd, &erfcalphasqr, i*i, workprec); float_add(&smd, x, &smd, workprec + 2); float_div(&smd, Ei, &smd, workprec + 1); /* add summand to the series */ float_add(&sum, &sum, &smd, digits + 3); } float_move(x, &sum); float_free(&smd); return 1; } /* checks the quality of the asymptotic series for erfc. If the ratio of two subsequent summands from the series (the convergence rate) should not fall below `ratio' for a desired result precision (represented by digits), the number of summands n must not be greater than n <= (`digits'*ln 10 + 0.5 * ln 2)/(1 - ln `ratio') and the parameter x has to fullfil x >= sqrt(n/`ratio') `ratio' must be a value < 1, If you pick a value close to 1, you finally have to add quite a lot of summands from the series (in low precision), that affect a few digits at the low end of the result only. On the other hand, choosing a good convergence rate pushes the validity range of the series towards larger x. Here, the convergence rate is chosen to be 0.5, meaning that the addition of a summand from the series at least halfs the magnitude of the tail of the series. The evaluation is carried out in low precision using interger arithmetic rather than floating point data. For a 100 digit result the lower boundary of the range of the asymptotic series (truncated when the convergence rate falls below 0.5) is x > approx. 16.5. The above formulas estimate the limit x slightly too small, especially when `digits' is small. So, to compensate for that, r should be at least <= 0.92 */ static char _asymptotic_good( floatnum x, int digits) { /* all constants scaled by 10000 */ /* 1/ratio */ #define RATIO 20000 /* (1 - ln ratio) */ #define C_RATIO 16931 /* ln 10 */ #define LN10 23026 /* 0.5*ln 2 */ #define LN2DIV2 3466 int n, ix; if (!float_isvalidexp(float_getexponent(x) + 2) || (digits == 1 && float_cmp(x, &c2) >= 0)) return 1; /* 10000 * n/ratio */ n = RATIO*((digits * LN10 + LN2DIV2) / C_RATIO); float_addexp(x, 2); ix = float_asinteger(x); float_addexp(x, -2); return ix == 0 || ix >= 0x10000 || ix * ix >= n; } static int _logexpxsqr(int exp) { if (exp < 0) exp = 0; if (exp >= 0x1000) exp = 0x1000; return ((exp * exp * 73) >> 5); } char _erf( floatnum x, int digits) { int workprec; signed char sign; sign = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) > 0) { workprec = digits - _logexpxsqr(float_getexponent(x)); if (workprec < 0 || !_erfc(x, workprec)) float_setzero(x); float_sub(x, &c1, x, digits + 1); } else { erfnear0(x, digits); float_mul(x, x, &c2DivSqrtPi, digits + 2); } float_setsign(x, sign); return 1; } char _erfc( floatnum x, int digits) { floatstruct tmp, t2, t3; int expx, prec; char result; if (float_cmp(x, &c1Div2) <= 0) { /* use erfc(x) = 1 - erf(x) for small or negative x */ prec = digits; /* default for negative x, result is approx. 1 */ expx = float_getexponent(x); if (expx < 0) { /* |x| < 1, but not 0 */ prec = expx + digits + 2; if (prec <= 0) { float_copy(x, &c1, EXACT); return 1; } } _erf(x, prec); float_sub(x, &c1, x, digits + 1); return 1; } float_create(&tmp); if (_asymptotic_good(x, digits)) { if (float_mul(&tmp, x, x, digits + 5) && _exp(&tmp, digits + 3) && float_mul(&tmp, &tmp, x, digits + 3) && float_div(&tmp, &c1DivSqrtPi, &tmp, digits + 3)) { if (!erfcbigx(x, digits)) result = _seterror(x, EvalUnstable); else result = float_mul(x, x, &tmp, digits + 4); } else result = _seterror(x, Underflow); } else { result = 1; float_create(&t2); float_create(&t3); float_mul(&t2, x, x, digits + 2); float_copy(&tmp, &t2, EXACT); erfcsum(&tmp, digits); float_add(&tmp, &tmp, &tmp, digits + 1); float_copy(&t3, &t2, EXACT); float_reciprocal(&t2, digits + 1); float_add(&tmp, &tmp, &t2, digits + 2); float_neg(&t3); _exp(&t3, digits + 2); float_mul(&t3, &t3, &tmp, digits + 2); float_mul(&tmp, &erfcalpha, x, digits + 2); float_mul(&t3, &tmp, &t3, digits + 3); float_mul(&t3, &c1DivPi, &t3, digits + 2); /* quick estimate to find the right working precision */ float_div(&tmp, x, &erfcalpha, 4); float_mul(&tmp, &tmp, &c2Pi, 4); float_div(&tmp, &tmp, &cLn10, 4); prec = digits - float_getexponent(&t3) - float_asinteger(&tmp) + 1; /* add correction term */ if (prec > 0) { float_div(&tmp, x, &erfcalpha, prec + 3); float_mul(&tmp, &tmp, &c2Pi, prec + 4); _exp(&tmp, prec); float_sub(&tmp, &c1, &tmp, prec); float_div(&tmp, &c2, &tmp, prec); float_add(&t3, &t3, &tmp, digits + 1); } float_free(&t2); float_move(x, &t3); } float_free(&tmp); return result; } deepin-calculator-5.7.21/3rdparty/math/floaterf.h000066400000000000000000000026101423020056600216520ustar00rootroot00000000000000/* floaterf.h: normal distribution integrals erf and the like */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATERF_H #define FLOATERF_H #include "floatseries.h" #ifdef __cplusplus extern "C" { #endif #define erfnear0 erfseries #define erfcbigx erfcasymptotic char _erf(floatnum x, int digits); char _erfc(floatnum x, int digits); #ifdef __cplusplus } #endif #endif /* FLOATERF_H */ deepin-calculator-5.7.21/3rdparty/math/floatexp.c000066400000000000000000000212011423020056600216620ustar00rootroot00000000000000/* floatexp.c: exponential function and friends, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatconst.h" #include "floatcommon.h" #include "floatseries.h" #include "floatexp.h" /* uses the addition theorem cosh(2x)-1 == 2*(cosh x - 1)*(cosh x + 1) to reduce the argument to the range |x| < 0.01. Starting with x == 1, you need 7 reduction steps to achieve the desired magnitude. The relative error is < 8e-100 for a 100 digit result. The return value is 0, if the result underflows. |x| < 1, otherwise the final process, where the reductions are unwinded, becomes too unstable */ char _coshminus1lt1( floatnum x, int digits) { floatstruct tmp; int reductions; if (float_iszero(x)) return 1; float_abs(x); reductions = 0; while(float_getexponent(x) >= -2) { float_mul(x, x, &c1Div2, digits+1); ++reductions; } if (!coshminus1near0(x, digits) && reductions == 0) return !float_iszero(x); float_create(&tmp); for(; reductions-- > 0;) { float_mul(&tmp, x, x, digits); float_add(x, x, x, digits+2); float_add(x, x, &tmp, digits+2); float_add(x, x, x, digits+2); } float_free(&tmp); return 1; } /* sinh x == sqrt((cosh x - 1) * (cosh x + 1)) */ static void _sinhfromcoshminus1( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_add(&tmp, x, &c2, digits); float_mul(x, &tmp, x, digits+1); float_sqrt(x, digits+1); float_free(&tmp); } /* sinh x for |x| < 1. Derived from cosh x - 1. The relative error is < 8e-100 for a 100 digit result */ void _sinhlt1( floatnum x, int digits) { signed char sgn; if (float_getexponent(x) < -digits) /* for very small x: sinh(x) approx. == x. */ return; sgn = float_getsign(x); _coshminus1lt1(x, digits); _sinhfromcoshminus1(x, digits); float_setsign(x, sgn); } /* evaluates exp(x) - 1. This value can be obtained by exp(x) - 1 == sinh(x) + cosh(x) - 1 relative error < 8e-100 for a 100 digit result */ void _expminus1lt1( floatnum x, int digits) { floatstruct tmp; signed char sgn; if (float_getexponent(x) < -digits || float_iszero(x)) /* for very small x: exp(x)-1 approx.== x */ return; float_create(&tmp); sgn = float_getsign(x); _coshminus1lt1(x, digits); float_copy(&tmp, x, EXACT); _sinhfromcoshminus1(x, digits); float_setsign(x, sgn); float_add(x, x, &tmp, digits+1); float_free(&tmp); } /* exp(x) for 0 <= x < ln 10 relative error < 5e-100 */ void _expltln10( floatnum x, int digits) { int expx; int factor; char sgnf; expx = float_getexponent(x); factor = 1; if (expx >= -1) { sgnf = leadingdigits(x, 2 + expx); if (sgnf > 4) { if (sgnf < 9) { factor = 2; float_sub(x, x, &cLn2, digits+1); } else if (sgnf < 14) { factor = 3; float_sub(x, x, &cLn3, digits+1); } else if (sgnf < 21) { factor = 7; float_sub(x, x, &cLn7, digits+1); } else { factor = 10; float_sub(x, x, &cLn10, digits+1); } } } _expminus1lt1(x, digits); float_add(x, x, &c1, digits+1); if (factor != 1) float_muli(x, x, factor, digits+1); } /* exp(x) for all x. Underflow or overflow is indicated by the return value (0, if error) relative error for 100 digit results is 5e-100 */ char _exp( floatnum x, int digits) { floatstruct exp, tmp; int expx, extra; char ok; if (float_iszero(x)) { float_copy(x, &c1, EXACT); return 1; } expx = float_getexponent(x); if (expx >= (int)(BITS_IN_EXP >> 1)) /* obvious overflow or underflow */ return 0; float_create(&exp); float_create(&tmp); float_setzero(&exp); if (expx >= 0) { float_div(&exp, x, &cLn10, expx+1); float_int(&exp); extra = float_getexponent(&exp)+1; float_mul(&tmp, &exp, &cLn10, digits+extra); float_sub(x, x, &tmp, digits+extra); if (float_cmp(x, &cLn10) >= 0) { float_add(&exp, &exp, &c1, EXACT); float_sub(x, x, &cLn10, digits); } } if (float_getsign(x) < 0) { float_sub(&exp, &exp, &c1, EXACT); float_add(x, x, &cLn10, digits); } /* when we get here 0 <= x < ln 10 */ _expltln10(x, digits); /* just in case rounding leads to a value >= 10 */ expx = float_getexponent(x); if (expx != 0) float_addi(&exp, &exp, expx, EXACT); ok = 1; if (!float_iszero(&exp)) { expx = float_asinteger(&exp); ok = expx != 0; float_setexponent(x, expx); } float_free(&exp); float_free(&tmp); return ok && !float_isnan(x); } static char _0_5exp( floatnum x, int digits) { float_sub(x, x, &cLn2, digits + (3*logexp(x)/10)+1); return _exp(x, digits); } /* exp(x)-1 for all x. Overflow is indicated by the return value (0, if error) relative error for 100 digit results is 8e-100 */ char _expminus1( floatnum x, int digits) { int expr; if (float_abscmp(x, &c1Div2) < 0) { _expminus1lt1(x, digits); return 1; } if (float_getsign(x) < 0) { expr = (2*float_getexponent(x)/5); if (expr >= digits) float_setinteger(x, -1); else { _exp(x, digits-expr); float_sub(x, x, &c1, digits); } return 1; } if (!_exp(x, digits)) return 0; float_sub(x, x, &c1, digits); return 1; } static void _addreciproc( floatnum x, int digits, signed char sgn) { floatstruct tmp; int expx; expx = float_getexponent(x); if (2*expx < digits) { float_create(&tmp); float_muli(&tmp, x, 4, digits-2*expx); float_reciprocal(&tmp, digits-2*expx); float_setsign(&tmp, sgn); float_add(x, x, &tmp, digits+1); float_free(&tmp); } } /* cosh(x)-1 for all x. Underflow or overflow is indicated by the return value (0, if error) relative error for 100 digit results is 6e-100 */ char _coshminus1( floatnum x, int digits) { if (float_getexponent(x) < 0 || float_iszero(x)) return _coshminus1lt1(x, digits); if(!_0_5exp(x, digits)) return 0; _addreciproc(x, digits, 1); float_sub(x, x, &c1, digits); return 1; } /* sinh(x) for all x. Overflow is indicated by the return value (0, if error) relative error for 100 digit results is < 8e-100 */ char _sinh( floatnum x, int digits) { if (float_getexponent(x) < 0 || float_iszero(x)) _sinhlt1(x, digits); else { if(!_0_5exp(x, digits)) return 0; _addreciproc(x, digits, -1); } return 1; } /* tanh(x) for |x| <= 0.5. relative error for 100 digit results is < 7e-100 */ void _tanhlt0_5( floatnum x, int digits) { floatstruct tmp; signed char sgn; float_create(&tmp); sgn = float_getsign(x); float_abs(x); float_add(x, x, x, digits+1); _expminus1lt1(x, digits); float_add(&tmp, x, &c2, digits); float_div(x, x, &tmp, digits); float_setsign(x, sgn); float_free(&tmp); } /* tanh(x)-1 for x > 0. relative error for 100 digit results is < 9e-100 */ char _tanhminus1gt0( floatnum x, int digits) { if (float_add(x, x, x, digits+1) && _0_5exp(x, digits)) { float_add(x, x, &c1Div2, digits+1); float_reciprocal(x, digits+1); float_setsign(x, -1); return 1; } return 0; } void _tanhgt0_5( floatnum x, int digits) { int expx; expx = float_getexponent(x); if (5*expx >= digits) float_copy(x, &c1, EXACT); else { _tanhminus1gt0(x, digits - 5*expx); float_add(x, x, &c1, digits); } } char _power10( floatnum x, int digits) { int exp; if (float_isinteger(x)) { exp = float_asinteger(x); if (exp == 0 && !float_iszero(x)) return 0; float_copy(x, &c1, EXACT); float_setexponent(x, exp); return !float_isnan(x); } return float_mul(x, x, &cLn10, digits+2) && _exp(x, digits); } deepin-calculator-5.7.21/3rdparty/math/floatexp.h000066400000000000000000000033711423020056600216770ustar00rootroot00000000000000/* floatexp.h: exponential function and friends, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATEXP_H # define FLOATEXP_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _coshminus1lt1(floatnum x, int digits); void _sinhlt1(floatnum x, int digits); void _expminus1lt1(floatnum x, int digits); void _expltln10(floatnum x, int digits); char _exp(floatnum x, int digits); char _expminus1(floatnum x, int digits); char _coshminus1(floatnum x, int digits); void _tanhlt0_5(floatnum x, int digits); char _tanhminus1gt0(floatnum x, int digits); char _sinh(floatnum x, int digits); void _tanhgt0_5(floatnum x, int digits); char _power10(floatnum exponent, int digits); #ifdef __cplusplus } #endif #endif /* FLOATEXP_H */ deepin-calculator-5.7.21/3rdparty/math/floatgamma.c000066400000000000000000000274561423020056600221720ustar00rootroot00000000000000/* floatgamma.c: Gamma function, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatgamma.h" #include "floatconst.h" #include "floatcommon.h" #include "floatlog.h" #include "floatexp.h" #include "floattrig.h" /* asymptotic series of the Binet function for x >= 77 and a 100 digit computation, the relative error is < 9e-100. the series converges, if x and digits comply to 100 >= digits >= 2 x >= sqrt((digits*ln 10 + 0.5*ln 2)/1.0033). As a special case, for digits == 1, convergence is guaranteed, if x >= 1.8. */ char binetasymptotic(floatnum x, int digits) { floatstruct recsqr; floatstruct sum; floatstruct smd; floatstruct pwr; int i, workprec; if (float_getexponent(x) >= digits) { /* if x is very big, ln(gamma(x)) is dominated by x*ln x and the Binet function does not contribute anything substantial to the final result */ float_setzero(x); return 1; } float_create(&recsqr); float_create(&sum); float_create(&smd); float_create(&pwr); int tempdigits = 0; if(digits > 117) { tempdigits = digits; digits = 117; } float_copy(&pwr, &c1, EXACT); float_setzero(&sum); float_div(&smd, &c1, &c12, digits+1); workprec = digits - 2*float_getexponent(x)+3; i = 1; if (workprec > 0) { float_mul(&recsqr, x, x, workprec); float_reciprocal(&recsqr, workprec); while (float_getexponent(&smd) > -digits-1 && ++i <= MAXBERNOULLIIDX) { workprec = digits + float_getexponent(&smd) + 3; float_add(&sum, &sum, &smd, digits+1); float_mul(&pwr, &recsqr, &pwr, workprec); float_muli(&smd, &cBernoulliDen[i-1], 2*i*(2*i-1), workprec); float_div(&smd, &pwr, &smd, workprec); float_mul(&smd, &smd, &cBernoulliNum[i-1], workprec); } } else /* sum reduces to the first summand*/ float_move(&sum, &smd); if (i > MAXBERNOULLIIDX) /* x was not big enough for the asymptotic series to converge sufficiently */ float_setnan(x); else float_div(x, &sum, x, digits); float_free(&pwr); float_free(&smd); float_free(&sum); float_free(&recsqr); digits = tempdigits; return i <= MAXBERNOULLIIDX; } /* returns the number of summands needed in the asymptotic series to guarantee precision. Each extra summand yields roughly extra 1.8 digits. This is derived under the assumption, that the costs of an extra factor in the rising pochhammer symbol are about the same than those of an extra summand in the series */ static int _findorder( int digits) { return (5*digits + 5)/9; } /* returns how big x has to be to let the asymptotic series converge to at least precision. Derived from an estimation of the Bernouilli number inserted in the formula of a summand. */ static int _minx( int digits) { return (4657*_findorder(digits)-2750)/5000; } /* returns how much x has to be increased to let the asymptotic series converge to places */ static int _ofs( floatnum x, int digits) { int result; if (float_getexponent(x) >= 8) return 0; result = _minx(digits) - float_asinteger(x); return result <= 0? 0 : result; } /* evaluates the rising pochhammer symbol x*(x+1)*...*(x+n-1) (n >= 0) by multiplying. This can be expensive when n is large, so better restrict n to something sane like n <= 100. su stands for "small" and "unsigned" n */ static char _pochhammer_su( floatnum x, int n, int digits) { floatstruct factor; char result; /* the rising pochhammer symbol is computed recursively, observing that pochhammer(x, n) == pochhammer(x, p) * pochhammer(x+p, n-p). p is choosen as floor(n/2), so both factors are somehow "balanced". This pays off, if x has just a few digits, since only some late multiplications are full scale then and Karatsuba boosting yields best results, because both factors are always almost the same size. */ result = 1; switch (n) { case 0: float_copy(x, &c1, EXACT); case 1: break; default: float_create(&factor); float_addi(&factor, x, n >> 1, digits+2); result = _pochhammer_su(x, n >> 1, digits) && _pochhammer_su(&factor, n - (n >> 1), digits) && float_mul(x, x, &factor, digits+2); float_free(&factor); } return result; } /* evaluates ln(Gamma(x)) for all those x big enough to let the asymptotic series converge directly. Returns 0, if the result overflows relative error for a 100 gigit calculation < 5e-100 */ static char _lngammabigx( floatnum x, int digits) { floatstruct tmp1, tmp2; char result; result = 0; float_create(&tmp1); float_create(&tmp2); /* compute (ln x-1) * (x-0.5) - 0.5 + ln(sqrt(2*pi)) */ float_copy(&tmp2, x, digits+1); _ln(&tmp2, digits+1); float_sub(&tmp2, &tmp2, &c1, digits+2); float_sub(&tmp1, x, &c1Div2, digits+2); if (float_mul(&tmp1, &tmp1, &tmp2, digits+2)) { /* no overflow */ binetasymptotic(x, digits); float_add(x, &tmp1, x, digits+3); float_add(x, x, &cLnSqrt2PiMinusHalf, digits+3); result = 1; } float_free(&tmp2); float_free(&tmp1); return result; } static char _lngamma_prim_xgt0( floatnum x, floatnum revfactor, int digits) { int ofs; ofs = _ofs(x, digits); float_copy(revfactor, x, digits+1); _pochhammer_su(revfactor, ofs, digits); float_addi(x, x, ofs, digits+2); return _lngammabigx(x, digits); } static char _lngamma_prim( floatnum x, floatnum revfactor, int* infinity, int digits) { floatstruct tmp; char result; char odd; *infinity = 0; if (float_getsign(x) > 0) return _lngamma_prim_xgt0(x, revfactor, digits); float_copy(revfactor, x, digits + 2); float_sub(x, &c1, x, digits+2); float_create(&tmp); result = _lngamma_prim_xgt0(x, &tmp, digits); if (result) { float_neg(x); odd = float_isodd(revfactor); _sinpix(revfactor, digits); if (float_iszero(revfactor)) { *infinity = 1; float_setinteger(revfactor, odd? -1 : 1); } else float_mul(&tmp, &tmp, &cPi, digits+2); float_div(revfactor, revfactor, &tmp, digits+2); } float_free(&tmp); return result; } char _lngamma( floatnum x, int digits) { floatstruct factor; int infinity; char result; if (float_cmp(x, &c1) == 0 || float_cmp(x, &c2) == 0) return _setzero(x); float_create(&factor); result = _lngamma_prim(x, &factor, &infinity, digits) && infinity == 0; if (result) { float_abs(&factor); _ln(&factor, digits + 1); result = float_sub(x, x, &factor, digits+1); } float_free(&factor); if (infinity != 0) return _seterror(x, ZeroDivide); if (!result) float_setnan(x); return result; } char _gammagtminus20( floatnum x, int digits) { floatstruct factor; int ofs; char result; float_create(&factor); ofs = _ofs(x, digits+1); float_copy(&factor, x, digits+1); _pochhammer_su(&factor, ofs, digits); float_addi(x, x, ofs, digits+2); result = _lngammabigx(x, digits) && _exp(x, digits) && float_div(x, x, &factor, digits+1); float_free(&factor); if (!result) float_setnan(x); return result; } char _gamma( floatnum x, int digits) { floatstruct tmp; int infinity; char result; if (float_cmp(&cMinus20, x) > 0) { float_create(&tmp); result = _lngamma_prim(x, &tmp, &infinity, digits) && infinity == 0 && _exp(x, digits) && float_div(x, x, &tmp, digits + 1); float_free(&tmp); if (infinity != 0) return _seterror(x, ZeroDivide); if (!result) float_setnan(x); return result; } return _gammagtminus20(x, digits); } char _gammaint( floatnum integer, int digits) { int ofs; if (float_getexponent(integer) >=2) return _gammagtminus20(integer, digits); ofs = float_asinteger(integer); float_copy(integer, &c1, EXACT); return _pochhammer_su(integer, ofs-1, digits); } char _gamma0_5( floatnum x, int digits) { floatstruct tmp; int ofs; if (float_getexponent(x) >= 2) return _gamma(x, digits); float_create(&tmp); float_sub(&tmp, x, &c1Div2, EXACT); ofs = float_asinteger(&tmp); float_free(&tmp); if (ofs >= 0) { float_copy(x, &c1Div2, EXACT); if(!_pochhammer_su(x, ofs, digits)) return 0; return float_mul(x, x, &cSqrtPi, digits); } if(!_pochhammer_su(x, -ofs, digits)) return 0; return float_div(x, &cSqrtPi, x, digits); } static char _pochhammer_si( floatnum x, int n, int digits) { /* this extends the rising Pochhammer symbol to negative integer offsets following the formula pochhammer(x,n-1) = pochhammer(x,n)/(x-n+1) */ if (n >= 0) return _pochhammer_su(x, n, digits); return float_addi(x, x, n, digits) && _pochhammer_su(x, -n, digits) && float_reciprocal(x, digits); } static char _pochhammer_g( floatnum x, cfloatnum n, int digits) { /* this generalizes the rising Pochhammer symbol using the formula pochhammer(x,n) = Gamma(x+1)/Gamma(x-n+1) */ floatstruct tmp, factor1, factor2; int inf1, inf2; char result; float_create(&tmp); float_create(&factor1); float_create(&factor2); inf2 = 0; float_add(&tmp, x, n, digits+1); result = _lngamma_prim(x, &factor1, &inf1, digits) && _lngamma_prim(&tmp, &factor2, &inf2, digits) && (inf2 -= inf1) <= 0; if (inf2 > 0) float_seterror(ZeroDivide); if (result && inf2 < 0) float_setzero(x); if (result && inf2 == 0) result = float_div(&factor1, &factor1, &factor2, digits+1) && float_sub(x, &tmp, x, digits+1) && _exp(x, digits) && float_mul(x, x, &factor1, digits+1); float_free(&tmp); float_free(&factor2); float_free(&factor1); if (!result) float_setnan(x); return result; } static char _pochhammer_i( floatnum x, cfloatnum n, int digits) { /* do not use the expensive Gamma function when a few multiplications do the same */ /* pre: n is an integer */ int ni; signed char result; if (float_iszero(n)) return float_copy(x, &c1, EXACT); if (float_isinteger(x)) { result = -1; float_neg((floatnum)n); if (float_getsign(x) <= 0 && float_cmp(x, n) > 0) /* x and x+n have opposite signs, meaning 0 is among the factors */ result = _setzero(x); else if (float_getsign(x) > 0 && float_cmp(x, n) <= 0) /* x and x+n have opposite signs, meaning at one point you have to divide by 0 */ result = _seterror(x, ZeroDivide); float_neg((floatnum)n); if (result >= 0) return result; } if (float_getexponent(x) < EXPMAX/100) { ni = float_asinteger(n); if (ni != 0 && ni < 50 && ni > -50) return _pochhammer_si(x, ni, digits+2); } return _pochhammer_g(x, n, digits); } char _pochhammer( floatnum x, cfloatnum n, int digits) { if (float_isinteger(n)) return _pochhammer_i(x, n, digits); return _pochhammer_g(x, n, digits); } deepin-calculator-5.7.21/3rdparty/math/floatgamma.h000066400000000000000000000027301423020056600221630ustar00rootroot00000000000000/* floatgamma.h: Gamma function, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATGAMMA_H # define FLOATGAMMA_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _lngamma(floatnum x, int digits); char _gamma(floatnum x, int digits); char _gammaint(floatnum integer, int digits); char _gamma0_5(floatnum x, int digits); char _pochhammer(floatnum x, cfloatnum n, int digits); #ifdef __cplusplus } #endif #endif /* FLOATGAMMA_H */ deepin-calculator-5.7.21/3rdparty/math/floathmath.c000066400000000000000000000306251423020056600222010ustar00rootroot00000000000000/* floathmath.c: higher mathematical functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floathmath.h" #include "floatconst.h" #include "floatcommon.h" #include "floatlog.h" #include "floatexp.h" #include "floattrig.h" #include "floatpower.h" #include "floatipower.h" #include "floatgamma.h" #include "floaterf.h" #include "floatlogic.h" static char _cvtlogic( t_longint* lx, cfloatnum x) { if (float_isnan(x)) { float_seterror(NoOperand); return 0; } if (_floatnum2logic(lx, x)) return 1; float_seterror(OutOfLogicRange); return 0; } char float_lnxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) < 0 && float_getexponent(x) >= 0) return _seterror(x, OutOfDomain); _lnxplus1(x, digits); return 1; } char float_ln(floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) <= 0) return _seterror(x, OutOfDomain); _ln(x, digits); return 1; } char float_artanh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getexponent(x) >= 0) return _seterror(x, OutOfDomain); _artanh(x, digits); return 1; } char float_artanhxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) >= 0 || float_abscmp(x, &c2) >= 0) return _seterror(x, OutOfDomain); if (float_cmp(x, &c1Div2) < 0) { float_neg(x); _artanh1minusx(x, digits); } else { float_sub(x, &c1, x, digits+1); _artanh(x, digits); } return 1; } char float_arsinh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; _arsinh(x, digits); return 1; } char float_arcoshxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) < 0) return _seterror(x, OutOfDomain); _arcoshxplus1(x, digits); return 1; } char float_arcosh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; float_sub(x, x, &c1, digits+1); return float_arcoshxplus1(x, digits); } char float_lg( floatnum x, int digits) { floatstruct tmp; int expx; if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) <= 0) return _seterror(x, OutOfDomain); float_create(&tmp); expx = float_getexponent(x); float_setexponent(x, 0); _ln(x, digits); float_div(x, x, &cLn10, digits); float_setinteger(&tmp, expx); float_add(x, x, &tmp, digits); float_free(&tmp); return 1; } char float_lb( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) <= 0) return _seterror(x, OutOfDomain); _ln(x, digits); float_div(x, x, &cLn2, digits); return 1; } char float_exp( floatnum x, int digits) { signed char sgn; if (!chckmathparam(x, digits)) return 0; sgn = float_getsign(x); if (_exp(x, digits)) return 1; if (sgn < 0) return _seterror(x, Underflow); return _seterror(x, Overflow); } char float_expminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (_expminus1(x, digits)) return 1; return _seterror(x, Overflow); } char float_cosh( floatnum x, int digits) { int expx; if (!chckmathparam(x, digits)) return 0; expx = float_getexponent(x); if (2*expx+2 <= -digits || !_coshminus1(x, digits+2*expx)) { if (expx > 0) return _seterror(x, Overflow); float_setzero(x); } return float_add(x, x, &c1, digits); } char float_coshminus1( floatnum x, int digits) { int expx; if (!chckmathparam(x, digits)) return 0; expx = float_getexponent(x); if (_coshminus1(x, digits)) return 1; if (expx < 0) return _seterror(x, Underflow); return _seterror(x, Overflow); } char float_sinh( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (_sinh(x, digits)) return 1; return _seterror(x, Overflow); } char float_tanh( floatnum x, int digits) { signed char sgn; if (!chckmathparam(x, digits)) return 0; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) >= 0) _tanhgt0_5(x, digits); else _tanhlt0_5(x, digits); float_setsign(x, sgn); return 1; } char float_tanhminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_cmp(x, &c1Div2) >= 0) return _tanhminus1gt0(x, digits)? 1 : _seterror(x, Underflow); if (!float_iszero(x)) { if (float_abscmp(x, &c1Div2) <= 0) _tanhlt0_5(x, digits); else { float_setsign(x, 1); _tanhgt0_5(x, digits); float_setsign(x, -1); } } return float_sub(x, x, &c1, digits); } char float_arctan( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; _arctan(x, digits); return 1; } char float_arcsin( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_abscmp(x, &c1) > 0) return _seterror(x, OutOfDomain); _arcsin(x, digits); return 1; } char float_arccos( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_abscmp(x, &c1) > 0) return _seterror(x, OutOfDomain); _arccos(x, digits); return 1; } char float_arccosxplus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getsign(x) > 0 || float_abscmp(x, &c2) > 0) return _seterror(x, OutOfDomain); _arccosxplus1(x, digits); return 1; } char float_cos( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getexponent(x) >= DECPRECISION - 1 || !_trigreduce(x, digits)) return _seterror(x, EvalUnstable); _cos(x, digits); return 1; } char float_cosminus1( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (!_trigreduce(x, digits)) return _seterror(x, EvalUnstable); return _cosminus1(x, digits)? 1 : _seterror(x, Underflow); } char float_sin( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; if (float_getexponent(x) >= DECPRECISION - 1 || !_trigreduce(x, digits)) return _seterror(x, EvalUnstable); _sin(x, digits); return 1; } char float_tan( floatnum x, int digits) { if (!chckmathparam(x, digits)) return 0; return float_getexponent(x) >= DECPRECISION - 1 || !_trigreduce(x, digits) || !_tan(x, digits)? _seterror(x, EvalUnstable) : 1; } char float_raisei( floatnum power, cfloatnum base, int exponent, int digits) { if (digits <= 0 || digits > maxdigits) return _seterror(power, InvalidPrecision); if (float_isnan(base)) return _seterror(power, NoOperand); if (float_iszero(base)) { if (exponent == 0) return _seterror(power, OutOfDomain); if (exponent < 0) return _seterror(power, ZeroDivide); return _setzero(power); } digits += 14; if (digits > maxdigits) digits = maxdigits; float_copy(power, base, digits); if (!_raisei(power, exponent, digits) || !float_isvalidexp(float_getexponent(power))) { if (float_getexponent(base) < 0) return _seterror(power, Underflow); return _seterror(power, Overflow); } return 1; } char float_raise( floatnum power, cfloatnum base, cfloatnum exponent, int digits) { signed char sgn; if (float_isnan(exponent) || float_isnan(base)) return _seterror(power, NoOperand); if (digits <= 0 || digits > MATHPRECISION) return _seterror(power, InvalidPrecision); if (float_iszero(base)) { switch(float_getsign(exponent)) { case 0: //edit jingzhou 20200720 0^0 = 1 float_copy(power, &c1, digits+1); return 1; // return _seterror(power, OutOfDomain); case -1: return _seterror(power, ZeroDivide); } return _setzero(power); } sgn = float_getsign(base); if (sgn < 0) { if (!float_isinteger(exponent)) return _seterror(power, OutOfDomain); if ((float_getdigit(exponent, float_getexponent(exponent)) & 1) == 0) sgn = 1; } float_copy(power, base, digits+1); float_abs(power); if (!_raise(power, exponent, digits)) { float_seterror(Overflow); if (float_getexponent(base) * float_getsign(exponent) < 0) float_seterror(Underflow); return _setnan(power); } float_setsign(power, sgn); return 1; } char float_power10( floatnum x, int digits) { signed char sign; if (!chckmathparam(x, digits)) return 0; sign = float_getsign(x); if (_power10(x, digits)) return 1; return sign > 0? _seterror(x, Overflow) : _seterror(x, Underflow); } char float_gamma( floatnum x, int digits) { signed char sign; char result; if (!chckmathparam(x, digits)) return 0; sign = float_getsign(x); if (float_isinteger(x)) { if (sign <= 0) return _seterror(x, ZeroDivide); result = _gammaint(x, digits); } else if (float_getlength(x) - float_getexponent(x) == 2 && float_getdigit(x, float_getlength(x) - 1) == 5) result = _gamma0_5(x, digits); else result = _gamma(x, digits); if (!result) { if (sign < 0) float_seterror(Underflow); else float_seterror(Overflow); float_setnan(x); } return result; } char float_lngamma( floatnum x, int digits) { if (!x) return _seterror(x, OutOfDomain); return chckmathparam(x, digits) && _lngamma(x, digits)? 1 : _setnan(x); } char float_factorial( floatnum x, int digits) { if (!float_isnan(x)) float_add(x, x, &c1, digits); return float_gamma(x, digits); } char float_pochhammer( floatnum x, cfloatnum delta, int digits) { if (!chckmathparam(x, digits)) return 0; return float_isnan(delta)? _seterror(x, NoOperand) : _pochhammer(x, delta, digits); } char float_erf(floatnum x, int digits) { return chckmathparam(x, digits)? _erf(x, digits) : 0; } char float_erfc(floatnum x, int digits) { return chckmathparam(x, digits)? _erfc(x, digits) : 0; } char float_not( floatnum x) { t_longint lx; if(!_cvtlogic(&lx, x)) return _setnan(x); _not(&lx); _logic2floatnum(x, &lx); return 1; } char float_and( floatnum dest, cfloatnum x, cfloatnum y) { t_longint lx, ly; if(!_cvtlogic(&lx, x) || !_cvtlogic(&ly, y)) return _setnan(dest); _and(&lx, &ly); _logic2floatnum(dest, &lx); return 1; } char float_or( floatnum dest, cfloatnum x, cfloatnum y) { t_longint lx, ly; if(!_cvtlogic(&lx, x) || !_cvtlogic(&ly, y)) return _setnan(dest); _or(&lx, &ly); _logic2floatnum(dest, &lx); return 1; } char float_xor( floatnum dest, cfloatnum x, cfloatnum y) { t_longint lx, ly; if(!_cvtlogic(&lx, x) || !_cvtlogic(&ly, y)) return _setnan(dest); _xor(&lx, &ly); _logic2floatnum(dest, &lx); return 1; } char _doshift( floatnum dest, cfloatnum x, cfloatnum shift, char right) { int ishift; t_longint lx; if (float_isnan(shift)) return _seterror(dest, NoOperand); if (!float_isinteger(shift)) return _seterror(dest, OutOfDomain); if(!_cvtlogic(&lx, x)) return 0; if (float_iszero(shift)) { float_copy(dest, x, EXACT); return 1; } ishift = float_asinteger(shift); if (ishift == 0) ishift = (3*LOGICRANGE) * float_getsign(shift); if (!right) ishift = -ishift; if (ishift > 0) _shr(&lx, ishift); else _shl(&lx, -ishift); _logic2floatnum(dest, &lx); return 1; } char float_shr( floatnum dest, cfloatnum x, cfloatnum shift) { return _doshift(dest, x, shift, 1); } char float_shl( floatnum dest, cfloatnum x, cfloatnum shift) { return _doshift(dest, x, shift, 0); } deepin-calculator-5.7.21/3rdparty/math/floathmath.h000066400000000000000000000332431423020056600222050ustar00rootroot00000000000000/* floathmath.h: higher mathematical functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATHMATH_H #define FLOATHMATH_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif /* evaluates ln(1+x) for x > -1. This function is especially useful for small x, where its computation is more precise than that of float_ln. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_lnxplus1(floatnum x, int digits); /* evaluates ln x (the logarithm to base e) for x > 0. Near x == 0, this function yields better results than float_lnxplus1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_ln(floatnum x, int digits); /* evaluates lg x (the logarithm to base 10) for x > 0. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_lg(floatnum x, int digits); /* evaluates lb x (the logarithm to base 2) for x > 0. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_lb(floatnum x, int digits); /* evaluates arsinh x, the inverse function of sinh. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arsinh(floatnum x, int digits); /* evaluates arcosh x, the inverse function of cosh, for x >= 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_arcosh(floatnum x, int digits); /* evaluates artanh x, the inverse function of tanh, for |x| < 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_artanh(floatnum x, int digits); /* evaluates artanh (1+x), for -2 < x <= 0. This function is especially useful, if you want to compute values near the pole at x == 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_artanhxplus1(floatnum x, int digits); /* evaluates arcosh (1+x), for x >= 0. This function is especially useful, if you want to compute values near the singularity of arcosh at x == 1. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) OutOfDomain */ char float_arcoshxplus1(floatnum x, int digits); /* evaluates exp(x) In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_exp(floatnum x, int digits); /* evaluates exp(x)-1. Use this in the neighbourhood of x == 0. In case of an error, x is set to NaN and 0 is returned. Errors: Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_expminus1(floatnum x, int digits); /* evaluates cosh(x). In case of an error, x is set to NaN and 0 is returned. Errors: Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_cosh(floatnum x, int digits); /* evaluates cosh(x) - 1. Yields better results in the neighbourhood of x == 0 than float_cosh. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_coshminus1(floatnum x, int digits); /* evaluates sinh(x). In case of an error, x is set to NaN and 0 is returned. Errors: Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_sinh(floatnum x, int digits); /* evaluates tanh(x). In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_tanh(floatnum x, int digits); /* evaluates tanh(x)-1. Yields better results for large x > 0, when tanh x approx.== 1, than float_tanh. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_tanhminus1(floatnum x, int digits); /* evaluates 10^x. No optimization is applied for integer exponents. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_power10(floatnum x, int digits); /* evaluates arctan x, yielding a result -pi/2 < result < pi/2. In case of an error, x is set to NaN and 0 is returned. Errors: NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arctan(floatnum x, int digits); /* evaluates arcsin x for -1 <= x <= 1, yielding a result -pi/2 <= result <= pi/2. In case of an error, x is set to NaN and 0 is returned. Errors: OutOfDomain NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arcsin(floatnum x, int digits); /* evaluates arccos x for -1 <= x <= 1, yielding a result 0 <= result <= pi. In case of an error, x is set to NaN and 0 is returned. Errors: OutOfDomain NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arccos(floatnum x, int digits); /* evaluates arccos (1+x) for -2 <= x <= 0, yielding a result 0 <= result <= pi. This function is more precise in the neighbourhood of x == 0 than float_arccos. In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_arccosxplus1(floatnum x, int digits); /* evaluates tan x. For extreme large x, the periodicity of tan is not recognized any more, and a FLOAT_UNSTABLE error is reported. The same holds, if x is too near to a pole of tan, more precise, if |x-0.5*n*pi| < 1e- for some n. In case of an error, x is set to NaN and 0 is returned. Errors: EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_tan(floatnum x, int digits); /* evaluates sin x. For extreme large x, the periodicity of sin is not recognized any more, and a FLOAT_UNSTABLE error is reported. In case of an error, x is set to NaN and 0 is returned. Errors: EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_sin(floatnum x, int digits); /* evaluates cos x. For extreme large x, the periodicity of sin is not recognized any more, and a FLOAT_UNSTABLE error is reported. In case of an error, x is set to NaN and 0 is returned. Errors: EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_cos(floatnum x, int digits); /* evaluates cos x - 1. In the neighbourhood of x==0, when cos x approx.== 1, this function yields better results than float_cos. For extreme large x, the periodicity of sin is not recognized any more, and a FLOAT_UNSTABLE error is reported. In case of an error, x is set to NaN and 0 is returned. Errors: Undeflow EvalUnstable NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_cosminus1(floatnum x, int digits); /* evaluates base^exponent In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow OutOfDomain (base <= 0 and most exponents) ZeroDivide ( base == 0 and exponent negative) NaNOperand InvalidPrecision (digits > maxprecision-14) */ char float_raisei(floatnum power, cfloatnum base, int exponent, int digits); /* evaluates base^exponent In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow OutOfDomain (base <= 0 and most exponents) ZeroDivide (base == 0 and exponent negative) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_raise(floatnum power, cfloatnum base, cfloatnum exponent, int digits); /* evaluates Gamma(x) = (x-1)! In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow ZeroDivide (for integers <= 0) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_gamma(floatnum x, int digits); /* evaluates ln(Gamma(x)) = ln((x-1)!) In case of an error, x is set to NaN and 0 is returned. Errors: Overflow OutOfDomain (for x <= 0) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_lngamma(floatnum x, int digits); /* evaluates x! In case of an error, x is set to NaN and 0 is returned. Errors: Underflow Overflow ZeroDivide (for integers < 0) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_factorial(floatnum x, int digits); /* evaluates gamma(x+delta)/gamma(x). If delta is a positive integer, this is the Pochhammer symbol x*(x+1)*...*(x+delta-1). The poles of the gamma function are handled appropriately. Errors: Underflow Overflow ZeroDivide (not annihilated pole in the nominator) NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_pochhammer(floatnum x, cfloatnum delta, int digits); /* evaluates erf(x). NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_erf(floatnum x, int digits); /* evaluates erfc(x). Underflow NaNOperand InvalidPrecision (digits > MATHPRECISION) */ char float_erfc(floatnum x, int digits); /* cuts off the fraction part of and complements the bits in the 2's complement representation of then. The corresponding integer of the result is stored back in . In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_not(floatnum x); /* uses the integer parts of and and builds their 2's complement representation. The resulting strings are and-ed and the corresponding integer is stored in dest. In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_and(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer parts of x and y and builds their 2's complement representation. The resulting strings are or-ed and the corresponding integer is stored in dest. In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_or(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer parts of and and builds their 2's complement representation. The resulting strings are xor-ed and the corresponding integer is stored in dest. In case of an error, is set to NaN and 0 is returned. Errors: OutOfLogicRange NaNOperand */ char float_xor(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer part of and builds its 2's complement representation as LOGICRANGE bits. The resulting bitstring is then shifted y times to the left. Shifted out bits are dropped, to the right 0 bits are fed in. The corresponding integer of the resulting bitstring is stored in . has to be an integer or an error is reported. If it is negative, this operation turns into a shift right. In case of an error, is set to NaN and 0 is returned. Errors: OutOfDomain (y not an integer) OutOfLogicRange NaNOperand */ char float_shl(floatnum dest, cfloatnum x, cfloatnum y); /* uses the integer part of and builds its 2's complement representation as LOGICRANGE bits. The resulting bitstring is then shifted y times to the right. Shifted out bits are dropped, to the left the sign bit is duplicated. The corresponding integer of the resulting bitstring is stored in . has to be an integer or an error is reported. If it is negative, this operation turns into a shift left. In case of an error, is set to NaN and 0 is returned. Errors: OutOfDomain (y not an integer) OutOfLogicRange NaNOperand */ char float_shr(floatnum dest, cfloatnum x, cfloatnum y); #ifdef __cplusplus } #endif #endif /* FLOATLOG_H */ deepin-calculator-5.7.21/3rdparty/math/floatincgamma.c000066400000000000000000000155021423020056600226510ustar00rootroot00000000000000/* floatincgamma.h: incomplete gamma function */ /* Copyright (C) 2009 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatincgamma.h" #include "floatconst.h" #include "floatcommon.h" #include "floathmath.h" /* many ideas are from a paper of Serge Winitzki, "Computing the incomplete Gamma function to arbitrary precision" */ /* The critical line of the lower incomplete gamma function lowgamma(a, z) is composed of all non-positive real 'a' along with z == 0. It cannot be continued on this line. Near this line lowgamma behaves approximately as 1. z^a/a, a not close to a negative integer 2. (z^a/a) + (-1)^k*z^h/h/k!, where -k is a negative integer very close to a and h = a + k very small If h << z the second summand in 2. becomes dominant, otherwise z^a/a is a rough estimate of lowgamma(a, z), diverging for fixed non-positive 'a* and z -> 0. Since z^a is true complex for real z < 0, lowgamma cannot be continued in the real number domain accross the critical line, except for 'a' a negative integer. reglowgammanearpole computes f(x, k, h) = x^(k-h) * [lowgamma(-k+h, x) - (-1)^k * x^h / h / k!] where k is an integer >= 0. It should only be used for |h| <= 0.5 and |x| not much bigger than 2. f is useful for computing both the lower and upper incomplete gamma function for values a, x close to the critical line. The term (-1)^k * x^h/(k!*h) subtracts the pole Gamma(-k), and, in addition, lowgamma(a, x) is regularized by the factor x^(k-h), in order to eliminate the singularity introduced by the factor z^a/a. f is real-valued even for negative x, where lowgamma is true complex. f is not continuous at a = (-2k-1)/2, k integer > 0, where the subtracted pole changes */ static void reglowgammanearpole(floatnum x, int k, cfloatnum h, int digits){ floatstruct tmp; float_create(&tmp); if (float_iszero(x) || float_getexponent(x) < -digits-3){ // tiny x, return the first element of the series: k > 0? 1/(h-k) : -x/(1+h) if (k > 0){ float_addi(x, h, -k, digits+2); float_reciprocal(x, digits+1); } else{ float_sub(&tmp, &cMinus1, h, digits+2); float_div(x, x, &tmp, digits+1); } } else{ // evaluate the series int workprec = digits+5; int i = 0; int expx = float_getexponent(x); floatstruct summand; floatstruct sum; float_create(&summand); float_create(&sum); float_copy(&tmp, &c1, EXACT); float_setzero(&sum); while (workprec > 0){ if (i != k){ float_addi(&summand, h, i-k, workprec); float_div(&summand, &tmp, &summand, workprec); float_add(&sum, &sum, &summand, digits+5); } workprec = digits - float_getexponent(&sum) + float_getexponent(&summand) + expx+5; if (workprec > 0){ float_mul(&tmp, &tmp, x, workprec); float_divi(&tmp, &tmp, -++i, workprec); } } float_move(x, &sum); // frees sum as a side-effect // float_free(&sum); float_free(&summand); } float_free(&tmp); } /* computes x^a (withExp = 0) or exp(-x)*x^a (withExp = 1) x^a[*exp(-x)] is the regulizing factor of the lower incomplete gamma function */ static char regulizingfactor(floatnum x, cfloatnum a, int digits, char withExp){ char result; floatstruct tmp; float_create(&tmp); result = float_raise(&tmp, x, a, digits); if (result && withExp){ float_neg(x); result = float_exp(x, digits) && float_mul(&tmp, &tmp, x, digits); } float_move(x, &tmp); // frees tmp as a side-effect // float_free(&tmp); return result; } /* adds (-1)^k * x^h / (h * k!) to lowgamma, accounting for the pole of the gamma function, h!= 0 */ static char addgammapole(floatnum lowgamma, cfloatnum x, int k, cfloatnum h, int digits){ // estimate the size of this summand, often it will not contribute // to the result char result = 1; float fh = float_getexponent(h) >= -37? float_asfloat(h) : 0; float xx; float fexp = aprxlog10fn(x); fexp *= fh; fexp -= aprxlog10fn(h); xx = aprxlngamma(k+1); xx *= 0.434294481903f; fexp += xx; fexp +=1; /* float fexp = (aprxlog2fn(x)*fh - aprxlog2fn(h)) * 0.301029995663981f - aprxlngamma(k+1) * 0.434294481903f + 1;*/ if (fexp > EXPMIN){ int exp = fexp; int explowgamma = float_getexponent(lowgamma); int workprec = digits + 3; if (exp < explowgamma-3) workprec = digits - explowgamma - exp -3; if (workprec > 0){ floatstruct pwr; floatstruct fct; float_create(&pwr); float_create(&fct); float_setinteger(&fct, k); result = float_raise(&pwr, x, h, workprec) && float_factorial(&fct, workprec) && float_div(&pwr, &pwr, &fct, workprec) && float_div(&pwr, &pwr, h, workprec); if ((k & 1) != 0) float_neg(&pwr); result = result && float_add(lowgamma, lowgamma, &pwr, digits+2); float_free(&fct); float_free(&pwr); } } return result; } /* for 0.5 > a and ln Gamma(-a) / ln 10 < 2 * digits */ static char lowgammanearpole(floatnum x, cfloatnum a, int digits){ int k = float_getexponent(a); char result; floatstruct h; floatstruct lowgamma; floatstruct factor; float_create(&h); float_create(&lowgamma); float_create(&factor); float_sub(&h, a, &c1Div2, k < -1? 2 : k+3); k = -float_asinteger(&h); float_addi(&h, a, k, digits+2); float_copy(&lowgamma, x, digits+2); float_copy(&factor, x, digits+3); reglowgammanearpole(&lowgamma, k, &h, digits); result = regulizingfactor(&factor, a, digits, 0) && float_mul(&lowgamma, &lowgamma, &factor, digits+2) && addgammapole(&lowgamma, x, k, &h, digits); float_move(x, &lowgamma); // frees lowgamma float_free(&lowgamma); float_free(&h); return result; } void testincgamma(floatnum x, cfloatnum a, int digits){ lowgammanearpole(x, a, digits); } deepin-calculator-5.7.21/3rdparty/math/floatincgamma.h000066400000000000000000000024641423020056600226610ustar00rootroot00000000000000/* floatincgamma.h: incomplete gamma function */ /* Copyright (C) 2009 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATINCGAMMA_H # define FLOATINCGAMMA_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif void testincgamma(floatnum x, cfloatnum a, int digits); #ifdef __cplusplus } #endif #endif /* FLOATINCGAMMA_H */ deepin-calculator-5.7.21/3rdparty/math/floatio.c000066400000000000000000000674511423020056600215160ustar00rootroot00000000000000/* floatio.c: low level conversion, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatio.h" #include "floatlong.h" #include typedef enum { NmbNormal, NmbSpecial, NmbBufferOverflow } NmbType; /* Besides the regular bases 2, 8, 10 and 16, there are three others (IO_BASE_DEFAULT, IO_BASE_NAN and IO_BASE_ZERO) used internally to mark special situations. They are called pseudo-bases, because you cannot use them as parameter to floatnum functions */ static char _isspecial( signed char base) { switch (base) { case IO_BASE_NAN: case IO_BASE_ZERO: case IO_BASE_DEFAULT: return 1; } return 0; } /*-------------- ASCII based functions -------------*/ static char emptystr = '\0'; /* sort of alias for (strlen == 0). I don't have access to a POSIX manual, so I don't know how strlen reacts on NULL.*/ static char _isempty( const char* p) { return p == NULL || *p == '\0'; } /* copies the null-terminated ASCIIZ string src into the buffer dest. If the buffer is too small to hold src, 0 is returned */ static char _setstr( p_buffer dest, const char* src) { if (dest->sz > 0) { if (src == NULL) *(dest->buf) = '\0'; else if (dest->sz < (int)strlen(src) + 1) return 0; else strcpy(dest->buf, src); } return 1; } /* looks, whether dest begins with the substring in pattern */ static int _match( const char* dest, const char* pattern) { int lg; if (_isempty(dest) || _isempty(pattern)) return 0; lg = strlen(pattern); return strncmp(dest, pattern, lg) == 0? lg : 0; } /* converts an ASCII encoded hexagesimal digit a corresponding value < 16 */ char _ascii2digit( char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return (c - 'A') + 10; if (c >= 'a' && c <= 'f') return (c - 'a') + 10; return NO_DIGIT; } static char hexdigits[] = "0123456789ABCDEF"; /* converts a value 0 <=x < 16 into a hexdigit */ char _digit2ascii( int value) { return hexdigits[value]; } /* advances the pointer buf until it points to the first character not being a valid digit of base base. The return pointer is the initial value of buf, or NULL if no digit was found */ static const char* _scandigits( const char** buf, char base) { const char* p; const char* result; result = *buf; p = result - 1; while (_ascii2digit(*++p) < base); *buf = p; return p == result? NULL : result; } /*-------------------- t_seq_desc ---------------*/ /* returns the offset6 of the last significant digit */ static int _ofslastnz( p_seq_desc n) { return n->digits - n->trailing0 - 1; } /* number of significant digits in a number sequence */ int _significantdigits( p_seq_desc n) { return n->digits - n->leadingSignDigits - n->trailing0; } /* number of digits without leading zeros in a sequence. If the sequence describes an integer, these are the digits of this integer */ static int _intdigits( p_seq_desc n) { return n->digits - n->leadingSignDigits; } /* has a sequence significant digits? */ static char _iszero( p_seq_desc n) { return _significantdigits(n) == 0; } /* returns a digit from an ASCIIZ string containing digits only */ static char _getseqdigit( int ofs, p_seq_desc n) { if (ofs < 0 || ofs > _ofslastnz(n)) return 0; return _ascii2digit(*((char*)(n->param) + ofs)); } /* returns a digit from an ASCIIZ string containing digits only, but complements them */ static char _getcmpldigit( int ofs, p_seq_desc n) { int lastnz; char c; lastnz = _ofslastnz(n); if (ofs > lastnz) return 0; c = n->base - _getseqdigit(ofs, n) - (ofs == lastnz? 0 : 1); return c == n->base? 1 : c; } /* initializes a structure used for copying digit sequences */ static void _clearint( p_ext_seq_desc n) { n->seq.leadingSignDigits = 0; n->seq.digits = 0; n->seq.trailing0 = 0; n->seq.base = IO_BASE_ZERO; n->seq.param = NULL; n->getdigit = _getseqdigit; } /*---------------------- t_[io]token ------------------*/ /* initializes a structure used for describing a floating point number */ void _clearnumber( p_number_desc n) { n->prefix.sign = IO_SIGN_NONE; n->prefix.base = IO_BASE_NAN; _clearint(&n->intpart); _clearint(&n->fracpart); n->exp = 0; } /* creates a sequence descriptor from an ASCII digit sequence, not necessarily terminated by \0. After maxdigits digits, all following digits are assumed to be zero, regardless of their true value. */ static void _str2seq( p_ext_seq_desc n, const char* digits, int maxdigits, signed char base, char complement) { /* pre: n has to be initialized to describe a zero */ const char* p; const char* pz; char leadingdigit; unsigned char c; leadingdigit = 0; if (complement) { leadingdigit = base - 1; n->getdigit = _getcmpldigit; } p = digits; /* skip sign digits (usually 0, in complement mode F, 7 or 1 */ for (; _ascii2digit(*p) == leadingdigit; ++p); n->seq.leadingSignDigits = p - digits; /* pz is pointer to first trailing zero */ pz = p; for (; (c = _ascii2digit(*(p++))) < base;) { if (--maxdigits >= 0 && c != 0) pz = p; } n->seq.trailing0 = p - pz - 1; n->seq.digits = p - digits - 1; n->seq.param = (void*)digits; if (complement || _significantdigits(&n->seq) != 0) n->seq.base = base; } /* copy count digits (leading zeros included) from the digit sequence described by n to an ASCII buffer */ static Error _seq2str( p_buffer dest, int count, p_ext_seq_desc n) { int ofs; char* buf; ofs = 0; if (count >= dest->sz) return IOBufferOverflow; buf = dest->buf; for (; ofs < count; ++ofs) *(buf++) = _digit2ascii(n->getdigit(ofs, &n->seq)); *(buf) = '\0'; return Success; } /* copy all digits (leading zeros included) from the digit sequence described by n to an ASCII buffer, but complement the sequence before writing to the buffer */ static Error _cmplseq2str( p_buffer dest, p_ext_seq_desc n) { int bound; int ofs; int lastnz; char* buf; char c; buf = dest->buf; bound = _intdigits(&n->seq); if (bound + 1 > dest->sz) return IOBufferOverflow; lastnz = _ofslastnz(&n->seq); for (ofs = -1; ++ofs < lastnz;) { c = n->seq.base - n->getdigit(ofs, &n->seq) - 1; *(buf++) = _digit2ascii(c); } c = n->getdigit(ofs, &n->seq); if (c != 1 || _significantdigits(&n->seq) != 1) *(buf++) = _digit2ascii(n->seq.base - c); else { --bound; --ofs; } for (; ++ofs < bound;) *(buf++) = _digit2ascii(0); *(buf) = '\0'; return Success; } /* create a descriptor from a sequence of digits, assuming the sequence is an integer */ static Error str2int( p_ext_seq_desc n, const char* value, p_prefix prefix, int maxdigits) { char complement; if (prefix->base == IO_BASE_NAN) return IONoBase; complement = prefix->sign == IO_SIGN_COMPLEMENT; if (complement) { n->getdigit = _getcmpldigit; /* necessary, because when value is empty, base = IO_BASE_ZERO */ n->seq.base = prefix->base; } if (value) _str2seq(n, value, maxdigits, prefix->base, complement); return Success; } /* if base describes a special value (0 or NaN), the normal conversion routines fail. This routine creates special output values for these bases, and return nmbBufferOverflow: if the buffer is too small nmbSpecial: if it created output nmbNormal: if base stands for a usual number that the normal routines should deal with */ static NmbType _special2str( p_otokens tokens, signed char base) { const char* p; switch (base) { case IO_BASE_ZERO: p = "0"; break; case IO_BASE_NAN: p = "NaN"; break; default: return NmbNormal; } return _setstr(&tokens->intpart, p)? NmbSpecial : NmbBufferOverflow; } /* create an ASCIIZ sequence of the integer part, set sign and base. */ static Error int2str( p_otokens tokens, p_number_desc n, char complement) { tokens->sign = n->prefix.sign; tokens->base = n->prefix.base; switch (_special2str(tokens, n->prefix.base)) { case NmbSpecial: return Success; case NmbBufferOverflow: return IOBufferOverflow; default: break; /* NmbNormal */ } /* no special encodings */ if (complement) return _cmplseq2str(&tokens->intpart, &n->intpart); return _seq2str(&tokens->intpart, _intdigits(&n->intpart.seq), &n->intpart); } /* do some sanity checks, create descriptors of integer and fraction part in tokens, set sign and base */ static Error str2fixp( p_number_desc n, p_itokens tokens) { Error result; int maxdigits; maxdigits = tokens->maxdigits; n->prefix.base = tokens->base; n->prefix.sign = tokens->sign; if (tokens->sign == IO_SIGN_COMPLEMENT && (!_isempty(tokens->fracpart) || tokens->exp)) return IOInvalidComplement; result = str2int(&n->intpart, tokens->intpart, &n->prefix, maxdigits); if (_isspecial(n->prefix.base)) return result; if (!_isempty(tokens->fracpart)) _str2seq(&n->fracpart, tokens->fracpart, maxdigits - _intdigits(&n->intpart.seq), n->prefix.base, 0); if (n->prefix.sign != IO_SIGN_COMPLEMENT && n->intpart.seq.digits + n->fracpart.seq.digits == 0) return IONoSignificand; if (n->prefix.sign != IO_SIGN_COMPLEMENT && _iszero(&n->intpart.seq) && _iszero(&n->fracpart.seq)) n->prefix.base = IO_BASE_ZERO; return Success; } /* convert integer and fraction part into ASCIIZ sequences */ static Error fixp2str( p_otokens tokens, p_number_desc n, int scale) { Error result; result = int2str(tokens, n, n->prefix.sign == IO_SIGN_COMPLEMENT); if (result != Success || _isspecial(n->prefix.base)) return result; return _seq2str(&tokens->fracpart, scale, &n->fracpart); } /* create a descriptor from the digit sequence of the exponent */ static Error _exp2desc( p_number_desc n, p_itokens tokens) { if (tokens->expsign != IO_SIGN_NONE || tokens->exp) { unsigned upperLimit; signed char sign; switch (tokens->base) { case 2 : upperLimit = BITS_IN_BINEXP - 1; break; case 8 : upperLimit = BITS_IN_OCTEXP - 1; break; case 16: upperLimit = BITS_IN_HEXEXP - 1; break; default: upperLimit = BITS_IN_EXP - 1; break; } upperLimit = (1 << (upperLimit)) - 1; sign = tokens->expsign; switch (sign) { case IO_SIGN_COMPLEMENT: return IOBadExp; case IO_SIGN_NONE: sign = IO_SIGN_PLUS; break; case IO_SIGN_MINUS: ++upperLimit; break; default:; } if (tokens->exp > upperLimit) return IOExpOverflow; if (sign < 0) n->exp = -(int)(tokens->exp); else n->exp = tokens->exp; } return Success; } /* create a descriptor from the floating point number given in tokens */ Error str2desc( p_number_desc n, p_itokens tokens) { Error result; _clearnumber(n); result = str2fixp(n, tokens); if (result == Success) result = _exp2desc(n, tokens); if (result != Success) n->prefix.base = IO_BASE_NAN; return result; } Error desc2str( p_otokens tokens, p_number_desc n, int scale) { Error result; result = fixp2str(tokens, n, scale); if (result != Success || _isspecial(n->prefix.base)) return result; tokens->exp = n->exp; return Success; } Error exp2str( p_buffer dest, int exp, char base) { char tmp[BITS_IN_EXP + 3]; int idx = 0; int di = 0; if (exp < 0) exp = -exp; while (exp != 0) { tmp[idx++] = hexdigits[exp % base]; exp /= base; } if (idx == 0) tmp[idx++] = hexdigits[0]; if (dest->sz <= idx) return IOBufferOverflow; for (; --idx >= 0;) dest->buf[di++] = tmp[idx]; dest->buf[di] = 0; return Success; } /* ***************** additional stuff, just to get started *************/ static t_ioparams stdioparams[4] = { {10, 10, '.', "0d", "Ee(", " )", "", DECPRECISION}, //edit 20200805 jingzhou for bug--41371,替换所有进制科学计数法标志的大小写 {16, 10, '.', "0x", "Hh(", " )", "sF", HEXPRECISION}, {2, 10, '.', "0b", "Bb(", " )", "s1", BINPRECISION}, {8, 10, '.', "0o", "OoC(", " )", "s7", OCTPRECISION} }; enum {idzero, idx10, idx16, idx2, idx8, idxcount}; static t_ioparams ioparams[idxcount] = { {IO_BASE_ZERO, IO_BASE_ZERO, '\0', "", "", "", "", 0x7FFFFFFF}, {IO_BASE_DEFAULT, IO_BASE_DEFAULT, '\0', "", "", "", "", 0}, {IO_BASE_DEFAULT, IO_BASE_DEFAULT, '\0', "", "", "", "", 0}, {IO_BASE_DEFAULT, IO_BASE_DEFAULT, '\0', "", "", "", "", 0}, {IO_BASE_DEFAULT, IO_BASE_DEFAULT, '\0', "", "", "", "", 0} }; static p_ioparams _defaultbase = NULL; static char _isvalidioparams( p_ioparams param) { return param != NULL && param->base != IO_BASE_DEFAULT; } static void _invalidateioparams( p_ioparams param) { if (param) param->base = IO_BASE_DEFAULT; } p_ioparams _base2ioparams( signed char base) { int idx; switch (base) { case 10: idx = idx10; break; case 16: idx = idx16; break; case 2: idx = idx2; break; case 8: idx = idx8; break; case IO_BASE_ZERO: idx = idzero; break; default: return NULL; } return &ioparams[idx]; } char setioparams( p_ioparams params) { p_ioparams dest; if (!_isvalidioparams(params)) return 0; dest = _base2ioparams(params->base); if (dest == NULL) return 0; *dest = *params; return 1; } char delioparams( signed char base) { p_ioparams dest; dest = _base2ioparams(base); _invalidateioparams(dest); return dest != NULL; } p_ioparams getioparams( signed char base) { p_ioparams result; if (base == IO_BASE_DEFAULT) return _defaultbase; result = _base2ioparams(base); return _isvalidioparams(result)? result : NULL; } static signed char _getdefaultbase() { p_ioparams param; param = getioparams(IO_BASE_DEFAULT); return param == NULL? IO_BASE_DEFAULT : param->base; } signed char setdefaultbase( signed char base) { char result; result = _getdefaultbase(); _defaultbase = _base2ioparams(base); return result; } void float_stdconvert() { int i; for (i = 0; i < 4; ++i) setioparams(&stdioparams[i]); setdefaultbase(10); } const char* basePrefix(char base) { return getioparams(base)->basetag; } static signed char _parsesign( const char** buf) { signed char result; result = IO_SIGN_NONE; if (!_isempty(*buf)) switch (**buf) { case '-': result = IO_SIGN_MINUS; break; case '+': result = IO_SIGN_PLUS; } if (result != IO_SIGN_NONE) (*buf)++; return result; } static signed char _parsebase( const char** buf, char defaultbase) { signed char base; int lg, i; lg = 0; base = IO_BASE_DEFAULT; if (!_isempty(*buf)) for (i = 0; i < idxcount; ++i) { lg = _match(*buf, ioparams[i].basetag); if (lg > 0) { base = ioparams[i].base; break; } } *buf += lg; return base == IO_BASE_DEFAULT? defaultbase : base; } static char _parsecmpl( const char** buf, char base) { int lg; p_ioparams param; param = getioparams(base); lg = 0; if (_isvalidioparams(param)) lg = _match(*buf, param->cmpltag); *buf += lg; return lg > 0; } Error parse( p_itokens tokens, const char** buffer) { p_ioparams params; const char* p; char* expchar; signed char base; int idx; char dot; char* expbegin; char* expend; tokens->fracpart = NULL; tokens->exp = 0; tokens->expsign = IO_SIGN_NONE; tokens->maxdigits = 0; dot = '.'; expbegin = "("; expend = ")"; p = *buffer; tokens->sign = _parsesign(&p); base = _parsebase(&p, _getdefaultbase()); params = getioparams(base); if (params != NULL) { dot = params->dot; if (params->expbegin != NULL) expbegin = params->expbegin; if (params->expend != NULL) expend = params->expend; tokens->maxdigits = params->maxdigits; } else base = 10; tokens->base = base; if (tokens->maxdigits <= 0) tokens->maxdigits = DECPRECISION; if (_parsecmpl(&p, tokens->base)) { if (tokens->sign != IO_SIGN_NONE) return IOInvalidComplement; tokens->sign = IO_SIGN_COMPLEMENT; } tokens->intpart = _scandigits(&p, base); if (*p == dot) { ++p; tokens->fracpart = _scandigits(&p, base); } if (!tokens->intpart && !tokens->fracpart && tokens->sign != IO_SIGN_COMPLEMENT) return IONoSignificand; expchar = strchr(expbegin, *p); if (!_isempty(expchar)) { const char* expptr; int i; int e = 0; int expbase; ++p; idx = expchar - expbegin; tokens->expsign = _parsesign(&p); expbase = _parsebase(&p, base); expptr = _scandigits(&p, expbase); if (!expptr || (*(expend + idx) != ' ' && *(expend + idx) != *p)) return IOBadExp; for (i = 0; i < p-expptr; ++i) { if (!_checkmul(&e, expbase) || !_checkadd(&e, _ascii2digit(*(expptr+i)))) return IOExpOverflow; } tokens->exp = e; } *buffer = p; return Success; } static char _decodesign( signed char s) { switch (s) { case IO_SIGN_PLUS: return '+'; case IO_SIGN_MINUS: return '-'; } return '\0'; } static char* _decodebase( signed char base) { p_ioparams param; param = getioparams(base); if (!_isvalidioparams(param) || _isempty(param->basetag)) return &emptystr; return param->basetag; } static char* _decodecomplement( signed char sign, signed char base) { p_ioparams param; param = getioparams(base); if (sign != IO_SIGN_COMPLEMENT || !_isvalidioparams(param) || _isempty(param->cmpltag)) return &emptystr; return param->cmpltag; } static void _cattoken( char* buf, char* token, char enable) { if (enable && !_isempty(token)) strcat(buf, token); } int cattokens( char* buf, int bufsz, p_otokens tokens, signed char expbase, unsigned flags) { int sz; int fraclg; p_ioparams ioparams; char* expbegin; char* expend; char* cmpltag; char* basetag; char* expbasetag; signed char base; char dot; char cbuf[2]; char printsign; char printbasetag; char printcmpl; char printleading0; char printdot; char printexp; char printexpsign = 0; char printexpbase = 0; char printexpbegin; char printexpend; char exp[BITS_IN_BINEXP+2]; t_buffer expBuf; expBuf.sz = sizeof(exp); expBuf.buf = exp; cbuf[1] = '\0'; fraclg = 0; if (!_isempty(tokens->fracpart.buf)) { fraclg = strlen(tokens->fracpart.buf) - 1; if ((flags & IO_FLAG_SUPPRESS_TRL_ZERO) != 0) while (fraclg >= 0 && tokens->fracpart.buf[fraclg] == '0') --fraclg; ++fraclg; } ioparams = getioparams(IO_BASE_DEFAULT); base = tokens->base; printbasetag = !_isspecial(base) && (flags & IO_FLAG_SUPPRESS_BASETAG) == 0 && (ioparams == NULL || ioparams->base != base); ioparams = getioparams(base); basetag = _decodebase(base); cmpltag = _decodecomplement(tokens->sign, base); expbasetag = NULL; if (base == IO_BASE_DEFAULT) flags |= IO_FLAG_SUPPRESS_DOT | IO_FLAG_SUPPRESS_LDG_ZERO; if ((flags & IO_FLAG_SHOW_BASE) != 0) printbasetag = 1; printcmpl = tokens->sign == IO_SIGN_COMPLEMENT && (flags & IO_FLAG_SUPPRESS_CMPL) == 0; printsign = !printcmpl && tokens->sign != IO_SIGN_NONE && (tokens->sign != IO_SIGN_PLUS || (flags & IO_FLAG_SUPPRESS_PLUS) == 0); printleading0 = _isempty(tokens->intpart.buf) && (flags & IO_FLAG_SUPPRESS_LDG_ZERO) == 0; printdot = fraclg > 0 || (flags & IO_FLAG_SUPPRESS_DOT) == 0; printexp = base != IO_BASE_NAN && base != IO_BASE_ZERO && ((flags & IO_FLAG_SUPPRESS_EXPZERO) == 0 || tokens->exp != 0); if (printexp) { if (expbase < 2) expbase = ioparams->expbase; expbasetag = _decodebase(expbase); // printexpsign = tokens->exp > 0 || tokens->exp < 0 // || (flags & IO_FLAG_SUPPRESS_EXPPLUS) == 0; // edit for bug-18136,add exp > 0 printexpsign = 1; //edit for bug-39849,0需要显示为+0 printexpbase = expbasetag != NULL && (flags & IO_FLAG_SUPPRESS_EXPBASE) == 0 && (_isempty(basetag) || strcmp(basetag, expbasetag) != 0); if ((flags & IO_FLAG_SHOW_EXPBASE) != 0) printexpbase = 1; } dot = '.'; expbegin = "("; expend = ")"; if (ioparams != NULL) { dot = ioparams->dot; expbegin = ioparams->expbegin; expend = ioparams->expend; } printexpbegin = *expbegin != '\0'; printexpend = *expend != '\0' && *expend != ' '; sz = 1; if (printsign) sz += 1; if (printbasetag) sz += strlen(basetag); if (printcmpl) sz += strlen(cmpltag); if (printleading0) ++sz; if (!_isempty(tokens->intpart.buf)) sz += strlen(tokens->intpart.buf); if (printdot) sz += 1; sz += fraclg; if (printexp) { exp2str(&expBuf, tokens->exp, expbase); if (printexpbegin) ++sz; if (printexpsign) sz += 1; if (printexpbase) sz += strlen(expbasetag); sz += strlen(expBuf.buf); if (printexpend) ++sz; } if (sz <= bufsz) { *buf = '\0'; cbuf[0] = _decodesign(tokens->sign); _cattoken(buf, cbuf, printsign); _cattoken(buf, basetag, printbasetag); _cattoken(buf, cmpltag, printcmpl); _cattoken(buf, "0", printleading0); _cattoken(buf, tokens->intpart.buf, 1); cbuf[0] = dot; _cattoken(buf, cbuf, printdot); if (fraclg > 0) strncat(buf, tokens->fracpart.buf, fraclg); if (printexp) { cbuf[0] = *expbegin; _cattoken(buf, cbuf, printexpbegin); cbuf[0] = _decodesign(tokens->exp < 0? -1:1); _cattoken(buf, cbuf, printexpsign); _cattoken(buf, expbasetag, printexpbase); strcat(buf, expBuf.buf); cbuf[0] = *expend; _cattoken(buf, cbuf, printexpend); } } return sz; } int cattokensbin(char *buf, int bufsz, p_otokens tokens, signed char expbase, unsigned flags, int bitlength, signed char iscut) { int sz; int fraclg; int comlength = 0; p_ioparams ioparams; char* expbegin; char* expend; // char* cmpltag = ""; char* basetag; char* expbasetag; signed char base; char dot; char cbuf[2]; char printsign; char printbasetag; char printcmpl; char printleading0; char printdot; char printexp; char printexpsign = 0; char printexpbase = 0; char printexpbegin; char printexpend; char exp[BITS_IN_BINEXP+2]; t_buffer expBuf; expBuf.sz = sizeof(exp); expBuf.buf = exp; cbuf[1] = '\0'; fraclg = 0; if (!_isempty(tokens->fracpart.buf)) { fraclg = strlen(tokens->fracpart.buf) - 1; if ((flags & IO_FLAG_SUPPRESS_TRL_ZERO) != 0) while (fraclg >= 0 && tokens->fracpart.buf[fraclg] == '0') --fraclg; ++fraclg; } ioparams = getioparams(IO_BASE_DEFAULT); base = tokens->base; printbasetag = !_isspecial(base) && (flags & IO_FLAG_SUPPRESS_BASETAG) == 0 && (ioparams == NULL || ioparams->base != base); ioparams = getioparams(base); basetag = _decodebase(base); comlength = bitlength - strlen(tokens->intpart.buf); if(comlength <=0) { comlength = 65; } char cmpltag[comlength + 1]; if(comlength >=0) { memset(cmpltag,0,comlength); } // cmpltag = _decodecomplement(tokens->sign, base); expbasetag = NULL; if (base == IO_BASE_DEFAULT) flags |= IO_FLAG_SUPPRESS_DOT | IO_FLAG_SUPPRESS_LDG_ZERO; if ((flags & IO_FLAG_SHOW_BASE) != 0) printbasetag = 1; printcmpl = tokens->sign == IO_SIGN_COMPLEMENT && (flags & IO_FLAG_SUPPRESS_CMPL) == 0 && (comlength < 65); printsign = !printcmpl && tokens->sign != IO_SIGN_NONE && (tokens->sign != IO_SIGN_PLUS || (flags & IO_FLAG_SUPPRESS_PLUS) == 0); printleading0 = _isempty(tokens->intpart.buf) && (flags & IO_FLAG_SUPPRESS_LDG_ZERO) == 0 && (comlength != bitlength); printdot = fraclg > 0 || (flags & IO_FLAG_SUPPRESS_DOT) == 0; printexp = base != IO_BASE_NAN && base != IO_BASE_ZERO && ((flags & IO_FLAG_SUPPRESS_EXPZERO) == 0 || tokens->exp != 0); if (printexp) { if (expbase < 2) expbase = ioparams->expbase; expbasetag = _decodebase(expbase); // printexpsign = tokens->exp > 0 || tokens->exp < 0 // || (flags & IO_FLAG_SUPPRESS_EXPPLUS) == 0; // edit for bug-18136,add exp > 0 printexpsign = 1; //edit for bug-39849,0需要显示为+0 printexpbase = expbasetag != NULL && (flags & IO_FLAG_SUPPRESS_EXPBASE) == 0 && (_isempty(basetag) || strcmp(basetag, expbasetag) != 0); if ((flags & IO_FLAG_SHOW_EXPBASE) != 0) printexpbase = 1; } dot = '.'; expbegin = "("; expend = ")"; if (ioparams != NULL) { dot = ioparams->dot; expbegin = ioparams->expbegin; expend = ioparams->expend; } printexpbegin = *expbegin != '\0'; printexpend = *expend != '\0' && *expend != ' '; sz = 1; if (printsign) sz += 1; if (printbasetag) sz += strlen(basetag); if (printcmpl) { for (int i = 0;i < comlength;i++) { strcat(cmpltag, "1"); } sz += comlength; } if (printleading0) ++sz; char cutnum[bitlength]; memset(cutnum,0,bitlength); int cut = 0; if (!_isempty(tokens->intpart.buf)) { if(bitlength < strlen(tokens->intpart.buf) && iscut > 0) { cut = 1; strncpy(cutnum,tokens->intpart.buf + (strlen(tokens->intpart.buf) - bitlength),bitlength); sz += bitlength; } else { sz += strlen(tokens->intpart.buf); } } if (printdot) sz += 1; sz += fraclg; if (printexp) { exp2str(&expBuf, tokens->exp, expbase); if (printexpbegin) ++sz; if (printexpsign) sz += 1; if (printexpbase) sz += strlen(expbasetag); sz += strlen(expBuf.buf); if (printexpend) ++sz; } if (sz <= bufsz) { *buf = '\0'; cbuf[0] = _decodesign(tokens->sign); _cattoken(buf, cbuf, printsign); _cattoken(buf, basetag, printbasetag); if(printcmpl > 0) strncat(buf, cmpltag, comlength); _cattoken(buf, "0", printleading0); if(cut == 0) _cattoken(buf, tokens->intpart.buf, 1); else strncat(buf, cutnum, bitlength); cbuf[0] = dot; _cattoken(buf, cbuf, printdot); if (fraclg > 0) strncat(buf, tokens->fracpart.buf, fraclg); if (printexp) { cbuf[0] = *expbegin; _cattoken(buf, cbuf, printexpbegin); cbuf[0] = _decodesign(tokens->exp < 0? -1:1); _cattoken(buf, cbuf, printexpsign); _cattoken(buf, expbasetag, printexpbase); strcat(buf, expBuf.buf); cbuf[0] = *expend; _cattoken(buf, cbuf, printexpend); } } return sz; } deepin-calculator-5.7.21/3rdparty/math/floatio.h000066400000000000000000000137401423020056600215130ustar00rootroot00000000000000/* floatio.h: low level conversion, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "../core/errors.h" #ifndef FLOATIO_H # define FLOATIO_H #define NO_DIGIT 0x7F #define IO_BASE_ZERO 1 #define IO_BASE_NAN 0 #define IO_BASE_DEFAULT (-1) #define IO_SIGN_PLUS 1 #define IO_SIGN_NONE 0 #define IO_SIGN_MINUS (-1) #define IO_SIGN_COMPLEMENT (-2) #define IO_FLAG_SUPPRESS_PLUS 0x001 #define IO_FLAG_SUPPRESS_BASETAG 0x002 #define IO_FLAG_SUPPRESS_CMPL 0x004 #define IO_FLAG_SUPPRESS_LDG_ZERO 0x008 #define IO_FLAG_SUPPRESS_TRL_ZERO 0x010 #define IO_FLAG_SUPPRESS_DOT 0x020 #define IO_FLAG_SUPPRESS_EXPPLUS 0x040 #define IO_FLAG_SUPPRESS_EXPBASE 0x080 #define IO_FLAG_SUPPRESS_EXPZERO 0x100 #define IO_FLAG_SHOW_BASE 0x200 #define IO_FLAG_SHOW_EXPBASE 0x400 #ifdef __cplusplus extern "C" { #endif typedef struct { int sz; char *buf; } t_buffer; typedef t_buffer *p_buffer; /* t_seq_desc describes the format of a sequence of digits. leadingSignDigits are the count of leading zeros (or for two's complement, F's, 7's or 1's), trailing0 are the number of zeros at the end of the sequence and digits are the total count of digits in the sequence. If a sequence contains only zeros, in some contexts, they are counted as sign digits, in others they are trailing zeros. base is the number base the sequence is coded in (one of 2, 8, 10 or 16) and is reserved for callback. */ typedef struct { int leadingSignDigits; int trailing0; int digits; int base; void *param; } t_seq_desc; typedef t_seq_desc *p_seq_desc; /* the number of digits not being a leading sign digit or a trailing zero */ int _significantdigits(p_seq_desc n); /* sequences of digits can be encoded in various ways (ASCII, bc_num style, packed and so on). In order to access a single digit, a getter has to be supplied for each encoding. This is the common interface of these getters. ofs is the index of the digit in the sequence, the first (most significant) having an index 0. The getter should return a sign digit (mostly 0) for negative indices and 0 for indices greator or equal to the length of the sequence. Instances of t_getdigit usually access the param field of n to find the data structure where the digits are encoded in */ typedef char (*t_getdigit)(int ofs, p_seq_desc param); /* list of tokens that are created in an output process. Instead of returning a single ASCII string, all parts of a number are kept in separate places, so a post-processor can reorder or beautify them */ typedef struct { signed char sign; signed char base; t_buffer intpart; t_buffer fracpart; int exp; } t_otokens; typedef t_otokens *p_otokens; /* list of tokens that are sources in an input process. Instead of using a single ASCII string, all parts of a number are kept in separate places, stripped off all grammar related information. The tokens need not be 0 terminated, as long as the token is delimited by something not mistaken as a part of it. */ typedef struct { signed char sign; signed char base; const char *intpart; const char *fracpart; signed char expsign; unsigned exp; unsigned maxdigits; } t_itokens; typedef t_itokens *p_itokens; typedef struct { t_seq_desc seq; t_getdigit getdigit; } t_ext_seq_desc; typedef t_ext_seq_desc *p_ext_seq_desc; typedef struct { signed char sign; signed char base; } t_prefix; typedef t_prefix *p_prefix; typedef struct { t_prefix prefix; t_ext_seq_desc intpart; t_ext_seq_desc fracpart; int exp; } t_number_desc; typedef t_number_desc *p_number_desc; void _clearnumber(p_number_desc n); Error str2desc(p_number_desc n, p_itokens tokens); Error desc2str(p_otokens tokens, p_number_desc n, int scale); Error exp2str(p_buffer dest, int exp, char base); /*------------ additional stuff ------------------*/ /* t_ioparams is a data structure that contains all necessary information to convert an ASCII character encoded number into a t_token and vice versa. Most information is grammar related like dot, basetag and so on. Others like maxdigits describe general limits of floatnums. */ typedef struct { signed char base; signed char expbase; char dot; char *basetag; char *expbegin; char *expend; char *cmpltag; unsigned maxdigits; } t_ioparams; typedef t_ioparams *p_ioparams; const char *basePrefix(char base); Error parse(p_itokens tokens, const char **buf); int cattokens(char *buf, int bufsz, p_otokens tokens, signed char expbase, unsigned flags); int cattokensbin(char *buf, int bufsz, p_otokens tokens, signed char expbase, unsigned flags, int bitlength, signed char iscut); void float_stdconvert(); char setioparams(p_ioparams params); char delioparams(signed char base); p_ioparams getioparams(signed char base); signed char setdefaultbase(signed char base); #ifdef __cplusplus } #endif #endif /* FLOATIO_H */ deepin-calculator-5.7.21/3rdparty/math/floatipower.c000066400000000000000000000064451423020056600224100ustar00rootroot00000000000000/* floatpower.c: power operation, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatipower.h" #include "floatconst.h" #include "floatcommon.h" #include "floatlong.h" /* for radix conversion, we need to get a result, even though it might slightly overflow or underflow. That is why we keep the exponent separate. For limited exponents (< 1024) the relative error for a 100 digit calculation is < 1e-99 x != 0 */ char _raiseposi( floatnum x, int* expx, unsigned exponent, int digits) { int exppwr, extra; floatstruct pwr; float_create(&pwr); float_move(&pwr, x); exppwr = float_getexponent(&pwr); float_setexponent(&pwr, 0); if ((exponent & 1) != 0) { float_copy(x, &pwr, digits+1); *expx = exppwr; } else { float_copy(x, &c1, EXACT); *expx = 0; } extra = _findfirstbit(exponent)/3+1; while((exponent >>= 1) != 0) { float_mul(&pwr, &pwr, &pwr, digits+extra); if (!_checkadd(&exppwr, exppwr)) break; exppwr += float_getexponent(&pwr); float_setexponent(&pwr, 0); if((exponent & 1) != 0) { float_mul(x, x, &pwr, digits+extra); *expx += exppwr + float_getexponent(x); float_setexponent(x, 0); } } float_free(&pwr); return exponent == 0; } char _raiseposi_( floatnum x, unsigned exponent, int digits) { int exp; char result; result = _raiseposi(x, &exp, exponent, digits); float_setexponent(x, exp); return result; } /* raises a non-zero x to the exponent-th power */ char _raisei( floatnum x, int exponent, int digits) { int expx; signed char sgn; char negexp; switch (exponent) { case 0: float_copy(x, &c1, EXACT); /* fall through */ case 1: return 1; } if (float_getlength(x) == 1 && float_getdigit(x, 0) == 1) { /* power of ten */ if (!_checkmul(&exponent, float_getexponent(x)) || exponent < EXPMIN || exponent > EXPMAX) return 0; sgn = float_getsign(x) < 0? -(exponent & 1) : 1; float_setexponent(x, exponent); float_setsign(x, sgn); return 1; } negexp = exponent < 0; if (negexp) exponent = -exponent; if (!_raiseposi(x, &expx, exponent, digits) || expx < EXPMIN || expx > EXPMAX) return 0; float_setexponent(x, expx); return negexp? float_reciprocal(x, digits) : 1; } deepin-calculator-5.7.21/3rdparty/math/floatipower.h000066400000000000000000000026731423020056600224140ustar00rootroot00000000000000/* floatpower.h: power operation, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATIPOWER_H # define FLOATIPOWER_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _raiseposi_(floatnum x, unsigned exponent, int digits); char _raiseposi(floatnum x, int* expx, unsigned exponent, int digits); char _raisei(floatnum x, int exponent, int digits); #ifdef __cplusplus } #endif #endif /* FLOATIPOWER_H */ deepin-calculator-5.7.21/3rdparty/math/floatlog.c000066400000000000000000000304261423020056600216600ustar00rootroot00000000000000/* floatlog.c: logarithm and friends, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatlog.h" #include "floatconst.h" #include "floatcommon.h" #include "floatseries.h" typedef struct { char c2; char c3; char c5; char c7; char c10; } _lincomb; static _lincomb _lincombtbl[] = { {0,3,3,2,5},{12,4,0,2,7},{4,0,0,0,1},{0,2,2,1,3},{13,3,0,1,6}, /* -.40 */ {7,5,0,2,6},{10,1,0,2,5},{4,3,0,3,5},{1,6,0,0,3},{4,2,0,0,2}, /* -.35 */ {0,4,2,1,4},{1,0,0,1,1},{0,9,0,1,5},{3,5,0,1,4},{6,1,0,1,3}, /* -.30 */ {0,3,0,2,3},{8,6,0,1,6},{11,2,0,1,5},{0,6,2,1,5},{22,1,0,0,7}, /* -.25 */ {9,5,0,0,5},{0,0,2,2,3},{0,5,1,0,3},{2,1,0,0,1},{0,3,4,1,5}, /* -.20 */ {0,1,8,0,6},{0,3,3,3,6},{5,6,0,2,6},{8,2,0,2,5},{0,13,0,1,7}, /* -.15 */ {12,3,0,0,5},{0,7,1,0,4},{0,2,1,4,5},{0,7,0,2,5},{3,3,0,2,4}, /* -.10 */ {20,0,0,0,6},{7,4,0,0,4},{10,0,0,0,3},{8,4,0,2,6},{0,0,0,0,0}, /* -.05 */ {0,0,0,0,0},{0,9,1,0,5},{13,5,0,2,8},{9,3,0,1,5},{0,7,4,1,7}, /* 0.00 */ {10,3,0,3,7},{0,1,5,0,4},{0,12,2,1,8},{10,2,0,0,4},{8,6,0,2,7},/* 0.05 */ {8,1,0,6,8},{7,0,0,1,3},{5,4,0,3,6},{22,1,0,1,8},{2,7,0,0,4}, /* 0.10 */ {2,2,0,4,5},{0,0,2,3,4},{0,5,1,1,4},{0,3,5,0,5},{14,6,0,1,8}, /* 0.15 */ {10,4,0,0,5},{3,1,0,3,4},{4,6,0,1,5},{0,4,0,0,2},{14,0,0,2,6}, /* 0.20 */ {0,13,1,0,7},{8,2,0,3,6},{4,0,0,2,3},{2,4,0,4,6},{0,2,2,3,5}, /* 0.25 */ {0,0,6,2,6},{0,5,5,0,6},{23,2,0,0,8},{0,1,2,0,2},{17,4,0,1,8}, /* 0.30 */ {0,10,3,0,7},{11,6,0,2,8},{4,3,0,5,7},{14,2,0,2,7},{10,0,0,1,4},/* 0.35 */ {8,4,0,3,7},{1,1,0,6,6},{11,0,0,3,6},{12,5,0,1,7},{2,1,0,8,8}, /* 0.40 */ {15,1,0,1,6},{0,7,5,0,7},{6,2,0,6,8},{2,0,0,5,5},{1,14,0,1,8}, /* 0.45 */ {0,12,3,0,8},{20,2,0,1,8},{0,8,0,0,4},{14,4,0,2,8},{3,4,0,0,3},/* 0.50 */ {0,1,4,3,6},{6,0,0,0,2},{4,4,0,2,5},{0,2,0,1,2},{8,0,1,2,5}, /* 0.55 */ {8,5,0,0,5},{15,3,0,1,7},{0,9,5,0,8},{0,0,3,2,4},{0,5,2,0,4}, /* 0.60 */ {5,3,0,1,4},{0,0,2,4,5},{13,6,0,0,7},{3,2,0,7,8},{16,2,0,0,6}, /* 0.65 */ {0,1,9,0,7},{3,6,0,0,4},{10,4,0,1,6},{0,0,0,8,7},{13,0,0,1,5}, /* 0.70 */ {0,6,7,0,8},{0,4,0,1,3},{0,2,4,0,4},{3,0,0,1,2},{15,5,0,1,8}, /* 0.75 */ {8,2,0,4,7},{2,9,0,1,6},{4,0,0,3,4},{2,4,0,5,7},{12,3,0,2,7}, /* 0.80 */ {1,3,0,0,2},{0,0,6,3,7},{6,5,0,3,7},{16,4,0,0,7},{0,3,9,0,8}, /* 0.85 */ {0,1,2,1,3},{10,6,0,1,7},{0,2,0,8,8},{0,10,3,1,8},{0,1,1,3,4}, /* 0.90 */ {9,0,0,0,3},{4,3,0,6,8},{0,4,4,0,5},{8,9,0,0,7},{10,0,0,2,5} /* 0.95 */ }; /* artanh x and ln(x+1) are closely related. Evaluate the logarithm using the artanh series, which converges twice as fast as the logarithm series. With 100 digits, if -0.0198 <= x <= 0.02, the relative error is less than 5.0e-100, or at most 1 unit in the 100th place */ void _lnxplus1near0( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_add(&tmp, &c2, x, digits); float_div(x, x, &tmp, digits); artanhnear0(x, digits); float_add(x, x, x, EXACT); float_free(&tmp); } /* helpers */ static void _addcoef( floatnum x, int coef, floatnum cnst, int digits) { floatstruct tmp; if (coef != 0) { float_create(&tmp); float_muli(&tmp, cnst, coef, digits); float_add(x, x, &tmp, digits); float_free(&tmp); } } static int _factor( int idx) { int factor; int i; factor = 1; for (i = _lincombtbl[idx].c2; --i >= 0;) factor *= 2; for (i = _lincombtbl[idx].c3; --i >= 0;) factor *= 3; for (i = _lincombtbl[idx].c5; --i >= 0;) factor *= 5; for (i = _lincombtbl[idx].c7; --i >= 0;) factor *= 7; return factor; } static void _lnguess( floatnum dest, int digits, int idx) { _addcoef(dest, _lincombtbl[idx].c2-_lincombtbl[idx].c5, &cLn2, digits); _addcoef(dest, _lincombtbl[idx].c3, &cLn3, digits); _addcoef(dest, _lincombtbl[idx].c7, &cLn7, digits); _addcoef(dest, _lincombtbl[idx].c5-_lincombtbl[idx].c10, &cLn10, digits); } /* reduces x using a special factor whose prime factors are 2, 3, 5 and 7 only. x is multiplied by this factor, yielding a value near a power of ten. Then x is divided by this power of ten. The logarithm of this factor is returned in lnguess. Valid for -0.4 <= x < 1. Relative error < 5e-100 for 100 digit result. This algorithm reduces x to a value < 0.01, which is appropriately small for submitting to a series evaluation */ void _lnreduce( floatnum x, floatnum lnguess, int digits) { floatstruct tmp1, tmp2; int idx; int expx; signed char pos; float_setzero(lnguess); expx = float_getexponent(x); if (expx < -2) return; float_create(&tmp1); float_create(&tmp2); idx = leadingdigits(x, 3 + expx) + 39; if (idx < 0) idx = 0; pos = idx >= 40? 1 : 0; idx += pos; float_setinteger(&tmp1, _factor(idx)); float_setexponent(&tmp1, -pos); float_sub(&tmp1, &tmp1, &c1, EXACT); float_mul(&tmp2, x, &tmp1, digits); float_add(&tmp1, &tmp1, &tmp2, digits+1); float_add(x, x, &tmp1, digits); _lnguess(lnguess, digits+4, idx); float_free(&tmp1); float_free(&tmp2); return; } /* for -0.4 <= x < 1.0 */ void _lnxplus1lt1( floatnum x, int digits) { floatstruct lnfactor; float_create(&lnfactor); _lnreduce(x, &lnfactor, digits); _lnxplus1near0(x, digits); float_sub(x, x, &lnfactor, digits+1); float_free(&lnfactor); } /* the general purpose routine evaluating ln(x) for all positive arguments. It uses multiplication and division to reduce the argument to a value near 1. The factors are always small, so these operations do not take much time. -- One often sees an argument reduction by taking the square root several times in succession. But the square root is slow in number.c, so we avoid it best. -- Super-fast algorithm like the AGM based ones, do not pay off for limited lengths because of the same reason: They require taking square roots several times. A test showed, a hundred digits calculation using AGM is 8 times slower than the algorithm here. For extreme precision, of course, AGM will be superior. The relative error seems to be less than 7e-101 for 100-digits computations */ void _ln( floatnum x, int digits) { floatstruct tmp; int coef10; char coef3; char dgt; float_create(&tmp); coef10 = float_getexponent(x); /* reducing the significand to 0.6 <= x < 2 by simple multiplication */ dgt = leadingdigits(x, 1); coef3 = 0; if (dgt == 1) float_setexponent(x, 0); else { ++coef10; float_setexponent(x, - 1); coef3 = (dgt < 6); if (coef3) float_mul(x, x, &c3, digits+1); } float_sub(x, x, &c1, digits+1); _lnxplus1lt1(x, digits); if (coef10 != 0) { float_muli(&tmp, &cLn10, coef10, digits+1); float_add(x, x, &tmp, digits+1); } if (coef3) float_sub(x, x, &cLn3, digits); float_free(&tmp); } void _lnxplus1( floatnum x, int digits) { if (float_cmp(x, &cMinus0_4) >= 0 && float_cmp(x, &c1) < 0) _lnxplus1lt1(x, digits); else { float_add(x, x, &c1, digits+1); _ln(x, digits); } } /* The artanh function has a pole at x == 1. For values close to 1 the general purpose evaluation is too unstable. We use a dedicated algorithm here to get around the problems. Avoid using this function for values of x > 0.5, _artanh is the better choice then. Values near the other pole of artanh at -1 can be derived from this function using artanh(-1+x) = -artanh(1-x). For x < 0.5 and a 100-digit computation, the maximum relative error is in the order of 1e-99 */ void _artanh1minusx( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_sub(&tmp, &c2, x, digits); float_div(x, &tmp, x, digits); _ln(x, digits); float_mul(x, x, &c1Div2, digits); float_free(&tmp); } /* designed for |x| <= 0.5. The evaluation is not symmetric with respect to 0, i.e. it might be -artanh x != artanh -x. The difference is in the order of the last digit, of course. Evaluation of positive values yield a slightly better relative error than that of negative values. The maximum relative error is the maximum of that of artanhnear0 and 1e-99 */ void _artanhlt0_5( floatnum x, int digits) { floatstruct tmp; if (float_getexponent(x) < -2 || float_iszero(x)) artanhnear0(x, digits); else { float_create(&tmp); float_sub(&tmp, &c1, x, digits+1); float_add(x, x, x, digits); float_div(x, x, &tmp, digits); _lnxplus1(x, digits); float_mul(x, x, &c1Div2, digits); float_free(&tmp); } } /* the general purpose routine for evaluating artanh. The evaluation is symmetric with respect to 0, i.e. it is always -artanh(x) == artanh -x. Valid for |x| < 1, but unstable for |x| approx. == 1 */ void _artanh( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) <= 0) _artanhlt0_5(x, digits); else { float_sub(x, &c1, x, digits+1); _artanh1minusx(x, digits); } float_setsign(x, sgn); } /* evaluates ln(2*x), the asymptotic function of arsinh and arcosh for large x */ static void _ln2x( floatnum x, int digits) { _ln(x, digits); float_add(x, &cLn2, x, digits); } /* valid for all x. The relative error is less than 1e-99. The evaluation is symmetric with respect to 0: arsinh -x == - arsinh x */ void _arsinh( floatnum x, int digits) { floatstruct tmp; int expxsqr; signed char sgn; expxsqr = 2*float_getexponent(x)+2; /* for extreme small x, sqrt(1+x*x) is approx == 1 + x*x/2 - x^4/8, so arsinh x == ln(1 + x + x*x/2 - x^4/8 +...) approx == x - x*x*x/6 + ... If we approximate arsinh x by x, the relative error is roughly |x*x/6|. This is less than acceptable 10^(-), if log(x*x) < - */ if (expxsqr < -digits || float_iszero(x)) return; float_create(&tmp); /* arsinh -x = -arsinh x, so we can derive the arsinh for negative arguments from that of positive arguments */ sgn = float_getsign(x); float_abs(x); if (expxsqr-2 > digits) /* for very large x, use the asymptotic formula ln(2*x) */ _ln2x(x, digits); else { float_mul(&tmp, x, x, digits + (expxsqr>=0? 0 : expxsqr)); float_add(&tmp, &tmp, &c1, digits+1); float_sqrt(&tmp, digits); if (float_getexponent(x) < 0) { /* for small x, use arsinh x == artanh (x/sqrt(1+x*x)). Stable for x < 1, but not for large x*/ float_div(x, x, &tmp, digits); _artanh(x, digits+1); } else { /* arsinh x = ln(x+sqrt(1+x*x)), stable for x >= 1, but not for small x */ float_add(x, x, &tmp, digits); _ln(x, digits); } } float_setsign(x, sgn); float_free(&tmp); } /* arcosh(x+1), x >= 0, is the stable variant of arcosh(x), x >= 1. The relative error is less than 1e-99. */ void _arcoshxplus1( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); if (2*float_getexponent(x) > digits) { /* for very large x, use the asymptotic formula ln(2*(x+1)) */ float_add(x, x, &c1, digits+1); _ln2x(x, digits); } else { /* arcosh(x+1) = ln(1+(x+sqrt(x*(x+2)))), stable for all positive x, except for extreme large x, where x*(x+2) might overflow */ /* get sinh(arcosh (1+x)) = sqrt(x*(x+2)) */ float_add(&tmp, x, &c2, digits); float_mul(&tmp, x, &tmp, digits); float_sqrt(&tmp, digits); float_add(x, x, &tmp, digits); _lnxplus1(x, digits); } float_free(&tmp); } deepin-calculator-5.7.21/3rdparty/math/floatlog.h000066400000000000000000000032531423020056600216630ustar00rootroot00000000000000/* floatlog.h: logarithms and friends, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATLOG_H # define FLOATLOG_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif void _lnxplus1near0(floatnum x, int digits); void _lnreduce(floatnum x, floatnum lnguess, int digits); void _lnxplus1lt1(floatnum x, int digits); void _ln(floatnum x, int digits); void _lnxplus1(floatnum x, int digits); void _artanh1minusx(floatnum x, int digits); void _artanhlt0_5(floatnum x, int digits); void _artanh(floatnum x, int digits); void _arsinh(floatnum x, int digits); void _arcoshxplus1(floatnum x, int digits); #ifdef __cplusplus } #endif #endif /* FLOATLOG_H */ deepin-calculator-5.7.21/3rdparty/math/floatlogic.c000066400000000000000000000115021423020056600221660ustar00rootroot00000000000000/* floatlogic.c: logic functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatlogic.h" #include "floatconst.h" #define MAXIDX ((LOGICRANGE-1) / BITS_IN_UNSIGNED) #define SIGNBIT (LOGICRANGE - 1 - MAXIDX * BITS_IN_UNSIGNED) static void _zeroextend( t_longint* longint) { int idx; idx = longint->length - 1; for (; ++idx <= (int)MAXIDX;) longint->value[idx] = 0; } signed char _signof( t_longint* longint) { return (longint->value[MAXIDX] & (1 << SIGNBIT)) != 0? -1:1; } static char _signextend( t_longint* longint) { unsigned mask; signed char sign; sign = _signof(longint); mask = (~0) << SIGNBIT; if (sign < 0) longint->value[MAXIDX] |= mask; else longint->value[MAXIDX] &= ~mask; return sign; } static void _neg( t_longint* longint) { int idx = -1; const int maxidx = MAXIDX; while (++idx <= maxidx && longint->value[idx] == 0); if (idx <= maxidx) longint->value[idx] = - longint->value[idx]; while (++idx <= maxidx) longint->value[idx] = ~longint->value[idx]; } char _floatnum2logic( t_longint* longint, cfloatnum x) { floatstruct tmp; int digits; digits = float_getexponent(x)+1; if (float_iszero(x) || digits <= 0) { longint->length = 1; longint->value[0] = 0; } else { if (digits > MATHPRECISION) return 0; float_create(&tmp); /* floatnum2longint rounds, we have to truncate first */ float_copy(&tmp, x, digits); if (float_getsign(x) < 0) float_add(&tmp, &tmp, &c1, EXACT); _floatnum2longint(longint, &tmp); float_free(&tmp); if (_bitlength(longint) > LOGICRANGE) return 0; } _zeroextend(longint); if (float_getsign(x) < 0) _not(longint); return 1; } void _logic2floatnum( floatnum f, t_longint* longint) { int idx; signed char sign; sign = _signextend(longint); if (sign < 0) _neg(longint); idx = MAXIDX; while (idx >= 0 && longint->value[idx] == 0) --idx; if (idx < 0) longint->length = 0; else longint->length = idx + 1; _longint2floatnum(f, longint); float_setsign(f, sign); } void _not( t_longint* longint) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) longint->value[idx] = ~(longint->value[idx]); } void _and( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) x1->value[idx] = x1->value[idx] & x2->value[idx]; } void _or( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) x1->value[idx] = x1->value[idx] | x2->value[idx]; } void _xor( t_longint* x1, t_longint* x2) { int idx; for (idx = -1; ++idx <= (int)MAXIDX;) x1->value[idx] = x1->value[idx] ^ x2->value[idx]; } void _shr( t_longint* x, unsigned shift) { int idx; const unsigned sign = _signof(x) < 0? ~0 : 0; const int moves = shift/BITS_IN_UNSIGNED; const int maxidx = MAXIDX; if (moves > 0) { shift -= moves * BITS_IN_UNSIGNED; for (idx = moves-1; ++idx <= maxidx;) x->value[idx-moves] = x->value[idx]; idx = MAXIDX - moves + 1; if (idx < 0) idx = 0; for (; idx <= maxidx; ++idx) x->value[idx] = sign; } if (shift > 0) { for (idx = -1; ++idx < maxidx;) x->value[idx] = _longshr(x->value[idx], x->value[idx+1], shift); x->value[MAXIDX] = _longshr(x->value[MAXIDX], sign, shift); } } void _shl( t_longint* x, unsigned shift) { int moves, idx; moves = shift/BITS_IN_UNSIGNED; if (moves > 0) { shift -= moves * BITS_IN_UNSIGNED; for (idx = MAXIDX; idx >= moves; --idx) x->value[idx] = x->value[idx-moves]; if (moves > (int)MAXIDX) moves = MAXIDX+1; for (idx = -1; ++idx < moves;) x->value[idx] = 0; } if (shift > 0) { for (idx = MAXIDX; idx > 0; --idx) x->value[idx] = _longshl(x->value[idx-1], x->value[idx], shift); x->value[0] <<= shift; } } deepin-calculator-5.7.21/3rdparty/math/floatlogic.h000066400000000000000000000031731423020056600222000ustar00rootroot00000000000000/* floatlogic.h: logic functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATLOGIC_H # define FLOATLOGIC_H #include "floatconvert.h" #ifdef __cplusplus extern "C" { #endif char _canconvert(cfloatnum x); char _floatnum2logic(t_longint* longint, cfloatnum x); void _logic2floatnum(floatnum f, t_longint* longint); void _not(t_longint* longint); void _and(t_longint* x1, t_longint* x2); void _or(t_longint* x1, t_longint* x2); void _xor(t_longint* x1, t_longint* x2); void _shr(t_longint* x, unsigned shift); void _shl(t_longint* x, unsigned shift); #ifdef __cplusplus } #endif #endif /* FLOATLOGIC_H */ deepin-calculator-5.7.21/3rdparty/math/floatlong.c000066400000000000000000000141161423020056600220340ustar00rootroot00000000000000/* floatlong.c: portable double size integer arithmetic. */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatlong.h" #define HALFSIZE (sizeof(unsigned) * 4) #define LOWMASK ((1 << HALFSIZE) - 1) #define MSB (1 << (2*HALFSIZE-1)) /*************** functions handling a single unsigned ********************/ int _findfirstbit( unsigned value) { int result; result = -1; while (value != 0) { value >>= 1; ++result; } return result; } /* pre: value != 0 */ static int _revfindfirstbit( unsigned value) { int result; result = 0; while ((value & 1) == 0) { value >>= 1; ++result; } return result; } /******************* double unsigned functions ********************/ static void _longsplit( unsigned value, unsigned* low, unsigned* high) { *high = value >> HALFSIZE; *low = value & LOWMASK; } static unsigned _longcat( unsigned low, unsigned high) { return (high << HALFSIZE) + low; } char _longadd( unsigned* s1, unsigned* s2) { unsigned s1h, s1l, s2h, s2l; _longsplit(*s1, &s1l, &s1h); _longsplit(*s2, &s2l, &s2h); s1l += s2l; _longsplit(s1l, &s1l, &s2l); s1h += s2h + s2l; _longsplit(s1h, &s1h, s2); *s1 = _longcat(s1l, s1h); return *s2 == 0; } char _longmul( unsigned* f1, unsigned* f2) { unsigned f1h, f1l, f2h, f2l; _longsplit(*f1, &f1l, &f1h); _longsplit(*f2, &f2l, &f2h); *f1 = f1l * f2l; *f2 = f1h * f2h; f1l *= f2h; f2l *= f1h; _longadd(&f1l, &f2l); _longsplit(f1l, &f1l, &f1h); f1l <<= HALFSIZE; _longadd(f1, &f1l); *f2 += f1l + (f2l << HALFSIZE) + f1h; return *f2 == 0; } unsigned _longshr( unsigned low, unsigned high, char shift) { if (shift == 0) return low; return (low >> shift) | (high << ((2*HALFSIZE)-shift)); } unsigned _longshl( unsigned low, unsigned high, char shift) { if (shift == 0) return high; return (low >> ((2*HALFSIZE)-shift)) | (high << shift); } /***************** unsigned array functions *****************/ unsigned _longarrayadd( unsigned* uarray, int lg, unsigned incr) { for(; lg-- > 0 && incr != 0;) _longadd(uarray++, &incr); return incr; } unsigned _longarraymul( unsigned* uarray, int lg, unsigned factor) { unsigned ovfl, carry; carry = 0; ovfl = 0; for (; lg-- > 0;) { carry += ovfl; ovfl = factor; _longmul(uarray, &ovfl); _longadd(uarray++, &carry); } return carry + ovfl; } unsigned _bitsubstr( unsigned* uarray, int ofs) { int idx; if (ofs <= 0) return *uarray << -ofs; idx = ofs / BITS_IN_UNSIGNED; return _longshr(*(uarray+idx), *(uarray+idx+1), ofs - idx * BITS_IN_UNSIGNED); } void _orsubstr( unsigned* uarray, int bitofs, unsigned value) { int idx; int ofs; idx = bitofs / BITS_IN_UNSIGNED; ofs = bitofs - idx * BITS_IN_UNSIGNED; if (ofs == 0) *(uarray + idx) |= value; else { *(uarray + idx) |= value << ofs; *(uarray + idx + 1) |= value >> (BITS_IN_UNSIGNED - ofs); } } /**************** longint functions ****************/ char _isfull( t_longint* l) { return l->length >= (int)UARRAYLG - 1; } unsigned _bitlength( t_longint* l) { if (l->length == 0) return 0; return (l->length - 1) * BITS_IN_UNSIGNED + _findfirstbit(l->value[l->length-1]) + 1; } unsigned _lastnonzerobit( t_longint* l) { int i; if (l->length == 0) return -1; i = -1; for (; ++i < l->length && l->value[i] == 0;); return i * BITS_IN_UNSIGNED + _revfindfirstbit(l->value[i]); } unsigned _longintadd( t_longint* l, unsigned summand) { unsigned ovfl; ovfl = _longarrayadd(l->value, l->length, summand); if (ovfl != 0 && !_isfull(l)) { l->value[l->length] = ovfl; ++l->length; ovfl = 0; } return ovfl; } unsigned _longintmul( t_longint* l, unsigned factor) { unsigned ovfl; ovfl = _longarraymul(l->value, l->length, factor); if (ovfl != 0 && !_isfull(l)) { l->value[l->length] = ovfl; ++l->length; ovfl = 0; } return ovfl; } char _longintsetsize( t_longint* l, unsigned bitlength) { int i; if (bitlength == 0) l->length = 0; else l->length = (bitlength - 1) / BITS_IN_UNSIGNED + 1; if (l->length >= (int)UARRAYLG) return 0; for(i = l->length; i >= 0; --i) l->value[i] = 0; return 1; } /**************** overflow checking integer functions *************/ char _checkadd( int* s1, int s2) { unsigned u1, u2; if ((*s1 < 0) ^ (s2 < 0)) { /* you can always add summands of opposite sign */ *s1 += s2; return 1; } if (s2 < 0) { u1 = -*s1; u2 = -s2; _longadd(&u1, &u2); *s1 = -(int)u1; return u2 == 0 && *s1 < 0; } u1 = *s1; u2 = s2; _longadd(&u1, &u2); *s1 = u1; return *s1 >= 0; } char _checkmul( int* f1, int f2) { unsigned x1, x2; signed char sgn = 1; const unsigned msb = MSB; if (*f1 >= 0) x1 = *f1; else { sgn = -1; x1 = -*f1; } if (f2 >= 0) x2 = f2; else { sgn = -sgn; x2 = -f2; } _longmul(&x1, &x2); if (sgn < 0) { *f1 = -(int)x1; return (x2 == 0 && x1 <= msb); } *f1 = (int)x1; return (x2 == 0 && x1 < msb); } deepin-calculator-5.7.21/3rdparty/math/floatlong.h000066400000000000000000000045221423020056600220410ustar00rootroot00000000000000/* floatlong.h: portable double size integer arithmetic */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATLONG_H # define FLOATLONG_H #include "floatconfig.h" #ifdef __cplusplus extern "C" { #endif #define BITS_IN_UNSIGNED (sizeof(unsigned)*8) /* one unsigned extra, so that _bitsubstr() does not access parts outside of t_uarray */ #define UARRAYLG ((8305*(MATHPRECISION+5) + 1)/20000/sizeof(unsigned) + 2) typedef unsigned t_uarray[UARRAYLG]; typedef struct{ int length; t_uarray value; } t_longint; int _findfirstbit(unsigned value); char _longadd(unsigned* s1, unsigned* s2); char _longmul(unsigned* f1, unsigned* f2); char _checkadd(int* s1, int s2); char _checkmul(int* f1, int f2); unsigned _longshr(unsigned low, unsigned high, char shift); unsigned _longshl(unsigned low, unsigned high, char shift); unsigned _longarrayadd(unsigned* uarray, int lg, unsigned incr); unsigned _longarraymul(unsigned* uarray, int lg, unsigned factor); void _orsubstr(unsigned* uarray, int bitofs, unsigned value); unsigned _bitsubstr(unsigned* uarray, int ofs); unsigned _bitlength(t_longint* l); unsigned _lastnonzerobit(t_longint* l); char _longintsetsize(t_longint* l, unsigned bitlength); unsigned _longintadd(t_longint* l, unsigned summand); unsigned _longintmul(t_longint* l, unsigned factor); #ifdef __cplusplus } #endif #endif /* FLOATLONG_H */ deepin-calculator-5.7.21/3rdparty/math/floatnum.c000066400000000000000000001216701423020056600217000ustar00rootroot00000000000000/* floatnum.c: Arbitrary precision floating point numbers, based on bc. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ /* a floating point engine based on bc's decimal fix point arithmetic. The speed is not overwhelming, but sufficient for calculators with limited demands. As bc's number.c is a portable engine, this should be portable as well. */ #include "floatnum.h" #include "floatlong.h" #include "floatconfig.h" #include #include #define NOSPECIALVALUE 1 int maxdigits = MAXDIGITS; Error float_error; int expmax = EXPMAX; int expmin = EXPMIN; /* general helper routines */ static int _max(int x, int y) { return x > y? x : y; } static int _min(int x, int y) { return x < y? x : y; } /* the return value points to the first character different from accept. */ const char* _memskip( const char* buf, const char* end, char accept) { for(--buf; ++buf != end && *buf == accept;); return buf; } /* scans a value in a bc-num (or part of it) for the first occurence of a digit *different* from . The scan is limited to bytes. Returns the offset of the matching byte, or , if none was found */ static int _scan_digit( const char*p, int count, char digit) { const char* ps; ps = p; for (; count-- > 0 && *p == digit; ++p); return p - ps; } /* bc_num primitives */ #define _scaleof(f) (f->significand->n_scale) #define _lenof(f) (f->significand->n_len) #define _valueof(f) (f->significand->n_value) #define _digit(f, offset) (*(_valueof(f) + offset)) #define _setscale(f, value) (_scaleof(f) = value) /* converts floatnum's sign encodings (+1, -1) to bc_num sign encoding (PLUS, MINUS) */ static void _setsign( floatnum f, signed char value) { f->significand->n_sign = value < 0? MINUS : PLUS; #ifdef FLOATDEBUG f->value[0] = value < 0? '-' : '+'; #endif } /* modifies a bc_num significand such that the last (existing) digits of its value are not visible to bc_num operations any more. A negative reverts this operation (unhide). pre: <= n_scale*/ static void _hidelast( floatnum f, int count) { f->significand->n_scale -= count; } /* modifies a bc_num significand such that the first (existing) digits of its value are not visible to bc_num operations any more. A negative reverts this operation (unhide). pre: <= n_scale*/ static void _hidefirst( floatnum f, int count) { f->significand->n_value += count; f->significand->n_scale -= count; } /* Usually, significands are normalized, which means they fulfill 1 <= x < 10. This operation moves the decimal point places to the right, effectively multiplying the significand by a power of 10. A negative reverts such an operation. pre: < n_scale */ static void _movepoint( floatnum f, int digits) { f->significand->n_len += digits; f->significand->n_scale -= digits; } /* floatstruct primitives */ /* a quick check for NaN and 0 */ static char _is_special( cfloatnum f) { return f->significand == NULL; } /* creates a shallow working copy of in , using b as a container for the significand. On return, is equal in value to . may then be modified freely in the course of an operation, without effecting source, *except* that the digits in *(dest->significand->n_value) have to be retained (or restored). must *never* be the destination of a float_xxx operation, in particiular, it must not be freed. Neither must b be modified (or freed) in a bc_num operation */ static void _copyfn( floatnum dest, cfloatnum source, bc_num b) { *dest = *source; if (!_is_special(source)) { *b = *(source->significand); b->n_ptr = 0; dest->significand = b; } } /* If you want to execute a bc_num operation to a limited scale, it is a waste of computation time to pass operands with a longer scale, because bc lets the operand's scale override your limit. This function hides superfluous digits from bc, returning the original scale for restoring purposes */ static int _limit_scale( floatnum f, int newscale) { int oldscale; oldscale = _scaleof(f); _setscale(f, _min(oldscale, newscale)); return oldscale; } /*============================ floatnum routines ===================*/ int float_getrange() { return expmax; } int float_getprecision() { return maxdigits; } int float_setrange( int maxexp) { int result; result = expmax; expmax = _max(_min(maxexp, MAXEXP), 1); expmin = -expmax - 1; return result; } int float_setprecision( int digits) { int result; result = maxdigits; maxdigits = _max(_min(digits, MAXDIGITS), 1); return result; } /* checking the limits on exponents */ char float_isvalidexp( int exp) { return exp >= expmin && exp <= expmax; } /* clears the error state as well */ Error float_geterror() { Error tmp; tmp = float_error; float_error = Success; return tmp; } /* the first error blocks all others as it may be the source of a cascade of dependent errors */ void float_seterror( Error code) { if (float_error == Success) float_error = code; } void floatnum_init() { bc_init_numbers(); float_geterror(); } void float_create( floatnum f) { f->significand = NULL; f->exponent = EXPNAN; #ifdef FLOATDEBUG memcpy(f->value, "NaN", 4); #endif } void float_setnan ( floatnum f) { bc_free_num(&(f->significand)); float_create(f); } char _setnan( floatnum result) { float_setnan(result); return FALSE; } char _seterror( floatnum result, Error code) { float_seterror(code); return _setnan(result); } void float_setzero ( floatnum f) { bc_free_num(&(f->significand)); f->exponent = EXPZERO; #ifdef FLOATDEBUG f->value[0] ='0'; f->value[1] = 0; #endif } char _setzero( floatnum result) { float_setzero(result); return TRUE; } char float_isnan( cfloatnum f) { return _is_special(f) && f->exponent != EXPZERO; } char float_iszero( cfloatnum f) { return _is_special(f) && f->exponent == EXPZERO; } int float_getlength( cfloatnum f) { return _is_special(f)? 0 : _scaleof(f) + 1; } char float_getdigit( cfloatnum f, int ofs) { if (ofs >= float_getlength(f) || ofs < 0) return 0; return _digit(f, ofs); } /* checks whether f is a NaN and sets the float_error variable accordingly. Used in parameter checks when float_xxx calls are executed. FALSE is returned if a NaN is encountered. */ char _checknan( cfloatnum f) { if (!float_isnan(f)) return TRUE; float_seterror(NoOperand); return FALSE; } /* checks whether is positive and sets the float_error variable accordingly. Used in parameter checks when float_xxx calls are executed. Some operations accept a special value like EXACT, that has to pass this check, even though its numerical encoding violates the boundaries. If a function does not accept a special value, use NOSPECIALVALUE as a parameter for . TRUE is returned if the check is passed. The check for the limit MAXDIGITS is not executed here, because some intermediate operations have to succeed on more than MAXDIGITS digits */ static char _checkdigits( int digits, int specialval) { if ((digits > 0 && digits <= maxdigits) || digits == specialval) return TRUE; float_seterror(InvalidPrecision); return FALSE; } /* backward-scans the significand in . Returns the number of digits equal to beginning with the +1-th digit of f->significand->n_value. */ static int _bscandigit( cfloatnum f, int scale, char digit) { char* p; char* ps; ps = _valueof(f); for (p = ps + scale + 1; p-- != ps && *p == digit;); return scale - (p - ps); } /* scans two significands for the first occurence of a pair of differnt digits. Returns the number of equal digits at the beginning */ static int _scan_equal( floatnum v1, floatnum v2) { int count, i; char* p1; char* p2; count = _min(_scaleof(v1), _scaleof(v2)); p1 = _valueof(v1); p2 = _valueof(v2); i = 0; for (; *(p1++) == *(p2++) && ++i <= count;); return i; } /* scans two significands until it finds a digit different from 0 in the first significand, or a digit different from 9 in the second operand. The scan is limited by compares and starts with the *second* digit in the significands. Returns the number of found (0,9) pairs. */ static int _scan_09pairs( floatnum f1, floatnum f2, int count) { char* p; char* p1; char* p2; p1 = _valueof(f1) + 1; p2 = _valueof(f2) + 1; p = p1; for (; count-- > 0 && *p1 == 0 && *(p2++) == 9; ++p1); return p1 - p; } signed char float_getsign( cfloatnum f) { if(_is_special(f)) return 0; return f->significand->n_sign == PLUS? 1 : -1; } void float_setsign( floatnum f, signed char s) { if (s == 1 || s == -1) { if(!_is_special(f)) _setsign(f, s); } else if (s != 0) float_setnan(f); } char float_neg( floatnum f) { float_setsign(f, -float_getsign(f)); return _checknan(f); } char float_abs( floatnum f) { if(float_getsign(f) == -1) float_neg(f); return _checknan(f); } signed char float_cmp( cfloatnum val1, cfloatnum val2) { signed char sgn1; if (!_checknan(val1) || !_checknan(val2)) return UNORDERED; sgn1 = float_getsign(val1); if (float_getsign(val2) != sgn1) { if (sgn1 != 0) return sgn1; return -float_getsign(val2); } if (val1->exponent > val2->exponent) return sgn1; if (val1->exponent < val2->exponent) return -sgn1; if (_is_special(val1)) return 0; return (bc_compare(val1->significand, val2->significand)); } /* normalizing process: hides leading zeros in a significand and corrects the exponent accordingly */ static void _corr_lead_zero( floatnum f) { int count; count = _scan_digit(_valueof(f), float_getlength(f), 0); _hidefirst(f, count); f->exponent-=count; } /* normalizing process: if the significand is > 10 in magnitude, this function corrects this */ static void _corr_overflow( floatnum f) { int shift; shift = _lenof(f) - 1; _movepoint(f, -shift); f->exponent += shift; } /* cuts off trailing zeros at the end of a significand */ static void _corr_trailing_zeros( floatnum f) { _hidelast(f, _bscandigit(f, _scaleof(f), 0)); } static char hexdigits[] = "0123456789ABCDEF"; int float_getsignificand( char* buf, int bufsz, cfloatnum f) { int idx, lg; if (bufsz <= 0) return 0; if (float_isnan(f)) { *buf = 'N'; return 1; } if (float_iszero(f)) { *buf = '0'; return 1; } idx = -1; lg = _min(bufsz, float_getlength(f)); for(; ++idx < lg;) *(buf++) = hexdigits[(int)float_getdigit(f, idx)]; return lg; } int float_getexponent( cfloatnum f) { if (_is_special(f)) return 0; return f->exponent; } int float_getscientific( char* buf, int bufsz, cfloatnum f) { char b[42]; /* supports exponents encoded in up to 128 bits */ int sgnlg, explg, mlg; /* handle special cases */ if(float_isnan(f)) { if (bufsz < 4) return -1; memcpy(buf, "NaN\0", 4); return 3; } if(float_iszero(f)) { if (bufsz < 2) return -1; *buf = '0'; *(buf+1) = '\0'; return 1; } /* set one byte aside for sign? */ sgnlg = 0; if(float_getsign(f) < 0) sgnlg = 1; /* convert the exponent */ sprintf(b, "%d", float_getexponent(f)); explg = strlen(b); /* 3 extra bytes for dot, exp char and terminating \0 */ bufsz -= explg + sgnlg + 3; /* rest is for significand */ if (bufsz <= 0) /* buffer too small */ return-1; if(sgnlg > 0) *(buf++) = '-'; /* get the digit sequence of the significand, trailing zeros cut off */ mlg = float_getsignificand(++buf, bufsz, f) - 1; /* move the first digit one byte to the front and fill the gap with a dot */ *(buf-1) = *buf; *(buf++) = '.'; /* append the exponent */ *(buf+mlg) = 'e'; memcpy(buf+mlg+1, b, explg); /* the trailing \0 */ *(buf+mlg+explg+1) = '\0'; return sgnlg + mlg + explg + 3; } #ifdef FLOATDEBUG void _setvalue_(floatnum f) { f->value[float_getsignificand(f->value+2, sizeof(f->value)-3, f)+2] = 0; f->value[1] = f->value[2]; f->value[2] = '.'; f->value[0] = float_getsign(f) < 0? '-' : '+'; } #endif int float_setsignificand( floatnum f, int* leadingzeros, const char* buf, int bufsz) { const char* p; const char* dot; const char* last; const char* b; char* bcp; int zeros; int lg; char c; float_setnan(f); if (bufsz == NULLTERMINATED) bufsz = strlen(buf); /* initialize the output parameters for all early out branches */ if (leadingzeros != NULL) *leadingzeros = 0; if (bufsz <= 0) return -1; dot = memchr(buf, '.', bufsz); /* do not accept more than 1 dots */ if (dot != NULL && memchr(dot + 1, '.', bufsz - (dot - buf)) != NULL) return -1; last = buf + bufsz; /* points behind the input buffer */ /* skip all leading zeros */ b = _memskip(buf, last, '0'); /* is the first non-zero character found a dot? */ if (b == dot) /* then skip all zeros following the dot */ b = _memskip(b+1, last, '0'); /* the 'leading zeros' */ zeros = b - buf - (dot == NULL || dot >= b? 0:1); /* only zeros found? */ if (b == last) { /* indicate no dot, no leading zeros, because this does not matter in case of zero */ if (bufsz > (dot == NULL? 0:1)) float_setzero(f); /* do not accept a dot without any zero */ return -1; } /* size of the rest buffer without leading zeros */ bufsz -= b - buf; /* does the rest buffer contain a dot? */ lg = dot >= b && dot - b < maxdigits? 1 : 0; /* points behind the last significant digit */ p = b + _min(maxdigits + lg, bufsz); /* digits, limited by MAXDIGITS */ lg = _min(maxdigits, bufsz - lg); /* reduce lg by the number of trailing zeros */ for (; *--p == '0'; --lg); if (*(p--) == '.') for (; *(p--) == '0'; --lg); /* get a bc_num of sufficient size */ f->significand = bc_new_num(1, lg - 1); if (f->significand == NULL) return -1; /* exponent is forced to 0 */ f->exponent = 0; /* copy lg digits into bc_num buffer, scan the rest for invalid characters */ bcp = _valueof(f); for(; --bufsz >= 0;) { c = *(b++); if (c != '.') /* ignore a dot */ { if (c < '0' || c > '9') { /* invalid character */ float_setnan(f); return -1; } if (--lg >= 0) *(bcp++) = c - '0'; } } if (leadingzeros != NULL) *leadingzeros = zeros; #ifdef FLOATDEBUG _setvalue_(f); #endif return dot == NULL? -1 : dot - buf; } void float_setexponent( floatnum f, int exponent) { if (!_is_special(f)) { if (!float_isvalidexp(exponent)) float_setnan(f); else f->exponent = exponent; } } void float_setscientific( floatnum f, const char* buf, int bufsz) { int exppos; int zeros; int dotpos; unsigned exp, ovfl; signed char expsign, msign; const char* expptr; const char* last; char c; float_setnan(f); if (bufsz == NULLTERMINATED) bufsz = strlen(buf); /* find the offset of the exponent character, or -1, if not found */ for(exppos = bufsz; --exppos >= 0;) if ((c = *(buf+exppos)) == 'E' || c == 'e') break; /* marks the end of the exponent string */ last = buf + bufsz; /* pre-set exponent to +0, which is the right value, if there is no exponent. */ exp = 0; expsign = 1; ovfl = 0; if (exppos >= 0) { /* points behind the exponent character */ expptr = buf + (exppos + 1); if (expptr == last) /* do not accept an exponent char without an integer */ return; /* get the exponent sign */ switch(*expptr) { case '-': expsign = -1; /* and fall through */ case '+': ++expptr; } if (expptr == last) /* do not accept a sign without a digit following */ return; /* encode the sequence of digits into an unsignedeger */ for (;expptr != last ;) { if (*expptr < '0' || *expptr > '9') /* invalid char encountered */ return; ovfl = 10; if (_longmul(&exp, &ovfl)) { ovfl = *(expptr++) - '0'; _longadd(&exp, &ovfl); } if (ovfl != 0 || exp > EXPMAX+1) { /* do not return immediately, because the significand can be zero */ ovfl = 1; break; } } /* move the last pointer to the exponent char.*/ last = buf + exppos; } /* last points behind the significand part. exp is at most -EXPMIN */ /* get the sign of the significand */ msign = 1; if (buf != last) switch(*buf) { case '-': msign = -1; /* fall through */ case '+': ++buf; } /* let setsignificand convert the sequence of digits into a significand. If a dot is found, its position is given in dotpos, -1 otherwise. zeros are the count of leading '0' digits before the first non_zero digit. */ dotpos = float_setsignificand(f, &zeros, buf, last-buf); if (_is_special(f)) /* setsignificand either found a zero or encountered invalid characters */ return; /* if we did not find a dot, we assume an integer, and put the dot after last digit */ if (dotpos == -1) dotpos = last - buf; /* leading zeros shift the dot to the left. dotpos is now the exponent that results from the position of the dot in the significand. */ dotpos -= zeros+1; /* combine the dot position with the explicit exponent */ if (ovfl != 0 || !_checkadd(&dotpos, expsign * (int)exp)) /* exponent overflow */ float_setnan(f); float_setexponent(f, dotpos); float_setsign(f, msign); } /* normalizes a significand such that 1 <= x < 10. If the exponent overflows during this operation this is notified. */ static char _normalize( floatnum f) { _corr_lead_zero(f); if (f->significand != NULL && _lenof(f) > 1) _corr_overflow(f); if (f->significand != NULL) _corr_trailing_zeros(f); if (f->significand != NULL && !float_isvalidexp(f->exponent)) { float_seterror(Underflow); if (f->exponent > 0) float_seterror(Overflow); float_setnan(f); } #ifdef FLOATDEBUG if (f->significand != NULL) _setvalue_(f); #endif return f->significand != NULL; } void float_setinteger(floatnum dest, int value) { char buf[BITS_IN_UNSIGNED/3 + 3]; sprintf(buf, "%d", value); float_setscientific(dest, buf, NULLTERMINATED); } void float_move( floatnum dest, floatnum source) { if (dest != source) { float_setnan(dest); *dest = *source; float_create(source); } } /* creates a copy of and assigns it to . The significand is guaranteed to have +1 digits. The significand is truncated, or padded with zeros to the right, to achieve the desired length. may assume the special value EXACT, in which case a true copy is generated. This function allows an in-place copy (dest == source). */ static void _scaled_clone( floatnum dest, cfloatnum source, int scale) { /* dest == source allowed! */ bc_num mant; unsigned exp; signed char sign; mant = NULL; if(scale == EXACT) scale = _scaleof(source); if (dest == source && scale <= _scaleof(source)) { _setscale(dest, scale); return; } mant = bc_new_num(1, scale); scale = _min(scale, _scaleof(source)); memcpy(mant->n_value, _valueof(source), scale+1); sign = float_getsign(source); exp = source->exponent; float_setnan(dest); dest->exponent = exp; dest->significand = mant; #ifdef FLOATDEBUG _setvalue_(dest); #endif float_setsign(dest, sign); } char float_copy( floatnum dest, cfloatnum source, int digits) { int scale, save; if (digits == EXACT) digits = _max(1, float_getlength(source)); if (!_checkdigits(digits, NOSPECIALVALUE)) return _seterror(dest, InvalidPrecision); if (_is_special(source)) { if (dest != source) float_free(dest); *dest = *source; } else { // invariant: source has to be restored, if it is != dest scale = _min(digits - 1, _scaleof(source)); save = _limit_scale((floatnum)source, scale); _corr_trailing_zeros((floatnum)source); _scaled_clone(dest, source, EXACT); if (dest != source) _setscale(source, save); } return TRUE; } /* rounding a value towards zero */ static void _trunc( floatnum dest, cfloatnum x, int scale) { scale -= _bscandigit(x, scale, 0); _scaled_clone(dest, x, scale); #ifdef FLOATDEBUG _setvalue_(dest); #endif } /* rounding a value towards infinity */ static char _roundup( floatnum dest, cfloatnum x, int scale) { scale -= _bscandigit(x, scale, 9); _scaled_clone(dest, x, _max(0, scale)); if (scale < 0) { *_valueof(dest) = 1; if (!float_isvalidexp(++dest->exponent)) return FALSE; } else { ++*(_valueof(dest) + scale); } #ifdef FLOATDEBUG _setvalue_(dest); #endif return TRUE; } char float_round( floatnum dest, cfloatnum src, int digits, roundmode mode) { int scalediff, scale; char digit; signed char sign, updown; if (mode > TOMINUSINFINITY) return _seterror(dest, InvalidParam); if (!_checkdigits(digits, NOSPECIALVALUE)) return _setnan(dest); if (float_isnan(src)) return _seterror(dest, NoOperand); updown = 0; scale = digits - 1; if (float_getlength(src) > digits) { sign = float_getsign(src); switch(mode) { case TONEAREST: scalediff = _scaleof(src) - scale; if (scalediff > 0) { digit = _digit(src, digits); if (digit < 5 || (digit == 5 && scalediff == 1 && (_digit(src, scale) & 1) == 0)) updown = -1; else updown = 1; } break; case TOZERO: updown = -1; break; case TOINFINITY: updown = 1; break; case TOPLUSINFINITY: updown = sign; break; case TOMINUSINFINITY: updown = -sign; break; } } switch (updown) { case 1: if (!_roundup(dest, src, scale)) return _seterror(dest, Overflow); break; case 0: float_copy(dest, src, digits); break; case -1: _trunc(dest, src, scale); break; } return TRUE; } char float_int( floatnum f) { if (!_checknan(f)) return FALSE; if (f->exponent < 0) float_setzero(f); else if (!float_iszero(f)) float_round(f, f, f->exponent+1, TOZERO); return TRUE; } char float_frac( floatnum f) { if (!_checknan(f) || float_iszero(f) || f->exponent < 0) return !float_isnan(f); if (_scaleof(f) <= f->exponent) float_setzero(f); else { int leadingzeros = 0; _hidefirst(f, f->exponent + 1); leadingzeros = _scan_digit(_valueof(f), float_getlength(f), 0); _hidefirst(f, leadingzeros); f->exponent = -leadingzeros - 1; #ifdef FLOATDEBUG _setvalue_(f); #endif } return TRUE; } /* the general purpose add/subtract routine that deals with the ordinary case. */ static char _addsub_normal( floatnum dest, floatnum summand1, floatnum summand2, int digits) { floatstruct tmp; int expdiff; int scale; int fulllength; int extradigit; /* the operands are ordered by their exponent */ expdiff = (unsigned)(summand1->exponent - summand2->exponent); /* the full length of the sum (without carry) */ fulllength = _max(expdiff + _scaleof(summand2), _scaleof(summand1)) + 1; extradigit = 0; if (digits == EXACT || digits > fulllength) digits = fulllength; else { if (float_getsign(summand1) + float_getsign(summand2) == 0) extradigit = 1; /* a true subtraction needs no space for a carry */ if (expdiff > digits + extradigit) /* second operand underflows due to exponent diff */ return float_copy(dest, summand1, digits+extradigit); } if (digits > maxdigits) return _seterror(dest, InvalidPrecision); /* we cannot add the operands directly because of possibly different exponents. So we assume the second operand "to be OK" and shift the decimal point of the first appropriately to the right. There is a cheap way to do this: increment len by expdiff and decrement scale by the same amount. But: Check the operand is long enough to do this. */ float_create(&tmp); if (_scaleof(summand1) < expdiff) { _scaled_clone(&tmp, summand1, expdiff); summand1 = &tmp; } scale = digits + extradigit - (int)expdiff - 1; _movepoint(summand1, expdiff); /* truncate overly long operands */ _limit_scale(summand1, scale); _limit_scale(summand2, scale); /* add */ dest->exponent = summand2->exponent; bc_add(summand1->significand, summand2->significand, &(dest->significand), scale); float_free(&tmp); return _normalize(dest); } static char _sub_checkborrow( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* the operands have opposite signs, the same exponent, but their first digit of the significand differ. The operands are ordered by this digit. */ int result; int borrow; int scale1, scale2; char save; char* v1; char* v2; /* Cancellation occurs, when the operands are of type p.000...yyy - q.999...xxx, p-q == 1, because a borrow propagates from the difference ..0yyy.. - ..9xxx.., leaving zeros in the first part. We check for this here. */ borrow = 0; if (_digit(summand1, 0) - _digit(summand2, 0) == 1) { scale1 = _scaleof(summand1); scale2 = _scaleof(summand2); if (scale1 == 0) /* the special case of a one-digit first operand p. - q.999..xxx */ borrow = _scan_digit(_valueof(summand2) + 1, scale2, 9); else if (scale2 > 0) /* count the 0 - 9 pairs after the first digit, the area where a borrow can propagate */ borrow = _scan_09pairs(summand1, summand2, _min(scale1, scale2)); /* In case of a one-digit second operand (p.yyy.. - q. == 1.yyy..), nothing is cancelled out. Borrow is already set to 0, and this is the correct value for this case, so nothing has to be done here */ if (borrow > 0) { /* we have cancellation here. We skip all digits, that cancel out due to a propagating borrow. These include the first digit and all following (0,9) digit pairs, except the last one. The last pair may be subject to cancellation or not, we do not care, because the following digit pair either yields a non-zero difference, or creates no borrow. Our standard adder is good enough to deal with such a limited cancelling effect. We will replace the last (0,9) digit pair with a (9,8) pair. This prevents the creation of a borrow, and yet, will yield the correct result */ /* hide all digits until the last found 0 - 9 pair */ summand2->exponent -= borrow; summand1->exponent -= borrow; /* in case of a one-digit significand, there is nothing to hide */ if (scale1 > 0) _hidefirst(summand1, borrow); _hidefirst(summand2, borrow); /* we replace the last found 0 - 9 pair by a 9 - 8 pair, avoiding a carry, yet yielding the correct result */ save = *(v1 = _valueof(summand1)); *v1 = 9; *(v2 = _valueof(summand2)) = 8; } } result = _addsub_normal(dest, summand1, summand2, digits); /* restore the modified digits */ if (borrow > 0) { if (summand1 != dest) *v1 = save; if (summand2 != dest) *v2 = 9; } return result; } static char _sub_expdiff0( floatnum dest, floatnum summand1, floatnum summand2, int digits) { int eq; int result; /* the operands are ordered by their significand length, and have the same exponent, and different sign */ /* One type of cancellation is when both significands set out with the same digits. Since these digits cancel out during subtraction, we look out for the first pair of different digits. eq receives the number of equal digits, which may be 0 */ eq = _scan_equal(summand1, summand2); if (float_getlength(summand2) == eq) { /* the complete second operand is cancelled out */ if (float_getlength(summand1) == eq) /* op1 == -op2 */ return _setzero(dest); /* If xxx.. denotes the second operand, the (longer) first one is of form xxx..yyy.., since it has the same digits in the beginning. During subtraction the xxx... part is cancelled out, and this leaves yyy... as the subtraction result. By copying the yyy... to the result, we can shortcut the subtraction. But before doing so, we have to check yyy... for leading zeros, because the cancellation continues in this case. */ eq += _scan_digit(_valueof(summand1) + eq, float_getlength(summand1) - eq, 0); _hidefirst(summand1, eq); result = float_copy(dest, summand1, digits); dest->exponent -= eq; return result != 0 && _normalize(dest); } /* hide the identical digits, and do the subtraction without them. */ summand1->exponent -= eq; summand2->exponent -= eq; _hidefirst(summand1, eq); _hidefirst(summand2, eq); /* order the operands by their first digit */ if (_digit(summand1, 0) >= _digit(summand2, 0)) return _sub_checkborrow(dest, summand1, summand2, digits); return _sub_checkborrow(dest, summand2, summand1, digits); } static char _sub_expdiff1( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* Cancellation occurs when subtracting 0.9xxx from 1.0yyy */ int result; char singledigit; char* v1; char* v2; /* the operands have different sign, are ordered by their exponent, and the difference of the exponents is 1 */ /* 1.0yyy may be given as a single digit 1 or as a string of digits starting with 1.0 */ singledigit = _scaleof(summand1) == 0; if (_digit(summand1, 0) != 1 || _digit(summand2, 0) != 9 || (!singledigit && _digit(summand1, 1) != 0)) return _addsub_normal(dest, summand1, summand2, digits); /* we have cancellation here. We transform this case into that of equal exponents. */ /* we align both operands by hiding the first digit (1) of the greater operand. This leaves .0yyy which matches the second operand .9xxx. Unfortunately, if the first operand has only one digit, we cannot hide it, so we have to work around this then. */ if (!singledigit) _hidefirst(summand1, 1); /* we change the leading digits into a '9' and a '8' resp. So we finally subtract .8xxx from .9yyy, yielding the correct result. */ v1 = _valueof(summand1); v2 = _valueof(summand2); *v1 = 9; *v2 = 8; summand1->exponent--; result = _sub_checkborrow(dest, summand1, summand2, digits); /* restore the original digits */ if (summand1 != dest) *v1 = singledigit? 1 : 0; if (summand2 != dest) *v2 = 9; return result; } static char _sub_ordered( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* we have to check for cancellation when subtracting. Cancellation occurs when the operands are almost equal in magnitude. E.g. in 1.234 - 1.226 = 0.008, the result is on quite a different scale than the operands. Actually, this is a big problem, because it means that the (true) subtraction is numerically not stable. There is no way to get around this; you always have to take this into account, when subtracting. We make the best out of it, and check for cancellation in advance, so the result is at least valid to all digits, if the operands are known to be exact. Cancellation occurs only, if the difference between the exponents is 1 at most. We prepare the critical cases in specialized routines, and let the standard routine do the rest. */ /* the operands are ordered by their exponent */ unsigned expdiff; expdiff = (unsigned)(summand1->exponent - summand2->exponent); switch (expdiff) { case 0: /* order the operands by their length of the significands */ if (float_getlength(summand1) >= float_getlength(summand2)) return _sub_expdiff0(dest, summand1, summand2, digits); return _sub_expdiff0(dest, summand2, summand1, digits); case 1: return _sub_expdiff1(dest, summand1, summand2, digits); } return _addsub_normal(dest, summand1, summand2, digits); } static char _addsub_ordered( floatnum dest, floatnum summand1, floatnum summand2, int digits) { /* operands are ordered by their exponent */ /* handle a bunch of special cases */ if (!_checkdigits(digits, EXACT) || !_checknan(summand1)) return _setnan(dest); if (float_iszero(summand2)) return float_copy(dest, summand1, digits); /* separate true addition from true subtraction */ /*start edit jingzhou 20200807 * 处理过长的小数,截掉超过精度的部分后进行运算处理 * 例:无限循环小数,1/3000,减一加一后,n_value中的长度由原有的范围精度 * HMATH_WORKING_PREC = DECPRECISION(运算精度) + 2,减少了位数,即0.0003的前三个0 * 再次将结果去减1/3000时,最后几位无法对齐,导致运算结果为-3.33×e82。现将超过的部分截掉 */ // int overprec_part_s1 = summand1->significand->n_scale - summand1->exponent - DECPRECISION; // int overprec_part_s2 = summand2->significand->n_scale - summand2->exponent - DECPRECISION; // if(overprec_part_s1 > 0 && DECPRECISION + summand1->exponent > 0) // { // float_round(summand1,summand1,DECPRECISION + summand1->exponent + 3,TONEAREST); // } // if(overprec_part_s2 > 0 && DECPRECISION + summand2->exponent > 0) // { // float_round(summand2,summand2,DECPRECISION + summand2->exponent + 3,TONEAREST); // } //end edit jingzhou 20200807 if (float_getsign(summand1) == float_getsign(summand2)) return _addsub_normal(dest, summand1, summand2, digits); return _sub_ordered(dest, summand1, summand2, digits); } char float_add( floatnum dest, cfloatnum summand1, cfloatnum summand2, int digits) { bc_struct bc1, bc2; floatstruct tmp1, tmp2; floatnum s1, s2; /* the adder may occasionally adjust operands to his needs. Hence we work on temporary structures */ s1 = dest; s2 = dest; if (dest != summand1) { _copyfn(&tmp1, summand1, &bc1); s1 = &tmp1; } if (dest != summand2) { _copyfn(&tmp2, summand2, &bc2); s2 = &tmp2; } /* order the operands by their exponent. This should bring a NaN always to the front, and keeps zeros after any other number. */ if (s1->exponent >= s2->exponent) return _addsub_ordered(dest, s1, s2, digits); return _addsub_ordered(dest, s2, s1, digits); } char float_sub( floatnum dest, cfloatnum minuend, cfloatnum subtrahend, int scale) { int result; if (minuend == subtrahend) { /* changing the sign of one operand would change that of the other as well. So this is a special case */ if(!_checknan(minuend)) return FALSE; _setzero(dest); } /* do not use float_neg, because it may change float_error */ float_setsign((floatnum)subtrahend, -float_getsign(subtrahend)); result = float_add(dest, minuend, subtrahend, scale); if (dest != subtrahend) float_setsign((floatnum)subtrahend, -float_getsign(subtrahend)); return result; } char float_mul( floatnum dest, cfloatnum factor1, cfloatnum factor2, int digits) { int result; int fullscale; int savescale1, savescale2; int scale; /* handle a bunch of special cases */ if (!_checkdigits(digits, EXACT) || !_checknan(factor1) || !_checknan(factor2)) /* invalid scale value or NaN operand */ return _setnan(dest); if (float_iszero(factor1) || float_iszero(factor2)) return _setzero(dest); scale = digits - 1; fullscale = _scaleof(factor1) + _scaleof(factor2); if (digits == EXACT || scale > fullscale) scale = fullscale; if (scale >= maxdigits) /* scale too large */ return _seterror(dest, InvalidPrecision); /* limit the scale of the operands to sane sizes */ savescale1 = _limit_scale((floatnum)factor1, scale); savescale2 = _limit_scale((floatnum)factor2, scale); /* multiply */ dest->exponent = factor1->exponent + factor2->exponent; bc_multiply(factor1->significand, factor2->significand, &(dest->significand), scale); result = _normalize(dest); /* reverse order is necessary in case factor1 == factor2 */ if (dest != factor2) _setscale(factor2, savescale2); if (dest != factor1) _setscale(factor1, savescale1); return result; } char float_div( floatnum dest, cfloatnum dividend, cfloatnum divisor, int digits) { int result; int savescale1, savescale2; int exp; /* handle a bunch of special cases */ if (!_checkdigits(digits, INTQUOT) || !_checknan(dividend) || !_checknan(divisor)) return _setnan(dest); if (float_iszero(divisor)) return _seterror(dest, ZeroDivide); if (float_iszero(dividend)) /* 0/x == 0 */ return _setzero(dest); exp = dividend->exponent - divisor->exponent; /* check for integer quotient */ if(digits == INTQUOT) { if (exp < 0) return _setzero(dest); digits = exp; } /* scale OK? */ if(digits > maxdigits) return _seterror(dest, InvalidPrecision); /* limit the scale of the operands to sane sizes */ savescale1 = _limit_scale((floatnum)dividend, digits); savescale2 = _limit_scale((floatnum)divisor, digits); /* divide */ result = TRUE; dest->exponent = exp; bc_divide(dividend->significand, divisor->significand, &(dest->significand), digits); if (bc_is_zero(dest->significand)) float_setzero(dest); else result = _normalize(dest); /* reverse order is necessary in case divisor == dividend */ if (dest != divisor) _setscale(divisor, savescale2); if (dest != dividend) _setscale(dividend, savescale1); return result; } char float_divmod( floatnum quotient, floatnum remainder, cfloatnum dividend, cfloatnum divisor, int digits) { int exp, exp1; if (!_checkdigits(digits, INTQUOT) || !_checknan(dividend) || !_checknan(divisor) || quotient == remainder || float_iszero(divisor) || float_getlength(divisor) > maxdigits) { if (quotient == remainder) float_seterror(InvalidParam); if (float_getlength(divisor) > maxdigits) float_seterror(TooExpensive); if (float_iszero(divisor)) float_seterror(ZeroDivide); float_setnan(quotient); return _setnan(remainder); } if (float_iszero(dividend)) { float_setzero(quotient); return _setzero(remainder); } exp1 = dividend->exponent; exp = exp1 - divisor->exponent; if(digits-- == INTQUOT) { if (exp < 0) { if (float_copy(remainder, dividend, EXACT)) return _setzero(quotient); return _setnan(quotient); } digits = exp; } if (digits > maxdigits) { float_setnan(quotient); return _seterror(remainder, TooExpensive); } /* divide */ quotient->exponent = exp; remainder->exponent = exp1; bc_divmod(dividend->significand, divisor->significand, &(quotient->significand), &(remainder->significand), digits); /* if something goes wrong (one of the results overflows or underflows), always set both quotient and remainder to NaN */ if (bc_is_zero(remainder->significand)) float_setzero(remainder); else if (!_normalize(remainder)) return _setnan(quotient); if (bc_is_zero(quotient->significand)) float_setzero(quotient); else if (!_normalize(quotient)) return _setnan(remainder); return TRUE; } char float_sqrt(floatnum value, int digits) { if (!_checkdigits(digits, NOSPECIALVALUE) || !_checknan(value)) return _setnan(value); switch (float_getsign(value)) { case -1: return _seterror(value, OutOfDomain); case 0: return TRUE; } if ((value->exponent & 1) != 0) { if (float_getlength(value) == 1) _scaled_clone(value, value, 1); _movepoint(value, 1); } bc_sqrt(&value->significand, digits - 1); #ifdef FLOATDEBUG _setvalue_(value); #endif if (value->exponent >= 0) value->exponent >>= 1; else value->exponent = -((1-value->exponent) >> 1); return TRUE; } deepin-calculator-5.7.21/3rdparty/math/floatnum.h000066400000000000000000000437231423020056600217070ustar00rootroot00000000000000/* floatnum.h: Arbitrary precision floating point numbers header file. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATNUM_H # define FLOATNUM_H #include "number.h" #include "floatconfig.h" #include "floatio.h" #define NULLTERMINATED (-20) #define UNORDERED (-2) #define EXACT (-101) #define INTQUOT (-102) #define float_free(f) float_setnan(f) #ifdef __cplusplus extern "C" { #endif extern int maxdigits; typedef struct { bc_num significand; int exponent; #ifdef FLOATDEBUG char value[110]; #endif /* FLOATDEBUG */ } floatstruct; typedef floatstruct* floatnum; typedef const floatstruct* cfloatnum; typedef enum {TONEAREST, TOZERO, TOINFINITY, TOPLUSINFINITY, TOMINUSINFINITY} roundmode; /* initializes this module. Has to be called prior to the first use of any of the following functions */ void floatnum_init(); /* sets the error to `code' unless it is already set */ void float_seterror(Error code); /* gets the last error and clears the error afterwards */ Error float_geterror(); /* returns the current overflow limit. It is the maximum possible exponent. The smallest exponent is -`return value' - 1. This function never reports an error */ int float_getrange(); /* sets the overflow/underflow limit. Subsequent arithmetic results with exponents between `maxexp' >= exponent >= -`maxexp'-1 are considered valid, all others trigger overflow/underflow errors. `maxexp' cannot be greater than MAXEXP and not less than 1. Exceeding arguments are replaced by the respective limit. The return value is the old overflow limit. This function affects future results only. Current stored values are not subject to overflow/underflow checking, even when they are used as parameters to an operation. This function never reports an error */ int float_setrange(int maxexp); /* returns the current precision limit. Arithmetic results may be cut off after this number of decimal digits */ int float_getprecision(); /* sets the current maximum precision (in decimal digits) that is used by basic arithmetic operations. The precision is at least 1 and at most MAXDIGITS. An exceeding argument is replaced by the respective limit. Setting a new precision affects future operations only; currently set variables are kept unmodified. The return value is the old precision limit. This function never reports an error */ int float_setprecision(int digits); /* checks whether the submitted exponent is within the current overflow and underflow limits. This function never reports an error */ char float_isvalidexp(int exp); /* initializes a new floatnum to NaN. Call this before the first use of a floatnum variable. The destructing function is float_setnan or its alias, float_free. This function never reports an error. */ void float_create(floatnum f); /* finalizes a variable. To avoid memory leaks, call this before a floatnum is freed. A special value (NaN = not a number) is loaded into `f', so any subsequent arithmetic operation on this variable will fail. However, a variable such finalized can still be re-used without prior initialization, by making it the destination of an operation. If you wish to deliberately "empty" a variable, without detroying it, call this function. An alias "float_free" to this function is defined that you may use anywhere as a replacement for float_setnan. This function never reports an error. */ void float_setnan(floatnum f); /* returns the base 10 exponent of the value in `f'. If `f' is zero or NaN, the returned exponent is 0. This function never reports an error. */ int float_getexponent(cfloatnum f); /* fills the buffer `buf' of size `bufsz' with an ASCII string representing the significand of `f'. No zeros are padded to the right to fill the buffer in case of a short significand. If `bufsz' <= 0, the function returns immediately with result 0. If the significand does not fit completely into the buffer, the output is stopped when the last buffer byte is written to. A non-zero significand yields a sequence of digits, without a decimal point; zero yields "0" and NaN "N". On truncation, no trailing zeros are removed. Exponent and sign are ignored, and no decimal point is written. No '\0' character is appended to the right. The return value are the number of characters written to the buffer. This function never reports an error. */ int float_getsignificand(char* buf, int bufsz, cfloatnum f); /* returns the number of digits in the significand, or 0 for NaN and zero. This function never reports an error. */ int float_getlength(cfloatnum f); /* returns 1, if `f' is positive, -1, if `f' is negative, and 0 if `f' is zero or NaN. This function never reports an error. */ signed char float_getsign(cfloatnum f); /* writes the value stored in `f' as an ASCIIZ string into a buffer of size `bufsz'. If the buffer is too small to hold the full value, the significand is truncated appropriately. If the buffer is too small to even store the most significant digit of the significand besides exponent and sign, nothing is stored at all, and -1 is returned. Else, the length of the output, but without the trailing \0 character, is returned. The output format is the usual scientific format. On truncation, no trailing zeros are removed from the output of the significand. Examples of an output: value output ----- ------ NaN NaN\0 0 0\0 1 1.e0\0 1.2 1.2e0\0 0.5 5.e-1\0 -1 -1.e0\0 1.009 1.00e0\0 (truncated to 3 digits) 10^10 1.e10\0 This function does not touch the adjacent bytes of the final output. If no reasonable output is possible, the complete buffer is left unchanged, not even the final \0 character is written. This function never reports an error. */ int float_getscientific(char* buf, int bufsz, cfloatnum f); /* gets the `ofs'-th digit from the decimal representation of the significand of `f'. If `ofs' is negative or greater equal to the length of the significand, 0 is returned. The return value is between 0 and 9 (not the ASCII representation of these digits (0x30 - 0x39)). This function never returns an error */ char float_getdigit(cfloatnum f, int ofs); /* sets the significand according to the the ASCII text in buffer buf of size `bufsz'. The buffer must contain digits '0' -'9' only, with one possible exception: A single decimal point ('.') may be placed anywhere in the buffer. It is skipped while encoding the significand. The function searches the buffer for the first non-zero digit, and starts the encoding from there. `f' is set to NaN, if the buffer fails to fulfill the above conditions. If the resulting significand exceeds digits, it is truncated. The exponent of `f' is set to 0, so the result is always NaN, 0 or a number between 1 and 9.99... If you want to set both the significand and the exponent of f, set the significand first. If `leadingzeros' is not NULL, and the result in `f' is neither zero nor NaN, the number of leading (and skipped) zeros are stored here. In case of NaN or zero, this value is 0. All trailing zeros in the significand of `f' are removed. The result is the position of the decimal point in `buf', or -1 if either none was found, or if it is not relevant (NaN or 0.0). This function never reports an error. */ int float_setsignificand(floatnum f, int* leadingzeros, const char* buf, int bufsz); /* sets the base 10 exponent of f to exponent. The significand is only changed when this operation fails. Integers greater than EXPMAX or smaller than EXPMIN are not accepted as exponent and let the operation fail, setting `f' to NaN. You cannot change the exponent of 0 or NaN, this is ignored. If you want to set both the significand and the exponent of `f', set the significand first. This function never reports an error. */ void float_setexponent(floatnum f, int exponent); /* converts an ASCII string of length `bufsz' in `buf' to `f'. `bufsz' may assume the special value NULLTERMINATED, in which case the first found \0 character terminates the input. The input format is [+|-][digit...][.[digit...][(e|E)[+|-]digit...]] At least one digit of the significand has to be present. Any non-valid input is converted into a NaN. This function never reports an error. */ void float_setscientific(floatnum f, const char* buf, int bufsz); /* if `s' is 1 or -1, the sign of `f' is set accordingly. Has no effect, if `f' == NaN or zero, or `s' == 0. `f' is set to NaN, if |s| > 1. This function never reports an error. */ void float_setsign(floatnum f, signed char s); /* sets dest to the value in `value'. This function never reports an error. */ void float_setinteger(floatnum dest, int value); /* sets a variable to the numerical value zero. This function never reports an error. */ void float_setzero (floatnum f); /* returns 1, if f contains the special NaN value, 0 otherwise. This function never reports an error. */ char float_isnan(cfloatnum f); /* returns 1, if f contains the value zero, 0 otherwise. This function never reports an error. */ char float_iszero(cfloatnum f); /* copies source to dest, limiting the significand to at most `digits' digits. The parameter `digits' may assume the value EXACT, in which case a full copy is made. If source and dest coincide, float_copy tries to re-use the significand. This prevents unnecessary copying. If a copy has to be made, the allocated space is just big enough to hold the significand, so no memory is wasted. A return value of 0 indicates an error. errors: InvalidPrecision, if `digits', or the length of the copy, exceeds `maxdigits' */ char float_copy(floatnum dest, cfloatnum source, int digits); /* transfers the contents of source to dest. source is assigned NaN afterwards. In contrast to float_copy, float_move does not create a copy of the significand (which employs memory allocation and copying), but transfers simply the data from the source to the destination. This function has been designed to implement, for example, swapping of variables in a fast way. If dest == source, nothing happens. This function never reports an error */ void float_move(floatnum dest, floatnum source); /* changes the value of `f' to -`f'. Has no effect on zero or NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_neg(floatnum f); /* changes the sign of `f', if `f' is negative. Has no effect on a NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_abs(floatnum f); /* compares two values and returns +1 if val1 > val2, 0 if val1 == val2 and -1 if val1 < val2. This function is not intended to be used with NaN's. If you pass it as an argument, UNORDERED is returned to indicate an error. errors: NaNOperand */ signed char float_cmp(cfloatnum val1, cfloatnum val2); /* rounds `f' to `digits' digits according to the submitted mode. If `digits' <= 0 or mode is not recognized, `f' is changed into a NaN. The same holds should the rounding operation overflow. mode == TONEAREST: checks whether the first cut off digit is a '5' or greater. In this case, the absolute value of the significand is rounded up, otherwise rounded down. If the part cut off is a single digit '5', the significand is rounded such that its last digit is even. mode == TOZERO: cuts off all digits after the `digits'th digit. This mode never overflows. mode = TOINFINITY: rounds positive numbers up, negative numbers down (towards greater magnitude). mode == TOPLUSINFINITY: always rounds up. So, negative values are effectively truncated. mode == TOMINUSINFINITY: always rounds down. So, negative values usually increase in magnitude. A return value of 0 indicates an error. errors: NaNOperand InvalidParam InvalidPrecision Overflow */ char float_round(floatnum dest, cfloatnum src, int digits, roundmode mode); /* cuts off the fractional part of `f'. The result is always less or equal in magnitude to the passed argument. A NaN yields a NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_int(floatnum f); /* cuts off the integer part of `f'. If the result is not equal to 0, it has the same sign as the argument. NaN yields NaN. A return value of 0 indicates an error. errors: NaNOperand */ char float_frac(floatnum f); /* adds the values in `summand1' and `summand2' and stores the result in `dest'. `dest' may coincide with either summand (or even both). The result is evaluated to `digits' or `digits'+1 digits. If `digits' is EXACT, the sum is evaluated to full scale (if possible). NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - `digits' is invalid, or the resulting digits exceed `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow */ char float_add(floatnum dest, cfloatnum summand1, cfloatnum summand2, int digits); /* subtracts `subtrahend' from `minuend' and stores the result in `dest'. `dest' may coincide with either operand (or even both). The result is evaluated to `digits' or `digits'+1 digits. If `digits' is EXACT, the difference is evaluated to full scale (if possible). NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - `digits' is invalid, or the resulting digits exceed `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow */ char float_sub(floatnum dest, cfloatnum minuend, cfloatnum subtrahend, int digits); /* multiplies both factors and stores the result in `dest'. `dest' may coincide with either factor (or even both). The result is evaluated to `digits' or `digits'+1 digits, or, if `digits' == EXACT, to full scale (if possible). NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - `digits' is invalid, or the resulting scale exceeds `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow */ char float_mul(floatnum dest, cfloatnum factor1, cfloatnum factor2, int digits); /* divides `dividend' by `divisor' and stores the result in `dest'. `dest' may coincide with either operand (or even both). The result is evaluated to `digits' or `digits'+1 digits, or, if `digits' == INTQUOT, to the size of the integer part of the quotient. EXACT is not allowed, even in cases where the dividend is divisible by the divisor. NaN is returned, if - (at least) one operand is NaN; - the result overflows or underflows; - the divisor is zero; - `digits' is invalid, or the effective scale exceeds `maxdigits'. A return value of 0 indicates an error. errors: NaNOperand InvalidPrecision Overflow Underflow ZeroDivide */ char float_div(floatnum dest, cfloatnum dividend, cfloatnum divisor, int digits); /* evaluates the quotient, using `digits' steps of the schoolbook division algorithm. The quotient, thus, has `digits' or `digits'-1 digits, and is always truncated towards zero. The remainder fulfills the equation: remainder = dividend - quotient * divisor. `digits' may assume the special value INTQUOT, in which case the integer part of the quotient is calculated. This function is an exact operation anyway, so EXACT is not allowed here. `digits' is subject to the `maxdigits' limit. `remainder' and `quotient' have to be different variables, but apart from this, there are no other restrictions on the passed variables. If this function fails, both result variables are set to NaN. A return value of 0 indicates an error. errors: NaNOperand InvalidParam InvalidPrecision TooExpensive Overflow Underflow ZeroDivide */ char float_divmod(floatnum quotient, floatnum remainder, cfloatnum dividend, cfloatnum divisor, int digits); /* computes the sqare root of `value' to `digits' or `digits'+1 digits. `digits' == EXACT is not allowed, even if the argument is a square. NaN is returned, if - the operand is NaN, - `digits' exceeds `maxdigits' - the operand is negative. A return value 0 indicates an error. errors: NaNOperand InvalidPrecision OutOfDomain */ char float_sqrt(floatnum value, int digits); /* a few convenience functions used everywhere */ char _setnan(floatnum result); char _seterror(floatnum result, Error code); char _checknan(cfloatnum f); char _setzero(floatnum x); #ifdef __cplusplus } #endif #endif /* FLOATNUM_H */ deepin-calculator-5.7.21/3rdparty/math/floatpower.c000066400000000000000000000034351423020056600222330ustar00rootroot00000000000000/* floatpower.c: power operation, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatpower.h" #include "floatipower.h" #include "floatcommon.h" #include "floatlog.h" #include "floatexp.h" char _raise( floatnum x, cfloatnum exponent, int digits) { int iexp; int extra; extra = float_getexponent(exponent); if (digits + extra > maxdigits) extra = maxdigits - digits; if (float_isinteger(exponent)) { iexp = leadingdigits(exponent, float_getexponent(exponent) + 1); if (float_iszero(exponent) || iexp != 0) return _raisei(x, iexp, digits+extra); } if (digits + extra > MATHPRECISION) extra = MATHPRECISION - digits; _ln(x, digits+extra); if (!float_mul(x, x, exponent, digits+extra)) return 0; return _exp(x, digits); } deepin-calculator-5.7.21/3rdparty/math/floatpower.h000066400000000000000000000024711423020056600222370ustar00rootroot00000000000000/* floatpower.h: power operation, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATPOWER_H # define FLOATPOWER_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif char _raise(floatnum x, cfloatnum exponent, int digits); #ifdef __cplusplus } #endif #endif /* FLOATPOWER_H */ deepin-calculator-5.7.21/3rdparty/math/floatseries.c000066400000000000000000000123561423020056600223730ustar00rootroot00000000000000/* floatseries.c: basic series, based on floatnum. */ /* Copyright (C) 2007 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floatseries.h" #include "floatconst.h" #include "floatcommon.h" #include "floatexp.h" /* Though all these serieses can be used with arguments |x| < 1 or even more, the computation time increases rapidly with x. Tests show, that for 100 digit results, it is best to limit x to |x| < 0.01..0.02, and use reduction formulas for greater x */ /* the Taylor series of arctan/arctanh x at x == 0. For small |x| < 0.01 this series converges very fast, yielding 4 or more digits of the result with every summand. The working precision is adjusted, so that the relative error for 100-digit arguments is around 5.0e-100. This means, the error is 1 in the 100-th place (or less) */ void arctanseries( floatnum x, int digits, char alternating) { int expx; int expsqrx; int pwrsz; int addsz; int i; floatstruct xsqr; floatstruct pwr; floatstruct smd; floatstruct sum; /* upper limit of log(x) and log(result) */ expx = float_getexponent(x)+1; /* the summands of the series from the second on are bounded by x^(2*i-1)/3. So the summation yields a result bounded by (x^3/(1-x*x))/3. For x < sqrt(1/3) approx.= 0.5, this is less than 0.5*x^3. We need to sum up only, if the first places of the result (roughly x) are touched. Ignoring the effect of a possile carry, this is only the case, if x*x >= 2*10^(-digits) > 10^(-digits) Example: for x = 9e-51, a 100-digits result covers the decimal places from 1e-51 to 1e-150. x^3/3 is roughly 3e-151, and so is the sum of the series. So we can ignore the sum, but we couldn't for x = 9e-50 */ if (float_iszero(x) || 2*expx < -digits) /* for very tiny arguments arctan/arctanh x is approx.== x */ return; float_create(&xsqr); float_create(&pwr); float_create(&smd); float_create(&sum); /* we adapt the working precision to the decreasing summands, saving time when multiplying. Unfortunately, there is no error bound given for the operations of bc_num. Tests show, that the last digit in an incomplete multiplication is usually not correct up to 5 ULP's. */ pwrsz = digits + 2*expx + 1; /* the precision of the addition must not decrease, of course */ addsz = pwrsz; i = 3; float_mul(&xsqr, x, x, pwrsz); float_setsign(&xsqr, alternating? -1 : 1); expsqrx = float_getexponent(&xsqr); float_copy(&pwr, x, pwrsz); float_setzero(&sum); for(; pwrsz > 0; ) { /* x^i */ float_mul(&pwr, &pwr, &xsqr, pwrsz+1); /* x^i/i */ float_divi(&smd, &pwr, i, pwrsz); /* The addition virtually does not introduce errors */ float_add(&sum, &sum, &smd, addsz); /* reduce the working precision according to the decreasing powers */ pwrsz = digits - expx + float_getexponent(&smd) + expsqrx + 3; i += 2; } /* add the first summand */ float_add(x, x, &sum, digits+1); float_free(&xsqr); float_free(&pwr); float_free(&smd); float_free(&sum); } /* series expansion of cos/cosh - 1 used for small x, |x| <= 0.01. The function returns 0, if an underflow occurs. The relative error seems to be less than 5e-100 for a 100-digit calculation with |x| < 0.01 */ char cosminus1series( floatnum x, int digits, char alternating) { floatstruct sum, smd; int expsqrx, pwrsz, addsz, i; expsqrx = 2 * float_getexponent(x); float_setexponent(x, 0); float_mul(x, x, x, digits+1); float_mul(x, x, &c1Div2, digits+1); float_setsign(x, alternating? -1 : 1); expsqrx += float_getexponent(x); if (float_iszero(x) || expsqrx < EXPMIN) { /* underflow */ float_setzero(x); return expsqrx == 0; } float_setexponent(x, expsqrx); pwrsz = digits + expsqrx + 2; if (pwrsz <= 0) /* for very small x, cos/cosh(x) - 1 = (-/+)0.5*x*x */ return 1; addsz = pwrsz; float_create(&sum); float_create(&smd); float_copy(&smd, x, pwrsz); float_setzero(&sum); i = 2; while (pwrsz > 0) { float_mul(&smd, &smd, x, pwrsz+1); float_divi(&smd, &smd, i*(2*i-1), pwrsz); float_add(&sum, &sum, &smd, addsz); ++i; pwrsz = digits + float_getexponent(&smd); } float_add(x, x, &sum, digits+1); float_free(&sum); float_free(&smd); return 1; } deepin-calculator-5.7.21/3rdparty/math/floatseries.h000066400000000000000000000032031423020056600223670ustar00rootroot00000000000000/* floatseries.h: header file for basic series, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATSERIES_H # define FLOATSERIES_H #include "floatnum.h" #define artanhnear0(x, digits) arctanseries(x, digits, 0) #define arctannear0(x, digits) arctanseries(x, digits, 1) #define coshminus1near0(x, digits) cosminus1series(x, digits, 0) #define cosminus1near0(x, digits) cosminus1series(x, digits, 1) #ifdef __cplusplus extern "C" { #endif void arctanseries(floatnum x, int digits, char alternating); char cosminus1series(floatnum x, int digits, char alternating); #ifdef __cplusplus } #endif #endif /* FLOATSERIES_H */ deepin-calculator-5.7.21/3rdparty/math/floattrig.c000066400000000000000000000215471423020056600220500ustar00rootroot00000000000000/* floattrig.c: trigonometry functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #include "floattrig.h" #include "floatseries.h" #include "floatconst.h" #include "floatcommon.h" /* evaluates arctan x for |x| <= 1 relative error for a 100 digit result is 6e-100 */ void _arctanlt1( floatnum x, int digits) { floatstruct tmp; int reductions; if (float_iszero(x)) return; float_create(&tmp); reductions = 0; while(float_getexponent(x) >= -2) { float_mul(&tmp, x, x, digits); float_add(&tmp, &tmp, &c1, digits+2); float_sqrt(&tmp, digits); float_add(&tmp, &tmp, &c1, digits+1); float_div(x, x, &tmp, digits); ++reductions; } arctannear0(x, digits); for (;reductions-- > 0;) float_add(x, x, x, digits+1); float_free(&tmp); } /* evaluates arctan x for all x. The result is in the range -pi/2 < result < pi/2 relative error for a 100 digit result is 9e-100 */ void _arctan( floatnum x, int digits) { signed char sgn; if (float_abscmp(x, &c1) > 0) { sgn = float_getsign(x); float_abs(x); float_reciprocal(x, digits); _arctanlt1(x, digits); float_sub(x, &cPiDiv2, x, digits+1); float_setsign(x, sgn); } else _arctanlt1(x, digits); } /* evaluates arccos(1+x) for -0.5 <= x <= 0 arccos(1+x) = arctan(sqrt(-x*(2+x))/(1+x)) the relative error of a 100 digit result is < 5e-100 */ void _arccosxplus1lt0_5( floatnum x, int digits) { floatstruct tmp; float_create(&tmp); float_add(&tmp, x, &c2, digits+1); float_mul(x, x, &tmp, digits+1); float_setsign(x, 1); float_sqrt(x, digits); float_sub(&tmp, &tmp, &c1, digits); float_div(x, x, &tmp, digits+1); _arctan(x, digits); float_free(&tmp); } /* evaluates arcsin x for -0.5 <= x <= 0.5 arcsin x = arctan(x/sqrt(1-x*x)) the relative error of a 100 digit result is < 5e-100 */ void _arcsinlt0_5( floatnum x, int digits) { floatstruct tmp; if (2*float_getexponent(x) < -digits) return; float_create(&tmp); float_mul(&tmp, x, x, digits); float_sub(&tmp, &c1, &tmp, digits); float_sqrt(&tmp, digits); float_div(x, x, &tmp, digits+1); _arctanlt1(x, digits); float_free(&tmp); } /* evaluates arccos x for -1 <= x <= 1. The result is in the range 0 <= result <= pi. The relative error for a 100 digit result is < 5e-100 */ void _arccos( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &c1Div2) > 0) { float_sub(x, x, &c1, digits+1); _arccosxplus1lt0_5(x, digits); } else { _arcsinlt0_5(x, digits); float_sub(x, &cPiDiv2, x, digits+1); } if (sgn < 0) float_sub(x, &cPi, x, digits+1); } /* evaluates arccos (1+x) for -2 <= x <= 0. The result is in the range 0 <= x <= pi */ void _arccosxplus1( floatnum x, int digits) { if (float_abscmp(x, &c1Div2) <= 0) _arccosxplus1lt0_5(x, digits); else { float_add(x, x, &c1, digits); _arccos(x, digits); } } /* evaluates arcsin x for -1 <= x <= 1. The result is in the range -pi/2 <= result <= pi/2 The relative error for a 100 digit result is < 8e-100 */ void _arcsin( floatnum x, int digits) { signed char sgn; if (float_abscmp(x, &c1Div2) <= 0) _arcsinlt0_5(x, digits); else { sgn = float_getsign(x); float_abs(x); _arccos(x, digits); float_sub(x, &cPiDiv2, x, digits); float_setsign(x, sgn); } } /* evaluates cos x - 1 for x < |pi/4| relative error for 100 digit results is < 5e-100 */ char _cosminus1ltPiDiv4( floatnum x, int digits) { floatstruct tmp; int reductions; if (float_iszero(x)) return 1; float_abs(x); reductions = 0; while(float_getexponent(x) >= -2) { float_mul(x, x, &c1Div2, digits+1); ++reductions; } if (!cosminus1near0(x, digits) && reductions == 0) return !float_iszero(x); float_create(&tmp); for(; reductions-- > 0;) { float_mul(&tmp, x, x, digits); float_add(x, x, x, digits+2); float_add(x, x, &tmp, digits+2); float_add(x, x, x, digits+2); } float_free(&tmp); return 1; } /* evaluate sin x for |x| <= pi/4, using |sin x| = sqrt((1-cos x)*(2 + cos x-1)) relative error for 100 digit results is < 6e-100*/ void _sinltPiDiv4( floatnum x, int digits) { floatstruct tmp; signed char sgn; if (2*float_getexponent(x)+2 < -digits) /* for small x: sin x approx.== x */ return; float_create(&tmp); sgn = float_getsign(x); _cosminus1ltPiDiv4(x, digits); float_add(&tmp, x, &c2, digits+1); float_mul(x, x, &tmp, digits+1); float_abs(x); float_sqrt(x, digits); float_setsign(x, sgn); float_free(&tmp); } /* evaluates tan x for |x| <= pi/4. The relative error for a 100 digit result is < 6e-100 */ void _tanltPiDiv4( floatnum x, int digits) { floatstruct tmp; signed char sgn; if (2*float_getexponent(x)+2 < -digits) /* for small x: tan x approx.== x */ return; float_create(&tmp); sgn = float_getsign(x); _cosminus1ltPiDiv4(x, digits); float_add(&tmp, x, &c2, digits+1); float_mul(x, x, &tmp, digits+1); float_abs(x); float_sqrt(x, digits); float_sub(&tmp, &tmp, &c1, digits); float_div(x, x, &tmp, digits+1); float_setsign(x, sgn); float_free(&tmp); } /* evaluates cos x for |x| <= pi */ void _cos( floatnum x, int digits) { signed char sgn; float_abs(x); sgn = 1; if (float_cmp(x, &cPiDiv2) > 0) { sgn = -1; float_sub(x, &cPi, x, digits+1); } if (float_cmp(x, &cPiDiv4) <= 0) { if (2*float_getexponent(x)+2 < - digits) float_setzero(x); else _cosminus1ltPiDiv4(x, digits); float_add(x, x, &c1, digits); } else { float_sub(x, &cPiDiv2, x, digits+1); _sinltPiDiv4(x, digits); } float_setsign(x, sgn); } /* evaluates cos x - 1 for |x| <= pi. This function may underflow, which is indicated by the return value 0 */ char _cosminus1( floatnum x, int digits) { float_abs(x); if (float_cmp(x, &cPiDiv4) <= 0) return _cosminus1ltPiDiv4(x, digits); _cos(x, digits); float_sub(x, x, &c1, digits); return 1; } /* evaluates sin x for |x| <= pi. */ void _sin( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &cPiDiv2) > 0) float_sub(x, &cPi, x, digits+1); if (float_cmp(x, &cPiDiv4) <= 0) _sinltPiDiv4(x, digits); else { float_sub(x, &cPiDiv2, x, digits+1); if (2*float_getexponent(x)+2 < - digits) float_setzero(x); else _cosminus1ltPiDiv4(x, digits); float_add(x, x, &c1, digits); } float_setsign(x, sgn); } /* evaluates tan x for |x| <= pi. A return value of 0 indicates that x = +/- pi/2 within small tolerances, so that tan x cannot be reliable computed */ char _tan( floatnum x, int digits) { signed char sgn; sgn = float_getsign(x); float_abs(x); if (float_cmp(x, &cPiDiv2) > 0) { float_sub(x, &cPi, x, digits+1); sgn = -sgn; } if (float_cmp(x, &cPiDiv4) <= 0) _tanltPiDiv4(x, digits); else { float_sub(x, &cPiDiv2, x, digits+1); if (float_iszero(x) || float_getexponent(x) < -digits) return 0; _tanltPiDiv4(x, digits); float_reciprocal(x, digits); } float_setsign(x, sgn); return 1; } char _trigreduce( floatnum x, int digits) { floatstruct tmp; int expx, save; signed char sgn; char odd; if (float_abscmp(x, &cPi) <= 0) return 1; expx = float_getexponent(x); if (expx > float_getlength(&cPi) - digits) return 0; save = float_setprecision(MAXDIGITS); float_create(&tmp); sgn = float_getsign(x); float_abs(x); float_divmod(&tmp, x, x, &cPi, INTQUOT); float_setprecision(save); odd = float_isodd(&tmp); if (odd) float_sub(x, x, &cPi, digits+1); if (sgn < 0) float_neg(x); float_free(&tmp); return 1; } void _sinpix( floatnum x, int digits) { char odd; odd = float_isodd(x); float_frac(x); float_mul(x, &cPi, x, digits+1); _sin(x, digits); if (odd) float_neg(x); } deepin-calculator-5.7.21/3rdparty/math/floattrig.h000066400000000000000000000036171423020056600220530ustar00rootroot00000000000000/* floattrig.h: trigonometry functions, based on floatnum. */ /* Copyright (C) 2007, 2008 Wolf Lammen. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: ookami1 gmx de mail: Wolf Lammen Oertzweg 45 22307 Hamburg Germany *************************************************************************/ #ifndef FLOATTRIG_H # define FLOATTRIG_H #include "floatnum.h" #ifdef __cplusplus extern "C" { #endif void _arctanlt1(floatnum x, int digits); void _arctan(floatnum x, int digits); void _arccosxplus1lt0_5(floatnum x, int digits); void _arcsinlt0_5(floatnum x, int digits); void _arccos(floatnum x, int digits); void _arccosxplus1(floatnum x, int digits); void _arcsin(floatnum x, int digits); char _cosminus1ltPiDiv4(floatnum x, int digits); void _sinltPiDiv4(floatnum x, int digits); void _tanltPiDiv4(floatnum x, int digits); void _cos(floatnum x, int digits); void _sin(floatnum x, int digits); char _tan(floatnum x, int digits); char _cosminus1(floatnum x, int digits); char _trigreduce(floatnum x, int digits); void _sinpix(floatnum x, int digits); #ifdef __cplusplus } #endif #endif /* FLOATTRIG_H */ deepin-calculator-5.7.21/3rdparty/math/hmath.cpp000066400000000000000000001707671423020056600215270ustar00rootroot00000000000000// HMath: C++ high precision math routines // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2007-2008, 2014 @heldercorreia // Copyright (C) 2008, 2009 Wolf Lammen // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "hmath.h" #include "floatcommon.h" #include "floatconst.h" #include "floatconvert.h" #include "floathmath.h" #include "rational.h" #include "../core/settings.h" #include #include #include #include #include #include #include #include #define RATIONAL_TOL HNumber("1e-20") // TODO make this configurable #define HMATH_WORKING_PREC (DECPRECISION + 3) #define HMATH_EVAL_PREC (HMATH_WORKING_PREC + 2) // TODO should go into a separate format file // default scale for fall back in formatting // rekols: 最大显示多少小数位 #define HMATH_MAX_SHOWN 15 // edit 20200326最大显示9 --->15小数位 #define HMATH_BIN_MAX_SHOWN ((33219 * HMATH_MAX_SHOWN) / 10000 + 1) #define HMATH_OCT_MAX_SHOWN ((11073 * HMATH_MAX_SHOWN) / 10000 + 1) #define HMATH_HEX_MAX_SHOWN ((8305 * HMATH_MAX_SHOWN) / 10000 + 1) /*------------------------ Helper routines -------------------------*/ static void checkfullcancellation(cfloatnum op1, cfloatnum op2, floatnum r) { if (float_getlength(op1) != 0 && float_getlength(op2) != 0 && float_getlength(r) != 0) { // NaN or zero not involved in computation. int expr = float_getexponent(r); if (float_getexponent(op1) - expr >= HMATH_WORKING_PREC - 1 || float_getexponent(op2) - expr >= HMATH_WORKING_PREC - 1) float_setzero(r); } } static char checkAdd(floatnum dest, cfloatnum s1, cfloatnum s2, int digits) { if (float_add(dest, s1, s2, digits) && float_getsign(s1) + float_getsign(s2) == 0) checkfullcancellation(s1, s2, dest); return float_isnan(dest); } static char checkSub(floatnum dest, cfloatnum s1, cfloatnum s2, int digits) { if (float_sub(dest, s1, s2, digits) && float_getsign(s1) - float_getsign(s2) == 0) checkfullcancellation(s1, s2, dest); return float_isnan(dest); } static void h_init() { static bool h_initialized = false; if (!h_initialized) { h_initialized = true; // TODO related to formats, get rid of it. float_stdconvert(); } } static void checkpoleorzero(floatnum result, floatnum x) { if (float_getlength(result) == 0 || float_getlength(x) == 0) return; int expx = float_getexponent(x) - HMATH_WORKING_PREC + 1; int expr = float_getexponent(result); if (expr <= expx) float_setzero(result); else if (expr >= -expx) { float_setnan(result); float_seterror(EvalUnstable); } } static char roundResult(floatnum x) { if (float_isnan(x)) // Avoids setting float_error. return 0; return float_round(x, x, HMATH_WORKING_PREC, TONEAREST); } /*--------------------------- HNumberPrivate --------------------*/ class HNumberPrivate { public: HNumberPrivate(); ~HNumberPrivate(); // TODO make this a variant floatstruct fnum; Error error; }; HNumberPrivate::HNumberPrivate() : error(Success) { h_init(); float_create(&fnum); } HNumberPrivate::~HNumberPrivate() { float_free(&fnum); } typedef char (*Float1ArgND)(floatnum x); typedef char (*Float1Arg)(floatnum x, int digits); typedef char (*Float2ArgsND)(floatnum result, cfloatnum p1, cfloatnum p2); typedef char (*Float2Args)(floatnum result, cfloatnum p1, cfloatnum p2, int digits); static Error checkNaNParam(const HNumberPrivate &v1, const HNumberPrivate *v2 = 0) { if (!float_isnan(&v1.fnum) && (!v2 || !float_isnan(&v2->fnum))) return Success; Error error = v1.error; if (error == Success && v2) error = v2->error; return error == 0 ? NoOperand : error; } void roundSetError(HNumberPrivate *dest) { dest->error = float_geterror(); floatnum dfnum = &dest->fnum; if (dest->error != Success) float_setnan(dfnum); if (!float_isnan(dfnum)) float_round(dfnum, dfnum, HMATH_WORKING_PREC, TONEAREST); } void call2Args(HNumberPrivate *dest, HNumberPrivate *n1, HNumberPrivate *n2, Float2Args func) { dest->error = checkNaNParam(*n1, n2); if (dest->error == Success) { floatnum dfnum = &dest->fnum; func(dfnum, &n1->fnum, &n2->fnum, HMATH_EVAL_PREC); roundSetError(dest); } } void call2ArgsND(HNumberPrivate *dest, HNumberPrivate *n1, HNumberPrivate *n2, Float2ArgsND func) { dest->error = checkNaNParam(*n1, n2); if (dest->error == Success) { floatnum dfnum = &dest->fnum; func(dfnum, &n1->fnum, &n2->fnum); roundSetError(dest); } } void call1Arg(HNumberPrivate *dest, HNumberPrivate *n, Float1Arg func) { dest->error = checkNaNParam(*n); if (dest->error == Success) { floatnum dfnum = &dest->fnum; float_copy(dfnum, &n->fnum, HMATH_EVAL_PREC); func(dfnum, HMATH_EVAL_PREC); roundSetError(dest); } } void call1ArgPoleCheck(HNumberPrivate *dest, HNumberPrivate *n, Float1Arg func) { dest->error = checkNaNParam(*n); if (dest->error == Success) { floatnum dfnum = &dest->fnum; float_copy(dfnum, &n->fnum, HMATH_EVAL_PREC); if (func(dfnum, HMATH_EVAL_PREC)) checkpoleorzero(dfnum, &n->fnum); roundSetError(dest); } } void call1ArgND(HNumberPrivate *dest, HNumberPrivate *n, Float1ArgND func) { dest->error = checkNaNParam(*n); if (dest->error == Success) { floatnum dfnum = &dest->fnum; float_copy(dfnum, &n->fnum, HMATH_EVAL_PREC); func(dfnum); roundSetError(dest); } } static char modwrap(floatnum result, cfloatnum p1, cfloatnum p2, int /*digits*/) { floatstruct tmp; float_create(&tmp); char ok = float_divmod(&tmp, result, p1, p2, INTQUOT); float_free(&tmp); return ok; } char idivwrap(floatnum result, cfloatnum p1, cfloatnum p2) { floatstruct tmp; int save = float_setprecision(DECPRECISION); float_create(&tmp); char ok = float_divmod(result, &tmp, p1, p2, INTQUOT); float_free(&tmp); float_setprecision(save); return ok; } /*-------------------------- HNumber -------------------*/ /** * Creates a new number. */ HNumber::HNumber() : d(new HNumberPrivate) { } /** * Copies from another number. */ HNumber::HNumber(const HNumber &hn) : d(new HNumberPrivate) { operator=(hn); } /** * Creates a new number from an integer value. */ HNumber::HNumber(int i) : d(new HNumberPrivate) { float_setinteger(&d->fnum, i); } /** * Creates a new number from a string. */ HNumber::HNumber(const char *str) : d(new HNumberPrivate) { t_itokens tokens; if ((d->error = parse(&tokens, &str)) == Success && *str == 0) d->error = float_in(&d->fnum, &tokens, Settings::instance()->proBitLength, 1); float_geterror(); } HNumber::HNumber(const QJsonObject &json) : d(new HNumberPrivate) { *this = deSerialize(json); } HNumber::HNumber(const char *str, bool b) : d(new HNumberPrivate) { t_itokens tokens; if ((d->error = parse(&tokens, &str)) == Success && *str == 0) { if (b) d->error = float_in(&d->fnum, &tokens, Settings::instance()->proBitLength, -1); else d->error = float_in(&d->fnum, &tokens, Settings::instance()->proBitLength, 1); } float_geterror(); } /** * Destroys this number. */ HNumber::~HNumber() { delete d; } /** * Returns the error code kept with a NaN. */ Error HNumber::error() const { return d->error; } /** * Returns true if this number is Not a Number (NaN). */ bool HNumber::isNan() const { return float_isnan(&d->fnum) != 0; } /** * Returns true if this number is zero. */ bool HNumber::isZero() const { return float_iszero(&d->fnum) != 0; } /** * Returns true if this number is more than zero. */ bool HNumber::isPositive() const { return float_getsign(&d->fnum) > 0; } /** * Returns true if this number is less than zero. */ bool HNumber::isNegative() const { return float_getsign(&d->fnum) < 0; } /** * Returns true if this number is integer. */ bool HNumber::isInteger() const { return float_isinteger(&d->fnum) != 0; } void HNumber::serialize(QJsonObject &json) const { json["value"] = HMath::format(*this, Format::Fixed() + Format::Precision(DECPRECISION)); } HNumber HNumber::deSerialize(const QJsonObject &json) { HNumber result; if (json.contains("value")) { QString str = json["value"].toString(); str.replace(",", "."); result = HNumber(str.toLatin1().constData()); } return result; } /** * Returns the number as an int. * It is meant to convert small (integer) numbers only and no * checking is done whatsoever. */ int HNumber::toInt() const { return float_asinteger(&d->fnum); } /** * Assigns from another number. */ HNumber &HNumber::operator=(const HNumber &hn) { d->error = hn.error(); float_copy(&d->fnum, &hn.d->fnum, EXACT); return *this; } /** * Adds another number. */ HNumber HNumber::operator+(const HNumber &num) const { if (this->isZero()) return num; if (num.isZero()) return *this; HNumber result; call2Args(result.d, d, num.d, checkAdd); return result; } /** * Adds another number. */ HNumber &HNumber::operator+=(const HNumber &num) { return operator=(*this + num); } /** * Subtract from another number. */ HNumber operator-(const HNumber &n1, const HNumber &n2) { HNumber result; call2Args(result.d, n1.d, n2.d, checkSub); return result; } /** * Subtract from another number. */ HNumber &HNumber::operator-=(const HNumber &num) { return operator=(*this - num); } /** * Multiplies with another number. */ HNumber HNumber::operator*(const HNumber &num) const { HNumber result; call2Args(result.d, d, num.d, float_mul); return result; } /** * Multiplies with another number. */ HNumber &HNumber::operator*=(const HNumber &num) { return operator=(*this * num); } /** * Divides with another number. */ HNumber HNumber::operator/(const HNumber &num) const { HNumber result; call2Args(result.d, d, num.d, float_div); return result; } /** * Divides with another number. */ HNumber &HNumber::operator/=(const HNumber &num) { return operator=(*this / num); } /** * Modulo (rest of integer division) */ HNumber HNumber::operator%(const HNumber &num) const { HNumber result; call2Args(result.d, d, num.d, modwrap); return result; } /** * Returns -1, 0, 1 if *this is less than, equal to, or more than other. */ int HNumber::compare(const HNumber &other) const { int result = float_relcmp(&d->fnum, &other.d->fnum, HMATH_EVAL_PREC - 1); float_geterror(); // clears error, if one operand was a NaN return result; } /** * Returns true if l is greater than r. */ bool operator>(const HNumber &l, const HNumber &r) { return l.compare(r) > 0; } /** * Returns true if l is less than r. */ bool operator<(const HNumber &l, const HNumber &r) { return l.compare(r) < 0; } /** * Returns true if l is greater than or equal to r. */ bool operator>=(const HNumber &l, const HNumber &r) { return l.compare(r) >= 0; } /** * Returns true if l is less than or equal to r. */ bool operator<=(const HNumber &l, const HNumber &r) { return l.compare(r) <= 0; } /** * Returns true if l is equal to r. */ bool operator==(const HNumber &l, const HNumber &r) { return l.compare(r) == 0; } /** * Returns true if l is not equal to r. */ bool operator!=(const HNumber &l, const HNumber &r) { return l.compare(r) != 0; } /** * Bitwise ANDs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber HNumber::operator&(const HNumber &num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_and); return result; } /** * Bitwise ANDs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber &HNumber::operator&=(const HNumber &num) { return operator=(*this & num); } /** * Bitwise ORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber HNumber::operator|(const HNumber &num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_or); return result; } /** * Bitwise ORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber &HNumber::operator|=(const HNumber &num) { return operator=(*this | num); } /** * Bitwise XORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber HNumber::operator^(const HNumber &num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_xor); return result; } /** * Bitwise XORs the integral parts of both operands. * Yields NaN, if any operand exeeds the logic range */ HNumber &HNumber::operator^=(const HNumber &num) { return operator=(*this ^ num); } /** * Bitwise NOTs the integral part *this. * Yields NaN, if *this exeeds the logic range */ HNumber HNumber::operator~() const { HNumber result; call1ArgND(result.d, d, float_not); return result; } /** * Changes the sign. */ HNumber operator-(const HNumber &x) { HNumber result; call1ArgND(result.d, x.d, float_neg); return result; } /** * Shifts the integral part of <*this> to the left by * the parameters value's bits. Zeros are shifted in * to the right, shifted out bits are dropped. * Yields NaN, if the operand exeeds the logic range, * or the shift count is not a non-negative integer. */ HNumber HNumber::operator<<(const HNumber &num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_shl); return result; } /** * Shifts the integral part of <*this> to the right by * the parameters value's bits. The most significand * bit is duplicated to the left, shifted out bits are dropped * (signed or arithmethic shift right). * Yields NaN, if the operand exeeds the logic range, * or the shift count is not a non-negative integer. */ HNumber HNumber::operator>>(const HNumber &num) const { HNumber result; call2ArgsND(result.d, d, num.d, float_shr); return result; } HNumber::Format::Format() : base(Base::Null) , radixChar(RadixChar::Null) , mode(Mode::Null) , cut(AutoCut::Null) , precision(PrecisionNull) { } HNumber::Format::Format(const HNumber::Format &other) : base(other.base) , radixChar(other.radixChar) , mode(other.mode) , cut(other.cut) , precision(other.precision) { } HNumber::Format HNumber::Format::operator+(const HNumber::Format &other) const { Format result; result.base = (this->base != Base::Null) ? this->base : other.base; result.radixChar = (this->radixChar != RadixChar::Null) ? this->radixChar : other.radixChar; result.mode = (this->mode != Mode::Null) ? this->mode : other.mode; result.cut = (this->cut != AutoCut::Null) ? this->cut : other.cut; result.precision = (this->precision != PrecisionNull) ? this->precision : other.precision; return result; } HNumber::Format HNumber::Format::Binary() { Format result; result.base = Base::Binary; return result; } HNumber::Format HNumber::Format::Octal() { Format result; result.base = Base::Octal; return result; } HNumber::Format HNumber::Format::Decimal() { Format result; result.base = Base::Decimal; return result; } HNumber::Format HNumber::Format::Hexadecimal() { Format result; result.base = Base::Hexadecimal; return result; } HNumber::Format HNumber::Format::Precision(int prec) { Format result; result.precision = prec; return result; } HNumber::Format HNumber::Format::Point() { Format result; result.radixChar = RadixChar::Point; return result; } HNumber::Format HNumber::Format::Comma() { Format result; result.radixChar = RadixChar::Comma; return result; } HNumber::Format HNumber::Format::General() { Format result; result.mode = Mode::General; return result; } HNumber::Format HNumber::Format::Fixed() { Format result; result.mode = Mode::Fixed; return result; } HNumber::Format HNumber::Format::Scientific() { Format result; result.mode = Mode::Scientific; return result; } HNumber::Format HNumber::Format::Engineering() { Format result; result.mode = Mode::Engineering; return result; } HNumber::Format HNumber::Format::Complement() { Format result; result.mode = Mode::Complement; return result; } HNumber::Format HNumber::Format::NCut() { Format result; result.cut = AutoCut::Ncut; return result; } namespace { char *_doFormat(cfloatnum x, signed char base, signed char expbase, char outmode, int prec, unsigned flags, bool iscut = true) { t_otokens tokens; char intbuf[BINPRECISION + 1]; char fracbuf[BINPRECISION + 1]; int sz = 0; char *str = nullptr; switch (base) { case 2: sz = BINPRECISION + 1; break; case 8: sz = OCTPRECISION + 1; break; case 10: sz = DECPRECISION + 1; break; case 16: sz = HEXPRECISION + 1; break; } tokens.intpart.sz = sz; tokens.intpart.buf = intbuf; tokens.fracpart.sz = sz; tokens.fracpart.buf = fracbuf; floatstruct tmp; float_create(&tmp); float_copy(&tmp, x, DECPRECISION + 2); if (float_out(&tokens, &tmp, prec, base, outmode) == Success) { if (base == 2) { sz = cattokensbin(nullptr, -1, &tokens, expbase, flags, Settings::instance()->proBitLength, iscut ? 1 : -1); str = (char *)malloc(sz); cattokensbin(str, sz, &tokens, expbase, flags, Settings::instance()->proBitLength, iscut ? 1 : -1); } else { sz = cattokens(nullptr, -1, &tokens, expbase, flags); str = (char *)malloc(sz); cattokens(str, sz, &tokens, expbase, flags); } } float_free(&tmp); return str; } /** * Formats the given number as string, using specified decimal digits. * Note that the returned string must be freed. */ char *formatFixed(cfloatnum x, int prec, int base = 10) { unsigned flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SUPPRESS_EXPZERO; if (base != 10) flags += IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE; if (prec < 0) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO; prec = HMATH_MAX_SHOWN; } //add 20200603 不需要为精度补0 if (prec == 15 || prec == 31 || prec == 65) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO; } char *result = _doFormat(x, base, base, IO_MODE_FIXPOINT, prec, flags); return result ? result : _doFormat(x, base, base, IO_MODE_SCIENTIFIC, HMATH_MAX_SHOWN, flags); } /** * Formats the given number as string, in scientific format. * Note that the returned string must be freed. */ char *formatScientific(cfloatnum x, int prec, int base = 10) { unsigned flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SUPPRESS_EXPPLUS; if (base != 10) flags += IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE; if (prec < 0) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO; prec = HMATH_MAX_SHOWN; } //add 20200603 不需要为精度补0 if (prec == 15 || prec == 31) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO; } return _doFormat(x, base, base, IO_MODE_SCIENTIFIC, prec, flags); } /** * Formats the given number as string, in engineering notation. * Note that the returned string must be freed. */ char *formatEngineering(cfloatnum x, int prec, int base = 10) { unsigned flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_EXPPLUS; if (base != 10) flags += IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE; if (prec <= 1) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO + IO_FLAG_SUPPRESS_DOT; prec = HMATH_MAX_SHOWN; } return _doFormat(x, base, base, IO_MODE_ENG, prec, flags); } /** * Formats the given number as string, using specified decimal digits. * Note that the returned string must be freed. */ char *formatGeneral(cfloatnum x, int prec, int base = 10) { // find the exponent and the factor int expd = float_getexponent(x); char *str; //edit 20200413 for bug-19653 if (expd > prec) str = formatScientific(x, prec, base); else if (expd < -prec) str = formatScientific(x, prec, base); else if ((expd < 0) && (prec >= 0) && (expd < -prec)) str = formatScientific(x, prec, base); else if ((expd < 0) && ((x->significand->n_scale + 1) <= prec - 2) && ((x->significand->n_scale - expd) > prec)) str = formatScientific(x, prec, base); else if ((expd < -3) && ((x->significand->n_scale + 1) > prec - 2)) str = formatScientific(x, prec, base); else str = formatFixed(x, prec, base); //edit 20200509 当出现循环小数时,位数由于小于科学计数法的临界值,format后进位,导致0.999...变成1e0 QString strnew = QString(QLatin1String(str)); strnew.remove(QRegExp("[^0-9E]")); int e = strnew.indexOf("E"); if (e > 0) { if (strnew.left(e).length() + (strnew.right(strnew.length() - e - 1)).toInt() < prec + 2) str = formatFixed(x, prec, base); } return str; } /** add jingzhou 20201118,增加补码方式的格式化 */ char *formatComplement(cfloatnum x, int prec, int base = 10, bool iscut = true) { unsigned flags = IO_FLAG_SUPPRESS_PLUS + IO_FLAG_SUPPRESS_DOT + IO_FLAG_SUPPRESS_EXPZERO; if (base != 10) flags += IO_FLAG_SHOW_BASE + IO_FLAG_SHOW_EXPBASE; if (prec < 0) { flags |= IO_FLAG_SUPPRESS_TRL_ZERO; prec = HMATH_MAX_SHOWN; } flags |= IO_FLAG_SUPPRESS_TRL_ZERO; char *result = _doFormat(x, base, base, IO_MODE_COMPLEMENT, prec, flags, iscut); return result; } } /* unnamed namespace */ /** * Formats the given number as string, using specified decimal digits. */ QString HMath::format(const HNumber &hn, HNumber::Format format) { char *rs = 0; if (format.precision < 0) // This includes PrecisionNull format.precision = -1; int base; switch (format.base) { case HNumber::Format::Base::Binary: base = 2; break; case HNumber::Format::Base::Octal: base = 8; break; case HNumber::Format::Base::Hexadecimal: base = 16; break; case HNumber::Format::Base::Decimal: case HNumber::Format::Base::Null: default: base = 10; break; } bool isautocut = true; if (format.cut == HNumber::Format::AutoCut::Ncut) isautocut = false; switch (format.mode) { case HNumber::Format::Mode::Fixed: rs = formatFixed(&hn.d->fnum, format.precision, base); break; case HNumber::Format::Mode::Scientific: rs = formatScientific(&hn.d->fnum, format.precision, base); break; case HNumber::Format::Mode::Engineering: rs = formatEngineering(&hn.d->fnum, format.precision, base); break; case HNumber::Format::Mode::Complement: if (base == 8 || base == 16) { rs = formatComplement(&hn.d->fnum, format.precision, 2, isautocut); const HNumber x(rs, true); free(rs); char *fixh = formatFixed(&x.d->fnum, format.precision, base); QString result(fixh); free(fixh); return result; } else if (base == 10) { rs = formatComplement(&hn.d->fnum, format.precision, 2, isautocut); const HNumber x(rs); free(rs); char *fixd = formatFixed(&x.d->fnum, format.precision, base); QString result(fixd); free(fixd); return result; } else { rs = formatComplement(&hn.d->fnum, format.precision, base, isautocut); } break; case HNumber::Format::Mode::General: default: rs = formatGeneral(&hn.d->fnum, format.precision, base); } QString result(rs); free(rs); return result; } /** * Converts radians to degrees. */ HNumber HMath::rad2deg(const HNumber &angle) { return angle * (HNumber(180) / HMath::pi()); } /** * Converts degrees to radians. */ HNumber HMath::deg2rad(const HNumber &angle) { return angle * (HMath::pi() / HNumber(180)); } /** * Converts radians to gons. */ HNumber HMath::rad2gon(const HNumber &angle) { return angle * (HNumber(200) / HMath::pi()); } /** * Converts gons to radians. */ HNumber HMath::gon2rad(const HNumber &angle) { return angle * (HMath::pi() / HNumber(200)); } /** * Returns the constant e (Euler's number). */ HNumber HMath::e() { HNumber value; float_copy(&value.d->fnum, &cExp, HMATH_EVAL_PREC); return value; } /** * Returns the constant Pi. */ HNumber HMath::pi() { HNumber value; float_copy(&value.d->fnum, &cPi, HMATH_EVAL_PREC); return value; } /** * Returns the constant Phi (golden number). */ HNumber HMath::phi() { HNumber value; float_copy(&value.d->fnum, &cPhi, HMATH_EVAL_PREC); return value; } /** * Returns a NaN (Not a Number) with error set to * passed parameter. */ HNumber HMath::nan(Error error) { HNumber result; result.d->error = error; return result; } /** * Returns the maximum of two numbers. */ HNumber HMath::max(const HNumber &n1, const HNumber &n2) { switch (float_cmp(&n1.d->fnum, &n2.d->fnum)) { case 0: case 1: return n1; case -1: return n2; default: return HMath::nan(checkNaNParam(*n1.d, n2.d)); } } /** * Returns the minimum of two numbers. */ HNumber HMath::min(const HNumber &n1, const HNumber &n2) { switch (float_cmp(&n1.d->fnum, &n2.d->fnum)) { case 0: case 1: return n2; case -1: return n1; default: return HMath::nan(checkNaNParam(*n1.d, n2.d)); } } /** * Returns the absolute value of n. */ HNumber HMath::abs(const HNumber &n) { HNumber result; call1ArgND(result.d, n.d, float_abs); return result; } /** * Rounds n to the specified decimal digits. */ HNumber HMath::round(const HNumber &n, int prec) { if (n.isNan()) return HMath::nan(checkNaNParam(*n.d)); HNumber result(n); floatnum rnum = &result.d->fnum; int exp = float_getexponent(rnum); // Avoid exponent overflow later. if (prec > HMATH_WORKING_PREC && exp > 0) prec = HMATH_WORKING_PREC; if (prec < 0 && -exp - 1 > prec) float_setzero(rnum); else if (exp + prec < HMATH_WORKING_PREC) { float_addexp(rnum, prec); float_roundtoint(rnum, TONEAREST); float_addexp(rnum, -prec); } return result; } /** * Truncates n to the specified decimal digits. */ HNumber HMath::trunc(const HNumber &n, int prec) { if (n.isNan()) return HMath::nan(checkNaNParam(*n.d)); HNumber result(n); floatnum rnum = &result.d->fnum; int exp = float_getexponent(rnum); // Avoid exponent overflow later on. if (prec > HMATH_WORKING_PREC && exp > 0) prec = HMATH_WORKING_PREC; if (prec < 0 && -exp - 1 > prec) float_setzero(rnum); else if (exp + prec < HMATH_WORKING_PREC) { float_addexp(rnum, prec); float_roundtoint(rnum, TOZERO); float_addexp(rnum, -prec); } return result; } /** * Returns the integer part of n. */ HNumber HMath::integer(const HNumber &n) { HNumber result; call1ArgND(result.d, n.d, float_int); return result; } /** * Returns the fraction part of n. */ HNumber HMath::frac(const HNumber &n) { HNumber result; call1ArgND(result.d, n.d, float_frac); return result; } #define CHECK_NAN \ if (n.isNan()) \ return HMath::nan(checkNaNParam(*n.d)); #define RETURN_IF_NEAR_INT \ HNumber nearest_int(n); \ float_roundtoint(&nearest_int.d->fnum, TONEAREST); \ /* Note: float_relcmp doesn't work here, because it's doesn't check the relative */ \ /* tolerance if exponents are not the same. */ \ /* FIXME: Put this value as parameter. */ \ /* Kudos to the guy who can figure out why we need such a small tolerance here. */ \ /* 1e-70 does not work, but 1e-10000 does. */ \ if (HMath::abs(n - nearest_int) < \ HNumber("1e-100") * HMath::abs(n + nearest_int)) /* FIXME: Make configurable. */ \ return nearest_int; /** * Returns the floor of n. */ HNumber HMath::floor(const HNumber &n) { CHECK_NAN; RETURN_IF_NEAR_INT; // Actual rounding, if needed. HNumber r(n); float_roundtoint(&r.d->fnum, TOMINUSINFINITY); return r; } /** * Returns the ceiling of n. */ HNumber HMath::ceil(const HNumber &n) { CHECK_NAN; RETURN_IF_NEAR_INT; // Actual rounding, if needed. HNumber r(n); float_roundtoint(&r.d->fnum, TOPLUSINFINITY); return r; } /** * Returns the greatest common divisor of n1 and n2. */ HNumber HMath::gcd(const HNumber &n1, const HNumber &n2) { if (!n1.isInteger() || !n2.isInteger()) { Error error = checkNaNParam(*n1.d, n2.d); if (error != Success) return HMath::nan(error); return HMath::nan(TypeMismatch); } HNumber a = abs(n1); HNumber b = abs(n2); if (a == 0) return b; if (b == 0) return a; // Run Euclidean algorithm. while (true) { a = a % b; if (a == 0) return b; b = b % a; if (b == 0) return a; } } /** * Performs an integer divide. */ HNumber HMath::idiv(const HNumber ÷nd, const HNumber &divisor) { HNumber result; call2ArgsND(result.d, dividend.d, divisor.d, idivwrap); if (result.error() == TooExpensive) result.d->error = Overflow; return result; } /** * Returns the square root of n. If n is negative, returns NaN. */ HNumber HMath::sqrt(const HNumber &n) { HNumber result; call1Arg(result.d, n.d, float_sqrt); return result; } /** * Returns the cube root of n. */ HNumber HMath::cbrt(const HNumber &n) { if (n.isNan()) return HMath::nan(checkNaNParam(*n.d)); if (n.isZero()) return n; HNumber r; floatnum rnum = &r.d->fnum; // iterations to approximate result // X[i+1] = (2/3)X[i] + n / (3 * X[i]^2)) // initial guess = sqrt(n) // r = X[i], q = X[i+1], a = n floatstruct a, q; float_create(&a); float_create(&q); float_copy(&a, &n.d->fnum, HMATH_EVAL_PREC); signed char sign = float_getsign(&a); float_abs(&a); int expn = float_getexponent(&a); float_setexponent(&a, expn % 3); expn /= 3; int digits = 0; float_copy(&q, &a, 2); float_sqrt(&q, 2); while (digits < HMATH_EVAL_PREC / 2 + 3) { digits = 4 * digits + 2; if (digits > HMATH_EVAL_PREC + 2) digits = HMATH_EVAL_PREC + 2; float_move(rnum, &q); float_mul(&q, rnum, rnum, digits); float_div(&q, &a, &q, digits); float_add(&q, &q, rnum, digits); float_add(&q, &q, rnum, digits); float_div(&q, &q, &c3, digits); float_sub(rnum, rnum, &q, 3); if (!float_iszero(rnum)) digits = float_getexponent(&q) - float_getexponent(rnum); } float_move(rnum, &q); float_free(&q); float_free(&a); float_setsign(rnum, sign); float_addexp(rnum, expn); roundResult(&r.d->fnum); return r; } /** * Raises n1 to an integer n. */ HNumber HMath::raise(const HNumber &n1, int n) { HNumber r; float_raisei(&r.d->fnum, &n1.d->fnum, n, HMATH_EVAL_PREC); roundSetError(r.d); return r; } /** * Raises n1 to n2. */ HNumber HMath::raise(const HNumber &n1, const HNumber &n2) { HNumber result; HNumber temp = n1; Rational exp; bool change_sgn = false; if (n1.isNegative() && !n2.isInteger()) { // Try to convert n2 to a Rational. If n2 is not rational, return NaN. // For negative bases only allow odd denominators. exp = Rational(n2); if (abs(exp.toHNumber() - n2) >= RATIONAL_TOL || (n1.isNegative() && exp.denominator() % 2 == 0)) return HMath::nan(OutOfDomain); // if (n1.isNegative() && !n2.isInteger()) { // temp = -temp; // change_sgn = true; // } temp = -temp; change_sgn = (exp.numerator() % 2 != 0); } call2Args(result.d, temp.d, n2.d, float_raise); result *= (change_sgn) ? -1 : 1; return result; } /** * Returns e raised to x. */ HNumber HMath::exp(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_exp); return result; }; /** * Returns the natural logarithm of x. * If x is non positive, returns NaN. */ HNumber HMath::ln(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_ln); return result; } /** * Returns the common logarithm of x. * If x is non positive, returns NaN. */ HNumber HMath::lg(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_lg); return result; } /** * Returns the binary logarithm of x. * If x is non positive, returns NaN. */ HNumber HMath::lb(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_lb); return result; } /** * Returns the logarithm of x to base. * If x is non positive, returns NaN. */ HNumber HMath::log(const HNumber &base, const HNumber &x) { return lg(x) / lg(base); } /** * Returns the sine of x. Note that x must be in radians. */ HNumber HMath::sin(const HNumber &x) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_sin); return result; } /** * Returns the cosine of x. Note that x must be in radians. */ HNumber HMath::cos(const HNumber &x) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_cos); return result; } /** * Returns the tangent of x. Note that x must be in radians. */ HNumber HMath::tan(const HNumber &x) { HNumber result; call1ArgPoleCheck(result.d, x.d, float_tan); return result; } /** * Returns the cotangent of x. Note that x must be in radians. */ HNumber HMath::cot(const HNumber &x) { return cos(x) / sin(x); } /** * Returns the secant of x. Note that x must be in radians. */ HNumber HMath::sec(const HNumber &x) { return HNumber(1) / cos(x); } /** * Returns the cosecant of x. Note that x must be in radians. */ HNumber HMath::csc(const HNumber &x) { return HNumber(1) / sin(x); } /** * Returns the arc tangent of x. */ HNumber HMath::arctan(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_arctan); return result; } /** * Returns the angle formed by the vector (x, y) and the x-axis. */ HNumber HMath::arctan2(const HNumber &x, const HNumber &y) { if (y.isZero()) { if (x.isNegative()) return HMath::pi(); if (x.isZero()) return HMath::nan(OutOfDomain); return HNumber(0); } else { HNumber phi = HMath::arctan(HMath::abs(y / x)); if (x.isNegative()) return (HMath::pi() - phi) * HMath::sgn(y); if (x.isZero()) return HMath::pi() / HNumber(2) * HMath::sgn(y); return phi * HMath::sgn(y); } } /** * Returns the arc sine of x. */ HNumber HMath::arcsin(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_arcsin); return result; }; /** * Returns the arc cosine of x. */ HNumber HMath::arccos(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_arccos); return result; }; /** * Returns the hyperbolic sine of x. */ HNumber HMath::sinh(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_sinh); return result; } /** * Returns the hyperbolic cosine of x. */ HNumber HMath::cosh(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_cosh); return result; } /** * Returns the hyperbolic tangent of x. */ HNumber HMath::tanh(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_tanh); return result; } /** * Returns the area hyperbolic sine of x. */ HNumber HMath::arsinh(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_arsinh); return result; } /** * Returns the area hyperbolic cosine of x. */ HNumber HMath::arcosh(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_arcosh); return result; } /** * Returns the area hyperbolic tangent of x. */ HNumber HMath::artanh(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_artanh); return result; } /** * Returns the Gamma function. */ HNumber HMath::gamma(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_gamma); return result; } /** * Returns ln(abs(Gamma(x))). */ HNumber HMath::lnGamma(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_lngamma); return result; } /** * Returns signum x. */ HNumber HMath::sgn(const HNumber &x) { if (x.isNan()) return HMath::nan(checkNaNParam(*x.d)); return float_getsign(&x.d->fnum); } /** * Returns the binomial coefficient of n and r. * Is any of n and r negative or a non-integer, * 1/(n+1)*B(r+1, n-r+1)) is returned, where * B(x,y) is the complete Beta function */ HNumber HMath::nCr(const HNumber &n, const HNumber &r) { Error error = checkNaNParam(*n.d, r.d); if (error != Success) return HMath::nan(error); if (r.isInteger() && r < 0) return HNumber(0); // use symmetry nCr(n, r) == nCr(n, n-r) to find r1 such // 2*r1 <= n and nCr(n, r) == nCr(n, r1) HNumber r1 = (r + r > n) ? n - r : r; HNumber r2 = n - r1; if (r1 >= 0) { if (n.isInteger() && r1.isInteger() && n <= 1000 && r1 <= 50) return factorial(n, r2 + 1) / factorial(r1, 1); HNumber result(n); floatnum rnum = &result.d->fnum; floatstruct fn, fr; float_create(&fn); float_create(&fr); float_copy(&fr, &r1.d->fnum, HMATH_EVAL_PREC); float_copy(&fn, rnum, EXACT); float_sub(rnum, rnum, &fr, HMATH_EVAL_PREC) &&float_add(&fn, &fn, &c1, HMATH_EVAL_PREC) && float_add(&fr, &fr, &c1, HMATH_EVAL_PREC) && float_add(rnum, rnum, &c1, HMATH_EVAL_PREC) &&float_lngamma(&fn, HMATH_EVAL_PREC) && float_lngamma(&fr, HMATH_EVAL_PREC) &&float_lngamma(rnum, HMATH_EVAL_PREC) && float_add(rnum, rnum, &fr, HMATH_EVAL_PREC) && float_sub(rnum, &fn, rnum, HMATH_EVAL_PREC) &&float_exp(rnum, HMATH_EVAL_PREC); float_free(&fn); float_free(&fr); roundSetError(result.d); return result; } if (r2 >= 0 || !r2.isInteger()) return factorial(n, r1 + 1) / factorial(r2, 1); return 0; } /** * Returns the permutation of n elements chosen r elements. */ HNumber HMath::nPr(const HNumber &n, const HNumber &r) { return factorial(n, (n - r + 1)); } /** * Returns the falling Pochhammer symbol x*(x-1)*..*base. * For base == 1, this is the usual factorial x!, what this * function is named after. * This function has been extended using the Gamma function, * so that actually Gamma(x+1)/Gamma(base) is computed, a * value that equals the falling Pochhammer symbol, when * x - base is an integer, but allows other differences as well. */ HNumber HMath::factorial(const HNumber &x, const HNumber &base) { floatstruct tmp; if (float_cmp(&c1, &base.d->fnum) == 0) { HNumber result; call1Arg(result.d, x.d, float_factorial); return result; } float_create(&tmp); HNumber r(base); float_sub(&tmp, &x.d->fnum, &base.d->fnum, HMATH_EVAL_PREC) && float_add(&tmp, &tmp, &c1, HMATH_EVAL_PREC) && float_pochhammer(&r.d->fnum, &tmp, HMATH_EVAL_PREC); roundSetError(r.d); float_free(&tmp); return r; } static bool checkpn(const HNumber &p, const HNumber &n) { return n.isInteger() && !n.isNegative() && !p.isNan() && !p.isNegative() && p <= 1; } /** * Calculates the binomial discrete distribution probability mass function: * \f[X{\sim}B(n,p)\f] * \f[\Pr(X=k|n,p)={n\choose k}p^{k}(1-p)^{n-k}\f] * * \param[in] k the number of probed exact successes * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the probability of exactly \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialPmf(const HNumber &k, const HNumber &n, const HNumber &p) { if (!k.isInteger() || !checkpn(p, n)) return HMath::nan(InvalidParam); HNumber result = nCr(n, k); if (result.isZero()) return result; // special case: powers of zero, 0^0 == 1 in this context if (p.isInteger()) return (int)(p.isZero() ? k.isZero() : n == k); return result * raise(p, k) * raise(HNumber(1) - p, n - k); } /** * Calculates the binomial cumulative distribution function: * \f[X{\sim}B(n,p)\f] * \f[\Pr(X \leq k|n,p)=\sum_{i=0}^{k}{n\choose i}p^{i}(1-p)^{n-i}\f] * * \param[in] k the maximum number of probed successes * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the probability of up to \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialCdf(const HNumber &k, const HNumber &n, const HNumber &p) { // FIXME: Use the regularized incomplete Beta function to avoid the potentially very expensive // loop. if (!k.isInteger() || n.isNan()) return HMath::nan(); // Initiates summation, checks arguments as well. HNumber summand = binomialPmf(0, n, p); if (summand.isNan()) return summand; HNumber one(1); // Some early out results. if (k.isNegative()) return 0; if (k >= n) return one; HNumber pcompl = one - p; if (p.isInteger()) return pcompl; // use reflexion formula to limit summation if (k + k > n && k + one >= p * (n + one)) return one - binomialCdf(n - k - one, n, pcompl); // loop adding binomialPdf HNumber result(summand); for (HNumber i(0); i < k;) { summand *= p * (n - i); i += one; summand /= pcompl * i; result += summand; } return result; } /** * Calculates the expected value of a binomially distributed random variable: * \f[X{\sim}B(n,p)\f] * \f[E(X)=np\f] * * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the expected value of the variable, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialMean(const HNumber &n, const HNumber &p) { if (!checkpn(p, n)) return HMath::nan(); return n * p; } /** * Calculates the variance of a binomially distributed random variable: * \f[X{\sim}B(n,p)\f] * \f[Var(X)=np(1-p)\f] * * \param[in] n the number of trials * \param[in] p the probability of success in a single trial * * \return the variance of the variable, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::binomialVariance(const HNumber &n, const HNumber &p) { return binomialMean(n, p) * (HNumber(1) - p); } static bool checkNMn(const HNumber &N, const HNumber &M, const HNumber &n) { return N.isInteger() && !N.isNegative() && M.isInteger() && !M.isNegative() && n.isInteger() && !n.isNegative() && HMath::max(M, n) <= N; } /** * Calculates the hypergeometric discrete distribution probability mass * function: * \f[X{\sim}H(N,M,n)\f] * \f[\Pr(X=k|N,M,n)=\frac{{M\choose k}{N-M\choose n-k}}{{N\choose n}}\f] * * \param[in] k the number of probed exact successes * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the probability of exactly \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::hypergeometricPmf(const HNumber &k, const HNumber &N, const HNumber &M, const HNumber &n) { if (!k.isInteger() || !checkNMn(N, M, n)) return HMath::nan(); return HMath::nCr(M, k) * HMath::nCr(N - M, n - k) / HMath::nCr(N, n); } /** * Calculates the hypergeometric cumulative distribution function: * \f[X{\sim}H(N,M,n)\f] * \f[\Pr(X\leq k|N,M,n)= * \sum_{i=0}^{k}\frac{{M\choose k}{N-M\choose n-k}}{{N\choose n}}\f] * * \param[in] k the maximum number of probed successes * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the probability of up to \p k successes, otherwise \p NaN if the * function is not defined for the specified parameters. */ HNumber HMath::hypergeometricCdf(const HNumber &k, const HNumber &N, const HNumber &M, const HNumber &n) { // Lowest index of non-zero summand in loop. HNumber c = M + n - N; HNumber i = max(c, 0); // First summand in loop, do the parameter checking here. HNumber summand = HMath::hypergeometricPmf(i, N, M, n); if (!k.isInteger() || summand.isNan()) return HMath::nan(); // Some early out results. HNumber one(1); if (k >= M || k >= n) return one; if (i > k) return 0; // Use reflexion formula to limit summations. Numerically unstable where the result is near 0, // disable for now. // if (k + k > n) // return one - hypergeometricCdf(n - k - 1, N, N - M, n); HNumber result = summand; for (; i < k;) { summand *= (M - i) * (n - i); i += one; summand /= i * (i - c); result += summand; } return result; } /** * Calculates the expected value of a hypergeometrically distributed random * variable: * \f[X{\sim}H(N,M,n)\f] * \f[E(X)=n\frac{M}{N}\f] * * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the expected value of the variable, otherwise \p NaN if the * function is not defined for the specified parameter. */ HNumber HMath::hypergeometricMean(const HNumber &N, const HNumber &M, const HNumber &n) { if (!checkNMn(N, M, n)) return HMath::nan(); return n * M / N; } /** * * Calculates the variance of a hypergeometrically distributed random variable: * \f[X{\sim}H(N,M,n)\f] * \f[Var(X)=\frac{n\frac{M}{N}(1-\frac{M}{N})(N-n)}{N-1}\f] * * \param[in] N the number of total elements * \param[in] M the number of success elements * \param[in] n the number of selected elements * * \return the variance of the variable, otherwise \p NaN if the function is * not defined for the specified parameter. */ HNumber HMath::hypergeometricVariance(const HNumber &N, const HNumber &M, const HNumber &n) { return (hypergeometricMean(N, M, n) * (HNumber(1) - M / N) * (N - n)) / (N - HNumber(1)); } /** * * Calculates the poissonian discrete distribution probability mass function: * \f[X{\sim}P(\lambda)\f] * \f[\Pr(X=k|\lambda)=\frac{e^{-\lambda}\lambda^k}{k!}\f] * * \param[in] k the number of event occurrences * \param[in] l the expected number of occurrences that occur in an interval * * \return the probability of exactly \p k event occurrences, otherwise \p NaN * if the function is not defined for the specified parameters. */ HNumber HMath::poissonPmf(const HNumber &k, const HNumber &l) { if (!k.isInteger() || l.isNan() || l.isNegative()) return HMath::nan(); if (k.isNegative()) return 0; if (l.isZero()) return int(k.isZero()); return exp(-l) * raise(l, k) / factorial(k); } /** * Calculates the poissonian cumulative distribution function: * \f[X{\sim}P(\lambda)\f] * \f[\Pr(X\leq k|\lambda)=\sum_{i=0}^{k}\frac{e^{-\lambda}\lambda^k}{k!}\f] * * \param[in] k the maximum number of event occurrences * \param[in] l the expected number of occurrences that occur in an interval * * \return the probability of up to \p k event occurrences, otherwise \p NaN * if the function is not defined for the specified parameters. */ HNumber HMath::poissonCdf(const HNumber &k, const HNumber &l) { // FIXME: Use the incomplete gamma function to avoid a potentially expensive loop. if (!k.isInteger() || l.isNan() || l.isNegative()) return HMath::nan(); if (k.isNegative()) return 0; HNumber one(1); if (l.isZero()) return one; HNumber summand = one; HNumber result = one; for (HNumber i = one; i <= k; i += one) { summand *= l / i; result += summand; } result = exp(-l) * result; return result; } /** * Calculates the expected value of a Poisson distributed random variable: * \f[X{\sim}P(\lambda)\f] * \f[E(X)=\lambda\f] * * \param[in] l the expected number of occurrences that occur in an interval * * \return the expected value of the variable, otherwise \p NaN if the * function is not defined for the specified parameter. */ HNumber HMath::poissonMean(const HNumber &l) { if (l.isNan() || l.isNegative()) return HMath::nan(); return l; } /** * Calculates the variance of a Poisson distributed random variable: * \f[X{\sim}P(\lambda)\f] * \f[Var(X)=\lambda\f] * * \param[in] l the expected number of occurrences that occur in an interval * * \return the variance of the variable, otherwise \p NaN if the function is * not defined for the specified parameter. */ HNumber HMath::poissonVariance(const HNumber &l) { return poissonMean(l); } /** * Returns the erf function (related to normal distribution). */ HNumber HMath::erf(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_erf); return result; } /** * Returns the complementary erf function (related to normal distribution). */ HNumber HMath::erfc(const HNumber &x) { HNumber result; call1Arg(result.d, x.d, float_erfc); return result; } /** * Restricts a logic value to a given bit size. */ HNumber HMath::mask(const HNumber &val, const HNumber &bits) { if (val.isNan() || bits == 0 || bits >= LOGICRANGE || !bits.isInteger()) return HMath::nan(); return val & ~(HNumber(-1) << HNumber(bits)); } /** * sign-extends an unsigned value */ HNumber HMath::sgnext(const HNumber &val, const HNumber &bits) { if (val.isNan() || bits == 0 || bits >= LOGICRANGE || !bits.isInteger()) return HMath::nan(); HNumber ofs = HNumber(LOGICRANGE) - bits; return (val << ofs) >> ofs; } /** * For bits >= 0 does an arithmetic shift right, for bits < 0 a shift left. */ HNumber HMath::ashr(const HNumber &val, const HNumber &bits) { if (val.isNan() || bits <= -Settings::instance()->proBitLength || bits >= Settings::instance()->proBitLength || !bits.isInteger()) return HMath::nan(); if (bits >= 0) return val >> bits; return val << -bits; } /** * 逻辑移位 */ HNumber HMath::lshr(const HNumber &val, const HNumber &bits) { if (val.isNan() || bits <= -Settings::instance()->proBitLength || bits >= Settings::instance()->proBitLength || !bits.isInteger()) return HMath::nan(); // int shift = 0; // QString str = format(val, HNumber::Format::Complement() + HNumber::Format::Precision(65) + HNumber::Format::Binary()).remove("0b"); // shift = bits.toInt(); // if (shift < 0) { // return val << -bits; // } else { // if (str.length() <= shift) { // str = "0"; // } else { // str = "0b" + str.left(str.length() - shift); // } // HNumber result(str.toLatin1().data()); // return result; // } if (bits >= 0) { return (val >> bits) & ~(((HNumber(-1) << HNumber(Settings::instance()->proBitLength - 1)) >> bits) << HNumber(1)); } return val << -bits; } /** * 循环移位 */ HNumber HMath::rosh(const HNumber &val, const HNumber &bits) { if (val.isNan() || !bits.isInteger()) return HMath::nan(); // int shift = 0; // HNumber bitlen(Settings::instance()->proBitLength); // QString str = format(val, HNumber::Format::Complement() + HNumber::Format::Precision(65) + HNumber::Format::Binary()).remove("0b"); // shift = (bits % bitlen).toInt(); // while (str.length() < Settings::instance()->proBitLength) { // str.push_front("0"); // } // if (shift <= 0) { // shift = -shift; // str = "0b" + str.right(str.length() - shift) + str.left(shift); // HNumber result(str.toLatin1().data()); // return result; // } else { // while (shift-- > 0) { // str.push_front(str.back()); // str.chop(1); // } // str = "0b" + str; // HNumber result(str.toLatin1().data()); // return result; // } HNumber bitlen(Settings::instance()->proBitLength); HNumber shift = bits % bitlen; if (shift == 0) return val; if (shift < 0) { shift = - shift; return lshr(val, bitlen - shift) | (val << shift); } return (val << (bitlen - shift)) | lshr(val, shift); } /** * 带进位循环移位 */ HNumber HMath::rcsh(const HNumber &val, const HNumber &bits) { if (val.isNan() || !bits.isInteger()) return HMath::nan(); int shift = 0; HNumber bitlen(Settings::instance()->proBitLength + 1); QString str = format(val, HNumber::Format::Complement() + HNumber::Format::Precision(65) + HNumber::Format::Binary()).remove("0b"); shift = (bits % bitlen).toInt(); while (str.length() < Settings::instance()->proBitLength) { str.push_front("0"); } str.push_front(Settings::instance()->proRotateCarry.front()); qDebug() << Settings::instance()->proRotateCarry.front(); if (shift <= 0) { shift = -shift; str = str.right(str.length() - shift) + str.left(shift); qDebug() << str; Settings::instance()->proRotateCarry.front() = str.front(); str = "0b" + str.right(Settings::instance()->proBitLength); HNumber result(str.toLatin1().data()); return result; } else { while (shift-- > 0) { str.push_front(str.back()); str.chop(1); } Settings::instance()->proRotateCarry.front() = str.front(); str = "0b" + str.right(Settings::instance()->proBitLength); HNumber result(str.toLatin1().data()); return result; } } /** * Decode an IEEE-754 bit pattern with the default exponent bias */ HNumber HMath::decodeIeee754(const HNumber &val, const HNumber &exp_bits, const HNumber &significand_bits) { return HMath::decodeIeee754(val, exp_bits, significand_bits, HMath::raise(2, exp_bits - 1) - 1); } /** * Decode an IEEE-754 bit pattern with the given parameters */ HNumber HMath::decodeIeee754(const HNumber &val, const HNumber &exp_bits, const HNumber &significand_bits, const HNumber &exp_bias) { if (val.isNan() || exp_bits <= 0 || exp_bits >= LOGICRANGE || !exp_bits.isInteger() || significand_bits <= 0 || significand_bits >= LOGICRANGE || !significand_bits.isInteger() || !exp_bias.isInteger()) return HMath::nan(); HNumber sign(HMath::mask(val >> (exp_bits + significand_bits), 1).isZero() ? 1 : -1); HNumber exp = HMath::mask(val >> significand_bits, exp_bits); // <=> '0.' b_x b_x-1 b_x-2 ... b_0 HNumber significand = HMath::mask(val, significand_bits) * HMath::raise(2, -significand_bits); if (exp.isZero()) { // Exponent 0, subnormal value or zero. return sign * significand * HMath::raise(2, exp - exp_bias + 1); } if (exp - HMath::raise(2, exp_bits) == -1) { // Exponent all 1... if (significand.isZero()) // ...and signficand 0, infinity. // TODO: Represent infinity as something other than NaN? return HNumber(); // ...and significand not 0, NaN. return HMath::nan(); } return sign * (significand + 1) * HMath::raise(2, exp - exp_bias); // Normalised value. } /** * Encode a value in a IEEE-754 binary representation with the default exponent bias */ HNumber HMath::encodeIeee754(const HNumber &val, const HNumber &exp_bits, const HNumber &significand_bits) { return HMath::encodeIeee754(val, exp_bits, significand_bits, HMath::raise(2, exp_bits - 1) - 1); } /** * Encode a value in a IEEE-754 binary representation */ HNumber HMath::encodeIeee754(const HNumber &val, const HNumber &exp_bits, const HNumber &significand_bits, const HNumber &exp_bias) { if (exp_bits <= 0 || exp_bits >= LOGICRANGE || !exp_bits.isInteger() || significand_bits <= 0 || significand_bits >= LOGICRANGE || !significand_bits.isInteger() || !exp_bias.isInteger()) return HMath::nan(); HNumber sign_bit; HNumber significand; HNumber exponent; HNumber min_exp(1 - exp_bias); HNumber max_exp(HMath::raise(2, exp_bits) - 2 - exp_bias); if (val.isNan()) { // Encode a NaN. sign_bit = 0; significand = HMath::raise(2, significand_bits) - 1; exponent = HMath::raise(2, exp_bits) - 1; } else if (val.isZero()) { // Encode a basic 0. sign_bit = 0; significand = 0; exponent = 0; } else { // Regular input value. sign_bit = val.isNegative() ? 1 : 0; // Determine exponent. HNumber search_min = min_exp; HNumber search_max = max_exp; exponent = HMath::ceil((search_max - search_min) / 2) + search_min; significand = HMath::abs(val) * HMath::raise(2, -exponent); do { if (significand >= 1 && significand < 2) { // Integer part is 1, stop here. break; } else if (significand >= 2) { // Increase exponent. search_min = exponent + 1; } else if (significand < 1) { // Decrease exponent. search_max = exponent - 1; } exponent = HMath::ceil((search_max - search_min) / 2) + search_min; significand = HMath::abs(val) * HMath::raise(2, -exponent); } while (exponent != min_exp && exponent != max_exp); HNumber rounded = HMath::round(significand * HMath::raise(2, significand_bits)); HNumber intpart = HMath::integer(rounded * HMath::raise(2, -significand_bits)); significand = HMath::mask(rounded, significand_bits); if (intpart.isZero()) { // Subnormal value. exponent = 0; } else if (intpart > 1) { // Infinity. exponent = HMath::raise(2, exp_bits) - 1; significand = 0; } else { // Normalised value. exponent = exponent + exp_bias; } } HNumber result = sign_bit << (exp_bits + significand_bits) | exponent << (significand_bits) | significand; return result; } std::ostream &operator<<(std::ostream &s, const HNumber &n) { QString str = HMath::format(n); s << str.toLatin1().constData(); return s; } struct MathInit { MathInit() { floatmath_init(); } }; MathInit mathinit; /** * Parses a string containing a real number. * * Parameters : * str_in : pointer towards the string to parse * str_out : pointer towards a pointer towards the remaining of the string after parsing */ HNumber HMath::parse_str(const char *str_in, const char **str_out) { // FIXME: Duplicate code. // FIXME: Error management. const char *str = str_in; t_itokens tokens; HNumber x; delete x.d; x.d = new HNumberPrivate; if ((x.d->error = parse(&tokens, &str)) == Success) x.d->error = float_in(&x.d->fnum, &tokens, Settings::instance()->proBitLength, 1); float_geterror(); /* Store remaining of the string */ if (str_out) *str_out = str; return x; } bool HNumber::isNearZero() const { return float_iszero(&(d->fnum)) || float_getexponent(&(d->fnum)) <= -80; } int HNumber::realNumberlength() const { int sca = d->fnum.significand->n_scale; int ex = d->fnum.exponent; int b = 0; if (ex > 0 && ex < sca) b = sca + 1; if (ex > 0 && ex >= sca) b = ex + 1; if (ex <= 0) b = sca - ex + 1; return b; } deepin-calculator-5.7.21/3rdparty/math/hmath.h000066400000000000000000000214531423020056600211570ustar00rootroot00000000000000// HMath: C++ high precision math routines // Copyright (C) 2004 Ariya Hidayat // Copyright (C) 2007-2008, 2014, 2016 @heldercorreia // Copyright (C) 2008 Wolf Lammen // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef MATH_HMATH_H #define MATH_HMATH_H #include "../core/errors.h" #include #include #include class HMath; class HNumberPrivate; class CNumber; class CMath; class Rational; class HNumber { friend class HMath; friend class CNumber; friend class CMath; friend HNumber operator-(const HNumber &); friend HNumber operator-(const HNumber &, const HNumber &); friend bool operator>(const HNumber &, const HNumber &); friend bool operator<(const HNumber &, const HNumber &); friend bool operator>=(const HNumber &, const HNumber &); friend bool operator<=(const HNumber &, const HNumber &); friend bool operator==(const HNumber &, const HNumber &); friend bool operator!=(const HNumber &, const HNumber &); public: HNumber(); HNumber(const HNumber &); HNumber(int); HNumber(const char *); HNumber(const QJsonObject &); HNumber(const char *, bool); ~HNumber(); bool isNan() const; bool isZero() const; bool isNearZero() const; bool isPositive() const; bool isNegative() const; bool isInteger() const; void serialize(QJsonObject &) const; static HNumber deSerialize(const QJsonObject &); int toInt() const; Error error() const; HNumber &operator=(const HNumber &); HNumber operator+(const HNumber &) const; HNumber &operator+=(const HNumber &); HNumber &operator-=(const HNumber &); HNumber operator*(const HNumber &)const; HNumber &operator*=(const HNumber &); HNumber operator/(const HNumber &) const; HNumber &operator/=(const HNumber &); HNumber operator%(const HNumber &) const; HNumber operator&(const HNumber &)const; HNumber &operator&=(const HNumber &); HNumber operator|(const HNumber &) const; HNumber &operator|=(const HNumber &); HNumber operator^(const HNumber &) const; HNumber &operator^=(const HNumber &); HNumber operator~() const; HNumber operator>>(const HNumber &) const; HNumber operator<<(const HNumber &) const; int realNumberlength() const; private: HNumberPrivate *d; int compare(const HNumber &) const; public: struct Format { enum class Base { Null, Binary, Decimal, Octal, Hexadecimal }; enum class RadixChar { Null, Point, Comma }; enum class Mode { Null, General, Fixed, Scientific, Engineering, Complement}; enum class AutoCut {Null, Ncut}; Base base; RadixChar radixChar; Mode mode; AutoCut cut; int precision; // -1 means 'auto' static const int PrecisionNull = -1000; Format(); Format(const Format &); Format operator+(const Format &) const; static Format Binary(); static Format Octal(); static Format Decimal(); static Format Hexadecimal(); static Format Precision(int); static Format Point(); static Format Comma(); static Format General(); static Format Fixed(); static Format Scientific(); static Format Engineering(); static Format Complement(); static Format NCut(); }; }; class HMath { public: // FORMAT static QString format(const HNumber &, HNumber::Format = HNumber::Format()); // PARSING static HNumber parse_str(const char *, const char **out); // CONSTANTS static HNumber e(); static HNumber phi(); static HNumber pi(); static HNumber nan(Error = Success); // GENERAL MATH static HNumber rad2deg(const HNumber &); static HNumber deg2rad(const HNumber &); static HNumber rad2gon(const HNumber &); static HNumber gon2rad(const HNumber &); static HNumber max(const HNumber &, const HNumber &); static HNumber min(const HNumber &, const HNumber &); static HNumber abs(const HNumber &); static HNumber integer(const HNumber &); static HNumber frac(const HNumber &); static HNumber floor(const HNumber &); static HNumber ceil(const HNumber &); static HNumber gcd(const HNumber &, const HNumber &); static HNumber idiv(const HNumber &, const HNumber &); static HNumber round(const HNumber &, int prec = 0); static HNumber trunc(const HNumber &, int prec = 0); static HNumber sqrt(const HNumber &); static HNumber cbrt(const HNumber &); static HNumber raise(const HNumber &, int); static HNumber raise(const HNumber &, const HNumber &); static HNumber sgn(const HNumber &); // EXPONENTIAL FUNCTION AND RELATED static HNumber exp(const HNumber &); static HNumber ln(const HNumber &); static HNumber lg(const HNumber &); static HNumber lb(const HNumber &); static HNumber log(const HNumber &base, const HNumber &x); static HNumber sinh(const HNumber &); static HNumber cosh(const HNumber &); static HNumber tanh(const HNumber &); static HNumber arsinh(const HNumber &); static HNumber arcosh(const HNumber &); static HNumber artanh(const HNumber &); // TRIGONOMETRY static HNumber sin(const HNumber &); static HNumber cos(const HNumber &); static HNumber tan(const HNumber &); static HNumber cot(const HNumber &); static HNumber sec(const HNumber &); static HNumber csc(const HNumber &); static HNumber arcsin(const HNumber &); static HNumber arccos(const HNumber &); static HNumber arctan(const HNumber &); static HNumber arctan2(const HNumber &, const HNumber &); // HIGHER MATH FUNCTIONS static HNumber factorial(const HNumber &, const HNumber &base = HNumber(1)); static HNumber gamma(const HNumber &); static HNumber lnGamma(const HNumber &); static HNumber erf(const HNumber &); static HNumber erfc(const HNumber &); // PROBABILITY static HNumber nCr(const HNumber &n, const HNumber &k); static HNumber nPr(const HNumber &n, const HNumber &r); static HNumber binomialPmf(const HNumber &k, const HNumber &n, const HNumber &p); static HNumber binomialCdf(const HNumber &k, const HNumber &n, const HNumber &p); static HNumber binomialMean(const HNumber &n, const HNumber &p); static HNumber binomialVariance(const HNumber &n, const HNumber &p); static HNumber hypergeometricPmf(const HNumber &k, const HNumber &N, const HNumber &M, const HNumber &n); static HNumber hypergeometricCdf(const HNumber &k, const HNumber &N, const HNumber &M, const HNumber &n); static HNumber hypergeometricMean(const HNumber &N, const HNumber &M, const HNumber &n); static HNumber hypergeometricVariance(const HNumber &N, const HNumber &M, const HNumber &n); static HNumber poissonPmf(const HNumber &k, const HNumber &l); static HNumber poissonCdf(const HNumber &k, const HNumber &l); static HNumber poissonMean(const HNumber &l); static HNumber poissonVariance(const HNumber &l); // LOGIC static HNumber mask(const HNumber &, const HNumber &bits); static HNumber sgnext(const HNumber &, const HNumber &bits); static HNumber ashr(const HNumber &, const HNumber &bits); static HNumber lshr(const HNumber &, const HNumber &bits); static HNumber rosh(const HNumber &, const HNumber &bits); static HNumber rcsh(const HNumber &, const HNumber &bits); // IEEE-754 CONVERSION static HNumber decodeIeee754(const HNumber &, const HNumber &exp_bits, const HNumber &significand_bits); static HNumber decodeIeee754(const HNumber &, const HNumber &exp_bits, const HNumber &significand_bits, const HNumber &exp_bias); static HNumber encodeIeee754(const HNumber &, const HNumber &exp_bits, const HNumber &significand_bits); static HNumber encodeIeee754(const HNumber &, const HNumber &exp_bits, const HNumber &significand_bits, const HNumber &exp_bias); }; std::ostream &operator<<(std::ostream &, const HNumber &); #endif // MATH_HMATH_H deepin-calculator-5.7.21/3rdparty/math/number.c000066400000000000000000001226271423020056600213460ustar00rootroot00000000000000/* number.c: Implements arbitrary precision numbers. */ /* Copyright (C) 1991, 1992, 1993, 1994, 1997, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to: The Free Software Foundation, Inc. 59 Temple Place, Suite 330 Boston, MA 02111-1307 USA. You may contact the author by: e-mail: philnelson@acm.org us-mail: Philip A. Nelson Computer Science Department, 9062 Western Washington University Bellingham, WA 98226-9062 !!!This is a patched file, the original file from bc 1.06 contains bugs in (a) bc_divide and (b) bc_int2num. A patch is applied here by Wolf Lammen, Oertzweg 45, 22307 Hamburg email ookami1 gmx de One patched line fixes a nasty bug, where a division by 1 may fail occasionly when an operand is overwritten by the result. The other one lets a conversion of an integer succeed, even if the most negative integer is passed as argument *************************************************************************/ #include "number.h" #include #include #include #include #include /* Prototypes needed for external utility routines. */ #define bc_rt_warn rt_warn #define bc_rt_error rt_error #define bc_out_of_memory out_of_memory _PROTOTYPE(void rt_warn, (char *mesg ,...)); _PROTOTYPE(void rt_error, (char *mesg ,...)); _PROTOTYPE(void out_of_memory, (void)); void out_of_memory(void){ return; } void rt_warn(char *mesg ,...){ (void)mesg; return; } void rt_error(char *mesg ,...){ (void)mesg; return; } /* Storage used for special numbers. */ bc_num _zero_; bc_num _one_; bc_num _two_; static bc_num _bc_Free_list = NULL; /* new_num allocates a number and sets fields to known values. */ bc_num bc_new_num (length, scale) int length, scale; { bc_num temp; if (_bc_Free_list != NULL) { temp = _bc_Free_list; _bc_Free_list = temp->n_next; } else { temp = (bc_num) malloc (sizeof(bc_struct)); if (temp == NULL) bc_out_of_memory (); } temp->n_sign = PLUS; temp->n_len = length; temp->n_scale = scale; temp->n_refs = 1; temp->n_ptr = (char *) malloc (length+scale+1); if (temp->n_ptr == NULL) bc_out_of_memory(); temp->n_value = temp->n_ptr; memset (temp->n_ptr, 0, length+scale); return temp; } /* "Frees" a bc_num NUM. Actually decreases reference count and only frees the storage if reference count is zero. */ void bc_free_num (num) bc_num *num; { if (*num == NULL) return; (*num)->n_refs--; if ((*num)->n_refs == 0) { if ((*num)->n_ptr) free ((*num)->n_ptr); (*num)->n_next = _bc_Free_list; _bc_Free_list = *num; } *num = NULL; } /* Intitialize the number package! */ void bc_init_numbers () { _zero_ = bc_new_num (1,0); _one_ = bc_new_num (1,0); _one_->n_value[0] = 1; _two_ = bc_new_num (1,0); _two_->n_value[0] = 2; } /* Make a copy of a number! Just increments the reference count! */ bc_num bc_copy_num (num) bc_num num; { num->n_refs++; return num; } /* Initialize a number NUM by making it a copy of zero. */ void bc_init_num (num) bc_num *num; { *num = bc_copy_num (_zero_); } /* For many things, we may have leading zeros in a number NUM. _bc_rm_leading_zeros just moves the data "value" pointer to the correct place and adjusts the length. */ static void _bc_rm_leading_zeros (num) bc_num num; { /* We can move n_value to point to the first non zero digit! */ while (*num->n_value == 0 && num->n_len > 1) { num->n_value++; num->n_len--; } } /* Compare two bc numbers. Return value is 0 if equal, -1 if N1 is less than N2 and +1 if N1 is greater than N2. If USE_SIGN is false, just compare the magnitudes. */ static int _bc_do_compare (n1, n2, use_sign, ignore_last) bc_num n1, n2; int use_sign; int ignore_last; { char *n1ptr, *n2ptr; int count; /* First, compare signs. */ if (use_sign && n1->n_sign != n2->n_sign) { if (n1->n_sign == PLUS) return (1); /* Positive N1 > Negative N2 */ else return (-1); /* Negative N1 < Positive N1 */ } /* Now compare the magnitude. */ if (n1->n_len != n2->n_len) { if (n1->n_len > n2->n_len) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) return (1); else return (-1); } else { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) return (-1); else return (1); } } /* If we get here, they have the same number of integer digits. check the integer part and the equal length part of the fraction. */ count = n1->n_len + MIN (n1->n_scale, n2->n_scale); n1ptr = n1->n_value; n2ptr = n2->n_value; while ((count > 0) && (*n1ptr == *n2ptr)) { n1ptr++; n2ptr++; count--; } if (ignore_last && count == 1 && n1->n_scale == n2->n_scale) return (0); if (count != 0) { if (*n1ptr > *n2ptr) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) return (1); else return (-1); } else { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) return (-1); else return (1); } } /* They are equal up to the last part of the equal part of the fraction. */ if (n1->n_scale != n2->n_scale) { if (n1->n_scale > n2->n_scale) { for (count = n1->n_scale-n2->n_scale; count>0; count--) if (*n1ptr++ != 0) { /* Magnitude of n1 > n2. */ if (!use_sign || n1->n_sign == PLUS) return (1); else return (-1); } } else { for (count = n2->n_scale-n1->n_scale; count>0; count--) if (*n2ptr++ != 0) { /* Magnitude of n1 < n2. */ if (!use_sign || n1->n_sign == PLUS) return (-1); else return (1); } } } /* They must be equal! */ return (0); } /* This is the "user callable" routine to compare numbers N1 and N2. */ int bc_compare (n1, n2) bc_num n1, n2; { return _bc_do_compare (n1, n2, TRUE, FALSE); } /* In some places we need to check if the number is negative. */ char bc_is_neg (num) bc_num num; { return num->n_sign == MINUS; } /* In some places we need to check if the number NUM is zero. */ char bc_is_zero (num) bc_num num; { int count; char *nptr; /* Quick check. */ if (num == _zero_) return TRUE; /* Initialize */ count = num->n_len + num->n_scale; nptr = num->n_value; /* The check */ while ((count > 0) && (*nptr++ == 0)) count--; if (count != 0) return FALSE; else return TRUE; } /* In some places we need to check if the number NUM is almost zero. Specifically, all but the last digit is 0 and the last digit is 1. Last digit is defined by scale. */ char bc_is_near_zero (num, scale) bc_num num; int scale; { int count; char *nptr; /* Error checking */ if (scale > num->n_scale) scale = num->n_scale; /* Initialize */ count = num->n_len + scale; nptr = num->n_value; /* The check */ while ((count > 0) && (*nptr++ == 0)) count--; if (count != 0 && (count != 1 || *--nptr != 1)) return FALSE; else return TRUE; } /* Perform addition: N1 is added to N2 and the value is returned. The signs of N1 and N2 are ignored. SCALE_MIN is to set the minimum scale of the result. */ static bc_num _bc_do_add (n1, n2, scale_min) bc_num n1, n2; int scale_min; { bc_num sum; int sum_scale, sum_digits; char *n1ptr, *n2ptr, *sumptr; int carry, n1bytes, n2bytes; int count; /* Prepare sum. */ sum_scale = MAX (n1->n_scale, n2->n_scale); sum_digits = MAX (n1->n_len, n2->n_len) + 1; sum = bc_new_num (sum_digits, MAX(sum_scale, scale_min)); /* Zero extra digits made by scale_min. */ if (scale_min > sum_scale) { sumptr = (char *) (sum->n_value + sum_scale + sum_digits); for (count = scale_min - sum_scale; count > 0; count--) *sumptr++ = 0; } /* Start with the fraction part. Initialize the pointers. */ n1bytes = n1->n_scale; n2bytes = n2->n_scale; n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1); n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1); sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1); /* Add the fraction part. First copy the longer fraction.*/ if (n1bytes != n2bytes) { if (n1bytes > n2bytes) while (n1bytes>n2bytes) { *sumptr-- = *n1ptr--; n1bytes--;} else while (n2bytes>n1bytes) { *sumptr-- = *n2ptr--; n2bytes--;} } /* Now add the remaining fraction part and equal size integer parts. */ n1bytes += n1->n_len; n2bytes += n2->n_len; carry = 0; while ((n1bytes > 0) && (n2bytes > 0)) { *sumptr = *n1ptr-- + *n2ptr-- + carry; if (*sumptr > (BASE-1)) { carry = 1; *sumptr -= BASE; } else carry = 0; sumptr--; n1bytes--; n2bytes--; } /* Now add carry the longer integer part. */ if (n1bytes == 0) { n1bytes = n2bytes; n1ptr = n2ptr; } while (n1bytes-- > 0) { *sumptr = *n1ptr-- + carry; if (*sumptr > (BASE-1)) { carry = 1; *sumptr -= BASE; } else carry = 0; sumptr--; } /* Set final carry. */ if (carry == 1) *sumptr += 1; /* Adjust sum and return. */ _bc_rm_leading_zeros (sum); return sum; } /* Perform subtraction: N2 is subtracted from N1 and the value is returned. The signs of N1 and N2 are ignored. Also, N1 is assumed to be larger than N2. SCALE_MIN is the minimum scale of the result. */ static bc_num _bc_do_sub (n1, n2, scale_min) bc_num n1, n2; int scale_min; { bc_num diff; int diff_scale, diff_len; int min_scale, min_len; char *n1ptr, *n2ptr, *diffptr; int borrow, count, val; /* Allocate temporary storage. */ diff_len = MAX (n1->n_len, n2->n_len); diff_scale = MAX (n1->n_scale, n2->n_scale); min_len = MIN (n1->n_len, n2->n_len); min_scale = MIN (n1->n_scale, n2->n_scale); diff = bc_new_num (diff_len, MAX(diff_scale, scale_min)); /* Zero extra digits made by scale_min. */ if (scale_min > diff_scale) { diffptr = (char *) (diff->n_value + diff_len + diff_scale); for (count = scale_min - diff_scale; count > 0; count--) *diffptr++ = 0; } /* Initialize the subtract. */ n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1); n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1); diffptr = (char *) (diff->n_value + diff_len + diff_scale -1); /* Subtract the numbers. */ borrow = 0; /* Take care of the longer scaled number. */ if (n1->n_scale != min_scale) { /* n1 has the longer scale */ for (count = n1->n_scale - min_scale; count > 0; count--) *diffptr-- = *n1ptr--; } else { /* n2 has the longer scale */ for (count = n2->n_scale - min_scale; count > 0; count--) { val = - *n2ptr-- - borrow; if (val < 0) { val += BASE; borrow = 1; } else borrow = 0; *diffptr-- = val; } } /* Now do the equal length scale and integer parts. */ for (count = 0; count < min_len + min_scale; count++) { val = *n1ptr-- - *n2ptr-- - borrow; if (val < 0) { val += BASE; borrow = 1; } else borrow = 0; *diffptr-- = val; } /* If n1 has more digits then n2, we now do that subtract. */ if (diff_len != min_len) { for (count = diff_len - min_len; count > 0; count--) { val = *n1ptr-- - borrow; if (val < 0) { val += BASE; borrow = 1; } else borrow = 0; *diffptr-- = val; } } /* Clean up and return. */ _bc_rm_leading_zeros (diff); return diff; } /* Here is the full subtract routine that takes care of negative numbers. N2 is subtracted from N1 and the result placed in RESULT. SCALE_MIN is the minimum scale for the result. */ void bc_sub (n1, n2, result, scale_min) bc_num n1, n2, *result; int scale_min; { bc_num diff = NULL; int cmp_res; int res_scale; if (n1->n_sign != n2->n_sign) { diff = _bc_do_add (n1, n2, scale_min); diff->n_sign = n1->n_sign; } else { /* subtraction must be done. */ /* Compare magnitudes. */ cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE); switch (cmp_res) { case -1: /* n1 is less than n2, subtract n1 from n2. */ diff = _bc_do_sub (n2, n1, scale_min); diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS); break; case 0: /* They are equal! return zero! */ res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); diff = bc_new_num (1, res_scale); memset (diff->n_value, 0, res_scale+1); break; case 1: /* n2 is less than n1, subtract n2 from n1. */ diff = _bc_do_sub (n1, n2, scale_min); diff->n_sign = n1->n_sign; break; } } /* Clean up and return. */ bc_free_num (result); *result = diff; } /* Here is the full add routine that takes care of negative numbers. N1 is added to N2 and the result placed into RESULT. SCALE_MIN is the minimum scale for the result. */ void bc_add (n1, n2, result, scale_min) bc_num n1, n2, *result; int scale_min; { bc_num sum = NULL; int cmp_res; int res_scale; if (n1->n_sign == n2->n_sign) { sum = _bc_do_add (n1, n2, scale_min); sum->n_sign = n1->n_sign; } else { /* subtraction must be done. */ cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE); /* Compare magnitudes. */ switch (cmp_res) { case -1: /* n1 is less than n2, subtract n1 from n2. */ sum = _bc_do_sub (n2, n1, scale_min); sum->n_sign = n2->n_sign; break; case 0: /* They are equal! return zero with the correct scale! */ res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); sum = bc_new_num (1, res_scale); memset (sum->n_value, 0, res_scale+1); break; case 1: /* n2 is less than n1, subtract n2 from n1. */ sum = _bc_do_sub (n1, n2, scale_min); sum->n_sign = n1->n_sign; } } /* Clean up and return. */ bc_free_num (result); *result = sum; } /* Recursive vs non-recursive multiply crossover ranges. */ #if defined(MULDIGITS) #include "muldigits.h" #else #define MUL_BASE_DIGITS 80 #endif int mul_base_digits = MUL_BASE_DIGITS; #define MUL_SMALL_DIGITS mul_base_digits/4 /* Multiply utility routines */ static bc_num new_sub_num (length, scale, value) int length, scale; char *value; { bc_num temp; if (_bc_Free_list != NULL) { temp = _bc_Free_list; _bc_Free_list = temp->n_next; } else { temp = (bc_num) malloc (sizeof(bc_struct)); if (temp == NULL) bc_out_of_memory (); } temp->n_sign = PLUS; temp->n_len = length; temp->n_scale = scale; temp->n_refs = 1; temp->n_ptr = NULL; temp->n_value = value; return temp; } static void _bc_simp_mul (bc_num n1, int n1len, bc_num n2, int n2len, bc_num *prod, int full_scale) { char *n1ptr, *n2ptr, *pvptr; char *n1end, *n2end; /* To the end of n1 and n2. */ int indx, sum; const int prodlen = n1len + n2len + 1; (void)full_scale; *prod = bc_new_num (prodlen, 0); n1end = (char *) (n1->n_value + n1len - 1); n2end = (char *) (n2->n_value + n2len - 1); pvptr = (char *) ((*prod)->n_value + prodlen - 1); sum = 0; /* Here is the loop... */ for (indx = 0; indx < prodlen-1; indx++) { n1ptr = (char *) (n1end - MAX(0, indx-n2len+1)); n2ptr = (char *) (n2end - MIN(indx, n2len-1)); while ((n1ptr >= n1->n_value) && (n2ptr <= n2end)) sum += *n1ptr-- * *n2ptr++; *pvptr-- = sum % BASE; sum = sum / BASE; } *pvptr = sum; } /* A special adder/subtractor for the recursive divide and conquer multiply algorithm. Note: if sub is called, accum must be larger that what is being subtracted. Also, accum and val must have n_scale = 0. (e.g. they must look like integers. *) */ static void _bc_shift_addsub (bc_num accum, bc_num val, int shift, int sub) { signed char *accp, *valp; int count, carry; count = val->n_len; if (val->n_value[0] == 0) count--; assert (accum->n_len+accum->n_scale >= shift+count); /* Set up pointers and others */ accp = (signed char *)(accum->n_value + accum->n_len + accum->n_scale - shift - 1); valp = (signed char *)(val->n_value + val->n_len - 1); carry = 0; if (sub) { /* Subtraction, carry is really borrow. */ while (count--) { *accp -= *valp-- + carry; if (*accp < 0) { carry = 1; *accp-- += BASE; } else { carry = 0; accp--; } } while (carry) { *accp -= carry; if (*accp < 0) *accp-- += BASE; else carry = 0; } } else { /* Addition */ while (count--) { *accp += *valp-- + carry; if (*accp > (BASE-1)) { carry = 1; *accp-- -= BASE; } else { carry = 0; accp--; } } while (carry) { *accp += carry; if (*accp > (BASE-1)) *accp-- -= BASE; else carry = 0; } } } /* Recursive divide and conquer multiply algorithm. Based on Let u = u0 + u1*(b^n) Let v = v0 + v1*(b^n) Then uv = (B^2n+B^n)*u1*v1 + B^n*(u1-u0)*(v0-v1) + (B^n+1)*u0*v0 B is the base of storage, number of digits in u1,u0 close to equal. */ static void _bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod, int full_scale) { bc_num u0, u1, v0, v1; /*int u0len, v0len;*/ bc_num m1, m2, m3, d1, d2; int n, prodlen, m1zero; int d1len, d2len; /* Base case? */ if ((ulen+vlen) < mul_base_digits || ulen < MUL_SMALL_DIGITS || vlen < MUL_SMALL_DIGITS ) { _bc_simp_mul (u, ulen, v, vlen, prod, full_scale); return; } /* Calculate n -- the u and v split point in digits. */ n = (MAX(ulen, vlen)+1) / 2; /* Split u and v. */ if (ulen < n) { u1 = bc_copy_num (_zero_); u0 = new_sub_num (ulen,0, u->n_value); } else { u1 = new_sub_num (ulen-n, 0, u->n_value); u0 = new_sub_num (n, 0, u->n_value+ulen-n); } if (vlen < n) { v1 = bc_copy_num (_zero_); v0 = new_sub_num (vlen,0, v->n_value); } else { v1 = new_sub_num (vlen-n, 0, v->n_value); v0 = new_sub_num (n, 0, v->n_value+vlen-n); } _bc_rm_leading_zeros (u1); _bc_rm_leading_zeros (u0); /*u0len = u0->n_len;*/ _bc_rm_leading_zeros (v1); _bc_rm_leading_zeros (v0); /*v0len = v0->n_len;*/ m1zero = bc_is_zero(u1) || bc_is_zero(v1); /* Calculate sub results ... */ bc_init_num(&d1); bc_init_num(&d2); bc_sub (u1, u0, &d1, 0); d1len = d1->n_len; bc_sub (v0, v1, &d2, 0); d2len = d2->n_len; /* Do recursive multiplies and shifted adds. */ if (m1zero) m1 = bc_copy_num (_zero_); else _bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1, 0); if (bc_is_zero(d1) || bc_is_zero(d2)) m2 = bc_copy_num (_zero_); else _bc_rec_mul (d1, d1len, d2, d2len, &m2, 0); if (bc_is_zero(u0) || bc_is_zero(v0)) m3 = bc_copy_num (_zero_); else _bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3, 0); /* Initialize product */ prodlen = ulen+vlen+1; *prod = bc_new_num(prodlen, 0); if (!m1zero) { _bc_shift_addsub (*prod, m1, 2*n, 0); _bc_shift_addsub (*prod, m1, n, 0); } _bc_shift_addsub (*prod, m3, n, 0); _bc_shift_addsub (*prod, m3, 0, 0); _bc_shift_addsub (*prod, m2, n, d1->n_sign != d2->n_sign); /* Now clean up! */ bc_free_num (&u1); bc_free_num (&u0); bc_free_num (&v1); bc_free_num (&m1); bc_free_num (&v0); bc_free_num (&m2); bc_free_num (&m3); bc_free_num (&d1); bc_free_num (&d2); } /* The multiply routine. N2 times N1 is put int PROD with the scale of the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)). */ void bc_multiply (n1, n2, prod, scale) bc_num n1, n2, *prod; int scale; { bc_num pval; int len1, len2; int full_scale, prod_scale; /* Initialize things. */ len1 = n1->n_len + n1->n_scale; len2 = n2->n_len + n2->n_scale; full_scale = n1->n_scale + n2->n_scale; prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale))); /* Do the multiply */ _bc_rec_mul (n1, len1, n2, len2, &pval, full_scale); /* Assign to prod and clean up the number. */ pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); pval->n_value = pval->n_ptr; pval->n_len = len2 + len1 + 1 - full_scale; pval->n_scale = prod_scale; _bc_rm_leading_zeros (pval); if (bc_is_zero (pval)) pval->n_sign = PLUS; bc_free_num (prod); *prod = pval; } /* Some utility routines for the divide: First a one digit multiply. NUM (with SIZE digits) is multiplied by DIGIT and the result is placed into RESULT. It is written so that NUM and RESULT can be the same pointers. */ static void _one_mult (num, size, digit, result) unsigned char *num; int size, digit; unsigned char *result; { int carry, value; unsigned char *nptr, *rptr; if (digit == 0) memset (result, 0, size); else { if (digit == 1) memcpy (result, num, size); else { /* Initialize */ nptr = (unsigned char *) (num+size-1); rptr = (unsigned char *) (result+size-1); carry = 0; while (size-- > 0) { value = *nptr-- * digit + carry; *rptr-- = value % BASE; carry = value / BASE; } if (carry != 0) *rptr = carry; } } } /* The full division routine. This computes N1 / N2. It returns 0 if the division is ok and the result is in QUOT. The number of digits after the decimal point is SCALE. It returns -1 if division by zero is tried. The algorithm is found in Knuth Vol 2. p237. */ int bc_divide (n1, n2, quot, scale) bc_num n1, n2, *quot; int scale; { bc_num qval; unsigned char *num1, *num2; unsigned char *ptr1, *ptr2, *n2ptr, *qptr; int scale1, val; unsigned int len1, len2, scale2, qdigits, extra, count; unsigned int qdig, qguess, borrow, carry; unsigned char *mval; char zero; unsigned int norm; /* Test for divide by zero. */ if (bc_is_zero (n2)) return -1; /* Test for divide by 1. If it is we must truncate. */ if (n2->n_scale == 0) { if (n2->n_len == 1 && *n2->n_value == 1) { qval = bc_new_num (n1->n_len, scale); qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS); memset (&qval->n_value[n1->n_len],0,scale); memcpy (qval->n_value, n1->n_value, n1->n_len + MIN(n1->n_scale,scale)); bc_free_num (quot); *quot = qval; return 0; /* bug fix Wolf Lammen */ } } /* Set up the divide. Move the decimal point on n1 by n2's scale. Remember, zeros on the end of num2 are wasted effort for dividing. */ scale2 = n2->n_scale; n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1; while ((scale2 > 0) && (*n2ptr-- == 0)) scale2--; len1 = n1->n_len + scale2; scale1 = n1->n_scale - scale2; if (scale1 < scale) extra = scale - scale1; else extra = 0; num1 = (unsigned char *) malloc (n1->n_len+n1->n_scale+extra+2); if (num1 == NULL) bc_out_of_memory(); memset (num1, 0, n1->n_len+n1->n_scale+extra+2); memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale); len2 = n2->n_len + scale2; num2 = (unsigned char *) malloc (len2+1); if (num2 == NULL) bc_out_of_memory(); memcpy (num2, n2->n_value, len2); *(num2+len2) = 0; n2ptr = num2; while (*n2ptr == 0) { n2ptr++; len2--; } /* Calculate the number of quotient digits. */ if (len2 > len1+scale) { qdigits = scale+1; zero = TRUE; } else { zero = FALSE; if (len2>len1) qdigits = scale+1; /* One for the zero integer part. */ else qdigits = len1-len2+scale+1; } /* Allocate and zero the storage for the quotient. */ qval = bc_new_num (qdigits-scale,scale); memset (qval->n_value, 0, qdigits); /* Allocate storage for the temporary storage mval. */ mval = (unsigned char *) malloc (len2+1); if (mval == NULL) bc_out_of_memory (); /* Now for the full divide algorithm. */ if (!zero) { /* Normalize */ norm = 10 / ((int)*n2ptr + 1); if (norm != 1) { _one_mult (num1, len1+scale1+extra+1, norm, num1); _one_mult (n2ptr, len2, norm, n2ptr); } /* Initialize divide loop. */ qdig = 0; if (len2 > len1) qptr = (unsigned char *) qval->n_value+len2-len1; else qptr = (unsigned char *) qval->n_value; /* Loop */ while (qdig <= len1+scale-len2) { /* Calculate the quotient digit guess. */ if (*n2ptr == num1[qdig]) qguess = 9; else qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr; /* Test qguess. */ if (n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2]) { qguess--; /* And again. */ if (n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2]) qguess--; } /* Multiply and subtract. */ borrow = 0; if (qguess != 0) { *mval = 0; _one_mult (n2ptr, len2, qguess, mval+1); ptr1 = (unsigned char *) num1+qdig+len2; ptr2 = (unsigned char *) mval+len2; for (count = 0; count < len2+1; count++) { val = (int) *ptr1 - (int) *ptr2-- - borrow; if (val < 0) { val += 10; borrow = 1; } else borrow = 0; *ptr1-- = val; } } /* Test for negative result. */ if (borrow == 1) { qguess--; ptr1 = (unsigned char *) num1+qdig+len2; ptr2 = (unsigned char *) n2ptr+len2-1; carry = 0; for (count = 0; count < len2; count++) { val = (int) *ptr1 + (int) *ptr2-- + carry; if (val > 9) { val -= 10; carry = 1; } else carry = 0; *ptr1-- = val; } if (carry == 1) *ptr1 = (*ptr1 + 1) % 10; } /* We now know the quotient digit. */ *qptr++ = qguess; qdig++; } } /* Clean up and return the number. */ qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); if (bc_is_zero (qval)) qval->n_sign = PLUS; _bc_rm_leading_zeros (qval); bc_free_num (quot); *quot = qval; /* Clean up temporary storage. */ free (mval); free (num1); free (num2); return 0; /* Everything is OK. */ } /* Division *and* modulo for numbers. This computes both NUM1 / NUM2 and NUM1 % NUM2 and puts the results in QUOT and REM, except that if QUOT is NULL then that store will be omitted. */ int bc_divmod (num1, num2, quot, rem, scale) bc_num num1, num2, *quot, *rem; int scale; { bc_num quotient = NULL; bc_num temp; int rscale; /* Check for correct numbers. */ if (bc_is_zero (num2)) return -1; /* Calculate final scale. */ rscale = MAX (num1->n_scale, num2->n_scale+scale); bc_init_num(&temp); /* Calculate it. */ bc_divide (num1, num2, &temp, scale); if (quot) quotient = bc_copy_num (temp); bc_multiply (temp, num2, &temp, rscale); bc_sub (num1, temp, rem, rscale); bc_free_num (&temp); if (quot) { bc_free_num (quot); *quot = quotient; } return 0; /* Everything is OK. */ } /* Modulo for numbers. This computes NUM1 % NUM2 and puts the result in RESULT. */ int bc_modulo (num1, num2, result, scale) bc_num num1, num2, *result; int scale; { return bc_divmod (num1, num2, NULL, result, scale); } /* Raise BASE to the EXPO power, reduced modulo MOD. The result is placed in RESULT. If a EXPO is not an integer, only the integer part is used. */ int bc_raisemod (base, expo, mod, result, scale) bc_num base, expo, mod, *result; int scale; { bc_num power, exponent, parity, temp; int rscale; /* Check for correct numbers. */ if (bc_is_zero(mod)) return -1; if (bc_is_neg(expo)) return -1; /* Set initial values. */ power = bc_copy_num (base); exponent = bc_copy_num (expo); temp = bc_copy_num (_one_); bc_init_num(&parity); /* Check the base for scale digits. */ if (base->n_scale != 0) bc_rt_warn ("non-zero scale in base"); /* Check the exponent for scale digits. */ if (exponent->n_scale != 0) { bc_rt_warn ("non-zero scale in exponent"); bc_divide (exponent, _one_, &exponent, 0); /*truncate */ } /* Check the modulus for scale digits. */ if (mod->n_scale != 0) bc_rt_warn ("non-zero scale in modulus"); /* Do the calculation. */ rscale = MAX(scale, base->n_scale); while ( !bc_is_zero(exponent) ) { (void) bc_divmod (exponent, _two_, &exponent, &parity, 0); if ( !bc_is_zero(parity) ) { bc_multiply (temp, power, &temp, rscale); (void) bc_modulo (temp, mod, &temp, scale); } bc_multiply (power, power, &power, rscale); (void) bc_modulo (power, mod, &power, scale); } /* Assign the value. */ bc_free_num (&power); bc_free_num (&exponent); bc_free_num (result); *result = temp; return 0; /* Everything is OK. */ } /* Raise NUM1 to the NUM2 power. The result is placed in RESULT. Maximum exponent is LONG_MAX. If a NUM2 is not an integer, only the integer part is used. */ void bc_raise (num1, num2, result, scale) bc_num num1, num2, *result; int scale; { bc_num temp, power; long exponent; int rscale; int pwrscale; int calcscale; char neg; /* Check the exponent for scale digits and convert to a long. */ if (num2->n_scale != 0) bc_rt_warn ("non-zero scale in exponent"); exponent = bc_num2long (num2); if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0)) bc_rt_error ("exponent too large in raise"); /* Special case if exponent is a zero. */ if (exponent == 0) { bc_free_num (result); *result = bc_copy_num (_one_); return; } /* Other initializations. */ if (exponent < 0) { neg = TRUE; exponent = -exponent; rscale = scale; } else { neg = FALSE; rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale)); } /* Set initial value of temp. */ power = bc_copy_num (num1); pwrscale = num1->n_scale; while ((exponent & 1) == 0) { pwrscale = 2*pwrscale; bc_multiply (power, power, &power, pwrscale); exponent = exponent >> 1; } temp = bc_copy_num (power); calcscale = pwrscale; exponent = exponent >> 1; /* Do the calculation. */ while (exponent > 0) { pwrscale = 2*pwrscale; bc_multiply (power, power, &power, pwrscale); if ((exponent & 1) == 1) { calcscale = pwrscale + calcscale; bc_multiply (temp, power, &temp, calcscale); } exponent = exponent >> 1; } /* Assign the value. */ if (neg) { bc_divide (_one_, temp, result, rscale); bc_free_num (&temp); } else { bc_free_num (result); *result = temp; if ((*result)->n_scale > rscale) (*result)->n_scale = rscale; } bc_free_num (&power); } /* Take the square root NUM and return it in NUM with SCALE digits after the decimal place. */ int bc_sqrt (num, scale) bc_num *num; int scale; { int rscale, cmp_res, done; int cscale; bc_num guess, guess1, point5, diff; /* Initial checks. */ cmp_res = bc_compare (*num, _zero_); if (cmp_res < 0) return 0; /* error */ else { if (cmp_res == 0) { bc_free_num (num); *num = bc_copy_num (_zero_); return 1; } } cmp_res = bc_compare (*num, _one_); if (cmp_res == 0) { bc_free_num (num); *num = bc_copy_num (_one_); return 1; } /* Initialize the variables. */ rscale = MAX (scale, (*num)->n_scale); bc_init_num(&guess); bc_init_num(&guess1); bc_init_num(&diff); point5 = bc_new_num (1,1); point5->n_value[1] = 5; /* Calculate the initial guess. */ if (cmp_res < 0) { /* The number is between 0 and 1. Guess should start at 1. */ guess = bc_copy_num (_one_); cscale = (*num)->n_scale; } else { /* The number is greater than 1. Guess should start at 10^(exp/2). */ bc_int2num (&guess,10); bc_int2num (&guess1,(*num)->n_len); bc_multiply (guess1, point5, &guess1, 0); guess1->n_scale = 0; bc_raise (guess, guess1, &guess, 0); bc_free_num (&guess1); cscale = 3; } /* Find the square root using Newton's algorithm. */ done = FALSE; while (!done) { bc_free_num (&guess1); guess1 = bc_copy_num (guess); bc_divide (*num, guess, &guess, cscale); bc_add (guess, guess1, &guess, 0); bc_multiply (guess, point5, &guess, cscale); bc_sub (guess, guess1, &diff, cscale+1); if (bc_is_near_zero (diff, cscale)) { if (cscale < rscale+1) cscale = MIN (cscale*3, rscale+1); else done = TRUE; } } /* Assign the number and clean up. */ bc_free_num (num); bc_divide (guess,_one_,num,rscale); bc_free_num (&guess); bc_free_num (&guess1); bc_free_num (&point5); bc_free_num (&diff); return 1; } /* The following routines provide output for bcd numbers package using the rules of POSIX bc for output. */ /* This structure is used for saving digits in the conversion process. */ typedef struct stk_rec { long digit; struct stk_rec *next; } stk_rec; /* The reference string for digits. */ static char ref_str[] = "0123456789ABCDEF"; /* A special output routine for "multi-character digits." Exactly SIZE characters must be output for the value VAL. If SPACE is non-zero, we must output one space before the number. OUT_CHAR is the actual routine for writing the characters. */ void bc_out_long (val, size, space, out_char) long val; int size, space; #ifdef NUMBER__STDC__ void (*out_char)(int); #else void (*out_char)(); #endif { char digits[40]; int len, ix; if (space) (*out_char) (' '); sprintf (digits, "%ld", val); len = strlen (digits); while (size > len) { (*out_char) ('0'); size--; } for (ix=0; ix < len; ix++) (*out_char) (digits[ix]); } /* Output of a bcd number. NUM is written in base O_BASE using OUT_CHAR as the routine to do the actual output of the characters. */ void bc_out_num (num, o_base, out_char, leading_zero) bc_num num; int o_base; #ifdef NUMBER__STDC__ void (*out_char)(int); #else void (*out_char)(); #endif int leading_zero; { char *nptr; int index, fdigit, pre_space; stk_rec *digits, *temp; bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit; /* The negative sign if needed. */ if (num->n_sign == MINUS) (*out_char) ('-'); /* Output the number. */ if (bc_is_zero (num)) (*out_char) ('0'); else if (o_base == 10) { /* The number is in base 10, do it the fast way. */ nptr = num->n_value; if (num->n_len > 1 || *nptr != 0) for (index=num->n_len; index>0; index--) (*out_char) (BCD_CHAR(*nptr++)); else nptr++; if (leading_zero && bc_is_zero (num)) (*out_char) ('0'); /* Now the fraction. */ if (num->n_scale > 0) { (*out_char) ('.'); for (index=0; indexn_scale; index++) (*out_char) (BCD_CHAR(*nptr++)); } } else { /* special case ... */ if (leading_zero && bc_is_zero (num)) (*out_char) ('0'); /* The number is some other base. */ digits = NULL; bc_init_num (&int_part); bc_divide (num, _one_, &int_part, 0); bc_init_num (&frac_part); bc_init_num (&cur_dig); bc_init_num (&base); bc_sub (num, int_part, &frac_part, 0); /* Make the INT_PART and FRAC_PART positive. */ int_part->n_sign = PLUS; frac_part->n_sign = PLUS; bc_int2num (&base, o_base); bc_init_num (&max_o_digit); bc_int2num (&max_o_digit, o_base-1); /* Get the digits of the integer part and push them on a stack. */ while (!bc_is_zero (int_part)) { bc_modulo (int_part, base, &cur_dig, 0); temp = (stk_rec *) malloc (sizeof(stk_rec)); if (temp == NULL) bc_out_of_memory(); temp->digit = bc_num2long (cur_dig); temp->next = digits; digits = temp; bc_divide (int_part, base, &int_part, 0); } /* Print the digits on the stack. */ if (digits != NULL) { /* Output the digits. */ while (digits != NULL) { temp = digits; digits = digits->next; if (o_base <= 16) (*out_char) (ref_str[ (int) temp->digit]); else bc_out_long (temp->digit, max_o_digit->n_len, 1, out_char); free (temp); } } /* Get and print the digits of the fraction part. */ if (num->n_scale > 0) { (*out_char) ('.'); pre_space = 0; t_num = bc_copy_num (_one_); while (t_num->n_len <= num->n_scale) { bc_multiply (frac_part, base, &frac_part, num->n_scale); fdigit = bc_num2long (frac_part); bc_int2num (&int_part, fdigit); bc_sub (frac_part, int_part, &frac_part, 0); if (o_base <= 16) (*out_char) (ref_str[fdigit]); else { bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char); pre_space = 1; } bc_multiply (t_num, base, &t_num, 0); } bc_free_num (&t_num); } /* Clean up. */ bc_free_num (&int_part); bc_free_num (&frac_part); bc_free_num (&base); bc_free_num (&cur_dig); bc_free_num (&max_o_digit); } } /* Convert a number NUM to a long. The function returns only the integer part of the number. For numbers that are too large to represent as a long, this function returns a zero. This can be detected by checking the NUM for zero after having a zero returned. */ long bc_num2long (num) bc_num num; { long val; char *nptr; int index; /* Extract the int value, ignore the fraction. */ val = 0; nptr = num->n_value; for (index=num->n_len; (index>0) && (val<=(LONG_MAX/BASE)); index--) val = val*BASE + *nptr++; /* Check for overflow. If overflow, return zero. */ if (index>0) val = 0; if (val < 0) val = 0; /* Return the value. */ if (num->n_sign == PLUS) return (val); else return (-val); } /* Convert an integer VAL to a bc number NUM. */ void bc_int2num (num, val) bc_num *num; int val; { char buffer[30]; char *bptr, *vptr; int ix = 1; char neg = 0; /* Sign. */ if (val < 0) { neg = 1; val = -val; } /* Get things going. */ bptr = buffer; *bptr++ = (unsigned)val % BASE; /* type cast to unsigned, bug fix Wolf Lammen */ val = (unsigned)val / BASE; /* type cast to unsigned, bug fix Wolf Lammen */ /* Extract remaining digits. */ while (val != 0) { *bptr++ = val % BASE; val = val / BASE; ix++; /* Count the digits. */ } /* Make the number. */ bc_free_num (num); *num = bc_new_num (ix, 0); if (neg) (*num)->n_sign = MINUS; /* Assign the digits. */ vptr = (*num)->n_value; while (ix-- > 0) *vptr++ = *--bptr; } /* Convert a numbers to a string. Base 10 only.*/ char *bc_num2str (num) bc_num num; { char *str, *sptr; char *nptr; int index, signch; /* Allocate the string memory. */ signch = ( num->n_sign == PLUS ? 0 : 1 ); /* Number of sign chars. */ if (num->n_scale > 0) str = (char *) malloc (num->n_len + num->n_scale + 2 + signch); else str = (char *) malloc (num->n_len + 1 + signch); if (str == NULL) bc_out_of_memory(); /* The negative sign if needed. */ sptr = str; if (signch) *sptr++ = '-'; /* Load the whole number. */ nptr = num->n_value; for (index=num->n_len; index>0; index--) *sptr++ = BCD_CHAR(*nptr++); /* Now the fraction. */ if (num->n_scale > 0) { *sptr++ = '.'; for (index=0; indexn_scale; index++) *sptr++ = BCD_CHAR(*nptr++); } /* Terminate the string and return it! */ *sptr = '\0'; return (str); } /* Convert strings to bc numbers. Base 10 only.*/ void bc_str2num (num, str, scale) bc_num *num; char *str; int scale; { int digits, strscale; char *ptr, *nptr; char zero_int; /* Prepare num. */ bc_free_num (num); /* Check for valid number and count digits. */ ptr = str; digits = 0; strscale = 0; zero_int = FALSE; if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */ while (*ptr == '0') ptr++; /* Skip leading zeros. */ while (isdigit((int)*ptr)) ptr++, digits++; /* digits */ if (*ptr == '.') ptr++; /* decimal point */ while (isdigit((int)*ptr)) ptr++, strscale++; /* digits */ if ((*ptr != '\0') || (digits+strscale == 0)) { *num = bc_copy_num (_zero_); return; } /* Adjust numbers and allocate storage and initialize fields. */ strscale = MIN(strscale, scale); if (digits == 0) { zero_int = TRUE; digits = 1; } *num = bc_new_num (digits, strscale); /* Build the whole number. */ ptr = str; if (*ptr == '-') { (*num)->n_sign = MINUS; ptr++; } else { (*num)->n_sign = PLUS; if (*ptr == '+') ptr++; } while (*ptr == '0') ptr++; /* Skip leading zeros. */ nptr = (*num)->n_value; if (zero_int) { *nptr++ = 0; digits = 0; } for (;digits > 0; digits--) *nptr++ = CH_VAL(*ptr++); /* Build the fractional part. */ if (strscale > 0) { ptr++; /* skip the decimal point! */ for (;strscale > 0; strscale--) *nptr++ = CH_VAL(*ptr++); } } /* pn prints the number NUM in base 10. */ static void out_char (int c) { putchar(c); } void pn (num) bc_num num; { bc_out_num (num, 10, out_char, 0); out_char ('\n'); } /* pv prints a character array as if it was a string of bcd digits. */ void pv (name, num, len) char *name; unsigned char *num; int len; { int i; printf ("%s=", name); for (i=0; i #ifdef __cplusplus extern "C" { #endif #undef _PROTOTYPE #ifndef NUMBER__STDC__ #define NUMBER__STDC__ #endif typedef enum {PLUS, MINUS} sign; typedef struct bc_struct *bc_num; typedef struct bc_struct { sign n_sign; int n_len; /* The number of digits before the decimal point. */ int n_scale; /* The number of digits after the decimal point. */ int n_refs; /* The number of pointers to this number. */ bc_num n_next; /* Linked list for available list. */ char *n_ptr; /* The pointer to the actual storage. If NULL, n_value points to the inside of another number (bc_multiply...) and should not be "freed." */ char *n_value; /* The number. Not zero char terminated. May not point to the same place as n_ptr as in the case of leading zeros generated. */ } bc_struct; /* The base used in storing the numbers in n_value above. Currently this MUST be 10. */ #define BASE 10 /* Some useful macros and constants. */ #define CH_VAL(c) (c - '0') #define CH_HEX(c) ((c < ':') ? ( c - '0') : (c < 'G') ? ( c - 'A' + 10) : ( c - 'a' + 10)) #define BCD_CHAR(d) (d + '0') #ifdef MIN #undef MIN #undef MAX #endif #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)>(b)?(b):(a)) #define ODD(a) ((a)&1) #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #ifndef LONG_MAX #define LONG_MAX 0x7ffffff #endif /* Global numbers. */ extern bc_num _zero_; extern bc_num _one_; extern bc_num _two_; /* Function Prototypes */ /* Define the _PROTOTYPE macro if it is needed. */ #ifndef _PROTOTYPE #ifdef NUMBER__STDC__ #define _PROTOTYPE(func, args) func args #else #define _PROTOTYPE(func, args) func() #endif #endif _PROTOTYPE(void bc_init_numbers, (void)); _PROTOTYPE(bc_num bc_new_num, (int length, int scale)); _PROTOTYPE(void bc_free_num, (bc_num *num)); _PROTOTYPE(bc_num bc_copy_num, (bc_num num)); _PROTOTYPE(void bc_init_num, (bc_num *num)); _PROTOTYPE(void bc_str2num, (bc_num *num, char *str, int scale)); _PROTOTYPE(char *bc_num2str, (bc_num num)); _PROTOTYPE(void bc_int2num, (bc_num *num, int val)); _PROTOTYPE(long bc_num2long, (bc_num num)); _PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2)); _PROTOTYPE(char bc_is_zero, (bc_num num)); _PROTOTYPE(char bc_is_near_zero, (bc_num num, int scale)); _PROTOTYPE(char bc_is_neg, (bc_num num)); _PROTOTYPE(void bc_add, (bc_num n1, bc_num n2, bc_num *result, int scale_min)); _PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result, int scale_min)); _PROTOTYPE(void bc_multiply, (bc_num n1, bc_num n2, bc_num *prod, int scale)); _PROTOTYPE(int bc_divide, (bc_num n1, bc_num n2, bc_num *quot, int scale)); _PROTOTYPE(int bc_modulo, (bc_num num1, bc_num num2, bc_num *result, int scale)); _PROTOTYPE(int bc_divmod, (bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, int scale)); _PROTOTYPE(int bc_raisemod, (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale)); _PROTOTYPE(void bc_raise, (bc_num num1, bc_num num2, bc_num *result, int scale)); _PROTOTYPE(int bc_sqrt, (bc_num *num, int scale)); _PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int), int leading_zero)); #ifdef __cplusplus } #endif #endif deepin-calculator-5.7.21/3rdparty/math/quantity.cpp000066400000000000000000000624401423020056600222700ustar00rootroot00000000000000// quantity.cpp // Support for units and dimensions // // This file is part of the SpeedCrunch project // Copyright (C) 2016 Pol Welter. // Copyright (C) 2016 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "quantity.h" #include "../core/settings.h" #include "rational.h" #include "units.h" #include #define RATIONAL_TOL HNumber("1e-20") #define ENSURE_DIMENSIONLESS(x) \ if (!(x).isDimensionless()) \ return DMath::nan(InvalidDimension); #define ENSURE_SAME_DIMENSION(x, y) \ if ((!(x).sameDimension(y))) \ return DMath::nan(DimensionMismatch); Quantity operator-(const Quantity &q) { Quantity res(q); res.m_numericValue = -res.m_numericValue; return res; } Quantity operator-(const Quantity &a, const Quantity &b) { Quantity res(a); if (!a.sameDimension(b)) return DMath::nan(DimensionMismatch); res.m_numericValue -= b.m_numericValue; return res; } bool operator>(const Quantity &l, const Quantity &r) { if (l.sameDimension(r)) return l.m_numericValue > r.m_numericValue; return false; } bool operator<(const Quantity &l, const Quantity &r) { if (l.sameDimension(r)) return l.m_numericValue < r.m_numericValue; return false; } bool operator>=(const Quantity &l, const Quantity &r) { if (l.sameDimension(r)) return l.m_numericValue >= r.m_numericValue; return false; } bool operator<=(const Quantity &l, const Quantity &r) { if (l.sameDimension(r)) return l.m_numericValue <= r.m_numericValue; return false; } bool operator==(const Quantity &l, const Quantity &r) { if (l.sameDimension(r)) return l.m_numericValue == r.m_numericValue; return false; } // Returns TRUE upon dimension mismatch. bool operator!=(const Quantity &l, const Quantity &r) { if (l.sameDimension(r)) return l.m_numericValue != r.m_numericValue; return true; } Quantity operator*(const HNumber &l, const Quantity &r) { return r * l; } Quantity operator*(const CNumber &l, const Quantity &r) { return r * l; } Quantity operator/(const HNumber &l, const Quantity &r) { return Quantity(l) / r; } Quantity operator/(const CNumber &l, const Quantity &r) { return Quantity(l) / r; } Quantity::Quantity() : m_numericValue(0) , m_unit(nullptr) , m_unitName("") { } Quantity::Quantity(const Quantity &other) : m_numericValue(other.m_numericValue) , m_dimension(other.m_dimension) , m_unit(nullptr) , m_unitName(other.m_unitName) , m_format(other.m_format) { if (other.hasUnit()) this->m_unit = new CNumber(other.unit()); cleanDimension(); } Quantity::Quantity(int i) : Quantity(CNumber(i)) { } Quantity::Quantity(const QJsonObject &json) : Quantity() { *this = deSerialize(json); } Quantity::Quantity(const HNumber &h) : Quantity(CNumber(h)) { } Quantity::Quantity(const CNumber &c) : Quantity() { this->m_numericValue = c; } Quantity::~Quantity() { delete m_unit; } bool Quantity::isNan() const { return m_numericValue.isNan(); } bool Quantity::isZero() const { return m_numericValue.isZero(); } bool Quantity::isReal() const { return m_numericValue.isReal(); } bool Quantity::isPositive() const { return m_numericValue.isPositive(); } bool Quantity::isNegative() const { return m_numericValue.isNegative(); } bool Quantity::isInteger() const { return (!this->hasDimension() && !this->hasUnit()) && m_numericValue.isInteger(); } bool Quantity::isEven() const { return this->isInteger() && (m_numericValue % CNumber(2) == 0); } bool Quantity::hasUnit() const { return this->m_unit != NULL; } CNumber Quantity::unit() const { if (this->hasUnit()) return CNumber(*(this->m_unit)); return CNumber(1); } QString Quantity::unitName() const { if (this->hasUnit()) return m_unitName; return ""; } CNumber Quantity::numericValue() const { return m_numericValue; } Quantity &Quantity::setDisplayUnit(const CNumber unit, const QString &name) { if (unit.isNan()) *this = DMath::nan(InvalidDimension); else { stripUnits(); m_unit = new CNumber(unit); m_unitName = name; } return *this; } Quantity &Quantity::setFormat(Format c) { m_format = c; return *this; } void Quantity::stripUnits() { delete m_unit; m_unit = nullptr; m_unitName = ""; } bool Quantity::hasDimension() const { return !this->m_dimension.empty(); } /* * Unlike hasDimension(), this does a clean up first, i.e. it * checks for redundant exponents. */ bool Quantity::isDimensionless() const { Quantity temp(*this); temp.cleanDimension(); return m_dimension.empty(); } QMap Quantity::getDimension() const { Quantity temp(*this); temp.cleanDimension(); return temp.m_dimension; } void Quantity::modifyDimension(const QString &key, const Rational &exponent) { if (exponent.isZero()) m_dimension.remove(key); else m_dimension.insert(key, exponent); } void Quantity::copyDimension(const Quantity &other) { clearDimension(); this->m_dimension = other.m_dimension; } void Quantity::clearDimension() { this->m_dimension.clear(); } // Note: Does NOT clean the dimension vector first. // The calling function must do so on its own. bool Quantity::sameDimension(const Quantity &other) const { return this->m_dimension == other.m_dimension; } void Quantity::cleanDimension() { auto i = m_dimension.begin(); while (i != m_dimension.end()) { if (i.value().isZero()) i = m_dimension.erase(i); else ++i; } } void Quantity::serialize(QJsonObject &json) const { QJsonObject nom_json; m_numericValue.serialize(nom_json); json["numeric_value"] = nom_json; if (hasDimension()) { QJsonObject dim_json; auto i = m_dimension.constBegin(); while (i != m_dimension.constEnd()) { const auto &exp = i.value(); const auto &name = i.key(); dim_json[name] = exp.toString(); ++i; } json["dimension"] = dim_json; } if (hasUnit()) { QJsonObject unit_json; m_unit->serialize(unit_json); json["unit"] = unit_json; json["unit_name"] = m_unitName; } if (!m_format.isNull()) { QJsonObject format_json; m_format.serialize(format_json); json["format"] = format_json; } } Quantity Quantity::deSerialize(const QJsonObject &json) { Quantity result; if (json.contains("numeric_value")) { QJsonObject num_json = json["numeric_value"].toObject(); result.m_numericValue = CNumber(num_json); } result.stripUnits(); if (json.contains("unit")) { QJsonObject unit_json = json["unit"].toObject(); result.m_unit = new CNumber(unit_json); } if (json.contains("unit_name")) result.m_unitName = json["unit_name"].toString(); if (json.contains("dimension")) { QJsonObject dim_json = json["dimension"].toObject(); for (int i = 0; i < dim_json.count(); ++i) { auto key = dim_json.keys().at(i); Rational val(dim_json[key].toString()); result.modifyDimension(key, val); } } if (json.contains("format")) { QJsonObject format_json = json["format"].toObject(); result.m_format = Quantity::Format::deSerialize(format_json); } return result; } Error Quantity::error() const { return m_numericValue.error(); } Quantity &Quantity::operator=(const Quantity &other) { m_numericValue = other.m_numericValue; m_dimension = other.m_dimension; m_format = other.m_format; stripUnits(); if (other.hasUnit()) { m_unit = new CNumber(*other.m_unit); m_unitName = other.m_unitName; } cleanDimension(); return *this; } Quantity Quantity::operator+(const Quantity &other) const { if (!this->sameDimension(other)) return DMath::nan(DimensionMismatch); Quantity result(*this); result.m_numericValue += other.m_numericValue; return result; } Quantity &Quantity::operator+=(const Quantity &other) { if (!this->sameDimension(other)) *this = DMath::nan(DimensionMismatch); else this->m_numericValue += other.m_numericValue; return *this; } Quantity &Quantity::operator-=(const Quantity &other) { return operator=(*this - other); } Quantity Quantity::operator*(const Quantity &other) const { Quantity result(*this); result.m_numericValue *= other.m_numericValue; if (!other.isDimensionless()) { result.stripUnits(); auto i = other.m_dimension.constBegin(); while (i != other.m_dimension.constEnd()) { const auto &exp = i.value(); const auto &name = i.key(); if (!result.m_dimension.contains(name)) result.m_dimension[name] = Rational(0); result.m_dimension[name] += exp; ++i; } result.cleanDimension(); } return result; } Quantity Quantity::operator*(const CNumber &other) const { Quantity result(*this); result.m_numericValue *= other; return result; } Quantity Quantity::operator*(const HNumber &other) const { return operator*(CNumber(other)); } Quantity &Quantity::operator*=(const Quantity &other) { return operator=(*this * other); } Quantity Quantity::operator/(const Quantity &other) const { Quantity result(*this); result.m_numericValue /= other.m_numericValue; if (!other.isDimensionless()) { result.stripUnits(); auto i = other.m_dimension.constBegin(); while (i != other.m_dimension.constEnd()) { const auto &exp = i.value(); const auto &name = i.key(); if (!result.m_dimension.contains(name)) result.m_dimension[name] = Rational(0); result.m_dimension[name] -= exp; ++i; } result.cleanDimension(); } return result; } Quantity Quantity::operator/(const HNumber &other) const { return operator/(CNumber(other)); } Quantity Quantity::operator/(const CNumber &other) const { Quantity result(*this); result.m_numericValue /= other; result.cleanDimension(); return result; } Quantity &Quantity::operator/=(const Quantity &other) { return operator=(*this / other); } Quantity Quantity::operator%(const Quantity &other) const { Quantity result(*this); result.m_numericValue = result.m_numericValue % other.m_numericValue; return result; } Quantity Quantity::operator&(const Quantity &other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue &= other.m_numericValue; return result; } Quantity &Quantity::operator&=(const Quantity &other) { return operator=(*this & other); } Quantity Quantity::operator|(const Quantity &other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue |= other.m_numericValue; return result; } Quantity &Quantity::operator|=(const Quantity &other) { return operator=(*this | other); } Quantity Quantity::operator^(const Quantity &other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue ^= other.m_numericValue; return result; } Quantity &Quantity::operator^=(const Quantity &other) { return operator=(*this ^ other); } Quantity Quantity::operator~() const { ENSURE_DIMENSIONLESS(*this); Quantity result(*this); result.m_numericValue = ~result.m_numericValue; return result; } Quantity Quantity::operator>>(const Quantity &other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue = result.m_numericValue >> other.m_numericValue; return result; } Quantity Quantity::operator<<(const Quantity &other) const { ENSURE_DIMENSIONLESS(*this); ENSURE_DIMENSIONLESS(other); Quantity result(*this); result.m_numericValue = result.m_numericValue << other.m_numericValue; return result; } Quantity::Format::Format() : CNumber::Format() { } Quantity::Format::Format(const CNumber::Format &other) : CNumber::Format(other) { } Quantity::Format::Format(const HNumber::Format &other) : CNumber::Format(other) { } Quantity::Format Quantity::Format::operator+(const Quantity::Format &other) const { return Quantity::Format(CNumber::Format::operator+(static_cast(other))); } void Quantity::Format::serialize(QJsonObject &json) const { switch (mode) { case Mode::General: json["mode"] = QStringLiteral("General"); break; case Mode::Fixed: json["mode"] = QStringLiteral("Fixed"); break; case Mode::Scientific: json["mode"] = QStringLiteral("Scientific"); break; case Mode::Engineering: json["mode"] = QStringLiteral("Engineering"); break; case Mode::Complement: json["mode"] = QStringLiteral("Complement"); break; case Mode::Null: break; } switch (base) { case Base::Binary: json["base"] = QStringLiteral("Binary"); break; case Base::Octal: json["base"] = QStringLiteral("Octal"); break; case Base::Hexadecimal: json["base"] = QStringLiteral("Hexadecimal"); break; case Base::Decimal: json["base"] = QStringLiteral("Decimal"); break; case Base::Null: break; } switch (notation) { case Notation::Cartesian: json["form"] = QStringLiteral("Cartesian"); break; case Notation::Polar: json["form"] = QStringLiteral("Polar"); break; case Notation::Null: default: break; } if (precision != PrecisionNull) json["precision"] = precision; } Quantity::Format Quantity::Format::deSerialize(const QJsonObject &json) { Format result; if (json.contains("mode")) { auto strMode = json["mode"].toString(); if (strMode == "General") result.mode = Mode::General; else if (strMode == "Fixed") result.mode = Mode::Fixed; else if (strMode == "Scientific") result.mode = Mode::Scientific; else if (strMode == "Engineering") result.mode = Mode::Engineering; else result.mode = Mode::Null; } else result.mode = Mode::Null; if (json.contains("base")) { auto strBase = json["base"].toString(); if (strBase == "Binary") result.base = Base::Binary; else if (strBase == "Octal") result.base = Base::Octal; else if (strBase == "Decimal") result.base = Base::Decimal; else if (strBase == "Hexadecimal") result.base = Base::Hexadecimal; else result.base = Base::Null; } else result.base = Base::Null; if (json.contains("form")) { auto strNotation = json["form"].toString(); if (strNotation == "Cartesian") result.notation = Notation::Cartesian; else if (strNotation == "Polar") result.notation = Notation::Polar; else result.notation = Notation::Null; } else result.notation = Notation::Null; result.precision = json.contains("precision") ? json["precision"].toInt() : PrecisionNull; return result; } bool Quantity::Format::isNull() const { return (mode == Mode::Null && base == Base::Null && precision == PrecisionNull && notation == Notation::Null); } // DMath // ===== bool DMath::complexMode = Settings::instance()->complexNumbers; // 关闭复数处理 #define COMPLEX_WRAP_1(fct, arg) \ (DMath::complexMode ? CMath::fct(arg) : CNumber(HMath::fct(arg.real))) #define COMPLEX_WRAP_2(fct, arg1, arg2) \ (DMath::complexMode ? CMath::fct(arg1, arg2) : CNumber(HMath::fct(arg1.real, arg2.real))) #define COMPLEX_WRAP_3(fct, arg1, arg2, arg3) \ (DMath::complexMode ? CMath::fct(arg1, arg2, arg3) : CNumber(HMath::fct(arg1.real, arg2.real, arg3.real))) #define COMPLEX_WRAP_4(fct, arg1, arg2, arg3, arg4) \ (DMath::complexMode ? CMath::fct(arg1, arg2, arg3, arg4) \ : CNumber(HMath::fct(arg1.real, arg2.real, arg3.real, arg4.real))) // Wrappers for functions that are only defined for dimensionless arguments // Mo argument. #define WRAPPER_DMATH_0(fct) \ Quantity DMath::fct() \ { \ return Quantity(CMath::fct()); \ } \ // One argument. #define WRAPPER_DMATH_1(fct) \ Quantity DMath::fct(const Quantity& arg1) \ { \ ENSURE_DIMENSIONLESS(arg1); \ return Quantity(COMPLEX_WRAP_1(fct, arg1.m_numericValue)); \ } // Two arguments. #define WRAPPER_DMATH_2(fct) \ Quantity DMath::fct(const Quantity& arg1, const Quantity& arg2) \ { \ ENSURE_DIMENSIONLESS(arg1); \ ENSURE_DIMENSIONLESS(arg2); \ return Quantity(COMPLEX_WRAP_2(fct, arg1.m_numericValue, arg2.m_numericValue)); \ } // Three arguments. #define WRAPPER_DMATH_3(fct) \ Quantity DMath::fct(const Quantity& arg1, const Quantity& arg2, const Quantity& arg3) \ { \ ENSURE_DIMENSIONLESS(arg1); \ ENSURE_DIMENSIONLESS(arg2); \ ENSURE_DIMENSIONLESS(arg3); \ return Quantity(COMPLEX_WRAP_3(fct, arg1.m_numericValue, arg2.m_numericValue, arg3.m_numericValue)); \ } // Four arguments. #define WRAPPER_DMATH_4(fct) \ Quantity DMath::fct(const Quantity& arg1, const Quantity& arg2, const Quantity& arg3, const Quantity& arg4) \ { \ ENSURE_DIMENSIONLESS(arg1); \ ENSURE_DIMENSIONLESS(arg2); \ ENSURE_DIMENSIONLESS(arg3); \ ENSURE_DIMENSIONLESS(arg4); \ return Quantity(COMPLEX_WRAP_4(fct, arg1.m_numericValue, arg2.m_numericValue, arg3.m_numericValue, \ arg4.m_numericValue)); \ } WRAPPER_DMATH_0(e) WRAPPER_DMATH_0(pi) WRAPPER_DMATH_0(phi) WRAPPER_DMATH_0(i) Quantity DMath::nan(Error error) { return Quantity(CMath::nan(error)); } WRAPPER_DMATH_1(rad2deg) WRAPPER_DMATH_1(deg2rad) WRAPPER_DMATH_1(rad2gon) WRAPPER_DMATH_1(gon2rad) WRAPPER_DMATH_1(integer) WRAPPER_DMATH_1(frac) WRAPPER_DMATH_1(floor) WRAPPER_DMATH_1(ceil) WRAPPER_DMATH_1(exp) WRAPPER_DMATH_1(ln) WRAPPER_DMATH_1(lg) WRAPPER_DMATH_1(lb) WRAPPER_DMATH_2(log) WRAPPER_DMATH_1(sinh) WRAPPER_DMATH_1(cosh) WRAPPER_DMATH_1(tanh) WRAPPER_DMATH_1(arsinh) WRAPPER_DMATH_1(arcosh) WRAPPER_DMATH_1(artanh) WRAPPER_DMATH_1(sin) WRAPPER_DMATH_1(cos) WRAPPER_DMATH_1(tan) WRAPPER_DMATH_1(cot) WRAPPER_DMATH_1(sec) WRAPPER_DMATH_1(csc) WRAPPER_DMATH_1(arcsin) WRAPPER_DMATH_1(arccos) WRAPPER_DMATH_1(arctan) WRAPPER_DMATH_2(arctan2) WRAPPER_DMATH_2(factorial) WRAPPER_DMATH_1(gamma) WRAPPER_DMATH_1(lnGamma) WRAPPER_DMATH_1(erf) WRAPPER_DMATH_1(erfc) WRAPPER_DMATH_2(gcd) WRAPPER_DMATH_2(idiv) Quantity DMath::round(const Quantity &n, int prec) { ENSURE_DIMENSIONLESS(n); return DMath::complexMode ? CMath::round(n.numericValue(), prec) : CNumber(HMath::round(n.numericValue().real, prec)); } Quantity DMath::trunc(const Quantity &n, int prec) { ENSURE_DIMENSIONLESS(n); return DMath::complexMode ? CMath::trunc(n.numericValue(), prec) : CNumber(HMath::trunc(n.numericValue().real, prec)); } WRAPPER_DMATH_2(nCr) WRAPPER_DMATH_2(nPr) WRAPPER_DMATH_3(binomialPmf) WRAPPER_DMATH_3(binomialCdf) WRAPPER_DMATH_2(binomialMean) WRAPPER_DMATH_2(binomialVariance) WRAPPER_DMATH_4(hypergeometricPmf) WRAPPER_DMATH_4(hypergeometricCdf) WRAPPER_DMATH_3(hypergeometricMean) WRAPPER_DMATH_3(hypergeometricVariance) WRAPPER_DMATH_2(poissonPmf) WRAPPER_DMATH_2(poissonCdf) WRAPPER_DMATH_1(poissonMean) WRAPPER_DMATH_1(poissonVariance) WRAPPER_DMATH_2(mask) WRAPPER_DMATH_2(sgnext) WRAPPER_DMATH_2(ashr) WRAPPER_DMATH_2(lshr) WRAPPER_DMATH_2(rosh) WRAPPER_DMATH_2(rcsh) WRAPPER_DMATH_3(decodeIeee754) WRAPPER_DMATH_4(decodeIeee754) QString DMath::format(Quantity q, Quantity::Format format) { format = q.format() + format; // Left hand side oerator takes priority. // Handle units. if (!q.hasUnit() && !q.isDimensionless()) { q.cleanDimension(); Units::findUnit(q); } QString unit_name = ' ' + q.unitName(); CNumber unit = q.unit(); CNumber number = q.m_numericValue; number /= unit; QString result = CMath::format(number, format); if (!number.real.isZero() && !number.imag.isZero() && unit_name != " ") result = "(" + result + ")"; if (unit_name != " ") result.append(unit_name); return result; } Quantity DMath::real(const Quantity &x) { Quantity result(x); result.m_numericValue = result.m_numericValue.real; return result; } Quantity DMath::imag(const Quantity &x) { Quantity result(x); result.m_numericValue = result.m_numericValue.imag; return result; } Quantity DMath::conj(const Quantity &n) { Quantity result = Quantity(n); // If in Real mode, just strip the imaginary part. result.m_numericValue = complexMode ? CMath::conj(result.m_numericValue) : CMath::real(result.m_numericValue); return result; } Quantity DMath::abs(const Quantity &n) { Quantity result(n); result.m_numericValue = COMPLEX_WRAP_1(abs, n.m_numericValue); return result; } Quantity DMath::phase(const Quantity &n) { return CMath::phase(n.numericValue()); } Quantity DMath::sqrt(const Quantity &n) { Quantity result(COMPLEX_WRAP_1(sqrt, n.m_numericValue)); auto i = n.m_dimension.constBegin(); while (i != n.m_dimension.constEnd()) { auto &exp = i.value(); auto &name = i.key(); result.modifyDimension(name, exp * Rational(1, 2)); ++i; } return result; } Quantity DMath::cbrt(const Quantity &n) { Quantity result(COMPLEX_WRAP_1(cbrt, n.m_numericValue)); auto i = n.m_dimension.constBegin(); while (i != n.m_dimension.constEnd()) { auto &exp = i.value(); auto &name = i.key(); result.modifyDimension(name, exp * Rational(1, 3)); ++i; } return result; } Quantity DMath::raise(const Quantity &n1, int n) { Quantity result; result.m_numericValue = complexMode ? CMath::raise(n1.m_numericValue, n) : CNumber(HMath::raise(n1.m_numericValue.real, n)); auto i = n1.m_dimension.constBegin(); while (i != n1.m_dimension.constEnd()) { auto &exp = i.value(); auto &name = i.key(); result.modifyDimension(name, exp * n); ++i; } return result; } Quantity DMath::raise(const Quantity &n1, const Quantity &n2) { if (!n2.isDimensionless() || (!n1.isDimensionless() && !n2.isReal() && complexMode)) return DMath::nan(InvalidDimension); // First get the new numeric value. Quantity result(COMPLEX_WRAP_2(raise, n1.m_numericValue, n2.m_numericValue)); if (n1.isDimensionless()) return result; // We can now assume that n1 has a dimension, but n2 is real. // Compute the new dimension: try to convert n2 to a Rational. If n2 is not // rational, return NaN. // For negative bases only allow odd denominators. Rational exponent(n2.m_numericValue.real); if (abs(exponent.toHNumber() - n2.m_numericValue.real) >= RATIONAL_TOL || (n1.isNegative() && exponent.denominator() % 2 == 0)) return DMath::nan(OutOfDomain); // Compute new dimension. auto i = n1.m_dimension.constBegin(); while (i != n1.m_dimension.constEnd()) { result.modifyDimension(i.key(), i.value()*exponent); ++i; } return result; } Quantity DMath::sgn(const Quantity &x) { return Quantity(CMath::sgn(x.m_numericValue)); } Quantity DMath::encodeIeee754(const Quantity &val, const Quantity &exp_bits, const Quantity &significand_bits) { ENSURE_DIMENSIONLESS(val); ENSURE_DIMENSIONLESS(exp_bits); ENSURE_DIMENSIONLESS(significand_bits); Quantity result(CMath::encodeIeee754(val.numericValue(), exp_bits.numericValue(), significand_bits.numericValue())); result.m_format = result.m_format + Quantity::Format::Fixed() + Quantity::Format::Hexadecimal(); return result; } Quantity DMath::encodeIeee754(const Quantity &val, const Quantity &exp_bits, const Quantity &significand_bits, const Quantity &exp_bias) { ENSURE_DIMENSIONLESS(val); ENSURE_DIMENSIONLESS(exp_bits); ENSURE_DIMENSIONLESS(significand_bits); ENSURE_DIMENSIONLESS(exp_bias); Quantity result(CMath::encodeIeee754(val.numericValue(), exp_bits.numericValue(), significand_bits.numericValue(), exp_bias.numericValue())); result.m_format = result.m_format + Quantity::Format::Fixed() + Quantity::Format::Hexadecimal(); return result; } deepin-calculator-5.7.21/3rdparty/math/quantity.h000066400000000000000000000225301423020056600217310ustar00rootroot00000000000000// quantity.h // Support for units and dimensions // // This file is part of the SpeedCrunch project // Copyright (C) 2016 Pol Welter. // Copyright (C) 2016 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef QUANTITY_H #define QUANTITY_H #include "cmath.h" #include "hmath.h" #include "../core/errors.h" #include class CNumber; class HNumber; class QJsonObject; class QString; class Rational; class DMath; class Quantity; Quantity operator*(const HNumber &, const Quantity &); Quantity operator*(const CNumber &, const Quantity &); Quantity operator/(const HNumber &, const Quantity &); Quantity operator/(const CNumber &, const Quantity &); class Quantity { friend class DMath; friend Quantity operator-(const Quantity &); friend Quantity operator-(const Quantity &, const Quantity &); friend bool operator>(const Quantity &, const Quantity &); friend bool operator<(const Quantity &, const Quantity &); friend bool operator>=(const Quantity &, const Quantity &); friend bool operator<=(const Quantity &, const Quantity &); friend bool operator==(const Quantity &, const Quantity &); friend bool operator!=(const Quantity &, const Quantity &); public: Quantity(); Quantity(const Quantity &); Quantity(int); Quantity(const QJsonObject &); Quantity(const HNumber &); Quantity(const CNumber &); ~Quantity(); bool isNan() const; bool isZero() const; bool isReal() const; bool isPositive() const; bool isNegative() const; bool isInteger() const; bool isEven() const; bool hasUnit() const; CNumber unit() const; QString unitName() const; CNumber numericValue() const; Quantity &setDisplayUnit(const CNumber unit, const QString &name); void stripUnits(); bool hasDimension() const; bool isDimensionless() const; QMap getDimension() const; void modifyDimension(const QString &key, const Rational &exponent); void copyDimension(const Quantity &); void clearDimension(); bool sameDimension(const Quantity &other) const; void cleanDimension(); void serialize(QJsonObject &) const; static Quantity deSerialize(const QJsonObject &); Error error() const; Quantity &operator=(const Quantity &); Quantity operator+(const Quantity &) const; Quantity &operator+=(const Quantity &); Quantity &operator-=(const Quantity &); Quantity operator*(const Quantity &) const; Quantity operator*(const CNumber &) const; Quantity operator*(const HNumber &) const; Quantity &operator*=(const Quantity &); Quantity operator/(const Quantity &) const; Quantity operator/(const HNumber &) const; Quantity operator/(const CNumber &) const; Quantity &operator/=(const Quantity &); Quantity operator%(const Quantity &) const; Quantity operator&(const Quantity &) const; Quantity &operator&=(const Quantity &); Quantity operator|(const Quantity &) const; Quantity &operator|=(const Quantity &); Quantity operator^(const Quantity &) const; Quantity &operator^=(const Quantity &); Quantity operator~() const; Quantity operator>>(const Quantity &) const; Quantity operator<<(const Quantity &) const; class Format : public CNumber::Format { public: Format(); Format(const CNumber::Format &); Format(const HNumber::Format &); Format operator+(const Format &) const; void serialize(QJsonObject &) const; static Format deSerialize(const QJsonObject &); bool isNull() const; }; Format format() const { return m_format; } Quantity &setFormat(Format); private: CNumber m_numericValue; QMap m_dimension; CNumber *m_unit; QString m_unitName; Format m_format; }; /* * Math functions for quantities with dimensions */ class DMath { public: static bool complexMode; static QString format(const Quantity, Quantity::Format = Quantity::Format()); // CONSTANTS static Quantity e(); static Quantity phi(); static Quantity pi(); static Quantity nan(Error = Success); static Quantity i(); // GENERAL MATH static Quantity rad2deg(const Quantity &); static Quantity deg2rad(const Quantity &); static Quantity rad2gon(const Quantity &); static Quantity gon2rad(const Quantity &); static Quantity abs(const Quantity &); static Quantity integer(const Quantity &); static Quantity frac(const Quantity &); static Quantity floor(const Quantity &); static Quantity ceil(const Quantity &); static Quantity gcd(const Quantity &, const Quantity &); static Quantity idiv(const Quantity &, const Quantity &); static Quantity round(const Quantity &, int prec = 0); static Quantity trunc(const Quantity &, int prec = 0); static Quantity sqrt(const Quantity &); static Quantity cbrt(const Quantity &); static Quantity raise(const Quantity &, int); static Quantity raise(const Quantity &, const Quantity &); static Quantity sgn(const Quantity &); // EXPONENTIAL FUNCTION AND RELATED static Quantity exp(const Quantity &); static Quantity ln(const Quantity &); static Quantity lg(const Quantity &); static Quantity lb(const Quantity &); static Quantity log(const Quantity &base, const Quantity &); static Quantity sinh(const Quantity &); static Quantity cosh(const Quantity &); static Quantity tanh(const Quantity &); static Quantity arsinh(const Quantity &); static Quantity arcosh(const Quantity &); static Quantity artanh(const Quantity &); // COMPLEX static Quantity real(const Quantity &); static Quantity imag(const Quantity &); static Quantity conj(const Quantity &); static Quantity phase(const Quantity &); // TRIGONOMETRY static Quantity sin(const Quantity &); static Quantity cos(const Quantity &); static Quantity tan(const Quantity &); static Quantity cot(const Quantity &); static Quantity sec(const Quantity &); static Quantity csc(const Quantity &); static Quantity arcsin(const Quantity &); static Quantity arccos(const Quantity &); static Quantity arctan(const Quantity &); static Quantity arctan2(const Quantity &, const Quantity &y); // HIGHER MATH FUNCTIONS static Quantity factorial(const Quantity &x, const Quantity &base = CNumber(1)); static Quantity gamma(const Quantity &); static Quantity lnGamma(const Quantity &); static Quantity erf(const Quantity &); static Quantity erfc(const Quantity &); // PROBABILITY static Quantity nCr(const Quantity &n, const Quantity &k); static Quantity nPr(const Quantity &n, const Quantity &r); static Quantity binomialPmf(const Quantity &k, const Quantity &n, const Quantity &p); static Quantity binomialCdf(const Quantity &k, const Quantity &n, const Quantity &p); static Quantity binomialMean(const Quantity &n, const Quantity &p); static Quantity binomialVariance(const Quantity &n, const Quantity &p); static Quantity hypergeometricPmf(const Quantity &k, const Quantity &N, const Quantity &M, const Quantity &n); static Quantity hypergeometricCdf(const Quantity &k, const Quantity &N, const Quantity &M, const Quantity &n); static Quantity hypergeometricMean(const Quantity &N, const Quantity &M, const Quantity &n); static Quantity hypergeometricVariance(const Quantity &N, const Quantity &M, const Quantity &n); static Quantity poissonPmf(const Quantity &k, const Quantity &l); static Quantity poissonCdf(const Quantity &k, const Quantity &l); static Quantity poissonMean(const Quantity &l); static Quantity poissonVariance(const Quantity &l); // LOGIC static Quantity mask(const Quantity &, const Quantity &bits); static Quantity sgnext(const Quantity &, const Quantity &bits); static Quantity ashr(const Quantity &, const Quantity &bits); static Quantity lshr(const Quantity &, const Quantity &bits); //逻辑移位 static Quantity rosh(const Quantity &, const Quantity &bits); //循环移位 static Quantity rcsh(const Quantity &, const Quantity &bits); //带进位循环移位 // IEEE-754 CONVERSION static Quantity decodeIeee754(const Quantity &, const Quantity &exp_bits, const Quantity &significand_bits); static Quantity decodeIeee754(const Quantity &, const Quantity &exp_bits, const Quantity &significand_bits, const Quantity &exp_bias); static Quantity encodeIeee754(const Quantity &, const Quantity &exp_bits, const Quantity &significand_bits); static Quantity encodeIeee754(const Quantity &, const Quantity &exp_bits, const Quantity &significand_bits, const Quantity &exp_bias); }; #endif // QUANTITY_H deepin-calculator-5.7.21/3rdparty/math/rational.cpp000066400000000000000000000142021423020056600222140ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "rational.h" #include "hmath.h" #include "../core/numberformatter.h" #include #include #include #include void Rational::normalize() { if (m_denom == 0) { m_valid = false; return; } if (m_num == 0) { m_denom = 1; return; } int g = gcd(abs(m_num), abs(m_denom)); m_num /= g; m_denom /= g; if (m_denom < 0) { m_num = -m_num; m_denom = -m_denom; } } int Rational::compare(const Rational &other) const { return m_num * other.m_denom - m_denom * other.m_num; } /* * Find a rational approximation to num using a continued fraction scheme. * Code adapted from the 'Fraction' module for the PYTHON programming language, * authored by Sjoerd Mullender and Jeffrey Yasskin. */ Rational::Rational(const HNumber &num) : m_num(1), m_denom(1), m_valid(1) { if (num.isZero()) { m_num = 0; return; } if (HMath::abs(num) > HNumber(INT_MAX) || HMath::abs(num) < HNumber(1) / HNumber(INT_MAX)) { m_valid = false; return; } if (num.isInteger()) { m_num = num.toInt(); return; } const unsigned long long MAXD = INT_MAX / 2; // maximal denominator unsigned long long p0 = 0, q0 = 1, p1 = 1, q1 = 0; HNumber val(HMath::abs(num)); while (true) { long a = HMath::floor(val).toInt(); unsigned long long q2 = q0 + a * q1; if (q2 > MAXD) break; unsigned long long temp1 = p0, temp2 = p1, temp3 = q1; p0 = temp2; q0 = temp3; p1 = temp1 + a * temp2; q1 = q2; if (HMath::frac(val).isZero()) break; val = HNumber(1) / HMath::frac(val); if (val > HNumber(MAXD)) break; } Rational bound(p1, q1); if (num < 0) { bound.m_num *= -1; } *this = bound; } Rational::Rational(const double &num): m_num(1), m_denom(1), m_valid(1) { if (num == 0) { m_num = 0; return; } if (std::abs(num) > INT_MAX || std::abs(1. / num) > INT_MAX) { m_valid = false; return; } const long long MAXD = INT_MAX / 2; // maximal denominator long long p0 = 0, q0 = 1, p1 = 1, q1 = 0; double val = fabs(num); while (true) { unsigned long long a = static_cast(floor(val)); unsigned long long q2 = q0 + a * q1; if (q2 > MAXD) break; unsigned long long temp1 = p0, temp2 = p1, temp3 = q1; p0 = temp2; q0 = temp3; p1 = temp1 + a * temp2; q1 = q2; if (val == a) break; val = 1 / (val - a); } Rational bound(p1, q1); if (num < 0) bound.m_num *= -1; *this = bound; } Rational::Rational(const QString &str) : m_num(0), m_denom(1), m_valid(true) { if (str == "") { m_valid = false; return; } QStringList l = str.split("/"); if (l.size() == 1) { bool ok; m_num = l.at(0).toInt(&ok); if (!ok) { m_valid = false; return; } } else if (l.size() == 2) { bool ok; m_num = l.at(0).toInt(&ok); if (!ok) { m_valid = false; return; } m_denom = l.at(1).toInt(&ok); if (!ok) { m_valid = false; return; } } } Rational Rational::operator*(const Rational &other) const { return Rational(this->m_num * other.m_num, this->m_denom * other.m_denom); } Rational Rational::operator/(const Rational &other) const { if (other.isZero()) return Rational(1, 0); // Rational(1,0) will set m_valid=false return Rational(this->m_num / other.m_num, this->m_denom / other.m_denom); } Rational Rational::operator+(const Rational &other) const { return Rational(this->m_num * other.m_denom + this->m_denom * other.m_num, this->m_denom * other.m_denom); } Rational Rational::operator-(const Rational &other) const { return Rational(this->m_num * other.m_denom - this->m_denom * other.m_num, this->m_denom * other.m_denom); } Rational &Rational::operator=(const Rational &other) { m_num = other.m_num; m_denom = other.m_denom; m_valid = other.m_valid; return *this; } Rational &Rational::operator+=(const Rational &other) { return operator=(*this + other); } Rational &Rational::operator-=(const Rational &other) { return operator=(*this - other); } Rational &Rational::operator*=(const Rational &other) { return operator=(*this * other); } Rational &Rational::operator/=(const Rational &other) { return operator=(*this / other); } bool Rational::operator<(const Rational &other) const { return compare(other) < 0; } bool Rational::operator==(const Rational &other) const { return compare(other) == 0; } bool Rational::operator>(const Rational &other) const { return compare(other) > 0; } bool Rational::isZero() const { return m_num == 0; } bool Rational::isValid() const { return m_valid; } QString Rational::toString() const { if (m_denom == 1) return QString::fromLatin1("%1").arg(m_num); return QString::fromLatin1("%1/%2").arg(m_num).arg(m_denom); } HNumber Rational::toHNumber() const { HNumber num(m_num); HNumber denom(m_denom); return num / denom; } double Rational::toDouble() const { return double(m_num) / m_denom; } deepin-calculator-5.7.21/3rdparty/math/rational.h000066400000000000000000000044501423020056600216650ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef RATIONAL_H #define RATIONAL_H class HNumber; class QString; class Rational { int m_num; int m_denom; bool m_valid; inline int gcd(int a, int b) const {return (b==0) ? a : gcd(b, a%b);} void normalize(); int compare(const Rational & other) const; public: Rational() : m_num(0), m_denom(1), m_valid(true) {} Rational(const HNumber &num); Rational(const double &num); Rational(const QString & str); Rational(const int a, const int b) : m_num(a), m_denom(b), m_valid(true) {normalize();} int numerator() const {return m_num;} int denominator() const {return m_denom;} Rational operator*(const Rational & other) const; Rational operator/(const Rational & other) const; Rational operator+(const Rational & other) const; Rational operator-(const Rational & other) const; Rational &operator=(const Rational & other); Rational &operator+=(const Rational & other); Rational &operator-=(const Rational & other); Rational &operator*=(const Rational & other); Rational &operator/=(const Rational & other); bool operator<(const Rational & other) const; bool operator==(const Rational & other) const; bool operator!=(const Rational & other) const {return !operator==(other);} bool operator>(const Rational & other) const; bool isZero() const; bool isValid() const; QString toString() const; HNumber toHNumber( )const; double toDouble() const; }; #endif // RATIONAL_H deepin-calculator-5.7.21/3rdparty/math/units.cpp000066400000000000000000000444711423020056600215600ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // Copyright (C) 2016 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #include "units.h" #include "quantity.h" #include "rational.h" #include #include #define UNIT_CACHE(name, value) \ const Quantity Units::name() \ { \ if (!m_cache.contains(#name)) \ m_cache[#name] = value; \ return (m_cache[#name]); \ } #define BASE_UNIT_CACHE(name, dimension) \ const Quantity Units::name() \ { \ if (!m_cache.contains(#name)) { \ Quantity name(1); \ name.modifyDimension(dimension, 1); \ m_cache[#name] = name; \ } \ return m_cache[#name]; \ } QHash, Unit> Units::m_matchLookup; QMap Units::m_cache; void Units::pushUnit(Quantity q, QString name) { q.cleanDimension(); Unit u(name, q); m_matchLookup.insert(q.getDimension(), u); } unsigned int qHash(QMap dimension) { QStringList keyList(dimension.keys()); QString blob(""); keyList.sort(); for (int i = 0; i < keyList.size(); ++i) { keyList[i].append(dimension[keyList[i]].toString()); blob.append(keyList[i]); } return qHash(blob); } /* * initialize the lookup table for automatic matching */ void Units::initTable() { m_matchLookup.clear(); pushUnit(joule(), "newton meter"); // energy or torque pushUnit(newton(), "newton"); // force pushUnit(watt(), "watt"); // power pushUnit(pascal(), "pascal"); // pressure or energy density pushUnit(coulomb(), "coulomb"); // charge pushUnit(volt(), "volt"); // electrical potential pushUnit(ohm(), "ohm"); // el. resistance pushUnit(siemens(), "siemens"); // el. conductance pushUnit(ohm()*meter(), "ohm meter"); // el. resistivity pushUnit(siemens() / meter(), "siemens/meter"); // el. conductivity pushUnit(siemens() / meter() / mole(), "siemens/(meter mole)"); // molar conductivity pushUnit(farad(), "farad"); // capacitance pushUnit(tesla(), "tesla"); // magnetic flux density pushUnit(weber(), "weber"); // magnetic flux pushUnit(henry(), "henry"); // inductance pushUnit(coulomb() / cbmeter(), "coulomb/meter³"); // electric charge density pushUnit(coulomb() / sqmeter(), "coulomb/meter²"); // surface charge density or el. flux pushUnit(coulomb() / kilogram(), "coulomb/kilogram"); // exposure pushUnit(farad() / meter(), "farad/meter"); // permittivity pushUnit(henry() / meter(), "henry/meter"); // permeability pushUnit(joule() / kilogram() / kelvin(), "joule/(kilogram kelvin)"); // specific heat capacity pushUnit(joule() / mole() / kelvin(), "joule/(mole kelvin"); // molar heat capacity pushUnit(mole() / second() / cbmeter(), "mole/(second meter³)"); // catalytic activity pushUnit(newton() / meter(), "newton/meter"); // surface tension pushUnit(pascal()*second(), "pascal second"); // dynamic viscosity pushUnit(volt() / meter(), "volt/meter"); // el. field pushUnit(watt() / meter() / kelvin(), "watt/(meter kelvin)"); // thermal conductivity pushUnit(watt() / sqmeter(), "watt/meter²"); // heat flux pushUnit(joule() / kelvin(), "joule/kelvin"); // entropy or heat capacity pushUnit(joule() / kilogram(), "joule/kilogram"); // specific energy } void Units::findUnit(Quantity &q) { QString unit_name = ""; CNumber unit(1); q.cleanDimension(); if (m_matchLookup.isEmpty()) initTable(); // Match derived units. if (m_matchLookup.contains(q.getDimension())) { Unit temp(m_matchLookup[q.getDimension()]); q.setDisplayUnit(temp.value.numericValue(), temp.name); } else { // Autogenerate unit name (product of base units). auto dimension = q.getDimension(); auto i = dimension.constBegin(); while (i != dimension.constEnd()) { auto exponent = i.value().toString(); if (exponent.contains('/')) exponent = "^(" + exponent + ')'; else if (exponent == "1") exponent = ""; else exponent = '^' + exponent; if (exponent == QLatin1String("^0")) exponent = QString::fromUtf8("⁰"); else if (exponent == QLatin1String("^2")) exponent = QString::fromUtf8("²"); else if (exponent == QLatin1String("^3")) exponent = QString::fromUtf8("³"); else if (exponent == QLatin1String("^4")) exponent = QString::fromUtf8("⁴") ; else if (exponent == QLatin1String("^5")) exponent = QString::fromUtf8("⁵") ; else if (exponent == QLatin1String("^6")) exponent = QString::fromUtf8("⁶") ; else if (exponent == QLatin1String("^7")) exponent = QString::fromUtf8("⁷") ; else if (exponent == QLatin1String("^8")) exponent = QString::fromUtf8("⁸") ; else if (exponent == QLatin1String("^9")) exponent = QString::fromUtf8("⁹") ; else if (exponent == QLatin1String("^-1")) exponent = QString::fromUtf8("⁻¹"); else if (exponent == QLatin1String("^-2")) exponent = QString::fromUtf8("⁻²"); else if (exponent == QLatin1String("^-3")) exponent = QString::fromUtf8("⁻³"); else if (exponent == QLatin1String("^-4")) exponent = QString::fromUtf8("⁻⁴") ; else if (exponent == QLatin1String("^-5")) exponent = QString::fromUtf8("⁻⁵") ; else if (exponent == QLatin1String("^-6")) exponent = QString::fromUtf8("⁻⁶") ; else if (exponent == QLatin1String("^-7")) exponent = QString::fromUtf8("⁻⁷") ; else if (exponent == QLatin1String("^-8")) exponent = QString::fromUtf8("⁻⁸") ; else if (exponent == QLatin1String("^-9")) exponent = QString::fromUtf8("⁻⁹") ; // TODO: Replace this with a lookup to a repository. if (i.key() == "length") unit_name += " meter"; else if (i.key() == "time") unit_name += " second"; else if (i.key() == "mass") unit_name += " kilogram"; else if (i.key() == "el. current") unit_name += " ampere"; else if (i.key() == "amount") unit_name += " mole"; else if (i.key() == "luminous intensity") unit_name += " candela"; else if (i.key() == "temperature") unit_name += " kelvin"; else if (i.key() == "information") unit_name += " bit"; else unit_name += " " + i.key(); // fall back to the dimension name unit_name += exponent; ++i; } q.setDisplayUnit(unit, unit_name.trimmed()); } } #define ADD_UNIT(name) result.append(Unit(#name, name())) #define ADD_UNIT_ALIAS(name, alias) result.append(Unit(#alias, name())) // This list contains the units that wil be set as builtin variables by the evaluator. const QList Units::getList() { QList result; ADD_UNIT(meter); ADD_UNIT(second); ADD_UNIT(kilogram); ADD_UNIT(ampere); ADD_UNIT(mole); ADD_UNIT(candela); ADD_UNIT(kelvin); ADD_UNIT(bit); ADD_UNIT(yocto); ADD_UNIT(zepto); ADD_UNIT(atto); ADD_UNIT(femto); ADD_UNIT(pico); ADD_UNIT(nano); ADD_UNIT(micro); ADD_UNIT(milli); ADD_UNIT(centi); ADD_UNIT(deci); ADD_UNIT(deca); ADD_UNIT(hecto); ADD_UNIT(kilo); ADD_UNIT(mega); ADD_UNIT(giga); ADD_UNIT(tera); ADD_UNIT(peta); ADD_UNIT(exa); ADD_UNIT(zetta); ADD_UNIT(yotta); ADD_UNIT(kibi); ADD_UNIT(mebi); ADD_UNIT(gibi); ADD_UNIT(tebi); ADD_UNIT(pebi); ADD_UNIT(exbi); ADD_UNIT(zebi); ADD_UNIT(yobi); ADD_UNIT(sqmeter); ADD_UNIT(cbmeter); ADD_UNIT(newton); ADD_UNIT(hertz); ADD_UNIT(joule); ADD_UNIT(watt); ADD_UNIT(pascal); ADD_UNIT(coulomb); ADD_UNIT(volt); ADD_UNIT(ohm); ADD_UNIT(farad); ADD_UNIT(tesla); ADD_UNIT(weber); ADD_UNIT(henry); ADD_UNIT(siemens); ADD_UNIT(becquerel); ADD_UNIT(gray); ADD_UNIT(sievert); ADD_UNIT(katal); ADD_UNIT(steradian); ADD_UNIT(lumen); ADD_UNIT(lux); ADD_UNIT(metric_ton); ADD_UNIT(short_ton); ADD_UNIT(long_ton); ADD_UNIT(pound); ADD_UNIT(ounce); ADD_UNIT(grain); ADD_UNIT(gram); ADD_UNIT(atomic_mass_unit); ADD_UNIT(carat); ADD_UNIT(micron); ADD_UNIT(angstrom); ADD_UNIT(astronomical_unit); ADD_UNIT(lightyear); ADD_UNIT(lightsecond); ADD_UNIT(lightminute); ADD_UNIT(parsec); ADD_UNIT(inch); ADD_UNIT(foot); ADD_UNIT(yard); ADD_UNIT(mile); ADD_UNIT(rod); ADD_UNIT(furlong); ADD_UNIT(fathom); ADD_UNIT(nautical_mile); ADD_UNIT(cable); ADD_UNIT(UK_gallon); ADD_UNIT(US_gallon); ADD_UNIT_ALIAS(US_gallon, gallon_US); ADD_UNIT_ALIAS(UK_gallon, gallon_UK); ADD_UNIT_ALIAS(UK_gallon, imperial_gallon); ADD_UNIT(UK_quart); ADD_UNIT(US_quart); ADD_UNIT_ALIAS(US_quart, quart_US); ADD_UNIT_ALIAS(UK_quart, quart_UK); ADD_UNIT(UK_pint); ADD_UNIT(US_pint); ADD_UNIT_ALIAS(US_pint, pint_US); ADD_UNIT_ALIAS(UK_pint, pint_UK); ADD_UNIT(UK_fluid_ounce); ADD_UNIT(US_fluid_ounce); ADD_UNIT_ALIAS(US_fluid_ounce, fluid_ounce_US); ADD_UNIT_ALIAS(UK_fluid_ounce, fluid_ounce_UK); ADD_UNIT(liter); ADD_UNIT(minute); ADD_UNIT(hour); ADD_UNIT(day); ADD_UNIT(week); ADD_UNIT(julian_year); ADD_UNIT(tropical_year); ADD_UNIT(sidereal_year); ADD_UNIT_ALIAS(julian_year, year_julian); ADD_UNIT_ALIAS(tropical_year, year_tropical); ADD_UNIT_ALIAS(sidereal_year, year_sidereal); ADD_UNIT(percent); ADD_UNIT(ppm); ADD_UNIT(ppb); ADD_UNIT(karat); ADD_UNIT(bar); ADD_UNIT(atmosphere); ADD_UNIT(torr); ADD_UNIT(pounds_per_sqinch); ADD_UNIT(electron_volt); ADD_UNIT(calorie); ADD_UNIT(british_thermal_unit); ADD_UNIT(nat); ADD_UNIT(hartley); ADD_UNIT(byte); ADD_UNIT(tablespoon); ADD_UNIT(teaspoon); ADD_UNIT(cup); ADD_UNIT(gravity); ADD_UNIT_ALIAS(gravity, force); ADD_UNIT(speed_of_light); ADD_UNIT(speed_of_sound_STP); ADD_UNIT(elementary_charge); ADD_UNIT(knot); ADD_UNIT(horsepower); return result; } BASE_UNIT_CACHE(meter, "length") BASE_UNIT_CACHE(second, "time") BASE_UNIT_CACHE(kilogram, "mass") BASE_UNIT_CACHE(ampere, "el. current") BASE_UNIT_CACHE(mole, "amount") BASE_UNIT_CACHE(kelvin, "temperature") BASE_UNIT_CACHE(candela, "luminous intensity") BASE_UNIT_CACHE(bit, "information") UNIT_CACHE(yocto, HNumber("1e-24")) UNIT_CACHE(zepto, HNumber("1e-21")) UNIT_CACHE(atto, HNumber("1e-18")) UNIT_CACHE(femto, HNumber("1e-15")) UNIT_CACHE(pico, HNumber("1e-12")) UNIT_CACHE(nano, HNumber("1e-9")) UNIT_CACHE(micro, HNumber("1e-6")) UNIT_CACHE(milli, HNumber("1e-3")) UNIT_CACHE(centi, HNumber("1e-2")) UNIT_CACHE(deci, HNumber("1e-1")) UNIT_CACHE(deca, HNumber("1e1")) UNIT_CACHE(hecto, HNumber("1e2")) UNIT_CACHE(kilo, HNumber("1e3")) UNIT_CACHE(mega, HNumber("1e6")) UNIT_CACHE(giga, HNumber("1e9")) UNIT_CACHE(tera, HNumber("1e12")) UNIT_CACHE(peta, HNumber("1e15")) UNIT_CACHE(exa, HNumber("1e18")) UNIT_CACHE(zetta, HNumber("1e21")) UNIT_CACHE(yotta, HNumber("1e24")) UNIT_CACHE(kibi, HNumber("1024")) UNIT_CACHE(mebi, kibi()*kibi()) UNIT_CACHE(gibi, kibi()*mebi()) UNIT_CACHE(tebi, kibi()*gibi()) UNIT_CACHE(pebi, kibi()*tebi()) UNIT_CACHE(exbi, kibi()*pebi()) UNIT_CACHE(zebi, kibi()*exbi()) UNIT_CACHE(yobi, kibi()*zebi()) UNIT_CACHE(newton, meter() * kilogram() / (second()*second())) UNIT_CACHE(hertz, Quantity(1) / second()) UNIT_CACHE(pascal, newton() / sqmeter()) UNIT_CACHE(joule, newton() * meter()) UNIT_CACHE(watt, joule() / second()) UNIT_CACHE(coulomb, ampere() * second()) UNIT_CACHE(volt, watt() / ampere()) UNIT_CACHE(farad, coulomb() / volt()) UNIT_CACHE(ohm, volt() / ampere()) UNIT_CACHE(siemens, ampere() / volt()) UNIT_CACHE(weber, volt() * second()) UNIT_CACHE(tesla, weber() / sqmeter()) UNIT_CACHE(henry, weber() / ampere()) UNIT_CACHE(becquerel, Quantity(1) / second()) UNIT_CACHE(gray, joule() / kilogram()) UNIT_CACHE(sievert, joule() / kilogram()) UNIT_CACHE(katal, mole() / second()) UNIT_CACHE(steradian, 1) UNIT_CACHE(lumen, candela()*steradian()) UNIT_CACHE(lux, lumen() / sqmeter()) UNIT_CACHE(sqmeter, meter() * meter()) UNIT_CACHE(cbmeter, sqmeter() * meter()) UNIT_CACHE(metric_ton, mega()*gram()) UNIT_CACHE(gram, milli()*kilogram()) UNIT_CACHE(pound, HNumber("0.45359237") * kilogram()) UNIT_CACHE(ounce, pound() / HNumber(16)) UNIT_CACHE(grain, pound() / HNumber(7000)) UNIT_CACHE(short_ton, HNumber(2000) * pound()) UNIT_CACHE(long_ton, HNumber(2240) * pound()) UNIT_CACHE(atomic_mass_unit, HNumber("1.660539040e-27") * kilogram()) // http://physics.nist.gov/cgi-bin/cuu/Value?tukg UNIT_CACHE(carat, HNumber(200) * milli()*gram()) // Do not confuse with karat below. UNIT_CACHE(micron, micro()*meter()) UNIT_CACHE(angstrom, HNumber("1e-10") * meter()) UNIT_CACHE(astronomical_unit, HNumber("149597870700") * meter()) // IAU 2012 Resolution B2. UNIT_CACHE(lightyear, speed_of_light() * julian_year()) UNIT_CACHE(lightminute, speed_of_light() * minute()) UNIT_CACHE(lightsecond, speed_of_light() * second()) UNIT_CACHE(parsec, HNumber(648000) / HMath::pi() * astronomical_unit()) // IAU 2015 Resolution B2. UNIT_CACHE(inch, HNumber("0.0254") * meter()) // International inch. UNIT_CACHE(foot, HNumber(12) * inch()) UNIT_CACHE(yard, HNumber(36) * inch()) UNIT_CACHE(mile, HNumber(1760) * yard()) UNIT_CACHE(rod, HNumber("5.5") * yard()) UNIT_CACHE(furlong, HNumber(40) * rod()) UNIT_CACHE(fathom, HNumber(6) * foot()) UNIT_CACHE(nautical_mile, HNumber("1852") * meter()) UNIT_CACHE(cable, HNumber("0.1") * nautical_mile()) UNIT_CACHE(are, HNumber(100) * sqmeter()) UNIT_CACHE(hectare, HNumber(100) * are()) UNIT_CACHE(acre, mile()*mile() / HNumber(640)) UNIT_CACHE(US_gallon, HNumber("3.785") * liter()) UNIT_CACHE(UK_gallon, HNumber("4.54609") * liter()) UNIT_CACHE(US_quart, US_gallon() / HNumber(4)) UNIT_CACHE(UK_quart, UK_gallon() / HNumber(4)) UNIT_CACHE(US_pint, US_gallon() / HNumber(8)) UNIT_CACHE(UK_pint, UK_gallon() / HNumber(8)) UNIT_CACHE(US_fluid_ounce, US_gallon() / HNumber(128)) UNIT_CACHE(UK_fluid_ounce, UK_gallon() / HNumber(160)) UNIT_CACHE(liter, milli() * cbmeter()) UNIT_CACHE(minute, HNumber(60) * second()) UNIT_CACHE(hour, HNumber(60) * minute()) UNIT_CACHE(day, HNumber(24) * hour()) UNIT_CACHE(week, HNumber(7) * day()) UNIT_CACHE(julian_year, HNumber("365.25") * day()) UNIT_CACHE(tropical_year, HNumber("365.24219") * day()) // Approx.: changes over time due to Earth's precession. UNIT_CACHE(sidereal_year, HNumber("365.25636") * day()) // http://hpiers.obspm.fr/eop-pc/models/constants.html UNIT_CACHE(percent, HNumber("0.01")) UNIT_CACHE(ppm, HNumber("1e-6")) UNIT_CACHE(ppb, HNumber("1e-9")) UNIT_CACHE(karat, Rational(1, 24).toHNumber()) // Do not confuse with carat above. UNIT_CACHE(bar, HNumber("1e5") * pascal()) UNIT_CACHE(atmosphere, HNumber("1.01325") * bar()) UNIT_CACHE(torr, atmosphere() / HNumber(760)) UNIT_CACHE(pounds_per_sqinch, pound() * gravity() / (inch()*inch())) UNIT_CACHE(electron_volt, elementary_charge() * volt()) UNIT_CACHE(calorie, HNumber("4.1868") * joule()) // International Table calorie. UNIT_CACHE(british_thermal_unit, HNumber("1055.056") * joule()) // International standard ISO 31-4. UNIT_CACHE(nat, bit() / HMath::ln(2)) UNIT_CACHE(hartley, HMath::ln(10) * nat()) UNIT_CACHE(byte, HNumber(8) * bit()) UNIT_CACHE(tablespoon, HNumber(15) * milli()*liter()) UNIT_CACHE(teaspoon, HNumber(5) * milli()*liter()) UNIT_CACHE(cup, HNumber(240) * milli()*liter()) UNIT_CACHE(gravity, HNumber("9.80665") * newton() / kilogram()) // 3rd CGPM (1901, CR 70). UNIT_CACHE(speed_of_light, HNumber(299792458) * meter() / second()) UNIT_CACHE(elementary_charge, HNumber("1.6021766208e-19") * coulomb()) // http://physics.nist.gov/cgi-bin/cuu/Value?e UNIT_CACHE(speed_of_sound_STP, HNumber(331) * meter() / second()) UNIT_CACHE(knot, nautical_mile() / hour()) UNIT_CACHE(horsepower, HNumber(550) * foot() * pound() * gravity() / second()) // Imperial horsepower. deepin-calculator-5.7.21/3rdparty/math/units.h000066400000000000000000000153011423020056600212130ustar00rootroot00000000000000// This file is part of the SpeedCrunch project // Copyright (C) 2015 Pol Welter // Copyright (C) 2016 @heldercorreia // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; see the file COPYING. If not, write to // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. #ifndef UNITS_H #define UNITS_H #include #include #include "quantity.h" class Rational; struct Unit { QString name; Quantity value; Unit(QString name, Quantity value) : name(name) , value(value) { } Unit() : name("") , value(1) { } }; class Units { static void pushUnit(Quantity q, QString name); static QHash, Unit> m_matchLookup; static QMap m_cache; static void initTable(); public: static void findUnit(Quantity &q); static void clearCache() { m_cache.clear(); } static const QList getList(); // Base SI units. static const Quantity meter(); static const Quantity second(); static const Quantity kilogram(); static const Quantity ampere(); static const Quantity mole(); static const Quantity kelvin(); static const Quantity candela(); // Base non-SI units. static const Quantity bit(); // SI prefixes. static const Quantity yocto(); static const Quantity zepto(); static const Quantity atto(); static const Quantity femto(); static const Quantity pico(); static const Quantity nano(); static const Quantity micro(); static const Quantity milli(); static const Quantity centi(); static const Quantity deci(); static const Quantity deca(); static const Quantity hecto(); static const Quantity kilo(); static const Quantity mega(); static const Quantity giga(); static const Quantity tera(); static const Quantity peta(); static const Quantity exa(); static const Quantity zetta(); static const Quantity yotta(); // Binary prefixes. static const Quantity kibi(); static const Quantity mebi(); static const Quantity gibi(); static const Quantity tebi(); static const Quantity pebi(); static const Quantity exbi(); static const Quantity zebi(); static const Quantity yobi(); // Derived SI units. static const Quantity sqmeter(); static const Quantity cbmeter(); static const Quantity newton(); static const Quantity hertz(); static const Quantity steradian(); static const Quantity pascal(); static const Quantity joule(); static const Quantity watt(); static const Quantity coulomb(); static const Quantity volt(); static const Quantity farad(); static const Quantity ohm(); static const Quantity siemens(); static const Quantity weber(); static const Quantity tesla(); static const Quantity henry(); static const Quantity lumen(); static const Quantity lux(); static const Quantity becquerel(); static const Quantity gray(); static const Quantity sievert(); static const Quantity katal(); // Derived from SI units. // Mass. static const Quantity metric_ton(); static const Quantity short_ton(); static const Quantity long_ton(); static const Quantity pound(); static const Quantity ounce(); static const Quantity grain(); static const Quantity gram(); static const Quantity atomic_mass_unit(); static const Quantity carat(); // Distance/length. static const Quantity micron(); static const Quantity angstrom(); static const Quantity astronomical_unit(); static const Quantity lightyear(); static const Quantity lightsecond(); static const Quantity lightminute(); static const Quantity parsec(); // US measures. static const Quantity inch(); static const Quantity foot(); static const Quantity yard(); static const Quantity mile(); static const Quantity rod(); static const Quantity furlong(); // Nautical (US). static const Quantity fathom(); static const Quantity nautical_mile(); static const Quantity cable(); // Area. static const Quantity are(); static const Quantity hectare(); static const Quantity acre(); // Volume. static const Quantity US_gallon(); static const Quantity UK_gallon(); static const Quantity US_quart(); static const Quantity UK_quart(); static const Quantity US_pint(); static const Quantity UK_pint(); static const Quantity US_fluid_ounce(); static const Quantity UK_fluid_ounce(); static const Quantity liter(); // Time. static const Quantity minute(); static const Quantity hour(); static const Quantity day(); static const Quantity week(); static const Quantity julian_year(); static const Quantity tropical_year(); static const Quantity sidereal_year(); // Concentration. static const Quantity percent(); static const Quantity ppm(); static const Quantity ppb(); static const Quantity karat(); // Pressure. static const Quantity bar(); static const Quantity atmosphere(); static const Quantity torr(); static const Quantity pounds_per_sqinch(); // Energy. static const Quantity electron_volt(); static const Quantity calorie(); static const Quantity british_thermal_unit(); // Information. static const Quantity nat(); static const Quantity hartley(); static const Quantity byte(); // Cooking. // Note: these again differ from US to UK, Australia, Japan, ... // Since for cooking generally not that high a precision is // required, let's just stick with the so called 'legal' variant. static const Quantity tablespoon(); static const Quantity teaspoon(); static const Quantity cup(); // Various others. // TODO: Some of these are constants that should be moved once constants are also accessible via builtin names. static const Quantity gravity(); static const Quantity speed_of_light(); static const Quantity elementary_charge(); static const Quantity speed_of_sound_STP(); static const Quantity knot(); static const Quantity horsepower(); }; #endif // UNITS_H deepin-calculator-5.7.21/CHANGELOG.md000066400000000000000000000142011423020056600170060ustar00rootroot00000000000000 ## 1.0.11 (2019-04-10) #### Bug Fixes * don't reply on fonts to show operators ([febdea24](https://github.com/linuxdeepin/deepin-calculator/commit/febdea245564c6164b69663c03669574858967ac)) ## 1.0.10 (2018-11-23) #### Features * **desktop:** add generic name. ([b6fd37af](https://github.com/linuxdeepin/deepin-calculator/commit/b6fd37af5dc071494dada9a635c316373c7b3f67)) 1.0.9 ## 1.0.9 (2018-11-09) #### Bug Fixes * **titlebar:** use default height value. ([ae254997](https://github.com/linuxdeepin/deepin-calculator/commit/ae254997049d83cb1638c1634bb1adfc627d5b83)) 1.0.8 ## 1.0.8 (2018-10-25) #### Features * press Ctrl+C to copy result. ([440cd132](https://github.com/linuxdeepin/deepin-calculator/commit/440cd1322d3bca1d4ee2df3aa860679ae3af3411)) ### 1.0.7 (2018-08-12) +#### Features * expression bar shows tooltip. ([2821e409](https://github.com/linuxdeepin/deepin-calculator/commit/2821e40949e3d73be8dbd325d0690546870e74db)) #### Bug Fixes * incorrect calculation in some language environments. ([2a3cd90e](https://github.com/linuxdeepin/deepin-calculator/commit/2a3cd90e1e82b821799a7391582d49dc1717952d)) ### 1.0.5 (2018-07-31) #### Bug Fixes * not set application name ([154bb923](https://github.com/linuxdeepin/deepin-calculator/commit/154bb923d6ec282a2ec0659759042e3221ab305d)) #### Features * set window title ([86aa9097](https://github.com/linuxdeepin/deepin-calculator/commit/86aa9097db5655ead4b1ab06733638dcc55f7118)) ## 1.0.4 (2018-06-12) * Update translations. ## 1.0.3 (2018-05-14) #### Bug Fixes * some env garbled ([146bea9e](https://github.com/linuxdeepin/deepin-calculator/commit/146bea9ecd30b8904df4d591780f4ac2539ae745)) * move to center ([01285734](https://github.com/linuxdeepin/deepin-calculator/commit/01285734c53741d74dad2bf434549dc593b15bdf)) * move to center ([81fa2c08](https://github.com/linuxdeepin/deepin-calculator/commit/81fa2c08f11d2599aa35ba654d430a4a571b952f)) #### Features * support for 0^(1+j). ([62fba07e](https://github.com/linuxdeepin/deepin-calculator/commit/62fba07eb595f2a20a90abc61615fd370d7dd34f)) * add scrollbar. ([76a1cdd2](https://github.com/linuxdeepin/deepin-calculator/commit/76a1cdd2e318bae48e9d746b08b4658a2917fbc8)) ## 1.0.1 (2017-12-07) #### Features * use fixed fonts for listview. ([aefea6e0](https://github.com/linuxdeepin/deepin-calculator/commit/aefea6e028caf7e1c113a7271eac1a4cd32e4cb5)) #### Bug Fixes * precision of the previous answer. ([81ff49a5](https://github.com/linuxdeepin/deepin-calculator/commit/81ff49a5481f8d2f84d02064e19c8d38cbfb9598)) ## 1.0.0 (2017-11-30) #### Bug Fixes * listview color. ([744a92a5](https://github.com/linuxdeepin/deepin-calculator/commit/744a92a5fcb0fd146785ddfd84f1a42a219f5389)) * history text pos. ([dbf187ad](https://github.com/linuxdeepin/deepin-calculator/commit/dbf187ada81094afb8c44b1eeb039d0f8bcf8225)) * mult dot not error. ([31636fc7](https://github.com/linuxdeepin/deepin-calculator/commit/31636fc754643cd70d993e66abdfbf8f21cd8fcc)) * inputEdit position ([9e14a700](https://github.com/linuxdeepin/deepin-calculator/commit/9e14a7008440cdf3e008e5dc4f7f76e288a19b72)) * inputEdit cursor position. ([abf3bbb5](https://github.com/linuxdeepin/deepin-calculator/commit/abf3bbb55cc54e4f3c55aa499550c06cf8538708)) * **background:** repeated rendering of background color ([80e5de0d](https://github.com/linuxdeepin/deepin-calculator/commit/80e5de0d19d44f1af10822ed92e132d1f250c6ba)) * **config:** parameter error ([e5e02e73](https://github.com/linuxdeepin/deepin-calculator/commit/e5e02e733d88f484a1ffc4aed649f13c228b056c)) * **inputEdit:** paired brackets. ([ecee0a7a](https://github.com/linuxdeepin/deepin-calculator/commit/ecee0a7aaa96d3346a9786c29c50a90e2a95bbbc)) * **title:** use correct icon ([9ee9c185](https://github.com/linuxdeepin/deepin-calculator/commit/9ee9c1850cd2259d60948c415d1f7016daf7300c)) #### Features * modify width for listview. ([f4750541](https://github.com/linuxdeepin/deepin-calculator/commit/f4750541a2e3336ae23ef8e807769747d3f8828c)) * double select ([79cd8bf8](https://github.com/linuxdeepin/deepin-calculator/commit/79cd8bf88fff0978a5db69efe0483b662c7d6f2f)) * add error font color && upgrade help manual. ([040f338c](https://github.com/linuxdeepin/deepin-calculator/commit/040f338ca9da1557c548eb0172753bf11bd299a0)) * modify max value of point. ([9bcbec91](https://github.com/linuxdeepin/deepin-calculator/commit/9bcbec9188e3c02bb8b945d28eb13767aaf9ca2e)) * add thousands separators. ([ead7ec78](https://github.com/linuxdeepin/deepin-calculator/commit/ead7ec7885a7f116d4a07d3b71fcfbbad7587c2e)) * press mult sign twice trigger pow. ([6e8327f0](https://github.com/linuxdeepin/deepin-calculator/commit/6e8327f085e7b988e15d6c173495e2d87a0abfa6)) * optimize editor. ([c414f2ff](https://github.com/linuxdeepin/deepin-calculator/commit/c414f2ffe7dfcbe81e7ae130cac6a91fa3bfd572)) * add help manual. ([0a85e03a](https://github.com/linuxdeepin/deepin-calculator/commit/0a85e03a148220db69195b839a7670099fc4785a)) * add thousands separators func. ([0c8549d4](https://github.com/linuxdeepin/deepin-calculator/commit/0c8549d4503aea902de6c458fb79b0bee50f843e)) * add icon install. ([27d3ae91](https://github.com/linuxdeepin/deepin-calculator/commit/27d3ae91b3d128e754f9c7140f9a401b0ff6249d)) * add service file. ([5c808d89](https://github.com/linuxdeepin/deepin-calculator/commit/5c808d89d30ccc3f90ea584b2dd0333a079a243a)) * make font size of edit fit text content. ([c4810e41](https://github.com/linuxdeepin/deepin-calculator/commit/c4810e41707da3ff36078a1640645065645212c2)) * **algorithm:** support percent sign(%) symbolic operation. ([6b714cfc](https://github.com/linuxdeepin/deepin-calculator/commit/6b714cfc00e7f62235a3b8813d469ade71ed4c9a)) * **mainwindow:** * optimize slots. ([3e971c08](https://github.com/linuxdeepin/deepin-calculator/commit/3e971c0894904ace52b4f8e2c1562961f276c309)) * use QSignalMapper ([01dc666f](https://github.com/linuxdeepin/deepin-calculator/commit/01dc666fde6c85667a6ad11eeb85ade1b79a68e8)) deepin-calculator-5.7.21/CMakeLists.txt000066400000000000000000000113341423020056600177410ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.9.5) if (NOT DEFINED VERSION) set(VERSION 1.2.2) endif () #最外层一个工程,单项目中不添加工程,只添加执行文件 project(deepin-calculator) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) set(CMAKE_CXX_STANDARD 11) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wl,--as-needed -fPIE") set(QT_MINIMUM_VERSION "5.7.1") set(CMAKE_EXE_LINKER_FLAGS "-pie") #add_definitions(-DQT_NO_DEBUG_OUTPUT) if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "sw_64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mieee") endif () if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips64") message(STATUS "this system is mips64=========") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -ftree-vectorize -march=loongson3a -mhard-float -mno-micromips -mno-mips16 -flax-vector-conversions -mloongson-ext2 -mloongson-mmi -Wl,--as-needed") endif() if (NOT (${CMAKE_BUILD_TYPE} MATCHES "Debug")) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") execute_process(COMMAND bash "${CMAKE_CURRENT_LIST_DIR}/translate_generation.sh" WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/) endif () set(CMAKE_SAFETYTEST "${CMAKE_SAFETYTEST_ARG}") if(CMAKE_SAFETYTEST STREQUAL "") set(CMAKE_SAFETYTEST "CMAKE_SAFETYTEST_ARG_OFF") endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${CMAKE_SAFETYTEST}") if(CMAKE_SAFETYTEST STREQUAL "CMAKE_SAFETYTEST_ARG_ON") #安全测试选项 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=undefined,address -O2") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=undefined,address -O2") endif() configure_file(src/environments.h.in environments.h @ONLY) # Find the library find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) find_package(Qt5Core REQUIRED) find_package(Qt5Gui REQUIRED) find_package(Qt5DBus REQUIRED) find_package(Qt5Xml REQUIRED) find_package(Qt5Svg REQUIRED) find_package(Qt5Test REQUIRED) find_package(DtkWidget REQUIRED dtkwidget) find_package(DtkGui REQUIRED dtkgui) find_package(DtkCore REQUIRED dtkcore) #find_package(DFrameworkDbus REQUIRED dframeworkdbus) pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) include_directories(${DtkWidget_INCLUDE_DIRS}) include_directories(${DtkGui_INCLUDE_DIRS}) include_directories(${DtkCore_INCLUDE_DIRS}) set (EXE_NAME deepin-calculator) set(LINK_LIBS Qt5::Core Qt5::DBus Qt5::Widgets Qt5::Xml Qt5::Svg Qt5::Test ${DtkWidget_LIBRARIES} ${DtkCore_LIBRARIES} ${DtkGUI_LIBRARIES} ${DFrameworkDBus_LIBRARIES} ) file(GLOB_RECURSE CAL_SRCH ${CMAKE_CURRENT_LIST_DIR}/src/*.h) file(GLOB_RECURSE CAL_SRCC ${CMAKE_CURRENT_LIST_DIR}/src/*.c) file(GLOB_RECURSE CAL_SRCCPP ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp) file(GLOB_RECURSE CAL_3rdH ${CMAKE_CURRENT_LIST_DIR}/3rdparty/*.h) file(GLOB_RECURSE CAL_3rdC ${CMAKE_CURRENT_LIST_DIR}/3rdparty/*.c) file(GLOB_RECURSE CAL_3rdCPP ${CMAKE_CURRENT_LIST_DIR}/3rdparty/*.cpp) set (DC_QRC_FILES src/deepin-calculator.qrc ) add_executable (${EXE_NAME} ${CAL_SRCH} ${CAL_SRCC} ${CAL_SRCCPP} ${CAL_3rdH} ${CAL_3rdC} ${CAL_3rdCPP} ${DC_QRC_FILES} ) target_include_directories(${EXE_NAME} PUBLIC ${Qt5Widgets_LIBRARIES} ${Qt5DBus_LIBRARIES} ${Qt5TestLib_LIBRARIES} ${PROJECT_BINARY_DIR} ${DtkWidget_INCLUDE_DIRS} ${DtkCore_LIBRARIES} ${DtkGUI_INCLUDE_DIRS} ${DFrameworkDBus_INCLUDE_DIRS}) target_link_libraries (${EXE_NAME} ${LINK_LIBS}) set(CMAKE_INSTALL_PREFIX /usr) install(TARGETS deepin-calculator DESTINATION bin) file(GLOB QM_FILES "${CMAKE_CURRENT_LIST_DIR}/translations/*.qm") install(FILES ${QM_FILES} DESTINATION share/deepin-calculator/translations) install(FILES ${CMAKE_CURRENT_LIST_DIR}/deepin-calculator.desktop DESTINATION share/applications/) install(FILES ${CMAKE_CURRENT_LIST_DIR}/src/assets/images/deepin-calculator.svg DESTINATION share/icons/hicolor/scalable/apps/) install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/src/assets/deepin-calculator DESTINATION /usr/share/deepin-manual/manual-assets/application/) #if (NOT ${CMAKE_SYSTEM_PROCESSOR} MATCHES "loongarch64") add_subdirectory(tests) #tests为ut测试文件夹名 #endif () #代码覆盖率开关 if(CMAKE_COVERAGE_ARG STREQUAL "CMAKE_COVERAGE_ARG_ON") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -Wall -fprofile-arcs -ftest-coverage") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -fprofile-arcs -ftest-coverage") endif() deepin-calculator-5.7.21/LICENSE000066400000000000000000001045051423020056600162110ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . deepin-calculator-5.7.21/README.md000066400000000000000000000017001423020056600164540ustar00rootroot00000000000000# Deepin Calculator Deepin calculator is an easy to use calculator for ordinary users. ## Dependencies * sudo apt install libdtkwidget-dev libqt5svg5-dev qttools5-dev-tools ## Installation * mkdir build * cd build * qmake .. * make ## Usage * ./deepin-calculator ## Getting help Any usage issues can ask for help via * [Gitter](https://gitter.im/orgs/linuxdeepin/rooms) * [IRC channel](https://webchat.freenode.net/?channels=deepin) * [Forum](https://bbs.deepin.org) * [WiKi](https://wiki.deepin.org/) ## Getting involved We encourage you to report issues and contribute changes * [Contribution guide for developers](https://github.com/linuxdeepin/developer-center/wiki/Contribution-Guidelines-for-Developers-en). (English) * [开发者代码贡献指南](https://github.com/linuxdeepin/developer-center/wiki/Contribution-Guidelines-for-Developers) (中文) ## License Deepin Calculator is licensed under [GPLv3](LICENSE) or any later version. deepin-calculator-5.7.21/com.deepin.Calculator.service000066400000000000000000000001121423020056600226640ustar00rootroot00000000000000[D-BUS Service] Name=com.deepin.Calculator Exec=/usr/bin/deepin-calculatordeepin-calculator-5.7.21/debian/000077500000000000000000000000001423020056600164215ustar00rootroot00000000000000deepin-calculator-5.7.21/debian/changelog000066400000000000000000000002351423020056600202730ustar00rootroot00000000000000deepin-calculator (0.1-1) unstable; urgency=medium * Initial Release. -- Deepin Packages Builder Wed, 11 Oct 2017 17:38:35 +0800 deepin-calculator-5.7.21/debian/compat000066400000000000000000000000021423020056600176170ustar00rootroot000000000000009 deepin-calculator-5.7.21/debian/control000066400000000000000000000013021423020056600200200ustar00rootroot00000000000000Source: deepin-calculator Section: utils Priority: optional Maintainer: Deepin Packages Builder Build-Depends: debhelper (>= 9),cmake ,pkg-config, libdtkgui-dev, libdtkwidget-dev, libqt5svg5-dev, qttools5-dev-tools, libdframeworkdbus-dev, libgtest-dev, libgmock-dev Standards-Version: 3.9.8 Homepage: http://www.deepin.org Package: deepin-calculator Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Calculator for UOS Calculator is a simple and easy-to-use desktop calculator. It supports addition, subtraction, multiplication and division with keyboard input perfectly matched, as well as symbolic fault-tolerant computing and calculation result linkage. deepin-calculator-5.7.21/debian/copyright000066400000000000000000000044511423020056600203600ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: deepin-calculator Files: * Copyright: 2017-2018 Deepin Technology Co., Ltd. 2019-2021 Uniontech Software Technology Co.,Ltd. License: GPL-3+ Files: 3rdparty/* Copyright: 2007-2009 Wolf Lammen 2007-2016 @heldercorreia 1991-2000 Free Software Foundation, Inc. 2015-2016 Pol Welter 2013-2016 Hadrien Theveneau 2004 Ariya Hidayat 2004-2008 Ariya Hidayat 2005-2006 Johan Thelin 2014 Tey License: GPL-2+ License: GPL-2+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this package; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA . On Debian systems, the full text of the GNU General Public License version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. License: GPL-3+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . On Debian systems, the complete text of the GNU General Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". deepin-calculator-5.7.21/debian/deepin-calculator.1000066400000000000000000000025441423020056600221030ustar00rootroot00000000000000.\" Hey, EMACS: -*- nroff -*- .\" (C) Copyright 2021 hufeng , .\" .TH "deepin-calculator" "1" "2021-3-11" "Deepin" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME deepin-calculator \- calculator for deepin. .SH SYNOPSIS deepin-calculator [OPTIONS...] .SH DESCRIPTION Calculator for UOS. .PP Calculator is a simple and easy-to-use desktop calculator. It supports addition, subtraction, multiplication and division with keyboard input perfectly matched, as well as symbolic fault-tolerant computing and calculation result linkage. .SH OPTIONS .PP Note: command .PP -h, --help Displays this help. .PP -v, --version Displays version information. .SH SEE ALSO https://github.com/linuxdeepin/deepin-calculator .SH AUTHOR .PP .B deepin-calculator is written by Deepin Technology Co., Ltd. .PP This manual page was written by .MT jingzhou@\:uniontech.com Jing Zhou .ME for the Debian Project (but may be used by others) deepin-calculator-5.7.21/debian/manpages000066400000000000000000000000331423020056600201330ustar00rootroot00000000000000debian/deepin-calculator.1 deepin-calculator-5.7.21/debian/rules000077500000000000000000000011051423020056600174760ustar00rootroot00000000000000#!/usr/bin/make -f export QT_SELECT=5 include /usr/share/dpkg/default.mk DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH) DH_AUTO_ARGS = --parallel --buildsystem=cmake export DEB_BUILD_MAINT_OPTIONS = hardening=+all # Uncomment this to turn on verbose mode. export DH_VERBOSE=1 %: dh $@ --parallel override_dh_auto_configure: dh_auto_configure -- \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_SAFETYTEST_ARG="CMAKE_SAFETYTEST_ARG_OFF" \ -DAPP_VERSION=$(DEB_VERSION_UPSTREAM) -DVERSION=$(DEB_VERSION_UPSTREAM) LIB_INSTALL_DIR=/usr/lib/$(DEB_HOST_MULTIARCH) deepin-calculator-5.7.21/debian/source/000077500000000000000000000000001423020056600177215ustar00rootroot00000000000000deepin-calculator-5.7.21/debian/source/format000066400000000000000000000000151423020056600211300ustar00rootroot000000000000003.0 (native) deepin-calculator-5.7.21/deepin-calculator.desktop000066400000000000000000000121421423020056600221650ustar00rootroot00000000000000[Desktop Entry] Categories=Utility;Calculator; Comment=Calculator Exec=deepin-calculator GenericName=Calculator Icon=deepin-calculator Keywords=calculator;scientific;maths;numbers;deepin;dde; Name=Deepin Calculator StartupNotify=true TryExec=deepin-calculator Type=Application X-Deepin-ManualID=deepin-calculator X-Deepin-Vendor=deepin # Translations: # Do not manually modify! Comment[am_ET]=ማስሊያ Comment[ar]=الحاسبة Comment[ast]=Calculadora Comment[az]=Hesablayıcı Comment[bg]=Калкулатор Comment[bn]=ক্যালকুলেটর Comment[bo]=རྩིས་ཆས། Comment[br]=Jederezig Comment[ca]=Calculadora Comment[cs]=Kalkulačka Comment[da]=Lommeregner Comment[de]=Taschenrechner Comment[el]=Αριθμομηχανή Comment[en_AU]=Calculator Comment[es]=Calculadora Comment[et]=Kalkulaator Comment[fa]=ماشین حساب Comment[fi]=Laskin Comment[fr]=Calculatrice Comment[gl_ES]=Calculadora Comment[hi_IN]=गणक Comment[hr]=Kalkulator Comment[hu]=Számológép Comment[id]=Kalkulator Comment[it]=Calcolatrice Comment[km_KH]=ម៉ាស៊ីនគិតលេខ Comment[ko]=계산기 Comment[ku_IQ]=ژمێرەر Comment[ky]=эсептегич Comment[lt]=Skaičiuotuvas Comment[mn]=Тооцоолуур Comment[ms]=Kalkulator Comment[ne]=क्याल्कुलेटर Comment[nl]=Rekenmachine Comment[pl]=Kalkulator Comment[pt]=Calculadora Comment[pt_BR]=Calculadora Comment[ro]=Calculator Comment[ru]=Калькулятор Comment[sk]=Kalkulačka Comment[sl]=Kalkulator Comment[sq]=Llogaritës Comment[sr]=Калкулатор Comment[sv]=Kalkylator Comment[tr]=Hesap Makinesi Comment[tzm]=Tamessiḍent Comment[ug]=ھېسابلىغۇچ Comment[uk]=Калькулятор Comment[vi]=Máy tính Comment[zh_CN]=计算器 Comment[zh_HK]=計數機 Comment[zh_TW]=計算器 GenericName[am_ET]=ማስሊያ GenericName[ar]=الحاسبة GenericName[ast]=Calculadora GenericName[az]=Hesablayıcı GenericName[bg]=Калкулатор GenericName[bn]=ক্যালকুলেটর GenericName[bo]=རྩིས་ཆས། GenericName[br]=Jederezig GenericName[ca]=Calculadora GenericName[cs]=Kalkulačka GenericName[da]=Lommeregner GenericName[de]=Taschenrechner GenericName[el]=Αριθμομηχανή GenericName[en_AU]=Calculator GenericName[es]=Calculadora GenericName[et]=Kalkulaator GenericName[fa]=ماشین حساب GenericName[fi]=Laskin GenericName[fr]=Calculatrice GenericName[gl_ES]=Calculadora GenericName[hi_IN]=गणक GenericName[hr]=Kalkulator GenericName[hu]=Számológép GenericName[id]=Kalkulator GenericName[it]=Calcolatrice GenericName[km_KH]=ម៉ាស៊ីនគិតលេខ GenericName[ko]=계산기 GenericName[ku_IQ]=ژمێرەر GenericName[ky]=эсептегич GenericName[lt]=Skaičiuotuvas GenericName[mn]=Тооцоолуур GenericName[ms]=Kalkulator GenericName[ne]=क्याल्कुलेटर GenericName[nl]=Rekenmachine GenericName[pl]=Kalkulator GenericName[pt]=Calculadora GenericName[pt_BR]=Calculadora GenericName[ro]=Calculator GenericName[ru]=Калькулятор GenericName[sk]=Kalkulačka GenericName[sl]=Kalkulator GenericName[sq]=Llogaritës GenericName[sr]=Калкулатор GenericName[sv]=Kalkylator GenericName[tr]=Hesap Makinesi GenericName[tzm]=Tamessiḍent GenericName[ug]=ھېسابلىغۇچ GenericName[uk]=Калькулятор GenericName[vi]=Máy tính GenericName[zh_CN]=计算器 GenericName[zh_HK]=計數機 GenericName[zh_TW]=計算器 Name[am_ET]=ዲፕኢን ማስሊያ Name[ar]=حاسبة ديبين Name[ast]=Deepin Calculator Name[az]=Deepin Hesablayıcı Name[bg]=Deepin Калкулатор Name[bn]=ডিপিন ক্যালকুলেটর Name[bo]=གཏིང་ཟབ་རྩིས་ཆས། Name[br]=Jederezig Deepin Name[ca]=Calculadora del Deepin Name[cs]=Kalkulačka Name[da]=Deepin lommeregner Name[de]=Deepin Taschenrechner Name[el]=Αριθμομηχανή Deepin Name[en_AU]=Deepin Calculator Name[es]=Calculadora Name[et]=Deepin kalkulaator Name[fa]=ماشین حساب دیپین Name[fi]=Deepin Laskin Name[fr]=Calculatrice Deepin Name[gl_ES]=Deepin Calculadora Name[hi_IN]=दीपिन गणक Name[hr]=Deepin kalkulator Name[hu]=Deepin® Számológép Name[id]=Kalkulator Deepin Name[it]=Calcolatrice di Deepin Name[km_KH]=ម៉ាស៊ីនគិតលេខ Deepin Name[ko]=Deepin 계산기 Name[ku_IQ]=ژمێرەری Deepin Name[ky]=Deepin эсептегич Name[lt]=Deepin skaičiuotuvas Name[mn]=Дээпин тооцоолуур Name[ms]=Kalkulator Deepin Name[ne]=डिपिन क्याल्कुलेटर Name[nl]=Deepin Rekenmachine Name[pl]=Kalkulator Deepin Name[pt]=Calculadora do Deepin Name[pt_BR]=deepin Calculadora Name[ro]=Calculatorul Deepin Name[ru]=Калькулятор Deepin Name[sk]=Deepin Kalkulačka Name[sl]=Deepin kalkulator Name[sq]=Llogaritës Deepin Name[sr]=Дипин Калкулатор Name[sv]=Deepin Kalkylator Name[tr]=Deepin Hesap Makinesi Name[tzm]=Tamessiḍent Deepin Name[ug]=Deepin ھېسابلىغۇچى Name[uk]=Калькулятор Deepin Name[vi]=Máy tính Deepin Name[zh_CN]=深度计算器 Name[zh_HK]=Deepin 計數機 Name[zh_TW]=Deepin 計算器 deepin-calculator-5.7.21/rpm/000077500000000000000000000000001423020056600157755ustar00rootroot00000000000000deepin-calculator-5.7.21/rpm/deepin-calculator.spec000066400000000000000000000041701423020056600222460ustar00rootroot00000000000000%define pkgrelease 1 %if 0%{?openeuler} %define specrelease %{pkgrelease} %else ## allow specrelease to have configurable %%{?dist} tag in other distribution %define specrelease %{pkgrelease}%{?dist} %endif Name: deepin-calculator Version: 5.7.1.1 Release: %{specrelease} Summary: An easy to use calculator for ordinary users License: GPLv3+ URL: https://github.com/linuxdeepin/%{name} Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz BuildRequires: gcc-c++ BuildRequires: cmake3 BuildRequires: qt5-linguist BuildRequires: qt5-devel BuildRequires: pkgconfig(dtkcore) BuildRequires: pkgconfig(dtkwidget) BuildRequires: pkgconfig(dtkgui) BuildRequires: pkgconfig(dframeworkdbus) # BuildRequires: pkgconfig(Qt5Widgets) # BuildRequires: pkgconfig(Qt5Core) # BuildRequires: pkgconfig(Qt5Gui) # BuildRequires: pkgconfig(Qt5DBus) # BuildRequires: pkgconfig(Qt5Xml) # BuildRequires: pkgconfig(Qt5Svg) BuildRequires: gtest-devel BuildRequires: gmock-devel Requires: qt5-qtbase Requires: qt5-qtbase-gui Requires: qt5-qtsvg Requires: dde-qt-dbus-factory Requires: dtkcore Requires: dtkgui Requires: dtkwidget %description %{summary}. %prep %autosetup %build # help find (and prefer) qt5 utilities, e.g. qmake, lrelease export PATH=%{_qt5_bindir}:$PATH # cmake_minimum_required version is too high sed -i "s|^cmake_minimum_required.*|cmake_minimum_required(VERSION 3.0)|" $(find . -name "CMakeLists.txt") mkdir build pushd build %cmake ../ -DCMAKE_BUILD_TYPE=Release \-DAPP_VERSION=%{version} -DVERSION=%{version} %make_build popd %install # pushd build # %make_install # popd %make_install -C build INSTALL_ROOT="%buildroot" %files %doc README.md %license LICENSE %{_bindir}/%{name} %{_datadir}/%{name}/translations/*.qm %{_datadir}/icons/hicolor/scalable/apps/%{name}.svg %{_datadir}/applications/%{name}.desktop %{_datadir}/deepin-manual/manual-assets/application/deepin-calculator/calculator/* %changelog * Mon Apr 19 2021 zhangdingwen - 5.7.1.1-1 - init spec for euler * Thu Aug 13 2020 guoqinglan - 5.5.27-1 - Update to 5.5.27 deepin-calculator-5.7.21/src/000077500000000000000000000000001423020056600157665ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/000077500000000000000000000000001423020056600172705ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/deepin-calculator/000077500000000000000000000000001423020056600226635ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/000077500000000000000000000000001423020056600250145ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/000077500000000000000000000000001423020056600263045ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/2nd.svg000066400000000000000000000034651423020056600275200ustar00rootroot00000000000000 编组 11 2 deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/F-E.svg000066400000000000000000000013331423020056600273740ustar00rootroot00000000000000 F-E F-E deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/M+.svg000066400000000000000000000023601423020056600272750ustar00rootroot00000000000000 编组 8 M+ deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/M-.svg000066400000000000000000000023601423020056600272770ustar00rootroot00000000000000 编组 9 M- deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/M.png000066400000000000000000000062241423020056600272120ustar00rootroot00000000000000PNG  IHDRA pHYs+ MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxKq_/ ԃ%(EAQBHPX?Ɛasyv'/QC @ [.F*(^<(xp$#-~{:W z}|~O&>a@̼X>_Ex(*""?$""aI4OtE,1788(xdL'%"e,$\ZS|D׮Ԓ!>3gWXX\s;xG|݊?1z0̓VT1J&;/I zEQ=R~&K۽&.UVDj}v{sִWN:TQ(L2xj'f6"1w;=;np6ïF-M_WsUU7؀Ws*J,OUy\ӇIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/MC.svg000066400000000000000000000023031423020056600273220ustar00rootroot00000000000000 编组 6 MC deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/MH.svg000066400000000000000000000040131423020056600273270ustar00rootroot00000000000000 编组 15 / H M ^ deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/MR.svg000066400000000000000000000023561423020056600273510ustar00rootroot00000000000000 编组 7 MR deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/MS.svg000066400000000000000000000023621423020056600273470ustar00rootroot00000000000000 编组 10 MS deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/M^.svg000066400000000000000000000027411423020056600273630ustar00rootroot00000000000000 编组 11 M ^ deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/arithmetic.svg000066400000000000000000000037471423020056600311710ustar00rootroot00000000000000 icon_as_normal deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/back.svg000066400000000000000000000021441423020056600277260ustar00rootroot00000000000000 icon_generalkeyboard_press deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/bit.svg000066400000000000000000000021141423020056600276010ustar00rootroot00000000000000 icon_binarysystem_normal deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/circular.svg000066400000000000000000000062341423020056600306360ustar00rootroot00000000000000 icon_ro_normal deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/deepin-calculator.svg000066400000000000000000000043251423020056600324240ustar00rootroot00000000000000 deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/deepin_launcher.svg000066400000000000000000000076341423020056600321640ustar00rootroot00000000000000 deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/delete.svg000066400000000000000000000044241423020056600302730ustar00rootroot00000000000000 image/svg+xml deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/icon_menu.svg000066400000000000000000000047771423020056600310200ustar00rootroot00000000000000 image/svg+xml img_upload img_upload Created with Sketch. deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/logical.svg000066400000000000000000000034501423020056600304410ustar00rootroot00000000000000 icon_ls_normal deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/notes.svg000066400000000000000000000031531423020056600301570ustar00rootroot00000000000000 notes deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/rotate.svg000066400000000000000000000074741423020056600303370ustar00rootroot00000000000000 icon_rc_normal deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/common/tips.svg000066400000000000000000000030731423020056600300070ustar00rootroot00000000000000 tips deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/000077500000000000000000000000001423020056600260255ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/calculator.md000066400000000000000000000322321423020056600305020ustar00rootroot00000000000000# Calculator|deepin-calculator| ## Overview Calculator is a simple and easy-to-use desktop calculator. It supports standard mode, scientific mode and programmer mode, with keyboard input perfectly matched, as well as symbolic fault-tolerant computing and calculation result linkage. ## Modes Click ![icon_menu](../common/icon_menu.svg) > **Mode** to: - Select **Standard** to perform the four fundamental operations of arithmetic; - Select **Scientific** to perform high-level operations such as function, exponent, root, and so on. - Select **Programmer** to perform binary, octal, decimal, hexadecimal and other complex operations. ### Standard Mode ​ ![0|calculator](fig/standard_mode.png) | Icon | Name | Description | | ------------------------------- | :-------------------------------------------------- | ------------------------------------------------------------ | | 0~9 | Number Key | Basic Arabic numerals | | MC | Clear Key | Clear all memories | | MR | Storage Key | Memory recall | | M+ | Storage Key | Memory add; click it to add the current number accumulatively to the memory and interrupt digital input. | | M- | Storage Key | Memory subtract; click it to subtract the current number from the memory and interrupt digital input. | | MS | Storage Key | Memory store;click it to add the numeric value in the input box to the memory list. | | ![M](../common/M.png) | Storage Key | Click ![M](../common/M.png)to expand the memory list; click again to fold the memory list. The memory will be cleared up when Calculator is closed. | | C/AC | Clear | Click once to clear current contents and click twice to clear all. | | % | Percent Sign | To input percent sign | | ![delete](../common/delete.svg) | Delete | Click once to delete a character forward | | +-×÷ | Addition, subtraction, multiplication, and division | Basic math operators for addition, subtraction, multiplication and division | | . | Decimal Point | To input decimal point | | () | Bracket | To input brackets with the left and right bracket completed automatically. | | = | Equal Sign | To get result | ### Scientific Mode ![0|scientific](fig/scientific_mode.png) | Icon | Name | Description | | ------------------------------------------------------------ | :--------- | ------------------------------------------------------------ | | F-E | E-notation | Click F-E to startup E-notation. Click again to close E-notation. | | ![icon](fig/MH.png) | Storage key | Click this button to show the memory list and history. | | ![icon](fig/deg.png)/![icon](fig/grad.png)/![icon](fig/rad.png) | Metric conversions | Click this button to calculate the angle, gradient and radian respectively. | | sin, cos, tan, cot | Trigonometric functions | Click these buttons to calculate the sine, cosine, tangent and cotangent of the numerical value respectively. | | sin-1, cos-1, tan-1, cot-1 | Anti-trigonometric function | Click 2nd to switch to the second function interface. Click them to calculate the anti-trigonometric functions of sin, cos, tan and cot respectively. | | |x|, Rand | F functions | Click these buttons to calculate the absolute value of the value and randomly display a 31 bit number. | | 2nd | 2nd function key | Click 2nd to switch to the second function interface; click again to switch to trigonometric functions and power operations. | | x2, x3 , xy | Power function | Click this button to calculate the square, cubic, y-power of numerical values. | | 10x, 2x, ex | Exponential function | Click these buttons to calculate the x-power of 10, the x-power of 2 and the x-power of e respectively. 2 x and e x are the second function interface buttons. | | ![icon](fig/square_root.png), ![icon](fig/cube_root.png), ![icon](fig/y_root.png) | Power function | Click 2nd to switch to the second function interface. Click them to calculate the square root, cube root and y-th root of X respectively. | | log, In, logyx | Logarithmic function | Click these buttons to calculate the logarithms based on 10 and E, respectively. logyx is the second function interface button. | | π | PI | It approximately equals to 3.14159......, which can be accurate to 31 digits after the decimal point. | | e | Constant | It approximately equals to 2.71828....., which can be accurate to 31 digits after the decimal point. | | Mod | Remainder | Click this button to display the modulus or remainder of x / y. | | 1/x | Inverse proportional function | Click this button to calculate the reciprocal of the displayed value. | | x! | Factorial | Click this button to calculate the factorial of the displayed number. | | exp | Exponent | Click it to enter numbers in scientific notation. | ### Programmer Mode ![0|scientific](fig/programmer.png) | Icon | Name | Description | | -------------------------- | :------- | ------------------------------------------------------------ | | HEX, DEC, OCT, BIN | Hex | They are respectively hexadecimal, decimal, octal, and binary; in which, decimal is the default one. | | ![icon](../common/back.svg) | Full keyboard | Click it to return to full keyboard interface. | | ![icon](../common/bit.svg) | Digit switching keyboard | Click it to show 0~63 digit bits, clicking each bit is supported. | | QWORD/DWORD/WORD/BYTE | Data type | Click it to select modes, including Byte (8 bits), Word (16 bits), DWord (32 bits), and QWord (64 bits) | | ![icon](../common/arithmetic.svg)/![icon](../common/logical.svg)/![icon](../common/circular.svg)/![icon](../common/rotate.svg) | Bit shifting | They are respectively arithmetic shift, logical shift, circular shift and rotate through carry circular shift. | | AND, OR, NOT, NAND, NOR, XOR | Logical operators | Select the logical operator you need for working with logic gates. | | A~F | Letters | They are only activated in hexadecimal. | | <<, >> | Movement operators | Click them to move left or right. | ## Functions ### Use thousands / ten-thousands separator Calculator supports thousands / ten-thousands separator. When the expression is in thousands, you can right-click the current expression area and select **Use ten-thousands separator**. When the expression is ten thousands, right-click the current expression area and select **Use thousands separator**. ### Symbolic Fault-tolerant Computing Calculator supports keyboard operation and fault-tolerant computing of special symbols besides normal numbers and operation symbols. The input of expressions will not be affected by the input status as well as the case state of the keyboard. - Fault-tolerance processing of multiplication: Input asterisk (*) or letter x to trigger multiplication; - Fault-tolerance processing of division: Input division (/) to trigger division; - Fault-tolerance processing of addition: Input addition (+) to trigger addition; - Fault-tolerance processing of subtraction: Input minus (-) or underline (_) to trigger subtraction; - Fault-tolerance processing of percent sign: Input percent sign (%) to trigger remainder percent sign; - Fault-tolerance processing of decimal point: Input an English decimal point (.) or a Chinese period (。) to trigger decimal point. - Fault-tolerance processing of the bracket symbol: Input open and close brackets to trigger bracket; - Fault-tolerance processing of equal sign: Input **=** in English and Chinese or press the **Enter** key to trigger equal sign; - Fault-tolerance processing of the clear symbol: Press **Esc** to trigger clearing; - Fault-tolerance processing of the delete symbol: Press **Backspace** to trigger deleting; - Fault-tolerance processing of the letter symbol: Whether the keyboard is in upper or lower case, pressing the **A~F** keys will trigger the activation of letters. ### Expression - Click = in the current expression input area or press the **Enter** key on the keyboard to perform calculation and display the calculated result in the current input box. The expression becomes historical expression. - Reedit: Click a single expression to reedit. The expression is displayed in the expression input area. After editing, press the **Enter** key or = on the keyboard or click = in the expression input area to modify the result of historical expression and linkage expression. - Expression error: If the expression input is incorrect, it is unavailable to perform calculation and "Expression error" is displayed. ### Scientific Notation When the calculation result is more than 16 digits / 32 digits respectively, it will be displayed in scientific notation, that is, taking the first 16 digits / 32 digits multiplied by 10 to the power of plus or minus n. - When the calculation result is an integer and greater than 16 digits / 32 digits, it is displayed in the following format: number + numbers of 15 digits / 31 digits after the decimal point+E+number. - When the calculation result is decimal and greater than 16 digits / 32 digits, it is displayed in the following format: number + numbers of 15 digits / 31 digits after the decimal point+E-number. ![0|scientific_notation](fig/scientific_notation.png) ### Digital Linkage - It is available to continue entering operator after an expression displays its numerical result. The first number in the expression now is the calculation result of the previous one. Take the current expression 10 + 20 = 30 for example. The displayed result is 30. Input + and number 9 and a new expression will be formed, 30 + 9. Press the **Enter** key and the calculation result of the new expression will be 39. - After the two expressions are linked, modify the numbers and operators of the previous expression. If the calculation result changes, it will affect the result of the new expression linked to it. For example, the two expressions 10 + 20 = 30 and 30 + 9 = 39 are linked. If the operator + in the first expression is changed to *, the expression will be 10 x 20 = 200. The second expression will be changed to 200 + 9 = 209 automatically. Up to 9 expression linkages are supported according to this rule. - In the process of re-editing an expression containing linked numbers, if the expression of linked numbers or linked numbers are modified incorrectly, the linkage can be released. >![notes](../common/notes.svg)Notes: This function is only supported under Standard Mode. ## Main Menu On the main menu, you can switch window themes, view help manual and get more information about Calculator. ### Theme The window theme includes Light Theme, Dark Theme and System Theme. 1. On the Calculator interface, click ![main_menu](../common/icon_menu.svg). 2. Click **Theme** to select a theme. ### Help View Help to get more information about Calculator. 1. On the Calculator interface, click ![main_menu](../common/icon_menu.svg). 2. Select **Help**. 3. View the manual. ### About 1. On the Calculator interface, click ![main_menu](../common/icon_menu.svg). 2. Select **About**. 3. View the version description. ### Exit 1. On the Calculator interface, click ![main_menu](../common/icon_menu.svg). 2. Click **Exit** to exit. deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/000077500000000000000000000000001423020056600265725ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/MH.png000066400000000000000000000014361423020056600276100ustar00rootroot00000000000000PNG  IHDR#=*IDATXMLQP(Pz!AL"&PЭzлHFz0F@8VQ8h.XhK UhBC%[gX[&̛ߛ7 ) 0)RFJB>P|?du Lըm\lnn@@Զb ߸z ]8+,-  +++^,`;{:%((n,k%x#7Cj^K ƏC^0E͂C۲ H[7|3&0ZI4;;h4&I(%5x6*/E4:=^<>07[p_ћr L__:::R"4;j&L[{W0pOEI\J@C_J6]Ɇx<( !c0l&,˦; dIVe\.l63W9 ŠVa3 PVJ{o;{IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/cube_root.png000066400000000000000000000010541423020056600312610ustar00rootroot00000000000000PNG  IHDR;0IDATHKˍQϫDQHQ$LLuFL2*L;-Ld K$Vs;S=u&{={}{&k\V~>kGR'b3)`0!iyb*!F5wOc00gyo{9vC] ̇qDzYpp\*2~۱ m=q4]6^aXq8%dac]q)7M> 5Ǔ^b^dk~ULnrIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/deg.png000066400000000000000000000013211423020056600300340ustar00rootroot00000000000000PNG  IHDR"":G IDATXG]g̦yoIH Řbx+RBr& 9 aj!o#& 52yY_{/~{}uwNFvC'Jt8F..y_Ջ6yKC #tG͹8ϸO )oaq&W<'9w(s`o$`>`hj XfmY#a;N&!8 ,.0e /qJa!$sORa1šr $8%lSH6akBq37̅0WRDv"4sr Nɸ9VF#tpGCfegz:+3+D[[R뚝2?V#FIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/grad.png000066400000000000000000000010571423020056600302200ustar00rootroot00000000000000PNG  IHDR"":G IDATXGͫQn@20V2a6  3J)T(F@H&LBUι=ٳ{3$klH8@NIEnζ"qׇd1`>~x qp {q G[p7'kEbx8P=ę<{+cF}/3 d󲲀Ezm%c?8L:#`mq{pK2q$Z;öTfUӢ8>)ȧ p5eK>ci$: i ,AzTlFM>hm(P$]bncGW)H9X#ӫ};7s0#fLo0MMoMUc.H'7U!mzm 45~T^['~Hӑ""X#62IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/programmer.png000066400000000000000000000604211423020056600314560ustar00rootroot00000000000000PNG  IHDR@s6% pHYs+ IDATxw\%aQ 2ݸ ]몳Zqoj[mmmuU{Dw?"!`Ѓ܅嫕K|Is0Jb< ʉT”̟.s3\$KĒ;܉!:)e1GR5?"ӧO>^O n81j(L-/~D!|r6.teN_Sb&R a$`| aDj!G驣 燞rkb*o_,"W:< ٫|HG =!;LuD:I{'=` &GDj!@=siGЯhBC_,A5xY}~ZˣrB?Hp;DϽ ]jvrWb)XBOѓ=DIyDCB44Egor~}-pD,9D,E>Ad8GD:"^/e4?7B)S")%b)2"1t>"M.`]SGNH0ϗf*1ļ(}4Ґ"7l<{x"&{ՔHK):JSRt < ѝ_VJ`UӏZ$ Ϗ,jΥ/^ =OzUYmH (fi]_< K,'Teg)R4cY1eT*?%"Nοٹ*MI) Z.N@Sq Oā<@Sq Oā<yvP0Oā<@Sq` Oā)80>@Sq`| Oā<@Sq` Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@b婐tV?Zpቲ.H_.=t`G興ģw:Y-(caaulqpw*?Mȼ [MkfgՇlO[D1){}n>`ܦ,W<-("6QxGD<__#;G7mmޜl9ҫ[j@,^JHDz+GL2鵥>}bSSg{*;_RwɶHTb:b)m/6;&|DqXmCOe4@|LXXZt3-66y )8@y )807O~W-0<"]Kߜ(Sd%ObW噩;S[sM4GHU3)W[L"VX`4uvO(U  KZtk؛~ߟIxHhP\D$As[47Œ@D1PWi;O%L_ljp? K*r+ [b>B$k^"^J }7kТvEs_S/yW]E)V__2(;807O]l^27O7+izS]@=( Oā<@Sq Oā<@SqxS!#>w_WyVrzoܴq5[t;͞! 荿ݮ̭3ۗ P@:Tȸiꄍ>m&\kɚv~Qlj;azvvdw{?A'5sc[7/O@)GW.a "UK?j}o-UUnJGOj ,0,CnD,7_;@ĉ1!sl6u{{g>k1#'1,`DӴgI|RƳuѥ4%$''q`Sō}btg!5)ʸ:;' +O6l;_Jvlf9~ " f[?p&dKQ{!#N؄mT}_a43~Uo2G>ԛ~Z [4]%Go}_7,ѵVLj0; @Sq Oā<@Sq Oā<@Sq Oā<@Sq O!fQ;& jҼC\e?v(\z%p)iI=>UxMKgmvla0>߷q.Uz;q⵹74ZPlޤ1T~̞:4d{ch{;T0ȓX7ͦhDEDDĕ]-,GTd۵,F>|#wnZ=駩kfuٲ(eDnez)ÿNJq{lrV4ݔu=nTiֳ'w_4#G|xu}c/cmKkY+P>KFjS`LXXZt3-66y )8@y )8@y )8@y )8^z pDz,HO <;.B]˲ [BB8e׏8^ uY"%+J\~)8S*l$uK+BB`YoeYV0=G]ez{33_IRq\7KPcnb %eK^JN]17O;b7 %eK^JN]niv_`&D\K^P?!Oā<@Sq OJq;,OC?bo\_ Dꫯ/tC r޽+W8::o>z3g(.]JJJqƓ'Oz{5lmm-Wc6E}TJ.SBwY-=7,?Zӆh+z-}/Qb^KRb'R뵴[KHV j/Uu֭[~æz ;)QJm8id3;4@Dgy4lҦPww? Pȵ74zZogb5W̙?>|86Jezzzbbb#""둒r1VؠA?? 88ExzSQm;εjb,'@ ʕ+gKHHS6+N?0B}ğ 9ze6]Z "ʺr>& TDpJ]b|9d26"QpĖ\p埿m&.5ޥMbVo[MADUYcҤ߿ʉxOY'~g[n !])Sƒm*<;;;"##[e>zHLL 666j`݃:[Hq-] /]jЋͺ>M@DDj\m܀o?CDغybȯBCN]rb|k7nv5J0=t萧gN";wj׮[[[<aٝ *-;<&ܤ qXWrز}/T#-;-mGǙHR@i (M ǙJSi; d`\vw ߰A/=wNӬG(ʅ;. UtOԵW?tğ=t.8d\- zZK#'Ljq*m󼗗VS!Bddfj/j4b&#{ޫߪLz u,iNEѩ(PP^ "U6=H` yտ"1;wܹsgΗ1}oy[nݺu@`+i(jzٽE u7hVkw\*<~/{__9Ox>sGfLo+ߌɭ؇K^^^DTn]} 4t[R%5lXCO|[wf~s CA=tQHrPҙ(:Mnv{|lٳgO:xՋexgY!RnT[-Mk'#șu j^#7>)@{ PS3vn:Wk4o~׷\3!^etΝٳg=zTVњ5k._C˗lll"##]]]r[ADDDŊkժ%kn:6]]{v( K7,%kjCDdUkQ5U([&Med˖-ǷlbI,~>*"Ʃ~㪉/^=}nŦ,MUzpKUlTC* kD0NC)ZǦM>hl+o?RݎRx'VRe… w9}ݻwOOO/JV3 #磢|}}MM*U:tp޽Ƹ4؄;z8Qܻ?FvX?K%؇&Q""%M IAOuIA>mVለ7|{Dz7}z{^ zDڢY{_6N>mfT5=`#?|4ݣ76;h>c1c|'[{.q6lҥ#UR'Odddx{{1˲UVUTyWYIܴc3ՅЃQxv .%6O2(!L:'U,E Qa󥳳ajƍgϞ<(ApmYz! ~ݡ4 .sN]T4<7GgL=@G6-Yu+:NEܻSC̝..DDY|LHuzϺuRZ~>ciKM5njCDmڴ9x`ʕ7l0pΝ;ٳ^Kӷovww*}F%?-'~g &*IXetZs۶,F!"ևh9:MPH 6u,_p:A˖->LDcǎ=r$gM}ZO釾~aj7_3zj7n3*͂]ո#{/W9d妯M\u*ޤԁkADzT5 t(]~|K W1 ںu#GTX:uڷoVhpwwWTqqq5+WApvv|Bԧkkرέۼv{׻{AAA9_2w\)UJeDD_UA[صuK(N}~[)< և2ڦMkϽ_V1c8::WX0dy{{GDDrp^R<<<}i6unSv{h,q T0\dڱ2uI*PWQ(!u)+HJ( :8 cSq Oā<@ H$ז %eK^JN]17Oy^*Wzy@]RԕsT׿nc$$oKPS5z|uI꒗UW~ q3փZ,tż FG Yo~BR ^PpWiLј|dء߳Z꒠MllF=ULDl[=b8(k- uIVI&rSUe60YDuEYc$!o3YDuEӛdEJ*$hLM%39/HKUrAsoy "kH@Sq,b.\(w5jE IDATў\ ϟpڵkkժew-Y蚔 E%99yNtCĒ%K:uT0-f1><7~z6X:m\yGײ}yK]Go8d ð*2w34Q\\\zz#.^g8.y;g Kz=+VV-6;yA|wXq1j9ie]6k,K7 E?>R΄`܄cΥ2~Mw+W6nXY:zo>]29UGEEQTT#">ξELj^ݓ;qӗ!qԁb?Xd,X 76og6`J;9)-Y$$$DV[!)<=vΧCOY6ۧo[#"s+xe}+js?ۢ}eccc|}}˔)a'mJnޛհM\oG}ҍ'6S-[Hy<\M`ʮw?m١i^FԦbĆɽ|TtAz:>vWn ճx: UTΟ?˗/O2E}>*jSL|rq/[Q`U[n~9p44\ l\gFF*|;j]9v.Ynkk[LDKMiaWLإWͧٵ}*|:䧳Nݾcyc%c^Uԥ;v0(}g}骣/c>_ٽU7Nΰx;_לJ-$Ғ%K&Nhkk5jtSjZV;uTNWF 4ԭ̃l~߳yބ5rƞ|ʽ|ܷ[ϗzݶ{m+9䝫,SGl۽f֧/םz1jv\:ƣxgԜ9%I|ٳQTm?ĝ?^t1SJrΜ9D4uԩSќ9s uhqm=SmK/XVm+'g 1A#Խ|ᕻsx'VWLJT*Gttt~2!q甾9fwg o[֎8e51\{M|Gs6XSq}?Gc҂?~oF検Us^~Vtl-/R9{˗/_|y S*<͸У+ o׮]nj /mfFV=t4kipe}<=y><X.!}F\}nr~{%Lƾe?aMq_mRׂ̊3fI_ ~ad0y TPj3fΘ1#g_EaRN= `x]^!Cύh;t1_v>Y2lr?Ǔ'ORSSAؿ2vRÈYO愬z^j[ejuCaQwnX~O~=ZVvHpm6yF^cXŴXȌwv}Um5}Vu~Q/=Y}L#=9ɭ=zƌ[3~ܰϔg] OmUjS(3y'6mҦ{q2T{=MIU3c?eˑ&M)Rxx803Lxxx|||JJTuOΰS;78kʟj|pL}âZ'w;m?>{и~XUoa!q3]Pu:v/턙;Q='.ߩLw?u [z0Je 5hw͚5N~Bșϙ3gƌׯ_ H;G 8"h(8wk4=p|*/ox=~cT71޵lMiiVVVLLZ.W㶶qqq5kִPפ&sh릻:`+e&\ݿxi/Ԧ2U|YVM=H?jn~Ɍ2WvU_אy1G?~|ݍ9_*ʹsZu1aaa\"^<)jSoK.5i$ׯTCeeeuС(NYJPW!ilxwǞy6Ne(I[چG6w--Ү8|pOOٳg PKllg"BXXGPŋ⼼,<(Tz5wˮL^a_ʻJwZj9sG1bD~${ ?ƧS)!uإYz}UY|Pi/)80+OevVO>  Uf2YDuESy%""=o1];|SU1wItS 46.Iv`>j!6:'ʼzqc;{Z '\=y.vN'ʊow&˱V0JKKcY*F|؉Sl@`w{W:4hZd[bY[eYym gv7D?eVsz9R)bSr2zX|7t݃1OZ"z>>>*Tprrz7JzCtjSb*y=oTN.elRd)*|wk/v$\h'ukJkpzv&x<S t^ ֻo!9+W\y,[bŚ5kZIbEh9/?1-EIyJ6u~>p(uWZ;nJYx~8oJl/[?k"I/_+pƷSƥiDDPQ IVE?Mn/}ʕ+{xxߏk֬쏇 )RYqSفҞd<-fJᇇe] #SXۥ|ث~-bvSjR1 *HwBU3{*z%Y`7k '.=,kBjZUZ[nY]"'k05\LYCL}jCFpLxxzyDK꣘qLs?-=A lsm3_ ~;L6/x\]]IKKtCD::92B+Xwa,{avQܽo2I3t&&6 oK7 #"emllcqWn;yɀ^ֶ5 ֑1W}^e}*>}>rgƔ-5nOp{I;n%hLM|(-X+_@qot폵g[ueI&Ѥ ԫLS(el/r;^ysB}i>pWuYĥp9z+V !Owڬ>9bX2RT<̙+W.Sj8z{!>v_wIDD Dڷn"ڔMŞW Gw7=t`'AN r/R-T,ǣ8N뇯]oBKw4ô~*TlokxӒќKY_?????o7[R8|}JI|褤+ Siom_o ""xl]rzPh,2 :P-?6]a`ODDOVIws)b:\z]:fY0Qi O1u}"Ve#$&jlNڷ`}-#谨\Q]TxbBZÇ7viOs}""!!CW9뷩:h/q YFvmլy_1[[3U]_tOOG֫Qߓ#OXDJ@F,蘙YcñTw5\45Τ3rSؖm忍.UdѶB/~?7nVIH*>O@oBcbO5dz{t)?l=~AxǶ|?e~c:{VytCR߷d]|ݻNHز?=kQ.ޕU#VkMoy=o=YST=m^8ӏ#j%X0}̰>]r0sU-斉111nKj%s}"ݎ~#Ev WF .e;x iWZ}é{]|4J ʄ7JOO/5{OILL '5)iQwW3-yK%66֮]w>zΝ; T*77\i.OB WU lk][e+YgZK |3rH" b#ݻx:BRJ㳧J)ZbRZoOPsW<ѱH))۳)X|+*gr/ %Sq OaV2<>7$D X/PhYyjB[/o` k- uIY& 5,[^/+` k- uIY&;>{*SAb&YVY꒬M2w"R;gYVR|Jw>N嬵4%A%+U(UPt*V+O^ W[kiKRJrW̥pR Fcan s:NsDz3k- uYb^o0w5í,݊"a.ٱ K@j@y )8 }|߰KX IDATZWrXki˲*\j4Y,w0d! +x) ㊧mo#9Z8tż 1̔E233 @Te6qR[ZkiKRJrW

Wј|Tuj4%A%+؜ uEi2yEè" q&wEYkiKJZW4ɬ<{B/*4%e%+d# yĘ*4%e%+̜$.PV!EfoU-yEZ"SW~ʎ}kSYP@ @y )8wR)KHH8zhBBXlي+Xm{oƘzw/.51#K7T5"tAR.NlZ{a)ZιuH(s{8;|g˺KHyZpeG>z^wGo8䷄v_q )>_s{MFaZb`n(FDnݺ~ppp2e,4JޕӤdF!mrNkKweSCaVrѦP9%QO[W>5}Dto&'ֳ7vdl}N{̞?~pwZpww211ԩSNj۶FH=\.t['?}Je R˪flBEZɇ+;vɿ zޫ;/Qo۸o/62])OO /_L_7JBիjݻg鶈CH9ˬ?w׿oH蒓RW7kK>.t>F˂ƾ葵nXv"{-é [j٪^S#Avm^}Ʃ~+>>q iggk WB囿^37-QI~811!88E#++b9Z7)EyiҊ.C&U7iXEΩwr8{E4@-(#?(۶O ?+{68g̶PW,yK%66Ve gFT:99ծ]|>eX[ujNJ邍g:|Оud(jP/_1t܄,;u&ܴ0>%gP$tżbcce Sq Oā<Yy*U/XG Y%:O'|PhYy*_[5\4*4%e%+dVPZZUr&PhSGB;>A/^oe.*i]$s'*J~eU*ɧt:|#<pjk- uIPy""mmm8JU(ljZmXkiKRJrW̥pR Fcan s:NsDz3k- uYb^o0w5+S~4%;V\\wH @Sq OQQXVv|-zZKC]WT! ѯP(^ APpe * Z꒠MllF:ULAl[=b8(k- uIVI&rSUe60YDuEYc$!o3YDuEӛdEJ*$hLM%39/HKUrAsoy "kH@SWZZ} ")X/!!ѣt:>O>]s'/]h.\Cǧ ew:f^r6ʞ>rnLR`WƿfFW*ijO=E?/t74f`%֞v$w/زVg,#T}k43bhvEf|i)k']\'K*Gjm:Y}f^q-\diﬞ8jZm:f}r?w5Y'%E=>el/r;^y??t/|9ӳK{rW{~g»|Ug$>8kV~T_V- Q{0nvo#ֽsF6n[ѐL9}oSoe!s,};=8{ëU@%.7!bzᎥ;SOaZV*75~isC.^>~jzw=p5\L@X,\5Bg=G0۶S"{gEsCȦYH`X$" k`XEa! y2O- >=o;uG,XVa-^xЎ/N:|o(wR\Ġqg]k q#[G!^L{/cG!?߃BYf;b0J=|V.HEQLbtLJySo.YCXh$TVXg>ib"Դ{K9d?Jo+[m{՜mCPȨӦt<Ŭ̂H;f#BA.ZK|F-\ȘݨBzO{ɟ pR-x bg~߫->mHE웟]Pן.y>8"CN;+v]eQ6}?M]ieE%ѨBx񣲆]1D%cOw(r25{Ot||Cݎ6So|{K)]vWĖSsDf­yj?8~vOv陯g:<ĊO9GmuEEE7Uy>..N[tu9udp> |Sw=!ިP_Kəm.|y rC~ASTqv^WDjmE>6[0u4ɣS[A~SEEgq7u&u 3z4盢KCQQNA0u^SAAiPև A4K:$a** uifOqף*dzLjQeeUHH** uif6?eRARJY?ْ$9+t) ui7Vwan="˲(:^. יGJC]'uk~jXS^~A] ϳqO$Ij΅^.jST((#[r/sP)jhkH&m]'T?JM5`00KU6EH ZNj B`X4AɨwsQQ3Yol u* uiF/aSLRM)P 2ͧv Wvu:.`&w+Wi*xw8ʦWiK8k KGp@)P SuO@ OqWeG\8/OY7SQ ނx* uiM yQqUJ/%~p6懷U;6?U6S_=UU2UP _l!@S?њuYgGU~Uh|=JqX{% +G)vif E Zo 9COq72Ia'6!pA#h*Am VXm!lSDR"F'57ګO&6H_%lQVlA`ŨAm@ktw=SRRr: L&ӠA̰6rg8m>`˥=ًo?Rp]hsdF֟SBw|%g~Ɔ_tRŹjg b[6|3ԥ*> <16Y@` gqGnݲeKaûF.-aCbLiצݒ0w]2rt+lqlN RWytm:+7^}g "/KO%)oU8gx8c2U*<6ηk'*pbmH3bֈ=6JnO%_.DYMQ/Pk(Nyv]ʼn"SR^^n;d25~)?uUcYVl/o JJnS00tm vЖ=''O^mP`ͥC$]:v *Y-\ԣO_e[o;ҥqk7*}-U@Jʉ3}9z@΁݆i҉Z}`4VTCnUC~}~JKv|c[ɜvxk b_,C75><"@⹽v|XtF$'$$$ٙ|aswV55Q|qۚ19ޜҫrf>}BcdFL&7-ZQB`hc[mP p2.w~I~!O}9sņV䗐֭rO ~gA|eww\Y]l|Tșf\{ ylvwi¢E jX+绪g~񱚻%Lә^ Jd0t |c5#f,Uuk'?- {M|}S{|c$G aAKz'\Hĝp!uyb!iڣ#Ǥwu\z6&AHh 9=Zt Mb0")eO>("!~TϮxWtT#{MQ1ǒ,جd@[v졗էEEEэ;]ab'Q=`GKOIgs:gn^C=Nj?ucSvLvKXyk9.7.OOl촛c ˑ#^;'N\x]vގ'@z Owc0af}dņ0J֪%6oZ14!u[4\fʕ+AA}ʽMOhh#7_-^aUZ%&&&&&z;&jB R A~Q j(A&Gݥ&&:*i5Ic~ 3z$S}\Y*9|4m#4 >/F٬DmЫ4ԥee[U>zT_,^iqBPqs8~:~UF)zfBp`** uig*언@xuK~~J)eKץ4ԥY5EkXM˱fJ-Rj ynq@n%˲(^ի4ԥAEp&ucO:INKO}||XRAiޛV@${* ui g# p+K=~J?hsq'ϟWkHeJf'% !eBeZMy8/fʲ촶r^.FJPaJT`odyURzT9-I_ک#QZx%KuNQQf3PJFPPx$d AtBG T_+@լ!y2%J j5V̔#`WOWYSA܈R#8yJDd T)*!}ρO,*"!8^aTO(^V- ZAi@?Ei(**v onep%d]IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/rad.png000066400000000000000000000010761423020056600300520ustar00rootroot00000000000000PNG  IHDR"":G IDATXGLqnaA6RePXػBJlDؐKJYRnK3b~9|L11" HIE.N"Gd^cYҗ w q[tIlܷK,7>ab?^xجywl:  qp(S7b>R`f= ,Fc KUV 'H(p= 25gFk;G@RL?di$F!>SuHsP٣N:a̸oBB<%2Cp9 j}#$ >*˓9Jc"ty 9a R:BO0UM1;4vH$RKA,͜R!QjrSZI%1ًQҜ*)BH#0 w9C "nw"OfBL&?yO`@}QB E-aE2H#@wB> @XY+Fq;BL"˵[`=25 S q7%qɀ05ap|Ҏ1JsS iJ3*kc V(TYg;C)Ա0H$,* 2#AhHU)0TSk=u`is jgYWgt@ЏKp=JELXO$yM`5X0L>?)+!?E5d`d Qicì0 EƧc⛢|!t} $Q$$|gxQR:_*|u j2)BHshH"H u(YWz-1$SPR0!| p>'iG!Quh)8) $$)$I!IIR`h`\,|(?SJ8<!ST J0+K٩}+)I1 A (gDC! S5Oá^mgJUiVs.Gg?55>ox!ST=RiLLLjj*k׊D"kkk==_"!)_ @ ؔ\5!kx'B!؁yBBǧ!SbB8>E!v!؁Sb)B!";p|Bh社:\4ga}]|{7~:mUì}%26Pݳ[E3vF-/Ы׻u[Sl+]ΈT6a"0t4sVN/si4eCԒ? нd+}j?$H\3CW۔Qi{z U8G)`$i i]գQ_Z{5y~yh B*8 n9YOF UI}nK KϬL|ײa|[D ǧ!E4F`` R`痯m״>n>66sP/L_0TY;s 5P9&>>C^XyR@gA]' -W[RHLo%̈́Fժ[<Q^L|cUǽ^/.ztKIa>YƷoV=IЄQD/>BHy3 3j,]ң_=xp@.n$0_|"*t4! ªjM6p,Mǃ}o},\:5˟-"'ܔr6|Ipn 퐻3! YcS3eBK "*.o')҅["sbL3O/|  _˧(J/SPt.ng>1^e6sg>ZrxpHٝWn>z×8}UW/_M<)ґ''XxO\З:ݵg%>rBHZ-(i#V5W?Cs?¤%'HQ)S*ahjNgIOc(R8S/1) 2J;~eRQiL3x!GL⧗SaI)4Nlo>'lԨQ_&&y*y!&۩4Pe}=* <,[1=彈.}sRvHa"Gˉ4kviQC?czvnn^;koдN<կ4G;1OB|#u V-, anD/kje_~Vmת3GqfѶub}ףB"~84GKeHiFCCTȾ\!#L]-GSeLV%Qeφe)Y̛O1t !O/y:cFj/ԓe IJe*S??7\z'MZ6.&9)H23w:oХ 4rhmaI_;dHçvs/룈0!(6~s~kOMk>EDxjdm4k~HQk_ͬf8>EqYs6vyrݐ~n`[٥wXTǧ!Ăh\B!v`";0OB!Sb)B!؁yBZLw"W0w->n$gA~SfҮ) [)R\[Ua& ]V6dB'293%L7pfo }… O v>fS٣׭.*S2lt` Z; Ҫ~kW=^/;ݙgx\%8xˆ.Y/-:|Ū @wvY&8tpͺj\gpXŅO~EjVeUKzg2˽Qmh.ߊo֜#.]Lh4ɼy&M(d6 k=d`hk5㯝vMTٍ?{zB^]94MŚ!#haf 02]"ǼUvZ-!PZ.ħ2@]$iQ|X`3 F|rZԾmi>R+dn#/{^Y 'e';i|rJ5+! Δ*SZc֬}\j *JooyXd#Zx7ɻW͚;(ܷo}_ti KƒlQ w( 0U$2Thґ̏oe]ɽҩEbqFj|cWI٣'*לzaG[BS.N+WJnkj ikxoɀ6l.{a_:{ݬEy~bڵk'MJ4Vvom5!&=.'5ҙvnc-Z֕=+?SV͕qirjͲР>imI pFRϤ6Gڲ鹈,s?k_z:gmD#,ۨq%{mҕm2_HvԧeьW.p _۷>R+ZD͙{XWqqqyBk}/?jK_&F)Nz1d %xN%}YzNCU:d&Kn6(jJ4>$+83t|c& Ԫe{jg:BMEԜ.n[y6Z>U3^M5WՖzg& ܲG78qℓSյ]? l\Zv]O?tvl[pOmk5+6ht S6pa3 mV34-MVhK=jU)mLǾqx] kuVe .u+S;=UqfN~yV bT|mN]޾x_T``^jn,#dv^ӽuz5s */Z\CvUo~~˗/3fH:at~mn Qi^ƨKxiG\Z%OK >w1,/532eVڂ5k֬˗/G>qDtޣ=5~V^ -EOKj|*p|!KPٸ>G\bbbRn]mGIG5k\&M>|¢$Rq|͛7wUa"52 *dS撀5k֬TZZA~XEߗRjOikW*_!\f|]2Wo%XsI5kP#OF&)k`š5k})zT*挃i4[*Y3f(^ߗH$\{dIao5k ;KAqJ2($0 M*űbÚ5kʭכ2 #f5k <!؁yB~8{l@;dȐmۊ3g~A,'%%nذ|%¯)Y/ٗdS鬟t72Bu޼yPP޽{ݼysŊ]6w\Js ޽oܰa+WDGG$&&ob IDATTcaaWųHP͊,%1->#^ujvyq\HHȣGvgmڴJOO xy'ݿ w}H$3fի6@r߂5jBdǎ;v옽ƍ Ҹqci: ϟ\|dߣchA<6Աɠ5[qQn0R}y+(W*`/CSc}n[޶gJ_gwy a\f}*Mێ6m3f5jH)S,YLD+J`Сl}){ 7n8::Kw3ax0)G;$iPAuO;kf6mb.eo8Qeu8 yw^u(s1npOFԪ.4^f}0doOz {㞶z{k֩tNeZtt"[l!Pdɒ)Sȓ,Y;O1ct-44ǏZZp!(8|-?dpR ODTt|= }϶ԵSSL6 p~e|iRmAd/L*YqJ)P`O>}4{E| -Zhӹ|*U=`rskLSF~%ɫ:6Xg;iXnV榣NNpnjzP/ AG\lSŹ'H$:|֭?*?f*?Z8c O3[q{ՔZXۄsOP0 ngEBdçέZ:QaCIȹ~%I_G'yΎ$eS%` af̘Ѹqcy$|}T~,Uʳ=?n휥#ce]Ά[5/GVjժM;mt|ʩS{l3%Rm}d7!&{_OV,_|ɔ^|)*?*^|"8Kǧ?=T*Pv\z.Q79jJ0 ]IT@96lX =O.>TDmƕ2Xqa nxڶ4v9&7&3{OV=60v/ʰav{ҥKGBpҥZܹh"###H'/8n9Pv 53 Gd/.?aX׭w^v)J[7ot@Fe$oVg~84O;oI.vzD:c3:[l1>\Yfu-X@۵+y ߿?~7onaao߾  1m۶,& Fy#i_YU¼صoɗ%cQT~'(:~xJ/N:-jݺ˗cbbZ)B)ƍglIRDKDnJLL H$>>>B۷?]vʕK.]H$yoQӘ₎6)Trr2]*NPQMjj*a s!eddd]'R*::'! ] !a8>Ց$¥:.t)[ j)o6:*ߛF_ЍSɦnߧ%n,ABISB'R~ JQT<%I*0 ߟ2,|_ÔUBc$ ѬH$u_* UAӴSu)8R;DD"GE:r| D"A&rN6W~IPHQMgK9*OH$/ p/ )TK*d2'3̠ K'KA1Gd〮p̝ya\Xt) Bk0OB!SbG1e:8n_AҪN6ؗiz}_,bNE.j_/ (d,t)8@=OOOE(J[W,zBQTA6W~X,cbXCڗ8u)8IݳSKY9Hĺڗ|ڢzBQ±6l /SWAS\.t/?ɦnߧ7>-V1򖿓ɦnߧTr!>oRTJXUS !a0G!.?cِ/IBk6CFwe TSw^ Xjᐪw.L.BD2'&wQ )ID)aW\0)6Nwk{v\mrA/NnʇTÍ^)reKs"KZڮ(t3m~R=˒gۦHC;w9tĄE50q"O Kk]F0/mI+Yr)~fSM/p|V;1 NEdHC404v!(:S~ЯѼà.NVB~NhJïLKԺyMXz84EeW̽v眡۶hѶٻ%[5^bܘTwܮ#jdҌPfO~FK/=*V>psG"[Lҝ^K`Ո"iG73vx܎ :NwK]ju&`5ր K45.J[j`h@ 9z8ߨcLhGr6 &`k-hYݫXْV)lIpwMpuڔA8Tؼ2iBnZMңSU- G14ʺ4*~*u5ˤe55ϒ /vql?^8&k@m7msWΝsӹzSgttzEsvOXgҙ 燧ͬ[Zh2?'ʦz/;@?ŲOP`4ͭLOTA==7^}q [7n_{O.͎)N6/[-z\zeI/adbILvt &pS\u,{iH0ifꄆ|VZ13:qk2Va^3֎~*DI9NNH^T#׸ӉtZj*@4ָTZ;WsN i׌413!RRR;jHdyGgi-lmd?.~TŤDIx}HwDCɡ$kt LPKL1+ii`h`hWĘ gf\? Bdn'޵5$NNHIOY\ln0?eeo]"7UzW%>fQ1Ge{K=xuzV3.,u:zjTXB)Awm|~#hґ6{F{~gnWI ޲ls Ƕ/ntڡ3WX5iU73-h{ƈ΃gQ%8>}dn^x,Й]FMZu3^LIqq \A$wӃN^+w\![펪7fJkZӺ_[sL_rg!WvLu0| pS k.թнvLKSQ+ŤȄU7%8T%Lݍ'Tǵ r`p֝ go$m-jMl{T7}ുAQ&Ɗ'kYӳӺ}V#]/GO_Rf.0iIA6m;~ YjSWؐ`>tZ[#-ඤU)8EG+dpO~qB9;nPRF3W'aaa666욚Zha_bn-6 +WR1)vVˊuCjDIp:lGE~草;3!`מtΞ\2.~~%qX/1Ou/SmF:/oTTS/]"o`";tHPDsk݃Sb)B!ءFw}!4 TgbxtK)tM)GO_Q#OIRBWi]W lJ>}*Q"Uվd2]sB:ٔ-|UƧ|@t|}1 gL&?׽0}DH$$IHj_R.R%7ɦBRJhN %H8@dIɦ"ʯ8 "ea.A|:SWJ2($9~204M2ɦRPY!sL^վQk :`_|׃!5!SbG1O#бuݾнl /mzX,qey&#R Ф} ǻr(d,t)8@=OOOE(J젫} B-V1ܢɦnߧTr!>Y)*?V%,}$BW*0]#`";0OB!Sb1do.oИtU!8o;m8>BdڲUKF]^KB;'j,BZyuӪNrVPe,ջs 1u3x] m4g2tZ7r ṮEN}$:f)}hWA*.% _мyc͙׳}&62v-T6 KEc&꿏m\ǣ3{}:$fdwG]`|}8k,h֩0g&Ѡ q7օ @T{_/&xמ.WIݾѱs?v/| k uTujӲux†i]۶l-p3oFzoռy=N]w5ãq᭚\z/1~:v}GBdQ_5_;咽9s ^^ FƑOj_CGK31"([;&:; tezhcK?5N䜓If"ߞC:gfnk@˱Y6G1x 驝&M\ge!ܲ9{Dϯ%xHsRwҰufz6-P˫Fy^V픋s+Yby_BҰ.o3 $I#4 돥\ܫ ;8 )~vؚöhK@Ã]@W=ZCGoߝXl$ 4Wn+w|ksv#ߌQ- I #2!C`0sL~e('ڲCuS LT o~A׭H3zI1?3t̷,cpmZCg<e6k?]_`7/>0N >?hV^aeև> kפ'wѡEJ< *u5ˤe55ϒK˼j:VQ_"%TYMï2q^mowjkэ}>R@o{g_3ᆬ֍ǭ\YV=2˛Rih)Hsyʤ&ҤID&9)/= IDATMMr=yI3cHMNfX;ݵ}Y>%do)31Qq&%:2^x}b C:qЅ +t\~ozޜnjh;aȚ ˕3KĀ%~Ń25OU|T**7=AZrO46uo9$:o\{׻ vEl#M &91?⠓SH^)#֦v? ;hGDw> >m {4cqjFM^VЩ[.Ԡď'Qt/d'_ΨXڄhr *ex zXh=WWicgC¾FҠk+RtH1icg y @G^.zt[kFOl!DCk[ U6iiCXMZAvv.]ҶU{:@Ԩ\#uib.{miy ,oݸ|B :9=p\)﫻gIT´ju;Whr)_|M:׍A[U9_u/>Tj 1`1~9m]?jf}η;ap҆#5R ^JrSa:hlUwݐqa&P^6ۏ޽Wg:5%4z>FS4 ;uiuw3&[v3!W" Õ<%lllT55Wd143վJpD,{OϾַćr9hSLIzt%~Q$ )Ttt. .PU61yR] k$MPd"  7n~ x?TLeW93d_:rzW'(l_:9ɦ<#Fa";0OBj)lBWBi{zB'R~ FfGw}Ѵ.ܮD lJ>}*Q"="w}d} ]dSJWA=zN0 ߟ2,|_ÔU"c$E"վR)'\4MKu)8R;D8젫}I$>d2DRu)8Ⱦ+ND"@ aKxA!Ϋ2վRL&($I0 MӪ̰t)8@sDVt/aԚN6!Bq )B!؁yB(z,[ [Zɦ6Mb^3Qȅ{]K P~W(LVB'Kt^T^j_B/( |oxl /)SXKb҇t/pPAUɦ$uoF^AJ/%վdS}qҾ F=tw}y,ЅN6t >}Di疷dЅN6t >}_yK}mU¢Mwt`l_! Ӆ8Bq)B!؁yBnuݚlyqbQ) ;QWKұOl :rD¼[0ɥ y`-F#S .e4Y]&)#lQwqor.V킊(gQ|K^q-Ƙr)Vu0j>9$}tOm;@۵&њ#F71 5yCEljڊCEj0U`cb6T-OjŽ跕}t8=&:Ȩ}n޼g6[av3Smr_g=^_`r yrOVoV߄N/7rmvW" a <~hӢibƅ$ ػS:4#j=wO.ջ};FDS8tVz.5#Oٮiٗ~0| Z({$o!޽KuC3gjfu6adn.V4ؓ+I-=M2"L<rח}qg*,_9ʑ0 AnM ('(=1峠VaV79B훹i.]4mؿ@sR m Nd:vS=ߑcZ@X`o]S&cafMzpGNm'$ܷZJW^HSdIy+Ya}ܑ!W48' ̭-ehimc{ ^je{ܻxIꎘ5!K7<~ΔwV>psG"[f J/[ƭ;y_I(߫G.PDM]3!iA7mZ˟m;/Y?Ɲ/{ ɌYGXF"(m8.{5'8uadY2ҳO#9zBfe ԔT-:AWO8f[C闕$\zXF|ahި .3Ob+ծP﫦"˧X?! )11eR8JV:չC^!2.9CJKR^BpS:AN5)v|+S&f=`bo/2$xM2ڶfÔVmPG4c!K zL`ɓ?,igg84Iy*}s#x萩BɆ˾i 01Qq&%:2^qY-]{OJ×s}?ٺHtu%̭m4G#c]<ӯEE&Ye#vO+;OjZq^htdAQ#g-ӑ~Ӿn֥-ͩ >?$:o\{׻%ïI]j~ODž xAD~HցgЬSYSwO= _Ͽ-SʺAC|MF_!$8ik;rT KsOO$ɒOju[v8lpj b,#@QLܥy \fEGGc=6ꩳ9:s9.¼?u;Dw` oooe=e%BĐGGH.eg=.B!)BS!d6SBGB9SnsQSp#,*9,  5jfɗPfaQe Dx_0m/>¢IOE)e}kVxP4l.KlzvGǂ 5,TUe32`.M*$Y6www{s$^sF;2`.)2WAũ z^$nRSxBi8oM\,+" @)UU՚siM)f1&xE)i.Cb BHk"}`=E!zBQQiY~sB;e(\th*$y\$蜶=%GNEEQ / Klʕ,&N>,gee^st:VDQt2`.)2WAScSYZWP4=li륬dRb^s-.iXsi\POY/:&S$_ .C}E%'%Om)9K޲;-_ .C}E%'WZC5;&% b}WĎJMwxe Sns!8BiS!dXOB>"}`=E!zB=-3KSb{wH(%Ԇs=f<n mon a %ogm3M?+o:cXk}.m{-<|ۗT9͗;*6(j1yؓrSƦח\>v7taۼ;CWI̝[ӈ{bDd꭬ U@VS'$Zv(ܩۼ5[=k8c-b":hܭ[4cjRN'L-ANx)QW婩IIwZD؄_6kVM| {>s?so۽KރFl:qǕG ҥNjy%uѨe_Y7cxx^ N'hn;;P׸sʏj% /og3l_w\Z5kjM=h)BTɉioG9y_lb1ugiego=h̀b|+zozo_=iyxnϦS,[7|tǑnWkұbp3oJ*{Y QI-:Uiv{tJB\ƙv@}ʕC,oMcqGT+X4#-C|J>iZjxɵ|J{CFZwj4=j4|iMmɼ^׌mؑ.y!sjޭKi/g㾑a*2֕`0R53L{ciVԷk04ljۊ-ҒSsutԔ.n hRBRt4=1!K(S4 GFKobԐsAtrg7$οwW7)/oOո3Oįi18>FZ)Ul;q*_ OJԤQ_j׏zQQ 5fϐ7Si227kTfʗ~;kL~?}b合ե{-;Vlv Y@=|U&fݿ“͙Y["' nu3gԮz)92 ۸K>ٯYE }XkȌ|?m۠oMIWarLM[vPEt,h{& nb~ڐkFY1ϬW{!3Kp+>/woQHB6/ۭgz43\9|_Zm2 n~ p v]LTbK<Ŝ W`Vi:\NwO6|>X۬/ 3"/۫uU]KeYܞϷ/vXv^o鵩žPZ}{eg]ݶ"ykѫлeU]o\Zl}AyiFF[yN+z{Q'~ ~߲v롿n%jcĘ~G-~>͑gg?90P4]k69~ƽ VBH6؁rGY4Jk<{3.#nXϑ^}8-eVtt4Snsq)s 0YYOY>܎BZ!)BS!dXOB>l0;a;)xͅr2梔EʗPfaQe Tx88P0T%2GXTrrYbC)$Wws)xͥ(,5#_ .C}E%'%OY/=$rR֬(J>si\6쎎A\,;RUU 1P4\f\DYI^k2,vE1-P4\zILJfOB!5O^sɲ(( h|2TUUkFX\̥6ʧ=BƘL5Ԧa  e4D!zB!죘OM8;o"w*P\ ǕM5T"%I*D$IE6giȉ(JsiMyDG嬬B^k.Nv(:śpr 0 ``R`)^sY@@,]e(\d6+ 2{L^DQwP4l.Kl)xvl/>¢j%d/>¢+?dgXxU-s^sY\!'7BZ!)BS!Vm:7ænG!dXOB>\RO}w_u&mzKO,yn)ǖ ob<6ƝC{?ߢyXx38z3L1Ɲ~Q:}-v8~<\Q!xvkϧ۶f JjNޱsoݦ4n4fSJN:Us3_;e×cri Sdnq"v1/)_9 k7b'PT=EԞwкoYv _YͣWR_^QuPh|k=z2l1j?m?}<];wʤx`|k޷k}ͣK \ k?¸?YEyסcN1R~jX* bR>$MSZ1i '6޹|kސznVS+gaSGJM'ߛjZ+_43ЅFMK\"Ѷ7ɮn(1c]J5xZrzRrl̈ QIDAT}ȶ52G 4ITQ_>:ivwfGRj [5irJpϽZ]Huk,@5ԉ#?tuQ>4b}۾զ 8CFlѷNɫ^ty$/- ^^f5+Ԙ#s_yнbXK lߡy7X:-Sq~҃7kcz-^?~*&4KjĐ:5g>P?yAsd?_jJXY-|.fedQ<-4@MKx |_ GT?j%tޫ s?O'=,uu\U}}E [SVNhfbBFޏQﻬ }VqF7y >oWw6Ư-qE>Ȑʆ4/rimb,/ÇnsIGSO-~}e8sOڵuM{*oƏ95{⮞ܷ[ZՍ)t-/7Zj',8W/wNoKѤngS%7M.X ‡/%.nvΈ+Qe/'=ܼ[Owu+@2t顮nZ]8W$zLY;ݲi~4ʡy<7? P$*** fdd85K'oF.YܵSG٪ Z9s O|c].;;߹ K2+::$t{'BdjBS!d6SBx8 ]0BN\2yn>Rp#,*9,  5J\2JN.Kl(%䪂)xͥ(KZb_Rp#,*9,z$l\RַfEQ KĶ^gwt,^o~ ^sɲKUUY61siR!̲؛$ݽRh4APhx#.CҘ"sT %I2v(=G!t?y%˲(( RUUaq 0ؔ+b c2\R-L2`.z!)BS!d<eyp7!S\~sũth*$y\$"3QE)2F"}M8u_I,Ys{ wVԞ5Ip(,Fvt^\~sAe﯊{!лƳޖ][ttmo``SYZWPo.0(0eQ@)P *.KRV 2{)1L1^DQw Po.e?@)P RPaKԜ*m{Sl8~z1e9G^s4E1e(7H$SF!KzERBS ﮈ}jp,ն/֬-2GXdnH{H ESnf"ֿY% mc}WĎJMwN(5WT7%@{ʷ)r9BL#TÕ4"T@L:*0@ii<> Ő'2DzO!(N@kFzr%##L͖Ukb=Ea! ɱ~ `5]XOBP$ Ծ:u l==5۱5 u$-)>Ý>$<؃ Jk&K?wZf;ȿʃ#Y\Uk;V{]b.w=O )1U>GnwÎJ=jsĸ˰@o=:?"o{P}TDӛf?~ _Y#^t v (Y˱| j'KJXs E׵;)wn5G:dzwTm>t,M XXDBߙdnm^R[;+c'=h{ToR̮8gZZS'S WS>qXO5#S7y$A0}J sbHws>XWStx_0:PpˏȺn?W|u.! >[vmb)^#W/,tl|uONa~̘Շ\ٲCSķo/eR>q!5f)$ߟN5&]ݿq$RY׎MW,ؼsң#C&toT\ـڝtuF9pҠf|+l;rTLLkzU7HR5~ؐ06$6)15י9I-ɣE-@F#%:}޺ degU +֯rs Rs cBx?|';bPziGM6|j{"W)pz~>J|л2=4HW_P}?gF{Ӭ\ڤ3 JMDQ(1QpYW69Ǭ[44V{&?""ѷ?l6}#j}.W΃^OTUJB\"x4)6VX8P9jv .xʠg+zqV ~Jn ׯӆ.r}j8%PNX: {@7oݦRAzsEg<[O vnSTn i+԰G KW35CGCY0$s;^0Ys=L|#x[vVۻը }';01WTfV-+tw_-ٝ|ԢFܗC\/k3nf@l;#QQQּ4##ѭqOO_+M3ҞFkҒ#C9UvޙX2$)C-zN1mo yڒJ+^"K%"TJix_Sg(Ld:hOl8c=E9JDI[5BhqA`=E9ˏZطKzrj1zQBi S!dXOB>"}`=E!zB!@ttB?aEIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/scientific_notation.png000066400000000000000000002441231423020056600333410ustar00rootroot00000000000000PNG  IHDRi!w IDATxxGtr@3066qifwwwfߛyfw]Or۳N`6htSU8 kk [:U]ԩS&MRH$_i,,..UoFo$3"iZ^zza۶lO+.F"H>}Z¶mU"- ]#D"|vªlDD"H$AD"H$4%D"H$+iK$D"H$W'UT_8(? D"|e}o$ɗK2vX >ME} q:M Ct~ Q[J$+'7fqMD-9RH$/ f;Jb@FP6?MYh,qļ(p_qoGUH$OX*B$k7+[! O c<}8}(7G.o }c[D%c x%1PaIk3}p?:Uq7}(t&޸o"D"㜾u'[8Oߘ&M{:"鍝7lbD%ccĊ~ϣ.~aX*41pSuiJ"0 -I OhpWEW%I$ŶmBATU#-50i!\!7 /zMg<}oD6i oÏJ}#H.?B_4]w/9?`d@A>qnM;&)L R˒yy%zFFEd0<_ERB[[ǹv0-wSTCjJDr%_ߌʀdH7qa$H6B@t!s>)o9H>3IO]ԹUDC5|CJikk ]CK6Eطp- 4b8D#FAѨבN6nbym!I3ϭf׾RSB>exU9p+\kK~2 .+ UQ`wشm/}f}\\L`ȇa.J}#|}b;lܼ5G$'a*R<ԋ T疭݇ghݎB"T&@h&R( H>>JjH P\(R_'zȡ&Փ˸ R.=}y[l߱~nO?ր_` l3А3qES^fLF~kkkbp /#O-wձw-?ûQ JD蛀K7}¡xhSɗA"|B_O?=>X,oGO_S^V̝߬߿#u=t7Bcǎu~XMgsɤt^h^g()zƸpsf^گL$⾪."2W`0 _@ Qy}\bb^2!*DX}YB466'^x`>߸‘ HH?~& WIt_;/J"dLX{5$úȍ$τk^A,nkBra*QO8Ycn43S^b@~}'*Yz~8HOq[Kw cu% 50s,'3#/ 4l{Pqˍ7/.ʣ7l6RXVp J$WBԵ?4}pu%T҆No$ʇuG׹;7`/OQp8ʷe˅g+=N~^;i8>`cm/mɐr ǹph S~/ sa1xd2I$aڤLj\$ߛ;.YxSRB>).I^ߜ@[ۭT5oDxo$ώFU~DCGGe5͸?㎛wL1S^.u>K}q7&/47 D d1.6i^|PCdjPO좗He%g_(0uK/^Dċg:ŅDZQ8M萖ʫkf#"{X??,qEMg#P(M[zN8I2.7fbs'WՈpNUgEi!+A}.k*>)˵G:ƺ ټm/8C;?{o3e%O%eqX$:KAA*jߔ0ƣ;TvޓA4%<"-ՓO`ێP:jb&=!>Ĕ533qpwGUķſ@J ^CS鉸FK =73t7~2k'o>q }&2]"\!(T1Cph,:r|T\@|>}-s~4\Ľ0?jWfIՄqLl@ 4l]-,j! >B؟:ʗ NbB7"G0CWw/Bꝧ Ɓt8|*pO p75fB߈sLis$|6Lt^\_\_y$Id{OO8wO_;~}}1QC6CKZoD^F3օuI>FXGiJNɐ0H4!_%D;y?,go; ~- 3n鉸~S]9S.$D'Vڞq^xW/oD4mQEDcגQQq&TD 5=Bz{1J$fLetaуcy|b7ȏ7}qoBH#HD|7H חRuBVDr8HD"HSHO'7+#'pQ176H$%f'{H$DݔED"P䆨D"H$4%D"H$+iK$D"H$WҀH$D"H /H$D"\AYhEqDD˅7D?^"H$D"xD"eCD"HD"H$Dr" xD"H$ BΔSWH.RH$g1Dˆ7D?/j*?GbbsN_044 N @Sc01~_Y ?_Da(Q5 )p8(4Oo0QKrr  ^0 N7 w {׉ 4-qqL;hc +D,߆K|R荀(Oɉ+DݖP9'W<MaDE"osNpk~")Z'|N)tTx?"j8^}ßD"H$W>_@^AU!Fރv5XܺJUʼni4 $Smlw@ٹcK5 "j/KF_ۈ^74=N i;o#CQl=̖8Oe1 \볶0NU6r*m0 :FWXPakxFgshQTKaM*)6w;jya^e4{sAC*DZq͸<%^u'-aa(qvIek2%Cmt!pVga1#24SaՍ lFy ʲ*aJr+&s8ըae19!fzm:N@Vl Sqtެhr%mϘXqXpX*rp߾ScMashMo8MȎۘ1>Yn^;2QOZD"H$/~B_CкVZc1*Gc`iRU>;_g~*b\.[[[&4|= .#EwiJA2>dj:{IgGD!QxjN0n?XVo3&C呗}<\00i9)?ynbUm:: 0kuC%oMuU2S!&  x01 w`!%Fc*8 s^szOUU%GSRRN]]]#F}|>;ck[')ζ}>t!+C;%ΩX7~^vC vsbq^ѝEN:>߇g8ֹ: _}]ŶmWM>Q_;ߖ`}m ~B._}򹭮jm坓O~!k'fųwBtq>|>} ;/ޯ."G|Fpɇ# QF )0TӲ?{za_sh}3I't0 M'L*F E4uZxAJ &'IJ<. hLFc ωͨcgƊUtO[PgMq676n;Bذqٻ|wqN|TWo :(DŽ;x;Bf҉7U))%'IZ=*Y J&,kl91!0s- P5( 96^epM)ޫpX< *+lbpþ-:/v#>X0b8RTmAec2!#֩F[ *7lj1a ˽kGZ> ?]c\9y6MX<&wD ls8} ^G8fe,X]a1> 23LYdx}qxa:׎sM ?}@˷YjFGYPesh+1>pbpSc'ot ŃliK0./(Gk;ւO!#%cB _Qj e2- CHsӳH2裷ښz:L)(cċ_zN[#Iu^@(}#ulA@G5X-5'(!2ғP9Q㭨I'nA?юfjjhvH X`@(5di њ#4H 5 ˭u#쌓IPsUAæx=GhId'?X}- m4Ғ <i;AMQZz21 GWi;^Ǒc:A23D}45ICaNwO$5@0'yZNwYgl,Oа8TGmIz2AwPBv7 5Gh8َNZHvTA8RsO Z|>u֟ LOƱl@5AJ@Ųq&5= jh~ũ56"p a@3i=BC~5,[%4ii(t 5DzZ;q勴SW[^$lG9ROKMZfLN64/l;it'LR*}# 43RхѭLc-5D$2B/#Jݑ#o J PlR0|>E]&'hlj:gARMIt{::o6H=Ks_1zU HMކ #,@UpGO9CqܸuOx8_\xƦҊ6jo;nn}Ҁ!mgL(w/$w?t%39 )+prTōօw[~s$ahﯯ({5L`npKm"*N) +)'EkaR=*[!-aիtm-pܠ겁^:ʶz<1 Ja|"t*l=0!KP${;)40m#RMaM ٙ6Ui7.N)`4l2'6m"ͮ I6ҁAvө0$ `4ڠsBn}zqBG7ftI cJT!{fli0}U6*x\l{Ž@Ǎk[K1ey , "*FcS*MI$_nT͇^˫7Psp"8\5w5no#(ͻ_ck{@>/fDʼnٰ$b/ɼWS4>iUP,S2{B1J$vX' /`uNxuoKat믦0׍H[VֽFuscpBUl^C\׉t>t L%3U:O1鉇pBW}|7+Wmt\EGBh1U96^ɆMh>pO3;k4)f\]=4XQ30{LGa:v %k8 Φ$ݡv+~Љ9t7OrO#k_Ý~%FIfuVI{{]M5ڍ^εsRc{ 6=33hLI֮cOs;`{"f /;{8v=g30Цn %*\3@;?æd)szz OQaJ\w0G1sv%v8~AH~xlq;WŵĨCX+7ݐXq4X˪wrUg3"/@$-{S{.$=tvb}t}4#D `ގ*K/Fjmq+yL4wq!MH@5H,/;TB6˿aR]' E' O4Z,&]W L g_񘊦Þ:^9 s{y"O_yzƙۤ fY{XtN!ldÍ1=:]x߳41EQxAe?N\<ֳDPqcSg/bFW+mRUK*gƋM*CFf%Rƶ=Q&e@wTY&T2)+nu5|Ά?NW;uƖb,*f d0NVܙg)t(UP/0rlf;u>6l^cix+f>7 H|nFxĸ8* :V8;_ɼY鹇ye?x#EJ^IwYl{֮LׯE9m?ɘ%19-k)Kz}̢k }k-%12K%wR> pR^3ô6xm~Gͤzp#xXV}saG"آ/p,,-Dk;@} (>r4#KSyI~|ťSdb1gYY[T|k.°s1|xyG3eՌ*;k1! sոhgxYa߻eLk1]Y]03sdե_(/YɠߠX(˘jS#za֬ϠkӨ6 #J}?MŃ7Tß9ê]AgxWT%jX yg|}!߿uDTWW;[y6V'UεQYW~[OY=j%4vEv^}?Y'u(ƍ,!Z:?ro*a~/UUTgQBm/UQHU4*'1u( C-<}-f1fس_ZGN`fk$e0khؿqk딗A/W1|(2uVS(tv}Z SFWϗgh0J73qƍ5Tŝ1.>[RQ1q|*')NgҶgW0#_/iOu=5A}B >h2 }LгEØ^I ]U'/A|n}-3aznM< W$zp)5wCWjkY6|}~t= |\TFLeP_\kğDŽy瞥ϏnV@A% L2~>b4P]'ad1nyu\=(Q!E^~~TO|LI*ds*O57>i@537' >LyN?;Cӽ29FKxxu/!d3K'|A ~W>f*CK㶕?%nKX4Wޏ2ΪzftdT3&qo~6pyh< ۊ$3giǔbD[d qT>ɛ9b0;K >PKv+l"wL>Z11O.xLs*o|6%M6 R"#۱(FS׹"fq5E,00{Բu>v uLnj(utuV=Cz!&Bxjs> f, xF1ϰ{6V¯]Cmظ}/')4٣LT==A[cLFFhXshXn7$D^#5'IZIbZ5;7yÍ ISTݧٵukPrÂHLm{ټ=NSpbfVebS&u;c>:`ʒ1DN l}Gꉦ9qlU~6nCC 2^L ЮlWN? -`P"n+]'xwfvl$']`ێ>ŀoeVU&v<̎i<2m u f{#7nPC ,n j<6a˦Ԝl!cfu۷c!ZI,^:E,.fӏev;'tOyQƐ71ch{5=ٺGP~BX#.V͛[ߌS0[nP4]l}=7vsREa-=tXsnYp);;9X_OohΛa lm9~-`JIfBQ8c+:ș^? nYHYX4Zϖm9XsZɧhԽǖ]odM\;,4~2F 0vpR}X·^o?Ppvkll Ϋ9i;l`P}-]Z"T@K$v9Ѩ@04ȫZsT݇Ԏ,9ՔdvH#ӧ1fSp!)DRbB2Mr;r 9vh?-j%: ذ =:fJƒPc2cQRJ'qk/kMZV,Z\>8&-pXO 羌xBg఩W.>u:^"~PCDZ1ĺ:莐 GFZMV{㤤1ML[Eutm#Z.z᪖X3 օzm$. 0M^ܠgؖEGk;3qc]vPJ4-„,]%N{w {hk#bE6-rK5X7mhXS,Uz[鎈L µL6_>FAlF{hoa@AEwω:쉓؉GNֶvbeuFh8.Zۻ)NIsg3mpYdkyŻD,H,+GӉwwKa~0xW,bt5ӓOO1v`ϥ X;K/9ūeJww:Pu7Ug>m^i,ƅ%jXv3}7q uk= Ybk-qVΎHNFϟ実l;搪solʼnvxq7vHr"뎒y,n=]tF '3#ݴ 4pΨ0m"Ytho|ThQuϹVN8ёjۿ;7'A(=t{P^AEpMix3TmV53;^A<sc5c+9#7;ޖ,<&~hd~y6-zLn; WF2rR8Nٌ?vDN9ГBMU%(OS/{JGDg~MX}+SYk4zE#POA(mQǴ*?^=Љʒ`I6]na +4m~rS g*ɰxV;TtS083a:S !-MJQt CU64RݱEL]XjxcĠ!<.},z5ir A]'F0j k~8" ;05o؋[\Uf4Tk^c=Q$aw7]>{BslW_s[xoP>V,E ~)^{o8sT0ϰɧhL}K O2X` 2"Ս޽spox᠟md\+_W=?4U7q׵nR 6ngߢd̯R6*b=Zln&7CG/Z &`;Uxw_ qK]շ<[bU_ٕ/`sݰĺUes{YHvt7SL;C<7 |s!n>\1aי^ϘɦJ:~m;qϋ^ׯ71X!;3ľW ͌6\uyz&)D3=ӭO_< yRj&)TT zi86y#_0x,eX 5K>΄ Uc 1/ǘC9O斥߀6r"#ƣD14n.fe_};#̡4+3[߳i䧨FN2?r@QXa{UOoUX-\?~7[q/Hꇚ#!_^gDʋ+Yw[ܕ0q/䔚/; E6׀o;y.%tl6nN"'[Q('հ9yɰBia· G4 IDAT:l]T>~FȾ>珂Yh!KZPda{*kqw" хĉIq$9{/Ď^ Л@; PC[HHT;1|k3}>ΞWTS-'֦[DG֖"C,+F`mTvQPKur;m *2őE]C-.5m(RK)2GfVРX$]ߨvzk5"053QA8XGc@90+먯!xQTջpUSe$R<q,jg=֐-ƀvzȯOM#Qa~5S][CU)pJd?**갅FEZUxꍄujQ'kꡨt"q-*kh# UȬYWMM~XqPS@}-PfzKm)vQ UUSU_ 8D]C5Ÿ`]Ȱ@*֍o98@Z;vQX\GډBf@څPw:7&O(E=%Vr"Û}Zj\Blz Ñ]C]C#UGkֈvUR瘟J.jxma@dukp5RR߈_Df?$A6+TޤS@5zch'!7:kw\ UZyh'FHocnXº1*5[ǕgAL6}yE٠!K=GۊDžk(H^tӉOT#]Ms0¡֟&NރdqMqINXC<8{]z[?۠&_{u|6ŀӡ/!Y0bB=No}@FvݞSNjf (vn\vzt5˃_x//4맍gh 0j5iw-Լsjt(/5mBګnz ӱ夭Hbh5IA Dz=I7!Dkǐ]C7ki̘ ۿ#%fq)È0Wȅi G' 40A4gɲXcnҙԄQTKcŞ|:'AƑDH,YEW;)hU )We(tkGɹc>)=5KA䡋č/.Xm(:ù;{zNIt{Jd_ `R)c|z2s$Բur"1΢3"uro|jαp6a*H( bCF#ݓTr% {.> lZs $GHC(K7&ΡfrNصRx` VOCg:n6u2r1$u 05QCqҗ@(;dm[,f?oGV?>ml^ 0qfr8\tN@t !ɐ-#h-qI=G.itUx%E$ņSyW8{.>@:5F~aѽL֖-zbssXMo%.!Оݢppi(R|%ދ@vŐX?rL S# .BV.Iҧè=Ycg (Ϫ5@L\Un#=-LXB;igau2$t}#'&u#vVh./!1$uuk_zL-ܻyzV]8ME8:m_o%tV>=yXUtK\Я|(MgZ\.5p -Xj?9oI\1hqVuu[Cs򋦶hUަƛgnut"x6q45Ѷn8_35&]wgZ>kw+hx '7J]]ݷzQ# 7p{`w#l'N!s4JeY*iw4)Cz`Q'ӹC՗s@ѩ vтYy2>h9W>9SO #0;*˧iTvP^ZЁ:Ѿ]JM19yT}3jɉQ| PM^Q%$&LKG?3aPRHdRG%f'<,OM!E42a"b1 QYGna8R&k~jsr)o c3Y B.\O1 /P#rTROޤNM?HMQR}QLJM/WE!9yE421l(!\륞2q1A>aWɽKyAI(uR/8~"C°oR.5vˤd|vΥM>͇а d3GPV@ΥR<510C 4PM~^0qH (%;'3#Rۯ#&/ၸ*/Ir$v bWTQ_kTQYUAIqt _4ňj-jltipO;Xz[+'#s%*_A}DjW+H416aqLE;.+=b:QI{{?ne8{K/XT[bN6dz?AUF^jkcZg2c\e OvtŇpZ]cX׃6hZY*brŇy(xYsZL -~|ZkTۺ{f1_I?jwi~C`6c5__x~̷yY7:. q}eoxۨm)5B/~M->~|oԧk/)ߺ(,ZsK;5CxDK _`fup3*=u J$whD"H$0BzdG%nvܸNH$I[@D"Ce@r]"!d/H$H_jDM$D"H$w K$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$Bl6R+D"H$D a2 77W@D"H$7b_fŊo2H$D"HAed/H$D"!d/H$D"!d/H$D"!YD"iS0[<0\g.j6vU+ G`0hL;+Dxp:<`02 &+ ;OPӎc'2G&`>D\j04 z`7yMkײt!ѽH<VhA>aCW86sCLLߟ j+,6gS:{ϖӗ 9Ȯl- N2waӁL<1JLAZQf2Xv Y?`mͣ7pl]j>`!ԓc=vg,edDF'n2j~6kM4 zËnCĦ8z:~-bfR9;RgmǐIĬʀn:7 JHݤTa]:'LDډM־46ӑ)p:M`'ixRw׾gNnSq6r<Ù8av~Rec3987M{3ǐ:?ڨ;evq%.@7NnXĶt+19J9s#[g pcn5RtzT 艌 Dž`Xú+8݈ 76LGvEx=xV^ bQ8.\}xG㱚omҋ_|vK$zut䛢koL6Vw>s_yƼ}|:c9x V*mf< `üY<\K1#1Qsf={7|qÙ-Kl!"&SwzgŠ8gaNX&8M[.Q0Ǭ:CF &f[r+>XuaPpp݀5ncwﯥ`Up93iƘX.-CT L_0l џƜ]zA+h6Bz';:NF}^f|~NfS}.KbsQh?"sva)d^Ŭ 3^0f1/9[q-TeaG )Mά{Xl]0G8JGݹ/6_0k""/L>ۂ},V*2TE`Db&U~c,R,c CF&DU/d!V>gt4nv էx~?mQ~2ia #0YϿ>+g!bNJͅ}dE!}ѫc?3/)덈lV:m%$IDΎ<xN;ٳx_(WhL3~_flV>>3 #iATgi쩈bD&Oz]ٶˎyP2#|4K\B٩L w@vha/׾ eA);3fs>Q#11Vc!hdʊ2 ޗAI0z(79F3Vÿa]Q;^q*[֥ٮ= 7)((v\pȗ|K P Jz݊˫[bޖ -JXebEwg(^qb,"~Bl|] ~>}P֊wߘ&;K[#z?&7Ū6NmFGE\ױcU;W|,ޞ&?EVګb@xg_ i2|(6(w:)~?H|K!Gs[b¥P/dѹ$ө{4֜ZAd.?7Y;HΪVʏ+⧾).CxĂ 7ex_a9bǂŇ ݸ_?YI|K BbxrT+RyV tц(~"{?!k3[:y[uOԟJ3]e86vzO,?.p~,}_,U4\3C9+];鯋];g??]|l;űzݣcŸG+V(e4fLqG5w gDeAtM/.8ox*}4_)I"Q gkYT/~7Et>U]piߵM2ql".j[Ev;w\G>9_&}ib_-3~"_ԉm.%tCs~-"{76ic^x/Y}QԘh؛ukNY-n)>6@Ďح\`!Ѩ+v+VyHxOɒ`Fh19B2C|]v(O>ƋQ^*AY}YĆQĬJgR;_ߤT(«(o1@c>nNƈAGI+L|'z:MkB#H$6rtᑟ>^j72~ ^ٶFK=8;@JK( &d~ѧeHsdG3*Pk$wV2팚LY]T}{Oʐ&0_/9g޲CPOR1s%ʪ!.<j=/_ƥ o kG(~-;c8%@>1#x" 3VfS^]Bs-:7a${((m@FN #[;>׷[ t%(~<$1l0zŲooeh#ϽbmC 'hn*c '0,8W M_$lE"e`o_BОuS;RG)Pw73GW78]^"ecGלÈV2@/֐ #๑-#lK=<3g/qps:yèGct0n 3ʯPC̘yNad߱5/_?ٲvMHЇ7PR}2$M\ȯ6~ٯE9:#+j7&įZ cɧJ < Z&jaqMjͶVb -]׼}}@i(LV8ۜ /bnz-0̿B#H$V`;q{#1,->BH+ttX0!1L2 n~uËYSo'F͒UN.NϢEp$<¤Qژn $r<@e9:镌;=CXme\/OXdRUZ.àؾh)ޡ<4ī6ɨ>rtmMwP1ov1")@+T;-2-ϝzjnUOWj P IDATN`"MVp{~_<< ԜV2.'+sߔ:XBQ_^}G>gm])r~ښpy4ǁy;=am\+9y'C rzcZ&. ag} R׮ף+^L-jΰ`A1=|fiJk.&ݽ5jtRKάL8@_п|< ogDWV0,CTusOrW-Mq7CR'տŎ,\zS&ӿY+maw) c0C[ ErP-,f/}K^-FJvGjx⹟g. D"HVe}oG?GлF-*5}mkxq Ͼ Oһqŝ6zٓYΨ彟ƨvu(?ƴsظ7ȉ|k A ,6ғ#V8BfE3uP flf/G>`M}ZZ -ϛcn{G3'ڥhfg,g IN V#w.al?st1 W"*2G,vB}{O&Gqq`2 ZW302<3xpKjTva]i>֋Tvlӧp2w3x~Z0aۿi=ħ_".C[W#|ǹX8}w&ŝVC!+ߙ[9?}̟ӫu f'ebCf~[̠i[?5R`ks>eRWVk06X.z_>ɱZЫʅ3mZ=mO`q_^[ygl6m?J}o|6C el:/ yC}bzM_W6sx=A_0 G/~Tīo Fwil>>\O[QqRS&vCWwHZ5śOc SRku%wk0P jԅR̾AXc`GwKmLf `B|\&hnBi9.8pԭ/"|A(ZW\2J v` o\Ft4Vq:?)}`Rփ(?M^@\NЮB8s٥XCҝ>]07Z.dBlSpy$M j^z!&܎j;PWt*at; W0 *23Q#>I[\d&DX[}R?:[Fj ϒ_vr>ѡ- ?2N_i*pHOY4ݥpyza!v.!]UƲ<Ξ/ū+"16]W+8w2 O>F7.c}uϨ+rOm" eSbo:-ԍޱPٳY8m=x!zC쳧(qc6׷/FEy]Igrv`O BSZ7B٫ >Ea0?{KՂ0\NAdB_:[zW"s  [$zEtkq%̾~X^HAm`ihK(Ⱦ] &0 Nq=~޷<;K||͘2Z$v lpfFV_>S {%ُRؼa-!Q 8Pʗ|׭y"V6^xԋ"4bN?V-O+Ls]sN+A!6ţj١xb/B(^]f!+ 4e{]ŽY-5ܝ-;xJ'Cst8D " nu.dT[ &)~%Mp?O="5j2T=Ğ?IFw2l1(9MOOYԢ?U2ǓE=Eަy>xZ9FLSPhe̺kFt\-YEϻ~+NUŊ^BH{QѽD1PjldԜY!(R֠t6f)ÃD{^1Z ~tu:k5Dy񽿬jnV;T}1Ef]k]bϋ C[RU(3]ֳxm1ZvHI~wlY-pm?%{(&-;]^=Sh\F*~/FQʸ?=ѭ1He[BdoxC I+O(kjϊ??8D wxQ+V#n8;Obpg/#~Q\IMQCH<:%[Fy XOOT *dzia?CJQn9SaUS2|b̠}yl[ג0Ztf[ҝl*NcYu5'( }Iv5eVw1 _ hTW\ZS ֲ3-2gOi4C?ʏpb*.hIۮ ܋?r5;VI˲5XUuW#=SH߰Kkm3?L-׮p5[ē-g݆×ׄb F<ٰbŞ&[Ye(`S8^Of`el+ vLyڶ>yGc`ٛX)ؿ'1n1>_)52U9_ELb"WK.pG*ÙDv6,N?A To79A􈍠^K¢|4za (WsՠN)^ם(#Z72Ҫ<@I aTgna [lW{bGѽ+s,j \{gavj ]wŒ^Ǣ]Zq<=A')H;oʣ*ңG7|B^pJ\ЁSX+OdڵJl/%'3w>k(nPsX> zZltOž X?Wr~:u#)ƇCXr?V2-h?ϊy8Vaўƪ=u]'jH}~Xۮb34$ҭSY c9c$1;,\e?4g acyՃpM>;(XϜ%p4C>.Uܣ;Tf` U[4[i:tLJ"Tź.`˩bu =F`L !&J`N[٪.ŠdX5Kp8"esH;ՁC(8xjK]_´8-k"^2k; ,#Qr1h(ɵjmd_{z'1Tv#`ּ̜>3g0cƧrBl_1yTG.5ܲZY*H$6Ʉ1! N!uPwY^sc<pm_s<3ԇ 'i1e4ݜؼyყio>};'ӫK0;X;gop:&%ŷ>mQ0WY>)wO'.gCI@N>~xS%+w3xgo0w6& ǧ.˗L~_<>VkKqgH:ڪ9ejM_3?d;I,_Ͼ9ς?b6<S9.]i<{O=ۼmܑ2*v-cm QQ(>ϙ;n_0JeLR uhYe+R?,QzuKW4W<o,.pj'u"n3\ڬh^zǴ8rb=wNPOnfl>6)ec_vF[tUV;:g>_.Xٯ;VVNj\).ٖs1swcCt\6vsN.cBs{O0WX6]h,<꥛K<9: 2-Νc)dӲ%t{~44Ur m>20yZ ;u0¥MWPkw?YHQMQXXx 7j̽\c%xLt:DZܦY|V]1q(Ul^3pBb0# z`ض_Q5 cF%`ua4ˣA,NnBk˨d%m [Hx>1Qcqܘn+IȔ)nX,#YE~OsTgq ?OUDt=MeHg]ŹY~ 1D1xL?v@陽^sx ȣObUz +EFqC?ۃwb^rJkE|76JNbMPHI(݃4F[X eBbu<02N I!VV̙KU`ר;xdBLj ʋl\u6{~u*oZ),k72L审]U}Xc q1(S5.;ˆիy$jȸA;Fv+\۰uۏQ\/{;ftNf>"qdz 6J3Yr {NiCP{t*}Yy%I_ņ=(RœzT&m4 c+W'#Db=Hb4iVT =GCihc[VjAK갇0Ω7;FVt+m2=&7a.8kVѩRۛZ* L{5O+47z4TUpOST\\oL%ƻҳ?O<䓗S|2H$2|+ܚ=Wj;rcվmxNׅ-^uFZuvPsd=F,V˵y‹KgnrM(%p\ ks`ǍS~yiחhd(WS%2V-2L^m ouHk2>nCq-0^[b4a\+C꿡Z0[[ e e4L oPdaNںT3F֦,˩?VrC.PVPvj7㫢m0d[D"-tuڮyNnvW\{MwPJz-م;3aK楏ݐq[2Bޛe0|| >WlMdJ|a2t5涺 a^ȸ M7*$x\ KSeh"VD"H$ !xD"H$ĭ|8] %D"H$ov- s%D"H$o5FD"H$7z^uhd/H$D"|9/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$,Bj_UC uknS3H$Fɤk0M]Q^z.6Ajd/H$$ln@@}YubHZvmQWD"|h] [uYb uv:;zYm)xoMxK$;z.4ߚoM[Y}|{%S7ڢWauni[KWɉƾFŐU F!d0xp'ˀlljU;e}ԘM6š4qf/a!IՍRUӱ@iG Yբ8u%s.fۡ$*nJ~г ;F+0PjesYf3q)K2bM* BEIlM2vc:o* ]<&>l"Æ IMmf+7K{o8Av3&Kw\poPťދֺaYPU}1~>cLq&c1[D{?ۇwi[+{Y~a&.۶]v/ 3e1'OӧTax`Jg.Cϕrֿ+U_+b^`W;έy~ckA;}93f% TRW>qm3[4FNn]%8LL׾^d ޚŔ/N xw`maX9kkcKڷ_򉁔|7?̳(*9أԅ_?Tnkg<CeG0/t2ww¬^ IO4cXDxڸg×OSKBqd#Oүmm9|÷w[e!ty ̯9/Qȼry3r֫4.U Rv?7e}$L”/Cb-S1*$>Cxf>b# T;pBa]o.47o"K0,4@ÐEsd#=fh4b sHOސrORI-Vɮ"[4[ZrOTD:)%H_6i7Rt|T)hzz4obXbҶcRs?-9~.r4H+^(֖>\}IbY f/\'ŚrQ MR k MۛhkK7--!lj:'}2]ixiOs?VөeRRoJ,g-;mYRRRsDMʌ=.-3WqN_'K^o,إ#k9?,-e?*T^{>[^&UܢMf?Hm)f3IlZ$]= l祷{֒*uƁ)xވbvbKɉR|\RlllYMRF zh/J )1wvݿ ,RfF7)KOI^"]OJ߯/,n`tR):e0lO!],]|UJ0߳w- )Ә9h. Y)KJ;̶wӿ&2%!ɐ2\U']+%$?`䜛3cGI:b4qvĉs]˺%Nrtb}^hjCX^CҦZ`4 (ը5 #HOH0nwYt7GMٿC%q 9}sP: ,?GQ2/"z,xWj!}"\]6oFDTIw Ɉ(vB4jۂFƏ0Dh_(h EzŸ4٬F> _lr[VQHH"1)KnkUбPz6du%7UҴR(s\78yVat[{v[Z1v'Ji\DM:eb64QpBHT'I% I2hܸɜ!?b M3l@BpdШm3H=> m?<_&Lc"qs9>K֤rK^GSiVEb́+RFcgI,9_q ֊p|u\p!_>E60ɧ5r8?6W]> c:cWfs}7ߐ+o ӷݺhIfGvl =M=y/gʅ*dV!_[Jp{6¥ Smܰ ;c͈'Y]LK)=6O^ƻB/Rmdgh;;7lz<.i{[A:d$Tٺ6ZfϞs%K/\HzڛK{شlV%ڐXA]乏?ei%g^ֺaK֙:dv슥JxWEجYhܸ1Ṯ+Cм\N=IDZ , őL$sQ-R30u\ 9W7fS1ds:M]EɮOhEoe7gj2Xyh*)/Y:tWر;fV1t)KfC,]Y,yhƒUcH2R19o#sf,DxmPԒ BR#RvYJ93 4bj5fa*/3r3Z7\?!@~|!d>BBEHDU%;^!_"!"#ҧrs;M[ŠSv䛽޼vBBU4ۭmHˀTvMm뼚ƭf/ Oh~4?z{dtYW2>۸!Qu~Fafx-,Au|7Ӭs'Rر]h:L%$3:kƑ[4}̱1cYDl!k/*ã*u(WG(}{3hH^hV҄^/38g6 -ek>qAÁcJ3츗j¤?0E#5͡ |Y.1mGψN-CV*/by}JZd7 ;}c,Jr2?~$ Vͥ3d[4wYF3φ՗F*ck };Pŋ_՞L(wZ'1YڭxoƤo0߄MrȫpƁVk8ǒXh6MO+/BG sf>&"(R4w]F|@5!+0e@Bf,JN˹oG;lVqp .0kjɱ~٢%;6m[f8ckNٴ]pmKrPv߆hcUѴUyvʟŭHA2ThGRi i.]S"Y¦Q};G vl"ѫ:ʥshOcm9)V,Mfã ]nUQK=ӯfK Ҭ9)`ɢ (q|VqGW0Z+V,Ow io7@Vx3jxzzFM{ 55$bdL֫K {œ^EZ4!8_!V}{EnR,D֍^Oa*Fեֳ9KRq $ͩ,ԫbB[ xDth"ܳ8w.ÉBYxjįde5G"#{Uj%m2j+JԢqxcٿ HU*{t*/*ՊQRd^=Y !r擛"2Q^#V$av2h@I?My+PzS~Cj}>> ]p!dffz#,{'wƪ͇9$7fm$hQGשgwݜpױz/KArhLfeĸ?!'ygBʎ_+Ճ|9YU!ѳyU\̥mOl9֍9\end]Ő.4-+d\<[ ti<Һd\`բ8socŒM5Gu:翢9"n9kܘ<,5r,u ʹmxjk)U>K֦S75WY7O5FɾVJR)XS⏟Ǣ^țkruTaZ0V W0^72&v,p!X,kГOzX^^+?*DvqRѴ vs~t9OqGs%цѢ()ʎٌR,Yʊ\*g9z<1:[F1c^9;HƎ␗_}?˸G^GBa3D۰YC 2gӼ2)~blrlº.*(݉;e/xn /f7n8ZPxt̖_dȳTş$8{,YH!4vo6G0d*РO7q ݐ2/0oIѮĞ|,QK]޽Z] Go/OVyoxЩ͔j5/o퉧(mPAԱ UGzڵ8¸65H;3T,_ zw7-d،5:);Zj[/(ϸlßgti3ЖIơ|s )p,ɓ~j5. SÍmSx{o(_ܷ 3)ݠ=%Mń~^TS%p _2t`TH DeM$jXRӕO~Ĺ}+͏yѤe[= oo7Y]-4if#;v`„Wea1u^Yg-BAE᜽nd6cZ";ձ ؿ|[Php 9agAϒ7eGMVy}\Sm_޵S7TGOg^o?fh1{5g[M|AYYvЪPșZmNJy+Hhom݃K/v/ۅNRłyd AXTo|3{cŖ2_jB)2-_.ޔV߈2Q&l_]e2+Ѿ_sbߐ2̨^K1f,DEZʖ7e`IG2 T סdbqDv]kl8#FTőG?c29**c6@Tm%alAmhӲm>BH6u[1m(s&}Z᭗'ot^ <>bC䑖d\]Z*k5=(< T-PXʗjkjx.˂MH IDATr&5Hٳ})jH&ҭjvi/|9m%RDy.V![@58:7D4}q-_N]\3A|[D0<bJ́96ш0Lh<9jV+qhwʵnGHN2Ztq**5|ε|E+¿7U9D2 s@z(Q_> LgR@ʕ߳hB xWCQ. Hh |CꖙB(nGki #nKV ./@|zR3EvEgYliT5šKsXReg[eK&RV⎟?!HK-Lb[Hj\?8]F&r(P E@fcU#˝YňUjټZXmrnAҠ!_aaYE5ٙk,lzaU"m27 a$U琷7"P\ةU-JC'|:ZexaMOAnMWV uZ.J䐁EnETC>3M8lnY,j4j|XHgB}d \s/ۜIDf[U R>KRjح1 .-d,[s.j%DӣJt.ZD4[0+sQp1xmx!keѣ^^Π[a`SJreq3]X8Z(8^B0zy|Mڳ1&9SXr܏g|fe )1Ĭe?ӿ +Meׅ֭p?lضt^ӭnϲIq#z\ _L)X2ghWA F=i7ֻٺ?=!SEʹ=n6z4sj-FҥQ|56Ƭi3Z7AHy5 OzX|h_O mNr5#k%xl@EF.e׎̜yGCBKc_pVFLHl]:k5q2W&Y~`mBGQq& w[x㉴(ȸt>c ޘ'Yr>a$]'_.gtnZ@7ne7sH-׍O!YzNX9y0FKiߘ9' G|Vr NG?f4,]+z/ co$U@!cLyl}[P6cIV|?UyiXBy+ Rϱf:*IL,V hR=^ ~%l"I8'`BͨCxٮV.Z*6hG \mjm9VC=+zdQJL>-71?cHEvq-&|N;E%ګ"c?ˠݽ+J!5~ u&j(\Fm_j[~|}7k(LZ(IDS:UXC?$s;  R,ϫ# f:(< yZ(7:O`y;馜TR{H4 = *۶m x͚5qՂEMxk0X}B)-ڱ9?,ec\LH#,uϠa<&"BEJ>=-b9{JPG5{ cWH s-fcK-5[ Xwu~ZN)D֘A07f+Jc,a+KdMjuhqF C˕F.q hfN[Ȝ .'fT[oؓ<ּ,ZZO{@iɔk2Kdf?q?lZ5}cZtLY1iE܃`)3ËX#pvnjjZgbs͂N4. yiQnE?FQl0xw=z4e˖M:3ƿdk/NR+$<i29 ^W@$]'-ӄӏaxwfh9{5i qdCD Qߊ]]$F8ndQh ]!e0fWRݳ]6L$%ȾjB#}h7ctvww'3 "<Ud a2 Ώh6*Up).\ K/AQ|.]رc ({Q -nϋ |0ߊ\J_ɡm[CY7\jhjIP ZS>U\Ťopo i{2Kv; /_{ي}2۶0Av=O]_;]C.w\x "!WcK@c^<4+ i]gRyW+ .  °M֢\Y)Q>yz,>UEB 9fQ5'""" ^| ŷg\p\ I]|k6a9oy滕a9Xiva^ q/j .BjYKAb{p\4p\4pƟGP#'_rq\pXiv?HWiy-o ;ws}p0|/W¥ .Pl\Ԋr 9}]43h.h.>B .BEq+-.\4 \4z]x\p5~~UI"OzKw\pa:#pg]Q,Z/a=׌OWKw\p!gF gPZqV❋9/qu7E8X["wW~#sB|'  .BSʕsQ{\NbAvss/R9Soڃ@΍xdSVy†S~JΗ'/?LiW蔹 .}bV\t/Ω? {N82L0B<5ɓP2"_Nzqa3w^O\ . Źӽ"g.'9$Ìx?ʠ&_޹{i/*8Kͯ+gPS{v7<;SEN]w/'}t⤱ߑ4>쓙 ?qM#UN^ ʼn9Y9? >*/S;\p;/j_@~A8x7"oKP>ND>p!T0v=H='* 8DF;6h9q>~{N8eʯ8xW5 .'uZ=<<.JPYnܳTL ;*nA4y[V2V\@VϞ=|p}AJY0X$+r;I,/M);CqI_qLŽ]p 14wm)O8!_#/~)->;Kʃj ^E 8釯kc 3Z-ycݬ;yv#}9'M9 BewމVvڔ-[NRn:lقhKV;w..\K.jJϟ?_N(:uD  RUwu/r4^5X"bɒ\%^GUz]p҈O6W" -,W ;7btmzPfJi& hKNB t& w`*UKX2OHGJw.M- @o¦HH»%yHMFH_:8M|Xrt6H?ϕ$=nϣ( \HSdtm >-Y*Kٷ WCt4-pp„S9߿?f#44JPw̙3ׯ'O$99Y>}iӆ~IעEZ* 2hРBzH(p={.,Jtp~}v Nd^)7N0w`ΝtO*yE"WwNi4#Ƿͥ]_:_WtԳiOSᩲNѯ2MZ6X~?%ӭ\EHwW㺶Dda8=WX 1{خdˆyޟ(U$.:7ɺɄէ"%OcA m| ;vp5ŝ:ȮJxO&wU3-ymJK׹]lAג}_xv{qUVO' ,Y~UѳmQ4A]2aD۷7:m;qDuX/ཙ{ $K"ÌٻkzG۳sjʔ$K$^]6ģJ\.1.R.|~mZlɂ x7o*d+Ff,/|B=bU&[g̘A*U9[~`yƜ^#jo ˗/b&Lp_{ t~(}Ѩz6T^bθׯB{ GeqG;_OéYG6vŐ&$zK(Ʊ8I`lԑ!VLJ5^^'R c'H/< Z씬ޔ=yvVlhѰ V%oOmgHU>Y *ۀfXq9C&QK{_AA2aѺUmnMY u$2؊bsB<0ƔMMٚu_|mrD1VujG3_q)w^ AvS<ҤDP ۋpGtt4Æ ՝ʷ k?̒%KHHHț4iBll2##CVE!Q*G,t@ ua%|6& fDyWաc*Uޙo(^ 03d&Jz ]k'H%>f+myoRWLrob'.\q>*$WCq+%~~:2s.q"\QWY.p ՐZOzFt]m;Nޠ)iOݥs.׋BB5#R`>{S<ɝH U2x*{r~^~8VmDDd| NjS6 y. vJ z?y"?a{;Gy=?GD]:EWRvVmۖg inA -]KWgL}\I[7ybs'dѦM)vn9Qhxn#q_&>8gīJ$p8aDDDиq\T>}Z#^unٲe$&&2vF}N!IѪs;ԗwGw/փ-뢰Qdt È[pmkoVڱmoNJR3J'>4ཧQ'>62nkӉҙGtF\ƣkӒ36I!Op"qədsE.\Ih\dUhځi21^zv3c: bNɌ n#.m{gl*ee%V$Q=ekg#1-6 `c]߾YVޱ̰:r#%:vPҺuk>ss)d~۷W^wtMv'x7xݻ>ǎE;Ki j1Jz2xnQZ* nGS#a(*Y2KՠR) 1^4}=}_/Ħ-ϳ}AEj+8ń١jɻSf2Q$!o.ifx%f%S /RA#Jkh!a-Wgc)Քu{k9kGS1͹wy)1Wf֭k[({sFeZR;0cubnS>f2 MC ;B 10ޜXLٚW)ߪ ǒíl m{ރ$%U%ZFWFick6u>|w2GS&M~t!vV} uT?Swxfg,%i۬,D+g?rw$_G{8ʱiל  q@5:%?Nfo'*VM,Ēm#?Qc'bԼ%t B(bޱcGoK!P];^ffY믲?Z#>bBRa+Cn }Ӯ4ȘcbɎlb`b= *E`_||CJpH(" \ g"Gf_}'^ҹ;~[b@`LG[ -JZ8t2$p/iգ֩Uk_˻vqye;&Piݥ;ս dj>'`ʔ)swb~7nj'NDy(- =^tlU}=-vBeXj9K"UiOMLS$m$bּoˆ w "5i<;SzꅜQa3]j >:$wTI[(,庙Pi(W|Gmeǟaw: 26X>λ<澋8bR4[!%1V1P+29]pA(Bq_ִ XuYfrg xK/ӎ0~$ČQdc[0JV$ 0SЧ/]ejcV GQCa7f Y(.eF4.N*#o& Zf_W*UˍKظ5vĘ1cԲO=\A6,qWS[;][YYf/xׇ  "T XPP콀 AE *XQQRCBO_6@}g%lݙ͹瞳aCOs,^U;NǕKnCvΗ i7M nyysyd(st˜疐[MÁ`ǶI˙0n%'=qmKoPX`ߋMoud9\Cjs[4$Zg(?^ƴ7`W?||>/'20ӏ>yhBqyvo|:ӸU+ eSo~+6q/"#_8;vl<2k֬rYS7^pgP5zĚr9爲~{鏱r;^|-^{ >zE /&|OSo+USb?óy鱋 ;[%QdFz(M2K~).Lxctej׮ALn<5HoASrj]jW4@xPlԮJQ%pI+P%ul.S$yƸU.鱏;5 ~oF`Y75c_bIʸvȲT6y;ӻGO_ЪQ[/X _$!" TZ5#X_Ņ\Ԉn VQS'5 O<8\[A2nrs}>}7 봸ǭt9kMۇ٤ {LVR?qI]ծ;Law`z0Vcu;O?緩Zs Ј&NGwX1?qba)Ak%Q6(Jl2{LSM$V"9YRDQ&(s,޿3Y/?͏({Hb|J=i5αH  1cǎe~/s*:Mm۶eʕVѭUDĿb@ЈɓVN09AOE=i"qFLT>+2Ý\6lMdpҨ]uEԳK'sGv'[pà:K圳\jS"uT=8<:t>IJo`DP| ͎%8%M6OMOVPޑ};lԪƋpt?˼D]dI0r?hР3sfE'jvNwq+eGR&g4xı*L(0䢜hw}_>XRԋFN=~!t)eC([VȧFjd2-Ӷm%T7k9P*GO{_9.HX"scDl`j5aEޫ0r1 V:i$9[PZDz,HX^+Gs%FCuJ3,nRkqS:FvL%Mm IhKr93GcDOpƇBC/+~UV4tסji%*}M$D cМyEWIՈGJAnRLO;\UW:H$P^j4M1\&^Y?&D *Ej]WaZimbU#el|O1)4r x(˿rE wT:SeYY(Ǜ0"J>fE1-6k)+ $\rC"4wAb&ͤ8+ǎt)¯ow:(JldI׃1PZq%Plr.;U,x6s%-Z/CyS9E5+a5G sӨ^V+ܯ<%ME+.JT"btyJ>_QSJqi^kTα~POUOV"Q;9j'Z:FK9ϔW!s5!uӽ>G|VImb/k$*X_ϱDE2= IDEP>4 %BNF9QxVg$\NEI@ʝ2pAsK⨈s,D˄VJ|$Uf+ =?Pr9U^kKA E)NG~s$DYL+ 5ZQVDn{aUh%zХT6B@ٔ+桸UJ9c-,f8zեB GxD"ż+)oZV(rSVN%P,O*4. VnQ˺gLQH$D*M^5{1M Х'-a_"ԃ:UW/I$D!Jn7^+f7tI\UT? -v y2J|i]ЋRd8_! D"HT7vFBa}'QTFp OQ(:8H$K}p 7zѯ^"H$D"K$D"H$BJHl D"F(gYB$ 42a…[ԯ_?ݮ]xǸ u1Is`&nkI$]bu]9wKjTƝ'K$@rq`=󗮧f>\Ҭڿܹ Gܩ)bƌq\z /-[tcH/~[\eb~rNdƈQgd”ߟp۪ 2/U[Ÿs45s:q+3푵c6lH߾}KZ*UUrZWBh\"&ts1U N\>YڀK3֬|Mp컿*e' ..Yfǽ[ncH$ `0'Y(mL&Hiy ST6撕4G4i۩#16nԚ0n0Y7eӰUjXp87bst:8$֘;2fpWٹxPg| /&OU}_ mM-P3mӢо2Dnў'!?+y6TNNi\ش}?u%l;AjKh]'wǖ|ZtlN"s[MT:a"UXoڦ.ZP]>˷u#& YW KpHwAtڕ"* ?&Awr.WqNߛֽYtٽ{7;v`̘1/tЁɓ'ʶmx"피ve@L@ -QK$z@TL;~c 14r_̄%Y[X>}?DBew{oEyz45tf$ɂyȅc?0|[VukSez}~.D9nT: d43oMﶯYyu};A^m5i@F0^E)d#Xh_M,yW]-ގ]ꏟeTO7y5`w;C^܈msY9:<~{[f[uSw<`oThrXt/{,'T*ѩ;P 5є6Mu"E=?}Ի86yDL[Lb,2ʯ0?E,)r cذaze˖Qzu8=֥Ca(Pn䯕H$`0e|=~F;?Nş>+`$CƁcԺ 2tDTk}|bwcҤӫ ʗxgT5i~Ӫ=p/nFtn. 4h sQƯKځnuwx}:}/X2gRMjժ_}UРp ~0>j(N''qI̺R2$6k4&0]y OɅWϑ^{|l≚iZ'r}viO޺O'jZ[ݜHϿ#;Ct)$: }{4>N>UCp?l#Uծ~?&Zo@"=1.'&x"s wm>d[[htyA9xT?.(6hv*.!EuVP&V+&rdolUhJˬ0oȣ~ĹV*'&_=# w}ÇgV^͛}Ĉ4jԈO>Ds$'QwMY11*{G/-{>?~πɬ&<\ܯqaW^_VZ=iڼ cz5[B2o׬?V>BSJrPor]DKͯ'V6hVطaƠo8WӲYr^ՂxplӋ5.> bs}و߯mtUZr8t,C,uUOM IDAT<=efW`{.AD+1VG|DJɚQu >&PDC7 U7M \\Ht'ru{ۓ~o4 7 _oՙfLK 'dL-y?\) 6\Ӆ[D^&WKM3w7'Hʀᤦ/⭕5fwፙ~gnj1W#Z5HLNeȘq<+LyeƍA$]!,kpxΓ!;f;VjpU,'ARDէk~r1U8[06!CG+ls8|NF/G\X+,|K25g.5Ӯ' lDM{Yk]NTޛ;`LLnegpT'dz?m-{=e^ץ\C{ش*J "]n`ȏ0qw^s .cDw3O~34G=FoP?.S(_MF6v3Sft~[~J"#e8ڀʶ>u/O>WHF{[O~YXS/ hsrjTKydOL7hЀ+D?rYCD%Iih\^UKfٚ)>՟N)Vv6ŭ7tbٙnkL87N@ ߆'5Kf{,'6cy4y'`ht/5{2BKk'{ׂYA3MWWrK_\Do}Y|pU=i+$_;AME-<{)x6_|}p=S /\HTN- &;)wڵ8Έ_Ź{Vg:n.xbC< DFh͒GM~ࣸlq-]]}\2s]ku<=J1f'{*Wx"-<&>D>q~f6ѬuN(Y{X5[f?vή?pov\uiT MiYڬݛؚiu&(3;iy~ N"G+ΉgړUshܶ5U;_S9ֽyj܀|}1'>wQη/x1_2k5-S]a3``VF4YTЅG^r>i+ފ4KBYx5P>cőcŕI\$k7(t |R<)omAӳ.o]E^ߎ\"H$a0pŅGv)'o$5ܾ?H"ND"H$IPiWn*۳J$D"H$^"H$D"K$DU%[l6+{>?V{EeBQ6THuH/H$U!MaWehp]z4N%iACﺊCxD"Lxh\CK*DE-=d)L({eP k!DDiHUK$DU , A yf7<)1,Nx^*-G/4 3%*bKaC_\$D h0kDE"5BhRXQD hϵ%y(8)=Я%MwRiQWI+Kdz'[Q{Nީs,h%kۃ6Gv5VE0dE0kċ^7Vk*f0͉UbɹQy4Ud] .Nws{ķ&z/* KD C<WmZH$DmJjUrDVʆS(QL)r_,Vaa(zk9]RMKZH8յPAIoB^uIR2KA 2IQ=h,J5cR:ZQ^\.MmbTX]-mb=.~j@ZS5tRJMW8Z8_D:Mcm#ͻD(]xt_afW|ܔcT1ZBb܊Phm_XhT]9W˺gLQWQ!K$DU @ C4>%D?|E/TnJ8.8i90|Ja KIѪ㌔VHeE92.2YV̮rBRZCIDC'r޵0u*J3Ϧt)%XC|EJsZ^OX#yլUH49&%cD(;V?%\^5%Z((p嚠Pt]Wq&PNF(Qsq9.αDV:Y^S)&P !^# PvYBαd%D"h]6E.pz[U,os cD"H$'"M*šN(fGYBӣUP"J^c:`dW3FF";=pg3:rIEWD 9Ξ]Ira1@|$@Uǐv fJ %D],6c[YlV%`J \CzH$<< $ᙋ!JY$D" ~?V=3bmƬ>aכya!Nͻ/3av<¹xv`qyk5 D"HE0]Ā-&J*v Qh!.㱙 ňq-WdPuRd $O:ucCF0{O}_B'FݯoRƎvO Fs0Ǒ[nq4Ho~ʘdc .߃8 laiڃt{c $ D;fͱFpW$ RMD" F Ƌo.f?s-̣8Lq4nws2Y>dؽSsGnZ m9Xu.'~7&M;~۫|юw>x{W$g(Ly:Cc5<:ְx#u?psЪ:<le`' D"Hth&eWkojo~߈~gwN炄}cOw9wF<'dd=$Te;H4'o'os5n~lcT}q"ClZVŕRPۃ'*UT0Lrϱ|HѨc#K&Hڏ/>ܮ/bg|./g2I@އ;:9,H/H$]1-׽.ܞ-X=b1c !b[;&F˅s27KĒ(| \ܯk:h'f]u~nͻGFښf)jGə&p룍 XE?G{ޮvdD"Ht?#z#qV#.뒻{=vzB&~]A ȏ傁w\{_eƤ+K 'dL-y?\) 6ۍ%n^ ;ZEѮp6,) z9&=6 Atp[cu.ZhHJNQrH^AwdF`$֞a/sDgRn0='⟎ٿzm7~fCξtmύS b5&/`Ԝ2׌O0q y; FzfTUs>}"I'ߦ`gU$!TreV%mߩT2_*+˞.;9p]%NM. ^Ί7t` O{tp+ qBKxm|:t(H cKM27y{z7&p)]G{hlsMuۆspUA.lrb:9Ԩ {Y Fs69wRM+6f&MWN[qele{%47V !ÝK [%? iiiYIIIb2E# |x'21 FL&$ԑ.7x0 wX,J@?~0KᏭàVeSzI,(xٸMl?ثG)ljŒO{om LְXT`'_0xPL4h4rر씔D駼ވiA]gXD#'؄x'T~WN;1;ssy1$&yN2c<@8sKTTT볢$Fl:Y6$x-QfjjM83^ٿU͢1x,~kD -b~Ŀh-϶{lϘύ-KM;(]Clrڭoh߲3P5lR@`JPi!<*E'뵊 |[Wa|,6sm~M]J=ߧ< wᆑu_cr;/~&~ /0b[W֊w?zfqw^s: /5;_zJ_Ԇ D5Wi?&[ 1V\y<2sTF,)k]"0'>+EjUC4i܅umƕ~0w]ya|RtuB6 HR{S:_Øh oh3~pbg)N8/@f_tҥN" ; wA#~IWqd(o~±4  Ҽ2o.)nnזy=MUhx{|:-sanv|˜UG>βYjs7c 4~R<א.llkz͈o]{2ᾯag]"H"nq-o1 f@IEzQ3vlŻ+T0ңAGt]ex>\x~ ϼ-xӒD(6N>s|">[kEuu&" r?<jdD"H$J3S"&4jk}Dh7z% FWU3׭p FSD3W0{^ dxuG+ed/q rw>Ww7+<jZV+h$"`%!.`W1Z1W_x^1h(]8]yejԤ.8x=q=R8TkK'"Q'Z@SdI/̋|i 9IB$Ȯh֢DԎb`yE\/ K(t)k)JI,8)+BZҤЫ.eHoTȩ}o)6ҥKHKɸK$ZFMU+*bfM^t)a0`{L7Vk*f04 Rnϡ)pZC"H$: 4'^ DN/̡4)ђK$QtSH$Kp bkyIKH/H$U qIL^uˋ́5!u;{^"H$DIyաjR:R<3zեT+ǧB+8:gJϺ$B^"H$C) r4PG)(*UFRhS"JI* ԥܐZ$ƪT:*lsuTPtϠ*JWQH/H$U\ө⦃yQI|- mU 7z%nÏ!*wddD"DB6Ę{Ks $rgϢcϛRIoCxD"%J]d5ޚ_iTNjZv04]jPjkz+T4D"QW;Z/pz0NbPPѡOz1EWqDVjz-PMoa둊pJ^>:䱨 tIS6tVY+Xa^"H$8/ {ӣQ[o(y9drCas,H$D(aHA(R+(M NhshsTH$D/N0;%)VB; 혧7EWr% b2s" Ctr.`0^|#<=vS\yYݖId<*`%SjqZ oo:_MZOӨ|x^ֲY(ihqhbrGIX"lvv om5\NǞ7qycXt1oN'[TX6b$sei+{q+\ī=2Yqdꢿi~ŵ\8 :/Atk?, 3 o#Ҙ9S!t }jg̛}tfվe>ˀj쾒7XwPKޘ'7/5Q%M |2/03 O.6^pE_ 0sZ79 AU 3\`>4 W.Rαd%}(ڱ-$T&f5bc1gobŊ9UYxud0!sY4}sOq#6Ɨoc8>XҹgG=KFCj]b;ڦPb"ϭA>~=ЯqfU균u}~}Yq @YJD9s(m/֜qٖ_̖<M]W %mzy$^an,WTnEP4)scDx\B&_`lП{uşE w==x8r0_Q̤C&u`xqNچ'_y6.Ծ^GuoDhxnU#`|6&t! &?r59hy$ FwԨo4k?͒Wp(7{Q/hZ`/X>Li3\%QYavDž#J=\cPK$z&Uq"'`%6:֕Ya^cmKtZךh`޶ߋ+*=:rHׇ`;YX; No+όogFF K-$_@e2^?W.-mkSDT&gz5uiٕˑn*WN"J] JE=н>Du(_@I1CzAQ%$ȥ'UL9s,TbKŊ lO{3ሪF:));^|^<>?Lx5kŞCbxn8 &+q (+7|`Dv  R<g69/ c1ʾ] O~Y+Ւ*ap;X n:91+'%{Ȅ?j-Mk)ɕJ5BhRGirdxf>ƨxWM,Եt'x}f8;3朵o£U뵌K$DW/|~9!\dfBw+Zd.h1 nEY*΂<LRJu|N6*ildQc*S3F{J#*>ZZT=D5 4D"h B>/n|H$FnbH$D"H44D"H$^"H$B/ uȞ l! D"H$^ |tz_g^}h3RIDCxD" QPJY:?k]'GA`B˛E)?#4(]ŕq EERvT Mց]0&RFeig7G^7i֨WV 9m{gbIKuIG-ꊻ2+C.4(VQrEC({1gZv]I(B^K޳+tgbpbT0 g>dǪ'%1j~c?A'qf[.F'yv=4tiDrP)uF-Z@16߆q klF4Ӄ.<OP㤬,(>ZDh RE{.NFčM{q Q?"=.j 9=}=>Lteݻt, tgѲ^e|.&}/7H$tVQ1WjNPn2yƨTR aƩbv.-iR 3@WQ&7TEWQ1c"{:q5GTJXraˮ,ڗ”,QD"/IQ\ߪgH|h{{5MjZӤbgǹ헨!෴KvvbsBhKNZw#yr-\'=Ie-wh>"灆Z4`D(6fDM׫͒Z ӤEMY^u)?M/ѽN4N0u]*E}{h9OgoM<8cf<{kfeLxE.ۖP9*́ZJ/ޡc]^KJ]DEYٕz=n|l`$mD~= yf^ލLYcs4K4&\݇W? ^Y>#< 3$OI6S^N'1<:DąLlDs8V7 Ƈ0.+(*Ntq4 ;Z01ţEX B+uu].-TDWQ&o՚!s粯oia6su+R \M;4v|o%5 crV./RwW1DRf(&WF4˪S!j\1hX0( ZW\1 B͠Sl M7]zUتtVF:L.pW'}GrSh.;4x+NR!L2dVDR" 0ucULVu)Cu)QD-V.JBQ(U»j]@|ޔs'-6p $ iiiYIIIŕQB!)ʕE3'Wi[<;ױcDzSRRtp Ezz)7w-_+Bq=z= e( beHQ2)H$I)PXNK4t+\:/JOHK$DUK$GxD"H$DCH/H$D"hi%D"H$ !KoK$DDьb&s7hLz e,vp{j1r8ņ99xD"TxXblE,O7ڢ>Aaf[4Q'ga;V,~̅ o>xcdݦ'y{x2eU g_p nuKz@F%DRجMBjI^uEяŞ@|_?|'_Ng5MdKgn&UɃ#muaϽ\@X<{8{w'D&]|2n^b'UkW%3<;kZJTƮ㥷r(߃Z?ϐU4KH/H$]TmDG1!ۙOӋEɸ5^|XX~|G 73=TKmiَ)w3&ዊt3و  U;ʛcbܤX~q8)uqAxi~.3{'2Iq䕗n{& 4d#4vlgf]_=1(\і8{B FO%5%0cY,c"]ʰ~ql[䙟a*zʖ2cɯd-86B^[QH8rܜ'^_&O`_~A:Z/ZGoq-<~1?1+Y2H/bSy/ոƾmTHIqg匣i~^,]L/BZ_f?Ϋc}RU"Q0sgˠM* 慧gW^ ژ=?|KO<9U{.a Й:գp9c}^'*{Eę8+0|nb#ٛdqrrD7hD5wuРy_ٛERM8 @]1O͢_/oj'8z Ǿ͒jСc4= G*Y M;ti(dς#`p oX+Zxq/L͎'"rVO?5=pOߪ{sabL9G|.SGзs)Ù\-#ZPIߞ] RK}nTOYmZ6NI ei'F.V8/&ly+Y_.<۟}vGuM._vO|070/@hMw* VàĜQ~YMZ/(ā=fl-6 a$-!}l_rcAp"z2Ny!F]-CK3wCa#Oq3a0q ^er@$(>=|<{͂92!թ5v2a"ɵԿLYZK0k/cl(ݑ 2㨶te(z҇AKzJ"Y$6I \Ey&d^G},NDOĈ /"t\@sc0nϿx\j2qLN9C?}gMr5S@ 7O=8\| `zy~loߤf"vM$(>nD! YW 嫉iw,'TH s ,_ӈ^Hb:I7窻ưb}RH!F`1@2LDzx7yq!͉Ghf}밝c9-$]{ѣR^eCo.?{.nUq+Va3IOSLb+++VUVVny7EcSlVRk׮A`WV\FݿX,ڼVD<ˍG]w,T:xt:bM7ϊҶe2PZVk *PPT?uN=N8"rv>([T \|/P6e]F=*g֜73#'G+o6Kۗ,%-ړ SBWOLŢ?̚$u5wf#S%d8,ն9N:d(QSd(QU3{kH%  86 x/)yMѦDڊi '7Eyf^lL!cAAKΊŌ{sbN%vk'ze{K;XAjQ TZ މbLH;>;ЯA-AN3y"dz+MoQjz>v&f uqϞ+2vmAEV_9>e\ywH&3Q'=au]f<'${ʆ̴NLXaw$ ^AJgV( lFlfje&>?e [3{]iI.E-'"AK&a%~Yvm|ʘ .%8jWsAJ4vQf={݉velS 7m5¹'Ab FrRv03?)ޒ@w]dxvP!e^w[Jc:!׽%p]-L{gr%D $S bqO9":.;Û"5YIծ\DSD `Y2h}թv)ɦ|viSڇyE %k'Ou.w]avYN&v %13K%V܌'XS28%D]k |kծ\b%^-JBx% ah4Zg/^xgG1~a.y3NVڳ BK4j+]:%ӇiG(;69.cͅ\3>Y.Y_2i 0k⿎!t>{Ja-ac~s8xTƺy|۳i[ g-SS 폵b(f>@Z~Dt+ʮgw{jE"-g>GhܖCeItr^4N# Ʊw} ՟J 'xώG1cZϞ漿=ZVFr2YNy>Y ^հ^W[7U)  lF>Fw573= ]FNa_<6{dhݖa03eeU{[(^j{( Z&``G,`|8箻رs oQ9{?d~`')cnGh?@p渭"AO\n.t층,T~l H`Xr4zXB4C<8Qo>{r}~qƄ'%'*.> C`5R))#AוZ@S9c+χڇ PCGϓWbF"B~g8 +Rm:pj ұ1v)JС:"'tgp[ :e}ޱm܂Ky7 `>ѿ%|y6%oyFDZ4ee,3Ǿ`GQ#f9Hsy(4ĝngq-ТM'Q`a;~:g=;څ<~ǭJU!LOW~yXTQsW6'x}r޾#/B!v=N.?tq\2^zx$q_u' tN Tદ\CnaCq%M}Vy"tL|c${RTXi48PH/*qaIIp{5" Dֈ(-'(B-c] j}9}wV}^v!ZGVo~$jݍO?;{8.vUyYƢ;oz[gm/?:cD#QhiCT8DcG9}*tڍ2o7@C Q1*DOe9GrMIǯ%=9m!6y=wU /%ռLy;BzG4@<>6b%}q0"K3cbAc;F\z̽BlZU߮\q/_ 8dۼG`c?S/˅ؾۭ]=EQ[*ڷ"٢MYyESVط(m>*%v@y}ٮk~!&1OuGům9mZ^m ,i}WÚ:-e©ZqVygD] a ePu_1~[wgK V04 xŬ'\N]ŴY_F+kۇ'_ߝp+؍rXz`>x%13ca(wPT%9} k.Gy/8kl&|Kh58K礼CLO3T]zd-/ F" TYd9U$h"\tuO**( ]z2֬.LR]{еt~j'B߾xݽox;9`yR2][.UNeq$ %~E2p0n\B5C$ EQIapx\9GgfltNYz\z2/VwuWv'Bf-51 e{8t3z ůrFݶڎY4[vt-u7!q =U ^App;.x((⬛a;@xAbGp#h=L}mڋri$" G,Dc(L?+`z5=A,$n$ӵOT0/fG^öڿ8K#O$YwWs@;6m?'~?f9뚉kՖ!  jD   SLkHC ü@L:OD'Ē}xby_vIiASALm^ H ëi~͑w`0HҰoh}-E}'pڥCm U\% X>/74ft]W{"K߈L^|xv9`fx[B`j\[誢yΔVtI_I&61D #IOOUo36:eѴ/m>v6 h~*"AG xv},v) l;d!-–"g%b)ZsNAٞgjohP:8e40 veۄ*3Ia.cEx% TpCl7-Je3fSlgK.6 UQI-ڝyFe/vk˴Is9{Θs[fRR6:>R/U_C2cslc{͂`UԽzFj|)1TvHv)~Mgv}+[:6E3#ivf-UQ ǂ lm0ŠD)jUەmJ~[ee[^xkbGo=̐Re\Bej=;]NiW[v6K;!ި-7oK,Bcx5#S/% ESɳ*d)v=v^šnWK"7.Ů$A򅙃`7I>OEC卋%SY6L1 k;PT2)r[#ydc]e>w]l7Nl*;Cdb YypB3/)i=[PEk4^͢H<-Bv٣ArU]= MvU:.C+ؕ6 xS; r3ʠ{AT 6#@MS\{jZNs:5ah72綆]j\3 iu:W {SSiQ3خ*tt|غ0]{^dq\fQHg+屶✺62b6xi.KV sAAAbWd:.%vV3$vKi:>k.ݢREׯ?DcpnŲzXbKq :%&|&Z%ؿ^o[PՕw d{Aj,2E)f&^쟙vgKv <'®(Ä`j{vF=#K'nM7sSQ^nǒ95_DB{$T xn3]̂ J7ƴԃ$?DmK.S(ڹ"r i`r{lpB ve/@ܚZC_xkOjG]*+MaV{)ԙBK>I42m,$ZWM)bETNBV$3';7.Mnunn#uMe`3#8iM*\\|Rch )gKĻ luĝPٚfpReO-pYw5Ra3&nlPxUee|JKgBbĖTta(Ic\!v 52H(Q}q%^Lj  8uOp3w m( !^AA%hϪ-eD Hz#1omV-xB# 6Cyߢ:ↇB.UU:Qg~6h A0ttwfDd妸 ۷i7"X\F3Hۢ-io"o6^Գ.JIe'fP/ h~$%Ņu*Bd"MeGÄ#@(?wfhG?Dݻ5DSx]В0t%'պ}dz}U>3^YiHR^ kwp0l(z8t~g硜W׭޺-Bp-YgUN>r7>2loOTC4Um^_w^e.2 6xt;lSՍq729]qP7P.څ|]O9 ]bĽt]=A5|ﻥDU7>>֯Zʨ"j>zo>ZL7R_"̄n؃%Bh6DK~,ܿAYbay0`(ҎN^=z7/1{<r&l:]UEqIR" zΩ>Œ7_f1mwO#`H2Ƿg)95'A0x):|Z(l._x~\wiϣ?Y_0Q~C7IZ " 棢`vdui 1y+5w]_gAP#y^xKzYt\(̘Cqé72Gy}T.?g:EWQ,bv-Z$7bv"gO%@@ٟI^e{wv?wL { O, AM"9[ot.R=:>n` :hKrvḛb]cwtpe}ddiJw&M%oG!<+߁bndǽ _ ͨCFϧg^OVCQ?>8v+(C_߯S]3odA߿NwPd\%Fqy<7,4  Gbh.+?*\@7wL&QLwGCy³(D8S{}8{^MйƎٛ h1,N_[t5FqGHe]sChTk`+j r~Yq-Fz*dW Řae&J=.NJ֡jWq2>74ơ!J1 0!jFtD8f`PVW%̟/ }m8WP:(ʊRYhgFzӦ]a3^g ewrU׽jeOzW0y!Yh>Cw 2ǐʢt kÿ>CPWμă \9djxBu=]&X@]]Wω\xnDꨩQ5\!bH:x hA8b~'X/HDՇAI=Lɐ=8mh$oĉ` KZf΃wm9pU&vrwŜw:Nq`30*mjW븨0ey\I8+osfMA} [q1 <0IDAT=;:X}WcVw^RV6 2r|)P%wAh*.݈KF"J}Y>L},WsU*;XX8H毙B:k ό&Aͺ:66d=8aF~=]ٸȫ_ hψ6B:skXxo3jJ}&rM-ВKɈoa#oqxj'/Ň@mut,].W`*&BSSЖ+7 eC椾ʴKkWU6IUAM;j]>DSv$^{EvDBG${hT~ĺSRVl}6>Ӥzez]v9Q"E2lc0 nfyFeS'(N^gItV:֊#1DQ[y T"ӞiW,5L/Iy& TLnS6&̨g/`_ە>t+Ib7ԨhhnoZ`J=ꩅGB𹍟+n BSЧ@ NMp>-,,LMjⶲWb i-L&S;.2Dycɴb^M4y{*Rmdhؙl頻9%~( )ם{m|C=* >Y,_n#e{bIShr9TLQR5ɉ60MN_S~[|D Ss{pQMxzjR[qjE$ubɶA;5kRk0L&!8imlcx%zact-fX-qdzj+uF&Qz]-:."8fxē^C2 N9$riw6ƶ9xN)ahg\lǓa1`iѢ͇>V1sIRWy[C+վlڂX3*h3l  ]o*tU2sYedGfz,ZZd~.،A+ CcpNJگЅMa4o:N-wAAp$MQۚ.*Nsv̖W=^i\A8Nlk:TxTEۆ  ؃J#-o'64nްZkÓ:n6h. C B7[y>(lBPך7gϞ=A|<| `q& Ki|IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/shift.png000066400000000000000000001271211423020056600304210ustar00rootroot00000000000000PNG  IHDR@T}r IDATx|>4'xll+2۴Iڴɯ;i Y썱{`lmYsҝ}%x<|.t=!77W /,,%ADDZUUtT E"""CHP$""R0 E"""CHP$""R0 E"""ۂЬGQtL= @,VVb`,f| % ia<> ÃDWDD-)^0:QjH΋Dz_E{YEˌoGY%"UT1 =":/C (/$~}@DD«:9ߔ7agjR9͚6zKDD)^ NͥZ-.RՌ(;W/R,n2&敶'J 4J ZDDD]PZKj0a `' GkېtHHDDǻPc /_8~"W®3=2{6sku!kj&nstbĚ"Q]^wq8gZZ;h=(:tWti:L_ $jQY܅]>""_<2>hkԷK޼g&4ρJDZε oj8Ռ[u1v9:DU;P{P9K|r:6ST^xMky*w~E`F2D:o'N5Eie!"".5Z,Tv@Ir,!Nͧ8\8"u#)^UN ʀr{Q<STy!1xAz uBXEM8!,(kI*nSð@?DD93l?'76kf(}ZmEMErZD5׋/r"uB/vцLf],r *8:Pu BqRŸv Nhфd6j9/A`ΖЛʐ΃DD=(X,p v\l>>>owcޟ%Cc0 &&""38HDD`()DDD "HDD`()DDD "6 ,""XS$""R0l>%""RHDD`()|JDD`MH"5E"""CDZ UMVl>%"6"–h_?~n]s.v)D}l;B#)CQ?]OliBc\j:Y%TS#K{?ĦJ܉8]|׍t!A,߆.JĜ*nĬFZs,Kǚ"3?] İ@*Pt 6?cSDzY%{';Rq~|01Gֶϵu0qhHBcf\Ni^5ط^OWB:;3g#Q8}QQ.o^:=t(;pb%6F݋kFApzw&C F/k_,J)<A)7)9K&}#-y?Z"pXqQx "aFQ(DY˗HD$1sf#8p3FLÀ|X2y8bF>yHj58pE"1vĩŨŸH}"|Ա F#RRg:a8&Db)OCTޔob)3H&? I0xv!J!V!ɏ=Ȉ rTôO uʯ!xdLGS)uI 1_y k6}XA0d:ݟbB)RYA7ͧnK"Jjg{tQu=Hos _G?o.FvS&E#`$OrؚPNocMu $S#%Ѿ>N|!Hh4I뭬8. X0F?V zmPC[pN= ^_} `.`bİK6 G!9ZqrNe|z VΗo8E"":Ҁ!zD |s+aNZ]$$hjE lLi߰7TB8U]ֱї}JDZ{m3A@tS "O|Aonl^"FbjLLc[y z:[ͧřk}O38kߏ80r1#vt~-߮S""Uc> ,E'b(5u-䛈vzť`cZ~GwnO?BaawqZ7`ȎAx&FORED4 s3gAٌA |CH4؆8SGֿ/ >si! 8uΌC1EWQsE# rͬDV6@LpZdu?Ք9& hR@Dtqqg2;D?IM(:%ͨ,G,z# Z > _|Lʓ{pJL‚ImYJ0q`D5<13y@;q !xRI5(8JkY%Dw '`t.ݹK %8}&Hx1 ,5<,s0 y؉gJ136s D?I 8k|)X8j&:LfIDze>ؙy;MxWbV;;q4o Qz[12u y94끋8Vc`EoǔߘS"~Ro9v ؼGՋ8(b%vsshF#<C?|_XS$"#n^_{l~hbŊش' gw˾aop#su.:?L|o}ccc\hLXoʢtW\+O}ktK 3a|{?tbXa(Qlj.D# Viq8!ؾ"qwQEa6b_n"C:L,ߏ{ 0{` xL Vlc pgcw"S0,8K= E"" 7boiC a0c|CTQQxurB ]Zt"ǓYe0wP$"cL4Ay0Wy.)3&".n؆RQDEI6P Dz]8 痢 E""l6kQhCę'W6b:M45ښB`=?CԍoC:@D龍Ȕ31lfuz#r*bcsNE&߷(+5ԁᏗ C'`߆}hs30&>S "7oZ$ВRRN} xx1]bI&6ht1i|!lSa7aZ&T~ N3l t4ц!8sڦƚ.OŦ-،Ym 4=CZ4Xl7&5jKNL3~XS$"""3S‰ۼkuE"C~(JpSR"lTnL*#ka&6#;8%#7QV[})a@\2u|9%f k8S+V(C8_-[{"\IP㐉TW"X,! 5YpXC1ut$''"Z=_5L cC9aAD-8Tڄ*EƬ``F\jJ<]_n|F؝D"y`߃O}E}0aDĴBFBbP0.Í5*iJ8 o^Qyw]!ܞS">N-FNv ŵD&\?,4Cc{I[&ɱI ;˺Fl|`҄7&<~F3ӪEeC^jW(>1<8;kn E">|fX; 쇩aקlc #bJ|ǚ2qȘuѸc3VB50Lywe/bj^$_DD5w֟E"Λ1># >7q;6E-=V$\W1bz|vvF) &aU):v9!77W'Rv!""R1 E"""CHP$""R0 E"""CHP$""R0 E"""CHP$""R0 E"""CHP$""R0 E"""SA%%r kADDkDDD 5EUoq.]^ǀ^v`%""סXmrKDD HDDA+Z[G(hNmGOK>6!qËl)&g'6>@$d`^`g׺|ZyĈ2z̀[_ =_ώ˨/u:g|\y$`ǾURo~%JOrԚ,p)ld7kFv>SVI30?= >%0y-""j_)%[\~uODhz,"='Z&\$/En~ +Nz- JϠ1q:K{p0s'VYꑽj[c(H87Zl+JDԯ6Q"ep fϲbY=>,iI\5pW";QG`H4egXZPP("zpl?%!’>[$DD]{j]JN17 = a|pFD"6ٗYKUrJ )~P+̂ `BuM#$WWn Ek7T)IxPs)3D|=3fگ&")SL(CLv f'$@g1, 1}4XXS$"V>Њ,HQkecHcw~ܹf pJD\k}YːsB/K/57L@N@-%͖P%`0C1z6ǀX1Z+p|jDXv;,B|TB .7A UjGǦS""/Pt8(|Uf eX1=˷I;+d87<ړTj85EVNfF#1ASyEhf}ZW $Grv""oPt8 &ɂOboO+e):ܱŀk M,,FYDy%`"*ADNV|BG?#FYl : {VmW ňz;9k]ƛ56}z5&4]V.afduѺv '^ز:0Í ɳ{ H39YZ=6چ0F,MmQ'J111.C=YIgTM?ypDDDrBp"""W/*aA͓Ӭ/1E"""CHP$""R0 E"""CHP$""R0kGbm(7#vD̜1Q<08%\ +49,'߄8OBfi>cuX +m8gq0-/$IDQhPg"Jd>Muዼ0LLc d,3y[jނ2d h~7X$H UaO&a#({VOFa#Ril^8h1 !3v9=\-~͘m njI3.A4BD 3㇯o^ۙuKBR!S+~ے5ÔiX$ Ԁ[<7ꂦ>Q,EMHۧ1%cB R,@q:{( P<[cH4`3&.$mSiD]topHԀ ЅpaX 9m.fED+Fq4(Q`=7p޴]1b˷ƢI0c&܌8 SOF nNLd,AlHaac[W$źjT 4Pnvh>"(<jI@H F ؈}Q'  ufT,6= @8˖LD\d!;l=^I{Qua(7} S02S0qbǮBɌhj'7]{?[+V`X2d~s=7  ABmAA:XvX""r=5EK-*J[[__Dၿ }xLQck7׿3GV_^Qv1Ms)sESĀ0< /E~1!cS""uK(eӷFx8L<?}&L}1E98>b_ƿֽVcd|<)cFqQ%Lb5*Mr"> ߐTE/S+Df -l DD@͕bbb\B]RoP^^*޶5E VX4ná0s09>2TZZP$""X)DDD "HDD`()DDD "HDD`()DDD "HDD DZc)!b0ƤĴ IDAT5$՞oY4D(?c,'m^. ,y"fϝXLtC(Jh,؎]͙9$N¬k !j_HBߺ K|C,kcoWⷋƀt7V~4(9TDԀ[pQ\ ^1=E`է:y$ dݟk]V'[ SWf"8xMS31@7 "ܾ`5(oQ`A&6ĦHLPج*ɽ8ia0r@#ۃE)?v*c@[N)H,7nx}xI g_#A @[M4H$$&4!VRC>1@q D4aϦ#Rn$a ۥFAXM H ܅sxK]jObo2+h;|&'c0eƚYX2qgn >Jr)'aKv!Vm'l0I):TWI0RX P]U ϖQPEq ƒ*BBkP]z}8BO'X-a9^=5X.6fa\.V-hlm> 0H ,ݿ9DD}F6 A@eYnkC @DXBg 'h0 bܵ7`NABN>ۺ%AW !.(=l6% rg].) A0-MĶGPi4em#1}\|N܀zMӟs61@0;&! h*DN X X!6e7A:u+DU BFjD}`O$"][Eb`dz!㎴X[ӏ_zƻ=a^:`XvoKbn^Mq" X[\sCX8A"7ESqmH{QguQv@QC R20/u0\J;""RtKMQ,NGzz:fZ/|t-¦&b~KC0akq^Rl(̞7/lǪOB)'N䡢!TzGϖd|w;GOf`+V~v`]vmy8 >^*~L4~~[ϽW??V52DN_yGa;G3OFeG'-”c0uBLgcrq^ł%i3j"/NEH.GkwNS pw1p7y^f $#{!$Ҍq2K3bQ?5u]\^DDn<苐QMƘԥX.k 3`z l*uxyP$Ƈ)o/b!磤YDua>j|4cGe~1jFAKDRZ؀J\O;ѦZRBу`K[AqI!SED}A7b3/,'|8m|]>V8&<0U{j#AjL_` t*TYQ[]) -~Q'֡J10-GJ;yzH 5 k  5M=+ʋhc>/)Woijn,iw=1KP6M #0b~`6"YaFS0h Y,cMl $ l6 @ډZ`zGyQ׍'wb-X Ƌx'oh.j.z % W$`0@@mgsA/dAo{lnmI%Fe{^ϵf#w^S^Du8E/B0at +;rOU#~վ7UzԷ T_Q = 4ԡmς&a#4LԈz /} 5qgg0>*cp˷ܶ>U$jV)ǴL(+A>:%!s)  ?%@*;+  mg=ګCY^lY&( IHw걽/cwn:?'ٷ௿[ahԻ]UmIi1xzlSv&o9lb#}|&A<X:6:1?Ŧ<E2Q?  @i(GYKܑĄʢ\7 $&PYXj* $K5Jr DTR= ֕!RyKP^s E\X M=]ƅUbDL~oq{""rssERd׫Ww -]в>CKpL;)N3lݴY-< s3XKP`|!?9bv.v:b7ò.Ph:)^:Y Nf(j D¸yF""+--e(A ER!""R0i6Ge))<Q E"""CHP$""R0 E"""CHP$""R0, @C.5$AEXVeΔmy(Q̪g,ιP4 oX:,g,λP4_\`6Y>.t|@,V.jd22UZ|}}3iRg,x]b/C-o',;)6 TNrhIm~8/w:rǫgLjfx.ߦz!˽m^~qӞ?xUr9jfع+ꘖSHSu6?y*kܙr`ر.%0Jj9o6㶳\q㙷ճb^o+@t]?Wvxm9'Q_Q߶z"QPp,u2 ]~W*l5E"io$km0z+Y3}%֑aL݉Hԏy8 )F OwE"&5-bQE`7XwR}RpPJ1<ﱾn"gayTVV???-9ϝ;gɓT}iP5x˗/oW)y+Ǚawgh?4Ǧw_ˏ7%1:I?;' v쮃?`z\(ȶEb!(ԩ I5C'?%5a¹kڣ)WB?y'B6W< Wbn=1y8C{㥇ǵVh"MQ(7E'2'ߥ_MCVߑJ{]d:fmƵ4hwRf|73`Vyak~q]Xkaw 'OVPPP^^AP?~ǏkYF@G/5eߝ,D\rr(R 6o}oA QV|HLHvccRX4w,1 Z߁]S욳b~4,PhNO#Wk0o燷>f* ?"V]NP~ >D8cʱg%AXfb>X6;j fon hkK j=oZB FIƜ%u|* 3[~Ո(۰"ّ4}"O,[i[-..-(322w\FC :uy1([ '_SSbFLF qzppxTmۄfbȅ_(ڏډQqܩ0݊ö5#&b[q6rn4sa^qlqn COwbilܒ Z#bՖwj 6nVnc3M Qbb]zXoEܢ0VM 3f"ٲ/Chu}|066ve䰔k=a{zEMqW}87{ ً~t| [^F~v?ӧO;ۖF,FIJ u1\S iS15 ;t˓DqCg!vb$YcfL1NJJě$D CDL_ֺsG8O{Z`ma ܣ~y:b5]h!}'>>b<5 Zi I9K [5s#DļX{j00w81~?SX~[&|[`Dh(7FFFBPHY]].^h;ή ޤW , =&l{()vW(=֭[pYw^ڵ1ct*v\Gv36D|y sx<2?_[Oy1(I̩!#UwfZZlD+ :X֠ ~X6(߷0̎mߦm6m{}X`TuVׄ^F^Ń' i۰铏r՛a]NjO>rCl';^풛EiJWu>䩧uq.}QK ȗc_ܼj0y G|`Mxۅ1v.fM=pcz E|l؄/n(XmrQaHlГl'XB)xPr oBf7/( 3{ns%$I]_K"S6 |)^}p5^Rם+bbbl cr7W\{*^K5CoLœtx rN|kŀ9󑢼S1aYwj;[Tv2f!kZoPe56ՌܙQ_ MH\r%Ӓvv,Ή_63cl= ^[p?m0yP ,6Z|]>KmVw0S|êqX~(z+[05Ċ ^M`@CEr.nlSXc?(>OmڟVHHHK'PSSp|GB0;Ŕow1Ѿh*= oهS[9"bZ?~X96`3ݎnO>ㆴpv'xe,ws֨x걵p] :\()FL)=}_>+'_m=7sǘ4%%v)G'07g@VH0>0CGz3f{n[7(?|5&_[u83`?_xgvΜ9ؼyc=-[8'݂ތ[}V5"{HM1mj8^)ɚ/nfd$oB:9v!Oג_+<#f,=+!ڻEsWG@!f?F/(ۍ?x^cSG6 D`>AXYwnw8#&"be|vwvًA(c~{8x hsϵubذa=z}#sx>G g\.)7Ap/u$6ܩ^s]'7QA%= iQxyN%HjBҔ*ιл7|'aAxD,G4lǪF$õgenQi܋9}&Myd*b#7vBnn St7ו3O+KJXZ˾%7"PwAyyj~wB(J>M`y6N3P" Yo|E[:ShMCyM~Zq㙫񤴴5Etы񋿘bGNkDppI! gǐ !Ghy,枆D w=RahMHjq{(sc8RP$G Tk&졧|n&@eRP$'krǚ6aK]Qi&mXZCt1)*Q/P$$Aj0 8v ߭g@tn>es*f E>U *:HDQj< T[:|GΫPyǡ|e㍺nھwrr -ɡZ.eg EyWI%+X>+Zj0Kj*[~@R DIُ, \kTeg EBW,C]#\;52qAKi뢓COv:5vEs*_vx^{j`/ +hzvz3(ZKPU-ZŖEOQfX5M:@dZks5©x9/;X,/I?#8g֑姗Tg_ӑJl6&2y{Q3w.yHjU]mJkf&o,GZr|ͷMT764zz:vm6_G岺$aРA.M>zAaRN،EG{^ ? Fڹ8˧.8EyE.ױ|]= IDAT!}DM9 ȷ9Yڱ۠=[8]{8&.'"uLLR{S5 E!&':* s$;)U}?4g;$~<㏆]˹:ameoIIJA[.$e[s$*MrmbưC:*9ÆUZ]vu۔%R9 Ed|)Wm-UE˒<^Վ4rTn.kfm;lذK/?W~ ו t^l L-mCT(GLLe۾zcC/UpuWI3˨/zIܧ{5iw4vˏ˳J>uǧjs_j eQʧ˾}r .ͺ:8jtv5??m9^3dFK-jkC:݄jϯ\ljjZ</;cR˧3jl5D5\\*9lkjjpEV#6eC5Ϧ[tU>;o~~\~Nԡ3p3;X8eW(햷SۦSc?_jjq׬|z]@4LR Tꐍ2jlvܔCCc8>.ut[?н1v:/u^@mJu76 0jxaԟO-jss&Su@.>>ޫޒh۩ GOH6G,$2p1H9߮:R0Mt:{ rpU[6&>r\2r57K[>Q^Hr6ZIې )W^7uݵC5͓*) K3NnvЮwgtlsF_.kWe᪷]6U\uɐK٨s/_w\VM|p{c᥯;\sꭚ| m̓߾5X[~*ױƹsLyg"|ڢsffmH}r:=m}=E %h̛7"a%5C?z9W_ZN&!5vQHT4DEŞ{6tvgV{癇ewfvݙs?~KKTz- YAbjG}Ҩ:.4nXQjB>C 5=ͣŧ 0"&g4q5gͬyo׳3ؔjT (HϲLQ}ޤhSiO?U=6Dn`kI MBz0̧|0GCҤ284lkQ8T̴6UmLt( tLBANgD.Z1(}XVDmjiiYdkR Dg:bnoΜ9*wI K(Ye36mJ븑K0;e/ve^25k/=Es1|PqWoL-Hqviű_,9"2)(S!=TVM5ed%tҤITREINTh1g8t2CVҷ7$2&?~ը Y1 ñ?S&ߑp{/{iQѶ,ǂE#<|xѦ #Q,a=/ dYH&QLϮ1_L Csl]*Qg2 fEJTF'8v^A.|Qg|~ZT̡qż)INϾZ%kqmjiF$q E}y)ׂ4rHh;9}woRoH_L1h&ys-:}& ʼnuT$dҦN q)i߿?*wXKJ.]E*{Q = I2҄D~<4yS}=H%qwho,䎑j7Rx1>R =i+ќS!%gm \'6LdFɋܾ[RbcߎBYL+qJ" "1)9m6$o6'>euK٭](șyV8) z옻92.%b}'ql~(Q>]|]^ROhUw.Q %"O~Lr\G $bXq dk8;9T5+.Ľgl=-ʣm$/VϪzǵ@EZ)+0=cT %qq=.JEt)3(Æ SQԩ#,wѥw2e$QN,jjkO*T 金:53Rf+K߫:e%kb)7fm|.֡SJ;(CIzԚxǘV˦98צҡn0ƹ4y ίm* BnjI#=*b[d0yp07DMF 5՚2.(m]>6qdm,{r)яw,!⏞ΔzWz2|-:&T+c|cNQOqo2)MaxJv`u]]Z;f#XĖ}b<+W"yQ~M?wN@hLI 9ۊʌ3pss{) R_PQz-j( T HXcf{ | ѷ_ ת ЅӤ++SʱbY փf}\)C {wb,\ ]¸j{Zղťr WT!no,\ʢET+Ob{GՍ^salz-(ZcSH_y}؛olz]p&# ԩS_OOO&=jCubE1!!A2ڨ-$zX"y{@T0x;>8S|WR#MgS!!Gʋ9t {^ƨZe[UbFXTdq4*AL:L.$(p)(H wH(@%?666y:T2dmcA:OQ;11{{xC^rfE~,ưOxrEŘj3^ ŘW,.j!@P0O{/KQ}=qD@ (="uCQK.>@ (z_@ Q u+9#DQ t(j(j@{tpb!@ xo) %6 z!\CHt2%)S˛/{U%\g)X!MFA[+*46um؅@$o<!Qu_ʐk``V*o׋k ɨڅ (`wiOq(cGb-NIn3v$P:T껔1 H6)Ȗ~o'Db#sg''q+'% Anڋ`)2?n%.js je065[5ͭ)Y8_ Wi PZyӴ mF{m1ȗ(IW8}>J-[wrD9lsKL\K{ u1ҕ+ (KQ)\\֍V+&'!/و~fQl#Ez}¦o0O G4@PP(655B0@Šh<{XclLԟhk*&r&L\1,!\k'?ʵYcqdu W1&/18X,J^5!3&y#S0z؞fZ4-R[E*VHJUߊSW0 -[!((Q& .5>i[ /L,>vR$ѫ$p)5n'^&|[b}nAA2-ٻoр)X(3nﯩ7{Aܺx&3~Vj9.;ugI2S\Ň`. -a6mWJDf|o(3vvl5qYxv3Y¿+?׶J,A9}SV P+:j5WE>?4ǜ6O;YQ <ȤI^ ׳gO aBJ|Ӳo͌S6sF73gYe߷vF8Შ+P`kYX }͛9OY(/Aq9) g6 IDAT߈ o 1@۵Wy[}R|)ݽ`Oٹ+T\t $H[YTzu7𿗈<1vrw-lx䷊aDZ7(}jS֬Z,aSX9( v֍)S0rHWt 2 ,}kA풅~dQ@;iZpLo0}7%СC̜9Se!n޼77!ì.40{ii-7ՋitJ9e)v.n[GrtsB1ďL -=4i]BbR #Cȋ[ \8Cg{w;vi_F0):9B)K=ǔT <%$1:T#sL;@(cǎUFfA,T$%%=/7( >0Mp҂BSwܡW^*iѢEDBOdݧ|w!s3 ngmWWѵ2]-d|ƍ3嚝tK%hj_ãȲ56S4)<הdE{ݾ?%DZf@rK+|bNFY C܌N0`:O@xy"Ω$Lh8EQIO޺tئL<"+-+N:M۶m?~[:4P *hd[r=ڰd堌c4nɰl8Wv><ѥj1s4ě?>ƴX66u0 7ΥɃl3dE*8~,;ӷ00 &WHtR<'$0["j4eϟzATMmԱ/ד( 6o\eEFFvڌ5ʕcJ*lKᾁ*"L/3{fIPg6_s?)ImK*rI qoO0)Vc)MaxO}Yg0mևyppD47ح4&՝zxϊ#hlꑒ;ns iZe$7Tv#۷Yի|Z ;Wr9ׯ_CX= ^;k,[bhtc!*LN3.V}|[v]) o6t?ϞL0**B9O,zl~+:pcaNlܿ+k_bZWmOkw]ZTNj@ '(w{c:p/^$u"ݻjժe̙Ê+4>bLQ(Q*AvÇpBkCNڣص[v MsPnr4PLOgDEM◂Z3&Ws~+og,.O BQG9S|'K[]ČkGcnE :a\Wj:رCBȑ#Æ YM籐^7YIBFA2H&(bq3Ru)}5 ԦXqR$E|}VckZq,*pjV3ٹAuies8_W2O k7O\D'j,V}a,* At^ KAm`MV(q埻xI=?Of<_;|8l2vqez3\2ڔr%f#@\s{ uA2~kHVH}%u̝yR7f)(׉Soi(sLNburt)↵dj:-ƁrQUd4iB5L~*ϢMJl,CV QLGFi ]Ǭ_}|bοog TY]fCG{T|FeT鳋cȴbll5֙F݇φU?ynZd£ jIN֞)7?ߜEWi¸k.UWF$aVR>㼒/KQӅQ*vd a|8Ξ*6PYeŨpo3O<6)ȴuy0.`}OI2clWv.-:0hзJ#Ō4ȀhUP]^sru@Kv%cS5B}* T@)&Q%1܁oCjΏEDZq~Sin(㓜LLL޾yÇ6N^vLk/g& 6Hơw"aRەW?OQ\ED ɏ.#D5jROBJYmqW4;zQR=,@ _^L3ΦK(*(qJzz@Pun ]3@ HG@ Q !@ ΁6@>%46|@ (HꭰS,0ѧRRQlQ(rJ7G^"m7@ ;Ƈ#KݧRFMK&W*wnzXB"R_%+eH~ۜZ@C[n+QQfڌCj3gQtAT]=AA~|YAM`8G4[  }*D1 Q@P>@ (A:BGYO3$< cG`rk7GI}9g|/3J.d́/I SZ5BCCE} ( >0.GG-kY:o*cmQ{ߏQ(rt+/3ֲkカ3/sp oI0; ^Q$."(ǜ6O6'>M'jԨAڵi֬!!!R08iY~iD9!@🢌Oәߜ~GXqkQձQg1g](WciWپ瘒@!-ObtFwF>L[ٱc[s&''ӽ{w _ \}EpNal~17VǢtTeks4X9vٍr*c(&Qˁ̨)}mFϣXˍ7$Y Xfw rEgE =h޶ݭ0Hy8 Q.l \\iUr 8{b!:Zv`x $ID%>&.ؚA[Vr8)u%%,>ĵMi0S=Hr 5" wvƷL4ǚnfUXZZ NrJ(m]I)SˎXš}ŒfY(~ao1ԛ u_R2m54]BǒI(mSt\3&D×X5Zz:'e7 eM5(&z7%9I .GE 2=Sjrh "!G.1ldžr^3e,mahUdQkM⇟a~3oVM]1[7‚l3*wL:(8~,;ӷ/1W.75$  <xNH` .Ul1DDDPD|R$RZɋ/RzYmjDqVWjaD F$Z _s*XwX>mI4eX|ҊOLnqBh +)ؽRtSagcY^OjCԲϰ54T!Pl;E),Z=Oe +#)+O"A$6VjK϶锻4Mr²=՜)ik5W}O9zbh̍HUnȫj+DMgƍk.sϞ=W@=rۖ a=Kj9v%Q Yz)<QbSZs#gKk^@13rk)&?iL8Œ}KZ i, %O8k+v}i"Swfvn:yq/FOTշ̡3ANf"%OTLxZieԐI(ya&OGIiNe Z hlAfAT#KSXR\,*B{39jLV*ż%h~kLc$X2̭^(O)$:ECQ5j/^Pe ̞=N:jO5-CeZ*MgbcAPvZJʤ-wnǙpa=怉2Kغ,]N{rVB1ߗEy:x2AqpQEo ˙ 1S)\_߆1iVsą(kO7ǫ˔k9#Ǫ~kHVR_sgsgnAr~ԍ5%8:qJX<uN^ ]C.]ܰ6V!Y|?[n-K)HՂNKA4[@.7Ed&TNL\x%+S2z4uA^GB*:R~*D}({2cъUpY.*K}u!I gêؼ7-Z2fQp$'kO_y}؛olz]pS5)SXݛӧO 3 J%&gTS؄#vC=3-3gCзZfCx-hugƘ }@Sթ8n&dxzi7 %+ۈR攪 Wct-Ce~_3}ΟcW̱g-3¡QKLGUUɍ.fAElG䠆2}3hgǴipuMKZ_QY'U,QMaFY``&HA 4}I?ټ'KȳچX,Mχ0g5 3TfܤISRRTiT!lCjtuuQeޑHZMpJFi)d/E.i@~Rە[D>⢃Ūti˦L3@ (- C>~~\Y.!@ 3Wl$yLQ @E@ ((sCgQ h!D1dWJ)0IYrq%z 㓟8 'Md_Ҥ€ %ie)j0JR"@PT>hU*Tң 7@ $$XR+!&%4Q*onJ9C(ݕN&YLP-#ub颂v:Et?v/J~+ 2;zq'j2_3 d^%CڤU2M }g]݁WW2-*{b~@ Q !@ #f L>gϞ /ٳquu?EA@}-O8`(lSg&u{3sWQqY\DK˻\AS֠UuJj>%Qv3 ]?+ neDe|rD=нUYL3( {{w LtY2Tb j7N~_IV(]f͚LGaܹlذA1|'I)ٟL ѧ|G!9{;1$Z"giz~UK87v0QU&1!hQ٣?vMY1fNJٴ;;SMͺ}+97=zHP}n^>1X cZƅ&1W+$[=SܨXd[UD'A؏s2Zґ6`u,ԷI\\E8;)Y*,X;ՇN?;a$SpOZ㋽)d#ID%>&.ؚA[Vr8)u%%,^$mjM9皒|O۷3g8֬HuWi~'x3˗/gy^}Yv-^^^Bڕ1<  g/~f?1^WF),#<,E ȳiq_? Ɲԗ&_!0B Reb:,,qTQKN%,1dbGD%fJB~ߐj7HȑK̨oD?[~eⱡWLr[ZzԚxg̛&SwLäVAs`!Jy ;m۶z9nݺ=ΫfRd_mUgO0r||c U^)/Vhܾ؎\XՅMhO+MpLyuu(gh_EG5s62r*Ms7*m#S/UTH眜W.ѥG)J[ΰ.w0Q!Ώ;z~ws L}y\i|nݺԩuVQ@~c!DBۅCҢ-[ܺ7\%SaKFi^KƲTEsf~oJ+(TBҭsXTEjt< M y@J2KI :[':k1zuSTo7ʥޫLN=z]yKж6Iޔ̱ mZLj oo ÇzEA!FIҭtt2i%5ҟezU-u͠i7e(m$(ЕdӔ%a( Xď~q2)7fٚ~JLSCq; #O\=TCφU?ynZd£ jINm>'?jRro)i^ܼ-RU~((`~29miadLna"SJ~䄛*EShc,˞GK::Rc "ǮN/99ӺK +rYCڦ87*=U7.Ο1$F7*n)s|JZqͱG.3¡QKLGUUɍ.fAElG䠆-5ksro)5ɓ*mllrMR )03zzo>(J4UڤvRW{{{ E`')9Y07,,CE&si= \gmvO~}e({G_x͛is^D$Z E"6nLƍiҤ9:b q/0"]*UJ[5Uƭ6d}o\ Y/@ӟ8+C_+'$ "(Gczϗ?8@[ck[uGem^v$Kd"!l񞸊5k~`ղL.ybw{IEQ ]` k-bu?փC7ѯEF]oeX`k_5>LkȯKq( U^uݱVf(O|.t=A;$+@ j4-$ɰWƆA.{, Ҡa5y3 _/FNʽ̄qs}҄*R6,4-)g A)Cߣ;Û>eGPWQEYʐgP@ fq6sB@Yh43D۶dhcX&k1";qIS:{chkG2R~.Òtxl=vTRU7zZ%g3[&Q 2?Yf὾_Ѩ7c0êxy?z;%3krKlՕrS |dFzHM]rQ$c:#O_3u(zL4ndvA6B _SڀtOۉvۓg3'cӭ |x8윾7#Gu\ Ͼ xuV?#<,wrVwMWJ>Pj&Zm oOXd(_<ı8OZ7ΤkZ8{qr6/dfߟo<7ޙIBR DAQA% UQ+ J ZHq (X@\Ԅ*!ɔp3{g*<{WgQߟ0kZod,*kC}ԛx8NC&4?B̅8-??{[88&{7"h6Hyf@>5ON$ 9-[]{' ErK۠(7_ 3g 1!"cĀ.PlYaJ'Xg xUĦ(Dq_>!R1"qM^^w!#6q=_PQmziSTuD#K;"EhV(Ĭƨg9%B_E?S? QB`Y꣍[j}R00 z+!^@DVCtPǜ #4D1BeZݨKUQ}*L.F-}D8723Ge|'ĔK%՝/`f1DpNKDXnQ piD%__ 6k*J6D{%uc}j'>Ҝj^DVgbeChT_*Bf$ހHVfȬT袤RNWY?﨡^tZ#EN-ҋl}(\>q&ڧ>,(0ZX4U^?]N:(j`f,-N2Z)oDc ꣏֤>iF@s%?I>gu FMQSaʸ`2ꪯPljJ#C}BT5Ҋ+#QS}j}+>E5}2ؔ9JuNjt>P!Ff8b -w B!N0iZDdI̬FpPP}OhQ̈́rObGU!xĪOJ D٫5 u@:>Zh8GYCZD)gT֝#vPq`JÚ~e>ԇ衧B\R\:ES-VzF5RA}tiEfH_1)mQRmF>t>>>: OIZ#}%bS3zi CeQ}>}eV$ZC/caDAu#/0V+C.4CB!~hB"!+ۀV6hB"!⇷"}Y=<yvR غ~Q璎;zF\7'μmXy8 xԨWw i /LC.˜y G?ƒc|ɧӪx|PAt8h[?DUpѥ]0ѸA|4xzZ%V,YL q|+?n;(x?QV=t3DBǭC7l^-~:bɃs^WNսnFOeLS/cfS&#E UV7 C-S ]n do'ߦcf(w!n|1M_1cZ1<E@JG@,64AC0m_Ӟ*JDѣISNÚ.fUWiQপՐ:5<29SPhGƥX3F٨˱pityd2w6mO , T.1HLaYuqq|l.B&K mt VS\q8 >mO.;<{A=3ٔKѪ#Yk9R!)IO1.$MC2;[Ǘ^']eL75ǭ" Nj7[vr6KG2 +LՑzF2.>;t ndVpI{Z׷Vn*ѝT &ƉZyi]L*);xl^$2\_g{TcTa  gplش=L_?OnB5 l:cs{ !ډ^[,yEBPbUSu|8pl?7`f?t 3?wx|"|[z#q]k&&I:eȬؼ}|']+CRYa)X[9<捄F>06˼"]3&Be\7Š pKNGFcH;_1ݻSPPOBBBX٢PTTyjt`QsP}uESF8tB!DSB!PFB"!'bS$nRu SBS4BjCK1#:Dl63\@|h@}|P}8BcD`*ttpD#z:P#Z:PGPhuc׊En)*C5>'c rMvr,5׈P-8BF0lUT\(+Nr35^pFP}OhQD$BPLUOTFB"!⇦H!)B!~]ha`՗>Hh3E IDAT!rbqq+W_c$`53I<Ġ?P#}>'|vb [p P*vk?iv-GBK fl?OqC}>Qfiv(N Mܘ|I2("D+$گTl\j>ZDr0{9';< ͘m-.!>)gTRVF_omkD}O(B1!~}w"|a !W#J}K#5E!AP#ZQG1?R*sD4G7INߋHOlǀ ED[ބهȇGOa|d+#M*EEF8RdI-XnPSA}A\6fF@th+F|QbDFh@VD$](km0u:OM:^ !!D(NTqPݜuJp  !dB'ʖH!FV%_w+rGDF ~݂Kb֓Q1h5Y-#y۟ ==(#P fU r_O`j4]=ܻ`v ;OL;ߚG` 7/UoĠyCpXu [&r&cIVP+WG$ (-܈~30}B+$_fE*2^_Zr᫒Z,kX6OƗ_&1duVw).-hW/crZX g>WxTiHƀWӼAR#VtR s[^nɷbݜEX:> wvL^\|WNCTչ}=Vhumv'Ror~8AF1;=Hnv4h ]iW9CH%" r8߅%a]w08B݌`̋jµ<@ I5=;Ա)8~W=#w /V`XY8P-ZYz Ti坅N.I)κvɨo mrhӖQ3+"[\N4K͸O  #p\X0ga {_t'zùdmMۏ8I2N;^ڜ(fHYEb5MQO_am0! 78 s\yZ#Q.֮ގZB]9ɗZoT mM/c/jj'mѬ _eSGk1׹-^yp)N}UaCJzЃkW⫢鄤?$̎[,y.YDx?-Փ(<G<ڦ%0uJ41'1Q| `ZܹE)Xwxyk _<t߆a=Zؒk3:v5g~nt>4}UpI.Di_q1VJ6HCeS_fwpe E꩖ ^–a9z Ksc;P`r+@Zġbo3E4zy65ݫt(_=?MݏŒחnO=ṛDN  #wF=Etk1ŷ̓Xz6+~mg5~Dt& p!dee!6()5hےQq(%)IJ26bUh;1v隀't X3|iR)7+?^[3L[†eprht]V]ҷ0۷o޽{QTTf͚YZ>7wT~x)1=1}s: +FLU!%f#wl>;^gcQQ;yf tJZxHI1h&qTze'?[>'- QF?LӸqcG ޯOrK!qo~ J١Bn b. WR^"HBʅ!o҅jFB !|MF_8R@f\G*㏤iA6r Ӂҁ>ҡFu2Mf2$ttx<D#z:P#Z:PGP:I)flpp::ݼ+B@|h@}|P}BЫu3 ݫɓH(گ)h)5ֈPPcbDTkVwCrMA\8תiTP\.˦xDECA5>GpF`QݸҨ-jvDҰURrhhw88NfE{EÅC}>eQҥ 6 Pd `v{XcL1/6ۮcv_m`))!z"| #K%#C4Q@w"Oeo؛: !d(Ba”iD?jM-z ? #Da]24EB1!J*{ k|hфE5"e*5D !ļԑ[_tClQ:\QDt)L !HQ>nSlrD 4EB19q#)Ɍf~v !"rynoyA!)B!~hB8B4AoZ&8IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/shift1.png000066400000000000000000001210001423020056600304700ustar00rootroot00000000000000PNG  IHDR@s6% pHYs+ IDATxw|u?̖l6M@ @HBD,X.;vy==yߩzH NH萐Fz#m31ɖIIG;~>|>B0)v1Bhhknn !4L`"80OBH!$S)B!āyB @OUx$qMt9BH]>t0ڧ[i!LXKԅ`!481*JaT'QFUNPp!I잺n}Sl`gH` B a05ߋ]~`%R0~ @9sooOxW(m잂*lxNpa.'=T5̚蠍6hcMm '4ϔoW5Tаbkyf#Y2TR{XXv )b!4l8r-A2lv"GGj \$P@E +?aj5wcNJr???#!dWr~)TA! D!q`"80OBH!$S)B!āyBE!q`"8B)B!ā}OBH>E!q`!āyr!#LpU%:3\aӛ~rL[rdLp}SNU(Jpu i/;sTΕ.נ  ѴVWU˺xax8氅O,2A-yzXѕux$aCahI#4 Wtbg))]u-'ԁqMynj_aR6㷤0cÞb@j7)?a% :)4$yۡϰ}АE)FOOLK9uW/LYuS-5Xd'٥sV;_l/󹊃ם1'aυE@yа NYvekic<ʊYɑr)<*\vJuzxh.'/$2&ao}&\Rա2+yDrWˮvVd} 2=>CH%Ś<~]oo5W4y~D~QݴZav .: /$)o_ N`[ډCIHbN+plm;|dN<G>Uj{YS^P%MLPWyVƥi6nq`"4m}y]q)*"DZXPP,.\SF蹇^ڤqpH> WִrYR/YĿUWMc8~kth^AmJ`MA, Y&jmkc]ՕViJ (1SNo!~172:;>$柲!"6:[?{U7=-CёZK&9u7HkyNI#KFҋ2E5.S!« MW@*rJJjοGcўGL v)BCQ[B;xL3vP72ŋDz.e8FϹkDɋVf9v\FϺk$_ @:<'=W?9ȩV)/cϙN.["Ӷ׏h.s$+YXQ2=*ꔠknP%%%BhR!$S)B!āyBBh0GY+0i8qSn(ak?I5(ւ;wɛCdx-W47V +}81wg\5o=\ÙG55&P4Ù*ip䈚٘EMگﴛi.?P1OB;?͜&%:i#5;|Qm+N9bB4))qrݕ윫}½&SN?2'LK@*9 hHW/Չ]PS}f;=!hiqra\Cu!@;Y7/T uմ@Z\Km\_XK7%a!Ug;efx' OrARr#\&V@9;~?[\U־3Zhy[-v๧pӇىvҦḟPIg[ ӵΧg>E+< k8xB"{]TbOBvw^ HO'Ι}Smg8#՝=]#]ܢj:<++hQa~S}b+O~A H3K߬Y[~~?Ldb1b93)gƑ||({A D))B.e{stI3b<ÅN}(L!P)U2WwNvKQ9>BhpmUEԗE9`t lɽ:yɁ}i);;diLE(=s/r;W^/vW̧$)Bh.g~i7Y5nGsd_̽u1iS{SnR9y4L9|RSZ_ɵwrqu+i[// Z1SaK2dӯ5IyLLIejBO_8P ͅ0JQXeRYwj`b#J9H"u&bj :CN%g Be@: ϶Cx'r:U<1(;Bh0 PTH|p_.ܗ s"3gH~)H☛< b`k ;|ƌ *,[Lmyr fJˮ[R@}QWi~Аm:uR%WiPǛ8S f߽MMq f[S6>ÃXTuk C9)|#rtrMKk'gjv#yvҷ/hdfe$X ~n@T%iLVX9Vy4B3 gT4UߞT&@`D<8YO11|Vzl f,bkj REdoCĂ'rwV;VPT3S$(1&%NG@* o+{Q+d-PW[9uET~Q͌`_W7)i"HgG;(CN!q PvP2L?D&j9ŽAct(}W[dn[qO9[W//Vܝ(^YZ/ M 4 Pv2"%i5D 1} `(4U-:!LKuI1C;f!gcؘPIQ~am̈̍w&7;ZoˆaTII5Szid=c \لr=eDtlYq}KfPET餚0}VRSSyB"B}xk \[Ѿu?<|T:fڼ;\'0"Z.eБv٠\ @LL\B?D]t`Kэʻz]Z;9ǰ=%FhS)&uS,-%4%s 𐖝Ψ]<=0Д?0x=Uv3}Y6}/GNܥV5`/M/lk/w{:5 9_{m$SMٿw qydN(&*B#H)H{9Q \qK;W;T-2]};!چ@?[L"x~ ~忇. [Z!4,(i?wIS,D;̞ƳS]]tjUܾnݺu\m E;C4^c!4>ej*KjogV [{=SVϏ0NfL^ %pOu?H&˽R1͙S*b)W:!vcj#@@8~ @,z ^gg=$L{klp-jJrG/bTbϺ!^EWee5$-ƃ%Qz'&l3{9[ɨLtU9tlUۨ3S';)FS^? !DyB±NXZbhv;"Z~ה{2Qr1\e,6ADsuM|4@vœ_;N|?b&%/$M'ӵ>Po;kuYAd.o>s_R ]v?`JBQ 1qc#;Kқ>yk] )eC%֦6pw*\/7T?@7MCIfYv(9pjeh]!$6"w_O_+ԅLD8S 鵯}][cRuS{ 4c{Cy񷎵:}jہ=1Y3bȂ׋Rx@fNE<`2oS1Ё[X\j:RSSyB"~7B !$S)B!āyB}XښN5P> |gEesg̫ecgk*t!'7ZC>_`l[E΅yژ{VRoY .]-]Z8SvRŤ'9>D#Bmr[ūmg8QSСrSɻpMb+\KɅ܊fӔڰ.tڬ`-OTĩ#B'v_6~ŗ[6OMnzm*l_ZŦ-=]3u~ı.H켐J=Y8y)͙$)̼Tה{2?{~RY]+3U2@,FYP?M=.mYh>xZu#g[CSL3sAJ`éS]6 RBuDhimzܱ?o5c姠z"p}觽U-e nA:@WSVz9ӎ!Z 5׻q> "!PSSyB"/)B!āyB9uBp Һɓ$͸>P9: :YjSu닜_>G}G*P.nNU:`|x1byJ~^=w[&9^m(i%jucc2)rpp}XdW& tK?(oώSt^:g\z'y'֙ ` hwӇOv, \~*?mf-ݡoy,W8$| "o &+h?zY4h(=˷}ϿX6qFA:jڹ5^ P ﷒@)OtŁ;<79ɘ%1cIi cS^E<0+GGGDR^^m\UWWP]]/qsstĉ`p:t,o :Y%K tQL_~|'K#5)qr#}}bSw}̜( vznlvKcQpGz#7>x7hJR_ Iw@` 84r/=<{c}ԩeϑoo%5]G*ROI_P\uѐ|R]:BJϟ8q*BfSRRR&r(/vQ^ ]! 2id|rBymMl>|8̩ :~lԻe'Ry*6q+;r;gz>WtKGZH%@ӴO/7> 蝰qʇiU5~J>L\vBSf+ V}p׉ ȴjpȗorW{q\``NBeԚl0n|u `p<Sam+l۶m۶mƻQQQ/|yyyz뭷:;=dž 634ԥ$~}iI(whiI> .:}d'`/VVC!&'ܑ #U }~6Joݙ`gE5 a. .Fk9;GP6KBϟ:ښ6ϕta7-Br K:hx,>nc}}||)..Θn04Cr,N2Ȭ8򴰰p׮]ƻ---'O?~ܸ<::zKKP@QҨ)-Yi꣗SVю3t|v(Wptux/ zi҆)Va}R%1rk" dشV-9WX@5}Zt߱='~-ssvG-&• {lYa/i^C!SU*ٳg5Cyy`n(/X4h ,R`X4tiʕׯ痯_^|ʕ\0#0бg+k,-is v1Ie?9K^[yWKG}^OQTuu5q*ʮNa5y:5V&QN2X +nCqjqɎ7o-^[uY12qM:%-i썇r$FIVۻP dHMZ'MտQE+{۪ J6mx#p#ٿkUj<'):CT;lZA̟.?kٝ{bmJ.ޒs+>r򆆆Π.Qoz58 F{VЁr⛟ƻ|>''GxG\ӟ|zɇgE9t\ܷf-\of'>!S}WANa%tĽ+ܛOɪݖFdnYh/Nwʧv%ȟ`뫫*AZSW{B{]O)ɿkUj`elR}Z`̮S\w3NSouϦyS7I[]r"RN8P(8= fnχAr3Z5oOG< NT#`ɤA,o|MԌ xꩧ4X?_zׇ|j_!| qF${*26s5q~ 嚸ÿZg?)s^ﲛ#-}с|kg7+-/ܺeJwQ/;{wFk_ת'2|?69Iש3vNPTDŽ6p Ә|ܔ|d]OOO/<#""bKo.]ڧ[U&W .Vn1K?cc= s狟ŧU9p}I^q"j!"OG|;L}_J`goRJNY'=?MC܂Yw.f Q-]D<6|8{)H$2.)Ėb [#^\WyWUxih&"8B鞮_I{)80!T'C;pEtoP ?@>LeQMM~P/ͺ 9ŝ*at_w2f+ ` } H?`d˄[0إX|cGga9JQ@Bjx,*2yF>F&!K!REVaE2%^>#eW۪=G«4G*E ~c>:) TǾ?*)>HMaQV[jqU@<;>^̼^.a1A}S<~1mR#Uh 6Tmw K8,_Z/klSCg^̼^r\C7KI*XL!3mh"ۦ}~}\=k[`!qk0˞B5z SBgIJDZDz,˲ 0 f98q|aU?k899,p5)!doe-G^ɤ^|kN&991Y%gQaƻ,+ҕTaSsrRJzk(a(Կ"8a,^vj2 LRcal7cD@~~A{iDBG41qbU{NupppuuXz zYԷJtm_^vzQdohY7?a2n|1n,0oxoonuR*=<! ?B?5_L&xӞ]L:Eu0dѣYFDze9X'⟝2m#:r:썄*#vY7P?3!&eYe DZ 2 1:ѧy<4MGDDP_`§>HrR ->?!8w?t G[R EQCe# E{!P_qO/c~(8::^ՇªiLb`q_^祶VazTn+ת-OZCg81 #Jå{!JQt^mDX53ÈZk׋$ؕ'NT*ojZXaé|er0{ɿoĕ7~l`򴫫5ue2a[|ck!Q5sd*|1j\|Va>nmmmjj2v!oe1T`8\jR/a ׋g|ufuyd^/U?/E?$R)95X>Dl,uIX DTbOew"f ZSe-ʼ|r7\Ԝx7_SNg1Cv㉺Akk(+橝2i O!K -XCVFZVR8/ 磪ڧ)…CZ8Bz`r*!8=ZV\ODš}!>OG'GT_rd1eLSajˍ-@_8d`(G*1ScLc\.wppd'6d2YdddGG`dqhYkR?oׅ Uk㏟:ueXbOQWև̻ӂ 29_=iОk{OWdoYa5P#+88x*P h4֚FFVVVEE#e F;2ׯmg-MK77oFW*GÒD"Q*yMSNiڛn >22^z饗^{ogorv;;5Z6{t=PB(O~Nk^ |L7喛hO\8?nV!|7N<== 4OOޛdoٳgϞ=ogv֜쁹s̙\mž]5=֡ܧX>65:^wY*I@]LWsYzʬ$EG[[:pfzxKƖ =&5nnn7 cE0yd\{n~etjlllll쫯jIC??%m'v&?qi9+we-ULR֬YcrKR{꫗.]Z[rw],V\:]W\[2J=:J"S8ɏ)Ӕ޲!oK׽qɨ{.=K_ֆPm?Bhذ#uŊ>.wwe2?ЅJJJ9ExΤ_CMTn3/k ѵxg}թ S_>{6fӡRԼ}9(tջ?~'wSoP*o=3iŃÃXRZYƜ0.jW?|?\~Ǭ/'[aOm!؇UhK6~kRqwX~؅4»X?P( 7g`GBHYyEGGwOQ,9uSYo00r[_`Ȣkgr6pp */YQ\$6G(JLgΜ !!!ϟoVZ3Su:9Ǔ&YR|&vQh&h23"IYԟ#+f׊7KaMg:ozl6ϓ]lٲ>"pR>˰'}ġCVm>)>z-"?~GŜSBޓ 6'PaPz"SjfiFѦj+L-.cj;+?r2LSR'{TRiVGG[]x!3~k/ k.I~)/ >/kԒj-Ϗ[n5ہ lqCk;_;5tb \G[;Ej.@|L-qp0WU$TO>ֹW3!IRnwN@? 9mW>NsUPܱ71|v_N~b@-}I6v'KMA:UO6jr}A;vhupF>,woϦS#b]ic?$''ru0dhyq~C0Z^ddiNz O͛éϟ߹sgttbHO50G}}  }} &N)?oom7,2cֵ5n˜1ԩ)^!Kߕ?5Ku.O cmoina /㎚S0cj&=@d=Qx8bccccc,Y[tRHHȕ+WmC,(>iE/j7e&uGT-q8/WwZl.?} $L] ;}b%_n<NnOevwؠW'Hbi'CԩNWdJD"$G$I]$ٷo_E[ =mirꕺѴ' Z1ۤrCĀ,wfL o 3V_u[-Ԓ@Ki|* ^PxhDxDDHR F^mRg=VBNkj_R èo9st<22揤!DEnb\V"3zNmg`ja/-`,k5af^꛹vu0Ib"4zUQQ;/e y-*S^畑{rmۗ$zT ={P/[n￿{ᾑ]Ţ2E݌CO.OObdɇQ_,[tc :3655_TUDr#_ݎ{}hhƺi\n<|Y>[섃=v~ϹnN-F$l2@/u}ğظaddl2K______#`5zr8?kYb).N,VK}kw#84ȜX-Bdf>o ͞k6{u5w5Sb6cٰ".haϗLE}"Ӛ)JUHd*K)xVVVr6Pjjj oWC(U4U9j^! @EIO.^ 1E  V7cI/c);2jL6/NHzSQ}USGP@ @  h.̖0PA@З\r够HOoqo0фMhwiEf¹g|>ֳl:p oc&ug20&[3`Yr6kAy7*HpK]ٳÀ1ݝD3O!W=f\Y+!(xjyIwG-nގ%]L(ayL6,7鯣{#b;kBE1El4/QC*lk*9:R!Io(Ud#^;ҁ9ܼϘ#93ASbأ'YcXӬWSh޺ 5Cnܾ=-`D"G⽸ѳxåRV\a03p.Rᖝ'[5QrxLÕ/0uwlBC6! h=";6!?=t8_KHw},Tڬ2le:f/2ti`}WF c)(֩#SZ{}=r!F5(% {ZxW)7ܪgjii:ph#8;{xv5vmMH=Er @-.J rXܨtW K K3~eյ}cǥ.%YԾ+oSwz2I.G??9drSL-$)5=5I%᧊Nݲny ~3ٵA10'GS<+@r۷}ûO DN\o )ZWH_:jk#<[;le YY{^e99E◓ȿwjfRvoȯ%'}0}}q.3[b2t]ͼ2%&|Yd-H\یa7p1M58fkI}o\.&n +x'z|}]s3οzlB+{[[}v>.]N~r=\( ]|ޥz Æ 366^ݻwEtŖwem:9x٦\/cX./&#c\ـ똕] ^՜+*c ^)L:tgM"Ύy3vg{M< Жz윙C<5*d#> ^[LRPa60˓ns9T#F,]t֬YP%#^ə퉐f?KE"=mYW#&_ cuLZYtr<]j* Î=TC)LW1sE~1CWHmu3ÇO2šALϚ,H` 56Y!D]VoˢS7]5##ٟ5åBܣ(.ji٣HL͛?\= HOUvO7(ֆߏ3$+VCjAQfz^hX5sîu:9ܱR0>d[%!̋s3s h3}:J{,â^Y};Ux;·- 4̜4L<_l]9q-;T%S@&6U)֗5 < ,~ּy;/?_ٱ;9X[[[[7q_>86 ̠;:xgv hmy~r/u?|l`ӯhZv|ɲG:k0$"5 f88k!5U(111bWeS_@hch;)}޽{=DEcP...e _~-tq6QCNh8<=333s3L}۸`@ǟ?s&yǑԹsr8͛7#=4k#Mό_j3tONj (/-*2n1ڻYF~׊ҳ SP|c4᷌׮bq~/)3*S^畑{rmۗ$zT]FN2͛ R\]]m}p8l6b1L8Q7)՝%ԒA|>_u#dV~Lf-b |>_`@4*BbJQ7}dTß *yr0&/@ ԓP"j,Qxq6]w)?$IʧX@PLB G@ԍ :~@z@ S"DP( To|z|e,Xav?>ǣ,)< &ӄ6Pmdc\.bZ @rk)b"I Œzh:)S e-,K!LRٳZk8޳ggϞǤqiaɮb@n"*AzH){?t+ enL s14%':F:jtYff8Xn۫&tp،gjOaҡ>hwv̛;kɤCfY)@=upjŤ+Urj3[ kOrӼ/!c)gXE?YUOuV!4"K>dR*|zMYsꦰ &a`䶾6W,Jܿf.g ׈ 2g(.ji٣kbѢE'Oi:5j!O( ]S%8+. rjՎYH֒%O9esg7nq(OYuNˆ pM#Yg,<ֽAꂯ^?VR" Swq˽`Ӌ7z=!NX &9(wpu U/NKv0Ɓ,+6npR>˰'}ġCVm>)>z5ȏn1g(aygԴ?rd͉k6ovaȚ@+61v\<.&x651,Mc3]!99͕p!C+(ܡeJ6@g;;[T\r >>b \,mp )GOILsMȴm*d K00*:WmmA癠㿟6ְ*h>rѬf8K%Jߚ:` K1 40WqGM)e 1z S^(VnjaS3ݸLTVqҢ~+C]S~Zܡ V^6xNmۚ_>f1!Wu-m~xKU-Xu~SEzW*^S@&**j.]jҤы/5kV=~o|tX-["ϡrܪaqsw_rZHtQV1J5-065ƅM5Xtšh{oO- ]8qHtk׭'wWSW.]`3`~ ; n<nִA #;.?$3YPk Oٳ}֭[ZʘFDD V&JMgmo Vv@@߱%rݸsj&q> L;$4zUQQ;/%e"?u^Ip:oYnJN ׶}IҫW8L%̚5k޽ǎsrrZᘘ(jJ13pI t4ϝG+0mi[FkrLľEGwuٲz9pns[gȃv?c8>agf'ܽ+o{tsjgm!'Qe?9z#=|cҥA;֊6Ra]ARZOY~/x9x`KеCk L7p2`8Z9{'yܳ_/[#u([~!umlfڍqtbt5!0 Rc,eԥiZwӖR;3f厎r6qq0 1Pbfff*++5 K55*grهB.зlo`oQ~A! xVVV f$\dddld2 8c\}1J+>ET~)ΦEazsЯ'f~A3A'[hg: \a8HO=`s~J';"DT(*@/2jPZh B&=qU !!2jLBY˶4B jC1EG.AGrȨƧtT&)$XIE ʏP(>lqg/P'P%B Xp2t(JE B>/{#f2TLG-QG좺)d P(_haJ!'/f-mgZCQ.I|})@x<|LB G4ԍ Z_J舚9K.QP6"D@ #+V(,,iI##GGG9XE 6j'Q[Ll.|snY~xѣ#[LXk3/u2ޤIee!r<$[11Ȗ|~ޙ,z|T.]XbM5"ޑsmFj#Z xEi?V8t h 9K3׵.W]uӿ XbzESܸqcڵUunU|)-ɗ)K@+󞟋GO _xyW;Gwm [K E Á?)x%S0,TⴡM~ة37'Szj)A:MJnogg-v>Y9FAu/,g^yMɓ܎p7)J_]6{e9\g]eRXXح[I&ׯ_߿__ͮQrߗSǓ[RA@ `2?M𢮜|lS XNpӬuVLc<̹8sНs>6?͕'qJmvzM/$kiü̯ΙNѧ[?)Oݛˡξbn:.]gK&E>ikaXڛ ~>ҩk{1/| 01;&F ]1 *yQ7aOQ,9uSYo00r[_[CF;)6lTf̙m6 Æ &Om(c()iEjWN*WI q>va99X&i9]c=/mn%qN\C8{3[s`fNw&OM c/xO6.؜`Yzy'lt'Fg n_^#>[$KzFJV$;-9K\~Ԯ܂ˇgߺmޫ}:J{,â^Y};U^}l̝;2H T_TbJ!WL|O+Sk-cgE9zT7%Ԇ,{t`A^/\G[;Ej.k53ӼrȞ,z|`mZ2n(/<0:ymn Nt~yώvy97tP/m Z/~[>n; \:<䲁Knz9MdêH=ծ];9X ,2(k|Q<^4Ζwޛh ůUt,ONzx1iȉ_Jv,I V;Nk̎yƷǂA7L .iyoA8˫6]c@$׻ZNl,\|èct8Qg fĜ0=oy{Z]溜EO-/"LX7|#CT؈Ȅ MA˩QWhg\)9Xd )m^TB9TϴQZ&q8nmCꋅ~ZJ,fʔkY4i֬! 0 q&[o9tćLv$ !WPg)ܡeJ6@g;;[Qa0cucL&yҷJYb,}}lޔ5VlLc첹Z{x\LYqg6lj:5b׋/X.e>f:Crr+l+WCv6vFFǎSurEFhzڨa:t>G3[o9>ղK^_Ymi=~xaygmZxx;q̜=< $:֛<>t>LguÛ@K5&嬩l))~ۼgN[zi4hV3%ȒGw%oRw~ӥBz[[˫縣&2T۷o9L<"@oSEzW*^#\SODGZS~Zܡ V^66 c|1\mg$o ^ۂ ]M` 7ܹsYf^tiMӧ.]* F?!DioŐxy͕&K.Z6L >f^C}f"d ltO|?a9e$Y~‰cGs^n=ĭF}>귰c^~mM0SK-?d1MR+00&˗/h!K:4eZhTvv&l:L:hd`BY׭NL"?u^Ip:oYnJN ׶}IҫW8LEH}Jb;3AcY@`X)v"wof̩-j;1a!᷌׮bq~/IFm neM_)Pٞ?ijkkqgW_qa IDATpG"cG^56' >V%Qe?9zc 3_%eaPvf-Oؙu w=z[s7ݜY[&lgƍ_~i;wԔ8AzڨaY9fbE8G:?։uyۿb,fkRq,ڌiokgX*wgԱT_sTޫ-"]PSiZwӖڽ밍$K/5tQ]t% {cf>R%LǷm>#fۧ}=fE2̬W(Fd-А3sfK__w}%]ڤܼ!1iNxd^0';;Ӈw߳`G~DNo+iLRGLyY@(,Q T#1g4JLA3pH(r-̷O=>{_%206!!MJ>Zw 1r^K7ro鰰Y=MjYc)ɔ~nf3Ox"1(noZZa. nq^ě*t_:{S)DSNB!\.HPQQb-EM%7EknYNa8KC#p}[[JC jlJPd~ )B)++c2@(i=iۗ#jPq/))ӣQB IŚTLJS@(5 FQ0 55Z@4(>]@zH$ǠI-++ 2h@AYY|!j-TY&"I:222m#QdffhTI1Z[ IEjjjVlEXeۦRݐ%BTkSJ+@ QQV[_<)dǤM3׃RW1`?,% 0 CTdffjhh(D]!IL]]]JL*ʤ8Dumo K`?fMQ]dx?@ HOOP.XD](+++..p8TëZd*UR.2 Lzd2U`#YYP$z 5Kj2T|>???ڿH@(jgIPhTg*RR-}P1;dO.L&S2>%IR%PK*&:B@ (..=S:Z+hoCMf*xM5`)Lb㒓D)IM"4PAKR@0_HMǪ )%p.Je2O~T'Lj5Iԗ*.$IRAHL)D$I5j sjjt_Z"fxX 7(ٚBNW6N QV*DI@ uIOD(2TjX ?E)wusʢ)T2\QmT^^nIɼ}I1UKVi h+SME}5%k]T/xb?S7ZM] 4TRūV6֤(BUBX t) ~ "^?D !h SE\.1i JLԮG^oOqF E-~tjYOl,߇J;ZmdI4XV 5uTE~)a&* rߧK)40&IeQ㤢SR=\/eIC~)ªfI\S*NL:)˥K8T4ԸRI)I=y<2pM5>_SRS@5~Ukzx<Ŕ q3qIZMk Ikh)ĔK&L4U95ѥm%$lש('L&?IC/_P]F %Q]&LC)tST/hI/_ʌ,UQ2J2^ YfR }W"\Rp yRfĽ&WEH&=Uڼ:!%K^(߫Osi|o%5TK&F^n$:`ȂQ|@ S"s9t#m =E )@P }dQA02v9~-%5͛?=7?zt3 Hu#O2Q C)AKnYOܳm} ^G_R8BYjԱ+w_})4=;ࠁ02vk?xn is=kAy7*~byzh+D"1!r.ҥ稞:ω:iwd#]nc7OU|dչ|DCǧrjՎYHj YtkXSVz@q?׎o{y1.A1]nj(/Hwj*ROLpkj^a>Y`˪iik9B2 μDGZ [VVVe*`sԘA@/qv=_2eCY_Js8ZsΎic[4Qip=%3:..tω{Br)&3 F*ǬX?̕cD^2fg ti}:N5A+wdyp폍&۽aj \U+&$5CV22I JvAW18$TH{N)0VV (iaĔIUavm[ߡA3oض#>thIŭrCkBnU=cݗJI-|l܎~ ޱJ~si[_㪫5teDwc6ѢMB "֚iKnpmC3 eWfUax%D`퀙AsGVJ"n?`J;o>erZ6-t^(u:u#Dέ5S_WiϜ6*Nr˸$lU|Z(r7LA3pu$›O0qzK}fl8H1RL97)Y^XPRB=ϖ47 _skb0ޡk{J}?n9d׵!_3n2 ȲOoª= ,yeڢKzԟm1Mh1*әcݝl,ycIi>ߎ@̾iUgA~}oz)IE )@2jl^ Q)I^k/eQUEȤ8 ^K^k/eQUE$L*Hz! bI" Uu 4(YSK*ɔOI 55T5تTdmȳlqgm!Ը𚪺RBgUp2LH|>B^FU]C~)*VnfL&!IRiG0 0ꦐ%B`8 $I!{DU]C~)T%sYKۙ֐$){TO/T5Pa(%@ S"D@ :GQX*6OEUGU5bU)ǣ3̟&$0L{P7 \ Uu pZ)>b3o($M5ׂL89!Q\.p%btA'k/eUxB;*sPaaп0-ӭGx<)񤞒C@ }]Uu t~y- $ZL$ [Ư2yu% VD b{ !MU]C~)-5UEOp I HjG6ؿZ2R'YGu.2]L)AT` !yT52#*BRdTK1cp11}ƧSr$oJ^k/eF$ E!)R7X/F>J"#5oI#]KqB,,UZA!Gb8 BYPS$|$XIE89߀ O=Uhe 0-ca(!*cBٞHODR9tSS1)P$hl&-}I(LiHOD ES%S`lWA<~)?N:c+nRlj@{JDgME>X 4wi?p̑>(@TfTOӎj_IzH,zdY-0A?=SaC٧1CZug20&[3`#G _&sUԝTa D+qk&/k7xV+g+hMCЉSܼ猱?3O#pz۹}0M3>253BCPrT̗o[icⶹ5eI۱o\ CGѡ}6ɾ`(kW_ FmOn%Gޘ%=z55r,L~K Rz[*:8Nݜ>M Oⓡ鴾nU M?p qJD ue-G= ^WV}Fk޽=b {77ż[/ݧe>>S1*tˉ}Nk ǷX#36(,)G?Ԟ<9YL+jjfim,xO]q'n83rfgeVpMC3ݟl@;%\+9+:pdɗ>o/HJswvケ<$LK LI!ń0F3F2X4%G?j:dAFCAdT[0 !9ckBM6}Y~Lc9g/]s< 8xVtĢ;R\>}w$=yj]ɽKa}K?zVahvۜ'u%>yjK-e$8yۜעuAhW/_Z1w'9=DǑ#FKc"4MrMۍǫUDHXcߍK-v?s$2Ǥ'q߯.*c5#|y^%#+ŦШv`N&>kv9d|_5c;Uxג2ӥܞ#M0-}ǂhz/iUu fJL(]9{qv/++k{ۜ$7%Ųx?ȣN[|b][=DM۽󝒆[gfS#P^^^^^^[.tÈ/E8 LY Dxur= "X[͍b[:(qs`$cM)AҀb%Sxq8CAHGBD6_DHM$2{RS.;NEWnuoOsB7@[EHNFL8Ertdnց* TTi΄SQ>qB~.;R-E*Z/٩)RCթV73-뺼Qszw*tِAt!CXRhܑ!_/K ,) kiBBU {S4K04M|J#]".33Wgs fP{`  =[[[333y" !l{Q즰XV#(1fBpfPF;vIDAT8U/Vt ̀. A3+~+;y/_Gp7<*yE᭢lN FY $;Kb,5NF$@Cp) \@vb" [hV;A rL3km)Cp1Qj} %?%"ŀ+ lY"n/ t bIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/square_root.png000066400000000000000000000010261423020056600316420ustar00rootroot00000000000000PNG  IHDR;0IDATHKջQߥ(PHqūHxF=*D"*n)^J!HHO&㜙o=4笵k2Ggjxו_9tKJRo <&\!Kī)=a0rwA[_C/2 GqB类oۈ3fjOq=Lcm|"T݌#gpoMM1!}3E*_S*#lK/U+؍d ({]q[: 6mӵU{B UlMrGX^JK)sQ0 ,G,-}$0r4v+cçpgSW2(Qa88ʅ[8"SJ2?2Tgom%W6klX !}]=$O9'Tq5(.)Q.IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/en_US/fig/standard_mode.png000066400000000000000000000532171423020056600321140ustar00rootroot00000000000000PNG  IHDRZ#D pHYs+ IDATxw\.R4Q5Jbbbbb)77䦘%{P`ADwvgyء,;O"royf!B8:: 1!$! BHq` $! BHq` $! i"jX7s"<4ޑ!*VBmj޶cɂH|_Xz P.9ުā Be2_W5Xk_XG4~5(ђ-۰ нkBW'^jrjhjnܛmv Btt`@ tpA{І_P2^/HB&U[up:_l祴\@Ɇ1q@e A}pA4傈q8. (1vف5?աu)?ߊzƁnCX?:Za;iBASGBHZ:;F6<5=hm8@U|?+#F FnD M/zb,j>k+:e_no9ޒ3)jzG0n48>I#Ji{f#R:B{q&F&;Z-4P7F& ZG7F޳@q ݗF+@]#uEm"U@7~vaR %]H? w@PpcIa$`nF 5/޳iґ׉zӖS8Ԏ ju_5YN=``i` (j)&`Ej7y?)K50 ֻ?Bho4jFAnB_[!lj ?) @$s@Xi oO q&QPwA~E5Ps ™9x>$T[{GhP>쁯Oԝ N?a&jT8w\gT;Z3@!!^ [pfA%?gPKzQBHnZR;E0s'2v5;m,xzP;q3w"2 ́w v4]2RLdq`2 =  `GtPˠ^[]TjxP[j-+.iK_wWb;*V^^lam0yEW$\͸Wm7&E9DIѫ"'?;6Du/6PŮHbw$H(ѹa#%w=S[: ~7C~r j\O8Qp.b[*!JvyfOxz1|b0FOGjTUMLF$i YЖ0[EBez휸)}vMTɾ#-``)zsM9#Τ,'w"("{U+?*8r7\ZԸP? ή[+>{~LѕSG73  bVdP|Qef0nczK@e50x1JzB+7;|9@.%dO2HWWJ?dkͥ N8qߧj*Y@~fjs8:hO{âI'DM&T[UgXLlUϢv q q0*.C'Xٳ/kΝN+ m^&=ck{:l̐0;8-b'wՏ_3EPL%30 Kv }K*2()&tJU CX71<" 8Bx 20-~ .C1'!@Eet9HD"O+_J [1c36T8h\$N6V* 7Ywn/,&!&O,sԾsGu5תJ?s*ϡ׈0&Sץh]G`Vm^ Tld&NwiHI%U-aCHaeZ<)FjGJ7TT7+:""V(IB%TeD].Up~'lCy% juc¨C$;TXP_n6jH7SgN1ڷdͶ/.Jk"~mBTLX1X;;9uq^zئYNrfۙUͯ-]|kjZb4 Ӫ]#T3u蘗^ctw% Vt9(C@ѵJh2O - $ptH%Op`բ'-+ݩ] Ę(`:~kLv aw/ VQ"hݤ*%Y??ȥ}!!\RS6XM+ʙYldWVB%]cnKT }aX,=i&eբ~\`кͱ&} 5ptΕ9Ǝp *~?OaxW/n鲣NgѪ}]hـ dbϚ;3ztHYAiﶜ6_l.Qdv[_atvw<=UC3fR,`7ކaDzՇ'h6'ԔF-^?>ѓA$?'L|I+װW1/ d,qP.$ wW`{&uo6qp7G󝢦5Ws8z.;/0#zJ^}Dž܈dT]=J항 mca̙ 7XLcQŒ$KˑHQz[Tցs $Gl̙ X@&PWOA58,^nF&:KkQ9@髞Tڳ̍rPS5j'𳺲c.15 GSr"x~"h)􋮋uBn,4MUyppu/!qWuteߺ]H:JA,3.N\S<-kFq&F8D! \%vdNEԄi9sXa!؃T1E XagaJ9ܻAC-8b &"-x6VHXKةӂ~ @qo~kӒ4ZyxC'DՎĒGO,ku5%q6bt"C˨&̡ꚉZU 2ĪkmvвJltә1A]s֛x"&d%` ҃:|ɭ?$Tdfq:*WE&z^LsO.F~6Lx0VU*"wQ9~"9%BGݤbeP\(f'1-g;M k1y.&v~/~.Q"싩STBʁ՛h&j5O"mROP 7һ(Rz;3Οq6JMޕAᎍJmafڙ}{ϟtd3Sht UWv.xQ=tփ1κhuErHgH=-Q+DIo?AvZEPYҺTUN~Ա=ÜrWŊ*huJA!ܲn-d6e ;BU7ၡ`;ǮA9Tھb$K6aǺԤgd?2?'u*8z*2 N.l]cy<ަ= <\_aN<"ە4[PA^(7oSMĢKGj)@Aꁝ57Âã>pDr_섄0-<0Ⱦ!*ة9zJէqqjK@kNeM%Tk?{3g!2@X;\cm*#U15[}O1e*ОGZ]u81е;~_r W:pP6ٿL˅ ڱm?WaBJ'2*2^c׻7)- ih\3j`6hDCdզ:IJDUeڼ?*b|`+? Sw;~CXMZfkHWql҃ێ=>X jH`|) Xḿ;elwq?e<_ȅԭ40qR¬#N=uDsi\ѓM=NG(P"XY2MK4 R$MΩkdX0%_,PMD7NWDž;bIvV Bk[ [0' _\fOY&%܊;^mMuR2Ⱥߨ+Ԫ8VVVVV|^Mƞ囮eS`{EʾWաؽhjf~qII~f2DcAyAu*;?q"L`pRZǭWF73f<>nxu10w(ݼV]-r xt|tEN e_umKqR0h`eggc pG#B>!$8@I0B!$8@I0B!$8@I0B!$8@I0Bu0ZW);e*lkt"cU^=nk_i+X^Uu8΂P-9u*1?iwhe7O<|Zoԣo^x-H;y<ʍۥj7}FNJ,;|tuN=w5s ٯ/֮K(b}{Ot5x 5mAډI)w-}Bt$j8GnF o# UBs4]pL 6ulL:B8RB61?N}mсd:CD)%䱳7ڟwj͛Ztਾ?Wζ Of]|׵  g6,_$C;Ȫ'uEN==ғNZt,Tܪ.Zz-eWwܘ%3Zy5dzzi۲'K\{ S{i۲nU="eO؄jWxv !G`Յ7ZrDenZKBYF5nO*'1};LG8:P;)ܛS OVR?C/"Е~z 13%Cu^xHAВԽnX.6 ίsۗ/;1w6r`ߞnj 'EMa@v͝6zԮi̓k֜v`[sľK|##l@ ۿ79WF#ǎ@t_wM1*H:k⍪06x%=W{BUfW8sD QQd8P J&3ž.T$*;nqMPOm= v!݃ rx{s7a}j*ǚEY,}ˑ ÉXTTF&j qU[q=]8Zyh$mÂm@䔃:uۿҵy:Pu%'6OwSxUsϬ@)hs*PWLHm6@Y jfcJdޡv(+-ߢ'n1NWbeyHlɆ;Wm& u00?`4`LB+~ltΦm;~c=$xZN#h<ƇX>*嵷1_Yҁ6[?K.c2c KxkW7{ѡ E)۷LZ.Tx8VQ+[jcU81gӡƁR0v4B K8TiZDei fgejTޮ,;W5M+-A%CҪT>qSrߐ"׮9^1!qxdqՎU@"sЦgfV] ."}i}<䏦 l̰ѓ5$^6'RBq 8$~q=9Pgp#pb;kn'mvN5>жَ≳EC!Veg R)*YЊ#u:!M0 -jB"lXHwf@|BcT /Q`lA@,gͦ~CGG:4\~ 'G[mɋl*ݛٕitLK6ZnIwicƁ+ŽpnLJN>j5O"mROP Ʒ[%XxvzYrVXQ_J/cK[b~ZrJ}̴8ok2v׉1ܡBp̾۵ODžDpkeNa~0ZG$wsUJ߭I$2HPYс4,29ItG3Ѕ¬r'cd: .+o$==ӳ}hy_X{rtݍ&$>xō3g5w9Vh4MpTwե WN&WvpVQdz?)}M2>,P}ubmyp"BHq` $! BHq` $! BHq` $!  fQ8 ˗u<Ӫv3n^+wܾֆϯ >kւ4r+>+s ZӋCr7zc5-9(7a02y%蝓^j@}{s8_1x{qay$ |og[{w cuuVN}YC$` $36oS#g=>_0Kyf5i!!=f| miqo5i.2ScUX^͙h/l?[[BXGoh_Q{0D' Bai%Bʦ*j} u"yiq\Q!Xx9F'U^s q_dBmA;ƍės[?篹󗞝6:QX~}rA ec{;q f]]VY:/#Z ebm[ T)\^If3ȹ~vPY(79[Jd*jI=sstssScu/oE{zz3#ԉUr +?lw+3׽4P5olTHV#>\H^{zar16^A5P\\l\oMBmgK$ѨG^/jķ~>Ç~3fo+#A  ԉB!$8@I0B!$8@I0B::$Q!$8@I0B!$8@I0BJ$,0 !p&PJEQһ^ʼ<}2/:CZDZ,{5˲ <7sOW(@ʼ< dƂJ2I,R5y:YW(@ʼ< 6Ÿ88ad10 ȼBPAgq%#emɼBPAgyFāiT+yyȨ kT+yyȨX0?T3U%Mi45a% x: xW 3P#bκ&kK}g\JǁlvI_%,ƐoH+F0rsoiXT=መ蘸~CL?oWhJӨhIy|h>Mך:5{U$(~vyfb`s[r-:0?vxṿd}sQZPeWny7]7_|Rb=_>܏#nL$:[Xg>^?*ڲF-ӦHu2ȡ_viq;kH n9n0kݒN!OzM~Oxw;-XɳYh7Ѷo}UbO3FqZVxcBqÇ3}mV'paNtۢ]i'݋l;QY{k)&fnY8xOH +ClBܼv_5ߣ־Q XcZZ'u?>Ծyvӻb߶-bέ|F Bg>qQ2,Uhvf.utwU˶Ž&:[T0 ?G+нA'(%nCGhn;TB۷^ ot 4NNzzbF*h4E~:sY>}*{nBLLLLLJ+j?_阹i -+x[lָOˎ]^v[!(•mۮ&ZZ# }䗗Y-Ъܥ+VXbu,ߑ{:EmueN-zccòϞǝ\ɳ:A;C ig&G'Ƿ-ou=ٷrLk:ߔ-Yj{Dh{NY!fl=u:ƌ1u i??2ΐWɦc؈Yo/\]n,}}WQuvľvgٺN1=2нwI?x6Zt/+=zї Wo*4Ot~gl ks={cqLn_jw`3>mGI!WL1Tbjow!.tƿݒrcv hЄ3wN ;ՌcвxwR*nP ڎ@'7}O5Ĕ#m.^ۮW[Za{G~a߯-zנOF:w;ֲ gVzb+ف-Lo޳Ř]|=]młVqzǣLr ][D:378락OzesJMǽw!4v|Ѳd\#:+_uk.;7}p)2xIzzgKja1+lTWmhȼBPAgBqкS5F%ɼB x*Ɉ8EdfHd^VGFdDhRd^VGFdƂտԌ+yy e^t gT"2h"32P+yy*l{ZOȼBPAg)9*yA|9JW(@ʼ< ʃ) dGy2/d_˃P>< !$8@I0B!$iu;x'J2vZVZȖiMp'K޳,+]w)e lY * ^XU;SZVZȖ 2.8c3n` ֲECZ~W8Ȓ: eֲE #_5ֲ5x1A#,T7֯[̌Q `|1I*0 c[<3FPa $! BHq` $! BHq` $! BHs%"dz<}tc* F9q:… ,X`ԣکvn­RᮦX01{?z'g;eʼn&$튉vN>=w\SbbCBWS93}߇]-kgf=;,XCw։~ׂܵDO+@͟b6Yp<dBL,~l"%8~+Zv5yvb_t35beh6$%%͟?ԅW>x{E.x)޹fCfMZU{s*=mIn=ǃ-a6[q .|g+L>=66VmRRҊ+>/ՑէGz,0WR`20 "}js3}|JJJOLL_}դ$^}ӧwx93!QjS7WҼjNw=.N;ߟӾ{o3+ʡo%-\pܹ;o޼W_}u֬Y/7o^H 550VBNVzZ3,z%Dw۸7K|Ϝ?ql};1kco7GM]i5kW_}5k,sikLNNs?K{h\?-$tv=5Ӱ`\]ɯ%봣9s|III/׿xHsJ^ϷF#dݼm6;ܛ ]6nٵ헇+/NxAys@l}|ng`Z...Wn`޼y>nA7`XҚ/S0~Q{}ΊqKKa=) !W`y$q̙?7}Ŋy+V@TGNq#ٴYRމWF7}"`ܽ;%^v;bccCCC.\?All,e49Y!|0wuO>0ßVl{׮7@-;/g3܉pϖVglٔd0g8gΜ+W^~ԅإ|xl=Wm*Q%e!ktl,9k'ѓt ﶪ&w̌ozWG8N|A{p_'Lff(b IOOl]-,,ڻZn~&|/ϾQM8ht ΖBȄ0B!$8@I0B!$8@I0B!$1"(_iֲ5x1A#@ELTZJ-fƨA0S7֯[̌Q `Ư GjYi"[nqS<ϛJE7|f~A-7= ZTVֲElPkN ,2 C:E((p4/(e}<2qHg/(F0$!$8@I0B{!J%/(FZDZ,ۊʊgYV^RZJٲ>7T*j,R5wh~A-d\p0f80 ()e lɇq%u,o1*e lFāj: *ek3cTFāYoPi-+_4ncb:#ITa7LUIyf8@I0B!$8@I0B!$8@I0Bv킊]'B n0j,8~ 8߁5gRn…5UŽqt3.>7:wPv>hʓsǸY9Ă3ys%)0jk|. >z'.e\ 2Ezd=m2eâ=q)?ϯ(˳ʮka鿢L][;'~湥#|!Ou>|??Ե1k|6D$dKY nW? @}VjhNn|z iOU6[>W$fmauiF_;S'|jYfM%<d>wbHټ^m,jNYCl Ij/Oj%vfDÅ{2̳c]"twB+,Y-tqH{`.9W"-Mcɞ zSVR vv8uqӯ}΢Q"6 @V 6.U7vf|6;0_.׳1Kޝ7}݋֦=;|j uU-/M[^ ,4g\qk!}´}6γ (ߔ7c}IeyWkK0j s3iЂ]6r9o(Ђ=ļ-޲oƟ^X浙O~TҚ+nʟe?|g]' 0pCxj`+lBùr#H@4 М?{D/b^O=ECW<ߝ{ce{Ǽt+=|mo-~oqh.#,׽ǗDOO&iiwH@\LC,iWs|*ЈPo{Nؽ2?<_?aۗnu4 JZXyݢ^^|GS}8n#}njlA~QeǪguƒYg߸9}XEU˖a_~0>ҴB{hrS&f80밷898 jB 쇇COv*Ĉ8BfGpVLBU0B!$8@I0B!$8@I0B!$1"(5jPi-+_4"DwՍC,`YVQi-+_Pd0"UoPi-+_4"r@U~JkYiՠq әI`J:3hDBHq` $! BHq` $! BHq` $! BH3)wZ4geEiax{S>?}7l{<˷II-ղ/>j29-;uB uɏ=k |zѢ qЖBۙ3hىeGykigbqQ:|/-;ۿ]y_u4\~ң|NC]\;S ˈR 1gے-,!%7g| &ّjʫ3?Ztg@EEnTZ|lT=> fi%Ţ6}߭)pO{慙}=δ 1 -ןQ"Z{vE[f'ppߗna=ޭ0K'DK('vvq 렡=98oBllMu#Ӆ-ShP3:/?-\ `&}F_3U@llm `2D' K6tlԛ<{tjszG絳4Ueު.pwb 3FvI_cG4vNp809HX[1eX!zp}s{&u頪sȖM2Gdkkϔ=Dn^1ugӻcu6EbMteu+]zMz'2nYD^/?.j+ψ9_?X3 ΅{zz3۔SJkYi"[nJvvٮB8@I0B!$8@I0B!$8@I0B!$1"(57֯[̌Q h'oPi-+_4"s~JkYiՠq f `p$/(f7YDQyֲE,hZ3KSAZm3wPZJٲA9u* ,0 !RQ[8RZJٲVIRj8SZJr#xBHq` $! BH= QZJr#X_oW޳,+]w/)e lY * ^XUTAi-+_Pd1N70 qJJkYi"[n!-nbdI˲[JkYi"[nq`Ư~JkYiՠq`TZJ-fƨX0H$tSU1-nG#B0B!$8@I0B!$8@I0B3t ]b"q` $`9ӣ]p$Ԣlѧ}o<~1l#c쵷mXKgn}Afˋ_|fqIalͿ{/K)D(7yŁgo/;/.1nCxw-Ƈ:ͭz~T3>mjN5iJݱʓf~N@^C4=,n }8я[sوNDQ@ `<єeΡ. D!^ ԕ+m//*{-\^|̸Cfqt4N5|ז|ʏ3=S Sin.h{mZq #͵~ Nfxv}+n]?G^YYbJ49w}gI~x/9@9q/<6 f4wz^7.0()f<Ĝ=행}>||*/jEQс9{>~Ϳ-?_rVUTQPJ ARڇOv, d,,h"eݖcP\3DK7f8I:3u?a=6,\3jɻ|l7S0L]LΨBα?k 飻ko^,=zkO{wq;66 '(I F.- i J"j>TJiBM4KZP,"(`,46.vػ3;6gln67d!c1Vg$ihh(..NWc`&p-myGMdb!:\, tB BH:@)X!!` uRB BH:@)u w>H h[d&ajԁ [b@"ۖ7O P8$ml[ޤ?1V@łj7PA? @t~hHo03GB #m AH (yJٽ[/dB|V4;@ B¥y-p5$p* t0fYp%:#KLKNa ƔN.\, {GX&/8Mez>4鮀q _2 X!!` uRB BH ]t|,]i1޺vbnO:u pW}? =M߭-k׾~#q#Լ+Vr/o3N>?/%sתVYBig֩kV!=g7<5]m=~.IrӶ܊a5g%b'ٳ=2螚fM#^ytËe'urHivoyJF(6lO9 SsӒezMZ8tg͘bT TL!:-]_ݳ/C{ssH<(9y݉`iYҏ/+&|MN7995R5Ӈ-W+I${Dwv5*4s.9fd73_?5Du@bnAq$D"ѠFlok$7/w %ͬ:P\Z_ `a,y5U/7BVaϣOJ!\B4/! ՗h8Nrv>uAS5N&N`>&Kќ"?ok}HK 0@]p+^p%L߲y׎}ogX,8xh+_^X:Ԭ"-]xFq(o<9#F0Bem^7IE訯z՚?wey~ggȯlmk~ڤ"ۓן8DF"aLp~A:3&1 aK<aaɨM"9y1F)ո|H)I'llI^@ D)=Jy3x_ÐlP(QԿ H֤ p ؊DRg8Erw(Hۊc{ Z5sx? SNrG@vUeOrz$^Tgq X !ͶKVs **模式**,您可以: - 选择 **标准**,切换到标准模式界面,执行基本的加减乘除运算。 - 选择 **科学**,切换到科学模式界面,执行函数、指数、方根等高级运算。 - 选择 **程序员**,切换到程序员模式界面,执行二进制、八进制、十进制、十六进制等复杂运算。 ### 标准模式 ![0|standard](fig/standard_mode.png) | 图标 | 名称 | 说明 | | -------------------------- | :------- | ------------------------------------------------------------ | | 0~9 | 数字键 | 基本阿拉伯数字。 | | MC | 清除键 | 清除所有内存。 | | MR | 存储键 | 重新调用内存。 | | M+ | 存储键 | 内存增加;将当前数值累加到存储器中,中断数字输入。 | | M- | 存储键 | 内存减少;从存储器内容中减去当前显示值,中断数字输入。 | | MS | 存储键 | 内存存储;将输入框中的数值添加到内存列表中。 | | ![icon](../common/M.png) | 存储键 | 单击![icon](../common/M.png)展开内存列表,再次单击折叠内存列表;关闭应用后内存清零。 | | C/AC | 清除 | 分别表示清除当前的表达式内容;清空所有历史表达式。 | | % | 百分号 | 用来输入百分号。 | | ![delete](../common/delete.svg) | 删除 | 点击一次向前删除1个字符。 | | +-×÷ | 加减乘除 | 基本数学运算符,用来进行加法、减法、乘法、除法运算。 | | . | 小数点 | 用来输入小数点。 | | () | 括号 | 用来输入括号,单击一次,同时显示左右括号。如果从键盘输入,输入左括号则出现左括号,
输入右括号则出现右括号,若只出现一侧括号,则表达式计算错误。 | | = | 等于 | 用来得出计算结果。 | ### 科学模式 ![0|scientific](fig/scientific_mode.png) | 图标 | 名称 | 说明 | | -------------------------- | :------- | ------------------------------------------------------------ | | F-E | 科学计数 | 单击 **F-E** 开启科学计数,再次单击关闭科学计数。 | | ![icon](fig/MH.png) | 存储键 | 展示内存列表及历史记录。 | | ![icon](fig/deg.png)/![icon](fig/grad.png)/![icon](fig/rad.png) | 度量转换 | 分别计算角度、梯度、弧度。 | | sin、cos、tan、cot | 三角函数 | 分别计算数值的正弦、余弦、正切、余切。 | | sin-1、cos-1、tan-1、cot-1 | 反三角函数 | 单击 **2nd** 切换到第二功能界面,分别计算sin、cos、tan、cot的反三角函数。 | | |x|、Rand | F函数 | 分别计算数值的绝对值和随机显示一个31位的小数。 | | 2nd | 第二功能键 | 单击 **2nd** 切换到第二功能界面,再次单击返回到三角函数与次方运算界面。 | | x2、x3 、xy | 幂函数 | 分别计算数值的平方、立方、y次方。 | | 10x、2x、ex | 指数函数 | 分别计算10的x次方、2的x次方和e的x次方。其中2x和ex为第二功能界面按钮。 | | ![icon](fig/square_root.png)、![icon](fig/cube_root.png)、![icon](fig/y_root.png) | 幂函数 | 单击 **2nd** 切换到第二功能界面,分别计算数值的平方根、立方根、x的y次方根。 | | log、In、logyx | 对数函数 | 分别以10为底的对数值、以e为底的对数值、以y为底x的对数。其中logyx 为第二功能界面按钮。 | | π | 圆周率 | 约等于3.14159......,可精确到小数点后31位。 | | e | 自然常数 | 约等于2.71828......,可精确到小数点后31位。 | | Mod | 求余函数 | 显示x/y的模数或余数。 | | 1/x | 反比例函数 | 计算显示数值的倒数。 | |x! | 阶乘 | 计算显示数字的阶乘。 | |exp | 指数 | 允许输入用科学计数法表示的数字。 | ### 程序员模式 ![0|scientific](fig/programmer.png) | 图标 | 名称 | 说明 | | -------------------------- | :------- | ------------------------------------------------------------ | | HEX、DEC、OCT、BIN | 进制 | 分别为十六进制、十进制、八进制、二进制;其中十进制为默认进制。 | | ![icon](../common/back.svg) | 全键盘 | 单击返回至全键盘界面。 | | ![icon](../common/bit.svg) | 位切换键盘 | 展示0~63位bit位,支持点击每一位bit位。 | | QWORD/DWORD/WORD/BYTE | 数据类型 | 单击按钮选择模式;分别为四字(64位)、双字(32位)、字(16位)、字节(8位)。 | | ![icon](../common/arithmetic.svg)/![icon](../common/logical.svg)/![icon](../common/circular.svg)/![icon](../common/rotate.svg) | 移位切换 | 分别为算术移位、逻辑移位、循环移位、带进位循环移位。 | | AND、OR、NOT、NAND、NOR、XOR | 逻辑运算符 | 分别为与、或、非、与非、或非、异或。 | | A~F | 字母| 仅在16进制下被激活。 | | <<、>> | 移位操作符 | 分别为左移位、右移位。 | ## 功能介绍 ### 千/万分位显示 计算器支持千分位和万分位数字显示。当表达式为千分位时,您可以右键单击当前表达式区域,选择 **切换为万分位**;当表达式为万分位时,右键单击当前表达式区域,选择 **切换为千分位**。 ### 符号容错 计算器支持键盘操作,除了支持常规的数字和运算符,还支持数学符号容错功能,让您在键盘输入表达式时,键盘的中英文状态和大小写状态,都不会影响输入表达式。 另外还支持一些特殊的符号容错: - 乘法符号容错处理:输入 *(星号)或x (字母x)都会触发乘法符号激活; - 除法符号容错处理:输入 / 字符触发除法符号激活; - 加法符号容错处理:输入 +(加号)触发加法符号激活; - 减法符号容错处理:输入 - (减号)或_ (下划线)都会触发减法符号激活; - 百分号符号容错处理:输入 % 字符触发百分号激活; - 小数点符号容错处理:输入 . (英文小数点)或。(中文句号)都会触发小数点符号激活; - 括号符号容错处理:输入左圆括号或右圆括号都会触发括号符号激活; - 等于号符号容错处理:输入 **=** (等于号)或按 **Enter** 键都会触发等于号符号激活; - 清除符号容错处理:按 **Esc** 键触发清除符号激活; - 删除符号容错处理:按 **Backspace** 键触发删除符号激活; - 字母符号容错处理:无论键盘上处于大写或小写状态,按下 **A~F** 键都会触发字母激活。 ### 表达式 + 在当前输入表达式区域单击 =(等号)、或按下键盘上的 **Enter** 键执行计算,当前输入框中显示计算结果数字,表达式进入历史表达式区域。 + 重新编辑:单击某条历史表达式,可重新编辑表达式,表达式显示在输入表达式区域 ,重新编辑后按下键盘上的 **Enter** 键或 **=** (等号),修改历史表达式及联动表达式的数字结果。 + 表达式错误:如输入的表达式错误,则无法计算结果,显示表达式错误。 ### 科学计数法 在标准模式和科学模式下,计算结果分别大于16位和32位时用科学计数法显示,即计算结果取前 16 位/ 32 位乘以 10 的正负 n 次方。 + 当计算结果为整数且大于 16 位/ 32 位时,显示数字+小数点后 15 位/ 31 位 + E + 数字。 + 当计算结果为小数且大于 16 位/ 32 位时,显示数字+小数点后 15 位/ 31 位 + E - 数字。 ![0|scientific_notation](fig/scientific_notation.png) ### 数字联动 - 当一个计算表达式显示数字结果后,可以继续输入操作符号,此时,新表达式的第一个数就是上一个表达式的计算结果。 例如:当前表达式是 10 + 20 = 30, 显示计算结果 30 后,键入 + 号,再输入数字 9,会新建一个新的表达式为 30 + 9,按 **Enter** 键,得出新表达式的计算结果为39。 - 两个表达式产生联动后,修改上一个表达式的数字和操作符,如果其计算结果改变,则会影响与其联动的新表达式的结果。 例如:两个表达式 10 + 20 = 30 和 30 + 9 = 39 产生联动,如果将第一个表达式的操作符 + 号修改为 x 号,算式为 10 x 20 = 200 , 则第二个表达式自动转变为 200 + 9 = 209;根据此规则,最多可支持 9 条表达式联动。 - 重新编辑含有联动数字的表达式时,修改联动数字或联动数字的表达式错误时,联动解除,同时会取消数字高亮显示。 >![icon](../common/notes.svg)说明:仅在标准模式下支持数字联动。 ## 主菜单 在主菜单中,您可以切换运算模式、切换窗口主题、查看帮助手册,了解计算器的更多信息。 ### 主题 窗口主题包含浅色主题、深色主题和系统主题。 1. 在计算器界面,单击 ![icon_menu](../common/icon_menu.svg)。 2. 选择 **主题**,选择一个主题颜色。 ### 帮助 查看帮助手册,进一步了解和使用计算器。 1. 在计算器界面,单击 ![icon_menu](../common/icon_menu.svg)。 2. 选择 **帮助**。 3. 查看计算器的帮助手册。 ### 关于 1. 在计算器界面,单击 ![icon_menu](../common/icon_menu.svg)。 2. 选择 **关于**。 3. 查看计算器的版本和介绍。 ### 退出 1. 在计算器界面,单击 ![icon_menu](../common/icon_menu.svg)。 2. 选择 **退出**。 deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/000077500000000000000000000000001423020056600265625ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/MH.png000066400000000000000000000014361423020056600276000ustar00rootroot00000000000000PNG  IHDR#=*IDATXMLQP(Pz!AL"&PЭzлHFz0F@8VQ8h.XhK UhBC%[gX[&̛ߛ7 ) 0)RFJB>P|?du Lըm\lnn@@Զb ߸z ]8+,-  +++^,`;{:%((n,k%x#7Cj^K ƏC^0E͂C۲ H[7|3&0ZI4;;h4&I(%5x6*/E4:=^<>07[p_ћr L__:::R"4;j&L[{W0pOEI\J@C_J6]Ɇx<( !c0l&,˦; dIVe\.l63W9 ŠVa3 PVJ{o;{IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/cube_root.png000066400000000000000000000010541423020056600312510ustar00rootroot00000000000000PNG  IHDR;0IDATHKˍQϫDQHQ$LLuFL2*L;-Ld K$Vs;S=u&{={}{&k\V~>kGR'b3)`0!iyb*!F5wOc00gyo{9vC] ̇qDzYpp\*2~۱ m=q4]6^aXq8%dac]q)7M> 5Ǔ^b^dk~ULnrIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/deg.png000066400000000000000000000013211423020056600300240ustar00rootroot00000000000000PNG  IHDR"":G IDATXG]g̦yoIH Řbx+RBr& 9 aj!o#& 52yY_{/~{}uwNFvC'Jt8F..y_Ջ6yKC #tG͹8ϸO )oaq&W<'9w(s`o$`>`hj XfmY#a;N&!8 ,.0e /qJa!$sORa1šr $8%lSH6akBq37̅0WRDv"4sr Nɸ9VF#tpGCfegz:+3+D[[R뚝2?V#FIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/grad.png000066400000000000000000000010571423020056600302100ustar00rootroot00000000000000PNG  IHDR"":G IDATXGͫQn@20V2a6  3J)T(F@H&LBUι=ٳ{3$klH8@NIEnζ"qׇd1`>~x qp {q G[p7'kEbx8P=ę<{+cF}/3 d󲲀Ezm%c?8L:#`mq{pK2q$Z;öTfUӢ8>)ȧ p5eK>ci$: i ,AzTlFM>hm(P$]bncGW)H9X#ӫ};7s0#fLo0MMoMUc.H'7U!mzm 45~T^['~Hӑ""X#62IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/programmer.png000066400000000000000000000604211423020056600314460ustar00rootroot00000000000000PNG  IHDR@s6% pHYs+ IDATxw\%aQ 2ݸ ]몳Zqoj[mmmuU{Dw?"!`Ѓ܅嫕K|Is0Jb< ʉT”̟.s3\$KĒ;܉!:)e1GR5?"ӧO>^O n81j(L-/~D!|r6.teN_Sb&R a$`| aDj!G驣 燞rkb*o_,"W:< ٫|HG =!;LuD:I{'=` &GDj!@=siGЯhBC_,A5xY}~ZˣrB?Hp;DϽ ]jvrWb)XBOѓ=DIyDCB44Egor~}-pD,9D,E>Ad8GD:"^/e4?7B)S")%b)2"1t>"M.`]SGNH0ϗf*1ļ(}4Ґ"7l<{x"&{ՔHK):JSRt < ѝ_VJ`UӏZ$ Ϗ,jΥ/^ =OzUYmH (fi]_< K,'Teg)R4cY1eT*?%"Nοٹ*MI) Z.N@Sq Oā<@Sq Oā<yvP0Oā<@Sq` Oā)80>@Sq`| Oā<@Sq` Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@b婐tV?Zpቲ.H_.=t`G興ģw:Y-(caaulqpw*?Mȼ [MkfgՇlO[D1){}n>`ܦ,W<-("6QxGD<__#;G7mmޜl9ҫ[j@,^JHDz+GL2鵥>}bSSg{*;_RwɶHTb:b)m/6;&|DqXmCOe4@|LXXZt3-66y )8@y )807O~W-0<"]Kߜ(Sd%ObW噩;S[sM4GHU3)W[L"VX`4uvO(U  KZtk؛~ߟIxHhP\D$As[47Œ@D1PWi;O%L_ljp? K*r+ [b>B$k^"^J }7kТvEs_S/yW]E)V__2(;807O]l^27O7+izS]@=( Oā<@Sq Oā<@SqxS!#>w_WyVrzoܴq5[t;͞! 荿ݮ̭3ۗ P@:Tȸiꄍ>m&\kɚv~Qlj;azvvdw{?A'5sc[7/O@)GW.a "UK?j}o-UUnJGOj ,0,CnD,7_;@ĉ1!sl6u{{g>k1#'1,`DӴgI|RƳuѥ4%$''q`Sō}btg!5)ʸ:;' +O6l;_Jvlf9~ " f[?p&dKQ{!#N؄mT}_a43~Uo2G>ԛ~Z [4]%Go}_7,ѵVLj0; @Sq Oā<@Sq Oā<@Sq Oā<@Sq O!fQ;& jҼC\e?v(\z%p)iI=>UxMKgmvla0>߷q.Uz;q⵹74ZPlޤ1T~̞:4d{ch{;T0ȓX7ͦhDEDDĕ]-,GTd۵,F>|#wnZ=駩kfuٲ(eDnez)ÿNJq{lrV4ݔu=nTiֳ'w_4#G|xu}c/cmKkY+P>KFjS`LXXZt3-66y )8@y )8@y )8@y )8^z pDz,HO <;.B]˲ [BB8e׏8^ uY"%+J\~)8S*l$uK+BB`YoeYV0=G]ez{33_IRq\7KPcnb %eK^JN]17O;b7 %eK^JN]niv_`&D\K^P?!Oā<@Sq OJq;,OC?bo\_ Dꫯ/tC r޽+W8::o>z3g(.]JJJqƓ'Oz{5lmm-Wc6E}TJ.SBwY-=7,?Zӆh+z-}/Qb^KRb'R뵴[KHV j/Uu֭[~æz ;)QJm8id3;4@Dgy4lҦPww? Pȵ74zZogb5W̙?>|86Jezzzbbb#""둒r1VؠA?? 88ExzSQm;εjb,'@ ʕ+gKHHS6+N?0B}ğ 9ze6]Z "ʺr>& TDpJ]b|9d26"QpĖ\p埿m&.5ޥMbVo[MADUYcҤ߿ʉxOY'~g[n !])Sƒm*<;;;"##[e>zHLL 666j`݃:[Hq-] /]jЋͺ>M@DDj\m܀o?CDغybȯBCN]rb|k7nv5J0=t萧gN";wj׮[[[<aٝ *-;<&ܤ qXWrز}/T#-;-mGǙHR@i (M ǙJSi; d`\vw ߰A/=wNӬG(ʅ;. UtOԵW?tğ=t.8d\- zZK#'Ljq*m󼗗VS!Bddfj/j4b&#{ޫߪLz u,iNEѩ(PP^ "U6=H` yտ"1;wܹsgΗ1}oy[nݺu@`+i(jzٽE u7hVkw\*<~/{__9Ox>sGfLo+ߌɭ؇K^^^DTn]} 4t[R%5lXCO|[wf~s CA=tQHrPҙ(:Mnv{|lٳgO:xՋexgY!RnT[-Mk'#șu j^#7>)@{ PS3vn:Wk4o~׷\3!^etΝٳg=zTVњ5k._C˗lll"##]]]r[ADDDŊkժ%kn:6]]{v( K7,%kjCDdUkQ5U([&Med˖-ǷlbI,~>*"Ʃ~㪉/^=}nŦ,MUzpKUlTC* kD0NC)ZǦM>hl+o?RݎRx'VRe… w9}ݻwOOO/JV3 #磢|}}MM*U:tp޽Ƹ4؄;z8Qܻ?FvX?K%؇&Q""%M IAOuIA>mVለ7|{Dz7}z{^ zDڢY{_6N>mfT5=`#?|4ݣ76;h>c1c|'[{.q6lҥ#UR'Odddx{{1˲UVUTyWYIܴc3ՅЃQxv .%6O2(!L:'U,E Qa󥳳ajƍgϞ<(ApmYz! ~ݡ4 .sN]T4<7GgL=@G6-Yu+:NEܻSC̝..DDY|LHuzϺuRZ~>ciKM5njCDmڴ9x`ʕ7l0pΝ;ٳ^Kӷovww*}F%?-'~g &*IXetZs۶,F!"ևh9:MPH 6u,_p:A˖->LDcǎ=r$gM}ZO釾~aj7_3zj7n3*͂]ո#{/W9d妯M\u*ޤԁkADzT5 t(]~|K W1 ںu#GTX:uڷoVhpwwWTqqq5+WApvv|Bԧkkرέۼv{׻{AAA9_2w\)UJeDD_UA[صuK(N}~[)< և2ڦMkϽ_V1c8::WX0dy{{GDDrp^R<<<}i6unSv{h,q T0\dڱ2uI*PWQ(!u)+HJ( :8 cSq Oā<@ H$ז %eK^JN]17Oy^*Wzy@]RԕsT׿nc$$oKPS5z|uI꒗UW~ q3փZ,tż FG Yo~BR ^PpWiLј|dء߳Z꒠MllF=ULDl[=b8(k- uIVI&rSUe60YDuEYc$!o3YDuEӛdEJ*$hLM%39/HKUrAsoy "kH@Sq,b.\(w5jE IDATў\ ϟpڵkkժew-Y蚔 E%99yNtCĒ%K:uT0-f1><7~z6X:m\yGײ}yK]Go8d ð*2w34Q\\\zz#.^g8.y;g Kz=+VV-6;yA|wXq1j9ie]6k,K7 E?>R΄`܄cΥ2~Mw+W6nXY:zo>]29UGEEQTT#">ξELj^ݓ;qӗ!qԁb?Xd,X 76og6`J;9)-Y$$$DV[!)<=vΧCOY6ۧo[#"s+xe}+js?ۢ}eccc|}}˔)a'mJnޛհM\oG}ҍ'6S-[Hy<\M`ʮw?m١i^FԦbĆɽ|TtAz:>vWn ճx: UTΟ?˗/O2E}>*jSL|rq/[Q`U[n~9p44\ l\gFF*|;j]9v.Ynkk[LDKMiaWLإWͧٵ}*|:䧳Nݾcyc%c^Uԥ;v0(}g}骣/c>_ٽU7Nΰx;_לJ-$Ғ%K&Nhkk5jtSjZV;uTNWF 4ԭ̃l~߳yބ5rƞ|ʽ|ܷ[ϗzݶ{m+9䝫,SGl۽f֧/םz1jv\:ƣxgԜ9%I|ٳQTm?ĝ?^t1SJrΜ9D4uԩSќ9s uhqm=SmK/XVm+'g 1A#Խ|ᕻsx'VWLJT*Gttt~2!q甾9fwg o[֎8e51\{M|Gs6XSq}?Gc҂?~oF検Us^~Vtl-/R9{˗/_|y S*<͸У+ o׮]nj /mfFV=t4kipe}<=y><X.!}F\}nr~{%Lƾe?aMq_mRׂ̊3fI_ ~ad0y TPj3fΘ1#g_EaRN= `x]^!Cύh;t1_v>Y2lr?Ǔ'ORSSAؿ2vRÈYO愬z^j[ejuCaQwnX~O~=ZVvHpm6yF^cXŴXȌwv}Um5}Vu~Q/=Y}L#=9ɭ=zƌ[3~ܰϔg] OmUjS(3y'6mҦ{q2T{=MIU3c?eˑ&M)Rxx803Lxxx|||JJTuOΰS;78kʟj|pL}âZ'w;m?>{и~XUoa!q3]Pu:v/턙;Q='.ߩLw?u [z0Je 5hw͚5N~Bșϙ3gƌׯ_ H;G 8"h(8wk4=p|*/ox=~cT71޵lMiiVVVLLZ.W㶶qqq5kִPפ&sh릻:`+e&\ݿxi/Ԧ2U|YVM=H?jn~Ɍ2WvU_אy1G?~|ݍ9_*ʹsZu1aaa\"^<)jSoK.5i$ׯTCeeeuС(NYJPW!ilxwǞy6Ne(I[چG6w--Ү8|pOOٳg PKllg"BXXGPŋ⼼,<(Tz5wˮL^a_ʻJwZj9sG1bD~${ ?ƧS)!uإYz}UY|Pi/)80+OevVO>  Uf2YDuESy%""=o1];|SU1wItS 46.Iv`>j!6:'ʼzqc;{Z '\=y.vN'ʊow&˱V0JKKcY*F|؉Sl@`w{W:4hZd[bY[eYym gv7D?eVsz9R)bSr2zX|7t݃1OZ"z>>>*Tprrz7JzCtjSb*y=oTN.elRd)*|wk/v$\h'ukJkpzv&x<S t^ ֻo!9+W\y,[bŚ5kZIbEh9/?1-EIyJ6u~>p(uWZ;nJYx~8oJl/[?k"I/_+pƷSƥiDDPQ IVE?Mn/}ʕ+{xxߏk֬쏇 )RYqSفҞd<-fJᇇe] #SXۥ|ث~-bvSjR1 *HwBU3{*z%Y`7k '.=,kBjZUZ[nY]"'k05\LYCL}jCFpLxxzyDK꣘qLs?-=A lsm3_ ~;L6/x\]]IKKtCD::92B+Xwa,{avQܽo2I3t&&6 oK7 #"emllcqWn;yɀ^ֶ5 ֑1W}^e}*>}>rgƔ-5nOp{I;n%hLM|(-X+_@qot폵g[ueI&Ѥ ԫLS(el/r;^ysB}i>pWuYĥp9z+V !Owڬ>9bX2RT<̙+W.Sj8z{!>v_wIDD Dڷn"ڔMŞW Gw7=t`'AN r/R-T,ǣ8N뇯]oBKw4ô~*TlokxӒќKY_?????o7[R8|}JI|褤+ Siom_o ""xl]rzPh,2 :P-?6]a`ODDOVIws)b:\z]:fY0Qi O1u}"Ve#$&jlNڷ`}-#谨\Q]TxbBZÇ7viOs}""!!CW9뷩:h/q YFvmլy_1[[3U]_tOOG֫Qߓ#OXDJ@F,蘙YcñTw5\45Τ3rSؖm忍.UdѶB/~?7nVIH*>O@oBcbO5dz{t)?l=~AxǶ|?e~c:{VytCR߷d]|ݻNHز?=kQ.ޕU#VkMoy=o=YST=m^8ӏ#j%X0}̰>]r0sU-斉111nKj%s}"ݎ~#Ev WF .e;x iWZ}é{]|4J ʄ7JOO/5{OILL '5)iQwW3-yK%66֮]w>zΝ; T*77\i.OB WU lk][e+YgZK |3rH" b#ݻx:BRJ㳧J)ZbRZoOPsW<ѱH))۳)X|+*gr/ %Sq OaV2<>7$D X/PhYyjB[/o` k- uIY& 5,[^/+` k- uIY&;>{*SAb&YVY꒬M2w"R;gYVR|Jw>N嬵4%A%+U(UPt*V+O^ W[kiKRJrW̥pR Fcan s:NsDz3k- uYb^o0w5í,݊"a.ٱ K@j@y )8 }|߰KX IDATZWrXki˲*\j4Y,w0d! +x) ㊧mo#9Z8tż 1̔E233 @Te6qR[ZkiKRJrW

Wј|Tuj4%A%+؜ uEi2yEè" q&wEYkiKJZW4ɬ<{B/*4%e%+d# yĘ*4%e%+̜$.PV!EfoU-yEZ"SW~ʎ}kSYP@ @y )8wR)KHH8zhBBXlي+Xm{oƘzw/.51#K7T5"tAR.NlZ{a)ZιuH(s{8;|g˺KHyZpeG>z^wGo8䷄v_q )>_s{MFaZb`n(FDnݺ~ppp2e,4JޕӤdF!mrNkKweSCaVrѦP9%QO[W>5}Dto&'ֳ7vdl}N{̞?~pwZpww211ԩSNj۶FH=\.t['?}Je R˪flBEZɇ+;vɿ zޫ;/Qo۸o/62])OO /_L_7JBիjݻg鶈CH9ˬ?w׿oH蒓RW7kK>.t>F˂ƾ葵nXv"{-é [j٪^S#Avm^}Ʃ~+>>q iggk WB囿^37-QI~811!88E#++b9Z7)EyiҊ.C&U7iXEΩwr8{E4@-(#?(۶O ?+{68g̶PW,yK%66Ve gFT:99ծ]|>eX[ujNJ邍g:|Оud(jP/_1t܄,;u&ܴ0>%gP$tżbcce Sq Oā<Yy*U/XG Y%:O'|PhYy*_[5\4*4%e%+dVPZZUr&PhSGB;>A/^oe.*i]$s'*J~eU*ɧt:|#<pjk- uIPy""mmm8JU(ljZmXkiKRJrW̥pR Fcan s:NsDz3k- uYb^o0w5+S~4%;V\\wH @Sq OQQXVv|-zZKC]WT! ѯP(^ APpe * Z꒠MllF:ULAl[=b8(k- uIVI&rSUe60YDuEYc$!o3YDuEӛdEJ*$hLM%39/HKUrAsoy "kH@SWZZ} ")X/!!ѣt:>O>]s'/]h.\Cǧ ew:f^r6ʞ>rnLR`WƿfFW*ijO=E?/t74f`%֞v$w/زVg,#T}k43bhvEf|i)k']\'K*Gjm:Y}f^q-\diﬞ8jZm:f}r?w5Y'%E=>el/r;^y??t/|9ӳK{rW{~g»|Ug$>8kV~T_V- Q{0nvo#ֽsF6n[ѐL9}oSoe!s,};=8{ëU@%.7!bzᎥ;SOaZV*75~isC.^>~jzw=p5\L@X,\5Bg=G0۶S"{gEsCȦYH`X$" k`XEa! y2O- >=o;uG,XVa-^xЎ/N:|o(wR\Ġqg]k q#[G!^L{/cG!?߃BYf;b0J=|V.HEQLbtLJySo.YCXh$TVXg>ib"Դ{K9d?Jo+[m{՜mCPȨӦt<Ŭ̂H;f#BA.ZK|F-\ȘݨBzO{ɟ pR-x bg~߫->mHE웟]Pן.y>8"CN;+v]eQ6}?M]ieE%ѨBx񣲆]1D%cOw(r25{Ot||Cݎ6So|{K)]vWĖSsDf­yj?8~vOv陯g:<ĊO9GmuEEE7Uy>..N[tu9udp> |Sw=!ިP_Kəm.|y rC~ASTqv^WDjmE>6[0u4ɣS[A~SEEgq7u&u 3z4盢KCQQNA0u^SAAiPև A4K:$a** uifOqף*dzLjQeeUHH** uif6?eRARJY?ْ$9+t) ui7Vwan="˲(:^. יGJC]'uk~jXS^~A] ϳqO$Ij΅^.jST((#[r/sP)jhkH&m]'T?JM5`00KU6EH ZNj B`X4AɨwsQQ3Yol u* uiF/aSLRM)P 2ͧv Wvu:.`&w+Wi*xw8ʦWiK8k KGp@)P SuO@ OqWeG\8/OY7SQ ނx* uiM yQqUJ/%~p6懷U;6?U6S_=UU2UP _l!@S?њuYgGU~Uh|=JqX{% +G)vif E Zo 9COq72Ia'6!pA#h*Am VXm!lSDR"F'57ګO&6H_%lQVlA`ŨAm@ktw=SRRr: L&ӠA̰6rg8m>`˥=ًo?Rp]hsdF֟SBw|%g~Ɔ_tRŹjg b[6|3ԥ*> <16Y@` gqGnݲeKaûF.-aCbLiצݒ0w]2rt+lqlN RWytm:+7^}g "/KO%)oU8gx8c2U*<6ηk'*pbmH3bֈ=6JnO%_.DYMQ/Pk(Nyv]ʼn"SR^^n;d25~)?uUcYVl/o JJnS00tm vЖ=''O^mP`ͥC$]:v *Y-\ԣO_e[o;ҥqk7*}-U@Jʉ3}9z@΁݆i҉Z}`4VTCnUC~}~JKv|c[ɜvxk b_,C75><"@⹽v|XtF$'$$$ٙ|aswV55Q|qۚ19ޜҫrf>}BcdFL&7-ZQB`hc[mP p2.w~I~!O}9sņV䗐֭rO ~gA|eww\Y]l|Tșf\{ ylvwi¢E jX+绪g~񱚻%Lә^ Jd0t |c5#f,Uuk'?- {M|}S{|c$G aAKz'\Hĝp!uyb!iڣ#Ǥwu\z6&AHh 9=Zt Mb0")eO>("!~TϮxWtT#{MQ1ǒ,جd@[v졗էEEEэ;]ab'Q=`GKOIgs:gn^C=Nj?ucSvLvKXyk9.7.OOl촛c ˑ#^;'N\x]vގ'@z Owc0af}dņ0J֪%6oZ14!u[4\fʕ+AA}ʽMOhh#7_-^aUZ%&&&&&z;&jB R A~Q j(A&Gݥ&&:*i5Ic~ 3z$S}\Y*9|4m#4 >/F٬DmЫ4ԥee[U>zT_,^iqBPqs8~:~UF)zfBp`** uig*언@xuK~~J)eKץ4ԥY5EkXM˱fJ-Rj ynq@n%˲(^ի4ԥAEp&ucO:INKO}||XRAiޛV@${* ui g# p+K=~J?hsq'ϟWkHeJf'% !eBeZMy8/fʲ촶r^.FJPaJT`odyURzT9-I_ک#QZx%KuNQQf3PJFPPx$d AtBG T_+@լ!y2%J j5V̔#`WOWYSA܈R#8yJDd T)*!}ρO,*"!8^aTO(^V- ZAi@?Ei(**v onep%d]IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/rad.png000066400000000000000000000010761423020056600300420ustar00rootroot00000000000000PNG  IHDR"":G IDATXGLqnaA6RePXػBJlDؐKJYRnK3b~9|L11" HIE.N"Gd^cYҗ w q[tIlܷK,7>ab?^xجywl:  qp(S7b>R`f= ,Fc KUV 'H(p= 2VO]0@!`mmm2BHC׀BF!؁yB 4Lǡ1BȨhj_iSKaCE P>" INx*f 28mmH&9KL2;hsMJBJ٣jWNUQPB|o"_#i;HU9Q'g0 EV*r`E!cKY!HT? j^eGAsTU'[+y26Z)| SQkQϪ0P|[zXϕ!dDS\ cP?eU5 t@ eAUY;Bh:4ϙ (OWï: S~)B:ZIi :mLFE:J Se!ZJ8];RvaaaڼBdlS"sT<9_Fg Qt*a]csi SL56J"AF9~7Oi I#g$YR|b" ('R S~JI}U21W29{%bG )x ,iBB+!徭|*Uo9WRv+E.lUb|*gd*~@ aj!dcHa=AO>0ZzCtBjSŦcflu eͲTАX4(qʏ2QV"UPYGN$ԅNoxܖ}~LףTj}tߖq>09̺ LϚ>Ӝ){!?E `dQi-c 0E\\BrHHHO/S}TC )9P!S! ! [uhXx2.9ŤȈSPS | p>T%i ;G!vaY9 YYSr9$+ Y HV@йYL)ߣTQ6Oih-aVrR5VRd@I2Y)Pk6Bzmv}Uɴ0ɕl}DJִLx2?!P(bccVT$988|7A!NR@*\5!kx'B!؁yBBǧ!SbB8>E!v!؁Sb)B!";p|B=?t¢N!ML_vLsvͤO< M^ǖLmu_Μ {v޺g#Gƈ&VT lԠzic}ScSمSd@"<[yoj\OJ5هup0h?2F_'LoCq)eBB D !=:3Cۇw"uTǯ^E;UX1i6sUbyd=P;0)Je#>Ё-J6Y}LmJ[Z\ޮzFwOۭ- Lқ-HT!e+EUM _<2VUеI>"'t;4{^`;"7w%^=/gJiQob-7W7nGZz;[Y"wIuVD@a"KPΓظTҢjUbէ\P{.[@SO+7|Iy{䝯6Ӝ׹ b^yNE"3<%K\KtҫGKwn]Ö}^T D63xҴW㲅S)BH[t뻡]T3iof:1S??ϙLV]3iPμx1i{s]{Z .S'^^F԰+tq'^z*q${0-PvYkt+`'̹SBq .6",,L*F&=F|Ie]*z֯TGwg~~T0md 76t\헣ՏP?йbY|Lkn9%6GTDXXT*e"PaRo1jkz@' -MS-1~ʳ:(0ɏwZ }Gwr@J(wR?xya"xEqnŜ/k~5t:%0gN߿?)B?{g-8J:'&R)tSЏIwd/d o/-4ݫ(T(s +!>`2>_9mōxr ϵu(JEjy0)mS+rմt4O噌g@jZǽ8a"Mh1/}RRNM\R~j'q]2St kly!R\w`%p)<!aO6NY:M?wO222J&0s),-1]3Сmj.:!*ٵ{.@74kIdϏ,]oE(n8m$>?8yRiuJ "8I.:LmƖ}ݽu΃acedvMDh\jG6yw ށ gǍ!T"z;V&O|Ew9*̶xY%+<|a|LH< S̍0¢A3go&"O}j_s.\8}VO[%z8b}QdٯgڥN; DBQTxxxl勣ctttƇ6nVE.5C ---~jooI ŗ/~0Ϋ~Ϋ(w] &KWvC7tnG~:Vn`UKto} Qmh ߖgТ AG?tLJcyݻ͛7 2m;Im;t`%**J6҈VVV9[RSS<<_z6K4aw`JDyJ Lj2x`~-^:yy@+wa3f(Y Q6%{hvrr>}Rma&<<9ndѲ@O@o]+;Y[ lJNgAUVՒ. )nlI<X }Z{w'3-ʪܳgOF\]] d[Vߴj,<<\aJJJ||s$25-ߍN9M "66666vvv-o[v$pK)YL;;ۻ^M&x{{{{ ]wD圡]Ϡesڙ^2m9[οN^'`Zo3O]j'd2ٚ5k&MdTJʞmW|Ht^{vWJL\z"!ڈ M;V~?7<|033$<<"gMZŋ/^Annnz>!Ҷiz+֚~sJ[Qp3gߤSfGv2۹vfUt<3SȐ7)Zm=kOG:m=U.X5Η#YuZ6\5q A3ߖM}|w|fs2N |xnd֠UIG%ئIUDZ`ϙI5GR 0@򇽽H$Sz ڵk_~ʕ+ʕT$+Vb^Uv"(9Y;tupp}dRgjnhPʋ_V-UkځۏJ`6ΕX1b@R\˗;V} s{^S=DXX=.*P_aa9Wkq.NϡS͆5֬zǏcƌ9zh%W~111%5>xM>uorIBe\#P~/^f@Jjo(8?Y?4o{6}"x?޽;nEF p n Xsk(==]" 0Y}i9x 2TjC(JT0ʦR|_&"L(JLVS5 "##B!_ǹgM1 薧r׍tL&u_Th@T4o7ʦBҼ)^MsIѪiAa EQjڌ)8Lc_1i#=LUwDZZFٔ-|U6*G_$+7.)[=K^yQ:JR*ayA*a׏WAtt5H%2.5nOiNKKh@4**M6.!tƭ>gͫ= kYԤ􄄷 W!׭as!q!!!۹sgյ7\Iiᑚ TxiܸqR6lgϞ[&''ڵkx(>=sܻw Tw}3fӧOZ Q&4""0UUVΏjժ$ٹsΝ;aÆC6k hn߾ׯ_(?7i)e|j֮8'0u5@\XiC|lTQ LCJc ;هv6m?zq~~m}OqYPBP=u*oPUYyJ ƎۣGw޵nz…\"ס!y4?ݵ*4 ȄꄸN;;N\ 6ye~xeQcsERJy741q!)QO(B >|Üi&ZlٲeKmWM[Ⱦǂ-0M9NESVun*v!%Q-,G%<~ŦFO<' Aϐ.ئ(s:uD3gδi&gULUG g̘a)41Buf+_njZpaDuFY'sٻsigVsX\r$|KQt} /:8$D}'Eh.LJ>cƌf͚#U3㧪cT ﹏rcE,YÔ(2RNۚUՙ *d֭߸gS]5ڽaq1N._sAܦgKnOyfoc?^+I*0uqqq92dzg*@URg R TusTՇQQQP(Γ Ԥ%# GM 8(ƍ]#}JKS(IIikG8/ԮUqۿY?9@ص|ڴ=٠)(Ç߾}{LLLjZtihT(.]Ԁ'Kw_~߿^7bĈ} ӧ͛7-Zdff&8x>r",ڋg(=W뉙#lJRʧ5W/V8_?}M QTwnr'j4R6A'ng@{v|_OXxo.vηԩSZjk׮]`k) W޼ys7o޴hvϞ=7oOHHX`ȑ#۵kiXla߼d_ٙ8BiG "6{|L\<ª-Uޱ&u)`gC ի/PU@uww˩S޿-CBBLMM۶m eʔx+"Xw(ad{sKk؟93ʳ%T:ux{{0]؋[y*e onzeʕ+_x鄄[[[?B?-["p+O)]v666o߾U}122233ĄanG!~dS՝P((ȑ#˗߻wSuֵ\hQ6m.\kJBH5~xssNP(%ZJ||H$ׯ_OJJ ~~~BI&^O͚5+TPTbC!{Ƭ&)8O/RRR0-*Uqڍj U n y-333F`_֗F111>!xD<5]k_!=$Q.|-uaMiG?N_!O|QQL8߅qRօQ6q 8}D(ɟD|?wc 2ڬHrZFٔ-|UƧ|T)I|T@/ahV*`_6 $YЍfE"ʹNW gol 5lMI!"8J(Q| \.ATrQ6W~IPHQMӪgTKު96OH$T/ p/ T)KP(Jρ'3̠ (tKM1Gd〮p̝ya\X) Bk0OB!SbG1Te:8o_AҪQ6ؗ{}_&bNE.k_/ rE)F`_S_jtgdd"t(m}N[=l(Hc+?T&1LSڗ8)8I׳uSKY9HڗjbzBQڱ6l /WAtSJ./?UԺ0ʦ4n6>-V1򖿓Ժ0ʦ4nr!8oRoJX㼉US !g0G!.6`¡>l_1\yDܵ{.$>gmU޹B_Oxމ@o]OpM97NF87wUi}k2N9%Is.s +) i>J-e)N^wlۦRb&Bb*1qgo=y9QF:UV][@'k2qMCWLʳ]~UwҊ@;n=#NN*`"#hމI~Fk6ՍMJRb*1t!(:1SWmip7{"!yȭB!Wz~e^.mZlc[v^vWxs/>gXv-[1lg,tցNʞQ!_&s.;Y2ޗi @T7pm:\]>y;BV#x7,&7|=?wà9;]ϧN9Ws~_G4x @H$b%ḘlקIkV}cX$@vצ>dHtRrsla.}>t-[>K\Y@Ly$_[;{Ki)x@wM#nceKx\.=_k7'1@G\IQ!Ɏi 2 %6) ܻmS#tT³u $P.]a^r2&Ҫ3ꌞջ'&A<pb Б,ZIIS[;)b/?VhK*}H|ݻ௧3ܱ;kH#MqO>HNXao+|;eԪD;vNq=st}[nCIJв~U1T훵]}G:͢}+ f_ =x"Ǡ/=ZV91ܨl'j2ct3;Io߳9y @;@3C=sA_Z8szz}Z~&rf >hߛטQu& 'W=K%Rhj׃,tMDWwhJgge=&S_hᶦ\uӮߦ4rNHW-A]V5_?舻w#O-*s(^*o@7ѭW +Uu/H{Rdfjy (};7L$Ĥ٬QMhl+C&)!aڄ}箜;4z55*\RY S a*4ɽP?|"Bă +Mt]t/OTa}]WS S'Z{.]G=j5Nz 3 bGu0JͳEcF6ӱxΜy#i,`Rv|zz38sk2Va>3Lr<ĤI!ĦČyJ$&)ug$:=- =Yͨѹk<甐O3ʂHMMwV+HC>: l]N~\aiɈ01Q J}ȟ>ѼjCy\xL*L/ċq&sd ISM4JLMU ,IAAl;֝Uh{S2>.1773w'QJ@ҼlÁV|*\iJ yՉ8;ڿر[^G[5mkgsӭmwJ{qL5>tzOEnr o1Umo*ڙ@-ԟ⏹},.,]v!etĽ1do5\<JҥvM{8w^:qWCyqso=^3&)xS &m4c׻}mtžyzyƟ7k#sMIz5 6zz/6"Ť|Dҥ.67ؕ;w޼xdug#hxecҥ{(|oC? mQ.z5M%vB^Y*_zχvZ:VjӼ-ŹZanmX}&ʐ] vS-SoϞs|Dmj^_M=\nRSB@yk(uc 5޻Ӻ-GUϟ(@SCZ²7n=n֖LU3x]1l/%kشG-[z ۗOX#3wwɤuq oG#oҦ$52ء x~&J5--SÐ+{^{kO;emڡJ`Z_&&$8m@SNm:ğ~NxGyL.R-7⠠;S|à&^gvygf~߳0_/;؝V}/3ߟT\_8`E6TYT徴!kIoR~}ǯ=|A LmT8j8֗F111Fۗޟ%Ԑo<+-K!!c<5!TQW ])B!؁yB!O Nހ@W0־Bzyj}1<%WԺ0ʦ4n萧$i wa}Ѵ1\ǫօQ6q 8}D(]k_J1ܹK lJ>q*nSG@ 8>5ʾYT_S}qƾ TW$wvLH g/B M \eS}qR!}isb>X,.dcK.qT*;jM1E_qD$ 0]# t^᧱P(J%EQ$IrdahfeM:#B昼f}1 Ӵ) Bk0OB!Ďb?UF`d6`}a|KF`_(LƋʪLTE@ (rXŏwV=(R*.)8@Bl3pڲUKx^vKB2k ^lB׺n2b (vݹs[5#x]Pjt{NMiX߯ՠg#r]ߒzcmZCE(m*lzqe^-Zv{ 3׬8Oep ka/73Vvnt-8Փuǘzu4]ud<#qYϝ;}p`++7ٿ1\P=0;v4t)KƝL}}< 0_CzfH9OY<~@tmS`ޞ]?-{VQ|{[hѺcaS^AsDKo'eOG_Bl+jRYGN/OxIj՘^ G;fR)B*5#(Gg)x{l`L5N眓IٗDzn%쓍gM3j!ėǷ*+ϧ?#Lc?xbcȣ~wl_qՉ , :䚭MMP̓OU ٛg *픋y;Ȟfujx*o\χ$ ͑hufZܧ";8=)qj׹jّ}bn?2QE6l{nT%"Z*CռV91ܨl'j2ct3;q7)*[̱KqPLgiNUF@XTFx,H+R&ɱ_3tX+mxyf06kPm+~<w>t5a@`zӴO2Hqћ_pzbl֨&v [3ձ%\8!]QJqIM_/j1|vϾlsS;_1Ņth// к/7KIKII +/LJr [ZzV搖Tz?{>8o_ֵsIu0ȍg? 3 N$oZ}*sȂkߛk:V4)Ky:K)eXx ƶ"EDŽGH1)sbMfn@vt ~e2|N2upPe>6mI+=[Xۗtҹzv*ɮ0+SeAҿߺOW:55ƽt~5FS4ś}N ;}}3&j"m_(\Byp%W J욖Fk_&&%8"Vwfcm_CohSLI~}?(wSP}铞(&&ƘHJ=[<{TCnеjS2LP7? *&.I};3הSkFuOW87ھr iMy8G!/bTXn{d"4#ߊѣUbbt|G4{:Yۏ|!^&vָsޥx$Ц͇.?Dظ9$CU+>Y`uw}Ta A.^|mYGq©QCr٭noV-6tA@7,!ώm,Yzw+u7apYIwӆݿxI ]w`R>l^#zK# ~Zf8TZPSi 6&6 y9=BHR+nGzļ7SΫ !q3Tϊ,{e^z"`ҩz#g g P-ItskzNg_k77:5[.{`TvM/N#xҧWC .RDX5䉿r% +>8v]n_3 )UGy#OMc3?Ha :_0+%̌ӈD^ղЄCi f'(}*g~_|fcF5NS`C?hVܠF0ujZ >걓b+ԮfUSW6.W;$"15%]3~ @LGJ'1:e.=i?s}&ƒ~پG[_?Utb+g%Xbh R{Mdly"X1ӮN'CIAaCz3YɀɈ01Q JPsHNs7u2tis=ŵoFEbjN=8# uRS:dۚWC9qk=>2,* ʔs2>0r-4 QwL*4+ ѡoS)*d)?^oW EyJ9$XeȂ.ei|)勺gO^^ZC{3\\ԷWw߳IF̓s{ަ&"8ԅpHCY6<~iWO&J5-Z15s {}1{a=}GQqfwҁP{t: U@ (E|Q&M @JUtDj{vw?@]rLǏK2?nٙY˞|܌}>XR'_/*8MqN)C]~ԿwV(5uwtztPb':yiD>Ϊw*1$" qY~fK#`=E!zB!)B9zJ(\!zm.J9< .CY}E%'- pp` ^sof`|) e\h(%)xͥ(Vn̜|) e\h럲^z$I?2YQ}B1l65쎎A0/k.Yp*Vne(\TH.4OOO{s$yzz^sf;62`.)2WAũ FQ$nRSxBe8oO\,+" :@)UU՞s逦\GVi梔j0PXAC!XOB1"c|eZg\Nr 0db<&ZJ$IE5$I(mEQQ .CM¢mb5F_JΒr˗PVaQePҤܒARTpﮖ8Pɹlzm.G!=zB!)B9Sr !XOHggP~jɸcqB,c:ĝ΂/.VežҌ7|?o_pnj^˗Pgf,[bJy>>xaMg]3kEmLEց3*G_tc݈M5ZLٲ|`0AT% &6O0`-ͣiB E}dڿY+&X˭MyWJ hM;rXk54)1z3cՇWj/4ꉯѠsQ(aNs|J[w7C}pTll'2lUDX1n~̩I.0tM;]bFQ{ݖǦ&'%A`d# M;lVD|:b9g ^֯G}hƵoW=0kמώQԥT 4ţ'm}iN:t𸹨_zB`&/X>KX`* tVROt: uWͅ_>:8LਯFVqԘV0}Spޘ&_6eփ}FE/]oNY{sc4 "ٴb꥔e^メ=y?]ӫ xѶXkB#DŽR)8ԾߣzP1J۰\} z0&G4kZr&'&? 5%/o1M헳A4 <1~Lh0n um}#5"QxIkx X!(,MJHt~T/'P+,b{ڨM>ló+'4A$&s )S|+5h줡-+0Po_,U,SA4ee4m: ]/6፝\d\9eP]S|zD ;?{Mi @eL7`SKh/Kߋj|3CN{]P1WJq/?|·[g*nNIK`8^n#lLth\i\"∊ufe_i'MKMR~_i_HKcCFBUf3hϗ^Ф?3d͸n6 h,LLy3޸J|jիێ߻£R)4iTfǩc糚7գ'{o&@f6;F%TZ̃(a~5'~Fo>rhҽo+6l > KժWގS,J=< P !݇Y 2kWukyˌ߬"fݯ5tS~JĨmЯd(װf9&iZU|C;"M:Kg& nbA|ڔkFX`qOV{)3KK_>+hQHB6τ˭Ospthն 01'|H@iw3RoH=,ڲ~'s'>[MX4:p9)u+_ gX=fߑd5Ğm_YtڹQoT܎Bz!)B9Sr !XOB14SBKBSnsQyKe(EC=Lk.Ua |) e\h(%`-rKe(E[#I)(o͊ 0Yehdwt,h&e\̥KJsd7'Igal6APlywp.Cҙ"sT b4%Iv(=G!Xt?y%˲(( RUUaq 0hʕO1{d1k.Ja  e4D!zB!O-8;o"w*PL&Ǖ-5R"%I*D$IE6giȉ(Js逦\hgee1Qte9++`0&`&\̥3E*H[=5LL_`2>k.萭뀹 K^!Kto [GE1߱6.C1lPOY/:S"_ .CY}E%'-j%d/>¢+?IYB\RTpﮖ8PɹIlzm.G!=zB!)B9S6aYw#Sr !n/ɾ ^ {w󞎛xJ:4k1xrizvxEG䗻טa9gߥS͟lٶ۠ 󶟎z@bgX{6]ZfF<'RCW+esbկ9mJ3|}c74yp ltl]N;zQoGbCBv#gR|-ճdfejX9_3~wzUd@|uSLߨ(1>4J?*,X; }ATN^}Iw.ߥ?U<4䊩o~y5|ү}Ӝ)w欚ʟM}y Fzg⅃f}"upw1?n(1wcCJux\rzRrlΈyȶ50g0tIRQe̎7>Իk4aӔ^ 4 0bѦzѡCP'ZݍFwoZ2 @D:KxIDAT=6{MgSۓL?싍axc5 짤j^g)]_l5ȼp*r9,oQOyD տ/ɕxjL$NCEAW^\)H 7wKΝ:NCš)PSbl2)x24E}xx*e)eoiG2Sjw&[aF#~!M#B^O/ԉ6z~cg7,=0bVOTSS&WʗiqlVrH92Y=,\1Y)ʍI)P衞Ҍ,5~^S ջ~xm걓19'^U' թ!=} e 27Ԙ#cUS#s 4+#hqo:n2n\zgЫC$ 垙0U+$/lG}Z}«)ۮǀ[-:?ODzKn:z\rJD>@32~2zEL5r3:giïHPz9x7~iw-~^T6Y|>"Lh'sgy~߼6t4/uL^gv||3b/vet_z c|a^'RgmqJyӿїBXGNu+;`7hs7s⋏Oy&xPZJ=!.Bvȁ+QNe7%A=ܼ[Opw+@2lanZxw$zJY?۲i4ҡx=5u  PƍAAA4##٭q oo_0|=jɚgܾMVmк]jx;ve(\/U?u%){ !T(N a=E!zBi)xͅr1梔KvɗPVaQez*<(\R+Rp#,*9lPJ$USKQı2GXTrr٢z$j\RַfEQ KǬEPh4;:hVdYfw,[YPt\Vi.",$I,T2,vE1mPt\FI,JnOB!=O^sɲ(( |2TUU{FX\̥rSY!cLRi.Cb BHo"c`=E!zBQQiY~sB;e(7WIPzj28Og)IR'y%I(q?K)EQQ .C,%WwtȒuhh^IUS_GYdee1z L}5``/UUmͦ2 L ,;%~}Yeܣ%>WTZvmNj#P jnn?o4Jw oSns!v*G$+inEtPUسa! 3yx!OLeb)BY֪)䝍!NFFY-NzrA1ZI)BHc@5]XOBP$ Ա;w 4z帧u}$-)>ӭ>2[-":֖qbf~[Ǵ9z=u|M)&üo:g|jk& l҉Wtwc>KFN~KBѳTm!ԋ Jk&K0ozDzV;C"\U+;V:l =``f_l1MyoܗT)mr0SZwSb.O+1U>p[GmwÎ {ռa&^?}:u6~D}W71[|jܫǃG|?X *s)1 * L8;ˣd]Z1+bST*_zmx@z3u*':v5^$)7|ٻYޕt.|^*ݼ񽥤ڷvv׺{1x;dm5]qϕjεUN1^-ok `=ՍL\::UH(T^‚|mM >Ԥ׶i1>}VUf[?Y|/Z5nGN_L4%gCB%nC/S =~lw]*3[vhj|ϝ@ ԸL '.fÒ,E\!7ԾC= o֭S7T7#C'hT\٠ڝu-OG9hf+l;jtDzLLkpUn&')~lElR6Psj3sO~SW+0[NfJ Ƽu`4vWPAp+r} M&R WcBxdڎ 7ÓoY3~Rz $ɿm𭜛!]_ 4d1L "ܥG]Sp*v$Ђ7h@@ @ozނreK{=`KPwo"?@DE˺@>)=gOzP5z߲###|M/Na31rP'QrD[$%W,lc%QNQ/LyɫoN !ˍ~7gW pjrƍ {^ָw/ya땏&zGfi/O5iə\*;L,rYVΔØB!&o"~Ztt #~]ݭ@%yPR]9_0"ؑSG9_)DC8!P [%b=EDϓ.pr"OlZPO ` ^s!^,gc=61˗PVaAlGkiŝU0TUk%_ .CY}EVStU쨫J$1~ 5(V_ɖ|) eYIA! ޢKRb~mSK$IV\梔)UxPo.B@ 0R{Ɗ@@ ^mk4 `4Z_Z\,;TUU傏s e $$9e?3BA* vuQ5<==M&mB$IUt,xe6%IEiSP].KT" O +B#7$>d!AY/ڸ}Z¶mU"- ]#D"|vªlDD"H$AD"H$4%D"H$+iK$D"H$W'UT_8(? D"|e}o$ɗK2vX >ME} q:M Ct~ Q[J$+'7fqMD-9RH$/ f;Jb@FP6?MYh,qļ(p_qoGUH$OX*B$k7+[! O c<}8}(7G.o }c[D%c x%1PaIk3}p?:Uq7}(t&޸o"D"㜾u'[8Oߘ&M{:"鍝7lbD%ccĊ~ϣ.~aX*41pSuiJ"0 -I OhpWEW%I$ŶmBATU#-50i!\!7 /zMg<}oD6i oÏJ}#H.?B_4]w/9?`d@A>qnM;&)L R˒yy%zFFEd0<_ERB[[ǹv0-wSTCjJDr%_ߌʀdH7qa$H6B@t!s>)o9H>3IO]ԹUDC5|CJikk ]CK6Eطp- 4b8D#FAѨבN6nbym!I3ϭf׾RSB>exU9p+\kK~2 .+ UQ`wشm/}f}\\L`ȇa.J}#|}b;lܼ5G$'a*R<ԋ T疭݇ghݎB"T&@h&R( H>>JjH P\(R_'zȡ&Փ˸ R.=}y[l߱~nO?ր_` l3А3qES^fLF~kkkbp /#O-wձw-?ûQ JD蛀K7}¡xhSɗA"|B_O?=>X,oGO_S^V̝߬߿#u=t7Bcǎu~XMgsɤt^h^g()zƸpsf^گL$⾪."2W`0 _@ Qy}\bb^2!*DX}YB466'^x`>߸‘ HH?~& WIt_;/J"dLX{5$úȍ$τk^A,nkBra*QO8Ycn43S^b@~}'*Yz~8HOq[Kw cu% 50s,'3#/ 4l{Pqˍ7/.ʣ7l6RXVp J$WBԵ?4}pu%T҆No$ʇuG׹;7`/OQp8ʷe˅g+=N~^;i8>`cm/mɐr ǹph S~/ sa1xd2I$aڤLj\$ߛ;.YxSRB>).I^ߜ@[ۭT5oDxo$ώFU~DCGGe5͸?㎛wL1S^.u>K}q7&/47 D d1.6i^|PCdjPO좗He%g_(0uK/^Dċg:ŅDZQ8M萖ʫkf#"{X??,qEMg#P(M[zN8I2.7fbs'WՈpNUgEi!+A}.k*>)˵G:ƺ ټm/8C;?{o3e%O%eqX$:KAA*jߔ0ƣ;TvޓA4%<"-ՓO`ێP:jb&=!>Ĕ533qpwGUķſ@J ^CS鉸FK =73t7~2k'o>q }&2]"\!(T1Cph,:r|T\@|>}-s~4\Ľ0?jWfIՄqLl@ 4l]-,j! >B؟:ʗ NbB7"G0CWw/Bꝧ Ɓt8|*pO p75fB߈sLis$|6Lt^\_\_y$Id{OO8wO_;~}}1QC6CKZoD^F3օuI>FXGiJNɐ0H4!_%D;y?,go; ~- 3n鉸~S]9S.$D'Vڞq^xW/oD4mQEDcגQQq&TD 5=Bz{1J$fLetaуcy|b7ȏ7}qoBH#HD|7H חRuBVDr8HD"HSHO'7+#'pQ176H$%f'{H$DݔED"P䆨D"H$4%D"H$+iK$D"H$WҀH$D"H /H$D"\AYhEqDD˅7D?^"H$D"xD"eCD"HD"H$Dr" xD"H$ BΔSWH.RH$g1Dˆ7D?/j*?GbbsN_044 N @Sc01~_Y ?_Da(Q5 )p8(4Oo0QKrr  ^0 N7 w {׉ 4-qqL;hc +D,߆K|R荀(Oɉ+DݖP9'W<MaDE"osNpk~")Z'|N)tTx?"j8^}ßD"H$W>_@^AU!Fރv5XܺJUʼni4 $Smlw@ٹcK5 "j/KF_ۈ^74=N i;o#CQl=̖8Oe1 \볶0NU6r*m0 :FWXPakxFgshQTKaM*)6w;jya^e4{sAC*DZq͸<%^u'-aa(qvIek2%Cmt!pVga1#24SaՍ lFy ʲ*aJr+&s8ըae19!fzm:N@Vl Sqtެhr%mϘXqXpX*rp߾ScMashMo8MȎۘ1>Yn^;2QOZD"H$/~B_CкVZc1*Gc`iRU>;_g~*b\.[[[&4|= .#EwiJA2>dj:{IgGD!QxjN0n?XVo3&C呗}<\00i9)?ynbUm:: 0kuC%oMuU2S!&  x01 w`!%Fc*8 s^szOUU%GSRRN]]]#F}|>;ck[')ζ}>t!+C;%ΩX7~^vC vsbq^ѝEN:>߇g8ֹ: _}]ŶmWM>Q_;ߖ`}m ~B._}򹭮jm坓O~!k'fųwBtq>|>} ;/ޯ."G|Fpɇ# QF )0TӲ?{za_sh}3I't0 M'L*F E4uZxAJ &'IJ<. hLFc ωͨcgƊUtO[PgMq676n;Bذqٻ|wqN|TWo :(DŽ;x;Bf҉7U))%'IZ=*Y J&,kl91!0s- P5( 96^epM)ޫpX< *+lbpþ-:/v#>X0b8RTmAec2!#֩F[ *7lj1a ˽kGZ> ?]c\9y6MX<&wD ls8} ^G8fe,X]a1> 23LYdx}qxa:׎sM ?}@˷YjFGYPesh+1>pbpSc'ot ŃliK0./(Gk;ւO!#%cB _Qj e2- CHsӳH2裷ښz:L)(cċ_zN[#Iu^@(}#ulA@G5X-5'(!2ғP9Q㭨I'nA?юfjjhvH X`@(5di њ#4H 5 ˭u#쌓IPsUAæx=GhId'?X}- m4Ғ <i;AMQZz21 GWi;^Ǒc:A23D}45ICaNwO$5@0'yZNwYgl,Oа8TGmIz2AwPBv7 5Gh8َNZHvTA8RsO Z|>u֟ LOƱl@5AJ@Ųq&5= jh~ũ56"p a@3i=BC~5,[%4ii(t 5DzZ;q勴SW[^$lG9ROKMZfLN64/l;it'LR*}# 43RхѭLc-5D$2B/#Jݑ#o J PlR0|>E]&'hlj:gARMIt{::o6H=Ks_1zU HMކ #,@UpGO9CqܸuOx8_\xƦҊ6jo;nn}Ҁ!mgL(w/$w?t%39 )+prTōօw[~s$ahﯯ({5L`npKm"*N) +)'EkaR=*[!-aիtm-pܠ겁^:ʶz<1 Ja|"t*l=0!KP${;)40m#RMaM ٙ6Ui7.N)`4l2'6m"ͮ I6ҁAvө0$ `4ڠsBn}zqBG7ftI cJT!{fli0}U6*x\l{Ž@Ǎk[K1ey , "*FcS*MI$_nT͇^˫7Psp"8\5w5no#(ͻ_ck{@>/fDʼnٰ$b/ɼWS4>iUP,S2{B1J$vX' /`uNxuoKat믦0׍H[VֽFuscpBUl^C\׉t>t L%3U:O1鉇pBW}|7+Wmt\EGBh1U96^ɆMh>pO3;k4)f\]=4XQ30{LGa:v %k8 Φ$ݡv+~Љ9t7OrO#k_Ý~%FIfuVI{{]M5ڍ^εsRc{ 6=33hLI֮cOs;`{"f /;{8v=g30Цn %*\3@;?æd)szz OQaJ\w0G1sv%v8~AH~xlq;WŵĨCX+7ݐXq4X˪wrUg3"/@$-{S{.$=tvb}t}4#D `ގ*K/Fjmq+yL4wq!MH@5H,/;TB6˿aR]' E' O4Z,&]W L g_񘊦Þ:^9 s{y"O_yzƙۤ fY{XtN!ldÍ1=:]x߳41EQxAe?N\<ֳDPqcSg/bFW+mRUK*gƋM*CFf%Rƶ=Q&e@wTY&T2)+nu5|Ά?NW;uƖb,*f d0NVܙg)t(UP/0rlf;u>6l^cix+f>7 H|nFxĸ8* :V8;_ɼY鹇ye?x#EJ^IwYl{֮LׯE9m?ɘ%19-k)Kz}̢k }k-%12K%wR> pR^3ô6xm~Gͤzp#xXV}saG"آ/p,,-Dk;@} (>r4#KSyI~|ťSdb1gYY[T|k.°s1|xyG3eՌ*;k1! sոhgxYa߻eLk1]Y]03sdե_(/YɠߠX(˘jS#za֬ϠkӨ6 #J}?MŃ7Tß9ê]AgxWT%jX yg|}!߿uDTWW;[y6V'UεQYW~[OY=j%4vEv^}?Y'u(ƍ,!Z:?ro*a~/UUTgQBm/UQHU4*'1u( C-<}-f1fس_ZGN`fk$e0khؿqk딗A/W1|(2uVS(tv}Z SFWϗgh0J73qƍ5Tŝ1.>[RQ1q|*')NgҶgW0#_/iOu=5A}B >h2 }LгEØ^I ]U'/A|n}-3aznM< W$zp)5wCWjkY6|}~t= |\TFLeP_\kğDŽy瞥ϏnV@A% L2~>b4P]'ad1nyu\=(Q!E^~~TO|LI*ds*O57>i@537' >LyN?;Cӽ29FKxxu/!d3K'|A ~W>f*CK㶕?%nKX4Wޏ2ΪzftdT3&qo~6pyh< ۊ$3giǔbD[d qT>ɛ9b0;K >PKv+l"wL>Z11O.xLs*o|6%M6 R"#۱(FS׹"fq5E,00{Բu>v uLnj(utuV=Cz!&Bxjs> f, xF1ϰ{6V¯]Cmظ}/')4٣LT==A[cLFFhXshXn7$D^#5'IZIbZ5;7yÍ ISTݧٵukPrÂHLm{ټ=NSpbfVebS&u;c>:`ʒ1DN l}Gꉦ9qlU~6nCC 2^L ЮlWN? -`P"n+]'xwfvl$']`ێ>ŀoeVU&v<̎i<2m u f{#7nPC ,n j<6a˦Ԝl!cfu۷c!ZI,^:E,.fӏev;'tOyQƐ71ch{5=ٺGP~BX#.V͛[ߌS0[nP4]l}=7vsREa-=tXsnYp);;9X_OohΛa lm9~-`JIfBQ8c+:ș^? nYHYX4Zϖm9XsZɧhԽǖ]odM\;,4~2F 0vpR}X·^o?Ppvkll Ϋ9i;l`P}-]Z"T@K$v9Ѩ@04ȫZsT݇Ԏ,9ՔdvH#ӧ1fSp!)DRbB2Mr;r 9vh?-j%: ذ =:fJƒPc2cQRJ'qk/kMZV,Z\>8&-pXO 羌xBg఩W.>u:^"~PCDZ1ĺ:莐 GFZMV{㤤1ML[Eutm#Z.z᪖X3 օzm$. 0M^ܠgؖEGk;3qc]vPJ4-„,]%N{w {hk#bE6-rK5X7mhXS,Uz[鎈L µL6_>FAlF{hoa@AEwω:쉓؉GNֶvbeuFh8.Zۻ)NIsg3mpYdkyŻD,H,+GӉwwKa~0xW,bt5ӓOO1v`ϥ X;K/9ūeJww:Pu7Ug>m^i,ƅ%jXv3}7q uk= Ybk-qVΎHNFϟ実l;搪solʼnvxq7vHr"뎒y,n=]tF '3#ݴ 4pΨ0m"Ytho|ThQuϹVN8ёjۿ;7'A(=t{P^AEpMix3TmV53;^A<sc5c+9#7;ޖ,<&~hd~y6-zLn; WF2rR8Nٌ?vDN9ГBMU%(OS/{JGDg~MX}+SYk4zE#POA(mQǴ*?^=Љʒ`I6]na +4m~rS g*ɰxV;TtS083a:S !-MJQt CU64RݱEL]XjxcĠ!<.},z5ir A]'F0j k~8" ;05o؋[\Uf4Tk^c=Q$aw7]>{BslW_s[xoP>V,E ~)^{o8sT0ϰɧhL}K O2X` 2"Ս޽spox᠟md\+_W=?4U7q׵nR 6ngߢd̯R6*b=Zln&7CG/Z &`;Uxw_ qK]շ<[bU_ٕ/`sݰĺUes{YHvt7SL;C<7 |s!n>\1aי^ϘɦJ:~m;qϋ^ׯ71X!;3ľW ͌6\uyz&)D3=ӭO_< yRj&)TT zi86y#_0x,eX 5K>΄ Uc 1/ǘC9O斥߀6r"#ƣD14n.fe_};#̡4+3[߳i䧨FN2?r@QXa{UOoUX-\?~7[q/Hꇚ#!_^gDʋ+Yw[ܕ0q/䔚/; E6׀o;y.%tl6nN"'[Q('հ9yɰBia· G4 IDAT:l]T>~FȾ>珂Yh!KZPda{*kqw" хĉIq$9{/Ď^ Л@; PC[HHT;1|k3}>ΞWTS-'֦[DG֖"C,+F`mTvQPKur;m *2őE]C-.5m(RK)2GfVРX$]ߨvzk5"053QA8XGc@90+먯!xQTջpUSe$R<q,jg=֐-ƀvzȯOM#Qa~5S][CU)pJd?**갅FEZUxꍄujQ'kꡨt"q-*kh# UȬYWMM~XqPS@}-PfzKm)vQ UUSU_ 8D]C5Ÿ`]Ȱ@*֍o98@Z;vQX\GډBf@څPw:7&O(E=%Vr"Û}Zj\Blz Ñ]C]C#UGkֈvUR瘟J.jxma@dukp5RR߈_Df?$A6+TޤS@5zch'!7:kw\ UZyh'FHocnXº1*5[ǕgAL6}yE٠!K=GۊDžk(H^tӉOT#]Ms0¡֟&NރdqMqINXC<8{]z[?۠&_{u|6ŀӡ/!Y0bB=No}@FvݞSNjf (vn\vzt5˃_x//4맍gh 0j5iw-Լsjt(/5mBګnz ӱ夭Hbh5IA Dz=I7!Dkǐ]C7ki̘ ۿ#%fq)È0Wȅi G' 40A4gɲXcnҙԄQTKcŞ|:'AƑDH,YEW;)hU )We(tkGɹc>)=5KA䡋č/.Xm(:ù;{zNIt{Jd_ `R)c|z2s$Բur"1΢3"uro|jαp6a*H( bCF#ݓTr% {.> lZs $GHC(K7&ΡfrNصRx` VOCg:n6u2r1$u 05QCqҗ@(;dm[,f?oGV?>ml^ 0qfr8\tN@t !ɐ-#h-qI=G.itUx%E$ņSyW8{.>@:5F~aѽL֖-zbssXMo%.!Оݢppi(R|%ދ@vŐX?rL S# .BV.Iҧè=Ycg (Ϫ5@L\Un#=-LXB;igau2$t}#'&u#vVh./!1$uuk_zL-ܻyzV]8ME8:m_o%tV>=yXUtK\Я|(MgZ\.5p -Xj?9oI\1hqVuu[Cs򋦶hUަƛgnut"x6q45Ѷn8_35&]wgZ>kw+hx '7J]]ݷzQ# 7p{`w#l'N!s4JeY*iw4)Cz`Q'ӹC՗s@ѩ vтYy2>h9W>9SO #0;*˧iTvP^ZЁ:Ѿ]JM19yT}3jɉQ| PM^Q%$&LKG?3aPRHdRG%f'<,OM!E42a"b1 QYGna8R&k~jsr)o c3Y B.\O1 /P#rTROޤNM?HMQR}QLJM/WE!9yE421l(!\륞2q1A>aWɽKyAI(uR/8~"C°oR.5vˤd|vΥM>͇а d3GPV@ΥR<510C 4PM~^0qH (%;'3#Rۯ#&/ၸ*/Ir$v bWTQ_kTQYUAIqt _4ňj-jltipO;Xz[+'#s%*_A}DjW+H416aqLE;.+=b:QI{{?ne8{K/XT[bN6dz?AUF^jkcZg2c\e OvtŇpZ]cX׃6hZY*brŇy(xYsZL -~|ZkTۺ{f1_I?jwi~C`6c5__x~̷yY7:. q}eoxۨm)5B/~M->~|oԧk/)ߺ(,ZsK;5CxDK _`fup3*=u J$whD"H$0BzdG%nvܸNH$I[@D"Ce@r]"!d/H$H_jDM$D"H$w K$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$Bl6R+D"H$D a2 77W@D"H$7b_fŊo2H$D"HAed/H$D"!d/H$D"!d/H$D"!YD"iS0[<0\g.j6vU+ G`0hL;+Dxp:<`02 &+ ;OPӎc'2G&`>D\j04 z`7yMkײt!ѽH<VhA>aCW86sCLLߟ j+,6gS:{ϖӗ 9Ȯl- N2waӁL<1JLAZQf2Xv Y?`mͣ7pl]j>`!ԓc=vg,edDF'n2j~6kM4 zËnCĦ8z:~-bfR9;RgmǐIĬʀn:7 JHݤTa]:'LDډM־46ӑ)p:M`'ixRw׾gNnSq6r<Ù8av~Rec3987M{3ǐ:?ڨ;evq%.@7NnXĶt+19J9s#[g pcn5RtzT 艌 Dž`Xú+8݈ 76LGvEx=xV^ bQ8.\}xG㱚omҋ_|vK$zut䛢koL6Vw>s_yƼ}|:c9x V*mf< `üY<\K1#1Qsf={7|qÙ-Kl!"&SwzgŠ8gaNX&8M[.Q0Ǭ:CF &f[r+>XuaPpp݀5ncwﯥ`Up93iƘX.-CT L_0l џƜ]zA+h6Bz';:NF}^f|~NfS}.KbsQh?"sva)d^Ŭ 3^0f1/9[q-TeaG )Mά{Xl]0G8JGݹ/6_0k""/L>ۂ},V*2TE`Db&U~c,R,c CF&DU/d!V>gt4nv էx~?mQ~2ia #0YϿ>+g!bNJͅ}dE!}ѫc?3/)덈lV:m%$IDΎ<xN;ٳx_(WhL3~_flV>>3 #iATgi쩈bD&Oz]ٶˎyP2#|4K\B٩L w@vha/׾ eA);3fs>Q#11Vc!hdʊ2 ޗAI0z(79F3Vÿa]Q;^q*[֥ٮ= 7)((v\pȗ|K P Jz݊˫[bޖ -JXebEwg(^qb,"~Bl|] ~>}P֊wߘ&;K[#z?&7Ū6NmFGE\ױcU;W|,ޞ&?EVګb@xg_ i2|(6(w:)~?H|K!Gs[b¥P/dѹ$ө{4֜ZAd.?7Y;HΪVʏ+⧾).CxĂ 7ex_a9bǂŇ ݸ_?YI|K BbxrT+RyV tц(~"{?!k3[:y[uOԟJ3]e86vzO,?.p~,}_,U4\3C9+];鯋];g??]|l;űzݣcŸG+V(e4fLqG5w gDeAtM/.8ox*}4_)I"Q gkYT/~7Et>U]piߵM2ql".j[Ev;w\G>9_&}ib_-3~"_ԉm.%tCs~-"{76ic^x/Y}QԘh؛ukNY-n)>6@Ďح\`!Ѩ+v+VyHxOɒ`Fh19B2C|]v(O>ƋQ^*AY}YĆQĬJgR;_ߤT(«(o1@c>nNƈAGI+L|'z:MkB#H$6rtᑟ>^j72~ ^ٶFK=8;@JK( &d~ѧeHsdG3*Pk$wV2팚LY]T}{Oʐ&0_/9g޲CPOR1s%ʪ!.<j=/_ƥ o kG(~-;c8%@>1#x" 3VfS^]Bs-:7a${((m@FN #[;>׷[ t%(~<$1l0zŲooeh#ϽbmC 'hn*c '0,8W M_$lE"e`o_BОuS;RG)Pw73GW78]^"ecGלÈV2@/֐ #๑-#lK=<3g/qps:yèGct0n 3ʯPC̘yNad߱5/_?ٲvMHЇ7PR}2$M\ȯ6~ٯE9:#+j7&įZ cɧJ < Z&jaqMjͶVb -]׼}}@i(LV8ۜ /bnz-0̿B#H$V`;q{#1,->BH+ttX0!1L2 n~uËYSo'F͒UN.NϢEp$<¤Qژn $r<@e9:镌;=CXme\/OXdRUZ.àؾh)ޡ<4ī6ɨ>rtmMwP1ov1")@+T;-2-ϝzjnUOWj P IDATN`"MVp{~_<< ԜV2.'+sߔ:XBQ_^}G>gm])r~ښpy4ǁy;=am\+9y'C rzcZ&. ag} R׮ף+^L-jΰ`A1=|fiJk.&ݽ5jtRKάL8@_п|< ogDWV0,CTusOrW-Mq7CR'տŎ,\zS&ӿY+maw) c0C[ ErP-,f/}K^-FJvGjx⹟g. D"HVe}oG?GлF-*5}mkxq Ͼ Oһqŝ6zٓYΨ彟ƨvu(?ƴsظ7ȉ|k A ,6ғ#V8BfE3uP flf/G>`M}ZZ -ϛcn{G3'ڥhfg,g IN V#w.al?st1 W"*2G,vB}{O&Gqq`2 ZW302<3xpKjTva]i>֋Tvlӧp2w3x~Z0aۿi=ħ_".C[W#|ǹX8}w&ŝVC!+ߙ[9?}̟ӫu f'ebCf~[̠i[?5R`ks>eRWVk06X.z_>ɱZЫʅ3mZ=mO`q_^[ygl6m?J}o|6C el:/ yC}bzM_W6sx=A_0 G/~Tīo Fwil>>\O[QqRS&vCWwHZ5śOc SRku%wk0P jԅR̾AXc`GwKmLf `B|\&hnBi9.8pԭ/"|A(ZW\2J v` o\Ft4Vq:?)}`Rփ(?M^@\NЮB8s٥XCҝ>]07Z.dBlSpy$M j^z!&܎j;PWt*at; W0 *23Q#>I[\d&DX[}R?:[Fj ϒ_vr>ѡ- ?2N_i*pHOY4ݥpyza!v.!]UƲ<Ξ/ū+"16]W+8w2 O>F7.c}uϨ+rOm" eSbo:-ԍޱPٳY8m=x!zC쳧(qc6׷/FEy]Igrv`O BSZ7B٫ >Ea0?{KՂ0\NAdB_:[zW"s  [$zEtkq%̾~X^HAm`ihK(Ⱦ] &0 Nq=~޷<;K||͘2Z$v lpfFV_>S {%ُRؼa-!Q 8Pʗ|׭y"V6^xԋ"4bN?V-O+Ls]sN+A!6ţj١xb/B(^]f!+ 4e{]ŽY-5ܝ-;xJ'Cst8D " nu.dT[ &)~%Mp?O="5j2T=Ğ?IFw2l1(9MOOYԢ?U2ǓE=Eަy>xZ9FLSPhe̺kFt\-YEϻ~+NUŊ^BH{QѽD1PjldԜY!(R֠t6f)ÃD{^1Z ~tu:k5Dy񽿬jnV;T}1Ef]k]bϋ C[RU(3]ֳxm1ZvHI~wlY-pm?%{(&-;]^=Sh\F*~/FQʸ?=ѭ1He[BdoxC I+O(kjϊ??8D wxQ+V#n8;Obpg/#~Q\IMQCH<:%[Fy XOOT *dzia?CJQn9SaUS2|b̠}yl[ג0Ztf[ҝl*NcYu5'( }Iv5eVw1 _ hTW\ZS ֲ3-2gOi4C?ʏpb*.hIۮ ܋?r5;VI˲5XUuW#=SH߰Kkm3?L-׮p5[ē-g݆×ׄb F<ٰbŞ&[Ye(`S8^Of`el+ vLyڶ>yGc`ٛX)ؿ'1n1>_)52U9_ELb"WK.pG*ÙDv6,N?A To79A􈍠^K¢|4za (WsՠN)^ם(#Z72Ҫ<@I aTgna [lW{bGѽ+s,j \{gavj ]wŒ^Ǣ]Zq<=A')H;oʣ*ңG7|B^pJ\ЁSX+OdڵJl/%'3w>k(nPsX> zZltOž X?Wr~:u#)ƇCXr?V2-h?ϊy8Vaўƪ=u]'jH}~Xۮb34$ҭSY c9c$1;,\e?4g acyՃpM>;(XϜ%p4C>.Uܣ;Tf` U[4[i:tLJ"Tź.`˩bu =F`L !&J`N[٪.ŠdX5Kp8"esH;ՁC(8xjK]_´8-k"^2k; ,#Qr1h(ɵjmd_{z'1Tv#`ּ̜>3g0cƧrBl_1yTG.5ܲZY*H$6Ʉ1! N!uPwY^sc<pm_s<3ԇ 'i1e4ݜؼyყio>};'ӫK0;X;gop:&%ŷ>mQ0WY>)wO'.gCI@N>~xS%+w3xgo0w6& ǧ.˗L~_<>VkKqgH:ڪ9ejM_3?d;I,_Ͼ9ς?b6<S9.]i<{O=ۼmܑ2*v-cm QQ(>ϙ;n_0JeLR uhYe+R?,QzuKW4W<o,.pj'u"n3\ڬh^zǴ8rb=wNPOnfl>6)ec_vF[tUV;:g>_.Xٯ;VVNj\).ٖs1swcCt\6vsN.cBs{O0WX6]h,<꥛K<9: 2-Νc)dӲ%t{~44Ur m>20yZ ;u0¥MWPkw?YHQMQXXx 7j̽\c%xLt:DZܦY|V]1q(Ul^3pBb0# z`ض_Q5 cF%`ua4ˣA,NnBk˨d%m [Hx>1Qcqܘn+IȔ)nX,#YE~OsTgq ?OUDt=MeHg]ŹY~ 1D1xL?v@陽^sx ȣObUz +EFqC?ۃwb^rJkE|76JNbMPHI(݃4F[X eBbu<02N I!VV̙KU`ר;xdBLj ʋl\u6{~u*oZ),k72L审]U}Xc q1(S5.;ˆիy$jȸA;Fv+\۰uۏQ\/{;ftNf>"qdz 6J3Yr {NiCP{t*}Yy%I_ņ=(RœzT&m4 c+W'#Db=Hb4iVT =GCihc[VjAK갇0Ω7;FVt+m2=&7a.8kVѩRۛZ* L{5O+47z4TUpOST\\oL%ƻҳ?O<䓗S|2H$2|+ܚ=Wj;rcվmxNׅ-^uFZuvPsd=F,V˵y‹KgnrM(%p\ ks`ǍS~yiחhd(WS%2V-2L^m ouHk2>nCq-0^[b4a\+C꿡Z0[[ e e4L oPdaNںT3F֦,˩?VrC.PVPvj7㫢m0d[D"-tuڮyNnvW\{MwPJz-م;3aK楏ݐq[2Bޛe0|| >WlMdJ|a2t5涺 a^ȸ M7*$x\ KSeh"VD"H$ !xD"H$ĭ|8] %D"H$ov- s%D"H$o5FD"H$7z^uhd/H$D"|9/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$,Bj_UC uknS3H$Fɤk0M]Q^z.6Ajd/H$$ln@@}YubHZvmQWD"|h] [uYb uv:;zYm)xoMxK$;z.4ߚoM[Y}|{%S7ڢWauni[KWɉƾFŐU F!d0xp'ˀlljU;e}ԘM6š4qf/a!IՍRUӱ@iG Yբ8u%s.fۡ$*nJ~г ;F+0PjesYf3q)K2bM* BEIlM2vc:o* ]<&>l"Æ IMmf+7K{o8Av3&Kw\poPťދֺaYPU}1~>cLq&c1[D{?ۇwi[+{Y~a&.۶]v/ 3e1'OӧTax`Jg.Cϕrֿ+U_+b^`W;έy~ckA;}93f% TRW>qm3[4FNn]%8LL׾^d ޚŔ/N xw`maX9kkcKڷ_򉁔|7?̳(*9أԅ_?Tnkg<CeG0/t2ww¬^ IO4cXDxڸg×OSKBqd#Oүmm9|÷w[e!ty ̯9/Qȼry3r֫4.U Rv?7e}$L”/Cb-S1*$>Cxf>b# T;pBa]o.47o"K0,4@ÐEsd#=fh4b sHOސrORI-Vɮ"[4[ZrOTD:)%H_6i7Rt|T)hzz4obXbҶcRs?-9~.r4H+^(֖>\}IbY f/\'ŚrQ MR k MۛhkK7--!lj:'}2]ixiOs?VөeRRoJ,g-;mYRRRsDMʌ=.-3WqN_'K^o,إ#k9?,-e?*T^{>[^&UܢMf?Hm)f3IlZ$]= l祷{֒*uƁ)xވbvbKɉR|\RlllYMRF zh/J )1wvݿ ,RfF7)KOI^"]OJ߯/,n`tR):e0lO!],]|UJ0߳w- )Ә9h. Y)KJ;̶wӿ&2%!ɐ2\U']+%$?`䜛3cGI:b4qvĉs]˺%Nrtb}^hjCX^CҦZ`4 (ը5 #HOH0nwYt7GMٿC%q 9}sP: ,?GQ2/"z,xWj!}"\]6oFDTIw Ɉ(vB4jۂFƏ0Dh_(h EzŸ4٬F> _lr[VQHH"1)KnkUбPz6du%7UҴR(s\78yVat[{v[Z1v'Ji\DM:eb64QpBHT'I% I2hܸɜ!?b M3l@BpdШm3H=> m?<_&Lc"qs9>K֤rK^GSiVEb́+RFcgI,9_q ֊p|u\p!_>E60ɧ5r8?6W]> c:cWfs}7ߐ+o ӷݺhIfGvl =M=y/gʅ*dV!_[Jp{6¥ Smܰ ;c͈'Y]LK)=6O^ƻB/Rmdgh;;7lz<.i{[A:d$Tٺ6ZfϞs%K/\HzڛK{شlV%ڐXA]乏?ei%g^ֺaK֙:dv슥JxWEجYhܸ1Ṯ+Cм\N=IDZ , őL$sQ-R30u\ 9W7fS1ds:M]EɮOhEoe7gj2Xyh*)/Y:tWر;fV1t)KfC,]Y,yhƒUcH2R19o#sf,DxmPԒ BR#RvYJ93 4bj5fa*/3r3Z7\?!@~|!d>BBEHDU%;^!_"!"#ҧrs;M[ŠSv䛽޼vBBU4ۭmHˀTvMm뼚ƭf/ Oh~4?z{dtYW2>۸!Qu~Fafx-,Au|7Ӭs'Rر]h:L%$3:kƑ[4}̱1cYDl!k/*ã*u(WG(}{3hH^hV҄^/38g6 -ek>qAÁcJ3츗j¤?0E#5͡ |Y.1mGψN-CV*/by}JZd7 ;}c,Jr2?~$ Vͥ3d[4wYF3φ՗F*ck };Pŋ_՞L(wZ'1YڭxoƤo0߄MrȫpƁVk8ǒXh6MO+/BG sf>&"(R4w]F|@5!+0e@Bf,JN˹oG;lVqp .0kjɱ~٢%;6m[f8ckNٴ]pmKrPv߆hcUѴUyvʟŭHA2ThGRi i.]S"Y¦Q};G vl"ѫ:ʥshOcm9)V,Mfã ]nUQK=ӯfK Ҭ9)`ɢ (q|VqGW0Z+V,Ow io7@Vx3jxzzFM{ 55$bdL֫K {œ^EZ4!8_!V}{EnR,D֍^Oa*Fեֳ9KRq $ͩ,ԫbB[ xDth"ܳ8w.ÉBYxjįde5G"#{Uj%m2j+JԢqxcٿ HU*{t*/*ՊQRd^=Y !r擛"2Q^#V$av2h@I?My+PzS~Cj}>> ]p!dffz#,{'wƪ͇9$7fm$hQGשgwݜpױz/KArhLfeĸ?!'ygBʎ_+Ճ|9YU!ѳyU\̥mOl9֍9\end]Ő.4-+d\<[ ti<Һd\`բ8socŒM5Gu:翢9"n9kܘ<,5r,u ʹmxjk)U>K֦S75WY7O5FɾVJR)XS⏟Ǣ^țkruTaZ0V W0^72&v,p!X,kГOzX^^+?*DvqRѴ vs~t9OqGs%цѢ()ʎٌR,Yʊ\*g9z<1:[F1c^9;HƎ␗_}?˸G^GBa3D۰YC 2gӼ2)~blrlº.*(݉;e/xn /f7n8ZPxt̖_dȳTş$8{,YH!4vo6G0d*РO7q ݐ2/0oIѮĞ|,QK]޽Z] Go/OVyoxЩ͔j5/o퉧(mPAԱ UGzڵ8¸65H;3T,_ zw7-d،5:);Zj[/(ϸlßgti3ЖIơ|s )p,ɓ~j5. SÍmSx{o(_ܷ 3)ݠ=%Mń~^TS%p _2t`TH DeM$jXRӕO~Ĺ}+͏yѤe[= oo7Y]-4if#;v`„Wea1u^Yg-BAE᜽nd6cZ";ձ ؿ|[Php 9agAϒ7eGMVy}\Sm_޵S7TGOg^o?fh1{5g[M|AYYvЪPșZmNJy+Hhom݃K/v/ۅNRłyd AXTo|3{cŖ2_jB)2-_.ޔV߈2Q&l_]e2+Ѿ_sbߐ2̨^K1f,DEZʖ7e`IG2 T סdbqDv]kl8#FTőG?c29**c6@Tm%alAmhӲm>BH6u[1m(s&}Z᭗'ot^ <>bC䑖d\]Z*k5=(< T-PXʗjkjx.˂MH IDATr&5Hٳ})jH&ҭjvi/|9m%RDy.V![@58:7D4}q-_N]\3A|[D0<bJ́96ш0Lh<9jV+qhwʵnGHN2Ztq**5|ε|E+¿7U9D2 s@z(Q_> LgR@ʕ߳hB xWCQ. Hh |CꖙB(nGki #nKV ./@|zR3EvEgYliT5šKsXReg[eK&RV⎟?!HK-Lb[Hj\?8]F&r(P E@fcU#˝YňUjټZXmrnAҠ!_aaYE5ٙk,lzaU"m27 a$U琷7"P\ةU-JC'|:ZexaMOAnMWV uZ.J䐁EnETC>3M8lnY,j4j|XHgB}d \s/ۜIDf[U R>KRjح1 .-d,[s.j%DӣJt.ZD4[0+sQp1xmx!keѣ^^Π[a`SJreq3]X8Z(8^B0zy|Mڳ1&9SXr܏g|fe )1Ĭe?ӿ +Meׅ֭p?lضt^ӭnϲIq#z\ _L)X2ghWA F=i7ֻٺ?=!SEʹ=n6z4sj-FҥQ|56Ƭi3Z7AHy5 OzX|h_O mNr5#k%xl@EF.e׎̜yGCBKc_pVFLHl]:k5q2W&Y~`mBGQq& w[x㉴(ȸt>c ޘ'Yr>a$]'_.gtnZ@7ne7sH-׍O!YzNX9y0FKiߘ9' G|Vr NG?f4,]+z/ co$U@!cLyl}[P6cIV|?UyiXBy+ Rϱf:*IL,V hR=^ ~%l"I8'`BͨCxٮV.Z*6hG \mjm9VC=+zdQJL>-71?cHEvq-&|N;E%ګ"c?ˠݽ+J!5~ u&j(\Fm_j[~|}7k(LZ(IDS:UXC?$s;  R,ϫ# f:(< yZ(7:O`y;馜TR{H4 = *۶m x͚5qՂEMxk0X}B)-ڱ9?,ec\LH#,uϠa<&"BEJ>=-b9{JPG5{ cWH s-fcK-5[ Xwu~ZN)D֘A07f+Jc,a+KdMjuhqF C˕F.q hfN[Ȝ .'fT[oؓ<ּ,ZZO{@iɔk2Kdf?q?lZ5}cZtLY1iE܃`)3ËX#pvnjjZgbs͂N4. yiQnE?FQl0xw=z4e˖M:3ƿdk/NR+$<i29 ^W@$]'-ӄӏaxwfh9{5i qdCD Qߊ]]$F8ndQh ]!e0fWRݳ]6L$%ȾjB#}h7ctvww'3 "<Ud a2 Ώh6*Up).\ K/AQ|.]رc ({Q -nϋ |0ߊ\J_ɡm[CY7\jhjIP ZS>U\Ťopo i{2Kv; /_{ي}2۶0Av=O]_;]C.w\x "!WcK@c^<4+ i]gRyW+ .  °M֢\Y)Q>yz,>UEB 9fQ5'""" ^| ŷg\p\ I]|k6a9oy滕a9Xiva^ q/j .BjYKAb{p\4p\4pƟGP#'_rq\pXiv?HWiy-o ;ws}p0|/W¥ .Pl\Ԋr 9}]43h.h.>B .BEq+-.\4 \4z]x\p5~~UI"OzKw\pa:#pg]Q,Z/a=׌OWKw\p!gF gPZqV❋9/qu7E8X["wW~#sB|'  .BSʕsQ{\NbAvss/R9Soڃ@΍xdSVy†S~JΗ'/?LiW蔹 .}bV\t/Ω? {N82L0B<5ɓP2"_Nzqa3w^O\ . Źӽ"g.'9$Ìx?ʠ&_޹{i/*8Kͯ+gPS{v7<;SEN]w/'}t⤱ߑ4>쓙 ?qM#UN^ ʼn9Y9? >*/S;\p;/j_@~A8x7"oKP>ND>p!T0v=H='* 8DF;6h9q>~{N8eʯ8xW5 .'uZ=<<.JPYnܳTL ;*nA4y[V2V\@VϞ=|p}AJY0X$+r;I,/M);CqI_qLŽ]p 14wm)O8!_#/~)->;Kʃj ^E 8釯kc 3Z-ycݬ;yv#}9'M9 BewމVvڔ-[NRn:lقhKV;w..\K.jJϟ?_N(:uD  RUwu/r4^5X"bɒ\%^GUz]p҈O6W" -,W ;7btmzPfJi& hKNB t& w`*UKX2OHGJw.M- @o¦HH»%yHMFH_:8M|Xrt6H?ϕ$=nϣ( \HSdtm >-Y*Kٷ WCt4-pp„S9߿?f#44JPw̙3ׯ'O$99Y>}iӆ~IעEZ* 2hРBzH(p={.,Jtp~}v Nd^)7N0w`ΝtO*yE"WwNi4#Ƿͥ]_:_WtԳiOSᩲNѯ2MZ6X~?%ӭ\EHwW㺶Dda8=WX 1{خdˆyޟ(U$.:7ɺɄէ"%OcA m| ;vp5ŝ:ȮJxO&wU3-ymJK׹]lAג}_xv{qUVO' ,Y~UѳmQ4A]2aD۷7:m;qDuX/ཙ{ $K"ÌٻkzG۳sjʔ$K$^]6ģJ\.1.R.|~mZlɂ x7o*d+Ff,/|B=bU&[g̘A*U9[~`yƜ^#jo ˗/b&Lp_{ t~(}Ѩz6T^bθׯB{ GeqG;_OéYG6vŐ&$zK(Ʊ8I`lԑ!VLJ5^^'R c'H/< Z씬ޔ=yvVlhѰ V%oOmgHU>Y *ۀfXq9C&QK{_AA2aѺUmnMY u$2؊bsB<0ƔMMٚu_|mrD1VujG3_q)w^ AvS<ҤDP ۋpGtt4Æ ՝ʷ k?̒%KHHHț4iBll2##CVE!Q*G,t@ ua%|6& fDyWաc*Uޙo(^ 03d&Jz ]k'H%>f+myoRWLrob'.\q>*$WCq+%~~:2s.q"\QWY.p ՐZOzFt]m;Nޠ)iOݥs.׋BB5#R`>{S<ɝH U2x*{r~^~8VmDDd| NjS6 y. vJ z?y"?a{;Gy=?GD]:EWRvVmۖg inA -]KWgL}\I[7ybs'dѦM)vn9Qhxn#q_&>8gīJ$p8aDDDиq\T>}Z#^unٲe$&&2vF}N!IѪs;ԗwGw/փ-뢰Qdt È[pmkoVڱmoNJR3J'>4ཧQ'>62nkӉҙGtF\ƣkӒ36I!Op"qədsE.\Ih\dUhځi21^zv3c: bNɌ n#.m{gl*ee%V$Q=ekg#1-6 `c]߾YVޱ̰:r#%:vPҺuk>ss)d~۷W^wtMv'x7xݻ>ǎE;Ki j1Jz2xnQZ* nGS#a(*Y2KՠR) 1^4}=}_/Ħ-ϳ}AEj+8ń١jɻSf2Q$!o.ifx%f%S /RA#Jkh!a-Wgc)Քu{k9kGS1͹wy)1Wf֭k[({sFeZR;0cubnS>f2 MC ;B 10ޜXLٚW)ߪ ǒíl m{ރ$%U%ZFWFick6u>|w2GS&M~t!vV} uT?Swxfg,%i۬,D+g?rw$_G{8ʱiל  q@5:%?Nfo'*VM,Ēm#?Qc'bԼ%t B(bޱcGoK!P];^ffY믲?Z#>bBRa+Cn }Ӯ4ȘcbɎlb`b= *E`_||CJpH(" \ g"Gf_}'^ҹ;~[b@`LG[ -JZ8t2$p/iգ֩Uk_˻vqye;&Piݥ;ս dj>'`ʔ)swb~7nj'NDy(- =^tlU}=-vBeXj9K"UiOMLS$m$bּoˆ w "5i<;SzꅜQa3]j >:$wTI[(,庙Pi(W|Gmeǟaw: 26X>λ<澋8bR4[!%1V1P+29]pA(Bq_ִ XuYfrg xK/ӎ0~$ČQdc[0JV$ 0SЧ/]ejcV GQCa7f Y(.eF4.N*#o& Zf_W*UˍKظ5vĘ1cԲO=\A6,qWS[;][YYf/xׇ  "T XPP콀 AE *XQQRCBO_6@}g%lݙ͹瞳aCOs,^U;NǕKnCvΗ i7M nyysyd(st˜疐[MÁ`ǶI˙0n%'=qmKoPX`ߋMoud9\Cjs[4$Zg(?^ƴ7`W?||>/'20ӏ>yhBqyvo|:ӸU+ eSo~+6q/"#_8;vl<2k֬rYS7^pgP5zĚr9爲~{鏱r;^|-^{ >zE /&|OSo+USb?óy鱋 ;[%QdFz(M2K~).Lxctej׮ALn<5HoASrj]jW4@xPlԮJQ%pI+P%ul.S$yƸU.鱏;5 ~oF`Y75c_bIʸvȲT6y;ӻGO_ЪQ[/X _$!" TZ5#X_Ņ\Ԉn VQS'5 O<8\[A2nrs}>}7 봸ǭt9kMۇ٤ {LVR?qI]ծ;Law`z0Vcu;O?緩Zs Ј&NGwX1?qba)Ak%Q6(Jl2{LSM$V"9YRDQ&(s,޿3Y/?͏({Hb|J=i5αH  1cǎe~/s*:Mm۶eʕVѭUDĿb@ЈɓVN09AOE=i"qFLT>+2Ý\6lMdpҨ]uEԳK'sGv'[pà:K圳\jS"uT=8<:t>IJo`DP| ͎%8%M6OMOVPޑ};lԪƋpt?˼D]dI0r?hР3sfE'jvNwq+eGR&g4xı*L(0䢜hw}_>XRԋFN=~!t)eC([VȧFjd2-Ӷm%T7k9P*GO{_9.HX"scDl`j5aEޫ0r1 V:i$9[PZDz,HX^+Gs%FCuJ3,nRkqS:FvL%Mm IhKr93GcDOpƇBC/+~UV4tסji%*}M$D cМyEWIՈGJAnRLO;\UW:H$P^j4M1\&^Y?&D *Ej]WaZimbU#el|O1)4r x(˿rE wT:SeYY(Ǜ0"J>fE1-6k)+ $\rC"4wAb&ͤ8+ǎt)¯ow:(JldI׃1PZq%Plr.;U,x6s%-Z/CyS9E5+a5G sӨ^V+ܯ<%ME+.JT"btyJ>_QSJqi^kTα~POUOV"Q;9j'Z:FK9ϔW!s5!uӽ>G|VImb/k$*X_ϱDE2= IDEP>4 %BNF9QxVg$\NEI@ʝ2pAsK⨈s,D˄VJ|$Uf+ =?Pr9U^kKA E)NG~s$DYL+ 5ZQVDn{aUh%zХT6B@ٔ+桸UJ9c-,f8zեB GxD"ż+)oZV(rSVN%P,O*4. VnQ˺gLQH$D*M^5{1M Х'-a_"ԃ:UW/I$D!Jn7^+f7tI\UT? -v y2J|i]ЋRd8_! D"HT7vFBa}'QTFp OQ(:8H$K}p 7zѯ^"H$D"K$D"H$BJHl D"F(gYB$ 42a…[ԯ_?ݮ]xǸ u1Is`&nkI$]bu]9wKjTƝ'K$@rq`=󗮧f>\Ҭڿܹ Gܩ)bƌq\z /-[tcH/~[\eb~rNdƈQgd”ߟp۪ 2/U[Ÿs45s:q+3푵c6lH߾}KZ*UUrZWBh\"&ts1U N\>YڀK3֬|Mp컿*e' ..Yfǽ[ncH$ `0'Y(mL&Hiy ST6撕4G4i۩#16nԚ0n0Y7eӰUjXp87bst:8$֘;2fpWٹxPg| /&OU}_ mM-P3mӢо2Dnў'!?+y6TNNi\ش}?u%l;AjKh]'wǖ|ZtlN"s[MT:a"UXoڦ.ZP]>˷u#& YW KpHwAtڕ"* ?&Awr.WqNߛֽYtٽ{7;v`̘1/tЁɓ'ʶmx"피ve@L@ -QK$z@TL;~c 14r_̄%Y[X>}?DBew{oEyz45tf$ɂyȅc?0|[VukSez}~.D9nT: d43oMﶯYyu};A^m5i@F0^E)d#Xh_M,yW]-ގ]ꏟeTO7y5`w;C^܈msY9:<~{[f[uSw<`oThrXt/{,'T*ѩ;P 5є6Mu"E=?}Ի86yDL[Lb,2ʯ0?E,)r cذaze˖Qzu8=֥Ca(Pn䯕H$`0e|=~F;?Nş>+`$CƁcԺ 2tDTk}|bwcҤӫ ʗxgT5i~Ӫ=p/nFtn. 4h sQƯKځnuwx}:}/X2gRMjժ_}UРp ~0>j(N''qI̺R2$6k4&0]y OɅWϑ^{|l≚iZ'r}viO޺O'jZ[ݜHϿ#;Ct)$: }{4>N>UCp?l#Uծ~?&Zo@"=1.'&x"s wm>d[[htyA9xT?.(6hv*.!EuVP&V+&rdolUhJˬ0oȣ~ĹV*'&_=# w}ÇgV^͛}Ĉ4jԈO>Ds$'QwMY11*{G/-{>?~πɬ&<\ܯqaW^_VZ=iڼ cz5[B2o׬?V>BSJrPor]DKͯ'V6hVطaƠo8WӲYr^ՂxplӋ5.> bs}و߯mtUZr8t,C,uUOM IDAT<=efW`{.AD+1VG|DJɚQu >&PDC7 U7M \\Ht'ru{ۓ~o4 7 _oՙfLK 'dL-y?\) 6\Ӆ[D^&WKM3w7'Hʀᤦ/⭕5fwፙ~gnj1W#Z5HLNeȘq<+LyeƍA$]!,kpxΓ!;f;VjpU,'ARDէk~r1U8[06!CG+ls8|NF/G\X+,|K25g.5Ӯ' lDM{Yk]NTޛ;`LLnegpT'dz?m-{=e^ץ\C{ش*J "]n`ȏ0qw^s .cDw3O~34G=FoP?.S(_MF6v3Sft~[~J"#e8ڀʶ>u/O>WHF{[O~YXS/ hsrjTKydOL7hЀ+D?rYCD%Iih\^UKfٚ)>՟N)Vv6ŭ7tbٙnkL87N@ ߆'5Kf{,'6cy4y'`ht/5{2BKk'{ׂYA3MWWrK_\Do}Y|pU=i+$_;AME-<{)x6_|}p=S /\HTN- &;)wڵ8Έ_Ź{Vg:n.xbC< DFh͒GM~ࣸlq-]]}\2s]ku<=J1f'{*Wx"-<&>D>q~f6ѬuN(Y{X5[f?vή?pov\uiT MiYڬݛؚiu&(3;iy~ N"G+ΉgړUshܶ5U;_S9ֽyj܀|}1'>wQη/x1_2k5-S]a3``VF4YTЅG^r>i+ފ4KBYx5P>cőcŕI\$k7(t |R<)omAӳ.o]E^ߎ\"H$a0pŅGv)'o$5ܾ?H"ND"H$IPiWn*۳J$D"H$^"H$D"K$DU%[l6+{>?V{EeBQ6THuH/H$U!MaWehp]z4N%iACﺊCxD"Lxh\CK*DE-=d)L({eP k!DDiHUK$DU , A yf7<)1,Nx^*-G/4 3%*bKaC_\$D h0kDE"5BhRXQD hϵ%y(8)=Я%MwRiQWI+Kdz'[Q{Nީs,h%kۃ6Gv5VE0dE0kċ^7Vk*f0͉UbɹQy4Ud] .Nws{ķ&z/* KD C<WmZH$DmJjUrDVʆS(QL)r_,Vaa(zk9]RMKZH8յPAIoB^uIR2KA 2IQ=h,J5cR:ZQ^\.MmbTX]-mb=.~j@ZS5tRJMW8Z8_D:Mcm#ͻD(]xt_afW|ܔcT1ZBb܊Phm_XhT]9W˺gLQWQ!K$DU @ C4>%D?|E/TnJ8.8i90|Ja KIѪ㌔VHeE92.2YV̮rBRZCIDC'r޵0u*J3Ϧt)%XC|EJsZ^OX#yլUH49&%cD(;V?%\^5%Z((p嚠Pt]Wq&PNF(Qsq9.αDV:Y^S)&P !^# PvYBαd%D"h]6E.pz[U,os cD"H$'"M*šN(fGYBӣUP"J^c:`dW3FF";=pg3:rIEWD 9Ξ]Ira1@|$@Uǐv fJ %D],6c[YlV%`J \CzH$<< $ᙋ!JY$D" ~?V=3bmƬ>aכya!Nͻ/3av<¹xv`qyk5 D"HE0]Ā-&J*v Qh!.㱙 ňq-WdPuRd $O:ucCF0{O}_B'FݯoRƎvO Fs0Ǒ[nq4Ho~ʘdc .߃8 laiڃt{c $ D;fͱFpW$ RMD" F Ƌo.f?s-̣8Lq4nws2Y>dؽSsGnZ m9Xu.'~7&M;~۫|юw>x{W$g(Ly:Cc5<:ְx#u?psЪ:<le`' D"Hth&eWkojo~߈~gwN炄}cOw9wF<'dd=$Te;H4'o'os5n~lcT}q"ClZVŕRPۃ'*UT0Lrϱ|HѨc#K&Hڏ/>ܮ/bg|./g2I@އ;:9,H/H$]1-׽.ܞ-X=b1c !b[;&F˅s27KĒ(| \ܯk:h'f]u~nͻGFښf)jGə&p룍 XE?G{ޮvdD"Ht?#z#qV#.뒻{=vzB&~]A ȏ傁w\{_eƤ+K 'dL-y?\) 6ۍ%n^ ;ZEѮp6,) z9&=6 Atp[cu.ZhHJNQrH^AwdF`$֞a/sDgRn0='⟎ٿzm7~fCξtmύS b5&/`Ԝ2׌O0q y; FzfTUs>}"I'ߦ`gU$!TreV%mߩT2_*+˞.;9p]%NM. ^Ί7t` O{tp+ qBKxm|:t(H cKM27y{z7&p)]G{hlsMuۆspUA.lrb:9Ԩ {Y Fs69wRM+6f&MWN[qele{%47V !ÝK [%? iiiYIIIb2E# |x'21 FL&$ԑ.7x0 wX,J@?~0KᏭàVeSzI,(xٸMl?ثG)ljŒO{om LְXT`'_0xPL4h4rر씔D駼ވiA]gXD#'؄x'T~WN;1;ssy1$&yN2c<@8sKTTT볢$Fl:Y6$x-QfjjM83^ٿU͢1x,~kD -b~Ŀh-϶{lϘύ-KM;(]Clrڭoh߲3P5lR@`JPi!<*E'뵊 |[Wa|,6sm~M]J=ߧ< wᆑu_cr;/~&~ /0b[W֊w?zfqw^s: /5;_zJ_Ԇ D5Wi?&[ 1V\y<2sTF,)k]"0'>+EjUC4i܅umƕ~0w]ya|RtuB6 HR{S:_Øh oh3~pbg)N8/@f_tҥN" ; wA#~IWqd(o~±4  Ҽ2o.)nnזy=MUhx{|:-sanv|˜UG>βYjs7c 4~R<א.llkz͈o]{2ᾯag]"H"nq-o1 f@IEzQ3vlŻ+T0ңAGt]ex>\x~ ϼ-xӒD(6N>s|">[kEuu&" r?<jdD"H$J3S"&4jk}Dh7z% FWU3׭p FSD3W0{^ dxuG+ed/q rw>Ww7+<jZV+h$"`%!.`W1Z1W_x^1h(]8]yejԤ.8x=q=R8TkK'"Q'Z@SdI/̋|i 9IB$Ȯh֢DԎb`yE\/ K(t)k)JI,8)+BZҤЫ.eHoTȩ}o)6ҥKHKɸK$ZFMU+*bfM^t)a0`{L7Vk*f04 Rnϡ)pZC"H$: 4'^ DN/̡4)ђK$QtSH$Kp bkyIKH/H$U qIL^uˋ́5!u;{^"H$DIyաjR:R<3zեT+ǧB+8:gJϺ$B^"H$C) r4PG)(*UFRhS"JI* ԥܐZ$ƪT:*lsuTPtϠ*JWQH/H$U\ө⦃yQI|- mU 7z%nÏ!*wddD"DB6Ę{Ks $rgϢcϛRIoCxD"%J]d5ޚ_iTNjZv04]jPjkz+T4D"QW;Z/pz0NbPPѡOz1EWqDVjz-PMoa둊pJ^>:䱨 tIS6tVY+Xa^"H$8/ {ӣQ[o(y9drCas,H$D(aHA(R+(M NhshsTH$D/N0;%)VB; 혧7EWr% b2s" Ctr.`0^|#<=vS\yYݖId<*`%SjqZ oo:_MZOӨ|x^ֲY(ihqhbrGIX"lvv om5\NǞ7qycXt1oN'[TX6b$sei+{q+\ī=2Yqdꢿi~ŵ\8 :/Atk?, 3 o#Ҙ9S!t }jg̛}tfվe>ˀj쾒7XwPKޘ'7/5Q%M |2/03 O.6^pE_ 0sZ79 AU 3\`>4 W.Rαd%}(ڱ-$T&f5bc1gobŊ9UYxud0!sY4}sOq#6Ɨoc8>XҹgG=KFCj]b;ڦPb"ϭA>~=ЯqfU균u}~}Yq @YJD9s(m/֜qٖ_̖<M]W %mzy$^an,WTnEP4)scDx\B&_`lП{uşE w==x8r0_Q̤C&u`xqNچ'_y6.Ծ^GuoDhxnU#`|6&t! &?r59hy$ FwԨo4k?͒Wp(7{Q/hZ`/X>Li3\%QYavDž#J=\cPK$z&Uq"'`%6:֕Ya^cmKtZךh`޶ߋ+*=:rHׇ`;YX; No+όogFF K-$_@e2^?W.-mkSDT&gz5uiٕˑn*WN"J] JE=н>Du(_@I1CzAQ%$ȥ'UL9s,TbKŊ lO{3ሪF:));^|^<>?Lx5kŞCbxn8 &+q (+7|`Dv  R<g69/ c1ʾ] O~Y+Ւ*ap;X n:91+'%{Ȅ?j-Mk)ɕJ5BhRGirdxf>ƨxWM,Եt'x}f8;3朵o£U뵌K$DW/|~9!\dfBw+Zd.h1 nEY*΂<LRJu|N6*ildQc*S3F{J#*>ZZT=D5 4D"h B>/n|H$FnbH$D"H44D"H$^"H$B/ uȞ l! D"H$^ |tz_g^}h3RIDCxD" QPJY:?k]'GA`B˛E)?#4(]ŕq EERvT Mց]0&RFeig7G^7i֨WV 9m{gbIKuIG-ꊻ2+C.4(VQrEC({1gZv]I(B^K޳+tgbpbT0 g>dǪ'%1j~c?A'qf[.F'yv=4tiDrP)uF-Z@16߆q klF4Ӄ.<OP㤬,(>ZDh RE{.NFčM{q Q?"=.j 9=}=>Lteݻt, tgѲ^e|.&}/7H$tVQ1WjNPn2yƨTR aƩbv.-iR 3@WQ&7TEWQ1c"{:q5GTJXraˮ,ڗ”,QD"/IQ\ߪgH|h{{5MjZӤbgǹ헨!෴KvvbsBhKNZw#yr-\'=Ie-wh>"灆Z4`D(6fDM׫͒Z ӤEMY^u)?M/ѽN4N0u]*E}{h9OgoM<8cf<{kfeLxE.ۖP9*́ZJ/ޡc]^KJ]DEYٕz=n|l`$mD~= yf^ލLYcs4K4&\݇W? ^Y>#< 3$OI6S^N'1<:DąLlDs8V7 Ƈ0.+(*Ntq4 ;Z01ţEX B+uu].-TDWQ&o՚!s粯oia6su+R \M;4v|o%5 crV./RwW1DRf(&WF4˪S!j\1hX0( ZW\1 B͠Sl M7]zUتtVF:L.pW'}GrSh.;4x+NR!L2dVDR" 0ucULVu)Cu)QD-V.JBQ(U»j]@|ޔs'-6p $ iiiYIIIŕQB!)ʕE3'Wi[<;ױcDzSRRtp Ezz)7w-_+Bq=z= e( beHQ2)H$I)PXNK4t+\:/JOHK$DUK$GxD"H$DCH/H$D"hi%D"H$ !KoK$DDьb&s7hLz e,vp{j1r8ņ99xD"TxXblE,O7ڢ>Aaf[4Q'ga;V,~̅ o>xcdݦ'y{x2eU g_p nuKz@F%DRجMBjI^uEяŞ@|_?|'_Ng5MdKgn&UɃ#muaϽ\@X<{8{w'D&]|2n^b'UkW%3<;kZJTƮ㥷r(߃Z?ϐU4KH/H$]TmDG1!ۙOӋEɸ5^|XX~|G 73=TKmiَ)w3&ዊt3و  U;ʛcbܤX~q8)uqAxi~.3{'2Iq䕗n{& 4d#4vlgf]_=1(\і8{B FO%5%0cY,c"]ʰ~ql[䙟a*zʖ2cɯd-86B^[QH8rܜ'^_&O`_~A:Z/ZGoq-<~1?1+Y2H/bSy/ոƾmTHIqg匣i~^,]L/BZ_f?Ϋc}RU"Q0sgˠM* 慧gW^ ژ=?|KO<9U{.a Й:գp9c}^'*{Eę8+0|nb#ٛdqrrD7hD5wuРy_ٛERM8 @]1O͢_/oj'8z Ǿ͒jСc4= G*Y M;ti(dς#`p oX+Zxq/L͎'"rVO?5=pOߪ{sabL9G|.SGзs)Ù\-#ZPIߞ] RK}nTOYmZ6NI ei'F.V8/&ly+Y_.<۟}vGuM._vO|070/@hMw* VàĜQ~YMZ/(ā=fl-6 a$-!}l_rcAp"z2Ny!F]-CK3wCa#Oq3a0q ^er@$(>=|<{͂92!թ5v2a"ɵԿLYZK0k/cl(ݑ 2㨶te(z҇AKzJ"Y$6I \Ey&d^G},NDOĈ /"t\@sc0nϿx\j2qLN9C?}gMr5S@ 7O=8\| `zy~loߤf"vM$(>nD! YW 嫉iw,'TH s ,_ӈ^Hb:I7窻ưb}RH!F`1@2LDzx7yq!͉Ghf}밝c9-$]{ѣR^eCo.?{.nUq+Va3IOSLb+++VUVVny7EcSlVRk׮A`WV\FݿX,ڼVD<ˍG]w,T:xt:bM7ϊҶe2PZVk *PPT?uN=N8"rv>([T \|/P6e]F=*g֜73#'G+o6Kۗ,%-ړ SBWOLŢ?̚$u5wf#S%d8,ն9N:d(QSd(QU3{kH%  86 x/)yMѦDڊi '7Eyf^lL!cAAKΊŌ{sbN%vk'ze{K;XAjQ TZ މbLH;>;ЯA-AN3y"dz+MoQjz>v&f uqϞ+2vmAEV_9>e\ywH&3Q'=au]f<'${ʆ̴NLXaw$ ^AJgV( lFlfje&>?e [3{]iI.E-'"AK&a%~Yvm|ʘ .%8jWsAJ4vQf={݉velS 7m5¹'Ab FrRv03?)ޒ@w]dxvP!e^w[Jc:!׽%p]-L{gr%D $S bqO9":.;Û"5YIծ\DSD `Y2h}թv)ɦ|viSڇyE %k'Ou.w]avYN&v %13K%V܌'XS28%D]k |kծ\b%^-JBx% ah4Zg/^xgG1~a.y3NVڳ BK4j+]:%ӇiG(;69.cͅ\3>Y.Y_2i 0k⿎!t>{Ja-ac~s8xTƺy|۳i[ g-SS 폵b(f>@Z~Dt+ʮgw{jE"-g>GhܖCeItr^4N# Ʊw} ՟J 'xώG1cZϞ漿=ZVFr2YNy>Y ^հ^W[7U)  lF>Fw573= ]FNa_<6{dhݖa03eeU{[(^j{( Z&``G,`|8箻رs oQ9{?d~`')cnGh?@p渭"AO\n.t층,T~l H`Xr4zXB4C<8Qo>{r}~qƄ'%'*.> C`5R))#AוZ@S9c+χڇ PCGϓWbF"B~g8 +Rm:pj ұ1v)JС:"'tgp[ :e}ޱm܂Ky7 `>ѿ%|y6%oyFDZ4ee,3Ǿ`GQ#f9Hsy(4ĝngq-ТM'Q`a;~:g=;څ<~ǭJU!LOW~yXTQsW6'x}r޾#/B!v=N.?tq\2^zx$q_u' tN Tદ\CnaCq%M}Vy"tL|c${RTXi48PH/*qaIIp{5" Dֈ(-'(B-c] j}9}wV}^v!ZGVo~$jݍO?;{8.vUyYƢ;oz[gm/?:cD#QhiCT8DcG9}*tڍ2o7@C Q1*DOe9GrMIǯ%=9m!6y=wU /%ռLy;BzG4@<>6b%}q0"K3cbAc;F\z̽BlZU߮\q/_ 8dۼG`c?S/˅ؾۭ]=EQ[*ڷ"٢MYyESVط(m>*%v@y}ٮk~!&1OuGům9mZ^m ,i}WÚ:-e©ZqVygD] a ePu_1~[wgK V04 xŬ'\N]ŴY_F+kۇ'_ߝp+؍rXz`>x%13ca(wPT%9} k.Gy/8kl&|Kh58K礼CLO3T]zd-/ F" TYd9U$h"\tuO**( ]z2֬.LR]{еt~j'B߾xݽox;9`yR2][.UNeq$ %~E2p0n\B5C$ EQIapx\9GgfltNYz\z2/VwuWv'Bf-51 e{8t3z ůrFݶڎY4[vt-u7!q =U ^App;.x((⬛a;@xAbGp#h=L}mڋri$" G,Dc(L?+`z5=A,$n$ӵOT0/fG^öڿ8K#O$YwWs@;6m?'~?f9뚉kՖ!  jD   SLkHC ü@L:OD'Ē}xby_vIiASALm^ H ëi~͑w`0HҰoh}-E}'pڥCm U\% X>/74ft]W{"K߈L^|xv9`fx[B`j\[誢yΔVtI_I&61D #IOOUo36:eѴ/m>v6 h~*"AG xv},v) l;d!-–"g%b)ZsNAٞgjohP:8e40 veۄ*3Ia.cEx% TpCl7-Je3fSlgK.6 UQI-ڝyFe/vk˴Is9{Θs[fRR6:>R/U_C2cslc{͂`UԽzFj|)1TvHv)~Mgv}+[:6E3#ivf-UQ ǂ lm0ŠD)jUەmJ~[ee[^xkbGo=̐Re\Bej=;]NiW[v6K;!ި-7oK,Bcx5#S/% ESɳ*d)v=v^šnWK"7.Ů$A򅙃`7I>OEC卋%SY6L1 k;PT2)r[#ydc]e>w]l7Nl*;Cdb YypB3/)i=[PEk4^͢H<-Bv٣ArU]= MvU:.C+ؕ6 xS; r3ʠ{AT 6#@MS\{jZNs:5ah72綆]j\3 iu:W {SSiQ3خ*tt|غ0]{^dq\fQHg+屶✺62b6xi.KV sAAAbWd:.%vV3$vKi:>k.ݢREׯ?DcpnŲzXbKq :%&|&Z%ؿ^o[PՕw d{Aj,2E)f&^쟙vgKv <'®(Ä`j{vF=#K'nM7sSQ^nǒ95_DB{$T xn3]̂ J7ƴԃ$?DmK.S(ڹ"r i`r{lpB ve/@ܚZC_xkOjG]*+MaV{)ԙBK>I42m,$ZWM)bETNBV$3';7.Mnunn#uMe`3#8iM*\\|Rch )gKĻ luĝPٚfpReO-pYw5Ra3&nlPxUee|JKgBbĖTta(Ic\!v 52H(Q}q%^Lj  8uOp3w m( !^AA%hϪ-eD Hz#1omV-xB# 6Cyߢ:ↇB.UU:Qg~6h A0ttwfDd妸 ۷i7"X\F3Hۢ-io"o6^Գ.JIe'fP/ h~$%Ņu*Bd"MeGÄ#@(?wfhG?Dݻ5DSx]В0t%'պ}dz}U>3^YiHR^ kwp0l(z8t~g硜W׭޺-Bp-YgUN>r7>2loOTC4Um^_w^e.2 6xt;lSՍq729]qP7P.څ|]O9 ]bĽt]=A5|ﻥDU7>>֯Zʨ"j>zo>ZL7R_"̄n؃%Bh6DK~,ܿAYbay0`(ҎN^=z7/1{<r&l:]UEqIR" zΩ>Œ7_f1mwO#`H2Ƿg)95'A0x):|Z(l._x~\wiϣ?Y_0Q~C7IZ " 棢`vdui 1y+5w]_gAP#y^xKzYt\(̘Cqé72Gy}T.?g:EWQ,bv-Z$7bv"gO%@@ٟI^e{wv?wL { O, AM"9[ot.R=:>n` :hKrvḛb]cwtpe}ddiJw&M%oG!<+߁bndǽ _ ͨCFϧg^OVCQ?>8v+(C_߯S]3odA߿NwPd\%Fqy<7,4  Gbh.+?*\@7wL&QLwGCy³(D8S{}8{^MйƎٛ h1,N_[t5FqGHe]sChTk`+j r~Yq-Fz*dW Řae&J=.NJ֡jWq2>74ơ!J1 0!jFtD8f`PVW%̟/ }m8WP:(ʊRYhgFzӦ]a3^g ewrU׽jeOzW0y!Yh>Cw 2ǐʢt kÿ>CPWμă \9djxBu=]&X@]]Wω\xnDꨩQ5\!bH:x hA8b~'X/HDՇAI=Lɐ=8mh$oĉ` KZf΃wm9pU&vrwŜw:Nq`30*mjW븨0ey\I8+osfMA} [q1 <0IDAT=;:X}WcVw^RV6 2r|)P%wAh*.݈KF"J}Y>L},WsU*;XX8H毙B:k ό&Aͺ:66d=8aF~=]ٸȫ_ hψ6B:skXxo3jJ}&rM-ВKɈoa#oqxj'/Ň@mut,].W`*&BSSЖ+7 eC椾ʴKkWU6IUAM;j]>DSv$^{EvDBG${hT~ĺSRVl}6>Ӥzez]v9Q"E2lc0 nfyFeS'(N^gItV:֊#1DQ[y T"ӞiW,5L/Iy& TLnS6&̨g/`_ە>t+Ib7ԨhhnoZ`J=ꩅGB𹍟+n BSЧ@ NMp>-,,LMjⶲWb i-L&S;.2Dycɴb^M4y{*Rmdhؙl頻9%~( )ם{m|C=* >Y,_n#e{bIShr9TLQR5ɉ60MN_S~[|D Ss{pQMxzjR[qjE$ubɶA;5kRk0L&!8imlcx%zact-fX-qdzj+uF&Qz]-:."8fxē^C2 N9$riw6ƶ9xN)ahg\lǓa1`iѢ͇>V1sIRWy[C+վlڂX3*h3l  ]o*tU2sYedGfz,ZZd~.،A+ CcpNJگЅMa4o:N-wAAp$MQۚ.*Nsv̖W=^i\A8Nlk:TxTEۆ  ؃J#-o'64nްZkÓ:n6h. C B7[y>(lBPך7gϞ=A|<| `q& Ki|IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/shift.png000066400000000000000000001271211423020056600304110ustar00rootroot00000000000000PNG  IHDR@T}r IDATx|>4'xll+2۴Iڴɯ;i Y썱{`lmYsҝ}%x<|.t=!77W /,,%ADDZUUtT E"""CHP$""R0 E"""CHP$""R0 E"""ۂЬGQtL= @,VVb`,f| % ia<> ÃDWDD-)^0:QjH΋Dz_E{YEˌoGY%"UT1 =":/C (/$~}@DD«:9ߔ7agjR9͚6zKDD)^ NͥZ-.RՌ(;W/R,n2&敶'J 4J ZDDD]PZKj0a `' GkېtHHDDǻPc /_8~"W®3=2{6sku!kj&nstbĚ"Q]^wq8gZZ;h=(:tWti:L_ $jQY܅]>""_<2>hkԷK޼g&4ρJDZε oj8Ռ[u1v9:DU;P{P9K|r:6ST^xMky*w~E`F2D:o'N5Eie!"".5Z,Tv@Ir,!Nͧ8\8"u#)^UN ʀr{Q<STy!1xAz uBXEM8!,(kI*nSð@?DD93l?'76kf(}ZmEMErZD5׋/r"uB/vцLf],r *8:Pu BqRŸv Nhфd6j9/A`ΖЛʐ΃DD=(X,p v\l>>>owcޟ%Cc0 &&""38HDD`()DDD "HDD`()DDD "6 ,""XS$""R0l>%""RHDD`()|JDD`MH"5E"""CDZ UMVl>%"6"–h_?~n]s.v)D}l;B#)CQ?]OliBc\j:Y%TS#K{?ĦJ܉8]|׍t!A,߆.JĜ*nĬFZs,Kǚ"3?] İ@*Pt 6?cSDzY%{';Rq~|01Gֶϵu0qhHBcf\Ni^5ط^OWB:;3g#Q8}QQ.o^:=t(;pb%6F݋kFApzw&C F/k_,J)<A)7)9K&}#-y?Z"pXqQx "aFQ(DY˗HD$1sf#8p3FLÀ|X2y8bF>yHj58pE"1vĩŨŸH}"|Ա F#RRg:a8&Db)OCTޔob)3H&? I0xv!J!V!ɏ=Ȉ rTôO uʯ!xdLGS)uI 1_y k6}XA0d:ݟbB)RYA7ͧnK"Jjg{tQu=Hos _G?o.FvS&E#`$OrؚPNocMu $S#%Ѿ>N|!Hh4I뭬8. X0F?V zmPC[pN= ^_} `.`bİK6 G!9ZqrNe|z VΗo8E"":Ҁ!zD |s+aNZ]$$hjE lLi߰7TB8U]ֱї}JDZ{m3A@tS "O|Aonl^"FbjLLc[y z:[ͧřk}O38kߏ80r1#vt~-߮S""Uc> ,E'b(5u-䛈vzť`cZ~GwnO?BaawqZ7`ȎAx&FORED4 s3gAٌA |CH4؆8SGֿ/ >si! 8uΌC1EWQsE# rͬDV6@LpZdu?Ք9& hR@Dtqqg2;D?IM(:%ͨ,G,z# Z > _|Lʓ{pJL‚ImYJ0q`D5<13y@;q !xRI5(8JkY%Dw '`t.ݹK %8}&Hx1 ,5<,s0 y؉gJ136s D?I 8k|)X8j&:LfIDze>ؙy;MxWbV;;q4o Qz[12u y94끋8Vc`EoǔߘS"~Ro9v ؼGՋ8(b%vsshF#<C?|_XS$"#n^_{l~hbŊش' gw˾aop#su.:?L|o}ccc\hLXoʢtW\+O}ktK 3a|{?tbXa(Qlj.D# Viq8!ؾ"qwQEa6b_n"C:L,ߏ{ 0{` xL Vlc pgcw"S0,8K= E"" 7boiC a0c|CTQQxurB ]Zt"ǓYe0wP$"cL4Ay0Wy.)3&".n؆RQDEI6P Dz]8 痢 E""l6kQhCę'W6b:M45ښB`=?CԍoC:@D龍Ȕ31lfuz#r*bcsNE&߷(+5ԁᏗ C'`߆}hs30&>S "7oZ$ВRRN} xx1]bI&6ht1i|!lSa7aZ&T~ N3l t4ц!8sڦƚ.OŦ-،Ym 4=CZ4Xl7&5jKNL3~XS$"""3S‰ۼkuE"C~(JpSR"lTnL*#ka&6#;8%#7QV[})a@\2u|9%f k8S+V(C8_-[{"\IP㐉TW"X,! 5YpXC1ut$''"Z=_5L cC9aAD-8Tڄ*EƬ``F\jJ<]_n|F؝D"y`߃O}E}0aDĴBFBbP0.Í5*iJ8 o^Qyw]!ܞS">N-FNv ŵD&\?,4Cc{I[&ɱI ;˺Fl|`҄7&<~F3ӪEeC^jW(>1<8;kn E">|fX; 쇩aקlc #bJ|ǚ2qȘuѸc3VB50Lywe/bj^$_DD5w֟E"Λ1># >7q;6E-=V$\W1bz|vvF) &aU):v9!77W'Rv!""R1 E"""CHP$""R0 E"""CHP$""R0 E"""CHP$""R0 E"""CHP$""R0 E"""SA%%r kADDkDDD 5EUoq.]^ǀ^v`%""סXmrKDD HDDA+Z[G(hNmGOK>6!qËl)&g'6>@$d`^`g׺|ZyĈ2z̀[_ =_ώ˨/u:g|\y$`ǾURo~%JOrԚ,p)ld7kFv>SVI30?= >%0y-""j_)%[\~uODhz,"='Z&\$/En~ +Nz- JϠ1q:K{p0s'VYꑽj[c(H87Zl+JDԯ6Q"ep fϲbY=>,iI\5pW";QG`H4egXZPP("zpl?%!’>[$DD]{j]JN17 = a|pFD"6ٗYKUrJ )~P+̂ `BuM#$WWn Ek7T)IxPs)3D|=3fگ&")SL(CLv f'$@g1, 1}4XXS$"V>Њ,HQkecHcw~ܹf pJD\k}YːsB/K/57L@N@-%͖P%`0C1z6ǀX1Z+p|jDXv;,B|TB .7A UjGǦS""/Pt8(|Uf eX1=˷I;+d87<ړTj85EVNfF#1ASyEhf}ZW $Grv""oPt8 &ɂOboO+e):ܱŀk M,,FYDy%`"*ADNV|BG?#FYl : {VmW ňz;9k]ƛ56}z5&4]V.afduѺv '^ز:0Í ɳ{ H39YZ=6چ0F,MmQ'J111.C=YIgTM?ypDDDrBp"""W/*aA͓Ӭ/1E"""CHP$""R0 E"""CHP$""R0kGbm(7#vD̜1Q<08%\ +49,'߄8OBfi>cuX +m8gq0-/$IDQhPg"Jd>Muዼ0LLc d,3y[jނ2d h~7X$H UaO&a#({VOFa#Ril^8h1 !3v9=\-~͘m njI3.A4BD 3㇯o^ۙuKBR!S+~ے5ÔiX$ Ԁ[<7ꂦ>Q,EMHۧ1%cB R,@q:{( P<[cH4`3&.$mSiD]topHԀ ЅpaX 9m.fED+Fq4(Q`=7p޴]1b˷ƢI0c&܌8 SOF nNLd,AlHaac[W$źjT 4Pnvh>"(<jI@H F ؈}Q'  ufT,6= @8˖LD\d!;l=^I{Qua(7} S02S0qbǮBɌhj'7]{?[+V`X2d~s=7  ABmAA:XvX""r=5EK-*J[[__Dၿ }xLQck7׿3GV_^Qv1Ms)sESĀ0< /E~1!cS""uK(eӷFx8L<?}&L}1E98>b_ƿֽVcd|<)cFqQ%Lb5*Mr"> ߐTE/S+Df -l DD@͕bbb\B]RoP^^*޶5E VX4ná0s09>2TZZP$""X)DDD "HDD`()DDD "HDD`()DDD "HDD DZc)!b0ƤĴ IDAT5$՞oY4D(?c,'m^. ,y"fϝXLtC(Jh,؎]͙9$N¬k !j_HBߺ K|C,kcoWⷋƀt7V~4(9TDԀ[pQ\ ^1=E`է:y$ dݟk]V'[ SWf"8xMS31@7 "ܾ`5(oQ`A&6ĦHLPج*ɽ8ia0r@#ۃE)?v*c@[N)H,7nx}xI g_#A @[M4H$$&4!VRC>1@q D4aϦ#Rn$a ۥFAXM H ܅sxK]jObo2+h;|&'c0eƚYX2qgn >Jr)'aKv!Vm'l0I):TWI0RX P]U ϖQPEq ƒ*BBkP]z}8BO'X-a9^=5X.6fa\.V-hlm> 0H ,ݿ9DD}F6 A@eYnkC @DXBg 'h0 bܵ7`NABN>ۺ%AW !.(=l6% rg].) A0-MĶGPi4em#1}\|N܀zMӟs61@0;&! h*DN X X!6e7A:u+DU BFjD}`O$"][Eb`dz!㎴X[ӏ_zƻ=a^:`XvoKbn^Mq" X[\sCX8A"7ESqmH{QguQv@QC R20/u0\J;""RtKMQ,NGzz:fZ/|t-¦&b~KC0akq^Rl(̞7/lǪOB)'N䡢!TzGϖd|w;GOf`+V~v`]vmy8 >^*~L4~~[ϽW??V52DN_yGa;G3OFeG'-”c0uBLgcrq^ł%i3j"/NEH.GkwNS pw1p7y^f $#{!$Ҍq2K3bQ?5u]\^DDn<苐QMƘԥX.k 3`z l*uxyP$Ƈ)o/b!磤YDua>j|4cGe~1jFAKDRZ؀J\O;ѦZRBу`K[AqI!SED}A7b3/,'|8m|]>V8&<0U{j#AjL_` t*TYQ[]) -~Q'֡J10-GJ;yzH 5 k  5M=+ʋhc>/)Woijn,iw=1KP6M #0b~`6"YaFS0h Y,cMl $ l6 @ډZ`zGyQ׍'wb-X Ƌx'oh.j.z % W$`0@@mgsA/dAo{lnmI%Fe{^ϵf#w^S^Du8E/B0at +;rOU#~վ7UzԷ T_Q = 4ԡmς&a#4LԈz /} 5qgg0>*cp˷ܶ>U$jV)ǴL(+A>:%!s)  ?%@*;+  mg=ګCY^lY&( IHw걽/cwn:?'ٷ௿[ahԻ]UmIi1xzlSv&o9lb#}|&A<X:6:1?Ŧ<E2Q?  @i(GYKܑĄʢ\7 $&PYXj* $K5Jr DTR= ֕!RyKP^s E\X M=]ƅUbDL~oq{""rssERd׫Ww -]в>CKpL;)N3lݴY-< s3XKP`|!?9bv.v:b7ò.Ph:)^:Y Nf(j D¸yF""+--e(A ER!""R0i6Ge))<Q E"""CHP$""R0 E"""CHP$""R0, @C.5$AEXVeΔmy(Q̪g,ιP4 oX:,g,λP4_\`6Y>.t|@,V.jd22UZ|}}3iRg,x]b/C-o',;)6 TNrhIm~8/w:rǫgLjfx.ߦz!˽m^~qӞ?xUr9jfع+ꘖSHSu6?y*kܙr`ر.%0Jj9o6㶳\q㙷ճb^o+@t]?Wvxm9'Q_Q߶z"QPp,u2 ]~W*l5E"io$km0z+Y3}%֑aL݉Hԏy8 )F OwE"&5-bQE`7XwR}RpPJ1<ﱾn"gayTVV???-9ϝ;gɓT}iP5x˗/oW)y+Ǚawgh?4Ǧw_ˏ7%1:I?;' v쮃?`z\(ȶEb!(ԩ I5C'?%5a¹kڣ)WB?y'B6W< Wbn=1y8C{㥇ǵVh"MQ(7E'2'ߥ_MCVߑJ{]d:fmƵ4hwRf|73`Vyak~q]Xkaw 'OVPPP^^AP?~ǏkYF@G/5eߝ,D\rr(R 6o}oA QV|HLHvccRX4w,1 Z߁]S욳b~4,PhNO#Wk0o燷>f* ?"V]NP~ >D8cʱg%AXfb>X6;j fon hkK j=oZB FIƜ%u|* 3[~Ո(۰"ّ4}"O,[i[-..-(322w\FC :uy1([ '_SSbFLF qzppxTmۄfbȅ_(ڏډQqܩ0݊ö5#&b[q6rn4sa^qlqn COwbilܒ Z#bՖwj 6nVnc3M Qbb]zXoEܢ0VM 3f"ٲ/Chu}|066ve䰔k=a{zEMqW}87{ ً~t| [^F~v?ӧO;ۖF,FIJ u1\S iS15 ;t˓DqCg!vb$YcfL1NJJě$D CDL_ֺsG8O{Z`ma ܣ~y:b5]h!}'>>b<5 Zi I9K [5s#DļX{j00w81~?SX~[&|[`Dh(7FFFBPHY]].^h;ή ޤW , =&l{()vW(=֭[pYw^ڵ1ct*v\Gv36D|y sx<2?_[Oy1(I̩!#UwfZZlD+ :X֠ ~X6(߷0̎mߦm6m{}X`TuVׄ^F^Ń' i۰铏r՛a]NjO>rCl';^풛EiJWu>䩧uq.}QK ȗc_ܼj0y G|`Mxۅ1v.fM=pcz E|l؄/n(XmrQaHlГl'XB)xPr oBf7/( 3{ns%$I]_K"S6 |)^}p5^Rם+bbbl cr7W\{*^K5CoLœtx rN|kŀ9󑢼S1aYwj;[Tv2f!kZoPe56ՌܙQ_ MH\r%Ӓvv,Ή_63cl= ^[p?m0yP ,6Z|]>KmVw0S|êqX~(z+[05Ċ ^M`@CEr.nlSXc?(>OmڟVHHHK'PSSp|GB0;Ŕow1Ѿh*= oهS[9"bZ?~X96`3ݎnO>ㆴpv'xe,ws֨x걵p] :\()FL)=}_>+'_m=7sǘ4%%v)G'07g@VH0>0CGz3f{n[7(?|5&_[u83`?_xgvΜ9ؼyc=-[8'݂ތ[}V5"{HM1mj8^)ɚ/nfd$oB:9v!Oג_+<#f,=+!ڻEsWG@!f?F/(ۍ?x^cSG6 D`>AXYwnw8#&"be|vwvًA(c~{8x hsϵubذa=z}#sx>G g\.)7Ap/u$6ܩ^s]'7QA%= iQxyN%HjBҔ*ιл7|'aAxD,G4lǪF$õgenQi܋9}&Myd*b#7vBnn St7ו3O+KJXZ˾%7"PwAyyj~wB(J>M`y6N3P" Yo|E[:ShMCyM~Zq㙫񤴴5Etы񋿘bGNkDppI! gǐ !Ghy,枆D w=RahMHjq{(sc8RP$G Tk&졧|n&@eRP$'krǚ6aK]Qi&mXZCt1)*Q/P$$Aj0 8v ߭g@tn>es*f E>U *:HDQj< T[:|GΫPyǡ|e㍺nھwrr -ɡZ.eg EyWI%+X>+Zj0Kj*[~@R DIُ, \kTeg EBW,C]#\;52qAKi뢓COv:5vEs*_vx^{j`/ +hzvz3(ZKPU-ZŖEOQfX5M:@dZks5©x9/;X,/I?#8g֑姗Tg_ӑJl6&2y{Q3w.yHjU]mJkf&o,GZr|ͷMT764zz:vm6_G岺$aРA.M>zAaRN،EG{^ ? Fڹ8˧.8EyE.ױ|]= IDAT!}DM9 ȷ9Yڱ۠=[8]{8&.'"uLLR{S5 E!&':* s$;)U}?4g;$~<㏆]˹:ameoIIJA[.$e[s$*MrmbưC:*9ÆUZ]vu۔%R9 Ed|)Wm-UE˒<^Վ4rTn.kfm;lذK/?W~ ו t^l L-mCT(GLLe۾zcC/UpuWI3˨/zIܧ{5iw4vˏ˳J>uǧjs_j eQʧ˾}r .ͺ:8jtv5??m9^3dFK-jkC:݄jϯ\ljjZ</;cR˧3jl5D5\\*9lkjjpEV#6eC5Ϧ[tU>;o~~\~Nԡ3p3;X8eW(햷SۦSc?_jjq׬|z]@4LR Tꐍ2jlvܔCCc8>.ut[?н1v:/u^@mJu76 0jxaԟO-jss&Su@.>>ޫޒh۩ GOH6G,$2p1H9߮:R0Mt:{ rpU[6&>r\2r57K[>Q^Hr6ZIې )W^7uݵC5͓*) K3NnvЮwgtlsF_.kWe᪷]6U\uɐK٨s/_w\VM|p{c᥯;\sꭚ| m̓߾5X[~*ױƹsLyg"|ڢsffmH}r:=m}=E %h̛7"a%5C?z9W_ZN&!5vQHT4DEŞ{6tvgV{癇ewfvݙs?~KKTz- YAbjG}Ҩ:.4nXQjB>C 5=ͣŧ 0"&g4q5gͬyo׳3ؔjT (HϲLQ}ޤhSiO?U=6Dn`kI MBz0̧|0GCҤ284lkQ8T̴6UmLt( tLBANgD.Z1(}XVDmjiiYdkR Dg:bnoΜ9*wI K(Ye36mJ븑K0;e/ve^25k/=Es1|PqWoL-Hqviű_,9"2)(S!=TVM5ed%tҤITREINTh1g8t2CVҷ7$2&?~ը Y1 ñ?S&ߑp{/{iQѶ,ǂE#<|xѦ #Q,a=/ dYH&QLϮ1_L Csl]*Qg2 fEJTF'8v^A.|Qg|~ZT̡qż)INϾZ%kqmjiF$q E}y)ׂ4rHh;9}woRoH_L1h&ys-:}& ʼnuT$dҦN q)i߿?*wXKJ.]E*{Q = I2҄D~<4yS}=H%qwho,䎑j7Rx1>R =i+ќS!%gm \'6LdFɋܾ[RbcߎBYL+qJ" "1)9m6$o6'>euK٭](șyV8) z옻92.%b}'ql~(Q>]|]^ROhUw.Q %"O~Lr\G $bXq dk8;9T5+.Ľgl=-ʣm$/VϪzǵ@EZ)+0=cT %qq=.JEt)3(Æ SQԩ#,wѥw2e$QN,jjkO*T 金:53Rf+K߫:e%kb)7fm|.֡SJ;(CIzԚxǘV˦98צҡn0ƹ4y ίm* BnjI#=*b[d0yp07DMF 5՚2.(m]>6qdm,{r)яw,!⏞ΔzWz2|-:&T+c|cNQOqo2)MaxJv`u]]Z;f#XĖ}b<+W"yQ~M?wN@hLI 9ۊʌ3pss{) R_PQz-j( T HXcf{ | ѷ_ ת ЅӤ++SʱbY փf}\)C {wb,\ ]¸j{Zղťr WT!no,\ʢET+Ob{GՍ^salz-(ZcSH_y}؛olz]p&# ԩS_OOO&=jCubE1!!A2ڨ-$zX"y{@T0x;>8S|WR#MgS!!Gʋ9t {^ƨZe[UbFXTdq4*AL:L.$(p)(H wH(@%?666y:T2dmcA:OQ;11{{xC^rfE~,ưOxrEŘj3^ ŘW,.j!@P0O{/KQ}=qD@ (="uCQK.>@ (z_@ Q u+9#DQ t(j(j@{tpb!@ xo) %6 z!\CHt2%)S˛/{U%\g)X!MFA[+*46um؅@$o<!Qu_ʐk``V*o׋k ɨڅ (`wiOq(cGb-NIn3v$P:T껔1 H6)Ȗ~o'Db#sg''q+'% Anڋ`)2?n%.js je065[5ͭ)Y8_ Wi PZyӴ mF{m1ȗ(IW8}>J-[wrD9lsKL\K{ u1ҕ+ (KQ)\\֍V+&'!/و~fQl#Ez}¦o0O G4@PP(655B0@Šh<{XclLԟhk*&r&L\1,!\k'?ʵYcqdu W1&/18X,J^5!3&y#S0z؞fZ4-R[E*VHJUߊSW0 -[!((Q& .5>i[ /L,>vR$ѫ$p)5n'^&|[b}nAA2-ٻoр)X(3nﯩ7{Aܺx&3~Vj9.;ugI2S\Ň`. -a6mWJDf|o(3vvl5qYxv3Y¿+?׶J,A9}SV P+:j5WE>?4ǜ6O;YQ <ȤI^ ׳gO aBJ|Ӳo͌S6sF73gYe߷vF8Შ+P`kYX }͛9OY(/Aq9) g6 IDAT߈ o 1@۵Wy[}R|)ݽ`Oٹ+T\t $H[YTzu7𿗈<1vrw-lx䷊aDZ7(}jS֬Z,aSX9( v֍)S0rHWt 2 ,}kA풅~dQ@;iZpLo0}7%СC̜9Se!n޼77!ì.40{ii-7ՋitJ9e)v.n[GrtsB1ďL -=4i]BbR #Cȋ[ \8Cg{w;vi_F0):9B)K=ǔT <%$1:T#sL;@(cǎUFfA,T$%%=/7( >0Mp҂BSwܡW^*iѢEDBOdݧ|w!s3 ngmWWѵ2]-d|ƍ3嚝tK%hj_ãȲ56S4)<הdE{ݾ?%DZf@rK+|bNFY C܌N0`:O@xy"Ω$Lh8EQIO޺tئL<"+-+N:M۶m?~[:4P *hd[r=ڰd堌c4nɰl8Wv><ѥj1s4ě?>ƴX66u0 7ΥɃl3dE*8~,;ӷ00 &WHtR<'$0["j4eϟzATMmԱ/ד( 6o\eEFFvڌ5ʕcJ*lKᾁ*"L/3{fIPg6_s?)ImK*rI qoO0)Vc)MaxO}Yg0mևyppD47ح4&՝zxϊ#hlꑒ;ns iZe$7Tv#۷Yի|Z ;Wr9ׯ_CX= ^;k,[bhtc!*LN3.V}|[v]) o6t?ϞL0**B9O,zl~+:pcaNlܿ+k_bZWmOkw]ZTNj@ '(w{c:p/^$u"ݻjժe̙Ê+4>bLQ(Q*AvÇpBkCNڣص[v MsPnr4PLOgDEM◂Z3&Ws~+og,.O BQG9S|'K[]ČkGcnE :a\Wj:رCBȑ#Æ YM籐^7YIBFA2H&(bq3Ru)}5 ԦXqR$E|}VckZq,*pjV3ٹAuies8_W2O k7O\D'j,V}a,* At^ KAm`MV(q埻xI=?Of<_;|8l2vqez3\2ڔr%f#@\s{ uA2~kHVH}%u̝yR7f)(׉Soi(sLNburt)↵dj:-ƁrQUd4iB5L~*ϢMJl,CV QLGFi ]Ǭ_}|bοog TY]fCG{T|FeT鳋cȴbll5֙F݇φU?ynZd£ jIN֞)7?ߜEWi¸k.UWF$aVR>㼒/KQӅQ*vd a|8Ξ*6PYeŨpo3O<6)ȴuy0.`}OI2clWv.-:0hзJ#Ō4ȀhUP]^sru@Kv%cS5B}* T@)&Q%1܁oCjΏEDZq~Sin(㓜LLL޾yÇ6N^vLk/g& 6Hơw"aRەW?OQ\ED ɏ.#D5jROBJYmqW4;zQR=,@ _^L3ΦK(*(qJzz@Pun ]3@ HG@ Q !@ ΁6@>%46|@ (HꭰS,0ѧRRQlQ(rJ7G^"m7@ ;Ƈ#KݧRFMK&W*wnzXB"R_%+eH~ۜZ@C[n+QQfڌCj3gQtAT]=AA~|YAM`8G4[  }*D1 Q@P>@ (A:BGYO3$< cG`rk7GI}9g|/3J.d́/I SZ5BCCE} ( >0.GG-kY:o*cmQ{ߏQ(rt+/3ֲkカ3/sp oI0; ^Q$."(ǜ6O6'>M'jԨAڵi֬!!!R08iY~iD9!@🢌Oәߜ~GXqkQձQg1g](WciWپ瘒@!-ObtFwF>L[ٱc[s&''ӽ{w _ \}EpNal~17VǢtTeks4X9vٍr*c(&Qˁ̨)}mFϣXˍ7$Y Xfw rEgE =h޶ݭ0Hy8 Q.l \\iUr 8{b!:Zv`x $ID%>&.ؚA[Vr8)u%%,>ĵMi0S=Hr 5" wvƷL4ǚnfUXZZ NrJ(m]I)SˎXš}ŒfY(~ao1ԛ u_R2m54]BǒI(mSt\3&D×X5Zz:'e7 eM5(&z7%9I .GE 2=Sjrh "!G.1ldžr^3e,mahUdQkM⇟a~3oVM]1[7‚l3*wL:(8~,;ӷ/1W.75$  <xNH` .Ul1DDDPD|R$RZɋ/RzYmjDqVWjaD F$Z _s*XwX>mI4eX|ҊOLnqBh +)ؽRtSagcY^OjCԲϰ54T!Pl;E),Z=Oe +#)+O"A$6VjK϶锻4Mr²=՜)ik5W}O9zbh̍HUnȫj+DMgƍk.sϞ=W@=rۖ a=Kj9v%Q Yz)<QbSZs#gKk^@13rk)&?iL8Œ}KZ i, %O8k+v}i"Swfvn:yq/FOTշ̡3ANf"%OTLxZieԐI(ya&OGIiNe Z hlAfAT#KSXR\,*B{39jLV*ż%h~kLc$X2̭^(O)$:ECQ5j/^Pe ̞=N:jO5-CeZ*MgbcAPvZJʤ-wnǙpa=怉2Kغ,]N{rVB1ߗEy:x2AqpQEo ˙ 1S)\_߆1iVsą(kO7ǫ˔k9#Ǫ~kHVR_sgsgnAr~ԍ5%8:qJX<uN^ ]C.]ܰ6V!Y|?[n-K)HՂNKA4[@.7Ed&TNL\x%+S2z4uA^GB*:R~*D}({2cъUpY.*K}u!I gêؼ7-Z2fQp$'kO_y}؛olz]pS5)SXݛӧO 3 J%&gTS؄#vC=3-3gCзZfCx-hugƘ }@Sթ8n&dxzi7 %+ۈR攪 Wct-Ce~_3}ΟcW̱g-3¡QKLGUUɍ.fAElG䠆2}3hgǴipuMKZ_QY'U,QMaFY``&HA 4}I?ټ'KȳچX,Mχ0g5 3TfܤISRRTiT!lCjtuuQeޑHZMpJFi)d/E.i@~Rە[D>⢃Ūti˦L3@ (- C>~~\Y.!@ 3Wl$yLQ @E@ ((sCgQ h!D1dWJ)0IYrq%z 㓟8 'Md_Ҥ€ %ie)j0JR"@PT>hU*Tң 7@ $$XR+!&%4Q*onJ9C(ݕN&YLP-#ub颂v:Et?v/J~+ 2;zq'j2_3 d^%CڤU2M }g]݁WW2-*{b~@ Q !@ #f L>gϞ /ٳquu?EA@}-O8`(lSg&u{3sWQqY\DK˻\AS֠UuJj>%Qv3 ]?+ neDe|rD=нUYL3( {{w LtY2Tb j7N~_IV(]f͚LGaܹlذA1|'I)ٟL ѧ|G!9{;1$Z"giz~UK87v0QU&1!hQ٣?vMY1fNJٴ;;SMͺ}+97=zHP}n^>1X cZƅ&1W+$[=SܨXd[UD'A؏s2Zґ6`u,ԷI\\E8;)Y*,X;ՇN?;a$SpOZ㋽)d#ID%>&.ؚA[Vr8)u%%,^$mjM9皒|O۷3g8֬HuWi~'x3˗/gy^}Yv-^^^Bڕ1<  g/~f?1^WF),#<,E ȳiq_? Ɲԗ&_!0B Reb:,,qTQKN%,1dbGD%fJB~ߐj7HȑK̨oD?[~eⱡWLr[ZzԚxg̛&SwLäVAs`!Jy ;m۶z9nݺ=ΫfRd_mUgO0r||c U^)/Vhܾ؎\XՅMhO+MpLyuu(gh_EG5s62r*Ms7*m#S/UTH眜W.ѥG)J[ΰ.w0Q!Ώ;z~ws L}y\i|nݺԩuVQ@~c!DBۅCҢ-[ܺ7\%SaKFi^KƲTEsf~oJ+(TBҭsXTEjt< M y@J2KI :[':k1zuSTo7ʥޫLN=z]yKж6Iޔ̱ mZLj oo ÇzEA!FIҭtt2i%5ҟezU-u͠i7e(m$(ЕdӔ%a( Xď~q2)7fٚ~JLSCq; #O\=TCφU?ynZd£ jINm>'?jRro)i^ܼ-RU~((`~29miadLna"SJ~䄛*EShc,˞GK::Rc "ǮN/99ӺK +rYCڦ87*=U7.Ο1$F7*n)s|JZqͱG.3¡QKLGUUɍ.fAElG䠆-5ksro)5ɓ*mllrMR )03zzo>(J4UڤvRW{{{ E`')9Y07,,CE&si= \gmvO~}e({G_x͛is^D$Z E"6nLƍiҤ9:b q/0"]*UJ[5Uƭ6d}o\ Y/@ӟ8+C_+'$ "(Gczϗ?8@[ck[uGem^v$Kd"!l񞸊5k~`ղL.ybw{IEQ ]` k-bu?փC7ѯEF]oeX`k_5>LkȯKq( U^uݱVf(O|.t=A;$+@ j4-$ɰWƆA.{, Ҡa5y3 _/FNʽ̄qs}҄*R6,4-)g A)Cߣ;Û>eGPWQEYʐgP@ fq6sB@Yh43D۶dhcX&k1";qIS:{chkG2R~.Òtxl=vTRU7zZ%g3[&Q 2?Yf὾_Ѩ7c0êxy?z;%3krKlՕrS |dFzHM]rQ$c:#O_3u(zL4ndvA6B _SڀtOۉvۓg3'cӭ |x8윾7#Gu\ Ͼ xuV?#<,wrVwMWJ>Pj&Zm oOXd(_<ı8OZ7ΤkZ8{qr6/dfߟo<7ޙIBR DAQA% UQ+ J ZHq (X@\Ԅ*!ɔp3{g*<{WgQߟ0kZod,*kC}ԛx8NC&4?B̅8-??{[88&{7"h6Hyf@>5ON$ 9-[]{' ErK۠(7_ 3g 1!"cĀ.PlYaJ'Xg xUĦ(Dq_>!R1"qM^^w!#6q=_PQmziSTuD#K;"EhV(Ĭƨg9%B_E?S? QB`Y꣍[j}R00 z+!^@DVCtPǜ #4D1BeZݨKUQ}*L.F-}D8723Ge|'ĔK%՝/`f1DpNKDXnQ piD%__ 6k*J6D{%uc}j'>Ҝj^DVgbeChT_*Bf$ހHVfȬT袤RNWY?﨡^tZ#EN-ҋl}(\>q&ڧ>,(0ZX4U^?]N:(j`f,-N2Z)oDc ꣏֤>iF@s%?I>gu FMQSaʸ`2ꪯPljJ#C}BT5Ҋ+#QS}j}+>E5}2ؔ9JuNjt>P!Ff8b -w B!N0iZDdI̬FpPP}OhQ̈́rObGU!xĪOJ D٫5 u@:>Zh8GYCZD)gT֝#vPq`JÚ~e>ԇ衧B\R\:ES-VzF5RA}tiEfH_1)mQRmF>t>>>: OIZ#}%bS3zi CeQ}>}eV$ZC/caDAu#/0V+C.4CB!~hB"!+ۀV6hB"!⇷"}Y=<yvR غ~Q璎;zF\7'μmXy8 xԨWw i /LC.˜y G?ƒc|ɧӪx|PAt8h[?DUpѥ]0ѸA|4xzZ%V,YL q|+?n;(x?QV=t3DBǭC7l^-~:bɃs^WNսnFOeLS/cfS&#E UV7 C-S ]n do'ߦcf(w!n|1M_1cZ1<E@JG@,64AC0m_Ӟ*JDѣISNÚ.fUWiQপՐ:5<29SPhGƥX3F٨˱pityd2w6mO , T.1HLaYuqq|l.B&K mt VS\q8 >mO.;<{A=3ٔKѪ#Yk9R!)IO1.$MC2;[Ǘ^']eL75ǭ" Nj7[vr6KG2 +LՑzF2.>;t ndVpI{Z׷Vn*ѝT &ƉZyi]L*);xl^$2\_g{TcTa  gplش=L_?OnB5 l:cs{ !ډ^[,yEBPbUSu|8pl?7`f?t 3?wx|"|[z#q]k&&I:eȬؼ}|']+CRYa)X[9<捄F>06˼"]3&Be\7Š pKNGFcH;_1ݻSPPOBBBX٢PTTyjt`QsP}uESF8tB!DSB!PFB"!'bS$nRu SBS4BjCK1#:Dl63\@|h@}|P}8BcD`*ttpD#z:P#Z:PGPhuc׊En)*C5>'c rMvr,5׈P-8BF0lUT\(+Nr35^pFP}OhQD$BPLUOTFB"!⇦H!)B!~]ha`՗>Hh3E IDAT!rbqq+W_c$`53I<Ġ?P#}>'|vb [p P*vk?iv-GBK fl?OqC}>Qfiv(N Mܘ|I2("D+$گTl\j>ZDr0{9';< ͘m-.!>)gTRVF_omkD}O(B1!~}w"|a !W#J}K#5E!AP#ZQG1?R*sD4G7INߋHOlǀ ED[ބهȇGOa|d+#M*EEF8RdI-XnPSA}A\6fF@th+F|QbDFh@VD$](km0u:OM:^ !!D(NTqPݜuJp  !dB'ʖH!FV%_w+rGDF ~݂Kb֓Q1h5Y-#y۟ ==(#P fU r_O`j4]=ܻ`v ;OL;ߚG` 7/UoĠyCpXu [&r&cIVP+WG$ (-܈~30}B+$_fE*2^_Zr᫒Z,kX6OƗ_&1duVw).-hW/crZX g>WxTiHƀWӼAR#VtR s[^nɷbݜEX:> wvL^\|WNCTչ}=Vhumv'Ror~8AF1;=Hnv4h ]iW9CH%" r8߅%a]w08B݌`̋jµ<@ I5=;Ա)8~W=#w /V`XY8P-ZYz Ti坅N.I)κvɨo mrhӖQ3+"[\N4K͸O  #p\X0ga {_t'zùdmMۏ8I2N;^ڜ(fHYEb5MQO_am0! 78 s\yZ#Q.֮ގZB]9ɗZoT mM/c/jj'mѬ _eSGk1׹-^yp)N}UaCJzЃkW⫢鄤?$̎[,y.YDx?-Փ(<G<ڦ%0uJ41'1Q| `ZܹE)Xwxyk _<t߆a=Zؒk3:v5g~nt>4}UpI.Di_q1VJ6HCeS_fwpe E꩖ ^–a9z Ksc;P`r+@Zġbo3E4zy65ݫt(_=?MݏŒחnO=ṛDN  #wF=Etk1ŷ̓Xz6+~mg5~Dt& p!dee!6()5hےQq(%)IJ26bUh;1v隀't X3|iR)7+?^[3L[†eprht]V]ҷ0۷o޽{QTTf͚YZ>7wT~x)1=1}s: +FLU!%f#wl>;^gcQQ;yf tJZxHI1h&qTze'?[>'- QF?LӸqcG ޯOrK!qo~ J١Bn b. WR^"HBʅ!o҅jFB !|MF_8R@f\G*㏤iA6r Ӂҁ>ҡFu2Mf2$ttx<D#z:P#Z:PGP:I)flpp::ݼ+B@|h@}|P}BЫu3 ݫɓH(گ)h)5ֈPPcbDTkVwCrMA\8תiTP\.˦xDECA5>GpF`QݸҨ-jvDҰURrhhw88NfE{EÅC}>eQҥ 6 Pd `v{XcL1/6ۮcv_m`))!z"| #K%#C4Q@w"Oeo؛: !d(Ba”iD?jM-z ? #Da]24EB1!J*{ k|hфE5"e*5D !ļԑ[_tClQ:\QDt)L !HQ>nSlrD 4EB19q#)Ɍf~v !"rynoyA!)B!~hB8B4AoZ&8IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/shift1.png000066400000000000000000001210001423020056600304600ustar00rootroot00000000000000PNG  IHDR@s6% pHYs+ IDATxw|u?̖l6M@ @HBD,X.;vy==yߩzH NH萐Fz#m31ɖIIG;~>|>B0)v1Bhhknn !4L`"80OBH!$S)B!āyB @OUx$qMt9BH]>t0ڧ[i!LXKԅ`!481*JaT'QFUNPp!I잺n}Sl`gH` B a05ߋ]~`%R0~ @9sooOxW(m잂*lxNpa.'=T5̚蠍6hcMm '4ϔoW5Tаbkyf#Y2TR{XXv )b!4l8r-A2lv"GGj \$P@E +?aj5wcNJr???#!dWr~)TA! D!q`"80OBH!$S)B!āyBE!q`"8B)B!ā}OBH>E!q`!āyr!#LpU%:3\aӛ~rL[rdLp}SNU(Jpu i/;sTΕ.נ  ѴVWU˺xax8氅O,2A-yzXѕux$aCahI#4 Wtbg))]u-'ԁqMynj_aR6㷤0cÞb@j7)?a% :)4$yۡϰ}АE)FOOLK9uW/LYuS-5Xd'٥sV;_l/󹊃ם1'aυE@yа NYvekic<ʊYɑr)<*\vJuzxh.'/$2&ao}&\Rա2+yDrWˮvVd} 2=>CH%Ś<~]oo5W4y~D~QݴZav .: /$)o_ N`[ډCIHbN+plm;|dN<G>Uj{YS^P%MLPWyVƥi6nq`"4m}y]q)*"DZXPP,.\SF蹇^ڤqpH> WִrYR/YĿUWMc8~kth^AmJ`MA, Y&jmkc]ՕViJ (1SNo!~172:;>$柲!"6:[?{U7=-CёZK&9u7HkyNI#KFҋ2E5.S!« MW@*rJJjοGcўGL v)BCQ[B;xL3vP72ŋDz.e8FϹkDɋVf9v\FϺk$_ @:<'=W?9ȩV)/cϙN.["Ӷ׏h.s$+YXQ2=*ꔠknP%%%BhR!$S)B!āyBBh0GY+0i8qSn(ak?I5(ւ;wɛCdx-W47V +}81wg\5o=\ÙG55&P4Ù*ip䈚٘EMگﴛi.?P1OB;?͜&%:i#5;|Qm+N9bB4))qrݕ윫}½&SN?2'LK@*9 hHW/Չ]PS}f;=!hiqra\Cu!@;Y7/T uմ@Z\Km\_XK7%a!Ug;efx' OrARr#\&V@9;~?[\U־3Zhy[-v๧pӇىvҦḟPIg[ ӵΧg>E+< k8xB"{]TbOBvw^ HO'Ι}Smg8#՝=]#]ܢj:<++hQa~S}b+O~A H3K߬Y[~~?Ldb1b93)gƑ||({A D))B.e{stI3b<ÅN}(L!P)U2WwNvKQ9>BhpmUEԗE9`t lɽ:yɁ}i);;diLE(=s/r;W^/vW̧$)Bh.g~i7Y5nGsd_̽u1iS{SnR9y4L9|RSZ_ɵwrqu+i[// Z1SaK2dӯ5IyLLIejBO_8P ͅ0JQXeRYwj`b#J9H"u&bj :CN%g Be@: ϶Cx'r:U<1(;Bh0 PTH|p_.ܗ s"3gH~)H☛< b`k ;|ƌ *,[Lmyr fJˮ[R@}QWi~Аm:uR%WiPǛ8S f߽MMq f[S6>ÃXTuk C9)|#rtrMKk'gjv#yvҷ/hdfe$X ~n@T%iLVX9Vy4B3 gT4UߞT&@`D<8YO11|Vzl f,bkj REdoCĂ'rwV;VPT3S$(1&%NG@* o+{Q+d-PW[9uET~Q͌`_W7)i"HgG;(CN!q PvP2L?D&j9ŽAct(}W[dn[qO9[W//Vܝ(^YZ/ M 4 Pv2"%i5D 1} `(4U-:!LKuI1C;f!gcؘPIQ~am̈̍w&7;ZoˆaTII5Szid=c \لr=eDtlYq}KfPET餚0}VRSSyB"B}xk \[Ѿu?<|T:fڼ;\'0"Z.eБv٠\ @LL\B?D]t`Kэʻz]Z;9ǰ=%FhS)&uS,-%4%s 𐖝Ψ]<=0Д?0x=Uv3}Y6}/GNܥV5`/M/lk/w{:5 9_{m$SMٿw qydN(&*B#H)H{9Q \qK;W;T-2]};!چ@?[L"x~ ~忇. [Z!4,(i?wIS,D;̞ƳS]]tjUܾnݺu\m E;C4^c!4>ej*KjogV [{=SVϏ0NfL^ %pOu?H&˽R1͙S*b)W:!vcj#@@8~ @,z ^gg=$L{klp-jJrG/bTbϺ!^EWee5$-ƃ%Qz'&l3{9[ɨLtU9tlUۨ3S';)FS^? !DyB±NXZbhv;"Z~ה{2Qr1\e,6ADsuM|4@vœ_;N|?b&%/$M'ӵ>Po;kuYAd.o>s_R ]v?`JBQ 1qc#;Kқ>yk] )eC%֦6pw*\/7T?@7MCIfYv(9pjeh]!$6"w_O_+ԅLD8S 鵯}][cRuS{ 4c{Cy񷎵:}jہ=1Y3bȂ׋Rx@fNE<`2oS1Ё[X\j:RSSyB"~7B !$S)B!āyB}XښN5P> |gEesg̫ecgk*t!'7ZC>_`l[E΅yژ{VRoY .]-]Z8SvRŤ'9>D#Bmr[ūmg8QSСrSɻpMb+\KɅ܊fӔڰ.tڬ`-OTĩ#B'v_6~ŗ[6OMnzm*l_ZŦ-=]3u~ı.H켐J=Y8y)͙$)̼Tה{2?{~RY]+3U2@,FYP?M=.mYh>xZu#g[CSL3sAJ`éS]6 RBuDhimzܱ?o5c姠z"p}觽U-e nA:@WSVz9ӎ!Z 5׻q> "!PSSyB"/)B!āyB9uBp Һɓ$͸>P9: :YjSu닜_>G}G*P.nNU:`|x1byJ~^=w[&9^m(i%jucc2)rpp}XdW& tK?(oώSt^:g\z'y'֙ ` hwӇOv, \~*?mf-ݡoy,W8$| "o &+h?zY4h(=˷}ϿX6qFA:jڹ5^ P ﷒@)OtŁ;<79ɘ%1cIi cS^E<0+GGGDR^^m\UWWP]]/qsstĉ`p:t,o :Y%K tQL_~|'K#5)qr#}}bSw}̜( vznlvKcQpGz#7>x7hJR_ Iw@` 84r/=<{c}ԩeϑoo%5]G*ROI_P\uѐ|R]:BJϟ8q*BfSRRR&r(/vQ^ ]! 2id|rBymMl>|8̩ :~lԻe'Ry*6q+;r;gz>WtKGZH%@ӴO/7> 蝰qʇiU5~J>L\vBSf+ V}p׉ ȴjpȗorW{q\``NBeԚl0n|u `p<Sam+l۶m۶mƻQQQ/|yyyz뭷:;=dž 634ԥ$~}iI(whiI> .:}d'`/VVC!&'ܑ #U }~6Joݙ`gE5 a. .Fk9;GP6KBϟ:ښ6ϕta7-Br K:hx,>nc}}||)..Θn04Cr,N2Ȭ8򴰰p׮]ƻ---'O?~ܸ<::zKKP@QҨ)-Yi꣗SVю3t|v(Wptux/ zi҆)Va}R%1rk" dشV-9WX@5}Zt߱='~-ssvG-&• {lYa/i^C!SU*ٳg5Cyy`n(/X4h ,R`X4tiʕׯ痯_^|ʕ\0#0бg+k,-is v1Ie?9K^[yWKG}^OQTuu5q*ʮNa5y:5V&QN2X +nCqjqɎ7o-^[uY12qM:%-i썇r$FIVۻP dHMZ'MտQE+{۪ J6mx#p#ٿkUj<'):CT;lZA̟.?kٝ{bmJ.ޒs+>r򆆆Π.Qoz58 F{VЁr⛟ƻ|>''GxG\ӟ|zɇgE9t\ܷf-\of'>!S}WANa%tĽ+ܛOɪݖFdnYh/Nwʧv%ȟ`뫫*AZSW{B{]O)ɿkUj`elR}Z`̮S\w3NSouϦyS7I[]r"RN8P(8= fnχAr3Z5oOG< NT#`ɤA,o|MԌ xꩧ4X?_zׇ|j_!| qF${*26s5q~ 嚸ÿZg?)s^ﲛ#-}с|kg7+-/ܺeJwQ/;{wFk_ת'2|?69Iש3vNPTDŽ6p Ә|ܔ|d]OOO/<#""bKo.]ڧ[U&W .Vn1K?cc= s狟ŧU9p}I^q"j!"OG|;L}_J`goRJNY'=?MC܂Yw.f Q-]D<6|8{)H$2.)Ėb [#^\WyWUxih&"8B鞮_I{)80!T'C;pEtoP ?@>LeQMM~P/ͺ 9ŝ*at_w2f+ ` } H?`d˄[0إX|cGga9JQ@Bjx,*2yF>F&!K!REVaE2%^>#eW۪=G«4G*E ~c>:) TǾ?*)>HMaQV[jqU@<;>^̼^.a1A}S<~1mR#Uh 6Tmw K8,_Z/klSCg^̼^r\C7KI*XL!3mh"ۦ}~}\=k[`!qk0˞B5z SBgIJDZDz,˲ 0 f98q|aU?k899,p5)!doe-G^ɤ^|kN&991Y%gQaƻ,+ҕTaSsrRJzk(a(Կ"8a,^vj2 LRcal7cD@~~A{iDBG41qbU{NupppuuXz zYԷJtm_^vzQdohY7?a2n|1n,0oxoonuR*=<! ?B?5_L&xӞ]L:Eu0dѣYFDze9X'⟝2m#:r:썄*#vY7P?3!&eYe DZ 2 1:ѧy<4MGDDP_`§>HrR ->?!8w?t G[R EQCe# E{!P_qO/c~(8::^ՇªiLb`q_^祶VazTn+ת-OZCg81 #Jå{!JQt^mDX53ÈZk׋$ؕ'NT*ojZXaé|er0{ɿoĕ7~l`򴫫5ue2a[|ck!Q5sd*|1j\|Va>nmmmjj2v!oe1T`8\jR/a ׋g|ufuyd^/U?/E?$R)95X>Dl,uIX DTbOew"f ZSe-ʼ|r7\Ԝx7_SNg1Cv㉺Akk(+橝2i O!K -XCVFZVR8/ 磪ڧ)…CZ8Bz`r*!8=ZV\ODš}!>OG'GT_rd1eLSajˍ-@_8d`(G*1ScLc\.wppd'6d2YdddGG`dqhYkR?oׅ Uk㏟:ueXbOQWև̻ӂ 29_=iОk{OWdoYa5P#+88x*P h4֚FFVVVEE#e F;2ׯmg-MK77oFW*GÒD"Q*yMSNiڛn >22^z饗^{ogorv;;5Z6{t=PB(O~Nk^ |L7喛hO\8?nV!|7N<== 4OOޛdoٳgϞ=ogv֜쁹s̙\mž]5=֡ܧX>65:^wY*I@]LWsYzʬ$EG[[:pfzxKƖ =&5nnn7 cE0yd\{n~etjlllll쫯jIC??%m'v&?qi9+we-ULR֬YcrKR{꫗.]Z[rw],V\:]W\[2J=:J"S8ɏ)Ӕ޲!oK׽qɨ{.=K_ֆPm?Bhذ#uŊ>.wwe2?ЅJJJ9ExΤ_CMTn3/k ѵxg}թ S_>{6fӡRԼ}9(tջ?~'wSoP*o=3iŃÃXRZYƜ0.jW?|?\~Ǭ/'[aOm!؇UhK6~kRqwX~؅4»X?P( 7g`GBHYyEGGwOQ,9uSYo00r[_`Ȣkgr6pp */YQ\$6G(JLgΜ !!!ϟoVZ3Su:9Ǔ&YR|&vQh&h23"IYԟ#+f׊7KaMg:ozl6ϓ]lٲ>"pR>˰'}ġCVm>)>z-"?~GŜSBޓ 6'PaPz"SjfiFѦj+L-.cj;+?r2LSR'{TRiVGG[]x!3~k/ k.I~)/ >/kԒj-Ϗ[n5ہ lqCk;_;5tb \G[;Ej.@|L-qp0WU$TO>ֹW3!IRnwN@? 9mW>NsUPܱ71|v_N~b@-}I6v'KMA:UO6jr}A;vhupF>,woϦS#b]ic?$''ru0dhyq~C0Z^ddiNz O͛éϟ߹sgttbHO50G}}  }} &N)?oom7,2cֵ5n˜1ԩ)^!Kߕ?5Ku.O cmoina /㎚S0cj&=@d=Qx8bccccc,Y[tRHHȕ+WmC,(>iE/j7e&uGT-q8/WwZl.?} $L] ;}b%_n<NnOevwؠW'Hbi'CԩNWdJD"$G$I]$ٷo_E[ =mirꕺѴ' Z1ۤrCĀ,wfL o 3V_u[-Ԓ@Ki|* ^PxhDxDDHR F^mRg=VBNkj_R èo9st<22揤!DEnb\V"3zNmg`ja/-`,k5af^꛹vu0Ib"4zUQQ;/e y-*S^畑{rmۗ$zT ={P/[n￿{ᾑ]Ţ2E݌CO.OObdɇQ_,[tc :3655_TUDr#_ݎ{}hhƺi\n<|Y>[섃=v~ϹnN-F$l2@/u}ğظaddl2K______#`5zr8?kYb).N,VK}kw#84ȜX-Bdf>o ͞k6{u5w5Sb6cٰ".haϗLE}"Ӛ)JUHd*K)xVVVr6Pjjj oWC(U4U9j^! @EIO.^ 1E  V7cI/c);2jL6/NHzSQ}USGP@ @  h.̖0PA@З\r够HOoqo0фMhwiEf¹g|>ֳl:p oc&ug20&[3`Yr6kAy7*HpK]ٳÀ1ݝD3O!W=f\Y+!(xjyIwG-nގ%]L(ayL6,7鯣{#b;kBE1El4/QC*lk*9:R!Io(Ud#^;ҁ9ܼϘ#93ASbأ'YcXӬWSh޺ 5Cnܾ=-`D"G⽸ѳxåRV\a03p.Rᖝ'[5QrxLÕ/0uwlBC6! h=";6!?=t8_KHw},Tڬ2le:f/2ti`}WF c)(֩#SZ{}=r!F5(% {ZxW)7ܪgjii:ph#8;{xv5vmMH=Er @-.J rXܨtW K K3~eյ}cǥ.%YԾ+oSwz2I.G??9drSL-$)5=5I%᧊Nݲny ~3ٵA10'GS<+@r۷}ûO DN\o )ZWH_:jk#<[;le YY{^e99E◓ȿwjfRvoȯ%'}0}}q.3[b2t]ͼ2%&|Yd-H\یa7p1M58fkI}o\.&n +x'z|}]s3οzlB+{[[}v>.]N~r=\( ]|ޥz Æ 366^ݻwEtŖwem:9x٦\/cX./&#c\ـ똕] ^՜+*c ^)L:tgM"Ύy3vg{M< Жz윙C<5*d#> ^[LRPa60˓ns9T#F,]t֬YP%#^ə퉐f?KE"=mYW#&_ cuLZYtr<]j* Î=TC)LW1sE~1CWHmu3ÇO2šALϚ,H` 56Y!D]VoˢS7]5##ٟ5åBܣ(.ji٣HL͛?\= HOUvO7(ֆߏ3$+VCjAQfz^hX5sîu:9ܱR0>d[%!̋s3s h3}:J{,â^Y};Ux;·- 4̜4L<_l]9q-;T%S@&6U)֗5 < ,~ּy;/?_ٱ;9X[[[[7q_>86 ̠;:xgv hmy~r/u?|l`ӯhZv|ɲG:k0$"5 f88k!5U(111bWeS_@hch;)}޽{=DEcP...e _~-tq6QCNh8<=333s3L}۸`@ǟ?s&yǑԹsr8͛7#=4k#Mό_j3tONj (/-*2n1ڻYF~׊ҳ SP|c4᷌׮bq~/)3*S^畑{rmۗ$zT]FN2͛ R\]]m}p8l6b1L8Q7)՝%ԒA|>_u#dV~Lf-b |>_`@4*BbJQ7}dTß *yr0&/@ ԓP"j,Qxq6]w)?$IʧX@PLB G@ԍ :~@z@ S"DP( To|z|e,Xav?>ǣ,)< &ӄ6Pmdc\.bZ @rk)b"I Œzh:)S e-,K!LRٳZk8޳ggϞǤqiaɮb@n"*AzH){?t+ enL s14%':F:jtYff8Xn۫&tp،gjOaҡ>hwv̛;kɤCfY)@=upjŤ+Urj3[ kOrӼ/!c)gXE?YUOuV!4"K>dR*|zMYsꦰ &a`䶾6W,Jܿf.g ׈ 2g(.ji٣kbѢE'Oi:5j!O( ]S%8+. rjՎYH֒%O9esg7nq(OYuNˆ pM#Yg,<ֽAꂯ^?VR" Swq˽`Ӌ7z=!NX &9(wpu U/NKv0Ɓ,+6npR>˰'}ġCVm>)>z5ȏn1g(aygԴ?rd͉k6ovaȚ@+61v\<.&x651,Mc3]!99͕p!C+(ܡeJ6@g;;[T\r >>b \,mp )GOILsMȴm*d K00*:WmmA癠㿟6ְ*h>rѬf8K%Jߚ:` K1 40WqGM)e 1z S^(VnjaS3ݸLTVqҢ~+C]S~Zܡ V^6xNmۚ_>f1!Wu-m~xKU-Xu~SEzW*^S@&**j.]jҤы/5kV=~o|tX-["ϡrܪaqsw_rZHtQV1J5-065ƅM5Xtšh{oO- ]8qHtk׭'wWSW.]`3`~ ; n<nִA #;.?$3YPk Oٳ}֭[ZʘFDD V&JMgmo Vv@@߱%rݸsj&q> L;$4zUQQ;/%e"?u^Ip:oYnJN ׶}IҫW8L%̚5k޽ǎsrrZᘘ(jJ13pI t4ϝG+0mi[FkrLľEGwuٲz9pns[gȃv?c8>agf'ܽ+o{tsjgm!'Qe?9z#=|cҥA;֊6Ra]ARZOY~/x9x`KеCk L7p2`8Z9{'yܳ_/[#u([~!umlfڍqtbt5!0 Rc,eԥiZwӖR;3f厎r6qq0 1Pbfff*++5 K55*grهB.зlo`oQ~A! xVVV f$\dddld2 8c\}1J+>ET~)ΦEazsЯ'f~A3A'[hg: \a8HO=`s~J';"DT(*@/2jPZh B&=qU !!2jLBY˶4B jC1EG.AGrȨƧtT&)$XIE ʏP(>lqg/P'P%B Xp2t(JE B>/{#f2TLG-QG좺)d P(_haJ!'/f-mgZCQ.I|})@x<|LB G4ԍ Z_J舚9K.QP6"D@ #+V(,,iI##GGG9XE 6j'Q[Ll.|snY~xѣ#[LXk3/u2ޤIee!r<$[11Ȗ|~ޙ,z|T.]XbM5"ޑsmFj#Z xEi?V8t h 9K3׵.W]uӿ XbzESܸqcڵUunU|)-ɗ)K@+󞟋GO _xyW;Gwm [K E Á?)x%S0,TⴡM~ة37'Szj)A:MJnogg-v>Y9FAu/,g^yMɓ܎p7)J_]6{e9\g]eRXXح[I&ׯ_߿__ͮQrߗSǓ[RA@ `2?M𢮜|lS XNpӬuVLc<̹8sНs>6?͕'qJmvzM/$kiü̯ΙNѧ[?)Oݛˡξbn:.]gK&E>ikaXڛ ~>ҩk{1/| 01;&F ]1 *yQ7aOQ,9uSYo00r[_[CF;)6lTf̙m6 Æ &Om(c()iEjWN*WI q>va99X&i9]c=/mn%qN\C8{3[s`fNw&OM c/xO6.؜`Yzy'lt'Fg n_^#>[$KzFJV$;-9K\~Ԯ܂ˇgߺmޫ}:J{,â^Y};U^}l̝;2H T_TbJ!WL|O+Sk-cgE9zT7%Ԇ,{t`A^/\G[;Ej.k53ӼrȞ,z|`mZ2n(/<0:ymn Nt~yώvy97tP/m Z/~[>n; \:<䲁Knz9MdêH=ծ];9X ,2(k|Q<^4Ζwޛh ůUt,ONzx1iȉ_Jv,I V;Nk̎yƷǂA7L .iyoA8˫6]c@$׻ZNl,\|èct8Qg fĜ0=oy{Z]溜EO-/"LX7|#CT؈Ȅ MA˩QWhg\)9Xd )m^TB9TϴQZ&q8nmCꋅ~ZJ,fʔkY4i֬! 0 q&[o9tćLv$ !WPg)ܡeJ6@g;;[Qa0cucL&yҷJYb,}}lޔ5VlLc첹Z{x\LYqg6lj:5b׋/X.e>f:Crr+l+WCv6vFFǎSurEFhzڨa:t>G3[o9>ղK^_Ymi=~xaygmZxx;q̜=< $:֛<>t>LguÛ@K5&嬩l))~ۼgN[zi4hV3%ȒGw%oRw~ӥBz[[˫縣&2T۷o9L<"@oSEzW*^#\SODGZS~Zܡ V^66 c|1\mg$o ^ۂ ]M` 7ܹsYf^tiMӧ.]* F?!DioŐxy͕&K.Z6L >f^C}f"d ltO|?a9e$Y~‰cGs^n=ĭF}>귰c^~mM0SK-?d1MR+00&˗/h!K:4eZhTvv&l:L:hd`BY׭NL"?u^Ip:oYnJN ׶}IҫW8LEH}Jb;3AcY@`X)v"wof̩-j;1a!᷌׮bq~/IFm neM_)Pٞ?ijkkqgW_qa IDATpG"cG^56' >V%Qe?9zc 3_%eaPvf-Oؙu w=z[s7ݜY[&lgƍ_~i;wԔ8AzڨaY9fbE8G:?։uyۿb,fkRq,ڌiokgX*wgԱT_sTޫ-"]PSiZwӖڽ밍$K/5tQ]t% {cf>R%LǷm>#fۧ}=fE2̬W(Fd-А3sfK__w}%]ڤܼ!1iNxd^0';;Ӈw߳`G~DNo+iLRGLyY@(,Q T#1g4JLA3pH(r-̷O=>{_%206!!MJ>Zw 1r^K7ro鰰Y=MjYc)ɔ~nf3Ox"1(noZZa. nq^ě*t_:{S)DSNB!\.HPQQb-EM%7EknYNa8KC#p}[[JC jlJPd~ )B)++c2@(i=iۗ#jPq/))ӣQB IŚTLJS@(5 FQ0 55Z@4(>]@zH$ǠI-++ 2h@AYY|!j-TY&"I:222m#QdffhTI1Z[ IEjjjVlEXeۦRݐ%BTkSJ+@ QQV[_<)dǤM3׃RW1`?,% 0 CTdffjhh(D]!IL]]]JL*ʤ8Dumo K`?fMQ]dx?@ HOOP.XD](+++..p8TëZd*UR.2 Lzd2U`#YYP$z 5Kj2T|>???ڿH@(jgIPhTg*RR-}P1;dO.L&S2>%IR%PK*&:B@ (..=S:Z+hoCMf*xM5`)Lb㒓D)IM"4PAKR@0_HMǪ )%p.Je2O~T'Lj5Iԗ*.$IRAHL)D$I5j sjjt_Z"fxX 7(ٚBNW6N QV*DI@ uIOD(2TjX ?E)wusʢ)T2\QmT^^nIɼ}I1UKVi h+SME}5%k]T/xb?S7ZM] 4TRūV6֤(BUBX t) ~ "^?D !h SE\.1i JLԮG^oOqF E-~tjYOl,߇J;ZmdI4XV 5uTE~)a&* rߧK)40&IeQ㤢SR=\/eIC~)ªfI\S*NL:)˥K8T4ԸRI)I=y<2pM5>_SRS@5~Ukzx<Ŕ q3qIZMk Ikh)ĔK&L4U95ѥm%$lש('L&?IC/_P]F %Q]&LC)tST/hI/_ʌ,UQ2J2^ YfR }W"\Rp yRfĽ&WEH&=Uڼ:!%K^(߫Osi|o%5TK&F^n$:`ȂQ|@ S"s9t#m =E )@P }dQA02v9~-%5͛?=7?zt3 Hu#O2Q C)AKnYOܳm} ^G_R8BYjԱ+w_})4=;ࠁ02vk?xn is=kAy7*~byzh+D"1!r.ҥ稞:ω:iwd#]nc7OU|dչ|DCǧrjՎYHj YtkXSVz@q?׎o{y1.A1]nj(/Hwj*ROLpkj^a>Y`˪iik9B2 μDGZ [VVVe*`sԘA@/qv=_2eCY_Js8ZsΎic[4Qip=%3:..tω{Br)&3 F*ǬX?̕cD^2fg ti}:N5A+wdyp폍&۽aj \U+&$5CV22I JvAW18$TH{N)0VV (iaĔIUavm[ߡA3oض#>thIŭrCkBnU=cݗJI-|l܎~ ޱJ~si[_㪫5teDwc6ѢMB "֚iKnpmC3 eWfUax%D`퀙AsGVJ"n?`J;o>erZ6-t^(u:u#Dέ5S_WiϜ6*Nr˸$lU|Z(r7LA3pu$›O0qzK}fl8H1RL97)Y^XPRB=ϖ47 _skb0ޡk{J}?n9d׵!_3n2 ȲOoª= ,yeڢKzԟm1Mh1*әcݝl,ycIi>ߎ@̾iUgA~}oz)IE )@2jl^ Q)I^k/eQUEȤ8 ^K^k/eQUE$L*Hz! bI" Uu 4(YSK*ɔOI 55T5تTdmȳlqgm!Ը𚪺RBgUp2LH|>B^FU]C~)*VnfL&!IRiG0 0ꦐ%B`8 $I!{DU]C~)T%sYKۙ֐$){TO/T5Pa(%@ S"D@ :GQX*6OEUGU5bU)ǣ3̟&$0L{P7 \ Uu pZ)>b3o($M5ׂL89!Q\.p%btA'k/eUxB;*sPaaп0-ӭGx<)񤞒C@ }]Uu t~y- $ZL$ [Ư2yu% VD b{ !MU]C~)-5UEOp I HjG6ؿZ2R'YGu.2]L)AT` !yT52#*BRdTK1cp11}ƧSr$oJ^k/eF$ E!)R7X/F>J"#5oI#]KqB,,UZA!Gb8 BYPS$|$XIE89߀ O=Uhe 0-ca(!*cBٞHODR9tSS1)P$hl&-}I(LiHOD ES%S`lWA<~)?N:c+nRlj@{JDgME>X 4wi?p̑>(@TfTOӎj_IzH,zdY-0A?=SaC٧1CZug20&[3`#G _&sUԝTa D+qk&/k7xV+g+hMCЉSܼ猱?3O#pz۹}0M3>253BCPrT̗o[icⶹ5eI۱o\ CGѡ}6ɾ`(kW_ FmOn%Gޘ%=z55r,L~K Rz[*:8Nݜ>M Oⓡ鴾nU M?p qJD ue-G= ^WV}Fk޽=b {77ż[/ݧe>>S1*tˉ}Nk ǷX#36(,)G?Ԟ<9YL+jjfim,xO]q'n83rfgeVpMC3ݟl@;%\+9+:pdɗ>o/HJswvケ<$LK LI!ń0F3F2X4%G?j:dAFCAdT[0 !9ckBM6}Y~Lc9g/]s< 8xVtĢ;R\>}w$=yj]ɽKa}K?zVahvۜ'u%>yjK-e$8yۜעuAhW/_Z1w'9=DǑ#FKc"4MrMۍǫUDHXcߍK-v?s$2Ǥ'q߯.*c5#|y^%#+ŦШv`N&>kv9d|_5c;Uxג2ӥܞ#M0-}ǂhz/iUu fJL(]9{qv/++k{ۜ$7%Ųx?ȣN[|b][=DM۽󝒆[gfS#P^^^^^^[.tÈ/E8 LY Dxur= "X[͍b[:(qs`$cM)AҀb%Sxq8CAHGBD6_DHM$2{RS.;NEWnuoOsB7@[EHNFL8Ertdnց* TTi΄SQ>qB~.;R-E*Z/٩)RCթV73-뺼Qszw*tِAt!CXRhܑ!_/K ,) kiBBU {S4K04M|J#]".33Wgs fP{`  =[[[333y" !l{Q즰XV#(1fBpfPF;vIDAT8U/Vt ̀. A3+~+;y/_Gp7<*yE᭢lN FY $;Kb,5NF$@Cp) \@vb" [hV;A rL3km)Cp1Qj} %?%"ŀ+ lY"n/ t bIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/square_root.png000066400000000000000000000010261423020056600316320ustar00rootroot00000000000000PNG  IHDR;0IDATHKջQߥ(PHqūHxF=*D"*n)^J!HHO&㜙o=4笵k2Ggjxו_9tKJRo <&\!Kī)=a0rwA[_C/2 GqB类oۈ3fjOq=Lcm|"T݌#gpoMM1!}3E*_S*#lK/U+؍d ({]q[: 6mӵU{B UlMrGX^JK)sQ0 ,G,-}$0r4v+cçpgSW2(Qa88ʅ[8"SJ2?2Tgom%W6klX !}]=$O9'Tq5(.)Q.IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_CN/fig/standard_mode.png000066400000000000000000000532171423020056600321040ustar00rootroot00000000000000PNG  IHDRZ#D pHYs+ IDATxw\.R4Q5Jbbbbb)77䦘%{P`ADwvgyء,;O"royf!B8:: 1!$! BHq` $! BHq` $! i"jX7s"<4ޑ!*VBmj޶cɂH|_Xz P.9ުā Be2_W5Xk_XG4~5(ђ-۰ нkBW'^jrjhjnܛmv Btt`@ tpA{І_P2^/HB&U[up:_l祴\@Ɇ1q@e A}pA4傈q8. (1vف5?աu)?ߊzƁnCX?:Za;iBASGBHZ:;F6<5=hm8@U|?+#F FnD M/zb,j>k+:e_no9ޒ3)jzG0n48>I#Ji{f#R:B{q&F&;Z-4P7F& ZG7F޳@q ݗF+@]#uEm"U@7~vaR %]H? w@PpcIa$`nF 5/޳iґ׉zӖS8Ԏ ju_5YN=``i` (j)&`Ej7y?)K50 ֻ?Bho4jFAnB_[!lj ?) @$s@Xi oO q&QPwA~E5Ps ™9x>$T[{GhP>쁯Oԝ N?a&jT8w\gT;Z3@!!^ [pfA%?gPKzQBHnZR;E0s'2v5;m,xzP;q3w"2 ́w v4]2RLdq`2 =  `GtPˠ^[]TjxP[j-+.iK_wWb;*V^^lam0yEW$\͸Wm7&E9DIѫ"'?;6Du/6PŮHbw$H(ѹa#%w=S[: ~7C~r j\O8Qp.b[*!JvyfOxz1|b0FOGjTUMLF$i YЖ0[EBez휸)}vMTɾ#-``)zsM9#Τ,'w"("{U+?*8r7\ZԸP? ή[+>{~LѕSG73  bVdP|Qef0nczK@e50x1JzB+7;|9@.%dO2HWWJ?dkͥ N8qߧj*Y@~fjs8:hO{âI'DM&T[UgXLlUϢv q q0*.C'Xٳ/kΝN+ m^&=ck{:l̐0;8-b'wՏ_3EPL%30 Kv }K*2()&tJU CX71<" 8Bx 20-~ .C1'!@Eet9HD"O+_J [1c36T8h\$N6V* 7Ywn/,&!&O,sԾsGu5תJ?s*ϡ׈0&Sץh]G`Vm^ Tld&NwiHI%U-aCHaeZ<)FjGJ7TT7+:""V(IB%TeD].Up~'lCy% juc¨C$;TXP_n6jH7SgN1ڷdͶ/.Jk"~mBTLX1X;;9uq^zئYNrfۙUͯ-]|kjZb4 Ӫ]#T3u蘗^ctw% Vt9(C@ѵJh2O - $ptH%Op`բ'-+ݩ] Ę(`:~kLv aw/ VQ"hݤ*%Y??ȥ}!!\RS6XM+ʙYldWVB%]cnKT }aX,=i&eբ~\`кͱ&} 5ptΕ9Ǝp *~?OaxW/n鲣NgѪ}]hـ dbϚ;3ztHYAiﶜ6_l.Qdv[_atvw<=UC3fR,`7ކaDzՇ'h6'ԔF-^?>ѓA$?'L|I+װW1/ d,qP.$ wW`{&uo6qp7G󝢦5Ws8z.;/0#zJ^}Dž܈dT]=J항 mca̙ 7XLcQŒ$KˑHQz[Tցs $Gl̙ X@&PWOA58,^nF&:KkQ9@髞Tڳ̍rPS5j'𳺲c.15 GSr"x~"h)􋮋uBn,4MUyppu/!qWuteߺ]H:JA,3.N\S<-kFq&F8D! \%vdNEԄi9sXa!؃T1E XagaJ9ܻAC-8b &"-x6VHXKةӂ~ @qo~kӒ4ZyxC'DՎĒGO,ku5%q6bt"C˨&̡ꚉZU 2ĪkmvвJltә1A]s֛x"&d%` ҃:|ɭ?$Tdfq:*WE&z^LsO.F~6Lx0VU*"wQ9~"9%BGݤbeP\(f'1-g;M k1y.&v~/~.Q"싩STBʁ՛h&j5O"mROP 7һ(Rz;3Οq6JMޕAᎍJmafڙ}{ϟtd3Sht UWv.xQ=tփ1κhuErHgH=-Q+DIo?AvZEPYҺTUN~Ա=ÜrWŊ*huJA!ܲn-d6e ;BU7ၡ`;ǮA9Tھb$K6aǺԤgd?2?'u*8z*2 N.l]cy<ަ= <\_aN<"ە4[PA^(7oSMĢKGj)@Aꁝ57Âã>pDr_섄0-<0Ⱦ!*ة9zJէqqjK@kNeM%Tk?{3g!2@X;\cm*#U15[}O1e*ОGZ]u81е;~_r W:pP6ٿL˅ ڱm?WaBJ'2*2^c׻7)- ih\3j`6hDCdզ:IJDUeڼ?*b|`+? Sw;~CXMZfkHWql҃ێ=>X jH`|) Xḿ;elwq?e<_ȅԭ40qR¬#N=uDsi\ѓM=NG(P"XY2MK4 R$MΩkdX0%_,PMD7NWDž;bIvV Bk[ [0' _\fOY&%܊;^mMuR2Ⱥߨ+Ԫ8VVVVV|^Mƞ囮eS`{EʾWաؽhjf~qII~f2DcAyAu*;?q"L`pRZǭWF73f<>nxu10w(ݼV]-r xt|tEN e_umKqR0h`eggc pG#B>!$8@I0B!$8@I0B!$8@I0B!$8@I0Bu0ZW);e*lkt"cU^=nk_i+X^Uu8΂P-9u*1?iwhe7O<|Zoԣo^x-H;y<ʍۥj7}FNJ,;|tuN=w5s ٯ/֮K(b}{Ot5x 5mAډI)w-}Bt$j8GnF o# UBs4]pL 6ulL:B8RB61?N}mсd:CD)%䱳7ڟwj͛Ztਾ?Wζ Of]|׵  g6,_$C;Ȫ'uEN==ғNZt,Tܪ.Zz-eWwܘ%3Zy5dzzi۲'K\{ S{i۲nU="eO؄jWxv !G`Յ7ZrDenZKBYF5nO*'1};LG8:P;)ܛS OVR?C/"Е~z 13%Cu^xHAВԽnX.6 ίsۗ/;1w6r`ߞnj 'EMa@v͝6zԮi̓k֜v`[sľK|##l@ ۿ79WF#ǎ@t_wM1*H:k⍪06x%=W{BUfW8sD QQd8P J&3ž.T$*;nqMPOm= v!݃ rx{s7a}j*ǚEY,}ˑ ÉXTTF&j qU[q=]8Zyh$mÂm@䔃:uۿҵy:Pu%'6OwSxUsϬ@)hs*PWLHm6@Y jfcJdޡv(+-ߢ'n1NWbeyHlɆ;Wm& u00?`4`LB+~ltΦm;~c=$xZN#h<ƇX>*嵷1_Yҁ6[?K.c2c KxkW7{ѡ E)۷LZ.Tx8VQ+[jcU81gӡƁR0v4B K8TiZDei fgejTޮ,;W5M+-A%CҪT>qSrߐ"׮9^1!qxdqՎU@"sЦgfV] ."}i}<䏦 l̰ѓ5$^6'RBq 8$~q=9Pgp#pb;kn'mvN5>жَ≳EC!Veg R)*YЊ#u:!M0 -jB"lXHwf@|BcT /Q`lA@,gͦ~CGG:4\~ 'G[mɋl*ݛٕitLK6ZnIwicƁ+ŽpnLJN>j5O"mROP Ʒ[%XxvzYrVXQ_J/cK[b~ZrJ}̴8ok2v׉1ܡBp̾۵ODžDpkeNa~0ZG$wsUJ߭I$2HPYс4,29ItG3Ѕ¬r'cd: .+o$==ӳ}hy_X{rtݍ&$>xō3g5w9Vh4MpTwե WN&WvpVQdz?)}M2>,P}ubmyp"BHq` $! BHq` $! BHq` $!  fQ8 ˗u<Ӫv3n^+wܾֆϯ >kւ4r+>+s ZӋCr7zc5-9(7a02y%蝓^j@}{s8_1x{qay$ |og[{w cuuVN}YC$` $36oS#g=>_0Kyf5i!!=f| miqo5i.2ScUX^͙h/l?[[BXGoh_Q{0D' Bai%Bʦ*j} u"yiq\Q!Xx9F'U^s q_dBmA;ƍės[?篹󗞝6:QX~}rA ec{;q f]]VY:/#Z ebm[ T)\^If3ȹ~vPY(79[Jd*jI=sstssScu/oE{zz3#ԉUr +?lw+3׽4P5olTHV#>\H^{zar16^A5P\\l\oMBmgK$ѨG^/jķ~>Ç~3fo+#A  ԉB!$8@I0B!$8@I0B::$Q!$8@I0B!$8@I0BJ$,0 !p&PJEQһ^ʼ<}2/:CZDZ,{5˲ <7sOW(@ʼ< dƂJ2I,R5y:YW(@ʼ< 6Ÿ88ad10 ȼBPAgq%#emɼBPAgyFāiT+yyȨ kT+yyȨX0?T3U%Mi45a% x: xW 3P#bκ&kK}g\JǁlvI_%,ƐoH+F0rsoiXT=መ蘸~CL?oWhJӨhIy|h>Mך:5{U$(~vyfb`s[r-:0?vxṿd}sQZPeWny7]7_|Rb=_>܏#nL$:[Xg>^?*ڲF-ӦHu2ȡ_viq;kH n9n0kݒN!OzM~Oxw;-XɳYh7Ѷo}UbO3FqZVxcBqÇ3}mV'paNtۢ]i'݋l;QY{k)&fnY8xOH +ClBܼv_5ߣ־Q XcZZ'u?>Ծyvӻb߶-bέ|F Bg>qQ2,Uhvf.utwU˶Ž&:[T0 ?G+нA'(%nCGhn;TB۷^ ot 4NNzzbF*h4E~:sY>}*{nBLLLLLJ+j?_阹i -+x[lָOˎ]^v[!(•mۮ&ZZ# }䗗Y-Ъܥ+VXbu,ߑ{:EmueN-zccòϞǝ\ɳ:A;C ig&G'Ƿ-ou=ٷrLk:ߔ-Yj{Dh{NY!fl=u:ƌ1u i??2ΐWɦc؈Yo/\]n,}}WQuvľvgٺN1=2нwI?x6Zt/+=zї Wo*4Ot~gl ks={cqLn_jw`3>mGI!WL1Tbjow!.tƿݒrcv hЄ3wN ;ՌcвxwR*nP ڎ@'7}O5Ĕ#m.^ۮW[Za{G~a߯-zנOF:w;ֲ gVzb+ف-Lo޳Ř]|=]młVqzǣLr ][D:378락OzesJMǽw!4v|Ѳd\#:+_uk.;7}p)2xIzzgKja1+lTWmhȼBPAgBqкS5F%ɼB x*Ɉ8EdfHd^VGFdDhRd^VGFdƂտԌ+yy e^t gT"2h"32P+yy*l{ZOȼBPAg)9*yA|9JW(@ʼ< ʃ) dGy2/d_˃P>< !$8@I0B!$iu;x'J2vZVZȖiMp'K޳,+]w)e lY * ^XU;SZVZȖ 2.8c3n` ֲECZ~W8Ȓ: eֲE #_5ֲ5x1A#,T7֯[̌Q `|1I*0 c[<3FPa $! BHq` $! BHq` $! BHs%"dz<}tc* F9q:… ,X`ԣکvn­RᮦX01{?z'g;eʼn&$튉vN>=w\SbbCBWS93}߇]-kgf=;,XCw։~ׂܵDO+@͟b6Yp<dBL,~l"%8~+Zv5yvb_t35beh6$%%͟?ԅW>x{E.x)޹fCfMZU{s*=mIn=ǃ-a6[q .|g+L>=66VmRRҊ+>/ՑէGz,0WR`20 "}js3}|JJJOLL_}դ$^}ӧwx93!QjS7WҼjNw=.N;ߟӾ{o3+ʡo%-\pܹ;o޼W_}u֬Y/7o^H 550VBNVzZ3,z%Dw۸7K|Ϝ?ql};1kco7GM]i5kW_}5k,sikLNNs?K{h\?-$tv=5Ӱ`\]ɯ%봣9s|III/׿xHsJ^ϷF#dݼm6;ܛ ]6nٵ헇+/NxAys@l}|ng`Z...Wn`޼y>nA7`XҚ/S0~Q{}ΊqKKa=) !W`y$q̙?7}Ŋy+V@TGNq#ٴYRމWF7}"`ܽ;%^v;bccCCC.\?All,e49Y!|0wuO>0ßVl{׮7@-;/g3܉pϖVglٔd0g8gΜ+W^~ԅإ|xl=Wm*Q%e!ktl,9k'ѓt ﶪ&w̌ozWG8N|A{p_'Lff(b IOOl]-,,ڻZn~&|/ϾQM8ht ΖBȄ0B!$8@I0B!$8@I0B!$1"(_iֲ5x1A#@ELTZJ-fƨA0S7֯[̌Q `Ư GjYi"[nqS<ϛJE7|f~A-7= ZTVֲElPkN ,2 C:E((p4/(e}<2qHg/(F0$!$8@I0B{!J%/(FZDZ,ۊʊgYV^RZJٲ>7T*j,R5wh~A-d\p0f80 ()e lɇq%u,o1*e lFāj: *ek3cTFāYoPi-+_4ncb:#ITa7LUIyf8@I0B!$8@I0B!$8@I0Bv킊]'B n0j,8~ 8߁5gRn…5UŽqt3.>7:wPv>hʓsǸY9Ă3ys%)0jk|. >z'.e\ 2Ezd=m2eâ=q)?ϯ(˳ʮka鿢L][;'~湥#|!Ou>|??Ե1k|6D$dKY nW? @}VjhNn|z iOU6[>W$fmauiF_;S'|jYfM%<d>wbHټ^m,jNYCl Ij/Oj%vfDÅ{2̳c]"twB+,Y-tqH{`.9W"-Mcɞ zSVR vv8uqӯ}΢Q"6 @V 6.U7vf|6;0_.׳1Kޝ7}݋֦=;|j uU-/M[^ ,4g\qk!}´}6γ (ߔ7c}IeyWkK0j s3iЂ]6r9o(Ђ=ļ-޲oƟ^X浙O~TҚ+nʟe?|g]' 0pCxj`+lBùr#H@4 М?{D/b^O=ECW<ߝ{ce{Ǽt+=|mo-~oqh.#,׽ǗDOO&iiwH@\LC,iWs|*ЈPo{Nؽ2?<_?aۗnu4 JZXyݢ^^|GS}8n#}njlA~QeǪguƒYg߸9}XEU˖a_~0>ҴB{hrS&f80밷898 jB 쇇COv*Ĉ8BfGpVLBU0B!$8@I0B!$8@I0B!$1"(5jPi-+_4"DwՍC,`YVQi-+_Pd0"UoPi-+_4"r@U~JkYiՠq әI`J:3hDBHq` $! BHq` $! BHq` $! BH3)wZ4geEiax{S>?}7l{<˷II-ղ/>j29-;uB uɏ=k |zѢ qЖBۙ3hىeGykigbqQ:|/-;ۿ]y_u4\~ң|NC]\;S ˈR 1gے-,!%7g| &ّjʫ3?Ztg@EEnTZ|lT=> fi%Ţ6}߭)pO{慙}=δ 1 -ןQ"Z{vE[f'ppߗna=ޭ0K'DK('vvq 렡=98oBllMu#Ӆ-ShP3:/?-\ `&}F_3U@llm `2D' K6tlԛ<{tjszG絳4Ueު.pwb 3FvI_cG4vNp809HX[1eX!zp}s{&u頪sȖM2Gdkkϔ=Dn^1ugӻcu6EbMteu+]zMz'2nYD^/?.j+ψ9_?X3 ΅{zz3۔SJkYi"[nJvvٮB8@I0B!$8@I0B!$8@I0B!$1"(57֯[̌Q h'oPi-+_4"s~JkYiՠq f `p$/(f7YDQyֲE,hZ3KSAZm3wPZJٲA9u* ,0 !RQ[8RZJٲVIRj8SZJr#xBHq` $! BH= QZJr#X_oW޳,+]w/)e lY * ^XUTAi-+_Pd1N70 qJJkYi"[n!-nbdI˲[JkYi"[nq`Ư~JkYiՠq`TZJ-fƨX0H$tSU1-nG#B0B!$8@I0B!$8@I0B3t ]b"q` $`9ӣ]p$Ԣlѧ}o<~1l#c쵷mXKgn}Afˋ_|fqIalͿ{/K)D(7yŁgo/;/.1nCxw-Ƈ:ͭz~T3>mjN5iJݱʓf~N@^C4=,n }8я[sوNDQ@ `<єeΡ. D!^ ԕ+m//*{-\^|̸Cfqt4N5|ז|ʏ3=S Sin.h{mZq #͵~ Nfxv}+n]?G^YYbJ49w}gI~x/9@9q/<6 f4wz^7.0()f<Ĝ=행}>||*/jEQс9{>~Ϳ-?_rVUTQPJ ARڇOv, d,,h"eݖcP\3DK7f8I:3u?a=6,\3jɻ|l7S0L]LΨBα?k 飻ko^,=zkO{wq;66 '(I F.- i J"j>TJiBM4KZP,"(`,46.vػ3;6gln67d!c1Vg$ihh(..NWc`&p-myGMdb!:\, tB BH:@)X!!` uRB BH:@)u w>H h[d&ajԁ [b@"ۖ7O P8$ml[ޤ?1V@łj7PA? @t~hHo03GB #m AH (yJٽ[/dB|V4;@ B¥y-p5$p* t0fYp%:#KLKNa ƔN.\, {GX&/8Mez>4鮀q _2 X!!` uRB BH ]t|,]i1޺vbnO:u pW}? =M߭-k׾~#q#Լ+Vr/o3N>?/%sתVYBig֩kV!=g7<5]m=~.IrӶ܊a5g%b'ٳ=2螚fM#^ytËe'urHivoyJF(6lO9 SsӒezMZ8tg͘bT TL!:-]_ݳ/C{ssH<(9y݉`iYҏ/+&|MN7995R5Ӈ-W+I${Dwv5*4s.9fd73_?5Du@bnAq$D"ѠFlok$7/w %ͬ:P\Z_ `a,y5U/7BVaϣOJ!\B4/! ՗h8Nrv>uAS5N&N`>&Kќ"?ok}HK 0@]p+^p%L߲y׎}ogX,8xh+_^X:Ԭ"-]xFq(o<9#F0Bem^7IE訯z՚?wey~ggȯlmk~ڤ"ۓן8DF"aLp~A:3&1 aK<aaɨM"9y1F)ո|H)I'llI^@ D)=Jy3x_ÐlP(QԿ H֤ p ؊DRg8Erw(Hۊc{ Z5sx? SNrG@vUeOrz$^Tgq X !ͶKVs **模式**,您可以: - 選擇 **標準**,切換到標準模式界面,執行基本的加減乘除運算。 - 選擇 **科學**,切換到科學模式界面,執行函數、指數、方根等高級運算。 - 選擇 **程序員**,切換到程序員模式界面,執行二進制、八進制、十進制、十六進制等複雜運算。 ### 標準模式 ![0|standard](fig/standard mode.png) | 圖標 | 名稱 | 說明 | | -------------------------- | :------- | ------------------------------------------------------------ | | 0~9 | 數字鍵 | 基本阿拉伯數字。 | |MC | 清除鍵 | 清除所有內存。 | | MR | 存儲鍵 |重新調用內存。 | | M+ | 存儲鍵| 內存增加;將當前數值累加到存儲器中,中斷數字輸入。 | | M- |存儲鍵 | 內存減少;從存儲器內容中減去當前顯示值,中斷數字輸入。 | | MS | 存儲鍵 | 內存存儲;將輸入框中的數值添加到內存列表中。 | | ![icon](../common/M.png) | 存儲鍵 | 單擊![icon](../common/M.png)展開內存列表,再次單擊摺疊內存列表;關閉應用後內存清零。 | | C/AC | 清除 | 分別表示清除當前的表達式內容,清空所有歷史表達式。 | | % | 百分號 | 用來輸入百分號。 | | ![delete](../common/delete.svg) | 刪除 | 單擊一次向前刪除1個字符。 | | +-×÷ | 加减乘除 | 基本數學運算符,用來進行加法、減法、乘法、除法運算。 | | . | 小數點 | 用來輸入小數點。 | | () | 括號 | 用來輸入括號,單擊一次,同時顯示左右括號。如果從鍵盤輸入,輸入左括號則出現左括號,
輸入右括號則出現右括號,若只出現一側括號,則表達式計算錯誤。 | | = | 等於 | 用來得出計算結果。 | ### 科學模式 ![0|scientific](fig/scientific_mode.png) | 圖標 | 名稱 | 說明 | | -------------------------- | :------- | ------------------------------------------------------------ | | F-E | 科學計數 | 單擊 **F-E** 開啟科學計數,再次單擊關閉科學計數。 | | ![icon](fig/MH.png) | 存儲鍵 | 展示內存列表及歷史記錄。 | | ![icon](fig/deg.png)/![icon](fig/grad.png)/![icon](fig/rad.png) | 度量轉換 | 分別計算角度、梯度、弧度。 | | sin、cos、tan、cot | 三角函數 | 分別計算數值的正弦、餘弦、正切、餘切。 | | sin-1、cos-1、tan-1、cot-1 | 反三角函數 | 單擊 **2nd** 切換到第二功能界面,分別計算sin、cos、tan、cot的反三角函數。 | | |x|、Rand | F函數 | 分別計算數值的絕對值和隨機顯示一個31位的小數。 | | 2nd | 第二功能鍵 | 單擊 **2nd** 切換到第二功能界面,再次單擊返回到三角函數與次方運算界面。 | | x2、x3 、xy | 冪函數 | 分別計算數值的平方、立方、y次方。 | | 10x、2x、ex | 指數函數 | 分別計算10的x次方、2的x次方和e的x次方。其中2x和ex為第二功能界面按鈕。 | | ![icon](fig/square_root.png)、![icon](fig/cube_root.png)、![icon](fig/y_root.png) | 冪函數 | 單擊 **2nd** 切換到第二功能界面,分別計算數值的平方根、立方根、x的y次方根。 | | log、In、logyx | 對數函數 | 分別以10為底的對數值、以e為底的對數值、以y為底x的對數。其中logyx 為第二功能界面按鈕。 | | π | 圓周率 | 約等於3.14159......,可精確到小數點後31位。 | | e | 自然常數 | 約等於2.71828......,可精確到小數點後31位。 | | Mod | 求余函數 | 顯示x/y的模數或餘數。 | | 1/x | 反比例函數 | 計算顯示數值的倒數。 | |x! | 階乘 | 計算顯示數字的階乘。 | |exp | 指數 | 允許輸入用科學計數法表示的數字。 | ### 程序員模式 ![0|scientific](fig/programmer.png) | 圖標 | 名稱 | 說明 | | -------------------------- | :------- | ------------------------------------------------------------ | | HEX、DEC、OCT、BIN | 進制 | 分別為十六進制、十進制、八進制、二進制;其中十進制為默認進制。 | | ![icon](../common/back.svg) | 全鍵盤 | 單擊返回至全鍵盤界面。 | | ![icon](../common/bit.svg) | 位切換鍵盤 | 展示0~63位bit位,支持點擊每一位bit位。 | | QWORD/DWORD/WORD/BYTE | 數據類型 | 單擊按鈕選擇模式;分別為四字(64位)、雙字(32位)、字(16位)、字節(8位)。 | | ![icon](../common/arithmetic.svg)/![icon](../common/logical.svg)/![icon](../common/circular.svg)/![icon](../common/rotate.svg) | 移位切換 | 分別為算術移位、邏輯移位、循環移位、帶進位循環移位。 | | AND、OR、NOT、NAND、NOR、XOR | 邏輯運算符 | 分別為與、或、非、與非、或非、異或。 | | A~F | 字母| 僅在16進制下被啟動。 | | <<、>> | 移位操作符 | 分別為左移位、右移位。 | ## 功能介紹 ### 千/萬分位顯示 計算器支持千分位和萬分位數字顯示。當表達式為千分位時,您可以右鍵單擊當前表達式區域,選擇 **切換為萬分位**;當表達式為萬分位時,右鍵單擊當前表達式區域,選擇 **切換為千分位**。 ### 數學符號容錯 計數機支持鍵盤操作,除了常規的數字和運算符支持之外,還支持數學符號容錯功能,讓您在鍵盤輸入表達式時,鍵盤的中英文狀態和大小寫狀態,都不會影響輸入表達式。 - 乘法符號容錯處理:輸入 * (星號)或x (字母x)都會觸發乘法符號啟動; - 除法符號容錯處理:輸入 / 字符觸發除法符號啟動; - 加法符號容錯處理:輸入 +(加號)會觸發加法符號啟動; - 減法符號容錯處理:輸入 - (減號)或_(下劃線)都會觸發減法符號啟動; - 百分號符號容錯處理:輸入 % 字符觸發百分號啟動; - 小數點符號容錯處理:輸入 . (英文小數點)或。(中文句號)都會觸發小數點符號啟動; - 括號符號容錯處理:輸入左圓括號或右圓括號都會觸發括號符號啟動; - 等於號符號容錯處理:輸入 = (等於號)或按 **Enter** 鍵都會觸發等於號符號啟動; - 清除符號容錯處理:按 **Esc** 鍵觸發清除符號啟動; - 刪除符號容錯處理:按 **Backspace** 鍵觸發刪除符號啟動; - 字母符號容錯處理:無論鍵盤上處於大寫或小寫狀態,按下 **A~F** 鍵都會觸發字母啟動。 ### 表達式 - 在當前輸入表達式區域單擊 =(等號)或按下鍵盤上的 **Enter** 鍵執行計算,當前輸入框中顯示計算結果數字,表達式進入歷史表達式區域。 - 重新編輯:單擊單條歷史表達式,可重新編輯表達式,表達式顯示在輸入表達式區域 ,重新編輯後按下鍵盤上的 **Enter** 鍵或 **=** (等號),可修改歷史表達式及聯動表達式的數字結果。 - 表達式錯誤:如輸入的表達式錯誤,無法計算,則顯示表達式錯誤。 ### 科學計數法 在標準模式和科學模式下,計算結果分別大於16位和32位時用科學計數法顯示,即計算結果取前 16 位/ 32 位乘以 10 的正負n次方。 - 當計算結果為整數且大於 16 位/ 32 位時,顯示數字+小數點後 15 位/ 31 位 + E + 數字。 - 當計算結果為小數且大於 16 位/ 32 位時,顯示數字+小數點後 15 位/ 31 位 + E - 數字。 ![0|scientific_notation](fig/scientific_notation.png) ### 數字聯動 - 當一個計算表達式顯示數字結果後,可以繼續輸入操作符號,此時,新表達式的第一個數就是上一個表達式的計算結果。 例如:當前表達式是 10 + 20 = 30, 顯示計算結果 30 後,鍵入 + 號,再輸入數字9,會新建一個新的表達式為 30 + 9,按 **Enter** 鍵,得出新表達式的計算結果為39。 - 兩個表達式產生聯動後,修改上一個表達式的數字和操作符,如果其計算結果改變,則會影響與其聯動的新表達式的結果。 例如:兩個表達式 10 + 20 = 30 和 30 + 9 = 39 產生聯動,如果將第一個表達式的操作符 + 號修改為 x 號,算式為 10 x 20 = 200 , 則第二個表達式自動轉變為 200 + 9 = 209;根據此規則,最多可支持9條表達式聯動。 - 重新編輯含有聯動數字的表達式時,修改聯動數字或聯動數字的表達式錯誤時,聯動解除,同時會取消數字高亮顯示。 >![icon](../common/notes.svg)說明:僅在標準模式下支持數字聯動。 ## 主菜單 在主菜單中,您可以切換運算模式、切換窗口主題、查看幫助手冊,了解計數機的更多訊息。 ### 主題 窗口主題包含淺色主題、深色主題和系統主題。 1. 在計數機界面,單擊![icon_menu](../common/icon_menu.svg)。 2. 選擇 **主題**,選擇一個主題顏色。 ### 幫助 查看幫助手冊,進一步了解和使用計數機。 1. 在計數機界面,單擊 ![icon_menu](../common/icon_menu.svg)。 2. 選擇 **幫助**。 3. 查看計數機的幫助手冊。 ### 關於 1. 在計數機界面,單擊 ![icon_menu](../common/icon_menu.svg)。 2. 選擇 **關於**。 3. 查看計數機的版本和介紹。 ### 退出 1. 在計數機界面,單擊 ![icon_menu](../common/icon_menu.svg)。 2. 選擇 **退出**。 deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/000077500000000000000000000000001423020056600265645ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/MH.png000066400000000000000000000014361423020056600276020ustar00rootroot00000000000000PNG  IHDR#=*IDATXMLQP(Pz!AL"&PЭzлHFz0F@8VQ8h.XhK UhBC%[gX[&̛ߛ7 ) 0)RFJB>P|?du Lըm\lnn@@Զb ߸z ]8+,-  +++^,`;{:%((n,k%x#7Cj^K ƏC^0E͂C۲ H[7|3&0ZI4;;h4&I(%5x6*/E4:=^<>07[p_ћr L__:::R"4;j&L[{W0pOEI\J@C_J6]Ɇx<( !c0l&,˦; dIVe\.l63W9 ŠVa3 PVJ{o;{IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/cube_root.png000066400000000000000000000010541423020056600312530ustar00rootroot00000000000000PNG  IHDR;0IDATHKˍQϫDQHQ$LLuFL2*L;-Ld K$Vs;S=u&{={}{&k\V~>kGR'b3)`0!iyb*!F5wOc00gyo{9vC] ̇qDzYpp\*2~۱ m=q4]6^aXq8%dac]q)7M> 5Ǔ^b^dk~ULnrIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/deg.png000066400000000000000000000013211423020056600300260ustar00rootroot00000000000000PNG  IHDR"":G IDATXG]g̦yoIH Řbx+RBr& 9 aj!o#& 52yY_{/~{}uwNFvC'Jt8F..y_Ջ6yKC #tG͹8ϸO )oaq&W<'9w(s`o$`>`hj XfmY#a;N&!8 ,.0e /qJa!$sORa1šr $8%lSH6akBq37̅0WRDv"4sr Nɸ9VF#tpGCfegz:+3+D[[R뚝2?V#FIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/grad.png000066400000000000000000000010571423020056600302120ustar00rootroot00000000000000PNG  IHDR"":G IDATXGͫQn@20V2a6  3J)T(F@H&LBUι=ٳ{3$klH8@NIEnζ"qׇd1`>~x qp {q G[p7'kEbx8P=ę<{+cF}/3 d󲲀Ezm%c?8L:#`mq{pK2q$Z;öTfUӢ8>)ȧ p5eK>ci$: i ,AzTlFM>hm(P$]bncGW)H9X#ӫ};7s0#fLo0MMoMUc.H'7U!mzm 45~T^['~Hӑ""X#62IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/programmer.png000066400000000000000000000602231423020056600314500ustar00rootroot00000000000000PNG  IHDR@s6% pHYs+ IDATxw|%چNhh[dɔ-eoT~ 8d "C@AenRZJJrw?BKhӒµK?/ɕ>'sATDnf(ÇYkF O<@Si O<@Si O|$Pt:M #d0Ƞ'2@'(6q7LUYxٶȉӤls]O֞#A|hD*"%b0.0C;fbh 6P{ 8?8!CDDLGCD =3/KXY:߯RM"_b|NКnC"j?Kǧ*9~hg'ƨ4d0n!>!_(D u @E`x(y< A"TT08:,g;HOܽ34X)󔞆HtU":9d0<=JueIK8g4K#==IēSU+@'f0-xq3+Owxv*HdYo\o\O<B5 ?\E>3AgI}@$B S>gp<NAA_pKd9=aM 7"զ̳7Yh?=_'<>Lo N}aZ944HO'2@:ÓQj@*/_>L^4O3Ij?ѧI{0t<+ʍT”,ts0^$KĒ͹܉1:ڳ)e"9H)؋Z ÇDS&CƿD,錩s(=*wKyI31{ܺ65ƧrG9ӧr”:Luƨ$ZQOwz(tǨɡٵ*O\|iLLK6@F,=40>Ƨ@Si` O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O<@Si O!U)>j{-ڽ#N >mPA5@D$&ݭSDmUӗcGDDK1mo<7v=V}ܘi @(<ܴOplƈ#V=oOoۖJ%D<է܋t∈YgH;"by:8rϕ;lHB>Z?>""rwBb*7ireֵ]1œ2OYQoQ#"n;dS}_cӭG6jߢpگh1ez)1ퟟV^l1jԱ.-p!•PE?2dڹ|g)tpߞe.g"Q@JDm>^к:(ӈ[^iVkf([||<7@Si O<@Si Oai.8y|m,Z`yqU>?^B(yHy )4$;6ZnbS_OyYb$UnKXqp]D"s_n챇T0!]X9aC`&sj:Mxt7t/CDDXƍHdNSmn▞ekv\$l @ɒt+z+bA=0e<=O7p]CU;VL!&֫&x%2ӟ|}?MdbHq%5IXw+=ydLۮFDD[l*3$:cD 6Ϣ퉲Xp@Ѩ?"aX ?WDopG"T`0w2WU^>,Ddj#!_Bs ᾊ 1TV@S>Z" 5(K H?%˞(v^T_!a JDDDhng?i& @^8 )4,S7, jPP.KG@!p< @2Si O<@Si O<@^Ť>eo6kev\5rM8ok͖ d{d;uV (T益76OIw}ؤ -[~0|¡>^Uݲ#o>5Î pw?)=ۥgP%/Wvb݈F ժÏt+{=ゃ07KDv!W">C&xÎP8ibLLz,ۢYm]ot?֙Zt I 9= 4QPlqv+KIi\W'd(8iqv`$Y|D]])i$?@ӪG7 Y.AkcO' OYBAbIt&ݍwILkY/o1ϻдIU'-IԔ+w9ұI%B՞ZÙ@i%,!""BOm!g;54e[_]`5?NcE=RL3P֫n?/=[`ų^s "R¿ի:y=M`7*4уOk!-j{C>c[=z6Hq=VeCg*QKƃǴ㳇7*Vkf([||<7@Si O<@Si O<@Si O<@Si8eY͟DQyQN˺P겮eyR8+wY8yPƨP.(R]ymVK1qZ.d%+KYJm]!OU**u+˲*8!ԥ,.[q BM A]TUKTU.9C]Rz*yU.9C]Rz*pK  X%B]ʂE>y )4@Hy 6"33իDzo\_ TO裏>vC s֭/:;;w!zӧOT]JIIrʃxwppQ|V^TRɷӚӵzz/"LjڬL"6iE+}nj֭[oݺUsx=7kܰq|Ù0 e4l>ewj%}CHHm_mդa]9 hT^z4 mj_ADD⣝o6W^z7h╾c>\y02D3gΟi{FFȑ#ۤRy2GZZѣGz}ݺu6l),ݻ ٕl0>\nUPpӧlV2ȭwҀOmp/Nښq_7{K{"o?؁=ޥ3 /nПf[ۙ#qEwzxo~.zɊ1?y}|Ō|[g:VD{h˚81bQ5Ja>غukxx8eddtã\rVmT988pm򬬬/_޽{GA J0 sss|rڵHki*GNj""W;Z_hB# KغԺukYi|Z|F_8*i\1|7+N0^Yk0"! {uZ9_8wݥN-~ӬegTް?f[UY""F^? OMChs.WGEXN敧 ۭd1L<?lyƍڵk6>..-7qDQdFqgZX0͚5V#;-@!eϕHRHY )K*ϕBRYZlC2QIck~xzƣA㠤'mP}l"]>/Sqmu[19)ۺWˇ' .eYgy(3X"rT՚i& =(FGGnjA8NF3_Y5;:CAeGiDDc_;)Ga2]Ydǎ;v2$$w%y]~=ݻw޽$&$l.bcM6ZuBJxpM|z6{ҫD{3 MGǢҚ~D~&pDT=1xPFƃK>>>D㔔z vwwoذ?WTzM.K.kh !m7됓NЩXpP^޺uk޽_r̙'O>^znY!t`aT!8n?oFMeʴhU]KUlް,C|!ӟ_]:Jg[^KSwO57nܘ={#GZ-[… wUn_p!;;.::%O{yyEFF޹s'***88VZv%Y5NHYV٩['!&~D!eغ4eʔ)S.Ƙb8$GD˚oȈ4׊~. V:¢ϥ\95jQ7eKUnj?KDө;Q<5;;1O{'z^6=nu=|*U,^xTѣ>ܣG]v9:*p}V0̽{bbb]*U*Utڵk׮+W89 k? )#IMSBiJS=BhJ*֛׵h*qܸq~6mn޼qƍv횑aHChdff1˲UVh4!S+y>Ȥ rR+BD\T,n8"j۶*WqAue:u랞]xbKbih cUVO1jժաCh}>*%\`k<-[M1 :ąk4̉36Q2ˢ5MM{ɵq}'0ZQqʭs'A. O~T>Xg4ٞHnVTs{7,dw@I0Fj6m>lΝ;۷OY+4syzzj4ƍŋ(geeݹsGR(y κ]/s5RYd8"o5zvDae4.Uu<_g?nzO]{O<:n Nw ɍ79111888OFEEvH5O6ͣꬋY Xegg~YM:|^8_uRRYr}Ac;*{WfJ( Ҍq}dMkV(^BHy )4,SQ4wq _3ԥ,X` TJ)KP bi|!jSU.9C]Rz*HJ u)K E8e0;z`0} uRRXYE;ic%w!.YA]Rjʯ 9cYVVWOEA,.C]dHu"X1R.eA]buz~i O<@E>e\%(=9aaXUT,kg0zVKC]օ_T)1ѯR4M۫T* F&=8-y-l4eua0`0deeZVl8Z]6Z꒕4Ou:Otf| whdtvE3QOb!'GViT83+VKC]UںY(JVa.9+U],Kǧ/Y_r Va.9+U]fl$uQE /ڰPAo΋i zPqjHr<@/r=i9r]3fرc=y O@Ν;_VZײeˊIy`_\RSSד'OZ!6bٲe;w.Rfƌ;\f}',6ck?yL2y?] #n5t ׻V;wҥK}Rig<ģΦ?:q7 +6nXg:Dn>ÝQ 9"vs$$طd]kx~qgAL>m;L3{ޟpg7>X{4:, IWFLLz=atAIaJD˖- jnHa=O{z:멽M߃G2-UЍ.張j5G\Zd}ElrEEE ڿOd7j[)ۑOk^݇}}ҾU9g\뵭?p2k=ʝ㓙#}egJ]xwE#*gGDΝ  N?S^pۗTw`ڴiCOPq'yi 2RߥwSѳJH{{r%''[E/CL8z>o1u_ O/-^߻>݆}sƥ?2| wk:O[}of_3z:ekhݮ_Y5vӔ^x9 de̜C/s-[lyQ`6m^ӦM3 5j԰J#󔿻߭6Am[^gTX@4x#&E]v0قkńedd$&&rq\TTbc>}l~ܽe.5ƽMo|m̜ 9%KB̙31T]ǪϹ?̝;wNu)SjzΜ9D4mڴiӦќ9sthio_ٻ?jV> GFPQ$b\CGwuSisw@.-i4//؂.h-gb&/.٨"O4u%qkY~J#GDĹW{uW/:~~vsʢ_~GOK8_:Z={ .\0{l+)sf싋uh߾}Wu17mcFW=|tkwoq=!22AV{xx8k7֓>q}\R3 owg krag=p3=2peG .&˄OƷpyfǟmѴ7#f)+)` 6h4{5^1cFݺu֭;cƌ}VQCL;.t¢{=c Lcʶ7ĥk+%ƶp 4twxǏEQ?L TصX*G}q~߼a←ޡ,!"uZ'}mD̩7l ߿gnsͿ쿒تs:z:-޳ۏvx}ں˿gqޞ,}'=cΘ1M6ߊSSg|ҥZŜ e}fSƳÄ7M~J6yXRoχ7߇m<"##_=g"##\]]ضcrFDܱM _,q ?-qm۰ AUeYnooUfM+51NMq7n|A$2}5XJm}vKn3U~A֕\=̰o0fay)n>]5ͿYCŌ;vĉ=z0]j~VΝk=DDDj*k70^ Si OaQ*쬞F [:OEQ֫-d [- uYfY,k Way6_TuE, JSѕ+< "c [- uYfY:>UzTSQb<_$&KC]UںYN5rg,j4d0;`(Z꒡+BD+qRvƔ^W'Ͻtd4w<FR?mDQ;a1dXm0gYVDQ ]1"7 ;+(VKC]cå)u( O<@E>e\ecbGm4e]-Ou:"* T*Uq&8{$q<[Zji+|?++Ka`*dZq{VKC]RbNSc:S¯`.*]ƖlT3XQU#PlhEy05__f#UjiKJUW45FW9)UjiKJUW4%v]TB6,T$["9bDZT)8 O<Sov;y 0vޠtqM!"䒒~m۶m۶_~ٱcǁ^Zzɟzо .fZ%R1Dl٢͑ʻi9BFtnޤYŘɒqvNCeeS*DݫX)D{Iq'^s75!M^4W}O70*gźҼ|F D\вeKXLbх]`HEU x-ILO }m|{fW%"E;.UPkD>fǓ>ޙ\ԹK/N* fL@bPuKׯ_rCk 7ygPPPPPPժU[ljvICm徔j:Rp>MyYNe79(ZospdHDK~l8rdc'kF`i~AҤFJ5tǗp6whX~Q==8KlſO{5nN Ŕmݭs;NgX)/Gx:1D\y?(e]X׀]m셓;q6vM'W;U{t3PX,d!h6y+6gK -"ò, @BԶEfu0)D?'dWpy62iDr1yؐzs?*-<ƋXͳ]Z҃l"Deo͟Z?0dM2iD~Qryʸ?Jk1V1%:ɰUUc7rzt|_8O?|z>r^^^D$Bjj۷7obڣ4quUpsuuGi"O֡u ӳnuiig *weھջA-.oۿiMÞss5Z}Y» KM={"Lwo{-y`7{Ґ'/?kBiZVSZǏ_v풀( M\,alZd =;kA?RmؘIooqu{|/.M12DS?%OK0O[?}}_ޕ3fl쐆y6_ԿE+N=R ^0wwwaӭ .ΌQ 0CH{NN%08pN>ޮt}Ò'c&Ȭ-镛6_Oݼn=2h}Cnf^YUPɽhUo7vQK("V8lc~m!O]6?h5sh-;"7s8H)~#G gMIw;ߦoLoT~!W^2XRR*(FEEi4ʕ+[]`\C1g^I\_tGpi_6*Zb 0Dz6kU\V]~T[;XpN&k|DIJoHHm"R0Nz0-AM?wL&(snhǢ9kX3ޘ1S+G>R'=̢׉_E2Z22~H<3n;;;kDZϼ*kK Y4y!>SZ%&~G/a"*ɺJR wE"7PSb9fJ#>>P~#۹\i[8KcDŽzCC$hJ(m]aj!)S5fYnTm_o;az_eBr-(IV)%b[l<0Ey0QVSUHT@Z꒳RͲ(Om.0.W:UjiKJUW4ˢTla*xnJf [- uYfY:>UzTSQb<_$&KC]UںYN5rg,j4 4 ʝ`0xB[- uP!"8JUTy/hJ+y99P殘GQѨT*㧍(=r0 0 DZ,+ ( `VKC]V_Ǜ̝MEGb.űҌK@n@Hy "2Ʋo#Z.t:NYo~J *㸒iK2Hx䵰Pա+W~VV"4UUjR^fSǩϹ;d4w<,SN3t:٧,! C_WVKC]2T:-٨Hgʓ3zG*Ǚe.*m],Taj FfPhӗk,BsSfPh~3K6"_mXIVɷDrfViJO]=8Rm5O$d Cq9@Hy )(AYGP<A%)~PP:]MCOu73)Z^%Ҳb;wbbbxh4*Tv^uCV1sS5uv.Ɏ!̏<_dNPeϑc5(B+Vn=_#LzٽB_Z^A uI\0EI)O3% W2n{aj""ѵyRLѳbVn(Z3zw}~}i.QP222N8ZL ZfƫN]uyyǚiZBߢFg=qsjHSF:<{lۆIXnK^0f† ѧMŴ4{{{%vs_7w[LbDӿhdu,\-{xOt$t&HvHaJ%"1^'=dl(HV,݅6_dl`ODD_֍U)7Osp:弟];g^4s1鏓naƴ Xk;ORfߢo뙜Fb"DT*> '&iW[ >o+eڐ =R..ֺy>:=jl+L9%gڻYԿX䛁:;'OЀw2ݱ*>OM@Ml𔵔Bsr/a+ȼ_m=vNdsή8~Jrr't:]rʖ-R>|XJ_LvvvG4""õ%|fZ?Pա+Wf!sgE3ڭ(ZR.HDy )4@H[ml[lu% ]1NSrc_R=wJ8d=8-y-l4eua0`0deeZVl89P殘y}N3;e IDATdjiKJgW4%d QU#PlhEy05__f#UjiKJUW45FW9)UjiKJUW4%v]TB6,T$["9bDZT)8 O<@Si(~rtȑ܅*ٹ|vvvmsWe}<&Fik?s#KMӏ.QFمQv~{rDbsm2凅}}1*>3\퀊93Rmy/,mo [ō];wNobL"+mA1m;j-?5όi"èm}`v2D|ڵ۷o+WMȻR|*:1]@i0o G"_:jv6Jv4dJ)cqVs^)&G+ϨM6R٥Z}~C-߀3d_?o'> \9<==sLNN>yɓ'۵kh4]\Ǯwv[ >|H V˦fl f~%K&5t?9Wv r X=o 79޾INlm;2Zmy U2Åu _7JF<<<ׯoݺeHCL;_7 Hs$ )w[K!aL0-Eck]]xZ}7jݺU)k:17{m0. z| VC||-\ A|trqgLln$ԔT).g!Abڹc;Դ#"Q?9~vrƏ88nl̓bکDŽ:m-fQnbs!r|]}<-zp/AO5>GcY?UL=OhL1rG)/;~iISU1z˽gJWWPf’F>5Z4eHòH.֡:КHk8q%fu#{5kWמȩaPEo'OްDyEAST*(Jzw9.q{3~բE͞AM1S,Ef uZj Mc 'MZqE{>'9梟}0JWB_{ɼODQ=a~""[hlaun|p7+Eз|^pPƽ4yΝN}k~t@y rtzQ6zgٌn Quz~eaPi{{~]'?~5?n5sycLnm`0w2NOh4?~yow\?{@% +VkA9O޿=!]`͕1UM3 bzx133Kd+#Y*nG&C2s(s{jq7hNƭGzcqaTv! z|v&> *Uv[^W߬-t&{wuϙc󩮀yBAtYIYqPKJ X~7smyЪ;80Z222J5-rz5o!BVVܤq.-[Zd?87SZ__:3ڦjio}NW]LԒ=j P?{˚Ns~ծlbV%!iy+a4 èjڵkWXQGlӲG[;On_=9CsUG6bjt삉CSƧ P̕_||?dy )4Ұ(O )ۨdTDT@Z꒳RͲ(O|SPTuE, JX &.l [- uYfY:>UzTSQb<_$&KC]UںYN5rg,j4O GA(նZ꒡+BD+qR @+y^_6Z꒕(Z>j4JeEQGaƸ’a`y8eeAEA,ji+x͝ b.űҌK@n@Hy "2Ʋo#Z.t:NYo~J *q'Kc8yK^ [- uYb~Egee)"L0 YYYlV28N~ m4%++ait:E1>e* Z꒡llFE:U̞Al[=R8([- uVifYJSU(e62[TuE,\cd!ʝ2[TuEYlEI*dhBMJ%3;/JKUz*Aőroy ![@SPzZ{ ")TP/))ȑ#yu6xb3]K0 ;oۉEUú FsGtqv>3.%Ct(Xyc/kP5OqoTA+ˇH05?=ĵE[eHl=|MUq6g!S{M_[R[]e=˸*ZϦjl,P)q?y@Jʿ^}Ӿz!AA!u[o߼lWlj7/_J[}-\L@XF-^3`;G0N۵ S"bj I I ?Z4L@r?$䭸T96;+y OFm5e43f8#eGSel}ȫ}lPC⣯ٽl꒥b?rƏ88nl!^"v{gEsh l$,EAd5Aް Dp>O>}oPB! D a@ &$Uu4YjLw׭'ꅜuwϹKUhC [kR>ߙyR6 RPP`;d2y0D5/S̗uc&~-~o= "M^Ʒv]PqR z%M8zKկ7Us*LHW>9baqmT F\322222laaaڵ`׳~Es;+] ҿԉ1?}rVa 9Ђsah]N (F=F<+n!K>~e+NI]{ie$OҘ)ۛGL/^f:1S8~aJi%sv̌K[ lPk- h]GAf@?ET>fAR-IŮ JC]ZV5ES} Yfr@^.-S]T a@e$y$Ů JC]ZV5EOYTA*秔RO$I,]JC]5E-F#U?qF]آ([Ȳ,/WiKΦX',ˋ,U//{׫*jJdZ~^.MQbG(PJ5;sG!(jjQ%Iy8/fʲѫ4q)V|ڙi(zЫ4:( @?EOAjSA(e5uQPgyIp㜟Z,&W_j$lSGG:qЇ=zyz,7,YT}7y硉k<%̟qʷS&n3#e^J'6w]F:D;c{//z7S ğMLޚ-!/ MѓǼdpe5Khhh lUc9Y&Ȱ &;pu/ں4) Zz{:4%\\PLKY7FszȢN5oc[ܹ'/`PXIPV+5'YvB 3 u```XXXϬMsz4HY{v_CG'UuOn#]rM݈%4qu^Mܲ*uၘ"q=q! 3fSVϦ|Bx?緬;lhV>٤yXۓ7?u+fenb&YfSgny[WϞ׹گuS~&b**"4qsg|zo-NC4̓3Ծnuy[Cyʔk\h5#{% %qcg 3<`fsG|9_&׍iG.g9s6Y2cȁ)NY< WpsS3[y2^ٻe_nA b)(( `2x?yޡ,pѽVRa"Q^c Zy,,[ÑޥKw@օG^[z),'/gJV k,}k322222lm۶`<`yxAѽ;rLu}p4z4fTZVJ i0 {**.a P;z?yWm/K¿joC A 7nVX}. <7n.}|6> F$DEE}}ٙ۠{ 4ٵcU^xgڑ9:KЇHB$lFL&-rQB`c[P p0*\4O> _vMWOkա}.dA|{i팶AUe>*t1W;jNGj6 "N@7|/_ K>촸Z֘8k>< #abKUh=zr4~t ~V_dx?Mupʔcg  kجcfc%pI|ˏvWA !rןPk!yrҵK|H2&*A-;pG7>1amj~06мeeŸ.o-};"cQ/ڋH<+?;3?]AA5~{%i;k(8cUYR'>-,, [CCHu+0{ʧMݥ᳞ 7)slj:=]&6GOZ.^5g~j/~JUn"6vUU2T{N}Tw=BeDRUWiK8R&m?S*= VV!IzZ]z#"dvK\BWNm~ʺ P9?ގ%IrTR,"P7^&#p3%Thd8e DQdԒeYEGU U"8ZKW %L^^^,f xyUuMbj Ij=z4#]J8`^'W$3R(xp\ɵk#eRIIB!DPVBx8N(,;Wi˳EZH"E"X%9tp{LW$@Coں&ף<^1PoJꘜ*jgVQ;3^.0 H2q$P}{@F ab?^xجywl:  qp(S7b>R`f= ,Fc KUV 'H(p= 2B IDATx\W}2mgf{KժKc% )K͛7y K!@ ImٖJ[[߹3+ɖ Bjf9׃D"H$D"H$D"H$D"H$D"H$D"H$D"H$D"H$D"H$D"H$D"H$D"H$D"H$1ziƑHoL\(,,,σD200 D"MWS%G 2dOD"\\ G"Go4bӊR+0$)6?_HϏD"."LX%S9d,Qfmh0ӊ7,,&C _lI0>_f*D"\IꏔKL+1X4bMU_jIl~kٌx`pRcwZ׉AO*o{z5^A6H~,ŸCUUb6IWV1 |E(Dew).hAЊ2Q 2M 5$|;?IEYcOxk7vi:D"yw fbTrrT: Q H$bLMe1 s\Y 8bҸ@C؉}b;ɯ#x.Wuif&a5Mh4fa,pH/QHؐrT"y;ys/(M$yZ"UU'7YK/I#|;gÈD//kK\ s𕧁5-ó/a΋4!ؼ g7*hԔīyX}ClcN>Ma~+ַ5+Jw9NzG(+]D@ѳ'/M '.DVn8EEUcLBx<.'O(v񃾺󟾇'jSl (CN?BUS®L[|bn{ l-q{b *ӌ.~7+ߢĵ_I$bܰu>c✛_ ] ow^}pZՔǞγ/?™ACaAT~$wv\crTOsMUcrT)^ ~W^oz\^Drm"!MHUU|MDIzjpX޳#'_N/|^ s_WJre Q XBmL,*TXEĀ.Wc S8_FQ-YExŃ}ăuJ sD;߹hԸnoDy5ZOaшcC=~RZ+K$wy9KP/DGBJjȈA\Y@CᄖY7w5l]S)+{_SxWk>'-)={r_ØF">G˿w>(-u4WX!z-R 6VaC-. O_ !SՒ2'i>qQlJ\~{ kNpI~ pP(Jx. '"1Uh$w ܝsr# -Ж5D,xB^W +F|EG/&%%驉9>=|byWw"Nz>B/bK(|wp^IY'X8M'XĘga5|l|q5o+HH.oĖ:Ǻq!^s<PWQ\rQ~ʩR>q'n./Heq_ty*Rb%c<rTI3.37>-D!B67P^K5Ax{\.ݑW3݈8O|g?{zNPn"ʒkBĆ +1⋯fӥGGL3SJ8 ˶.Zٵ8O#&,;b#!ť'H^DBy5򕘼LIFNXyO3sUy?21 )n㺗< wBY^^}]OlLJrC\ŀibw"uayQU` XJE qXYWg-yL͸$4WeD"Hq!19*rzVcZѕOrTQDrrE<>+T޷tY~m][|-"*qA(+ͭB!CxJ"H$4Bw= u;P:." q]d;׬UCX͗tH$k+Tf>Q,3BJʅ]:f!-AR)t H$ɵ: 26U=} wg|Br@O`}D"y7pŪ kҊDZrt[@o; Z"H$ HKJ"3Qm?jm)G%̕S|Q2 +H$ hǑRJ$[rEH$D"H$ɻ H$D"H$kH$D"H$kH$D"H$kH$D"H$kˮ&Q~TLDr"!D"\>3~JD"H$D"DrY_"y{H9*H$H$D"H$ɛ D"H$DrsYnky颗H_ \>RJ$rP#H. K$o)G%p`GVYoq a`crb~V4j8*~g3 Q}xjl;}d´{˃rbW _F]scǻZ\b;޵,jl;q|^MoQXϪ ~i*ؿ]n;Sa%V|w-gT |~EWqX )ؿu7xqI-789}~w (DwVH$D"HQPU+pGËV5R@$j^b0'jX͹imF:aS pݫ8|NARIv /(:^P/a]%Iz.jΒ^V|FKb/rh &ml C$q&o XPyYXWfqO "s*;4砡 83?8䶸b]MTh9J0 3:ݮp|n1paOu cqwESFlJDv=# &Hq)D¹ KMEǺU]65KO3yv@nXޱ2Xʉ%^mq[y[aĆ6l˴1@H˴xhEKPlB *T/_Ž<[1%GnGElBxnPŕbpIʳ<9D\ {7Q12D"qKr. "cRT 5"ͷ\:Čfons}cuJLYQGܸѵؾLej.w?iDD l[Asp隳7gutfn\_Tt_OQ4t ]U_o_p3ѰsMkO|?^q+`Q?qSDMM=K7;\xN/sAT?-ss\k8r?^qb's;/*#^|]xuAlq}DM%~OůZ #B4jo8^5 g]x^8R c r&~?Ye|jjjesڏD ϾBǢ[ykJge%o:7[x +Dx'^jEb`bƪL㿞:Q:={?YWGdbLNOD8I̎N.^4}d[Npq@Sc¶, ʌo>ӭlJWzU* n#{F7աoJJÖ(qE>;Roa[Mh>tZg՘zAwEm&G]k*Y6eWWBOlτ}*|og1sm{UjEL:]>mNe߽/ʝ {71fhPe(oR/gjlBQ-L0W/Q)|O۰ Zo`R%RIUefff!777٣Dr022rU娢VNN0lRԑD.P~4eiCqzv6ň2czlNu^2=M=EuQ0X]qQfnl,P!{ǎX Nzk󐼼KhEo'$$xxCmBZHuE2óQU sK)KE3cڱ9jl`UL&qÆt<8#M|S-UQs,coYɧ?j2|(zQ> Y7>I.=4HiS|>0\\H"v4X¹~k48qaSHʹ;-V5>,J w3-jrFi?iSɤ u&fq{-<>C6~M&n27OРLɰ,u]ឍYTWX<6'`>o2hA?xMԤ1RRla%yL?ԕZ|zm6{9y,jwzܝu\dAF[LhHҝwE ?#> ]gy&5ܞ{t+L6Ajͽ-h0Y*4ڔ$rO0mtkQ+ct4||= _zمmrSōɝ54XOp4fKXwtK u,n/s*p0G$ū*GUMt4/rhJ1YnzrB<E_uy*{?iRSFo>jK3{xO1)<=Lgo~_]5x}+TW7ޗ5 ioXqy\ʾdU8bRr\ fUw.PTUA1mx ( .oKiyT3u#}&e: rJt:?J}egExOŵC IDAT$,pŽ TfeUg)8Bj S<KTUfv\(M 1fSUTԖ ^w WF)E3jgR[™{8:bSQU>k-}Uԓ {)d3*֕cC W qlAE&qE{/ĿǾNux̹(Lb e#'xa_'*Njj Ympt!f{iݻ9í89NNu-/Y_UɌظκbNॣ#dUVrf"Ug9NؔTb^IZ3{fiCɉI$'MZŲ.y.LIU7^*GCJE2 _%C~Blgt'p'b3~x2.Dv޻>|f 7j#jI͡X.X`:즸GPr3<0Y[ubxIxK=*)M:z&Kϩ&NX$Ξ9L Uq<2l<1H=mո!2l)Y 4+[{8` UcLXmXViQ3!)fӫzU|y--`4*$f4&*(^M6XP8<&M jg00`[%f2jQ$R2 CcQº< 7$ylfOee"AG`SXlH|6ۊeQmA _Nj3ӯ3YrD)N[CP\$raEeߨB]E&)6)N 3μZKX7hѐa;'_zl#{)uGĄ m[6Nj|-My$VX\W"a+q1bWkS}AM*wph?_ob&< QR?}>{ْR__f|{ V{ fA <6ſ=CƆ;=5__M|6OByQsXl,vœ2wu}bb=čhQɮ{/mLە2_kMExTI\oNN6eVqjH u>|3GhDFn޿1)Ȧ/K!R{>3)WZuuyNuq˖wN$Adꛢ)mz`qjksݣL囹Fn'{kNjBdS>eohW2AL]a{ ޤDGk|mOC7o`=w?@0܃WsnlHuچn~)AgUI[XWJ|$`^Odiu[!Jw&*!/l.{& 81ΫmܲF*NW8;h$*=HYm7q?DD/*}|SݼꪝmgwQ"Qw7<<0LD( `BvUWY_Ikg+b~nגMB\>/jxe<ˈϮ[0P/:ͶSPX\ڥXh}q7_9r6zc ֶl; WOhMɺļkc:L(Q/C[/fk7v3O ǣ8oq{6`?ǫAq_~U=>+R.n8c,)k2QW|- eeX\i;yI0<|NLȊTNQUYgtKXgt;zr< 1f'9kӸ,"ZDKL 搓mRrH31119;k)qSnvtM12bT%??=ַ\}01:UX0-yk RX'X j#sg"! %"!!!? S we2X˖<=*cu~Q"wfJuLE#5Xgn,'zK#)”&7 rv<_?+S&Q 3ph'%u-9IƦ96MͦP=x 15>Do+V 78Ӄ~cS8@cO;9ّYf爆(D I&׃2o Y\J4ӥsUYP4N`{+ vP$_vc ÓBe&3Щ 'S>Wt]).Rk5 ?sTbǷ[?Ź^"i3$ɡcb0I|ӫ`A]*Tq),T_<שCշUp%Z<ͤzX3^a@IkcT^lyo(+ 7X'G!߻L}EMwI]c*_oz[\ r-igܔkP8DZ>UJ&h&uٰOqVZr jC[:䷪2$ON¡gų5|s^ 幱2>s_浧| _T\+?`OK?3M5N1OP۝XEuلW0T-.\ q ~Xw|R\xuՐpB;F(.jo(7lts#o=4`C j: ]ט'P?NCAE=Dٳ(Ӟ"li8x xԘqq8?ؽ0o{,e(sv*dT' ^╧@8)5r\'$,/qo[!?n^l9ɬV½H[!j*؋~Qu ֆ'{c/ѳPƈDQ]6s43rg6ӈF-~^zYNtCܳ>݈8 p+>|!sEL4k΃OiV=%|C &QKGYyu`Mܾ2}ӳv󳔧yD|Uryje&ҼVg910NʆhBK]cj} &o"rwbS$K"Uіxk nߐP:{uߧ)M8 \ [}],|]x'h'.*Sь(3y'wHהN*Ë1PN}׎b%yݽKU n&PC3XXA0+nn&D.eSW Ky $ jiDyݜ8=O{i* c.qvf?Cef6c/f!7r]6Y;þ+n.vXD"RPörҲwjwOU\v↑9>~,V:4~KQ4 G3( ذ mC#Mk #F/Hfv嵤-T63y ;D{K6g: Nc$Sc[Q\D4Eôpflu^LbSc5>%xA'qtd }=()̌Y;" %&.l8}SRnʴi,1#MYlLO[PkuN+|ģ*ljLn`o#_䮀Ư<[e> \>(˵Zi;;rVӱ&%Z|.F /McŽ VfeyjL:RDX ,nYos5?Xjl[ePjoSXaQ ./lȟv[D~IK!YCn-+Yvzl"saYH!Pk9t~ʝ-]H\{6O &J-e۸-HTbq&Gb^h"hXu x {NXy ڕ#\KKKoK}K&'$G^R A JLDs\攲 }KTt۱bl;>6l&0ĉ:U hu&?CԨ,MeFS=`.}Քrʳ-b0qC'uށI\Y]QY4*""H~E%E) hfΠ8͉S@%QPڢ 2SQȿ@z5HFi9GjI " Mz~)5 ),'BVTSr`$Y 9גO|*:%u5,}KyYBPT^OM3Zr(HqTԒ %ylLCF^uUD:jSQYW1R)"](23ئoz)9Cbq3259EW0})/幨BIY5yZ2ͣ27RH(j/NNWQI,KfA%j ĈNyE>>Hv=6mG g9˧4s>R+ 'lNл䧢<]ϟJIM-Y:-GXL*439'gr/&ȫ,'UDc^ +-f1:Fu* pL*k)N sHVz E^LK%^@mm5IUVE~j+`0gBTd[KFi:4N4\BIVTI)ivN[^Nrj dS[|GI,mZ3 ʱr R {9OTlE$!Zy(_!'w-W'r,dpK:rmu%d-MK0U|~DvѿfQO"C\VNԡVv6򐘒鴼LlS.-LrUF?q3۶1EB0iY9,^;Ɗt)rC۩7@h2kU :??|{!KRhe'hN4tT2V'i 4dHHLuZVNg-]l-߆9 tpk;U;NK%0nat:J|Y1ϵdS{HtHN-v?iJ~M.Os=RÃͣߵѿee3Za[f4v~˱sNJ2hYzځlXEQ@?w=2 ^m`k ]^Ӽ%տ}U k4o\zW3br2?%Op=.KRhtw8ֳL\ k:2}:`Ӳs2GtrSUeXzyI#┳dT;*.a07BsG鉮0!/&rۖ \v4^Sh.={93>{jO9޳ NԈ EΏ]fteCQ*2'¥|#-$_Zۯ$A5w{w;'رI^8K+M5* zE$zu^ 86Kd~߷93sfٙs@EQ3&0hX.Ϛ%j+3ޝVHe'e1nM0]з+i<%x]Bc^#+ ;29VNxcꯚs.禸@9v30$tغQ <#+SIFH/r2#HxJ tvBFt6Q\OU5'^pLUCLæx=/%*Pu)q=dz $ի_LM* F1 A2*`$!!MNN5=1QPRVd~7T]`b+O Ucd'ߋlIRu],6- IQOF*h6ͫc5'1U-Ǝp FZ  GMN[tӝ|@qJG"UPf˓(?23#ҥsi{ӵws9Y9'$ja)"zrY\dA;]ӵtO7"O;ImT2NPaNZ(0=l}F~پ|mrk {z(FbjCԭLN ҏQjΐ-6!ݿ'2.5;JE 5@OQdbN\>{RF'ԙ (ZI']146 :2A#z rH9$M]Q*/GDXz[JϨ.C^SG+I.2`c w p5qJ r33|&OЙnJ3R8Yظt64rt.r&F=8*N[cb7%_&bXzX(?AˏݬI⢻Wr|^ՒxwA ]GVh.:͡zA7_t ƌSg1&U¾g@%i\R:SN Rt U1"H^j"EOF UɩsW&50J٥NzJSͭg5:\H?K+!&r&v&u7v28ٻ 1024.=nFm[m*d`Efn |C}YWCDt *=[d`x[맃\Kp 71g imNGCYz]0~N_˗lk͠uZUA. pltٜl z+:r ly~`p8mdw9);Ѝ+ԓzFO la}<qr}E-FL=a\Q ©î|{A%+Wԇ<>פ_;&4RWN5Ԁ]6w'f-`R.4㭷6'yxJ W2wiY\jK-X.f54)[wR۶f:M%̪q%)l1jAVk^|%gd1ANSRa7xcPeDW4'0c L=K]w0 λgD$Εh N5z DR{ۓSbnd;i)(FXԄ0D g޼)6瓲k -F6Q3Y8?uYر$5nveʌ;``W=v;nӁ%lGԔGDr820o掊ibpc3iB"N$'p(2zC?|v&yIk9j>EEf ;S6cQSww2(Ix"^ZB9C`:AY$&[jVgdIEi"\8L)Os-kh.k{"-xynz~I4,o$c`h i{9Qh;<LƷ6}Ufθè8)iԪSW-]t lh6$6+INENC?@smT$'I:Iތ@fLZbY(>᣹qdmG Eu ^f6w0c`g$B@Փi-dpP-8qJ؅ ™#VfSR.R7vFDgѢjEs T.`^;{ZJs JhVEDc"jJ.qJ&.DEtv64}xNۈ zDom"u !2" /Ss7)/F`V4&|УRl>RisK\iFDx&QiFU=5}(' {]98U_B^чza %*" p! F~6A#譅j7M8*/.Î6^(zF%\҄5 ȞZ ьLq~U ]#Rg)!r%.Sg£"3q P[z˕B57 5FOBc-ʰ';=c _{w#TU $4[[{niߍeqb ٍߴ?Q"4|$_mк+hx^i(8$Xju'j>~a^nm2Upj/ujTR sk95yyZP'my4[-pQ#;P\Z"-]Nnsh/;lZ?OИZ2gaW#y[j S:70w,>j Op:3_j[\_~W7g[ƯT?uk-`bX?B%;t]{#w*n'~tyq|~UiW3hI~ՇUsW7ڳYpa4_E}7!sIG4|$a|!%y[{2 M^K$67b"y|e\H$fG͗}7v[z-H$אD"H$0Эo#Hna>^"H$D"Hn9#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"Hny#H$D"HnyRD"ܤ9wmѡV f7.6NCdd6t:Vr]v.ks2ˁ%F c*m2X-_.M@d(N;т d72w =~ 5}nsjPF,P:j"؜ab ˵ ȸڎG_"C]y3k/a#ȰX-_Wfw_qݱ|tG۰-VU]_kz,keveXN?'Ä|}hc[baéamuq)k1X^{l6/z|VPi6SwV'xdd 5:NbA=bŤq:%}0aʬb&.7$?M1Qf3o.;ńb8¬I2]V ZN$&rL殱L=6t,XM.O&7e`pqV$&r3cL6Qѝ;9]w̜3O_M^ݍ3f3Wp{VU4ӆ٪3n.D_f̚BDg6Rg'vęsY#VLvC^ z!=}9~!{5}ո7u ='? 3g1#4I o0gfL7V2w&~>#=s aLQɂŠP42j,džbJjI(l4gTfjP E49SDh̚9PQ3xufNRI>ݫ;cfT MC+}V̱1}f+XV\IJEFq a2k(Bz1jb184Gsp3~lP :t\=LT*> 0#*NNՊ}ȽǜB]9? 3f3,OČլ,{NP1t, 3o* a[p`a컹}B-ɳQ}bƤ\aךUv ;O&Ĥr+_>)gyۢYq?Sss9$Gcc75X,Ŭz{.VZRpj ̱LfmU 'K"I^i <.^%~''0Y\۳>=I F`뛿B0c/dݒdb?2Noz~i G9V϶,51 w /ygYDɉ-*s1 .cKwoZgQrVјN~wݻZJHZFF@K!,}^}O񭼷j3eVi8:,J;2ihFkzB>] 'd^38TѢwxXvEߐy؋h6! Aǹwx7/rȎ]޵x=h~ +`w}M :~]1?֦0χ6P:q`0(dl{_uNW09+ٳ~ O+G3SRf+Y,Q#'+؊.} f UgYVF0&6ͩMԳoQ-0Kپz9 nMeiy?= FF',ϡDZ0.o%44gk( .M{dՀVĖKShft6)=ؙS̱-Y|coF|h?-F3SՔ anxԤG4f r5cȆ|r'׀/LJh1Z;o&p0aבOƓe[ϒM9/gRqM\Œep`tLz]=;~߼ ʕlV.P&닗^4y!FꪯPS}Zc07n7<1 \J|5 e];E6yWw!%%%uCl6yC PM;Q[JCXkb)JX9bqIK([ٶ\l(lv^C?_rL(B;ś,'my=⁑}Ą,UbҿY®]"5E<]}}xQޢ)_Ã#;pH>S鹠(ߋ\zAǒCI9"b i]{EbHtlOy;OΫVN_ύ^"Ebou)<2WĚ_MAlŻjO?mY[wS1Ĉ{^%n!bK+B,tcŞbPsxmfQGў7خ=SISVx%HG(E<4$BL{-QvfUXƴ2z*}o]qRsbRDQeW<:O|YEu<]~zM^J SJԨ_KK|Sl=^ђ/^=1q3n\*(YT^DLtڳ߅[kk=Vqbo֋m\X?3EwDE"CCk*C>#zw!w֋7Z)k=%ԝ]#%|vGUb-}E,t3nX~(yCh(L\+7tx%H+ޕ?=BTP !z5Sb[Op7.'}OQ%V-h:-cѻ˧~(VރEăczWjL7E"~-?&L}ZQ ۗ)o>.ұ]L>N [/o>Qƶ_@S+xg_  Y5& ǟl>3&xfc¢0!ӦVQtc]BԁѤ |yɧ{[c0E5ݏ9?1~cȅRw<ѯDT+8|G*ЕQZ:%#Ft `Ă IDATx 'vȉL "]7G^5G%;ct"P_ ȅ<5]WI G hmνw+2eon1u1x BUpONh/oT&tgBPâ=W Mλ)U٠xI cԩ[J^q'n:b~ޢbMFg~<cЕ3\gUzOHeX\ 2x..cfp\y[+Y|yAw^1ڮ;>]AN!]ﶝAiؘmeܬۉ0NhuW3XM16ʀT4slzrsaQ4uq9l=] )VʪmŌ{#ke8ػvh ӎyo9p= с[xJչ.>u^I!HZ }2g -p6&Vk9`2itVǮWnO Q;N&F\Z?؝ Uٹn]dmlpnJvcެijӇtUgrqQ-V6$㣴NndϩF;sJn)͛ðF-B 8+Y*>qգ|M nnM&LF&W8 m XMz*{ɟH'ǿ#H$Mb[Cqy>1^ 6'jWGTgcQê!2xxdBOt+\O7X-#9UL|M$j7tZԫx/]ԇ/64Y,+ϲr9AxpxJݤǿÒ 9q<e_Ŏ@NBVqj3ӱE ?Ku,,a`XТ^9i1M$#3_ML`5(:7m!ql1 %xu*<W,~ow]z`17q`ջsey٘H_jd-K?eu?qXDAB&jγf{lwR/}9?ErI4իٹԌ2^{|2&F3r!ctKy:u ,2Y]6' ._GjF^u@wU]>rYLm^^U:-JYN2KXj&b+whЛ+س{wT{XD,fݖ=d7rC(vNab1Ptl }zLJ?K_ 8l6m\JOx"ܖhd1 zyu̺R){9?ϟӭEl3Qp~A?,76ZMLӥ#8Nn/QF-dA\a}qN_r~3s5ЃWf.X;9z4[O:vmƲٽ?2H^h u}BGKX.^aSGKqedw~Oꕇ lR'J;Oo06Tߺ^^^Gةs=>~mKِޯ(.+o.[g^c}o"[@7H$7 n 8Fp6{UX1*v  pY:u?\ ^t2)< x^T(;z7>mИAYpv]\eD`q~0*UswơtbtVWΗ/|}j-5d]ΐnv5ɣYOCڡPY A޸lN:Bo容̼ :uEafH.Ƞ|\Nt2p0$_ BŅlj+F $:KsVTOn~%X108*=g9T _- ~C`E q ^zN# ![xtXǹ:}:sڰfpd: wSYŸ- NdtNϟr 8 ]w=͞C],DvA>p`ڟ=LOoחqeޝ0+ޡ H[|[>{Do ={`z OȪ.`l4b`k{_:-K[I}L'H] s?R憞}2΋!,8S(NA3ldwQn+XBMֱ3_)U+OwuCUimuP2x5goilwDzC)1h^O`gQ~d;4{h]qL<1D}.4Ys꘰_ -S,>Hѡcń JT_#z 'Vr:!_O.MJ%;Qh۟@ؐYsu\]sn5LLO+N.|/M|GKh}9VvUr1[ b˶ bw#n|8[)ܭ:H$&DKh6cXе9?(E{Ӵm7 ^}n$B~rWG$[:uńnlt'?ES~eס{d]'j(;alBŽU|UUd~7_؟;vW'C<ꂺ[LԱog*t-Aݲx0'ٛwxw(`]n!d&C'31ǘ=Ufu_Bu #kޝ+:& G[_Y@AvhmqU?&=Crٴ.r:drjZeU~]TIvQvb(!qY¶]'¦oFk̡Ux;aN^-]/w+>ˮCZ;L}"c~ge{]oч?63~cxWvuLxBڵ@]=cI޲rWk_Pc2|w"vQbxtOeDMf]+eU3~̝VNlMml[Z&mo`&t:üGe3s+w<=ާaPzlu=vzUWt$m}á55 MN/M;IHH!Q὇8_aR;vIG"H$ Ns&.9OvSM*=s!gt &6]BMLsu!GRIOoIktښ^pH&.}½htkyd2Np~09tzҊ\j\9Ch^j,rS6!4:uךE?30CB󥣬]Hc4g&EX^.udVdXmh'.aC=d%aLτd8NQ2]Ù#* OL\6bT!CYu!H&#i5kmH;zfW01ʌg喃4uOMqJ el^m}%.sxA{&=i=[y V'CÛ3IڔbnQrjM+O+8Gֽ+wpXBMOT$^ -?7_XϾӉ f~ǧEYl3)#b_@捄L}_Y6KR {OoNj._GaĆpt;OzK?% ˲UlػCYlO]?㑹ٽyݙ¼ Hnl^zv(>^\Eܹ rA>^ϼŌ.&ra_cc<4wxRs_xo~LLgW)7}JA{x3=ƖIKc %ˮH92lόG8ջRv}G5dM.j*(7F&{n S&H/._r>,,TD(--~G`:*rus+p|=M1I?~(Dʱm̻>& tcMٷQ\݄90fľN= غ9"æp'J}>{wDUz#3уpb0:-G)ay#8Qtz.gۦxNw":n=_E g-ϸ@m3 1*#C h[qof͢ð:*eDsq}7C7/NE[7%zĎfXN8.>ϖT6`܃]bq9q"[w2&?ϢɅéƞcghتFgV`g{cR,&=.D10h|c2!&N=۷9AYp+u'a ` ggBom, {ٺ#skyԈl&5صu#{hp5;? w-i}WfX8: m\UOeˎ$Nb7gt-G/7N$oSyԹɝaDN$?MyN]03'Éިa6oMl;IŭM9$l3w4w=!]Z;t $n#i]cy" BYPy[,A1wy,}2VnEGSY6񛶒U@bqs=5t{l{FALZ&Ơ -aY  8;  vlZsdSìq+ l" ^mz͵S~<WcJ s&uŋ|/)1nM_ߔyHnݾ䆐Dr|;_?KRh;rlN(`Ge0a TvCG| pxd荭[>sˉ]ysvi^<X=_&Cq9Z|I9<.v[>'㢆G>r=\1ב)rz"ۘ>_D>5WܩF)>/CͅZn_ua4w2t,{\WFkΛpƂgpc6o@Q'т b"!Ե_4|$[3|$?1|dpD"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Dr# D"H$Drc*Hs0 \.n[j^" Bt_zٮ/_]RW^dniH$!& l64CDAk//(vgz^}6,R뫾4Om7TQۤï­.WߔӮE>… 9pƍnKK$7E]&/WE]]V[d24Ri[5gR7_֮6CN&Dt^mCGnvR^vy,v}+}wD"ƴ~"H:N`n& ٕv/daL IDATnvL66F@vݬAvѺC=w3=m|Y%Y&7DC"Oms3߳[P?mFg<6۾ zMQQz`o] U@D*4!$^ٝ6a^}ޝΝ;= %ޗDrral%] QkPB >V3RzJ:e2DAatJ\!J|TPB Ei ;lUX1+ 'Ep9yXZ"׵J|TPB *T\PB *TPç2:=8RprV!rbs8(`1zn/\tzGt9؝EUҠ3kH8v΢:  :vjыawٶH.'v1^n D[8EˌEcNoȅ1+hm̃+Z& 9SUMg4ۓ;*TPB  >:&./3+z "ƒ18mVQ&%$Il9r9@Xd(&V,tEJ%=ۂHDDF݊)%!iZhd&m0I6ћFڹTB 4ӃbA; 5+YIKN%ߥ# 8#z\X-6 &3,S2K# 2,'1fGXD8&{ b6TRLGzfrcv Fny2l j[ c yrr<^t,N-AVo6'=t Oubqƫmyr䙟. d'\29|?8 ?5!rY3ΓK;$/+5< *TPBEɁ 3H&ά,;sP2hAGЫiEY.Co4`M=O'1{jy ahҦ;CF KhvNIɨ'.LEk8d%ZvːwӺjՂa92O/ 9WCtztnFM =6i\Ifj^2&j4[ ߅hM5wf{|&O-Q^k}[fpaqP 3;qgs0GUU^ 5VUBe1q\L%/ @\xxJJQέƀ۾zޚIIj<+#~AaVB *T)\Uk hž'r nwf&|.}[OC>.0>ܟ6tN(+?MǢykw\YV>Iplb l6䃩"R$o°{d|F *:^7#5{yz:9 /o1pxtocĝ2jb|=Eeh%O}OKX Պ}kg_i0c&uQz1crU3$@Lat}[>{7F MV7v5c!8ϒ3x˩_JJJF73XaX߲%ϚĠeǗ: Nt'3eɷ3&лF1dɈwrןb2bRFdǬY<{nmJ3V< ߎJޅFkccy_v۽ \rؾh2_勽 @[ %iX#CsfArNop(+_Cdb;‡c{<:$u$CnY\+GhLV~7g'0\> nę[ս+7nuX֫>rPfٳg9*F%B(UJ\6&RR]lZ dR1L˷a) Ne *zHlll!l6bnK?N,ڗ*yԊzRǦJsǥ+老IM'.}RRߓO\%I= itvym)].j*~).0VzdeNL<'Dw|I-:.r:Kf-X/4aL{),4~yw[W{iRwSau}=+-9Yij?WZTq[.G!i$_ܯJNmRΙHg_ϯI5¥~/͕߸;H$ʺx xVCzuxYJf,.sҤZH~eKq:ҟ+[w8HM"trzq)S2._ޕ nyi|{XpHE)7SSW4RH^?/X qF9XZ K}X'veW+JK">L6dt'%.+Kwq4|piAR>äOO}癫`ݻr ;vLZl~w{VZ%Y;v֭[']Vںu}o \z ?~\ZtzwVX!Ke֯_/t:syjaٷPۥlɛu4u|EB.7 >!ukrO&35Z!?[yW;KliI@zp(iԨ#Ͼ'm8yb;}IC f É.:ps+$ f3q-:<=;F"qpm8nwy!~5Ѧi+O'5_rAZs.6 LdsGIsAN` >f15oC8x^@9NbtexCV}U3ʹ܎Oq>1pRmh)ՆK2a6GҮE#"~˱ MGIpKjGҙ1ТC3ssz } wÆU2cњU2abeh/ЌfL?L. erpOVN Lh)O Jvtgxmٲq߬șT2vTn՛j.4hѹ +8Dr@㾸X`lLfz矜8 UM؊i^Ô1Ʌ-\U7^ H&W? с=s)\|O@L_l ) ɹE&IGyUPӰ%a$ xb ."lOa5$w r8nnZ}3D6'''OR\9BCC >b,yyy_???*T tٚkԩS^;"˕%[s,UTw!YTn!9y29 Ml?EKN?( T,Mj1TQݾBs_,_pY:?߷3`]XivRRYc+i|!ul SׇO/M=mCJ`&Nb-n%NxjфٝG:uRF#"*xiBۜ;m&ڄ6Nϵba:}-eӶn#8$&G.dMuSjCԚ^c*VV8w% gD[AHdѨZȅk{<^H+yM{h|O-B Q?yк ]ˠ "$yاCMY9炷}ET u*1K:ַϏrdddD@ 9{,]v߷o!DFAv̞^rrL܂PB$E2eOߟ{SXڴ~grtC: :8_>}a\8V {[ܠ^_)l81O guƺЇp .xԘh6BSX4zu2?z'}meq!}' 4.;Yesl l67i4.r3-j<ᵇSV/<1 dgsrjj|*Ɩy21cec>k{tcT{TJQW 5L Ih O€'@hpXr'78kOcv_G8Dd哙te31߸GhU({br1H#?/[:KҫKO %B+euL+c%kc#3=L/ܭŵq]e%-=3l^:g_eR(%A6ddj/=MxIÖ%AC2k"cxhl2^@I~~&]䯾LgxaH+FLME4[6Ǔ wDriJa%w^ YPw|5tddu~'߼<v%[A뮾T ӡתG l]޽>hu%*[dbŊښBll $BL dNbbLΝ;GtttGz ϖ/X1էs`"ۖ-'];^)MɆӤ[d䃤=ѣ0]6ߜZCN1Il L(S^/juF yb(/ECK6#4}F ]gBϕg's4^(=- QʎyؐOO`S]*ʉyVڏ[8EϽo~;Ú(+dв{  KU`/!\ }Xw~t?ߜ,V0źK4;$B~Ϟ+y_frҞ12a|V>wS^*z$a1{ivkL^b6F&2l+ʱ@`EF>F4?Dž$5!ן_`s_s8U>"'>RzZ` N}|Jm k%vJ*y#7^x 2o_U %:?$MEnyVQ\Hٵt s-咧 En$+Cx=#""52 ^A~KES$RA!Z*gΜ)h+?~\Q|'E>G~$Y(u¶ױ-.:&dj/ro^gA'&.?΋O݆o]j>m{Yfw̖$k0ECQ,aD΍OlH>9,t%z 8ħy$e&<5Y2'鳢]y~'7]}HИéۨ9 qvvˡFpihД&5c?$61"< z,n،F58w`NJą/K#'Z6rđ؟JF5DC4_*M7%֜έ9ኡii 7!QZBUEFDi2ٱu UhPF N VKDZ6K ۶lUFUˠuqYd]UҢ^9'b]Qr%!c`Z4N?شGAʅ _$7'Rv6j7iHx])Q4m݄8? {H"4W \_ efV ʢ}.:UqԚQ:Ϙȑ#8.e^^5((W}*nR\sT(EueނN$94o?f,_j{Efz|8rDΣkKN|3Wc˹-*U /G-Ȑh#`"TZ{r6|"Ixv'[$$~Yޚ5k^ 5G/`X#8՝UL^gg}}9b>eѭ~yjF=0Uo(T'@Rąd<4B.7r} rO|fwtboH?a$O&0W5ʟrv3C =G B:ͷ p!mn/Ihכ:ޟvgVY䑫((z|pz9M9p =Ol Yt|}9E^r`'f}ٹ?~cc0oK c9\hIka/06/ ި1j`qs⁖4N9w\-êuKdc;0]Nv' ݃̓Lzq/<:y.OwM@a-)<7OeP(9MKB^Ch6i<c39Bri7p pr$Fca*tNqs}s<23D\ ҌazBy;GC~ܕiQmvetݮ18q`›nPiwh3#yvX &al;t:n1k {y40Dzɞ(Lub7\u:*7ʃM^}l +h.q5"by"Q|OL^?":]yTPQ2aR?Fx/,Gٍ`4@Bpsg}g!P-GbW^ &>ƒ"Hw_PDR"Ixr +B>AD1!:rL|' ٲхӵ}5&Yg;X9Z;/Vc!ϡUUS ,JJ8̴P:vD;l0!\ tހ-˧2hjH5?mB*`K-zğ^.{ Eeja]Fjx6aۼޑFc O$/e ๱wc[=ٛm)lrjx]#˷%yؤ(F \v'1=πf,f ;ӄKZ9w[X> Cje 9+<,z.lm]C*pK/HX]Ú#3OДuLlIEH IDAT^l)4D7q!Y.}LAǠB{yfhW.$E yڀuX7cfEEAw<T`L %cP1ϼ@Ϩ]|J5:xQ096Orbάd ]W6)_<+p8nPϯ B={(R@ !OBJP-8NɴB.ldĦ"ZŇ,E!g˲|ECcGUNr!aO{u^{Iz5q]q1{p'ޞ'Mw4WI"!{\MJ]bG ^CpT~NVրn-e^H!7A..F@P8<ҳr߈jc;1tEE`&'Л<\r:u1FvL&QiQ ́ס1GvV4CoBBXtڦ7`{dup8Ǝ^g@DXYDufQL]^6;:NrӲcDuKL ϕCz{ &ڈ bBwIr¿Q'L8lE.Ar[wSLz HhP4䦁zLcG`$2Lff6c܂ɲ1EЙ0#/'zS<2q*v=& dҳ/%'8BB/4t9dY)$w-U8B2qõSn; FOq[Jj`j7,ZX8e#=[4^V>YŞCo!-8y6aӟZU"v)] \I&F /ꝧ(۷%IS~!hn_1Xviڻe'F^~Qe?$~]GnԪ'\n53rTWB]Ӊ뙳v خ4eI;z?""B1H)5cmշE5q^UxqmTBŵOXX(+y`\|RLzU^]:u~ϽzCunӦ\YAz|Q(@@)} 9:ѣ 7I?% z3}}#%Oz] u!F#hhn<ՂtЛwyBӬM}|g|cFFc%>6Vfx6 r &CxhS<^{?[ܟTLj#$Ώk0h`OjDŽ992uIz8^ biZFс2Xӎ˴Ϙ=Dzq`%kVoDH;_Ob_+}z rr8}_>CFӳEu NNY˷TLއQ8+cʄ1ls|:~&w.u㗉|r26c1K~LYDdyOs#}>~Ĭ%k3ˇ!e'fYA__P97Ś}ioc `8’0k{}U儽f,Y9[G}̝) ̄hhcټ6gV A 8m1|3G1<6Ş%δE=+g|=ػZc`ɽ@#]|{NnGp3qW,<C>F2 M~_,ZDp8VnDZ1h"Vcwpnb^n ᶎ D]+i0F&uqP!O"gk?Hn 4f-Uob{7ry;Q`-GM/`ple.\jԾa}0SƅhTz[]p Jx_" Z e[0x >29'&&fFFF+֫S*|&Oú8_TE7H!#Smt;ހ2 z.V'rL=+7oЩTeՠd- j. Fđ- pYNb԰T sFk<&z z{bl}'Q-;2pĽٶ<.}!o֞#=u'G㧿gӻl8QNJJqg̯%Qr]ZtE,qFZn-L\-JIIɊ)9 *TΞ=Qb] ,bqVl6b7K@u+Ix60/ (rPNj!W`٠`v'K%&cBhJ3 V##9\-S\hZ9+=)Ԭ1YeKAD7.1[gϓmuALLAf ٝ Mlry aFȃlxdvrRI:FSGPh=yӓINĆhʆ^3ȉ; 1HKJ$-3LD%OC:s1Ӊ=t^]P@;\ޜ7I4z̞ɦwU+R66l_,ƽE |F/oyqS\]Ņ U=qt:B ˁdE4k0"t s9l 1@[䵱Y(eX.yl ‚*TPBb\ENE˅y)d*mZB%>*TDPv)W6SBB(6;N_/ޗ(׫%. !Gp)r(rWZ\k*nD'oWZ-*T&b((JOIW"Ad( DR*>BqPKP mۖÇ͕JD*T](J_l^Y QV7Q\'K(?U-M"E.re0KbUs/P 7qi 3QfPPm~_NQ"K%miK! B$+P 9K"׵J|T h%=lFUu+B|*]Z*i2)kiK6 TB *Tx'e:U_T:+rDnfV*QB *JJkaUZ,*QB *JRr󮴿|Y>d+gq\kPq5P *TPQ$^1JH# J.R׉H2)ղ._`0» "WIu P栯8r]-TB *T0"I$@IPJ FH >2% Rjd2]e$HVcX9!SI ~$Lt.WY$Ut .Uy- (lF*FOo,&+km}?=oE %xC@a|gZ ޗ(T*e R 4 x88ʩ/*T(v[)^}EBcS/[Ti [O:Ō3.1x4Y .Pq'4.lsQFw]EkB^^^GUim322HMM%++XU{gO!5y\=uOӜ,*aJ3d߀IMTRE=Ӓ8}6 Jgg?CfTxyC$ʟ$&&=}B APdRwFF(9?ȟ OHH 4lx/^;=6°5DpXaAqDXx8a޽͛7e˖bL ݩ!?=*Ѻ^[ޜXpE8z5}R}ʚ\OOx:'(,D38#NdawS8oL\Nu)/}.5k%799Y&BQBE釲7X'PȏX:ĤIXv-r~ >b /9zLtEx&Ȍ?(N_FeO_9,sA ~۰E?`d;J~ *>XRRR[/:_7(n-|κX6M!M F_"\Nʪ6P@cBc0ވˊ#*1ì[;݇6/u$0Tnl_2AI"rvms] +\"DFFri5*n(T'N(˟g<믿Nj$?????gVՙ0a=3gܹsr40c5ȗkuzrq \N$Yɇޢ6I~˘5T 4#TPQ4N8 D;ۗ5jܨG R2eY(o ,8b%,M‚ռys V8r5o `EJh*Up\4c/;/Ύ]8 m+v- MhSE%[/|ߒh٪zҰbd%M8s-G pe[Nע#mK>K)c2RnC'Tx*˗=9ޞDq{Af͚2QB<ϣG}Tؼ26 o͢E;v£# wwqlHٰa桇b̘1hтƍly!` "-O&-__<أ"g6š}|tUC䕼}aU2HN+śqx75N:Ԯ]_b8r P҄&gΜ:<\TT$] 2bG_$= ˺7x0-aTNMi/рx=lZSTO'˿gI I-c}6g7v9qh۹KW-gusXs_E)7.YYTlՙ+Y--YtdžՇHֶf?cw=S{j\O2- *!BI(S(@*T ;&<6={ׁ+9SX;mAI1[n[oIPb>CyiӦ)j3 Fi3r8 ͂\ϼ-aEh8!edAV#¹W=*Gwq4׏ y=KSn-PNu:oO7E aEp6\)Ě"_ϔRBdBIҎ(LŢu.O#_aT«0 9H U 73O?${|@t6\贲Kms1gYL|?GĎ+?Y ++_0%xCfbȐ!]WC}fIAtAV'%G(rbł~X»#5qP/ ImYfc،NXu;-8#Mi^UmFH1'ƍjY}#/CtoƷ6p.A{9^hSӛA/*zv&ф~QŜE#I8 ¡v:Nm)&ɰ?=LzI^}#MzZ ]dĊ{Ex7*T(oQ IDAT~rˡ'"Mx oꫯd#JΝ?Δ)SWLDN( b-"'ol u<§cO<^or0#c&e?飩Z ]6RO)l}LVOVF2k+#(,N?z=*w5^=ſB-ný|7UC]K ۡ%)M*(7 +Ӣpw)yp%|>԰T3&bnyW *t_BdСC۷o ( 1 e"T:@ T{P. gڵ H . aG!_ɡqW_qZ@C[۰pW󇖘fc@nz>yk?4.+ m{wdꫳI3PH2iˊB|CnY~T'kZnw'z>%j;( #梸_D( *T!xF·zK&=U:=z-bFݻw/]-4 F#740ҏ"B|+OFj,;h69i[`sz|N4%lrVO \/qrd>^=O=I 3=̠{n# i |l<ٳ/wLg$;sr u$lZȄƄ7B1q|;h#3)>~s2Z=#aGO~+Q #,!<âұ۶m+0w: #8%TL1`[^GT4[XIx* H(W-B֧"˹(9頭ܓ*xu}_->(;Y;UaVgra%/[HeutemVrs-XΊ})UO \ʩ3qUmAS1QzVĺ\TB<O[CڌT<dF1.T%Bз `9cǎOfAvl>g?_}>v#Q7kV:VӒIfv>LzhփsH}0v2oFZ;w\3/&*Ϝ/qxYgټ;շaˎtZ;zuhŸ+u՛ k?%av255rЀgF`=:=<R%Vs! ZO;ע_1!VOEN 㛦<ڴqucj4:` B|yŪ@{tcgDxB_0R|<e߶-C{}P*kׂё?0oP: /:)<*EV憲߭Ys숼+En4N./?~mƧOE= G؝vy`Ձr|PqIΧ2ֻpI)OoD>|4u5Թ* [3D4U8v,s2 |ho#$gPa8C|+}QMxu C +*_B&(eDLb.8hٲeAnN_w3H /]v-x/&wK.?sޅ¸sܧY=BT(hhL~Жg̛\y|O&YL|@>lzgF-ݼ碰ȶnG %Qy B$>9K6.X_~qAAn8D0L)xQ,Ǹ_IHOsiw #g@<B͉42)M#a'DL|Wg>!;v-Wr$m^mPFY -jS~-ʁP0wԉٳg_B|;;e]\x~a_/ əq_ʠb2'9B %oUD-(eWGT4B]$1v(ߡawg bGhD\T\0akE߯gp,9Yd}Q)$N'=#,+w]?O-6<[+2rw [Cs shyl"‡Y 3o< uCo+r.{IA_/Jbu\c_?_ƾxPA9̜9S ͚5+شTՊ q"E]'HϬWZ3|y,~n>`MF.6=ٺ.&W˴D#?+M.:XSc.y.FYA}D4ͽ}@/ FD[;g&(D9L'^xakpoi:>+X@EEP, (* b`o ;VQAHҧ΄cSLf&a93w>gԦGHsQBVrm)ĭZ->WڦMF~ni]QQ {GT4ɩ+F9Ze~6eS^X t5z}A0'&PUmiꦺaÆs'FjyT0t=_F |9ZjЭWObv§  9HJ kJI5]|#[Jۀ <οiR>ɻ}_f57kWj]&&Gt;c@ A}AJeSc\TWdz:Lk.\=QaJ 6m:ʩ=lv۵Q)J5lST5-@k,9Q5Gٳ'2TZZAUu%U3~T]vE ?P|QjBHkXx/kT.T0JrE2NP 1-7|sd~ )|u=)#Po_;PmU`QZߒzj^e4I( ,'FXcEW[`UQ `^Ϛ5+Rs5DkJoQ*0R'@>a! r.)ʤaÆL24J9c[e^45`5 ڮVkQλZA ޵RWkWk)ojnEUEwƕuA0{Jq@WHuʳl2mfM43fDZZWfA*Ԯ/F~o*3,(։S㎄Z]3Q/c?fե]WE$WQ7yhZsE^pUЂBis]tyRX5V0 TךhzRhCJ(,1PPΎ;Jb]G-(uQB&StM툫vfh(-B9%ըkޫXC 4GHM|19Ng4"%N}d{>#~6D^B3~̈c*m`(m%47(Ƃ T-ZjX9=;jiQIjzQwT*^m~AM A[WkNy~ht]ѺנSˢ<0-BmVe-J2f- "zG khiò芮1 ZppVP**gYu)~cvک`D>F./+q%QRW*r8uE[Y0R#Aӑ zAA0' F:)ͨ+:(i 2en$AF8T-Yuw` -ڈ5>èR #5>DAA1PE^7bvnU nʑ)sK51JK″i֚cuu+F5_:X0^*^) `PU36%=Hs|*D;F$۵1؊hۋ0njX]BAA)n5ZUtiQuu)+mm5UZ3t-z3KWzI# :D;|ʠyDFw΢ui=f("J HvfUZg4*.IAA*R@af霥0R CQ\&tfe |AA%@0k#nQi%ƖeGAAG->O=M4)6lছn{Xm0+X FvҁA  DO ?}kQvޠ[Edl+? WPY*߻R~ޝHƘM4Ivv6< W^y%rJgզ |v/ aJlb21o'LA~ `A#ٳow~͡F lښ #e&wĽNe72[&A`3nĮ:;w.͚5_~˒q::Uut Az,AϨݎ 5E/~լ+A̓'  p(6uW1{k{f>,'5Ke g& t``%Н^%ӆ19e/68Kب8oEo>1\m޽ fUcAL(%/`!&6antߵo@b:fƞ3; Xcsܚ07+XE=p9]"+Xp(0|WmUn&=PAxf4_#vTa$Z( G~~g#g8&ꫯҮ];ZnUΔ)S"bّ JB KCoMY+ß,n )OVWXڛ%&g%iokҲ ݪm=R6nڵktoƌ3_>k֬3C2ؐqeܽ*6Ui zFs C@^$AlV+Ba~)IBb<_>9yB;qk%===?k9Ldp3o|[?.P~aO[<kKF[XXC^ |h>qF&.9q9:wM\9G1x&3߇#I:9|Obc݊ Oҟd^}|>ɭLcɉV:%1tPFZhk׮jˍ;`N(k?ye Í+W=ۋWS4ƍ`ϱښ_>/^/5,d~'ǝ;!gv-$g`s߲{&Lӛ|M<{no418aT.V{t̅ DZldVy\N7~ȸ{rү5!*Dz$9k(qL5)$L$֮SЮ<V($)\3B2vޡurFS 75e*mz*iL>~#\p8N?Z>[sn♿_wj* f!)ց?9:ms\օ?ZLu;$]Ɖ\<_d\ۓ lJ^L0Yfk׮6ܘ}6 /-mhvI PX§ڟt2Nq8v5?[NÅ+Λ?s!kY] $oCĭ3Rq"{n\:Ż`;$;`wQ, (6lѝ өSݮzٳ -{̠( BɄCig4>Se 7t h:W5c "r}??ԶLk gW`E(ۓq>gⳖTotw]LS)~y13’op͊˅.`o3\ dZbf!)#ȠYp[0 u9ZkѪN,?V+:|vlPH7݊)?;{~2%$bTsVü!8.}^xً0i9{qeʐ!C#5=ZO5[k֬U@ `eb>#VdA`R z H3.yOrCw`&G%Fjg@@H?aFtڗI3OVj 咕ULQh>N ܓ%.7,∱xا>ஹҾD爳[qh̹&0⨝Q6lvs9]Yѫlu5 -*47;Ņ_ɏ~OJûpr~Mww?cM{]MOasx&S_LmtoVdܕitt/߬ʱwM{}ԫ狇n̞^s=ؒzv{B}y9ޜG;ܳ[->%;.D=xb_qhu:FŞԬ;#Gskv IDAT=zx+ D6|t xw߭]&lr^ϼ'g܄a5SABBl0i؄$,nC[Nl٫yhdP{O<_5ocmů_KV|2oJdҴ) I\{fhmmqvq6%T V}V=]s^y&^~=Tӆ?hXZw=gW.Ćow6í.(ELW\QGiuN8׆w^K9uҶCX纩JLoOKZzvo3^:Ģ\G<)+󱧴cއ3zӰdo䅧xU|@ڑlD# ؾ}{vZZZb 7jnGnf& #gfÁMH#fEu[XI V{dddT1ZPر㐟"ŊaǪ~G8L0 a;pXqڭ=q@uS]3cbb_\<#b9yC )U*L~ҢGW]뵦BFGiR9Sֵۘ/Mrl]պ* {)ԩS~  | jzT/ %goU}7??P=IIaQM >  P4GAt. uE BAA*>T4zyt8h:u20zQl:,k> Cʹ6#ZhRDR:UKa38QQǛUzAtvG>a}Q7n PtdAqfD=kĨn? 4#SR@7}iuq`^4eF]E>·ىk ^Y%klN5jц&\Fqfte{I,Km*)O]?!F$۵Qљ=z̪+1#hѶWRI4((Qoj=_ PhJ ޟzwQgCiYuuzhkPR@9JҥwM)Oi0>uihz,ʃ V6cKJZmlҬnwL̨r> UOO~OUhmV]Fт]5 5$UWY>ͪHhD9SEEFvwE{}A7"jݴ`5#z%RFF7.]K/T*%N̐>lWDߌq) P=z8fu$ϯ*g ̨ UTu S4 zAh)VF(XV]YuiIFȂhʺgV]fu$TI.M/ƆBA7хZ'huZ5.j 2҄>Fut6 U!#;ZF 156&E7}>_fk(v$(MZ3f /i3VwYImKQ.Q8R#|ơZ> Q56."ޏZp`Fi4]|"vFCkNeJSt>3RYesmqE$rUca4(-zT7ͲƦA<4C5D6.-59(I nk fXP[Q8Ѩ˂v}}g6k;fh f #Kj\PC +( Nͣ7FG>ߌ0Գ,h:4]fH'!Cy#1()5n(^$'kl>T)1(es c0cj묣1ԉavwǵ,kb1k   w$AAH 'AȦJqǸG )[1AA? `:.7|4m Wͣ8s9I>o2Y ;`c&  QWHLΌ*oYsMe쭫Xsn,_~R.ذs>r%u6VJt> `rvN ˉf-JX;\.;r-V;N_ S8Z׊-h^34z֕@^F 9sQ~)=j&<3yi̗??yk>N֯],/xV4qػmkmdl|!}vX<پ+ՉS (\{(XOIViQ?ױ'eЩ??aΘJ);uo?m:M+_'.eWv}[yornXuЭ : GAL+6xt|1` fE'<|2C6$sX<[pΓ:Ba~4'D~GW;V𮯹皇Ht3c+yqqu0j~<}<]ϰ93`YԲ[ v]˼kxэՁ9E o.\)CWHrIS;қ 1D|+\=xy@s)H# &bwm{`A bJjHyzd kn"g/WV2䱹\z/ |N<#sh N Gm䋯K~ 7|NJus XSXѳkm2#ը:.*4w3o)^OdYAs.LjMn|B B$LM$.2^`!I `9ؿ{w_K禱|z/f,d_5;!Hj_t1_A;ѩѻ,x9j^ԟSw'3ۃEopB /kWa5WɤշqA4wsaN߉n4Ö'l1\kO̠~mnVՔ#50hAzlZm|һyu}#3}&A&751H,d{{8> &/p ?7 Az,L&UAJFx;8'xr+8yq 7OBx$>wċϿ7}N4wR6!Oq5tѣ/KM仡ه7hFp|,qOAV6Xbt`L9ŷ \8z$[xGW7_YnՖ5/Hk\tBVGN7O/1:. 䭙{KtjPh|2]t5l=^|kvIlԙC/] fCi{ C tT\Vu4뢝]*%}p=}N ¡8={knh]DF:IdĶ|;º?H얆S՜7ih8> ?@H_k%OW= ,n;5,?oЮV @0HV4ɭ|hU6;s۸>EDAMw}'t W{(ܶ0x4jJ'fMkסI_vI l|c&d;49\5.~٧Q9}3?dqTT|sW\ {L6}N;j-=aw~ {kӡҼA(_uO`Ix-<;1{o.[z>b!Oy pya<7}s/⏩I ¡ȎC\R?3]/E<:e*?sBF)u@V&hܹPr-Rle r^v< Tw?Y^ H)ybwO|j}wYѩ  GoD 92f;2oΫi8y_C; >?Ieȁ6w,!Z㊾WA3Wcsh7VB ÷) &srNS:1xvk}G)M?u8'u aX1p5m 9g"&@Iu4A\wL^9z7k4mOw!o:(d͊$CN<;9qOOuGkzuNag;Cqp¢;NwZ[I'[>X-iA{e0'On. {3{#s=ԗ@R_PM )1E_KSls1atA&gYX2}5c_IdEweduR(oUTӣNzb0lnЁa T *P |%+$WO,VP'E9WL|> .FZ C>?Vd~!^8{m2k=j $4jڐBr6d_q#M`,Q.n'4qcs⩙d5wbm&# B4',OѝVkQB u.ʪ_n>t4cE=F] |9fMс9Gz-˯Ljvh#&w\{9Qxf9עC߻Lۏ]uMRE9ޢ֒ BuIk1AV"TL79~wsƿ29"A)㸨 o\sb]SvKmލQКLà-M۹Oa:xL8@$M<ȜAAߘ(ķsi{*GCmbcGY#_aw/f@ &geSP˺ `=m |Z \>YOS]ϮnAAc,)1N2 ֆ4e 0m .9 0c?Ar<|Zփ~oT1Hj`V]V3A>NNP6+UmYu@_QE7i&LכzOQWyan `xSۍ530˅Wpꕃ9Im]9ˮiFӤ3iSfХ֪t0Mz F*$A 111@K+YRيDIQζ|ljINt.}!P |AAhNڙ6 Zq0.i+-J4&D.LAA0F) fՅI[B͵2? A0s8YuY3jBtU9r# BnMzvdC^,]̪+mWi5@h^UTfԥ3GHGAtrSiLdKu@Ӻ8A)YZu 3 6+P5.fե^F4ʪ  - ʼnTRׂ9 v(]D=FB&ŃQi5SչF֥^cjzU4sFIr}nYe:qu(F@9ڜhDϴ)>=Z9Ks8<5Zq9єԂ T꠫~whGfv|D)]v56'k,Bա]ozw !:uEU|Pti5kzV8͠T63WyQ'>Q6k. kl.k/3l.i)3u.l|j;4ʋ }%G.ɑ., m'lUeI ڄjYccSZ UY1I_>f3%3E$j\mCursB`h;uu56K# Y':Ƿ"[U&r5fN*GAbMAAAC  #e&>>k(C|JݖjI76CU7Iql6leK~ܽ5|lZs$e Br.  f-=cR32.|/ pXe\q8-~`T }:\Nk7c{.';b7ƼrXɹ IDAT}dNf}#G29nB5}ѳx̎t^0e' R7 ۤ1{F/ڽozq ?;{͇3#%15ul΃:z6n+99*J )Ή7?yP +.xx UvSTfSTN#ʋ|$MACbX G̷Z9d) hHsAAAL>    |AAA0=޺Lk2 뤚6 زn#s b!لV`ruJ6ڏ#mnD ԧD{R|}FZ4fҚm цtUTˇ\r<ϻ3*Uo2[ Nuۅ`Y3;ɚ[y߈f y޲ [>xtA| 6W|1|͌FҮq*AAhP9zK}FUWtjC9תG(mJC( 3R׆׫0M3wx87_<:ޕtY;̃ ^r 爑N frjQiQ+')_ 0PZtu2fp@6KŨ3A Sx}ocxn #''m~Op٪;C2&]{Qk<g@J5O7pQV *2A@\#S)[թlVQԩkwʢFJUԂNPG캴FUQ?{0E-VSkzY۹mn7_]Sϥ˕Br gcOOۋ<ެVH)¥$0C*TJs$KUӥ圙E ~TcGՍCi͉.KYu5|/<'P"^*r挧!tE)/*#nS`'u4zi:̮GAtJA_>fyY+>TH#  GAA#   GAAp+X'a86u T$ApC!,8RRRHw iK8ȸ⒋Sڝdo_6aU`;$sOA0P-q}x )v?#9P O ޴Þ1%9XaZ/'EUWR#jԐ/)#Q^~]|'~ߋߝiq\}c,"e|7+֓mO!tkê5!6-RШy9Xp%}vDNK:HH>p"f!vPF ;K6ZD54EX/}[n_t9Ճ&'-&~M1Z~6{&'^H4{Nt3,xzعql$-sdļٺm;UO9rA8#7{Y>ݘW?b[D{3L=*klNú ډOpo|@hV6Ik~԰ݻMb٬K:|)thن#8w}`ri  8cqO%8|tP'5xఁקX*#K"x&I1p\xuN#T^7ޒ'^=3#Cy2M,iffr\j=>M(Ƃ 87|yݎl>;]5YTf|iuSٿ%>^qβ=?jҩ_)^r JҢf\f[Xۨجvo59s~m~lLa`kҍjB1gqV'7+X99Q \&)B8 ?e!L0#`ql#XX,a2yUԗ*爖`iiieMQP7ww7CӬE{"w`RUg}Y "`WT boK4Ѩ$Ehb&&~&jb45SШD#n>sq,s=v+9.|Gi\I԰ۈA%9Vџs@m V.+hKx3d -l"eS~ oi )o.cIXqQ=jWH)ds 4h?GZj&t6'o~=n^F{mMfkk>mq%>i>jj$hjs:p$EIVE{zS>=[OIN}SpQB1v=%{V{)=Vn4 C֦j>?cRvcy+>#4?G݄j6gm.`*{. XA LH(e}6fcwǂ  nlPIya  > PrRNqK\>7f67P ;D CQtS:(| Nu]nt8ߋdXLn/m.D 5&i%62v)ѓF٩ޚo6ѡPй.5v:r~u"|A~5C bI; -zH(t:]Pwez^9&GH ׯlRNzT 4.-½=yA(: nrhL :ʣfm.^R:;v"EE}R-zPygM}tn:9'v顺&U*D P(u;ڑZ]J(-viQ{jZ ]L[R{H$6:k{# _cz2nK#SRq6kLҔ:]D> `n,nl 6b#y0 [vJ3nk[^[l&Į^'"|<F6rFMz 'ӊۭv:z__%Lbl)M6Ʈm='g38bLTZ6,ygŚ]&ɱ +̼ɺMa{qnjvӯ 7BmFwhFI-UuuSvkl.:Mӯj\ԣIBNlMjQºyҭ7g4EQ]݁NW}u>w!d/ <5v'~/n8lnzMjwA/?5n}>Hު EX,VnG@5EHp]zF&[+TqQkVk/?nK^Cn;0^'WAla|jvŀQN㰽g7/wI;S}ȷuHC/~KA(ꃿT@O֬槇.}n2zXn~tQ=gTصtu=mvu Lp?s39ggy{$9~ozQ7) FwW5m|ńaB2I3ԇ)S>z ]?SntT{.?.1#򆶚!?R`NaRn`2fr?&2h{yi5I;WŪ۞acZV6pmwsV}ml h>X<7Dap>*Bq1&Tvh;A[B]S.j/5pޝg3c9mmXxλ32_kx4uؑ_x.Q-m p7-H;kY8kL NۧնVٓùdI[F2~F4-S{zE  A{!. ^qߟ1̕6n<([ ҧlL#+DAp_%Y\_dEg[k&.LHcod}L%OorhAAAb\(ⓢe:XK I/f3y_!n&~: IDATiorE?Sp>x) D;Vro;`  Mm S.>9;IԏrZJ՟so5ErӮI% ;ȅnMd|U 3 acGnAJ*RVTh%,X3**|"i}ne Gs4}=m$3I<^Bv >8.8aOQʡ}s\= :*;L2‡=OȲ gim;Xo~y̐:cG :`utuAKu*,桹g1et-8/ 0QՓ`%ՕA6խ 5KmMxϿM/8$֎_?8|ƾV~n~ep% ,#0d2>>qS~ <䋜X6PTfߝ?D⋦+o—cGW-40#AA(#_Y[KGYqWOeVʘŢ'nkeUGe}ny;o%5uu?U?Vgrٵw=Hؐ_v/fb4k>=YX^^\T7aG%,ZOom4a?ܘ 5x={T?  v&I;~oķoTm7 @}yL^tjל-C/`iK޾g= WU0Q _$n?M>o)жza&&y=3&w¶/ &VW~#ªCcp졂AA(3mа3 :VclHCAo\ɾސj!aAR`!+W,c(&OfPbq'sM? n_\W5s.{y6UkxOk᲌-O%T?w Sv* X/8|i r|5NE  2/gW߳taZTʽPL*J"' 2v^E.pf_w}NΘ |kK?’2Μ*{>lnR# eY/Gr2fó\Gi Vc_Nm} PVIϰC=/ilPIˋ,]ߎ/gMr|?NjO;;N'z]u:T&1 Aikjfq\|QTomIQVMC0s.=7˙LUSyqɕ'N +y5|Vښ:CbJȈX5 ?8|>U-\@<SՏ#QibҁPmry֭ב-A2"J`ՏkgE*DcSݧsxhkH ;&J5'_?WdznC34kҧڤ-!1  NzٿeOWO*?fcQǂ O2gASW#- LbԌ>&{T܄%ܔJDZIC>[VPkm6Ǟ{9k3D{̈́m"vA354TI s{ WCVqʘ\j!zoʁJRd;Cٶ+ԾjX} cuqKIS3z GҴ4x mloifԁuAXK0g1hm3/MN:BI=7ucd2tՉ e|eݿǂ O.խh}+knŘ*zrd ,_ {8c'w<ږJ%:A(/zS'*&;U)TqWΡz^;1΅D훲C?6zOd$%M7aY$iHGnuP~uq6ٱRNbi@[rM@c챙l г,C5 =3+V7:)fcGDRVSh[~j;9u:\2CVA܇N5١VXa:N6](yW7vm:[J7mGA[*jr;/H@9٬, xw)_"Vb?I8&H#% inK?omC>kw;on./q~-|.X[3DM7&lrc`R xeeMH[F̪keɃ3 ;Ap~?HP%S>SgB0 ,@ +ijOg~VSGW(Jk]ĚmDTT͖zL_*էFUQ{i방Vߝeo9z2?ˢuL[Y`;OMv9etg!G=Hu_N#Zٿ.hSp]eI6mKvmNۥ}3ؒ]A}p \^mMś:r&]XD_}ZmW̔75bFXӖfifOg$#v犺ךz3nȏv-4-w]:6 vC3!&ѓGeNLXE?}D0F2vG8@< A,wn 6MCIAp!0%[/7jMlƭvm %>ōFw!rY٨mף /Ţ>ic&}Q'䃶#L%CmAA0qn>+iħh8kSXvʞAу >Zh;(#=5];\cK)anKGLi2Q`-6@@}Ck T AmATVr/(&| Q1feP訕EDzzxmҜ-EmZrUsl0N6&V]Yvm:Y^Ya}D:9j6{9ad=gRu#[xNJ hqŌƮ}v]k {n.`qɅ-vl`Gɢ:N# Z<+{f(!"|a+џq.):uO >z~֯ӈ򇘺.d=i}*i] S0﮶_luv⧔]]va?&G|TS{t"G}0[Q>A0tb ~DOhO)gu.?.qCN"o7f"ft ';FQܻ'-k\&g GZPu_adS޺wLʚpPb)M2V+ pK|;LS ڎ.>X ~Ofo;2v5moxe'kKw#GAD܎쓉جmXݖd2fdp5*`cV4S>  +u[ -DE  h:ZJ#  7)*E+kD `2ɫj,);Y5XrZXfs? [IX2Ak[T:AG  M:ɗeym}3bJBr+S{+/[e]8k8ftV&t˟?g3Y:Rx׽ "IX^iG}cNA(kl5'PA}u!xfYL֖`Se"'~[qАuGs~j.:b6W-uxv g^I t„|cOT&kOD>k9?^X/滞c3z`1)/}7]G{ om%j^ N`7խdA:Nn%پCT+TK'9q"ޗT>VD[^(6MӶ!3i24[CWGpX\~wN][U7קSln%d54&6& .5Aȡ xܧ8ϙJ0_>`/ ˲g={nPi{>]v? = }qh_8Xjpc:A{[_Auet2xH#GxVTRA S$ǽV6ͭ壗x= xkefƴBzLӛާf͹OˆgdiUm>.+zr b*~h v#л  ^_JiL韵# WΛs7QᇥᖿCط5R~c'cPM\xMLy?Mʱ ˙Gx&CLEN?~_Z}߾>3]6sgs>Y>yOۧ40FzH{Y< ]~}9$puO˙sr`x[ mU/ȫpG,_I<x0ʻ ^z>"iBu)Ԇ7 "y": !1_&]SR<PʝP~!u5^r+wFcƬ+sϔ yX N 5QgE:8;N:YOE%uΙc, aWqp͟Y>M;/bn nQi"EV:XɁ8}#I4gĨ{4*tCB$n`%MogADړL: ?g!_cTd=ɪ Y:޺;j4=Jw,OVgUv+%.Yzm^o7.%j𩧾2{Kд}cQ"bTT]nkd4iȅQUVTmS ЛdvHkPNT::¤3f2l-$鴏d*my'N>( *"\% M Lk⍦ :fJǿjp˩ O 61Uj%ڔI4q Gň1<'> .⥷ƎaC>[*gZ%nwtsڭV+ӞGXj Eenz7`puׯ 93|xμ~*g8/5jO >j{ڲKgJtMdi5,;ode3HnN:ǜ`i̼pbދm2`hW1CΦ4Z 2r4Oe@]N$vrpH9: u]lvphnx.x@=|0t:?6+-_'\[~˧Pv[.fMK'ڰj9|Ej#K(yz6i]w7cNNʑMnwRڃҶFæ47e _;d!w_|nj6UxRI٨US ɎLD"[WؙԦӼq#Z>t;<k,CEM/{ Gz??u3Gg>+=f"'ow%ǎ* ˷D a2Zn<{-~Qe1gGƎ7^ga ̆>yb@ETGw>U}&0T Bٓhm%8hb lnq6L<|,OӎKU 8I(f:(q1G,ZgQ͚SZF^EQHGc2(ejcuaW4Яa݅I]ss*],~R]3~lYAv4CZ-.? e6냐 4h?ݪDp޹S,r6>ϼGDOOcwtbOG: eJj'#45uS46v1iu£n@MkJיdAt:SaTGC*:_rVH/ZT7dA;oEgxL? WE}賿wIGlDv= =_U%Ϻ\^oK37A]㓭Qb,[㓫>W{)œm~bT..>1.ġF>AAVnIT,"|AA%X%8DCRn" :忇PKl[JEgS鷻֦Q^>@ib>"|AA()n>v.4p@u~MY\ 5b;IDATa^|$+`L_Ink# EKV-[MvДlG}m]tF٩Z o:A|vuN>#gW"fL!HdIC2?C$M ln-ݱ3TLonK|󦋄lP_.:7ؕJ}>,lK©9fd8ɶqw*J'aCls΄g y@gK 8=[ԃM@ `0iȷF] TnK}i~AE~MDٔq]jmWN*MJӯ˼iSidVvS4P5= a8bX0&>VSUnk0[tgU "O]'+g[;Njq!ʡ*ͭviG[*lʑ=+{]&٤ ŁtG}B< GlZXNlr>6cY* فMIO98ŅFfMn}'ҠT!lvI лrmB]J̸."?vz4KRZMI?VhM*nMzf:TשKIxZErkW;Q2/z֢ fOe>攬:,cxhANT] I ۆvtL9\+`̭vћ@16]# x:`gk)渕8Z";~P\ƉD)*|CnB 4:_mm u80G8l.'zY`&cꎫ6U ɻ9~T&Q6",¶(ڭm]c;Uѓ@:Nt_VYG =Rc2Bm.gT w! =:ĞX3iFƿ{GM#);cZa4_ɞ(1dI  =JH(AxT鴧=֨n4oɎq~]^͉ͦוg')64S3'-邋։oCOX0fxk!Q  7⳼cGPSL59nl\a6~O*{bb†XZZH:RAa[Dnr2Dz!|XSETm>AA:C2a:Ee庥ضy%|TpG١ďK 6D6B sKG"]E_kv7AR^5AtѠl)yĚ5kn l;dek6 90%z&ڳ-'- :ty+Azm>rR%p"                              нqRN>|BIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/scientific_mode.png000066400000000000000000000713521423020056600324260ustar00rootroot00000000000000PNG  IHDR { pHYs+ IDATxw\H@@TPq .{k+Yj:uԭu7T=3~B.>VO]0@!`mmm2BHC׀BF!؁yB 4Lǡ1BȨhj_iSKaCE P>" INx*f 28mmH&9KL2;hsMJBJ٣jWNUQPB|o"_#i;HU9Q'g0 EV*r`E!cKY!HT? j^eGAsTU'[+y26Z)| SQkQϪ0P|[zXϕ!dDS\ cP?eU5 t@ eAUY;Bh:4ϙ (OWï: S~)B:ZIi :mLFE:J Se!ZJ8];RvaaaڼBdlS"sT<9_Fg Qt*a]csi SL56J"AF9~7Oi I#g$YR|b" ('R S~JI}U21W29{%bG )x ,iBB+!徭|*Uo9WRv+E.lUb|*gd*~@ aj!dcHa=AO>0ZzCtBjSŦcflu eͲTАX4(qʏ2QV"UPYGN$ԅNoxܖ}~LףTj}tߖq>09̺ LϚ>Ӝ){!?E `dQi-c 0E\\BrHHHO/S}TC )9P!S! ! [uhXx2.9ŤȈSPS | p>T%i ;G!vaY9 YYSr9$+ Y HV@йYL)ߣTQ6Oih-aVrR5VRd@I2Y)Pk6Bzmv}Uɴ0ɕl}DJִLx2?!P(bccVT$988|7A!NR@*\5!kx'B!؁yBBǧ!SbB8>E!v!؁Sb)B!";p|B=?t¢N!ML_vLsvͤO< M^ǖLmu_Μ {v޺g#Gƈ&VT lԠzic}ScSمSd@"<[yoj\OJ5هup0h?2F_'LoCq)eBB D !=:3Cۇw"uTǯ^E;UX1i6sUbyd=P;0)Je#>Ё-J6Y}LmJ[Z\ޮzFwOۭ- Lқ-HT!e+EUM _<2VUеI>"'t;4{^`;"7w%^=/gJiQob-7W7nGZz;[Y"wIuVD@a"KPΓظTҢjUbէ\P{.[@SO+7|Iy{䝯6Ӝ׹ b^yNE"3<%K\KtҫGKwn]Ö}^T D63xҴW㲅S)BH[t뻡]T3iof:1S??ϙLV]3iPμx1i{s]{Z .S'^^F԰+tq'^z*q${0-PvYkt+`'̹SBq .6",,L*F&=F|Ie]*z֯TGwg~~T0md 76t\헣ՏP?йbY|Lkn9%6GTDXXT*e"PaRo1jkz@' -MS-1~ʳ:(0ɏwZ }Gwr@J(wR?xya"xEqnŜ/k~5t:%0gN߿?)B?{g-8J:'&R)tSЏIwd/d o/-4ݫ(T(s +!>`2>_9mōxr ϵu(JEjy0)mS+rմt4O噌g@jZǽ8a"Mh1/}RRNM\R~j'q]2St kly!R\w`%p)<!aO6NY:M?wO222J&0s),-1]3Сmj.:!*ٵ{.@74kIdϏ,]oE(n8m$>?8yRiuJ "8I.:LmƖ}ݽu΃acedvMDh\jG6yw ށ gǍ!T"z;V&O|Ew9*̶xY%+<|a|LH< S̍0¢A3go&"O}j_s.\8}VO[%z8b}QdٯgڥN; DBQTxxxl勣ctttƇ6nVE.5C ---~jooI ŗ/~0Ϋ~Ϋ(w] &KWvC7tnG~:Vn`UKto} Qmh ߖgТ AG?tLJcyݻ͛7 2m;Im;t`%**J6҈VVV9[RSS<<_z6K4aw`JDyJ Lj2x`~-^:yy@+wa3f(Y Q6%{hvrr>}Rma&<<9ndѲ@O@o]+;Y[ lJNgAUVՒ. )nlI<X }Z{w'3-ʪܳgOF\]] d[Vߴj,<<\aJJJ||s$25-ߍN9M "66666vvv-o[v$pK)YL;;ۻ^M&x{{{{ ]wD圡]Ϡesڙ^2m9[οN^'`Zo3O]j'd2ٚ5k&MdTJʞmW|Ht^{vWJL\z"!ڈ M;V~?7<|033$<<"gMZŋ/^Annnz>!Ҷiz+֚~sJ[Qp3gߤSfGv2۹vfUt<3SȐ7)Zm=kOG:m=U.X5Η#YuZ6\5q A3ߖM}|w|fs2N |xnd֠UIG%ئIUDZ`ϙI5GR 0@򇽽H$Sz ڵk_~ʕ+ʕT$+Vb^Uv"(9Y;tupp}dRgjnhPʋ_V-UkځۏJ`6ΕX1b@R\˗;V} s{^S=DXX=.*P_aa9Wkq.NϡS͆5֬zǏcƌ9zh%W~111%5>xM>uorIBe\#P~/^f@Jjo(8?Y?4o{6}"x?޽;nEF p n Xsk(==]" 0Y}i9x 2TjC(JT0ʦR|_&"L(JLVS5 "##B!_ǹgM1 薧r׍tL&u_Th@T4o7ʦBҼ)^MsIѪiAa EQjڌ)8Lc_1i#=LUwDZZFٔ-|U6*G_$+7.)[=K^yQ:JR*ayA*a׏WAtt5H%2.5nOiNKKh@4**M6.!tƭ>gͫ= kYԤ􄄷 W!׭as!q!!!۹sgյ7\Iiᑚ TxiܸqR6lgϞ[&''ڵkx(>=sܻw Tw}3fӧOZ Q&4""0UUVΏjժ$ٹsΝ;aÆC6k hn߾ׯ_(?7i)e|j֮8'0u5@\XiC|lTQ LCJc ;هv6m?zq~~m}OqYPBP=u*oPUYyJ ƎۣGw޵nz…\"ס!y4?ݵ*4 ȄꄸN;;N\ 6ye~xeQcsERJy741q!)QO(B >|Üi&ZlٲeKmWM[Ⱦǂ-0M9NESVun*v!%Q-,G%<~ŦFO<' Aϐ.ئ(s:uD3gδi&gULUG g̘a)41Buf+_njZpaDuFY'sٻsigVsX\r$|KQt} /:8$D}'Eh.LJ>cƌf͚#U3㧪cT ﹏rcE,YÔ(2RNۚUՙ *d֭߸gS]5ڽaq1N._sAܦgKnOyfoc?^+I*0uqqq92dzg*@URg R TusTՇQQQP(Γ Ԥ%# GM 8(ƍ]#}JKS(IIikG8/ԮUqۿY?9@ص|ڴ=٠)(Ç߾}{LLLjZtihT(.]Ԁ'Kw_~߿^7bĈ} ӧ͛7-Zdff&8x>r",ڋg(=W뉙#lJRʧ5W/V8_?}M QTwnr'j4R6A'ng@{v|_OXxo.vηԩSZjk׮]`k) W޼ys7o޴hvϞ=7oOHHX`ȑ#۵kiXla߼d_ٙ8BiG "6{|L\<ª-Uޱ&u)`gC ի/PU@uww˩S޿-CBBLMM۶m eʔx+"Xw(ad{sKk؟93ʳ%T:ux{{0]؋[y*e onzeʕ+_x鄄[[[?B?-["p+O)]v666o߾U}122233ĄanG!~dS՝P((ȑ#˗߻wSuֵ\hQ6m.\kJBH5~xssNP(%ZJ||H$ׯ_OJJ ~~~BI&^O͚5+TPTbC!{Ƭ&)8O/RRR0-*Uqڍj U n y-333F`_֗F111>!xD<5]k_!=$Q.|-uaMiG?N_!O|QQL8߅qRօQ6q 8}D(ɟD|?wc 2ڬHrZFٔ-|UƧ|T)I|T@/ahV*`_6 $YЍfE"ʹNW gol 5lMI!"8J(Q| \.ATrQ6W~IPHQMӪgTKު96OH$T/ p/ T)KP(Jρ'3̠ (tKM1Gd〮p̝ya\X) Bk0OB!SbG1Te:8o_AҪQ6ؗ{}_&bNE.k_/ rE)F`_S_jtgdd"t(m}N[=l(Hc+?T&1LSڗ8)8I׳uSKY9HڗjbzBQڱ6l /WAtSJ./?UԺ0ʦ4n6>-V1򖿓Ժ0ʦ4nr!8oRoJX㼉US !g0G!.6`¡>l_1\yDܵ{.$>gmU޹B_Oxމ@o]OpM97NF87wUi}k2N9%Is.s +) i>J-e)N^wlۦRb&Bb*1qgo=y9QF:UV][@'k2qMCWLʳ]~UwҊ@;n=#NN*`"#hމI~Fk6ՍMJRb*1t!(:1SWmip7{"!yȭB!Wz~e^.mZlc[v^vWxs/>gXv-[1lg,tցNʞQ!_&s.;Y2ޗi @T7pm:\]>y;BV#x7,&7|=?wà9;]ϧN9Ws~_G4x @H$b%ḘlקIkV}cX$@vצ>dHtRrsla.}>t-[>K\Y@Ly$_[;{Ki)x@wM#nceKx\.=_k7'1@G\IQ!Ɏi 2 %6) ܻmS#tT³u $P.]a^r2&Ҫ3ꌞջ'&A<pb Б,ZIIS[;)b/?VhK*}H|ݻ௧3ܱ;kH#MqO>HNXao+|;eԪD;vNq=st}[nCIJв~U1T훵]}G:͢}+ f_ =x"Ǡ/=ZV91ܨl'j2ct3;Io߳9y @;@3C=sA_Z8szz}Z~&rf >hߛטQu& 'W=K%Rhj׃,tMDWwhJgge=&S_hᶦ\uӮߦ4rNHW-A]V5_?舻w#O-*s(^*o@7ѭW +Uu/H{Rdfjy (};7L$Ĥ٬QMhl+C&)!aڄ}箜;4z55*\RY S a*4ɽP?|"Bă +Mt]t/OTa}]WS S'Z{.]G=j5Nz 3 bGu0JͳEcF6ӱxΜy#i,`Rv|zz38sk2Va>3Lr<ĤI!ĦČyJ$&)ug$:=- =Yͨѹk<甐O3ʂHMMwV+HC>: l]N~\aiɈ01Q J}ȟ>ѼjCy\xL*L/ċq&sd ISM4JLMU ,IAAl;֝Uh{S2>.1773w'QJ@ҼlÁV|*\iJ yՉ8;ڿر[^G[5mkgsӭmwJ{qL5>tzOEnr o1Umo*ڙ@-ԟ⏹},.,]v!etĽ1do5\<JҥvM{8w^:qWCyqso=^3&)xS &m4c׻}mtžyzyƟ7k#sMIz5 6zz/6"Ť|Dҥ.67ؕ;w޼xdug#hxecҥ{(|oC? mQ.z5M%vB^Y*_zχvZ:VjӼ-ŹZanmX}&ʐ] vS-SoϞs|Dmj^_M=\nRSB@yk(uc 5޻Ӻ-GUϟ(@SCZ²7n=n֖LU3x]1l/%kشG-[z ۗOX#3wwɤuq oG#oҦ$52ء x~&J5--SÐ+{^{kO;emڡJ`Z_&&$8m@SNm:ğ~NxGyL.R-7⠠;S|à&^gvygf~߳0_/;؝V}/3ߟT\_8`E6TYT徴!kIoR~}ǯ=|A LmT8j8֗F111Fۗޟ%Ԑo<+-K!!c<5!TQW ])B!؁yB!O Nހ@W0־Bzyj}1<%WԺ0ʦ4n萧$i wa}Ѵ1\ǫօQ6q 8}D(]k_J1ܹK lJ>q*nSG@ 8>5ʾYT_S}qƾ TW$wvLH g/B M \eS}qR!}isb>X,.dcK.qT*;jM1E_qD$ 0]# t^᧱P(J%EQ$IrdahfeM:#B昼f}1 Ӵ) Bk0OB!Ďb?UF`d6`}a|KF`_(LƋʪLTE@ (rXŏwV=(R*.)8@Bl3pڲUKx^vKB2k ^lB׺n2b (vݹs[5#x]Pjt{NMiX߯ՠg#r]ߒzcmZCE(m*lzqe^-Zv{ 3׬8Oep ka/73Vvnt-8Փuǘzu4]ud<#qYϝ;}p`++7ٿ1\P=0;v4t)KƝL}}< 0_CzfH9OY<~@tmS`ޞ]?-{VQ|{[hѺcaS^AsDKo'eOG_Bl+jRYGN/OxIj՘^ G;fR)B*5#(Gg)x{l`L5N眓IٗDzn%쓍gM3j!ėǷ*+ϧ?#Lc?xbcȣ~wl_qՉ , :䚭MMP̓OU ٛg *픋y;Ȟfujx*o\χ$ ͑hufZܧ";8=)qj׹jّ}bn?2QE6l{nT%"Z*CռV91ܨl'j2ct3;q7)*[̱KqPLgiNUF@XTFx,H+R&ɱ_3tX+mxyf06kPm+~<w>t5a@`zӴO2Hqћ_pzbl֨&v [3ձ%\8!]QJqIM_/j1|vϾlsS;_1Ņth// к/7KIKII +/LJr [ZzV搖Tz?{>8o_ֵsIu0ȍg? 3 N$oZ}*sȂkߛk:V4)Ky:K)eXx ƶ"EDŽGH1)sbMfn@vt ~e2|N2upPe>6mI+=[Xۗtҹzv*ɮ0+SeAҿߺOW:55ƽt~5FS4ś}N ;}}3&j"m_(\Byp%W J욖Fk_&&%8"Vwfcm_CohSLI~}?(wSP}铞(&&ƘHJ=[<{TCnеjS2LP7? *&.I};3הSkFuOW87ھr iMy8G!/bTXn{d"4#ߊѣUbbt|G4{:Yۏ|!^&vָsޥx$Ц͇.?Dظ9$CU+>Y`uw}Ta A.^|mYGq©QCr٭noV-6tA@7,!ώm,Yzw+u7apYIwӆݿxI ]w`R>l^#zK# ~Zf8TZPSi 6&6 y9=BHR+nGzļ7SΫ !q3Tϊ,{e^z"`ҩz#g g P-ItskzNg_k77:5[.{`TvM/N#xҧWC .RDX5䉿r% +>8v]n_3 )UGy#OMc3?Ha :_0+%̌ӈD^ղЄCi f'(}*g~_|fcF5NS`C?hVܠF0ujZ >걓b+ԮfUSW6.W;$"15%]3~ @LGJ'1:e.=i?s}&ƒ~پG[_?Utb+g%Xbh R{Mdly"X1ӮN'CIAaCz3YɀɈ01Q JPsHNs7u2tis=ŵoFEbjN=8# uRS:dۚWC9qk=>2,* ʔs2>0r-4 QwL*4+ ѡoS)*d)?^oW EyJ9$XeȂ.ei|)勺gO^^ZC{3\\ԷWw߳IF̓s{ަ&"8ԅpHCY6<~iWO&J5-Z15s {}1{a=}GQqfwҁP{t: U@ (E|Q&M @JUtDj{vw?@]rLǏK2?nٙY˞|܌}>XR'_/*8MqN)C]~ԿwV(5uwtztPb':yiD>Ϊw*1$" qY~fK#`=E!zB!)B9zJ(\!zm.J9< .CY}E%'- pp` ^sof`|) e\h(%)xͥ(Vn̜|) e\h럲^z$I?2YQ}B1l65쎎A0/k.Yp*Vne(\TH.4OOO{s$yzz^sf;62`.)2WAũ FQ$nRSxBe8oO\,+" :@)UU՞s逦\GVi梔j0PXAC!XOB1"c|eZg\Nr 0db<&ZJ$IE5$I(mEQQ .CM¢mb5F_JΒr˗PVaQePҤܒARTpﮖ8Pɹlzm.G!=zB!)B9Sr !XOHggP~jɸcqB,c:ĝ΂/.VežҌ7|?o_pnj^˗Pgf,[bJy>>xaMg]3kEmLEց3*G_tc݈M5ZLٲ|`0AT% &6O0`-ͣiB E}dڿY+&X˭MyWJ hM;rXk54)1z3cՇWj/4ꉯѠsQ(aNs|J[w7C}pTll'2lUDX1n~̩I.0tM;]bFQ{ݖǦ&'%A`d# M;lVD|:b9g ^֯G}hƵoW=0kמώQԥT 4ţ'm}iN:t𸹨_zB`&/X>KX`* tVROt: uWͅ_>:8LਯFVqԘV0}Spޘ&_6eփ}FE/]oNY{sc4 "ٴb꥔e^メ=y?]ӫ xѶXkB#DŽR)8ԾߣzP1J۰\} z0&G4kZr&'&? 5%/o1M헳A4 <1~Lh0n um}#5"QxIkx X!(,MJHt~T/'P+,b{ڨM>ló+'4A$&s )S|+5h줡-+0Po_,U,SA4ee4m: ]/6፝\d\9eP]S|zD ;?{Mi @eL7`SKh/Kߋj|3CN{]P1WJq/?|·[g*nNIK`8^n#lLth\i\"∊ufe_i'MKMR~_i_HKcCFBUf3hϗ^Ф?3d͸n6 h,LLy3޸J|jիێ߻£R)4iTfǩc糚7գ'{o&@f6;F%TZ̃(a~5'~Fo>rhҽo+6l > KժWގS,J=< P !݇Y 2kWukyˌ߬"fݯ5tS~JĨmЯd(װf9&iZU|C;"M:Kg& nbA|ڔkFX`qOV{)3KK_>+hQHB6τ˭Ospthն 01'|H@iw3RoH=,ڲ~'s'>[MX4:p9)u+_ gX=fߑd5Ğm_YtڹQoT܎Bz!)B9Sr !XOB14SBKBSnsQyKe(EC=Lk.Ua |) e\h(%`-rKe(E[#I)(o͊ 0Yehdwt,h&e\̥KJsd7'Igal6APlywp.Cҙ"sT b4%Iv(=G!Xt?y%˲(( RUUaq 0hʕO1{d1k.Ja  e4D!zB!O-8;o"w*PL&Ǖ-5R"%I*D$IE6giȉ(Js逦\hgee1Qte9++`0&`&\̥3E*H[=5LL_`2>k.萭뀹 K^!Kto [GE1߱6.C1lPOY/:S"_ .CY}E%'-j%d/>¢+?IYB\RTpﮖ8PɹIlzm.G!=zB!)B9S6aYw#Sr !n/ɾ ^ {w󞎛xJ:4k1xrizvxEG䗻טa9gߥS͟lٶ۠ 󶟎z@bgX{6]ZfF<'RCW+esbկ9mJ3|}c74yp ltl]N;zQoGbCBv#gR|-ճdfejX9_3~wzUd@|uSLߨ(1>4J?*,X; }ATN^}Iw.ߥ?U<4䊩o~y5|ү}Ӝ)w欚ʟM}y Fzg⅃f}"upw1?n(1wcCJux\rzRrlΈyȶ50g0tIRQe̎7>Իk4aӔ^ 4 0bѦzѡCP'ZݍFwoZ2 @D:KxIDAT=6{MgSۓL?싍axc5 짤j^g)]_l5ȼp*r9,oQOyD տ/ɕxjL$NCEAW^\)H 7wKΝ:NCš)PSbl2)x24E}xx*e)eoiG2Sjw&[aF#~!M#B^O/ԉ6z~cg7,=0bVOTSS&WʗiqlVrH92Y=,\1Y)ʍI)P衞Ҍ,5~^S ջ~xm걓19'^U' թ!=} e 27Ԙ#cUS#s 4+#hqo:n2n\zgЫC$ 垙0U+$/lG}Z}«)ۮǀ[-:?ODzKn:z\rJD>@32~2zEL5r3:giïHPz9x7~iw-~^T6Y|>"Lh'sgy~߼6t4/uL^gv||3b/vet_z c|a^'RgmqJyӿїBXGNu+;`7hs7s⋏Oy&xPZJ=!.Bvȁ+QNe7%A=ܼ[Opw+@2lanZxw$zJY?۲i4ҡx=5u  PƍAAA4##٭q oo_0|=jɚgܾMVmк]jx;ve(\/U?u%){ !T(N a=E!zBi)xͅr1梔KvɗPVaQez*<(\R+Rp#,*9lPJ$USKQı2GXTrr٢z$j\RַfEQ KǬEPh4;:hVdYfw,[YPt\Vi.",$I,T2,vE1mPt\FI,JnOB!=O^sɲ(( |2TUU{FX\̥rSY!cLRi.Cb BHo"c`=E!zBQQiY~sB;e(7WIPzj28Og)IR'y%I(q?K)EQQ .C,%WwtȒuhh^IUS_GYdee1z L}5``/UUmͦ2 L ,;%~}Yeܣ%>WTZvmNj#P jnn?o4Jw oSns!v*G$+inEtPUسa! 3yx!OLeb)BY֪)䝍!NFFY-NzrA1ZI)BHc@5]XOBP$ Ա;w 4z帧u}$-)>ӭ>2[-":֖qbf~[Ǵ9z=u|M)&üo:g|jk& l҉Wtwc>KFN~KBѳTm!ԋ Jk&K0ozDzV;C"\U+;V:l =``f_l1MyoܗT)mr0SZwSb.O+1U>p[GmwÎ {ռa&^?}:u6~D}W71[|jܫǃG|?X *s)1 * L8;ˣd]Z1+bST*_zmx@z3u*':v5^$)7|ٻYޕt.|^*ݼ񽥤ڷvv׺{1x;dm5]qϕjεUN1^-ok `=ՍL\::UH(T^‚|mM >Ԥ׶i1>}VUf[?Y|/Z5nGN_L4%gCB%nC/S =~lw]*3[vhj|ϝ@ ԸL '.fÒ,E\!7ԾC= o֭S7T7#C'hT\٠ڝu-OG9hf+l;jtDzLLkpUn&')~lElR6Psj3sO~SW+0[NfJ Ƽu`4vWPAp+r} M&R WcBxdڎ 7ÓoY3~Rz $ɿm𭜛!]_ 4d1L "ܥG]Sp*v$Ђ7h@@ @ozނreK{=`KPwo"?@DE˺@>)=gOzP5z߲###|M/Na31rP'QrD[$%W,lc%QNQ/LyɫoN !ˍ~7gW pjrƍ {^ָw/ya땏&zGfi/O5iə\*;L,rYVΔØB!&o"~Ztt #~]ݭ@%yPR]9_0"ؑSG9_)DC8!P [%b=EDϓ.pr"OlZPO ` ^s!^,gc=61˗PVaAlGkiŝU0TUk%_ .CY}EVStU쨫J$1~ 5(V_ɖ|) eYIA! ޢKRb~mSK$IV\梔)UxPo.B@ 0R{Ɗ@@ ^mk4 `4Z_Z\,;TUU傏s e $$9e?3BA* vuQ5<==M&mB$IUt,xe6%IEiSP].KT" O +B#7$>d!AY/ڸ}Z¶mU"- ]#D"|vªlDD"H$AD"H$4%D"H$+iK$D"H$W'UT_8(? D"|e}o$ɗK2vX >ME} q:M Ct~ Q[J$+'7fqMD-9RH$/ f;Jb@FP6?MYh,qļ(p_qoGUH$OX*B$k7+[! O c<}8}(7G.o }c[D%c x%1PaIk3}p?:Uq7}(t&޸o"D"㜾u'[8Oߘ&M{:"鍝7lbD%ccĊ~ϣ.~aX*41pSuiJ"0 -I OhpWEW%I$ŶmBATU#-50i!\!7 /zMg<}oD6i oÏJ}#H.?B_4]w/9?`d@A>qnM;&)L R˒yy%zFFEd0<_ERB[[ǹv0-wSTCjJDr%_ߌʀdH7qa$H6B@t!s>)o9H>3IO]ԹUDC5|CJikk ]CK6Eطp- 4b8D#FAѨבN6nbym!I3ϭf׾RSB>exU9p+\kK~2 .+ UQ`wشm/}f}\\L`ȇa.J}#|}b;lܼ5G$'a*R<ԋ T疭݇ghݎB"T&@h&R( H>>JjH P\(R_'zȡ&Փ˸ R.=}y[l߱~nO?ր_` l3А3qES^fLF~kkkbp /#O-wձw-?ûQ JD蛀K7}¡xhSɗA"|B_O?=>X,oGO_S^V̝߬߿#u=t7Bcǎu~XMgsɤt^h^g()zƸpsf^گL$⾪."2W`0 _@ Qy}\bb^2!*DX}YB466'^x`>߸‘ HH?~& WIt_;/J"dLX{5$úȍ$τk^A,nkBra*QO8Ycn43S^b@~}'*Yz~8HOq[Kw cu% 50s,'3#/ 4l{Pqˍ7/.ʣ7l6RXVp J$WBԵ?4}pu%T҆No$ʇuG׹;7`/OQp8ʷe˅g+=N~^;i8>`cm/mɐr ǹph S~/ sa1xd2I$aڤLj\$ߛ;.YxSRB>).I^ߜ@[ۭT5oDxo$ώFU~DCGGe5͸?㎛wL1S^.u>K}q7&/47 D d1.6i^|PCdjPO좗He%g_(0uK/^Dċg:ŅDZQ8M萖ʫkf#"{X??,qEMg#P(M[zN8I2.7fbs'WՈpNUgEi!+A}.k*>)˵G:ƺ ټm/8C;?{o3e%O%eqX$:KAA*jߔ0ƣ;TvޓA4%<"-ՓO`ێP:jb&=!>Ĕ533qpwGUķſ@J ^CS鉸FK =73t7~2k'o>q }&2]"\!(T1Cph,:r|T\@|>}-s~4\Ľ0?jWfIՄqLl@ 4l]-,j! >B؟:ʗ NbB7"G0CWw/Bꝧ Ɓt8|*pO p75fB߈sLis$|6Lt^\_\_y$Id{OO8wO_;~}}1QC6CKZoD^F3օuI>FXGiJNɐ0H4!_%D;y?,go; ~- 3n鉸~S]9S.$D'Vڞq^xW/oD4mQEDcגQQq&TD 5=Bz{1J$fLetaуcy|b7ȏ7}qoBH#HD|7H חRuBVDr8HD"HSHO'7+#'pQ176H$%f'{H$DݔED"P䆨D"H$4%D"H$+iK$D"H$WҀH$D"H /H$D"\AYhEqDD˅7D?^"H$D"xD"eCD"HD"H$Dr" xD"H$ BΔSWH.RH$g1Dˆ7D?/j*?GbbsN_044 N @Sc01~_Y ?_Da(Q5 )p8(4Oo0QKrr  ^0 N7 w {׉ 4-qqL;hc +D,߆K|R荀(Oɉ+DݖP9'W<MaDE"osNpk~")Z'|N)tTx?"j8^}ßD"H$W>_@^AU!Fރv5XܺJUʼni4 $Smlw@ٹcK5 "j/KF_ۈ^74=N i;o#CQl=̖8Oe1 \볶0NU6r*m0 :FWXPakxFgshQTKaM*)6w;jya^e4{sAC*DZq͸<%^u'-aa(qvIek2%Cmt!pVga1#24SaՍ lFy ʲ*aJr+&s8ըae19!fzm:N@Vl Sqtެhr%mϘXqXpX*rp߾ScMashMo8MȎۘ1>Yn^;2QOZD"H$/~B_CкVZc1*Gc`iRU>;_g~*b\.[[[&4|= .#EwiJA2>dj:{IgGD!QxjN0n?XVo3&C呗}<\00i9)?ynbUm:: 0kuC%oMuU2S!&  x01 w`!%Fc*8 s^szOUU%GSRRN]]]#F}|>;ck[')ζ}>t!+C;%ΩX7~^vC vsbq^ѝEN:>߇g8ֹ: _}]ŶmWM>Q_;ߖ`}m ~B._}򹭮jm坓O~!k'fųwBtq>|>} ;/ޯ."G|Fpɇ# QF )0TӲ?{za_sh}3I't0 M'L*F E4uZxAJ &'IJ<. hLFc ωͨcgƊUtO[PgMq676n;Bذqٻ|wqN|TWo :(DŽ;x;Bf҉7U))%'IZ=*Y J&,kl91!0s- P5( 96^epM)ޫpX< *+lbpþ-:/v#>X0b8RTmAec2!#֩F[ *7lj1a ˽kGZ> ?]c\9y6MX<&wD ls8} ^G8fe,X]a1> 23LYdx}qxa:׎sM ?}@˷YjFGYPesh+1>pbpSc'ot ŃliK0./(Gk;ւO!#%cB _Qj e2- CHsӳH2裷ښz:L)(cċ_zN[#Iu^@(}#ulA@G5X-5'(!2ғP9Q㭨I'nA?юfjjhvH X`@(5di њ#4H 5 ˭u#쌓IPsUAæx=GhId'?X}- m4Ғ <i;AMQZz21 GWi;^Ǒc:A23D}45ICaNwO$5@0'yZNwYgl,Oа8TGmIz2AwPBv7 5Gh8َNZHvTA8RsO Z|>u֟ LOƱl@5AJ@Ųq&5= jh~ũ56"p a@3i=BC~5,[%4ii(t 5DzZ;q勴SW[^$lG9ROKMZfLN64/l;it'LR*}# 43RхѭLc-5D$2B/#Jݑ#o J PlR0|>E]&'hlj:gARMIt{::o6H=Ks_1zU HMކ #,@UpGO9CqܸuOx8_\xƦҊ6jo;nn}Ҁ!mgL(w/$w?t%39 )+prTōօw[~s$ahﯯ({5L`npKm"*N) +)'EkaR=*[!-aիtm-pܠ겁^:ʶz<1 Ja|"t*l=0!KP${;)40m#RMaM ٙ6Ui7.N)`4l2'6m"ͮ I6ҁAvө0$ `4ڠsBn}zqBG7ftI cJT!{fli0}U6*x\l{Ž@Ǎk[K1ey , "*FcS*MI$_nT͇^˫7Psp"8\5w5no#(ͻ_ck{@>/fDʼnٰ$b/ɼWS4>iUP,S2{B1J$vX' /`uNxuoKat믦0׍H[VֽFuscpBUl^C\׉t>t L%3U:O1鉇pBW}|7+Wmt\EGBh1U96^ɆMh>pO3;k4)f\]=4XQ30{LGa:v %k8 Φ$ݡv+~Љ9t7OrO#k_Ý~%FIfuVI{{]M5ڍ^εsRc{ 6=33hLI֮cOs;`{"f /;{8v=g30Цn %*\3@;?æd)szz OQaJ\w0G1sv%v8~AH~xlq;WŵĨCX+7ݐXq4X˪wrUg3"/@$-{S{.$=tvb}t}4#D `ގ*K/Fjmq+yL4wq!MH@5H,/;TB6˿aR]' E' O4Z,&]W L g_񘊦Þ:^9 s{y"O_yzƙۤ fY{XtN!ldÍ1=:]x߳41EQxAe?N\<ֳDPqcSg/bFW+mRUK*gƋM*CFf%Rƶ=Q&e@wTY&T2)+nu5|Ά?NW;uƖb,*f d0NVܙg)t(UP/0rlf;u>6l^cix+f>7 H|nFxĸ8* :V8;_ɼY鹇ye?x#EJ^IwYl{֮LׯE9m?ɘ%19-k)Kz}̢k }k-%12K%wR> pR^3ô6xm~Gͤzp#xXV}saG"آ/p,,-Dk;@} (>r4#KSyI~|ťSdb1gYY[T|k.°s1|xyG3eՌ*;k1! sոhgxYa߻eLk1]Y]03sdե_(/YɠߠX(˘jS#za֬ϠkӨ6 #J}?MŃ7Tß9ê]AgxWT%jX yg|}!߿uDTWW;[y6V'UεQYW~[OY=j%4vEv^}?Y'u(ƍ,!Z:?ro*a~/UUTgQBm/UQHU4*'1u( C-<}-f1fس_ZGN`fk$e0khؿqk딗A/W1|(2uVS(tv}Z SFWϗgh0J73qƍ5Tŝ1.>[RQ1q|*')NgҶgW0#_/iOu=5A}B >h2 }LгEØ^I ]U'/A|n}-3aznM< W$zp)5wCWjkY6|}~t= |\TFLeP_\kğDŽy瞥ϏnV@A% L2~>b4P]'ad1nyu\=(Q!E^~~TO|LI*ds*O57>i@537' >LyN?;Cӽ29FKxxu/!d3K'|A ~W>f*CK㶕?%nKX4Wޏ2ΪzftdT3&qo~6pyh< ۊ$3giǔbD[d qT>ɛ9b0;K >PKv+l"wL>Z11O.xLs*o|6%M6 R"#۱(FS׹"fq5E,00{Բu>v uLnj(utuV=Cz!&Bxjs> f, xF1ϰ{6V¯]Cmظ}/')4٣LT==A[cLFFhXshXn7$D^#5'IZIbZ5;7yÍ ISTݧٵukPrÂHLm{ټ=NSpbfVebS&u;c>:`ʒ1DN l}Gꉦ9qlU~6nCC 2^L ЮlWN? -`P"n+]'xwfvl$']`ێ>ŀoeVU&v<̎i<2m u f{#7nPC ,n j<6a˦Ԝl!cfu۷c!ZI,^:E,.fӏev;'tOyQƐ71ch{5=ٺGP~BX#.V͛[ߌS0[nP4]l}=7vsREa-=tXsnYp);;9X_OohΛa lm9~-`JIfBQ8c+:ș^? nYHYX4Zϖm9XsZɧhԽǖ]odM\;,4~2F 0vpR}X·^o?Ppvkll Ϋ9i;l`P}-]Z"T@K$v9Ѩ@04ȫZsT݇Ԏ,9ՔdvH#ӧ1fSp!)DRbB2Mr;r 9vh?-j%: ذ =:fJƒPc2cQRJ'qk/kMZV,Z\>8&-pXO 羌xBg఩W.>u:^"~PCDZ1ĺ:莐 GFZMV{㤤1ML[Eutm#Z.z᪖X3 օzm$. 0M^ܠgؖEGk;3qc]vPJ4-„,]%N{w {hk#bE6-rK5X7mhXS,Uz[鎈L µL6_>FAlF{hoa@AEwω:쉓؉GNֶvbeuFh8.Zۻ)NIsg3mpYdkyŻD,H,+GӉwwKa~0xW,bt5ӓOO1v`ϥ X;K/9ūeJww:Pu7Ug>m^i,ƅ%jXv3}7q uk= Ybk-qVΎHNFϟ実l;搪solʼnvxq7vHr"뎒y,n=]tF '3#ݴ 4pΨ0m"Ytho|ThQuϹVN8ёjۿ;7'A(=t{P^AEpMix3TmV53;^A<sc5c+9#7;ޖ,<&~hd~y6-zLn; WF2rR8Nٌ?vDN9ГBMU%(OS/{JGDg~MX}+SYk4zE#POA(mQǴ*?^=Љʒ`I6]na +4m~rS g*ɰxV;TtS083a:S !-MJQt CU64RݱEL]XjxcĠ!<.},z5ir A]'F0j k~8" ;05o؋[\Uf4Tk^c=Q$aw7]>{BslW_s[xoP>V,E ~)^{o8sT0ϰɧhL}K O2X` 2"Ս޽spox᠟md\+_W=?4U7q׵nR 6ngߢd̯R6*b=Zln&7CG/Z &`;Uxw_ qK]շ<[bU_ٕ/`sݰĺUes{YHvt7SL;C<7 |s!n>\1aי^ϘɦJ:~m;qϋ^ׯ71X!;3ľW ͌6\uyz&)D3=ӭO_< yRj&)TT zi86y#_0x,eX 5K>΄ Uc 1/ǘC9O斥߀6r"#ƣD14n.fe_};#̡4+3[߳i䧨FN2?r@QXa{UOoUX-\?~7[q/Hꇚ#!_^gDʋ+Yw[ܕ0q/䔚/; E6׀o;y.%tl6nN"'[Q('հ9yɰBia· G4 IDAT:l]T>~FȾ>珂Yh!KZPda{*kqw" хĉIq$9{/Ď^ Л@; PC[HHT;1|k3}>ΞWTS-'֦[DG֖"C,+F`mTvQPKur;m *2őE]C-.5m(RK)2GfVРX$]ߨvzk5"053QA8XGc@90+먯!xQTջpUSe$R<q,jg=֐-ƀvzȯOM#Qa~5S][CU)pJd?**갅FEZUxꍄujQ'kꡨt"q-*kh# UȬYWMM~XqPS@}-PfzKm)vQ UUSU_ 8D]C5Ÿ`]Ȱ@*֍o98@Z;vQX\GډBf@څPw:7&O(E=%Vr"Û}Zj\Blz Ñ]C]C#UGkֈvUR瘟J.jxma@dukp5RR߈_Df?$A6+TޤS@5zch'!7:kw\ UZyh'FHocnXº1*5[ǕgAL6}yE٠!K=GۊDžk(H^tӉOT#]Ms0¡֟&NރdqMqINXC<8{]z[?۠&_{u|6ŀӡ/!Y0bB=No}@FvݞSNjf (vn\vzt5˃_x//4맍gh 0j5iw-Լsjt(/5mBګnz ӱ夭Hbh5IA Dz=I7!Dkǐ]C7ki̘ ۿ#%fq)È0Wȅi G' 40A4gɲXcnҙԄQTKcŞ|:'AƑDH,YEW;)hU )We(tkGɹc>)=5KA䡋č/.Xm(:ù;{zNIt{Jd_ `R)c|z2s$Բur"1΢3"uro|jαp6a*H( bCF#ݓTr% {.> lZs $GHC(K7&ΡfrNصRx` VOCg:n6u2r1$u 05QCqҗ@(;dm[,f?oGV?>ml^ 0qfr8\tN@t !ɐ-#h-qI=G.itUx%E$ņSyW8{.>@:5F~aѽL֖-zbssXMo%.!Оݢppi(R|%ދ@vŐX?rL S# .BV.Iҧè=Ycg (Ϫ5@L\Un#=-LXB;igau2$t}#'&u#vVh./!1$uuk_zL-ܻyzV]8ME8:m_o%tV>=yXUtK\Я|(MgZ\.5p -Xj?9oI\1hqVuu[Cs򋦶hUަƛgnut"x6q45Ѷn8_35&]wgZ>kw+hx '7J]]ݷzQ# 7p{`w#l'N!s4JeY*iw4)Cz`Q'ӹC՗s@ѩ vтYy2>h9W>9SO #0;*˧iTvP^ZЁ:Ѿ]JM19yT}3jɉQ| PM^Q%$&LKG?3aPRHdRG%f'<,OM!E42a"b1 QYGna8R&k~jsr)o c3Y B.\O1 /P#rTROޤNM?HMQR}QLJM/WE!9yE421l(!\륞2q1A>aWɽKyAI(uR/8~"C°oR.5vˤd|vΥM>͇а d3GPV@ΥR<510C 4PM~^0qH (%;'3#Rۯ#&/ၸ*/Ir$v bWTQ_kTQYUAIqt _4ňj-jltipO;Xz[+'#s%*_A}DjW+H416aqLE;.+=b:QI{{?ne8{K/XT[bN6dz?AUF^jkcZg2c\e OvtŇpZ]cX׃6hZY*brŇy(xYsZL -~|ZkTۺ{f1_I?jwi~C`6c5__x~̷yY7:. q}eoxۨm)5B/~M->~|oԧk/)ߺ(,ZsK;5CxDK _`fup3*=u J$whD"H$0BzdG%nvܸNH$I[@D"Ce@r]"!d/H$H_jDM$D"H$w K$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$Bl6R+D"H$D a2 77W@D"H$7b_fŊo2H$D"HAed/H$D"!d/H$D"!d/H$D"!YD"iS0[<0\g.j6vU+ G`0hL;+Dxp:<`02 &+ ;OPӎc'2G&`>D\j04 z`7yMkײt!ѽH<VhA>aCW86sCLLߟ j+,6gS:{ϖӗ 9Ȯl- N2waӁL<1JLAZQf2Xv Y?`mͣ7pl]j>`!ԓc=vg,edDF'n2j~6kM4 zËnCĦ8z:~-bfR9;RgmǐIĬʀn:7 JHݤTa]:'LDډM־46ӑ)p:M`'ixRw׾gNnSq6r<Ù8av~Rec3987M{3ǐ:?ڨ;evq%.@7NnXĶt+19J9s#[g pcn5RtzT 艌 Dž`Xú+8݈ 76LGvEx=xV^ bQ8.\}xG㱚omҋ_|vK$zut䛢koL6Vw>s_yƼ}|:c9x V*mf< `üY<\K1#1Qsf={7|qÙ-Kl!"&SwzgŠ8gaNX&8M[.Q0Ǭ:CF &f[r+>XuaPpp݀5ncwﯥ`Up93iƘX.-CT L_0l џƜ]zA+h6Bz';:NF}^f|~NfS}.KbsQh?"sva)d^Ŭ 3^0f1/9[q-TeaG )Mά{Xl]0G8JGݹ/6_0k""/L>ۂ},V*2TE`Db&U~c,R,c CF&DU/d!V>gt4nv էx~?mQ~2ia #0YϿ>+g!bNJͅ}dE!}ѫc?3/)덈lV:m%$IDΎ<xN;ٳx_(WhL3~_flV>>3 #iATgi쩈bD&Oz]ٶˎyP2#|4K\B٩L w@vha/׾ eA);3fs>Q#11Vc!hdʊ2 ޗAI0z(79F3Vÿa]Q;^q*[֥ٮ= 7)((v\pȗ|K P Jz݊˫[bޖ -JXebEwg(^qb,"~Bl|] ~>}P֊wߘ&;K[#z?&7Ū6NmFGE\ױcU;W|,ޞ&?EVګb@xg_ i2|(6(w:)~?H|K!Gs[b¥P/dѹ$ө{4֜ZAd.?7Y;HΪVʏ+⧾).CxĂ 7ex_a9bǂŇ ݸ_?YI|K BbxrT+RyV tц(~"{?!k3[:y[uOԟJ3]e86vzO,?.p~,}_,U4\3C9+];鯋];g??]|l;űzݣcŸG+V(e4fLqG5w gDeAtM/.8ox*}4_)I"Q gkYT/~7Et>U]piߵM2ql".j[Ev;w\G>9_&}ib_-3~"_ԉm.%tCs~-"{76ic^x/Y}QԘh؛ukNY-n)>6@Ďح\`!Ѩ+v+VyHxOɒ`Fh19B2C|]v(O>ƋQ^*AY}YĆQĬJgR;_ߤT(«(o1@c>nNƈAGI+L|'z:MkB#H$6rtᑟ>^j72~ ^ٶFK=8;@JK( &d~ѧeHsdG3*Pk$wV2팚LY]T}{Oʐ&0_/9g޲CPOR1s%ʪ!.<j=/_ƥ o kG(~-;c8%@>1#x" 3VfS^]Bs-:7a${((m@FN #[;>׷[ t%(~<$1l0zŲooeh#ϽbmC 'hn*c '0,8W M_$lE"e`o_BОuS;RG)Pw73GW78]^"ecGלÈV2@/֐ #๑-#lK=<3g/qps:yèGct0n 3ʯPC̘yNad߱5/_?ٲvMHЇ7PR}2$M\ȯ6~ٯE9:#+j7&įZ cɧJ < Z&jaqMjͶVb -]׼}}@i(LV8ۜ /bnz-0̿B#H$V`;q{#1,->BH+ttX0!1L2 n~uËYSo'F͒UN.NϢEp$<¤Qژn $r<@e9:镌;=CXme\/OXdRUZ.àؾh)ޡ<4ī6ɨ>rtmMwP1ov1")@+T;-2-ϝzjnUOWj P IDATN`"MVp{~_<< ԜV2.'+sߔ:XBQ_^}G>gm])r~ښpy4ǁy;=am\+9y'C rzcZ&. ag} R׮ף+^L-jΰ`A1=|fiJk.&ݽ5jtRKάL8@_п|< ogDWV0,CTusOrW-Mq7CR'տŎ,\zS&ӿY+maw) c0C[ ErP-,f/}K^-FJvGjx⹟g. D"HVe}oG?GлF-*5}mkxq Ͼ Oһqŝ6zٓYΨ彟ƨvu(?ƴsظ7ȉ|k A ,6ғ#V8BfE3uP flf/G>`M}ZZ -ϛcn{G3'ڥhfg,g IN V#w.al?st1 W"*2G,vB}{O&Gqq`2 ZW302<3xpKjTva]i>֋Tvlӧp2w3x~Z0aۿi=ħ_".C[W#|ǹX8}w&ŝVC!+ߙ[9?}̟ӫu f'ebCf~[̠i[?5R`ks>eRWVk06X.z_>ɱZЫʅ3mZ=mO`q_^[ygl6m?J}o|6C el:/ yC}bzM_W6sx=A_0 G/~Tīo Fwil>>\O[QqRS&vCWwHZ5śOc SRku%wk0P jԅR̾AXc`GwKmLf `B|\&hnBi9.8pԭ/"|A(ZW\2J v` o\Ft4Vq:?)}`Rփ(?M^@\NЮB8s٥XCҝ>]07Z.dBlSpy$M j^z!&܎j;PWt*at; W0 *23Q#>I[\d&DX[}R?:[Fj ϒ_vr>ѡ- ?2N_i*pHOY4ݥpyza!v.!]UƲ<Ξ/ū+"16]W+8w2 O>F7.c}uϨ+rOm" eSbo:-ԍޱPٳY8m=x!zC쳧(qc6׷/FEy]Igrv`O BSZ7B٫ >Ea0?{KՂ0\NAdB_:[zW"s  [$zEtkq%̾~X^HAm`ihK(Ⱦ] &0 Nq=~޷<;K||͘2Z$v lpfFV_>S {%ُRؼa-!Q 8Pʗ|׭y"V6^xԋ"4bN?V-O+Ls]sN+A!6ţj١xb/B(^]f!+ 4e{]ŽY-5ܝ-;xJ'Cst8D " nu.dT[ &)~%Mp?O="5j2T=Ğ?IFw2l1(9MOOYԢ?U2ǓE=Eަy>xZ9FLSPhe̺kFt\-YEϻ~+NUŊ^BH{QѽD1PjldԜY!(R֠t6f)ÃD{^1Z ~tu:k5Dy񽿬jnV;T}1Ef]k]bϋ C[RU(3]ֳxm1ZvHI~wlY-pm?%{(&-;]^=Sh\F*~/FQʸ?=ѭ1He[BdoxC I+O(kjϊ??8D wxQ+V#n8;Obpg/#~Q\IMQCH<:%[Fy XOOT *dzia?CJQn9SaUS2|b̠}yl[ג0Ztf[ҝl*NcYu5'( }Iv5eVw1 _ hTW\ZS ֲ3-2gOi4C?ʏpb*.hIۮ ܋?r5;VI˲5XUuW#=SH߰Kkm3?L-׮p5[ē-g݆×ׄb F<ٰbŞ&[Ye(`S8^Of`el+ vLyڶ>yGc`ٛX)ؿ'1n1>_)52U9_ELb"WK.pG*ÙDv6,N?A To79A􈍠^K¢|4za (WsՠN)^ם(#Z72Ҫ<@I aTgna [lW{bGѽ+s,j \{gavj ]wŒ^Ǣ]Zq<=A')H;oʣ*ңG7|B^pJ\ЁSX+OdڵJl/%'3w>k(nPsX> zZltOž X?Wr~:u#)ƇCXr?V2-h?ϊy8Vaўƪ=u]'jH}~Xۮb34$ҭSY c9c$1;,\e?4g acyՃpM>;(XϜ%p4C>.Uܣ;Tf` U[4[i:tLJ"Tź.`˩bu =F`L !&J`N[٪.ŠdX5Kp8"esH;ՁC(8xjK]_´8-k"^2k; ,#Qr1h(ɵjmd_{z'1Tv#`ּ̜>3g0cƧrBl_1yTG.5ܲZY*H$6Ʉ1! N!uPwY^sc<pm_s<3ԇ 'i1e4ݜؼyყio>};'ӫK0;X;gop:&%ŷ>mQ0WY>)wO'.gCI@N>~xS%+w3xgo0w6& ǧ.˗L~_<>VkKqgH:ڪ9ejM_3?d;I,_Ͼ9ς?b6<S9.]i<{O=ۼmܑ2*v-cm QQ(>ϙ;n_0JeLR uhYe+R?,QzuKW4W<o,.pj'u"n3\ڬh^zǴ8rb=wNPOnfl>6)ec_vF[tUV;:g>_.Xٯ;VVNj\).ٖs1swcCt\6vsN.cBs{O0WX6]h,<꥛K<9: 2-Νc)dӲ%t{~44Ur m>20yZ ;u0¥MWPkw?YHQMQXXx 7j̽\c%xLt:DZܦY|V]1q(Ul^3pBb0# z`ض_Q5 cF%`ua4ˣA,NnBk˨d%m [Hx>1Qcqܘn+IȔ)nX,#YE~OsTgq ?OUDt=MeHg]ŹY~ 1D1xL?v@陽^sx ȣObUz +EFqC?ۃwb^rJkE|76JNbMPHI(݃4F[X eBbu<02N I!VV̙KU`ר;xdBLj ʋl\u6{~u*oZ),k72L审]U}Xc q1(S5.;ˆիy$jȸA;Fv+\۰uۏQ\/{;ftNf>"qdz 6J3Yr {NiCP{t*}Yy%I_ņ=(RœzT&m4 c+W'#Db=Hb4iVT =GCihc[VjAK갇0Ω7;FVt+m2=&7a.8kVѩRۛZ* L{5O+47z4TUpOST\\oL%ƻҳ?O<䓗S|2H$2|+ܚ=Wj;rcվmxNׅ-^uFZuvPsd=F,V˵y‹KgnrM(%p\ ks`ǍS~yiחhd(WS%2V-2L^m ouHk2>nCq-0^[b4a\+C꿡Z0[[ e e4L oPdaNںT3F֦,˩?VrC.PVPvj7㫢m0d[D"-tuڮyNnvW\{MwPJz-م;3aK楏ݐq[2Bޛe0|| >WlMdJ|a2t5涺 a^ȸ M7*$x\ KSeh"VD"H$ !xD"H$ĭ|8] %D"H$ov- s%D"H$o5FD"H$7z^uhd/H$D"|9/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$,Bj_UC uknS3H$Fɤk0M]Q^z.6Ajd/H$$ln@@}YubHZvmQWD"|h] [uYb uv:;zYm)xoMxK$;z.4ߚoM[Y}|{%S7ڢWauni[KWɉƾFŐU F!d0xp'ˀlljU;e}ԘM6š4qf/a!IՍRUӱ@iG Yբ8u%s.fۡ$*nJ~г ;F+0PjesYf3q)K2bM* BEIlM2vc:o* ]<&>l"Æ IMmf+7K{o8Av3&Kw\poPťދֺaYPU}1~>cLq&c1[D{?ۇwi[+{Y~a&.۶]v/ 3e1'OӧTax`Jg.Cϕrֿ+U_+b^`W;έy~ckA;}93f% TRW>qm3[4FNn]%8LL׾^d ޚŔ/N xw`maX9kkcKڷ_򉁔|7?̳(*9أԅ_?Tnkg<CeG0/t2ww¬^ IO4cXDxڸg×OSKBqd#Oүmm9|÷w[e!ty ̯9/Qȼry3r֫4.U Rv?7e}$L”/Cb-S1*$>Cxf>b# T;pBa]o.47o"K0,4@ÐEsd#=fh4b sHOސrORI-Vɮ"[4[ZrOTD:)%H_6i7Rt|T)hzz4obXbҶcRs?-9~.r4H+^(֖>\}IbY f/\'ŚrQ MR k MۛhkK7--!lj:'}2]ixiOs?VөeRRoJ,g-;mYRRRsDMʌ=.-3WqN_'K^o,إ#k9?,-e?*T^{>[^&UܢMf?Hm)f3IlZ$]= l祷{֒*uƁ)xވbvbKɉR|\RlllYMRF zh/J )1wvݿ ,RfF7)KOI^"]OJ߯/,n`tR):e0lO!],]|UJ0߳w- )Ә9h. Y)KJ;̶wӿ&2%!ɐ2\U']+%$?`䜛3cGI:b4qvĉs]˺%Nrtb}^hjCX^CҦZ`4 (ը5 #HOH0nwYt7GMٿC%q 9}sP: ,?GQ2/"z,xWj!}"\]6oFDTIw Ɉ(vB4jۂFƏ0Dh_(h EzŸ4٬F> _lr[VQHH"1)KnkUбPz6du%7UҴR(s\78yVat[{v[Z1v'Ji\DM:eb64QpBHT'I% I2hܸɜ!?b M3l@BpdШm3H=> m?<_&Lc"qs9>K֤rK^GSiVEb́+RFcgI,9_q ֊p|u\p!_>E60ɧ5r8?6W]> c:cWfs}7ߐ+o ӷݺhIfGvl =M=y/gʅ*dV!_[Jp{6¥ Smܰ ;c͈'Y]LK)=6O^ƻB/Rmdgh;;7lz<.i{[A:d$Tٺ6ZfϞs%K/\HzڛK{شlV%ڐXA]乏?ei%g^ֺaK֙:dv슥JxWEجYhܸ1Ṯ+Cм\N=IDZ , őL$sQ-R30u\ 9W7fS1ds:M]EɮOhEoe7gj2Xyh*)/Y:tWر;fV1t)KfC,]Y,yhƒUcH2R19o#sf,DxmPԒ BR#RvYJ93 4bj5fa*/3r3Z7\?!@~|!d>BBEHDU%;^!_"!"#ҧrs;M[ŠSv䛽޼vBBU4ۭmHˀTvMm뼚ƭf/ Oh~4?z{dtYW2>۸!Qu~Fafx-,Au|7Ӭs'Rر]h:L%$3:kƑ[4}̱1cYDl!k/*ã*u(WG(}{3hH^hV҄^/38g6 -ek>qAÁcJ3츗j¤?0E#5͡ |Y.1mGψN-CV*/by}JZd7 ;}c,Jr2?~$ Vͥ3d[4wYF3φ՗F*ck };Pŋ_՞L(wZ'1YڭxoƤo0߄MrȫpƁVk8ǒXh6MO+/BG sf>&"(R4w]F|@5!+0e@Bf,JN˹oG;lVqp .0kjɱ~٢%;6m[f8ckNٴ]pmKrPv߆hcUѴUyvʟŭHA2ThGRi i.]S"Y¦Q};G vl"ѫ:ʥshOcm9)V,Mfã ]nUQK=ӯfK Ҭ9)`ɢ (q|VqGW0Z+V,Ow io7@Vx3jxzzFM{ 55$bdL֫K {œ^EZ4!8_!V}{EnR,D֍^Oa*Fեֳ9KRq $ͩ,ԫbB[ xDth"ܳ8w.ÉBYxjįde5G"#{Uj%m2j+JԢqxcٿ HU*{t*/*ՊQRd^=Y !r擛"2Q^#V$av2h@I?My+PzS~Cj}>> ]p!dffz#,{'wƪ͇9$7fm$hQGשgwݜpױz/KArhLfeĸ?!'ygBʎ_+Ճ|9YU!ѳyU\̥mOl9֍9\end]Ő.4-+d\<[ ti<Һd\`բ8socŒM5Gu:翢9"n9kܘ<,5r,u ʹmxjk)U>K֦S75WY7O5FɾVJR)XS⏟Ǣ^țkruTaZ0V W0^72&v,p!X,kГOzX^^+?*DvqRѴ vs~t9OqGs%цѢ()ʎٌR,Yʊ\*g9z<1:[F1c^9;HƎ␗_}?˸G^GBa3D۰YC 2gӼ2)~blrlº.*(݉;e/xn /f7n8ZPxt̖_dȳTş$8{,YH!4vo6G0d*РO7q ݐ2/0oIѮĞ|,QK]޽Z] Go/OVyoxЩ͔j5/o퉧(mPAԱ UGzڵ8¸65H;3T,_ zw7-d،5:);Zj[/(ϸlßgti3ЖIơ|s )p,ɓ~j5. SÍmSx{o(_ܷ 3)ݠ=%Mń~^TS%p _2t`TH DeM$jXRӕO~Ĺ}+͏yѤe[= oo7Y]-4if#;v`„Wea1u^Yg-BAE᜽nd6cZ";ձ ؿ|[Php 9agAϒ7eGMVy}\Sm_޵S7TGOg^o?fh1{5g[M|AYYvЪPșZmNJy+Hhom݃K/v/ۅNRłyd AXTo|3{cŖ2_jB)2-_.ޔV߈2Q&l_]e2+Ѿ_sbߐ2̨^K1f,DEZʖ7e`IG2 T סdbqDv]kl8#FTőG?c29**c6@Tm%alAmhӲm>BH6u[1m(s&}Z᭗'ot^ <>bC䑖d\]Z*k5=(< T-PXʗjkjx.˂MH IDATr&5Hٳ})jH&ҭjvi/|9m%RDy.V![@58:7D4}q-_N]\3A|[D0<bJ́96ш0Lh<9jV+qhwʵnGHN2Ztq**5|ε|E+¿7U9D2 s@z(Q_> LgR@ʕ߳hB xWCQ. Hh |CꖙB(nGki #nKV ./@|zR3EvEgYliT5šKsXReg[eK&RV⎟?!HK-Lb[Hj\?8]F&r(P E@fcU#˝YňUjټZXmrnAҠ!_aaYE5ٙk,lzaU"m27 a$U琷7"P\ةU-JC'|:ZexaMOAnMWV uZ.J䐁EnETC>3M8lnY,j4j|XHgB}d \s/ۜIDf[U R>KRjح1 .-d,[s.j%DӣJt.ZD4[0+sQp1xmx!keѣ^^Π[a`SJreq3]X8Z(8^B0zy|Mڳ1&9SXr܏g|fe )1Ĭe?ӿ +Meׅ֭p?lضt^ӭnϲIq#z\ _L)X2ghWA F=i7ֻٺ?=!SEʹ=n6z4sj-FҥQ|56Ƭi3Z7AHy5 OzX|h_O mNr5#k%xl@EF.e׎̜yGCBKc_pVFLHl]:k5q2W&Y~`mBGQq& w[x㉴(ȸt>c ޘ'Yr>a$]'_.gtnZ@7ne7sH-׍O!YzNX9y0FKiߘ9' G|Vr NG?f4,]+z/ co$U@!cLyl}[P6cIV|?UyiXBy+ Rϱf:*IL,V hR=^ ~%l"I8'`BͨCxٮV.Z*6hG \mjm9VC=+zdQJL>-71?cHEvq-&|N;E%ګ"c?ˠݽ+J!5~ u&j(\Fm_j[~|}7k(LZ(IDS:UXC?$s;  R,ϫ# f:(< yZ(7:O`y;馜TR{H4 = *۶m x͚5qՂEMxk0X}B)-ڱ9?,ec\LH#,uϠa<&"BEJ>=-b9{JPG5{ cWH s-fcK-5[ Xwu~ZN)D֘A07f+Jc,a+KdMjuhqF C˕F.q hfN[Ȝ .'fT[oؓ<ּ,ZZO{@iɔk2Kdf?q?lZ5}cZtLY1iE܃`)3ËX#pvnjjZgbs͂N4. yiQnE?FQl0xw=z4e˖M:3ƿdk/NR+$<i29 ^W@$]'-ӄӏaxwfh9{5i qdCD Qߊ]]$F8ndQh ]!e0fWRݳ]6L$%ȾjB#}h7ctvww'3 "<Ud a2 Ώh6*Up).\ K/AQ|.]رc ({Q -nϋ |0ߊ\J_ɡm[CY7\jhjIP ZS>U\Ťopo i{2Kv; /_{ي}2۶0Av=O]_;]C.w\x "!WcK@c^<4+ i]gRyW+ .  °M֢\Y)Q>yz,>UEB 9fQ5'""" ^| ŷg\p\ I]|k6a9oy滕a9Xiva^ q/j .BjYKAb{p\4p\4pƟGP#'_rq\pXiv?HWiy-o ;ws}p0|/W¥ .Pl\Ԋr 9}]43h.h.>B .BEq+-.\4 \4z]x\p5~~UI"OzKw\pa:#pg]Q,Z/a=׌OWKw\p!gF gPZqV❋9/qu7E8X["wW~#sB|'  .BSʕsQ{\NbAvss/R9Soڃ@΍xdSVy†S~JΗ'/?LiW蔹 .}bV\t/Ω? {N82L0B<5ɓP2"_Nzqa3w^O\ . Źӽ"g.'9$Ìx?ʠ&_޹{i/*8Kͯ+gPS{v7<;SEN]w/'}t⤱ߑ4>쓙 ?qM#UN^ ʼn9Y9? >*/S;\p;/j_@~A8x7"oKP>ND>p!T0v=H='* 8DF;6h9q>~{N8eʯ8xW5 .'uZ=<<.JPYnܳTL ;*nA4y[V2V\@VϞ=|p}AJY0X$+r;I,/M);CqI_qLŽ]p 14wm)O8!_#/~)->;Kʃj ^E 8釯kc 3Z-ycݬ;yv#}9'M9 BewމVvڔ-[NRn:lقhKV;w..\K.jJϟ?_N(:uD  RUwu/r4^5X"bɒ\%^GUz]p҈O6W" -,W ;7btmzPfJi& hKNB t& w`*UKX2OHGJw.M- @o¦HH»%yHMFH_:8M|Xrt6H?ϕ$=nϣ( \HSdtm >-Y*Kٷ WCt4-pp„S9߿?f#44JPw̙3ׯ'O$99Y>}iӆ~IעEZ* 2hРBzH(p={.,Jtp~}v Nd^)7N0w`ΝtO*yE"WwNi4#Ƿͥ]_:_WtԳiOSᩲNѯ2MZ6X~?%ӭ\EHwW㺶Dda8=WX 1{خdˆyޟ(U$.:7ɺɄէ"%OcA m| ;vp5ŝ:ȮJxO&wU3-ymJK׹]lAג}_xv{qUVO' ,Y~UѳmQ4A]2aD۷7:m;qDuX/ཙ{ $K"ÌٻkzG۳sjʔ$K$^]6ģJ\.1.R.|~mZlɂ x7o*d+Ff,/|B=bU&[g̘A*U9[~`yƜ^#jo ˗/b&Lp_{ t~(}Ѩz6T^bθׯB{ GeqG;_OéYG6vŐ&$zK(Ʊ8I`lԑ!VLJ5^^'R c'H/< Z씬ޔ=yvVlhѰ V%oOmgHU>Y *ۀfXq9C&QK{_AA2aѺUmnMY u$2؊bsB<0ƔMMٚu_|mrD1VujG3_q)w^ AvS<ҤDP ۋpGtt4Æ ՝ʷ k?̒%KHHHț4iBll2##CVE!Q*G,t@ ua%|6& fDyWաc*Uޙo(^ 03d&Jz ]k'H%>f+myoRWLrob'.\q>*$WCq+%~~:2s.q"\QWY.p ՐZOzFt]m;Nޠ)iOݥs.׋BB5#R`>{S<ɝH U2x*{r~^~8VmDDd| NjS6 y. vJ z?y"?a{;Gy=?GD]:EWRvVmۖg inA -]KWgL}\I[7ybs'dѦM)vn9Qhxn#q_&>8gīJ$p8aDDDиq\T>}Z#^unٲe$&&2vF}N!IѪs;ԗwGw/փ-뢰Qdt È[pmkoVڱmoNJR3J'>4ཧQ'>62nkӉҙGtF\ƣkӒ36I!Op"qədsE.\Ih\dUhځi21^zv3c: bNɌ n#.m{gl*ee%V$Q=ekg#1-6 `c]߾YVޱ̰:r#%:vPҺuk>ss)d~۷W^wtMv'x7xݻ>ǎE;Ki j1Jz2xnQZ* nGS#a(*Y2KՠR) 1^4}=}_/Ħ-ϳ}AEj+8ń١jɻSf2Q$!o.ifx%f%S /RA#Jkh!a-Wgc)Քu{k9kGS1͹wy)1Wf֭k[({sFeZR;0cubnS>f2 MC ;B 10ޜXLٚW)ߪ ǒíl m{ރ$%U%ZFWFick6u>|w2GS&M~t!vV} uT?Swxfg,%i۬,D+g?rw$_G{8ʱiל  q@5:%?Nfo'*VM,Ēm#?Qc'bԼ%t B(bޱcGoK!P];^ffY믲?Z#>bBRa+Cn }Ӯ4ȘcbɎlb`b= *E`_||CJpH(" \ g"Gf_}'^ҹ;~[b@`LG[ -JZ8t2$p/iգ֩Uk_˻vqye;&Piݥ;ս dj>'`ʔ)swb~7nj'NDy(- =^tlU}=-vBeXj9K"UiOMLS$m$bּoˆ w "5i<;SzꅜQa3]j >:$wTI[(,庙Pi(W|Gmeǟaw: 26X>λ<澋8bR4[!%1V1P+29]pA(Bq_ִ XuYfrg xK/ӎ0~$ČQdc[0JV$ 0SЧ/]ejcV GQCa7f Y(.eF4.N*#o& Zf_W*UˍKظ5vĘ1cԲO=\A6,qWS[;][YYf/xׇ  "T XPP콀 AE *XQQRCBO_6@}g%lݙ͹瞳aCOs,^U;NǕKnCvΗ i7M nyysyd(st˜疐[MÁ`ǶI˙0n%'=qmKoPX`ߋMoud9\Cjs[4$Zg(?^ƴ7`W?||>/'20ӏ>yhBqyvo|:ӸU+ eSo~+6q/"#_8;vl<2k֬rYS7^pgP5zĚr9爲~{鏱r;^|-^{ >zE /&|OSo+USb?óy鱋 ;[%QdFz(M2K~).Lxctej׮ALn<5HoASrj]jW4@xPlԮJQ%pI+P%ul.S$yƸU.鱏;5 ~oF`Y75c_bIʸvȲT6y;ӻGO_ЪQ[/X _$!" TZ5#X_Ņ\Ԉn VQS'5 O<8\[A2nrs}>}7 봸ǭt9kMۇ٤ {LVR?qI]ծ;Law`z0Vcu;O?緩Zs Ј&NGwX1?qba)Ak%Q6(Jl2{LSM$V"9YRDQ&(s,޿3Y/?͏({Hb|J=i5αH  1cǎe~/s*:Mm۶eʕVѭUDĿb@ЈɓVN09AOE=i"qFLT>+2Ý\6lMdpҨ]uEԳK'sGv'[pà:K圳\jS"uT=8<:t>IJo`DP| ͎%8%M6OMOVPޑ};lԪƋpt?˼D]dI0r?hР3sfE'jvNwq+eGR&g4xı*L(0䢜hw}_>XRԋFN=~!t)eC([VȧFjd2-Ӷm%T7k9P*GO{_9.HX"scDl`j5aEޫ0r1 V:i$9[PZDz,HX^+Gs%FCuJ3,nRkqS:FvL%Mm IhKr93GcDOpƇBC/+~UV4tסji%*}M$D cМyEWIՈGJAnRLO;\UW:H$P^j4M1\&^Y?&D *Ej]WaZimbU#el|O1)4r x(˿rE wT:SeYY(Ǜ0"J>fE1-6k)+ $\rC"4wAb&ͤ8+ǎt)¯ow:(JldI׃1PZq%Plr.;U,x6s%-Z/CyS9E5+a5G sӨ^V+ܯ<%ME+.JT"btyJ>_QSJqi^kTα~POUOV"Q;9j'Z:FK9ϔW!s5!uӽ>G|VImb/k$*X_ϱDE2= IDEP>4 %BNF9QxVg$\NEI@ʝ2pAsK⨈s,D˄VJ|$Uf+ =?Pr9U^kKA E)NG~s$DYL+ 5ZQVDn{aUh%zХT6B@ٔ+桸UJ9c-,f8zեB GxD"ż+)oZV(rSVN%P,O*4. VnQ˺gLQH$D*M^5{1M Х'-a_"ԃ:UW/I$D!Jn7^+f7tI\UT? -v y2J|i]ЋRd8_! D"HT7vFBa}'QTFp OQ(:8H$K}p 7zѯ^"H$D"K$D"H$BJHl D"F(gYB$ 42a…[ԯ_?ݮ]xǸ u1Is`&nkI$]bu]9wKjTƝ'K$@rq`=󗮧f>\Ҭڿܹ Gܩ)bƌq\z /-[tcH/~[\eb~rNdƈQgd”ߟp۪ 2/U[Ÿs45s:q+3푵c6lH߾}KZ*UUrZWBh\"&ts1U N\>YڀK3֬|Mp컿*e' ..Yfǽ[ncH$ `0'Y(mL&Hiy ST6撕4G4i۩#16nԚ0n0Y7eӰUjXp87bst:8$֘;2fpWٹxPg| /&OU}_ mM-P3mӢо2Dnў'!?+y6TNNi\ش}?u%l;AjKh]'wǖ|ZtlN"s[MT:a"UXoڦ.ZP]>˷u#& YW KpHwAtڕ"* ?&Awr.WqNߛֽYtٽ{7;v`̘1/tЁɓ'ʶmx"피ve@L@ -QK$z@TL;~c 14r_̄%Y[X>}?DBew{oEyz45tf$ɂyȅc?0|[VukSez}~.D9nT: d43oMﶯYyu};A^m5i@F0^E)d#Xh_M,yW]-ގ]ꏟeTO7y5`w;C^܈msY9:<~{[f[uSw<`oThrXt/{,'T*ѩ;P 5є6Mu"E=?}Ի86yDL[Lb,2ʯ0?E,)r cذaze˖Qzu8=֥Ca(Pn䯕H$`0e|=~F;?Nş>+`$CƁcԺ 2tDTk}|bwcҤӫ ʗxgT5i~Ӫ=p/nFtn. 4h sQƯKځnuwx}:}/X2gRMjժ_}UРp ~0>j(N''qI̺R2$6k4&0]y OɅWϑ^{|l≚iZ'r}viO޺O'jZ[ݜHϿ#;Ct)$: }{4>N>UCp?l#Uծ~?&Zo@"=1.'&x"s wm>d[[htyA9xT?.(6hv*.!EuVP&V+&rdolUhJˬ0oȣ~ĹV*'&_=# w}ÇgV^͛}Ĉ4jԈO>Ds$'QwMY11*{G/-{>?~πɬ&<\ܯqaW^_VZ=iڼ cz5[B2o׬?V>BSJrPor]DKͯ'V6hVطaƠo8WӲYr^ՂxplӋ5.> bs}و߯mtUZr8t,C,uUOM IDAT<=efW`{.AD+1VG|DJɚQu >&PDC7 U7M \\Ht'ru{ۓ~o4 7 _oՙfLK 'dL-y?\) 6\Ӆ[D^&WKM3w7'Hʀᤦ/⭕5fwፙ~gnj1W#Z5HLNeȘq<+LyeƍA$]!,kpxΓ!;f;VjpU,'ARDէk~r1U8[06!CG+ls8|NF/G\X+,|K25g.5Ӯ' lDM{Yk]NTޛ;`LLnegpT'dz?m-{=e^ץ\C{ش*J "]n`ȏ0qw^s .cDw3O~34G=FoP?.S(_MF6v3Sft~[~J"#e8ڀʶ>u/O>WHF{[O~YXS/ hsrjTKydOL7hЀ+D?rYCD%Iih\^UKfٚ)>՟N)Vv6ŭ7tbٙnkL87N@ ߆'5Kf{,'6cy4y'`ht/5{2BKk'{ׂYA3MWWrK_\Do}Y|pU=i+$_;AME-<{)x6_|}p=S /\HTN- &;)wڵ8Έ_Ź{Vg:n.xbC< DFh͒GM~ࣸlq-]]}\2s]ku<=J1f'{*Wx"-<&>D>q~f6ѬuN(Y{X5[f?vή?pov\uiT MiYڬݛؚiu&(3;iy~ N"G+ΉgړUshܶ5U;_S9ֽyj܀|}1'>wQη/x1_2k5-S]a3``VF4YTЅG^r>i+ފ4KBYx5P>cőcŕI\$k7(t |R<)omAӳ.o]E^ߎ\"H$a0pŅGv)'o$5ܾ?H"ND"H$IPiWn*۳J$D"H$^"H$D"K$DU%[l6+{>?V{EeBQ6THuH/H$U!MaWehp]z4N%iACﺊCxD"Lxh\CK*DE-=d)L({eP k!DDiHUK$DU , A yf7<)1,Nx^*-G/4 3%*bKaC_\$D h0kDE"5BhRXQD hϵ%y(8)=Я%MwRiQWI+Kdz'[Q{Nީs,h%kۃ6Gv5VE0dE0kċ^7Vk*f0͉UbɹQy4Ud] .Nws{ķ&z/* KD C<WmZH$DmJjUrDVʆS(QL)r_,Vaa(zk9]RMKZH8յPAIoB^uIR2KA 2IQ=h,J5cR:ZQ^\.MmbTX]-mb=.~j@ZS5tRJMW8Z8_D:Mcm#ͻD(]xt_afW|ܔcT1ZBb܊Phm_XhT]9W˺gLQWQ!K$DU @ C4>%D?|E/TnJ8.8i90|Ja KIѪ㌔VHeE92.2YV̮rBRZCIDC'r޵0u*J3Ϧt)%XC|EJsZ^OX#yլUH49&%cD(;V?%\^5%Z((p嚠Pt]Wq&PNF(Qsq9.αDV:Y^S)&P !^# PvYBαd%D"h]6E.pz[U,os cD"H$'"M*šN(fGYBӣUP"J^c:`dW3FF";=pg3:rIEWD 9Ξ]Ira1@|$@Uǐv fJ %D],6c[YlV%`J \CzH$<< $ᙋ!JY$D" ~?V=3bmƬ>aכya!Nͻ/3av<¹xv`qyk5 D"HE0]Ā-&J*v Qh!.㱙 ňq-WdPuRd $O:ucCF0{O}_B'FݯoRƎvO Fs0Ǒ[nq4Ho~ʘdc .߃8 laiڃt{c $ D;fͱFpW$ RMD" F Ƌo.f?s-̣8Lq4nws2Y>dؽSsGnZ m9Xu.'~7&M;~۫|юw>x{W$g(Ly:Cc5<:ְx#u?psЪ:<le`' D"Hth&eWkojo~߈~gwN炄}cOw9wF<'dd=$Te;H4'o'os5n~lcT}q"ClZVŕRPۃ'*UT0Lrϱ|HѨc#K&Hڏ/>ܮ/bg|./g2I@އ;:9,H/H$]1-׽.ܞ-X=b1c !b[;&F˅s27KĒ(| \ܯk:h'f]u~nͻGFښf)jGə&p룍 XE?G{ޮvdD"Ht?#z#qV#.뒻{=vzB&~]A ȏ傁w\{_eƤ+K 'dL-y?\) 6ۍ%n^ ;ZEѮp6,) z9&=6 Atp[cu.ZhHJNQrH^AwdF`$֞a/sDgRn0='⟎ٿzm7~fCξtmύS b5&/`Ԝ2׌O0q y; FzfTUs>}"I'ߦ`gU$!TreV%mߩT2_*+˞.;9p]%NM. ^Ί7t` O{tp+ qBKxm|:t(H cKM27y{z7&p)]G{hlsMuۆspUA.lrb:9Ԩ {Y Fs69wRM+6f&MWN[qele{%47V !ÝK [%? iiiYIIIb2E# |x'21 FL&$ԑ.7x0 wX,J@?~0KᏭàVeSzI,(xٸMl?ثG)ljŒO{om LְXT`'_0xPL4h4rر씔D駼ވiA]gXD#'؄x'T~WN;1;ssy1$&yN2c<@8sKTTT볢$Fl:Y6$x-QfjjM83^ٿU͢1x,~kD -b~Ŀh-϶{lϘύ-KM;(]Clrڭoh߲3P5lR@`JPi!<*E'뵊 |[Wa|,6sm~M]J=ߧ< wᆑu_cr;/~&~ /0b[W֊w?zfqw^s: /5;_zJ_Ԇ D5Wi?&[ 1V\y<2sTF,)k]"0'>+EjUC4i܅umƕ~0w]ya|RtuB6 HR{S:_Øh oh3~pbg)N8/@f_tҥN" ; wA#~IWqd(o~±4  Ҽ2o.)nnזy=MUhx{|:-sanv|˜UG>βYjs7c 4~R<א.llkz͈o]{2ᾯag]"H"nq-o1 f@IEzQ3vlŻ+T0ңAGt]ex>\x~ ϼ-xӒD(6N>s|">[kEuu&" r?<jdD"H$J3S"&4jk}Dh7z% FWU3׭p FSD3W0{^ dxuG+ed/q rw>Ww7+<jZV+h$"`%!.`W1Z1W_x^1h(]8]yejԤ.8x=q=R8TkK'"Q'Z@SdI/̋|i 9IB$Ȯh֢DԎb`yE\/ K(t)k)JI,8)+BZҤЫ.eHoTȩ}o)6ҥKHKɸK$ZFMU+*bfM^t)a0`{L7Vk*f04 Rnϡ)pZC"H$: 4'^ DN/̡4)ђK$QtSH$Kp bkyIKH/H$U qIL^uˋ́5!u;{^"H$DIyաjR:R<3zեT+ǧB+8:gJϺ$B^"H$C) r4PG)(*UFRhS"JI* ԥܐZ$ƪT:*lsuTPtϠ*JWQH/H$U\ө⦃yQI|- mU 7z%nÏ!*wddD"DB6Ę{Ks $rgϢcϛRIoCxD"%J]d5ޚ_iTNjZv04]jPjkz+T4D"QW;Z/pz0NbPPѡOz1EWqDVjz-PMoa둊pJ^>:䱨 tIS6tVY+Xa^"H$8/ {ӣQ[o(y9drCas,H$D(aHA(R+(M NhshsTH$D/N0;%)VB; 혧7EWr% b2s" Ctr.`0^|#<=vS\yYݖId<*`%SjqZ oo:_MZOӨ|x^ֲY(ihqhbrGIX"lvv om5\NǞ7qycXt1oN'[TX6b$sei+{q+\ī=2Yqdꢿi~ŵ\8 :/Atk?, 3 o#Ҙ9S!t }jg̛}tfվe>ˀj쾒7XwPKޘ'7/5Q%M |2/03 O.6^pE_ 0sZ79 AU 3\`>4 W.Rαd%}(ڱ-$T&f5bc1gobŊ9UYxud0!sY4}sOq#6Ɨoc8>XҹgG=KFCj]b;ڦPb"ϭA>~=ЯqfU균u}~}Yq @YJD9s(m/֜qٖ_̖<M]W %mzy$^an,WTnEP4)scDx\B&_`lП{uşE w==x8r0_Q̤C&u`xqNچ'_y6.Ծ^GuoDhxnU#`|6&t! &?r59hy$ FwԨo4k?͒Wp(7{Q/hZ`/X>Li3\%QYavDž#J=\cPK$z&Uq"'`%6:֕Ya^cmKtZךh`޶ߋ+*=:rHׇ`;YX; No+όogFF K-$_@e2^?W.-mkSDT&gz5uiٕˑn*WN"J] JE=н>Du(_@I1CzAQ%$ȥ'UL9s,TbKŊ lO{3ሪF:));^|^<>?Lx5kŞCbxn8 &+q (+7|`Dv  R<g69/ c1ʾ] O~Y+Ւ*ap;X n:91+'%{Ȅ?j-Mk)ɕJ5BhRGirdxf>ƨxWM,Եt'x}f8;3朵o£U뵌K$DW/|~9!\dfBw+Zd.h1 nEY*΂<LRJu|N6*ildQc*S3F{J#*>ZZT=D5 4D"h B>/n|H$FnbH$D"H44D"H$^"H$B/ uȞ l! D"H$^ |tz_g^}h3RIDCxD" QPJY:?k]'GA`B˛E)?#4(]ŕq EERvT Mց]0&RFeig7G^7i֨WV 9m{gbIKuIG-ꊻ2+C.4(VQrEC({1gZv]I(B^K޳+tgbpbT0 g>dǪ'%1j~c?A'qf[.F'yv=4tiDrP)uF-Z@16߆q klF4Ӄ.<OP㤬,(>ZDh RE{.NFčM{q Q?"=.j 9=}=>Lteݻt, tgѲ^e|.&}/7H$tVQ1WjNPn2yƨTR aƩbv.-iR 3@WQ&7TEWQ1c"{:q5GTJXraˮ,ڗ”,QD"/IQ\ߪgH|h{{5MjZӤbgǹ헨!෴KvvbsBhKNZw#yr-\'=Ie-wh>"灆Z4`D(6fDM׫͒Z ӤEMY^u)?M/ѽN4N0u]*E}{h9OgoM<8cf<{kfeLxE.ۖP9*́ZJ/ޡc]^KJ]DEYٕz=n|l`$mD~= yf^ލLYcs4K4&\݇W? ^Y>#< 3$OI6S^N'1<:DąLlDs8V7 Ƈ0.+(*Ntq4 ;Z01ţEX B+uu].-TDWQ&o՚!s粯oia6su+R \M;4v|o%5 crV./RwW1DRf(&WF4˪S!j\1hX0( ZW\1 B͠Sl M7]zUتtVF:L.pW'}GrSh.;4x+NR!L2dVDR" 0ucULVu)Cu)QD-V.JBQ(U»j]@|ޔs'-6p $ iiiYIIIŕQB!)ʕE3'Wi[<;ױcDzSRRtp Ezz)7w-_+Bq=z= e( beHQ2)H$I)PXNK4t+\:/JOHK$DUK$GxD"H$DCH/H$D"hi%D"H$ !KoK$DDьb&s7hLz e,vp{j1r8ņ99xD"TxXblE,O7ڢ>Aaf[4Q'ga;V,~̅ o>xcdݦ'y{x2eU g_p nuKz@F%DRجMBjI^uEяŞ@|_?|'_Ng5MdKgn&UɃ#muaϽ\@X<{8{w'D&]|2n^b'UkW%3<;kZJTƮ㥷r(߃Z?ϐU4KH/H$]TmDG1!ۙOӋEɸ5^|XX~|G 73=TKmiَ)w3&ዊt3و  U;ʛcbܤX~q8)uqAxi~.3{'2Iq䕗n{& 4d#4vlgf]_=1(\і8{B FO%5%0cY,c"]ʰ~ql[䙟a*zʖ2cɯd-86B^[QH8rܜ'^_&O`_~A:Z/ZGoq-<~1?1+Y2H/bSy/ոƾmTHIqg匣i~^,]L/BZ_f?Ϋc}RU"Q0sgˠM* 慧gW^ ژ=?|KO<9U{.a Й:գp9c}^'*{Eę8+0|nb#ٛdqrrD7hD5wuРy_ٛERM8 @]1O͢_/oj'8z Ǿ͒jСc4= G*Y M;ti(dς#`p oX+Zxq/L͎'"rVO?5=pOߪ{sabL9G|.SGзs)Ù\-#ZPIߞ] RK}nTOYmZ6NI ei'F.V8/&ly+Y_.<۟}vGuM._vO|070/@hMw* VàĜQ~YMZ/(ā=fl-6 a$-!}l_rcAp"z2Ny!F]-CK3wCa#Oq3a0q ^er@$(>=|<{͂92!թ5v2a"ɵԿLYZK0k/cl(ݑ 2㨶te(z҇AKzJ"Y$6I \Ey&d^G},NDOĈ /"t\@sc0nϿx\j2qLN9C?}gMr5S@ 7O=8\| `zy~loߤf"vM$(>nD! YW 嫉iw,'TH s ,_ӈ^Hb:I7窻ưb}RH!F`1@2LDzx7yq!͉Ghf}밝c9-$]{ѣR^eCo.?{.nUq+Va3IOSLb+++VUVVny7EcSlVRk׮A`WV\FݿX,ڼVD<ˍG]w,T:xt:bM7ϊҶe2PZVk *PPT?uN=N8"rv>([T \|/P6e]F=*g֜73#'G+o6Kۗ,%-ړ SBWOLŢ?̚$u5wf#S%d8,ն9N:d(QSd(QU3{kH%  86 x/)yMѦDڊi '7Eyf^lL!cAAKΊŌ{sbN%vk'ze{K;XAjQ TZ މbLH;>;ЯA-AN3y"dz+MoQjz>v&f uqϞ+2vmAEV_9>e\ywH&3Q'=au]f<'${ʆ̴NLXaw$ ^AJgV( lFlfje&>?e [3{]iI.E-'"AK&a%~Yvm|ʘ .%8jWsAJ4vQf={݉velS 7m5¹'Ab FrRv03?)ޒ@w]dxvP!e^w[Jc:!׽%p]-L{gr%D $S bqO9":.;Û"5YIծ\DSD `Y2h}թv)ɦ|viSڇyE %k'Ou.w]avYN&v %13K%V܌'XS28%D]k |kծ\b%^-JBx% ah4Zg/^xgG1~a.y3NVڳ BK4j+]:%ӇiG(;69.cͅ\3>Y.Y_2i 0k⿎!t>{Ja-ac~s8xTƺy|۳i[ g-SS 폵b(f>@Z~Dt+ʮgw{jE"-g>GhܖCeItr^4N# Ʊw} ՟J 'xώG1cZϞ漿=ZVFr2YNy>Y ^հ^W[7U)  lF>Fw573= ]FNa_<6{dhݖa03eeU{[(^j{( Z&``G,`|8箻رs oQ9{?d~`')cnGh?@p渭"AO\n.t층,T~l H`Xr4zXB4C<8Qo>{r}~qƄ'%'*.> C`5R))#AוZ@S9c+χڇ PCGϓWbF"B~g8 +Rm:pj ұ1v)JС:"'tgp[ :e}ޱm܂Ky7 `>ѿ%|y6%oyFDZ4ee,3Ǿ`GQ#f9Hsy(4ĝngq-ТM'Q`a;~:g=;څ<~ǭJU!LOW~yXTQsW6'x}r޾#/B!v=N.?tq\2^zx$q_u' tN Tદ\CnaCq%M}Vy"tL|c${RTXi48PH/*qaIIp{5" Dֈ(-'(B-c] j}9}wV}^v!ZGVo~$jݍO?;{8.vUyYƢ;oz[gm/?:cD#QhiCT8DcG9}*tڍ2o7@C Q1*DOe9GrMIǯ%=9m!6y=wU /%ռLy;BzG4@<>6b%}q0"K3cbAc;F\z̽BlZU߮\q/_ 8dۼG`c?S/˅ؾۭ]=EQ[*ڷ"٢MYyESVط(m>*%v@y}ٮk~!&1OuGům9mZ^m ,i}WÚ:-e©ZqVygD] a ePu_1~[wgK V04 xŬ'\N]ŴY_F+kۇ'_ߝp+؍rXz`>x%13ca(wPT%9} k.Gy/8kl&|Kh58K礼CLO3T]zd-/ F" TYd9U$h"\tuO**( ]z2֬.LR]{еt~j'B߾xݽox;9`yR2][.UNeq$ %~E2p0n\B5C$ EQIapx\9GgfltNYz\z2/VwuWv'Bf-51 e{8t3z ůrFݶڎY4[vt-u7!q =U ^App;.x((⬛a;@xAbGp#h=L}mڋri$" G,Dc(L?+`z5=A,$n$ӵOT0/fG^öڿ8K#O$YwWs@;6m?'~?f9뚉kՖ!  jD   SLkHC ü@L:OD'Ē}xby_vIiASALm^ H ëi~͑w`0HҰoh}-E}'pڥCm U\% X>/74ft]W{"K߈L^|xv9`fx[B`j\[誢yΔVtI_I&61D #IOOUo36:eѴ/m>v6 h~*"AG xv},v) l;d!-–"g%b)ZsNAٞgjohP:8e40 veۄ*3Ia.cEx% TpCl7-Je3fSlgK.6 UQI-ڝyFe/vk˴Is9{Θs[fRR6:>R/U_C2cslc{͂`UԽzFj|)1TvHv)~Mgv}+[:6E3#ivf-UQ ǂ lm0ŠD)jUەmJ~[ee[^xkbGo=̐Re\Bej=;]NiW[v6K;!ި-7oK,Bcx5#S/% ESɳ*d)v=v^šnWK"7.Ů$A򅙃`7I>OEC卋%SY6L1 k;PT2)r[#ydc]e>w]l7Nl*;Cdb YypB3/)i=[PEk4^͢H<-Bv٣ArU]= MvU:.C+ؕ6 xS; r3ʠ{AT 6#@MS\{jZNs:5ah72綆]j\3 iu:W {SSiQ3خ*tt|غ0]{^dq\fQHg+屶✺62b6xi.KV sAAAbWd:.%vV3$vKi:>k.ݢREׯ?DcpnŲzXbKq :%&|&Z%ؿ^o[PՕw d{Aj,2E)f&^쟙vgKv <'®(Ä`j{vF=#K'nM7sSQ^nǒ95_DB{$T xn3]̂ J7ƴԃ$?DmK.S(ڹ"r i`r{lpB ve/@ܚZC_xkOjG]*+MaV{)ԙBK>I42m,$ZWM)bETNBV$3';7.Mnunn#uMe`3#8iM*\\|Rch )gKĻ luĝPٚfpReO-pYw5Ra3&nlPxUee|JKgBbĖTta(Ic\!v 52H(Q}q%^Lj  8uOp3w m( !^AA%hϪ-eD Hz#1omV-xB# 6Cyߢ:ↇB.UU:Qg~6h A0ttwfDd妸 ۷i7"X\F3Hۢ-io"o6^Գ.JIe'fP/ h~$%Ņu*Bd"MeGÄ#@(?wfhG?Dݻ5DSx]В0t%'պ}dz}U>3^YiHR^ kwp0l(z8t~g硜W׭޺-Bp-YgUN>r7>2loOTC4Um^_w^e.2 6xt;lSՍq729]qP7P.څ|]O9 ]bĽt]=A5|ﻥDU7>>֯Zʨ"j>zo>ZL7R_"̄n؃%Bh6DK~,ܿAYbay0`(ҎN^=z7/1{<r&l:]UEqIR" zΩ>Œ7_f1mwO#`H2Ƿg)95'A0x):|Z(l._x~\wiϣ?Y_0Q~C7IZ " 棢`vdui 1y+5w]_gAP#y^xKzYt\(̘Cqé72Gy}T.?g:EWQ,bv-Z$7bv"gO%@@ٟI^e{wv?wL { O, AM"9[ot.R=:>n` :hKrvḛb]cwtpe}ddiJw&M%oG!<+߁bndǽ _ ͨCFϧg^OVCQ?>8v+(C_߯S]3odA߿NwPd\%Fqy<7,4  Gbh.+?*\@7wL&QLwGCy³(D8S{}8{^MйƎٛ h1,N_[t5FqGHe]sChTk`+j r~Yq-Fz*dW Řae&J=.NJ֡jWq2>74ơ!J1 0!jFtD8f`PVW%̟/ }m8WP:(ʊRYhgFzӦ]a3^g ewrU׽jeOzW0y!Yh>Cw 2ǐʢt kÿ>CPWμă \9djxBu=]&X@]]Wω\xnDꨩQ5\!bH:x hA8b~'X/HDՇAI=Lɐ=8mh$oĉ` KZf΃wm9pU&vrwŜw:Nq`30*mjW븨0ey\I8+osfMA} [q1 <0IDAT=;:X}WcVw^RV6 2r|)P%wAh*.݈KF"J}Y>L},WsU*;XX8H毙B:k ό&Aͺ:66d=8aF~=]ٸȫ_ hψ6B:skXxo3jJ}&rM-ВKɈoa#oqxj'/Ň@mut,].W`*&BSSЖ+7 eC椾ʴKkWU6IUAM;j]>DSv$^{EvDBG${hT~ĺSRVl}6>Ӥzez]v9Q"E2lc0 nfyFeS'(N^gItV:֊#1DQ[y T"ӞiW,5L/Iy& TLnS6&̨g/`_ە>t+Ib7ԨhhnoZ`J=ꩅGB𹍟+n BSЧ@ NMp>-,,LMjⶲWb i-L&S;.2Dycɴb^M4y{*Rmdhؙl頻9%~( )ם{m|C=* >Y,_n#e{bIShr9TLQR5ɉ60MN_S~[|D Ss{pQMxzjR[qjE$ubɶA;5kRk0L&!8imlcx%zact-fX-qdzj+uF&Qz]-:."8fxē^C2 N9$riw6ƶ9xN)ahg\lǓa1`iѢ͇>V1sIRWy[C+վlڂX3*h3l  ]o*tU2sYedGfz,ZZd~.،A+ CcpNJگЅMa4o:N-wAAp$MQۚ.*Nsv̖W=^i\A8Nlk:TxTEۆ  ؃J#-o'64nްZkÓ:n6h. C B7[y>(lBPך7gϞ=A|<| `q& Ki|IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/square_root.png000066400000000000000000000010261423020056600316340ustar00rootroot00000000000000PNG  IHDR;0IDATHKջQߥ(PHqūHxF=*D"*n)^J!HHO&㜙o=4笵k2Ggjxו_9tKJRo <&\!Kī)=a0rwA[_C/2 GqB类oۈ3fjOq=Lcm|"T݌#gpoMM1!}3E*_S*#lK/U+؍d ({]q[: 6mӵU{B UlMrGX^JK)sQ0 ,G,-}$0r4v+cçpgSW2(Qa88ʅ[8"SJ2?2Tgom%W6klX !}]=$O9'Tq5(.)Q.IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/standard mode.png000066400000000000000000000761151423020056600320110ustar00rootroot00000000000000PNG  IHDRZ2| pHYs+iTXtXML:com.adobe.xmp f5vIDATxu|nݕ$DR\[JB[z{oob $@Hw]9c',f<#9sfvBںe%%%\o!/0B!$8@I0B!$8@I0BY_JY g"PD@A h@XR`)lB]|gge1؞3⁲X  @%%r[\/Î Bd137Xk<s@\C>72B׮X?kA&+(DPa5< ¬}󎴧iGX!{gۤCA1eҡFV3>0 Ěx˪Oz%zn˪OYjۏy%eƘhd P,4<}O]Ajn : Sk qDqPg&BWeg7kjq(_(i@Fo $BK0 JJJg h[{@ ,;q'sosw͂`]/0 pq^3k;fb]ܔv_4jX +zP4Z,vqPspA0EEXT/  @Rqi/%0^5-&HjLHݩ7WaUiRMw;xd8p(Z/8B>"] .=GG :Y(l)|9~=@ˉzC,0c'i{SB; (8O+@ÝxBSjG1?rb~)449dQFioBMSjCip@!Fk{?APBzGzÍ P.Bk\Fц7_~T9xBq]VLrm(xQ4D"H*Wwka!]+!]5 ͍ꅂP 꺓k~J)Vh(#Bz]h꒒RI;q1!D&wCB]N_4( GGG_!pMFPmB!$8@I0B!$8@Idg!{Z! , $;@I0BY@Iw`!$BHq2(LDe<.SI­o4zE{|{ӾrlSS-|^iSS<g#׾]&\|SZIzWatpat3CZ9M![u{H񶁣:؃%t(ǁon%>:MۮyWIUƥ;6Vzp)Ab'"\z'gc'U|N?L|3 U?BͲ>2ٷɶE޸)^l|#|kb{ΫL݁[E;ȑs!4wJ?ƕ>$PN؅9()Ls`=?qUڙs!;Z x'11TJFLZWꝇFmJ tV5Fl J^Y@}+OW<2״%Vi~g8HoK5NJ#jJFUv9[J\ >,ɸ Is.nx(qԢE )!Y*6ܜX3.E*lJ|-{`71 4V]S&-SJsRj[8{؛ f&̊\/;:WzMY0І08h n]Q΍Sem't/&C~^. aI `B0P_A8Ok+{FS[2 fC?>ރ-O>wD8R~w8AsyKɺ?Ĥ; 6.͛叭T8wа3AEOfc|pg :',8[qWc[lS!dIɣ(AC޲3NF6|5ome1b`3I}v@fŞz@=?òncJnNfS~4U{OyszJJVZExkzMȸI)E#]1;ϞH?܀Ʋ>v.f Sl]@v픽Z>]aKU] 2ffFX* ٔ0eu5XUjU/J;⠺}z XF[7^9s'};Sl\MTNLm){* ^y zq`lbԉ6mȘ~7ڴ"H]s&"dv*j˧}LYbK=ąoSۇKӡ̝KqS$Ujn08@+㶝ЎO'`>AYYɈW4\̵5ƶ.ޣE 0|En1g/_v.Q4u <%:٤ӄ 3H`aGtQi2nK%6 q@RSS{k"V.88ouudH_oS f(BHq` $! BHq` $! BHq` $! BHq` $! BHq` $! BHWRF$ 8B}_]6̛>:Rbձo<*&>5_ed?xİ`Gf~T7.\HUL͝C"XuJE\K$'݅!gbd I혰w:|>Þ9RsQ @]Z- 9~߲ յvTl<W q?bDTEq޵.5}sfݚ] =5UL>y[U ;Jeu\k<ՀHvoU>I4Ԯt,Ih-{CnQdцǿ/{@p7gC Mw`gbi-ص}-ko{F˓mqhh1r4mJt 7~LLz$7\9 4Ռew>!f]ZMPޔxS^Oe<8)>V;:{L+@ 8 ́͛wmr߄K'޸"{ VF blN2K431q1\.k2/=-5[41ja]X+}3#, Vef֌$5x%&Y|-9m9d`}wݸ=A9gV(TU(j5Ҝg'2po&/li0qԢEUqL]̞̃@i!G-3{u1}aU~w?63/r fhfI `6Zy۰{;J7,VwKeϭj@ϭ^y<mf3­>@ u""(/e mfi9P"+s-+ѕ /#h3E,oac3a6ۨB9`[KV>v7mߨ& ۻDz %jE|"4ϩ K=Q['qy"t`uG[Խ);dMQԢiES 9}`A&X6yKZ<|`7`F0xH O=d\}pMҞ;FEB̚BFtar/w<twvb&05O dN٫MWZ|dÎx{arK$JgD?mP <=,2axsiVشImTQ므eD1019#.8@Ĕ$2WSU"D`9SqvʞJgkrk L@8BDG6T1v`)Ug\̹괘K~Aڰe9YeLoex̝|:v6*%ڞ D(: -hm'#0P0r|bI}:S?;b)n Vͭ"9~eܶ@`jBjFͻ6?0U %߼/D tb8rIuqܱ Rd&G5../rی53.[Uo1st?$xq)Ns֎͉c-n8PlĹ<9x ;&fW1ުXZ;`"_ㆫnY-AlF@II/oPsQ6Bk͛3؁`jqCJK3HzoN]޲Peag˟`Kr{80Fxw"H 3$ @|63wUꯆ0TL<#8'><2w-g4 G_'3*ڟ$x.]ϔҏF OJ6'/xu#k!Sqw^Ȅmk~ovN7z ְJe칍|, R#ifP܌~8:|@Ms;\ ZV(E;P*[OSrLY%\P8pȇEG@ ϗ6hs-d+O՗/{=6GXX5hr@\'asf1UkPsTj<4›o>Vr-6xL;#K ^uՋAsb%< ʼn>1S| )`q_X|JdfG'ɠaGQs`"pivϺ?Mqb+d`9Ẑ=>;C:35U0wha#د pWKȎo#O,Fg縻PJ0D. 0KvWhjm}ߖ#>܅sD/9e5X<@(^pTOPJŋbb*a07DקexlS._nhy8 Ft?@ %9q+uJF̣.4g8>娈[MTȝϟNL 1*775y$}ۣ99 }CN*Kϫlu`ȭ]mcυ2 2w5yͮsd\" hF[Ry !0rpha``[(.&E [Ҭ;1'ȾMnteJPXyًl^F Sf+JْR4ى ramIf}#p5"a B&w-[Y5ɢkY< ry2&vP(TJ5Sss"00UU'[X2v c%ŹقijT)^ Б3:;4p1-jr-vhmj5`z&Q8Ơ `kZy+Vr݇Nt3Qyp3K6w^/{/4W .ky9$LlY{d\ϲILa) % T)Gw95 h,ʱ HzQXRBU5I7 FZ<R}G; I "<AdE~Oףߛ ӆQǞU8HJķ⠊d`SY1@(,T4swgz׽[)NX#0R1Td^9w|SjތEӃ,J07oQV~eREb0yxڨhV^Ԕ2S{317J%crϿ2sSߑ i%9eےc;o]' L[4g-c n["&44p•?eW*& #?l4K|*Va0j$z;W&Ơ`Pjdž@6KCY^#(*Wm%r(*#\;!  EfFmTܝ02Psjk학(+6G2 /6XhRL>%zM2&f UWƁXshf:v2*^ޚGM*?˟-;H'cʴ}=鱹, pv'O*~`W޺߰1% 9b=5gtL\T0NPP(c)E7nv޻Yr|{lӭ=DadJUwm$O5h Tv*(Jq'#uRmSM{û05uJ\? N?:7ʼnr~9G׍|hMG8kN9O=&YG{/b{f^Ut]i&<8U QjL%~DliWdˎȿqP6 Jڏepe/'vGXxMQ&z->I/W!M9|ݺ,[CلED y.`DF/r 1bXQCf69H Ɯ' 66"^ٺ4n-QQo3 cps>N~-2˶5f/_hbdKf0k9C?sPaOQU@I0ŸPѡ589{XV!{>1cĘ(U=R5I[ְ=R0P|k;03#0QOf CAb^ Kt c~oq,~'3ЋY_5ÛEkF Ί([]vain.){}@3` v619#}oljPu+3YG:5ƀp2M;Yyxq2h?mZnZfysi'QX6ߜT 8 |En5|3]#F̆,a\߄\aMFppJ%]h&}WHKܗIE E O1Z?ἇ/qF,=^ԫCn5å2Bk"^-LXYՄn&H~60 TMGO:"0Ƶ#SeqcqI>|!wnu.=<%ڞ D(: -h`3XZxx3&Y762UŘd<:ȁ mGhɍ4Q$bac qť"q\"œܬ"9X5)mB{@UR\X73w1oh{$ɞΧ{NuRܡ,w.R8&W3'u]u*Gぽ?1T,dL Ej0AꬑuoϏG'W{#q'KNhC,bLxDz4 Q@~4T^Q'Ter[aP7ʾr&Ҭ|)Ge[nQL+%lܼ$Kr8I!URj5r.&%%q%rbfϸ"jN"yG;qU[/gѯv Cx.CMQ$p{TY>LZ|J}Sv6M8Pt#0(Z|:E ɤ¸f"_].Hdp=-kr`3uˉ# @,ʼ~P8?_og+RrL1fd9bj_B}8Mqǎy9[ W4ѣEjX;v݉iOwxk:>?UOV@?WD~olG,ZCf2U'VU8ҎU&LBRSS;))%\Xc?-R/v^x -2)?>F XmߚeihUKBIӗs+~!CC3 hefWoWsN#GDZĤ&9CaKgbR9s{7ёAN&;h=@sN+1pCÛv;r*Ҽ>-[s\PØE/@ p5OI.Z({t9:Dspm~xY. 76ԃ.G84;5MOP0NnSLq#zM8P&;T7d.rsI O|lop~Ѩ~.`/te "|_ǝ(&rs6&@|xyC]Av7$q'JW0 xY:*!NtBp ANNNg'VK [0H]Qaiaxui:uBNN.pmB] /\LSNY*•j!u>e-u!6%E=sua~aDSpg!; 0B!$8@I0B!$8@I0B!$8@I0B!$8@I0B!$8@I0B.{a'.U29>Ƕ[3uѵNM˩l0ztDiۙ?onu`<υ׻a)K>w2Dlz"j58ba>-UV?uB[e O?_\[[w_U(pV {Q@/4Z};¾w\*RE˃&\çƤʫ9 WP*N|'[YٯsC"Vĝp͛yKcnkB N^8x# ;rUә"$9{jfjv; l¸^2U^?wzҔ! ~w} wݲ_oX9'͝[H:F@,K=z/Gsko&^WwH\rLW׽VR此 sQ;jJ_YBתKcl_C7sgu n_-}՘1n>2nόs3n+[xOMCV#q/J){SO>vUy'أώoRSUU׫s.1EY)7l?2j#N4kvB1۾TByTɥWlC {Yʁ6.?|coǜe t1j\HcvJv]UWVR9@ң8i,59Ŝf?JYe2ͩlo]QE w˲n_9+ܮ#&zLm*ytOKEcw.Ls矿 y{ft/Q`vlH s]‚qn {v |M:g*:za˱ZkO<6̹aM9}H\lBEg*JbEiA [%wxPi(iab[6Ȧ21 ۨyUǦ!3~!Bz76ufe5#F;mQw@>bY X=;y^[s^]hE?|11F̆Jƻ q SѡV\Y^<ԡrc>uQhb_3[d[gAB9D="cA@t;~7My`qS(X}+.VC nRoԄLAb827WY^&2UA#w@,)jakSuO|Q~D]:0 u&]EOh|i〈0z-dJe8kvrV&ln!xV|~{bԌ(͝0}p6ͭۊZVCLUYAҴ};ZH:I52S #*eMxL e_J 5s|{uZak9d6`Je,|2en|-@}yh~% ~M3-s 3%cR} SUW0[wvZs*XAx #? RR-ڵMo[By}%j @L-jdiEwnޚNi{{7VS,Q`t#ģN4;gEoD/4Įɜf[7M,`(g@:4ԝPNsUs`ʪR [I;1Lܾb mJO||_Qs}m:iLYQ8[K)W(m.$]A[%&kY1;-] svu5')qcn.A~a#ܻkKJ`]ct[&I*bp,tܒ+*9o E=Y9CӎNJr:eEYJ94FN@-f3pyYiɕcN%dgk{Xq]YyzjYM´d5blρXyCn$d==|<ÆdaV\asvHNn15 c]n>r!59W)s:Q!MnB%FSgSYpue"5lnõܔco4g'Yt$J7cv%95\HVu*|PƇ8-Q-bή:}x#F/fm>p΢EM5Y{<KǶpE{ivvJYha_XfbjFj^buU9[~TŒ8pkL mO_9so<Ы+ 2*H[ {w=7ףMeIaqYIIiv;.\+ Guhѩ^BujTd_.Ⱦ|⦝!OFW.―_s"Eb:}] FYM\ä38)DSya϶' .hWOy]̥ Ty/YO߲3碑^KZ]?D$`dD}d5>xkG{-N|ZU)Zh\j=&~c}.(q9q\EQv=kw*w_g{[SZvf9wrTz ]n:ţ-hENF5;vⷯ具rlnO-{tވp8O8 \8hƤѾN6f"?'+O+~|lq!2} *\q>`5i7c}5}-l==-ygwAѱRuS"pA:+jFL5{~g?,|zunf*)I;pis׿8{>{e-O "k3.,::=_(ݻ燶5 }$Qb5`XF{f^Ir3G=~߯Ysz50z;!'cIQaլi=5ٸ۸?/Wܪ,bwҐ!趐t!}Jd?&uҩ  Ĕ6nt4s91\]IK(]vi陿6(D&s1캷whq^Z# #SLiT% L mIӃD4~P:y6%BM\f8ja GsDFotLbҙŔLp-\}/!7+w On|5N&윺9E$ZV}cO066#@+UNTqw 0ege>z9F䘦gV[baBe*9Nnba2x'eh魿bwF7zrV&6iz &9c`CaFNXʆSU'Nz4ؔ_Ĝ|/-';@/n:4gifJfQpl򕬴Hή͎5EyHiYe|l@y/&j@3?D6ՓlMY^I%C6 @CK>vi1aiH<\q!VkRxWxi>=ơ}8͌JfQQ`y^ Ӓ plWP~}_ʡ$h hfE%I `BX0xr+I:wPw'r'ISgT*QsS_]߭g |i!͞qHܽyMb6LED!oײ{s,>5>K'1Z31Uh>t]H^*W&3!jΫ5 {-OPg g;4^XqV& :ª s);ٴѬ2{d/?;o.@ni-DaekƁWWS۽}qo _)mPgMlMͤN>WI=گܤdxw'׈%kX6cy/Re_N߯w N\j^%nK\(LDžӿJǫ?^ΦC=kD3{5YfgU$*@! >JKZ:++[5iIy\#^}cpA,\X՛͞Q*3*(dE:t41pLp u1nS FQu'2Un|bi ;C ?Ŀ!PM~ouš~D-#A9 ^xҜ+Wn2~5H*niE̻B˩}=ԄDȊyVÀ 2]Hgq@ˮ )=jnX18} 2of2vO6~2'vw.B}Y]'{||pVR4<Ǜ:,2ϛ׷Z'@[6r]8)K& 6&*@{#4TW2 f-T~˙"#~,Vy=ATyҳ ,NyjLGGol1f tQeN\=1cq&6؍Ӱ:?vY]Fh47ػlF?H>{_`wS0][f<46gZdbѱ?3n|ua+7I/e@dN<9=nU&ߧ;OSF-5Ʋ$FRX:g1Ыm~'c??YϝvPoYUvRGSbl@ih߿s=vH1,Hܿ|| e9SerJ)[i%*-qs3`Bʉ|x g =td)(HNسJr509XHZFRSS~a6|†|a__==ٱz*X_7r^׋&=]*d%'jYޛ6w~ykJPL}gÛOՕO~x̆^~(j̶-nIHoz9Ozl0vбi(6~)$gxct,O:[hߵum*Ծ_V\;_ +5G ӟkq@YȪ3 '0_3uXu湃8z.s_X8ĭ9/(Xxz͟vl 21=9ŧ.P-$џ,+m{9n1?k7=srFj%l 4:kX }'̝ޯ򙲪Z›4}CLrKK:q,6.5;%%;Seak+:1 uل|Ӡ>r>%9Jf40|„.ʙzQW~=0+Rn9x܈ e3UUI3OIϼ2_ɪ v^ÆNnz)Tb5#Ɲv- +Tij5hEW:`zqr r{7Fqhٽ IkwM999z6=! BHq` $! BHq` $! BHq` $! BHq` $! BHkCBx8tTEڸ7ؼ i#qL `NbA[7ؼfm; Uj}2盿μ7ؼ6:bfyZ' kԱf`t`ڣ6@Q! BHqb8w1&⩘u.zg=~_Voaj% X}{E[v-laFSTox7Ϭ=::/ݧVEƘ,`X]^QUKiQʮL|Ϸ,*-çv+bJcl2ФZۑdE^ {ݿ6rB!NŻ6F,<CcC#~r0EgtVz&VZS S{'⩘'_/)-6d!{ "3۲l-ٳt!4bsΝ;ɎC_]wܹsH۰B`%1gH@='գ}8vgȹ\kϚҽu⼂܂B?/s3SBHyEe6Ӓec ZSJ]z YDLo} ̛<^D8$22222b+,"2222rHI6)[?LrqU=kau/2NTgv8(O7Lv%L\)G{[LEiҼ8 szy@M^~8oRi,&i/V2I',{:L:eڦI̪Euo(rO7碒R/wWy[X\PTUi!&7Rs eߟo!RkהJiӚ>{ɒ%dɒW^yгpupTW"&AKj_W;m ׫ZK&txw~f.Y_//_-t]~uLYQZY%+@{p>S-,YS7n^<;'Oe>ݮ+tx/b rg}O>y'BCC{ayvcM} SAŨZ3Ҳ[>|tJDEoT.ˏ1F+N?ͷkH֛0~xQlC]6***66  MYNMMկA#b;~>Xo{_8Yfn߯<9ʎ&_ɳa1q Rq[lTvׯ?˗/_`c]v[ӳ8NUwnKaoS/Frϔ>?*}ѪU_j Du,s̫ym7+j+wۻ3:#=*.W6o}" :;bD[_9+WrʞmZOSС*=;@Lfe҇>[8f].v|߮<B@緗 7wU &˵O bׯ_.TAB:;;fz"XLd{a}'@z[qA7'1&˟Fzːk12"z BHq` $! BHq` $! BH[0=v5*50wxm-D^};6 k06iT6N;da@i}kE'& m * mxQHj;fֺmqkW5nqpܭRD)Θix7 8J;J i_mn)cwmOãkw0jx0ÖDZj0 ;Ak䞂G1?'S^qPvԀvn@M?dt3أ,=v' 1pWZ¤i_I/ A= |E1N0ZNm'j`ೠvAp%Awf` ;B݂oΗ ^NԮW>nwsk @e7csFw?L.#aD-x0T m쾍So6Łx֤f_]zu݀|uȻ?G<1{G=Clet"{P7$z׾qf_d;T<:;I ~_>T[{q^}S[x=3w7N 'soWLuߗL̊owѻd9a6}-ct':z3np-ɏ_詡Vw"-HPj5s[;FOhզ %\Ŭ20?, 04q U_ó{!l?gIWe %~2}S[#f-~D!-+5:;?Sm[g^EMg}@6ǂ2V?kp <_N {H/e%o Mկ,}VvVE/<aa@#yB-{_n?\3ِ~mӮgM]G]>a{h3qR_)3Ο/ЧC]G`#$BB8h>;>i[yLz)݊Nv K.=t 6q cyq^|ҮQ괳[<-rGͿtP]Ŕ7׽xσ޵gs{Y:0Eӟ]s44b>G~#q;bWͼ<0#PnvlnЈݬoUߌ9\j>,@1sǯKw2݈Qg~ pϽ@LB޺p헸j@w^mUP^Q6^w@bhٝ{l36xKkUxlݱ[zjBڹ!j`W"B_fH4!=;s@P-wLj@Z(@(V&'jtUl曃 Ng`3Zl$51ָg7נq@ s* ' 6.W7R dmgUC ,L3w5sԄ/}˟f<^bPY6U V)@6!mգDD,+43ܑy_pG_ywg- ǽywU:LȻ-k vȲUv&bvcܷr+]|V6e$55ٹ622ўR1 +Hl <m;ztȈ?0;ݴ`Cf#s`G!_-l[s*anۯ3w"YtSCۺ:yYÆhJWw8@I0B!$8扏c0B!$8hY]2 ܝpj^-2HI`Z T>Łڸ~frFT*NAj:Dwmѵ@@ݣ~F<1Wb*2#2H-F;wmѵ@QhAn%K*4{C& y,za_xܤ6&f$Pˣ7 CJ9(Fw?FCi04s,+Vi؅l|&1 ;F j[Nu&TVd23RAcFa@# 9Ҕ2G2Ӓ8cb$#vT+VJ^ʪic_BB v;Vtu1FՀzĢ5=Qw 8B0+p5cE..GxyS302.4x !X3`o˯mIXC:v2fē{l/*@I9FYC}`M80ᘱ e@`G0F7Z oN)mWAЮ9@PLdDNHÕ_'sJjv#j#@6L*@1Bj!D1c; Zfn7Tu f4M p1)&s.v*o~|A\ A&#@p#=kR?\,6=TEA;uHAu-miX^(lTAkj~C:ToM=XO˂,@ u*5C@p8iW`1RjmG ;ަ:>}vf<|gqiW^/!q<O)h R@ w^-H);iëΪN.Gp';MzN.7;^Ào vҰ^I8yo |G^CI8}NťZ3jI80(jT k`zd 8@I0B!$8@I0B!$8@I0B!$8P\Ì.ݚmΣi-p" 9_bׂqC_oZ,v~_X]uwܖY.ݒnE+K TVC,ھmV Nx9OU|/^ O~Ϳysи)p$ҭXem鸙tZY>x懢y@s<YvS7w{=3L{-݋)+Jmvft)͍/ Y 07E6 Ɓ6 |_(sӭXUyْ_t|lbFR 1Q>;z9KT7׽Ww>;–;ۭvUEbWF{#ћv7u *,fy$am{#_xZkCp5y׾ށwƧOGYhZ4O_}FnRY}e[^W +J5U?_Ȫϩ}\[,* ޾EzyА, z]T_a3|ӎa&ٲnqK+ޙmL`pa X~o;<ׇ|YZ̼mO4!|7Ǖ /lEU~JNy@LmMM 4V}!4:<;a5}(|g~Wt@}v`Ы}r{W`ŹjSc{+3CT6&8ީt{ݥJQnзΣgs{ U1ϨɳfbЂ?6|Avy!_ '& 4Ƚ%b3š/_ѡ@zfY!(_CK,82/3qo^5{ƸBʑUoʈ|ycl 1 '?9χ'eo^i>w_lk/{A#|A o@R7kxz[c 0B!$8@I0B!$8@I0B!$-35*50wxm-D/_ը@I80@e5]\^IA0[k6[k06RFF+cmY|~jOzۯJdi4җ.uc5z[uގԥS;}kzӐB!$8@I0B!$ywiXo_vL"ɴ/ly /۰޾/5;R?q NF,Ӱ^ہ/&='˛XazC7dng͖ M}kE'?M:ǁNs..ՒVKzFƁGV^s&MEuBHq` $! BHq` $! B=Z};H9BfZ#v;Z!$8/\CQNfz=݌$8a>Z{>WMVƾ__<5y]pq :sȐ\^oʛޚ?aD.=6qڛr NBWgC%ol=0v' D/eA캹~{Žݚn&JܽfP{cj_u3?=k`$_|# 0=PX9Xcn״lX>ŷ6}e~zpvsSfwZa90zY1A+ k+|h<|~i,3:\yPWCjVrۙW~W5yv`Mꖯqz{C zGI>'XE,pPC&{0*e'o=3ِvg-,+ͽڦ=02=0weO3]vk'73l}թzg(zYw6ne=_˩u#W 0=Y`'Q 4PwhӆT(|Gdp*7x/F#cs}+e q0YU^J܎v휙x_|4:W>⾨[ >jg_KJUw|ԫ>aа7S>a7S{<k6oܶ+_d ;ôg=_o-Pb~8e X_!qP}o-?; ! BHq` $! BHq` $!nq_QXmnq Ns;6 k06'8@gμvNs>j?Vpv&Ksǒ4k4؆}Uߘ?ڑFͻ?6KoALtz %5wC#4hUhE vwsEf+K=g߫vBʽZ䝍M>NLO8kϵbGl}CU>Q7л+KWۘ!fꌼbw"Tyiv&"gkZz+m:!"^mVo6sjeFzK XTdCRU^"M^܊W'Vܥ.wqL2WGsNN>L~k3Vyy=,yS/v55=477}%"gGfSpd{B?O/0P#^`ˍABHq` $! #/Ca5!$8@I0НφTz1jT k`k4z=t+P8E9Z^Ө)~~)~rq`X5M/H31zL}Ac`wk4`4*2G!#HXw5RFFCi3]G04 <1^°̦1/#G(jم/jOk9S|YAN0؉GyЩ834 WNCMLkXo^Yi䒣i\.JU|X1gswc'@1Bѩs2X)D N,QdL^ч0@Ɓ Ld`,Yxt(x !A#e@0up@8")x0g x]0J+\ѧV')#$! BHq` $! BHq` $! rrrz]4_IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_HK/fig/y_root.png000066400000000000000000000010511423020056600306020ustar00rootroot00000000000000PNG  IHDR;0IDATHK;NQoT DgAeLBLtT:ƫ2dPD BD; [Ε?}Ins=k34MfUR{M**_|*֤ p ؊DRg8Erw(Hۊc{ Z5sx? SNrG@vUeOrz$^Tgq X !ͶKVs **模式**,您可以: - 選擇 **標準**,切換到標準模式介面,執行基本的加減乘除運算。 - 選擇 **科學**,切換到科學模式介面,執行函數、指數、方根等進階運算。 - 選擇 **程式設計師**,切換到程式設計師模式介面,執行二進位制、八進位制、十進位制、十六進位制等複雜運算。 ### 標準模式 ![0|standard](fig/standard_mode.png) | 圖示 | 名稱 | 說明 | | -------------------------- | :------- | ------------------------------------------------------------ | | 0~9 | 數字鍵 | 基本阿拉伯數字。 | | MC | 清除鍵 | 清除所有記憶體。 | | MR | 儲存鍵 | 重新呼叫記憶體。 | | M+ | 儲存鍵 | 記憶體增加;將目前數值累加到儲存器中,中斷數字輸入。 | | M- | 儲存鍵 | 記憶體減少;從儲存器內容中減去目前顯示值,中斷數字輸入。 | | MS | 儲存鍵 | 記憶體儲存;將輸入框中的數值添加到記憶體列表中。 | | ![icon](../common/M.png) | 儲存鍵 | 單擊![icon](../common/M.png)展開記憶體列表,再次單擊摺疊記憶體列表;關閉應用後記憶體清零。 | | C/AC | 清除 | 單擊一次清除目前的表達式內容,連續按兩次清空所有歷史表達式。 | | % | 百分號 | 用來輸入百分號。 | | ![delete](../common/delete.svg) | 刪除 | 單擊一次向前刪除1個字元。 | | +-×÷ | 加減乘除 | 基本數學運算符,用來進行加法、減法、乘法、除法運算。 | | . | 小數點 | 用來輸入小數點。 | | () | 括號 | 用來輸入括號,單擊同時顯示左右括號。如果從鍵盤輸入,輸入左括號則出現左括號,輸入右括號則出現右括號,若只出現一側括號,則表達式計算錯誤。 | | = | 等於 | 用來得出計算結果。 | ### 科學模式 ![0|standard](fig/scientific_mode.png) | 圖示 | 名稱 | 說明 | | ------------------------------------------------------------ | :--------- | ------------------------------------------------------------ | | F-E | 科學計數 | 單擊 **F-E** 開啟科學計數,再次單擊關閉科學計數。 | | ![icon](fig/MH.png) | 儲存鍵 | 展示記憶體列表及歷史記錄。 | | ![icon](fig/deg.png)/![icon](fig/grad.png)/![icon](fig/rad.png) | 度量轉換 | 分別計算角度、梯度、弧度。 | | sin、cos、tan、cot | 三角函數 | 分別計算數值的正弦、餘弦、正切、餘切。 | | sin-1、cos-1、tan-1、cot-1 | 反三角函數 | 單擊 **2nd** 切換到第二功能介面,分別計算sin、cos、tan、cot的反三角函數。 | | |x|、Rand | F函數 | 分別計算數值的絕對值和隨機顯示一個31位的小數。 | | 2nd | 第二功能鍵 | 單擊 **2nd** 切換到第二功能介面,再次單擊切換到三角函數與次方運算介面。 | | x2、x3 、xy | 冪函數 | 分別計算數值的平方、立方、y次方。 | | 10x、2x、ex | 指數函數 | 分別計算10的x次方、2的x次方和e的x次方。其中2x和ex為第二功能介面按鈕。 | | ![icon](fig/square_root.png)、![icon](fig/cube_root.png)、![icon](fig/y_root.png) | 冪函數 | 單擊 **2nd** 切換到第二功能介面,分別計算數值的平方根、立方根、x的y次方根。 | | log、In、logyx | 對數函數 | 分別以10為底的對數值、以e為底的對數值、以y為底x的對數。其中logyx 為第二功能介面按鈕。 | | π | 圓周率 | 約等於3.14159......,可精確到小數點後31位。 | | e | 自然常數 | 約等於2.71828......,可精確到小數點後31位。 | | Mod | 求余函數 | 顯示x/y的模數或餘數。 | | 1/x | 反比例函數 | 計算顯示數值的倒數。 | | x! | 階乘 | 計算顯示數字的階乘。 | | exp | 指數 | 允許輸入用科學計數法表示的數字。 | ### 程式設計師模式 ![0|scientific](fig/programmer.png) | 圖示 | 名稱 | 說明 | | ------------------------------------------------------------ | :--------- | ------------------------------------------------------------ | | HEX、DEC、OCT、BIN | 進位制 | 分別為十六進位制、十進位制、八進位制、二進位制;其中十進位制為預設進位制。 | | ![icon](../common/back.svg) | 全鍵盤 | 單擊返回至全鍵盤介面。 | | ![icon](../common/bit.svg) | 位切換鍵盤 | 展示0~63位bit位,支援單擊每一位bit位。 | | QWORD/DWORD/WORD/BYTE | 資料類型 | 單擊按鈕選擇模式;分別為四字(64位)、雙字(32位)、字(16位)、位元組(8位)。 | | ![icon](../common/arithmetic.svg)/![icon](../common/logical.svg)/![icon](../common/circular.svg)/![icon](../common/rotate.svg) | 移位切換 | 分別為算術移位、邏輯移位、循環移位、帶進位循環移位。 | | AND、OR、NOT、NAND、NOR、XOR | 邏輯運算符 | 分別為與、或、非、與非、或非、異或。 | | A~F | 字母 | 僅在16進位制下被啟動。 | | <<、>> | 移位操作符 | 分別為左移位、右移位。 | ## 功能介紹 ### 千/萬分位顯示 計算器支援千分位和萬分位數字顯示。當表達式為千分位時,您可以右鍵單擊目前表達式區域,選擇 **切換為萬分位**;當表達式為萬分位時,右鍵單擊目前表達式區域,選擇 **切換為千分位**。 ### 數學符號容錯 計算器支援鍵盤操作,除了一般的數字和運算符支援之外,還支援數學符號容錯功能,讓您在鍵盤輸入表達式時,鍵盤的中英文狀態和大小寫狀態,都不會影響輸入表達式。 另外還支援一些特殊的符號容錯: - 乘法符號容錯處理:使用者輸入 *(星號)和x (字母x)都會觸發乘法符號啟動; - 除法符號容錯處理:輸入 / 字元觸發除法符號啟動; - 加法符號容錯處理:輸入 +(加號)會觸發加法符號啟動; - 減法符號容錯處理:輸入 - (減號)和_ (下劃線)都會觸發減法符號啟動; - 百分號符號容錯處理:輸入 % 字元觸發餘數百分號啟動; - 小數點符號容錯處理:輸入 . (英文小數點)和。(中文句號)都會觸發小數點符號啟動; - 括號符號容錯處理:輸入 左圓括號、右圓括號都會觸發括號符號啟動; - 等於號 符號容錯處理:輸入 =(等於號)、按下 **Enter** 鍵都會觸發等於號符號啟動; - 清除符號容錯處理:按下 **Esc** 鍵觸發清除符號啟動; - 刪除符號容錯處理:按下 **Backspace** 鍵觸發刪除符號啟動; - 字母符號容錯處理:無論鍵盤上處於大寫或小寫狀態,按下 **A~F** 鍵都會觸發字母啟動。 ### 表達式 + 在目前輸入表達式區域單擊 =(等號)、或按下鍵盤上的 **Enter** 鍵執行計算,目前輸入框中顯示計算結果數字,表達式進入歷史表達式區域。 + 重新編輯:單擊單條歷史表達式,可重新編輯表達式,表達式顯示在輸入表達式區域 ,重新編輯後按下鍵盤上的 **Enter** 鍵或 **=** (等號),可修改歷史表達式及同步表達式的數字結果。 + 表達式錯誤:如輸入的表達式錯誤,無法計算,則顯示表達式錯誤。 ### 科學計數法 在標準模式和科學模式下,計算結果分別大於16位和32位時用科學計數法顯示,即計算結果取前16位/32位乘以10的正負n次方。 + 當計算結果為整數且大於16位/32位時,顯示數字+小數點後15位/31位+E+數字。 + 當計算結果為小數且大於16位/32位時,顯示數字+小數點後15位/31位+E-數字。 ![0|scientific-notation](fig/scientific_notation.png) ### 數字同步 - 當一個計算表達式顯示數字結果後,可以繼續輸入操作符號,此時,新表達式的第一個數就是上一個表達式的計算結果。 例如,目前表達式是 10 + 20 = 30, 顯示計算結果 30 後,鍵入 + 號,再輸入數字9,會建立一個新的表達式為 30 + 9,按 **Enter** 鍵,得出新表達式的計算結果為39。 - 兩個表達式產生同步後,修改上一個表達式的數字和操作符,如果其計算結果改變,則會影響與其同步的新表達式的結果。 例如,兩個表達式 10 + 20 = 30 和 30 + 9 = 39 產生同步,如果將第一個表達式的操作符 + 號修改為 x 號,算式為 10 x 20 = 200 , 則第二個表達式自動轉變為 200 + 9 = 209;根據此規則,最多可支援9條表達式同步。 - 重新編輯含有同步數字的表達式時,修改同步數字或同步數字的表達式錯誤時,同步解除,同時會取消數字突顯顯示。 > ![icon](../common/notes.svg)說明:僅在標準模式下支援數字同步。 ## 主選單 在主選單中,您可以切換視窗主題、查看說明手冊,了解計算器的更多訊息。 ### 主題 視窗主題包含亮色主題、暗色主題和系統主題。 1. 在計算器介面,單擊 ![icon_menu](../common/icon_menu.svg)。 2. 單擊 **主題**,選擇一個主題顏色。 ### 說明 查看說明手冊,進一步了解和使用計算器。 1. 在計算器介面,單擊 ![icon_menu](../common/icon_menu.svg)。 2. 單擊 **說明**。 3. 查看計算器的說明手冊。 ### 關於 1. 在計算器介面,單擊 ![icon_menu](../common/icon_menu.svg)。 2. 單擊 **關於**。 3. 查看計算器的版本和介紹。 ### 退出 1. 在計算器介面,單擊 ![icon_menu](../common/icon_menu.svg)。 2. 單擊 **退出**。 deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/000077500000000000000000000000001423020056600266145ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/MH.png000066400000000000000000000014361423020056600276320ustar00rootroot00000000000000PNG  IHDR#=*IDATXMLQP(Pz!AL"&PЭzлHFz0F@8VQ8h.XhK UhBC%[gX[&̛ߛ7 ) 0)RFJB>P|?du Lըm\lnn@@Զb ߸z ]8+,-  +++^,`;{:%((n,k%x#7Cj^K ƏC^0E͂C۲ H[7|3&0ZI4;;h4&I(%5x6*/E4:=^<>07[p_ћr L__:::R"4;j&L[{W0pOEI\J@C_J6]Ɇx<( !c0l&,˦; dIVe\.l63W9 ŠVa3 PVJ{o;{IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/cube_root.png000066400000000000000000000010541423020056600313030ustar00rootroot00000000000000PNG  IHDR;0IDATHKˍQϫDQHQ$LLuFL2*L;-Ld K$Vs;S=u&{={}{&k\V~>kGR'b3)`0!iyb*!F5wOc00gyo{9vC] ̇qDzYpp\*2~۱ m=q4]6^aXq8%dac]q)7M> 5Ǔ^b^dk~ULnrIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/deg.png000066400000000000000000000013211423020056600300560ustar00rootroot00000000000000PNG  IHDR"":G IDATXG]g̦yoIH Řbx+RBr& 9 aj!o#& 52yY_{/~{}uwNFvC'Jt8F..y_Ջ6yKC #tG͹8ϸO )oaq&W<'9w(s`o$`>`hj XfmY#a;N&!8 ,.0e /qJa!$sORa1šr $8%lSH6akBq37̅0WRDv"4sr Nɸ9VF#tpGCfegz:+3+D[[R뚝2?V#FIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/grad.png000066400000000000000000000010571423020056600302420ustar00rootroot00000000000000PNG  IHDR"":G IDATXGͫQn@20V2a6  3J)T(F@H&LBUι=ٳ{3$klH8@NIEnζ"qׇd1`>~x qp {q G[p7'kEbx8P=ę<{+cF}/3 d󲲀Ezm%c?8L:#`mq{pK2q$Z;öTfUӢ8>)ȧ p5eK>ci$: i ,AzTlFM>hm(P$]bncGW)H9X#ӫ};7s0#fLo0MMoMUc.H'7U!mzm 45~T^['~Hӑ""X#62IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/programmer.png000066400000000000000000000604211423020056600315000ustar00rootroot00000000000000PNG  IHDR@s6% pHYs+ IDATxw\%aQ 2ݸ ]몳Zqoj[mmmuU{Dw?"!`Ѓ܅嫕K|Is0Jb< ʉT”̟.s3\$KĒ;܉!:)e1GR5?"ӧO>^O n81j(L-/~D!|r6.teN_Sb&R a$`| aDj!G驣 燞rkb*o_,"W:< ٫|HG =!;LuD:I{'=` &GDj!@=siGЯhBC_,A5xY}~ZˣrB?Hp;DϽ ]jvrWb)XBOѓ=DIyDCB44Egor~}-pD,9D,E>Ad8GD:"^/e4?7B)S")%b)2"1t>"M.`]SGNH0ϗf*1ļ(}4Ґ"7l<{x"&{ՔHK):JSRt < ѝ_VJ`UӏZ$ Ϗ,jΥ/^ =OzUYmH (fi]_< K,'Teg)R4cY1eT*?%"Nοٹ*MI) Z.N@Sq Oā<@Sq Oā<yvP0Oā<@Sq` Oā)80>@Sq`| Oā<@Sq` Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@Sq Oā<@b婐tV?Zpቲ.H_.=t`G興ģw:Y-(caaulqpw*?Mȼ [MkfgՇlO[D1){}n>`ܦ,W<-("6QxGD<__#;G7mmޜl9ҫ[j@,^JHDz+GL2鵥>}bSSg{*;_RwɶHTb:b)m/6;&|DqXmCOe4@|LXXZt3-66y )8@y )807O~W-0<"]Kߜ(Sd%ObW噩;S[sM4GHU3)W[L"VX`4uvO(U  KZtk؛~ߟIxHhP\D$As[47Œ@D1PWi;O%L_ljp? K*r+ [b>B$k^"^J }7kТvEs_S/yW]E)V__2(;807O]l^27O7+izS]@=( Oā<@Sq Oā<@SqxS!#>w_WyVrzoܴq5[t;͞! 荿ݮ̭3ۗ P@:Tȸiꄍ>m&\kɚv~Qlj;azvvdw{?A'5sc[7/O@)GW.a "UK?j}o-UUnJGOj ,0,CnD,7_;@ĉ1!sl6u{{g>k1#'1,`DӴgI|RƳuѥ4%$''q`Sō}btg!5)ʸ:;' +O6l;_Jvlf9~ " f[?p&dKQ{!#N؄mT}_a43~Uo2G>ԛ~Z [4]%Go}_7,ѵVLj0; @Sq Oā<@Sq Oā<@Sq Oā<@Sq O!fQ;& jҼC\e?v(\z%p)iI=>UxMKgmvla0>߷q.Uz;q⵹74ZPlޤ1T~̞:4d{ch{;T0ȓX7ͦhDEDDĕ]-,GTd۵,F>|#wnZ=駩kfuٲ(eDnez)ÿNJq{lrV4ݔu=nTiֳ'w_4#G|xu}c/cmKkY+P>KFjS`LXXZt3-66y )8@y )8@y )8@y )8^z pDz,HO <;.B]˲ [BB8e׏8^ uY"%+J\~)8S*l$uK+BB`YoeYV0=G]ez{33_IRq\7KPcnb %eK^JN]17O;b7 %eK^JN]niv_`&D\K^P?!Oā<@Sq OJq;,OC?bo\_ Dꫯ/tC r޽+W8::o>z3g(.]JJJqƓ'Oz{5lmm-Wc6E}TJ.SBwY-=7,?Zӆh+z-}/Qb^KRb'R뵴[KHV j/Uu֭[~æz ;)QJm8id3;4@Dgy4lҦPww? Pȵ74zZogb5W̙?>|86Jezzzbbb#""둒r1VؠA?? 88ExzSQm;εjb,'@ ʕ+gKHHS6+N?0B}ğ 9ze6]Z "ʺr>& TDpJ]b|9d26"QpĖ\p埿m&.5ޥMbVo[MADUYcҤ߿ʉxOY'~g[n !])Sƒm*<;;;"##[e>zHLL 666j`݃:[Hq-] /]jЋͺ>M@DDj\m܀o?CDغybȯBCN]rb|k7nv5J0=t萧gN";wj׮[[[<aٝ *-;<&ܤ qXWrز}/T#-;-mGǙHR@i (M ǙJSi; d`\vw ߰A/=wNӬG(ʅ;. UtOԵW?tğ=t.8d\- zZK#'Ljq*m󼗗VS!Bddfj/j4b&#{ޫߪLz u,iNEѩ(PP^ "U6=H` yտ"1;wܹsgΗ1}oy[nݺu@`+i(jzٽE u7hVkw\*<~/{__9Ox>sGfLo+ߌɭ؇K^^^DTn]} 4t[R%5lXCO|[wf~s CA=tQHrPҙ(:Mnv{|lٳgO:xՋexgY!RnT[-Mk'#șu j^#7>)@{ PS3vn:Wk4o~׷\3!^etΝٳg=zTVњ5k._C˗lll"##]]]r[ADDDŊkժ%kn:6]]{v( K7,%kjCDdUkQ5U([&Med˖-ǷlbI,~>*"Ʃ~㪉/^=}nŦ,MUzpKUlTC* kD0NC)ZǦM>hl+o?RݎRx'VRe… w9}ݻwOOO/JV3 #磢|}}MM*U:tp޽Ƹ4؄;z8Qܻ?FvX?K%؇&Q""%M IAOuIA>mVለ7|{Dz7}z{^ zDڢY{_6N>mfT5=`#?|4ݣ76;h>c1c|'[{.q6lҥ#UR'Odddx{{1˲UVUTyWYIܴc3ՅЃQxv .%6O2(!L:'U,E Qa󥳳ajƍgϞ<(ApmYz! ~ݡ4 .sN]T4<7GgL=@G6-Yu+:NEܻSC̝..DDY|LHuzϺuRZ~>ciKM5njCDmڴ9x`ʕ7l0pΝ;ٳ^Kӷovww*}F%?-'~g &*IXetZs۶,F!"ևh9:MPH 6u,_p:A˖->LDcǎ=r$gM}ZO釾~aj7_3zj7n3*͂]ո#{/W9d妯M\u*ޤԁkADzT5 t(]~|K W1 ںu#GTX:uڷoVhpwwWTqqq5+WApvv|Bԧkkرέۼv{׻{AAA9_2w\)UJeDD_UA[صuK(N}~[)< և2ڦMkϽ_V1c8::WX0dy{{GDDrp^R<<<}i6unSv{h,q T0\dڱ2uI*PWQ(!u)+HJ( :8 cSq Oā<@ H$ז %eK^JN]17Oy^*Wzy@]RԕsT׿nc$$oKPS5z|uI꒗UW~ q3փZ,tż FG Yo~BR ^PpWiLј|dء߳Z꒠MllF=ULDl[=b8(k- uIVI&rSUe60YDuEYc$!o3YDuEӛdEJ*$hLM%39/HKUrAsoy "kH@Sq,b.\(w5jE IDATў\ ϟpڵkkժew-Y蚔 E%99yNtCĒ%K:uT0-f1><7~z6X:m\yGײ}yK]Go8d ð*2w34Q\\\zz#.^g8.y;g Kz=+VV-6;yA|wXq1j9ie]6k,K7 E?>R΄`܄cΥ2~Mw+W6nXY:zo>]29UGEEQTT#">ξELj^ݓ;qӗ!qԁb?Xd,X 76og6`J;9)-Y$$$DV[!)<=vΧCOY6ۧo[#"s+xe}+js?ۢ}eccc|}}˔)a'mJnޛհM\oG}ҍ'6S-[Hy<\M`ʮw?m١i^FԦbĆɽ|TtAz:>vWn ճx: UTΟ?˗/O2E}>*jSL|rq/[Q`U[n~9p44\ l\gFF*|;j]9v.Ynkk[LDKMiaWLإWͧٵ}*|:䧳Nݾcyc%c^Uԥ;v0(}g}骣/c>_ٽU7Nΰx;_לJ-$Ғ%K&Nhkk5jtSjZV;uTNWF 4ԭ̃l~߳yބ5rƞ|ʽ|ܷ[ϗzݶ{m+9䝫,SGl۽f֧/םz1jv\:ƣxgԜ9%I|ٳQTm?ĝ?^t1SJrΜ9D4uԩSќ9s uhqm=SmK/XVm+'g 1A#Խ|ᕻsx'VWLJT*Gttt~2!q甾9fwg o[֎8e51\{M|Gs6XSq}?Gc҂?~oF検Us^~Vtl-/R9{˗/_|y S*<͸У+ o׮]nj /mfFV=t4kipe}<=y><X.!}F\}nr~{%Lƾe?aMq_mRׂ̊3fI_ ~ad0y TPj3fΘ1#g_EaRN= `x]^!Cύh;t1_v>Y2lr?Ǔ'ORSSAؿ2vRÈYO愬z^j[ejuCaQwnX~O~=ZVvHpm6yF^cXŴXȌwv}Um5}Vu~Q/=Y}L#=9ɭ=zƌ[3~ܰϔg] OmUjS(3y'6mҦ{q2T{=MIU3c?eˑ&M)Rxx803Lxxx|||JJTuOΰS;78kʟj|pL}âZ'w;m?>{и~XUoa!q3]Pu:v/턙;Q='.ߩLw?u [z0Je 5hw͚5N~Bșϙ3gƌׯ_ H;G 8"h(8wk4=p|*/ox=~cT71޵lMiiVVVLLZ.W㶶qqq5kִPפ&sh릻:`+e&\ݿxi/Ԧ2U|YVM=H?jn~Ɍ2WvU_אy1G?~|ݍ9_*ʹsZu1aaa\"^<)jSoK.5i$ׯTCeeeuС(NYJPW!ilxwǞy6Ne(I[چG6w--Ү8|pOOٳg PKllg"BXXGPŋ⼼,<(Tz5wˮL^a_ʻJwZj9sG1bD~${ ?ƧS)!uإYz}UY|Pi/)80+OevVO>  Uf2YDuESy%""=o1];|SU1wItS 46.Iv`>j!6:'ʼzqc;{Z '\=y.vN'ʊow&˱V0JKKcY*F|؉Sl@`w{W:4hZd[bY[eYym gv7D?eVsz9R)bSr2zX|7t݃1OZ"z>>>*Tprrz7JzCtjSb*y=oTN.elRd)*|wk/v$\h'ukJkpzv&x<S t^ ֻo!9+W\y,[bŚ5kZIbEh9/?1-EIyJ6u~>p(uWZ;nJYx~8oJl/[?k"I/_+pƷSƥiDDPQ IVE?Mn/}ʕ+{xxߏk֬쏇 )RYqSفҞd<-fJᇇe] #SXۥ|ث~-bvSjR1 *HwBU3{*z%Y`7k '.=,kBjZUZ[nY]"'k05\LYCL}jCFpLxxzyDK꣘qLs?-=A lsm3_ ~;L6/x\]]IKKtCD::92B+Xwa,{avQܽo2I3t&&6 oK7 #"emllcqWn;yɀ^ֶ5 ֑1W}^e}*>}>rgƔ-5nOp{I;n%hLM|(-X+_@qot폵g[ueI&Ѥ ԫLS(el/r;^ysB}i>pWuYĥp9z+V !Owڬ>9bX2RT<̙+W.Sj8z{!>v_wIDD Dڷn"ڔMŞW Gw7=t`'AN r/R-T,ǣ8N뇯]oBKw4ô~*TlokxӒќKY_?????o7[R8|}JI|褤+ Siom_o ""xl]rzPh,2 :P-?6]a`ODDOVIws)b:\z]:fY0Qi O1u}"Ve#$&jlNڷ`}-#谨\Q]TxbBZÇ7viOs}""!!CW9뷩:h/q YFvmլy_1[[3U]_tOOG֫Qߓ#OXDJ@F,蘙YcñTw5\45Τ3rSؖm忍.UdѶB/~?7nVIH*>O@oBcbO5dz{t)?l=~AxǶ|?e~c:{VytCR߷d]|ݻNHز?=kQ.ޕU#VkMoy=o=YST=m^8ӏ#j%X0}̰>]r0sU-斉111nKj%s}"ݎ~#Ev WF .e;x iWZ}é{]|4J ʄ7JOO/5{OILL '5)iQwW3-yK%66֮]w>zΝ; T*77\i.OB WU lk][e+YgZK |3rH" b#ݻx:BRJ㳧J)ZbRZoOPsW<ѱH))۳)X|+*gr/ %Sq OaV2<>7$D X/PhYyjB[/o` k- uIY& 5,[^/+` k- uIY&;>{*SAb&YVY꒬M2w"R;gYVR|Jw>N嬵4%A%+U(UPt*V+O^ W[kiKRJrW̥pR Fcan s:NsDz3k- uYb^o0w5í,݊"a.ٱ K@j@y )8 }|߰KX IDATZWrXki˲*\j4Y,w0d! +x) ㊧mo#9Z8tż 1̔E233 @Te6qR[ZkiKRJrW

Wј|Tuj4%A%+؜ uEi2yEè" q&wEYkiKJZW4ɬ<{B/*4%e%+d# yĘ*4%e%+̜$.PV!EfoU-yEZ"SW~ʎ}kSYP@ @y )8wR)KHH8zhBBXlي+Xm{oƘzw/.51#K7T5"tAR.NlZ{a)ZιuH(s{8;|g˺KHyZpeG>z^wGo8䷄v_q )>_s{MFaZb`n(FDnݺ~ppp2e,4JޕӤdF!mrNkKweSCaVrѦP9%QO[W>5}Dto&'ֳ7vdl}N{̞?~pwZpww211ԩSNj۶FH=\.t['?}Je R˪flBEZɇ+;vɿ zޫ;/Qo۸o/62])OO /_L_7JBիjݻg鶈CH9ˬ?w׿oH蒓RW7kK>.t>F˂ƾ葵nXv"{-é [j٪^S#Avm^}Ʃ~+>>q iggk WB囿^37-QI~811!88E#++b9Z7)EyiҊ.C&U7iXEΩwr8{E4@-(#?(۶O ?+{68g̶PW,yK%66Ve gFT:99ծ]|>eX[ujNJ邍g:|Оud(jP/_1t܄,;u&ܴ0>%gP$tżbcce Sq Oā<Yy*U/XG Y%:O'|PhYy*_[5\4*4%e%+dVPZZUr&PhSGB;>A/^oe.*i]$s'*J~eU*ɧt:|#<pjk- uIPy""mmm8JU(ljZmXkiKRJrW̥pR Fcan s:NsDz3k- uYb^o0w5+S~4%;V\\wH @Sq OQQXVv|-zZKC]WT! ѯP(^ APpe * Z꒠MllF:ULAl[=b8(k- uIVI&rSUe60YDuEYc$!o3YDuEӛdEJ*$hLM%39/HKUrAsoy "kH@SWZZ} ")X/!!ѣt:>O>]s'/]h.\Cǧ ew:f^r6ʞ>rnLR`WƿfFW*ijO=E?/t74f`%֞v$w/زVg,#T}k43bhvEf|i)k']\'K*Gjm:Y}f^q-\diﬞ8jZm:f}r?w5Y'%E=>el/r;^y??t/|9ӳK{rW{~g»|Ug$>8kV~T_V- Q{0nvo#ֽsF6n[ѐL9}oSoe!s,};=8{ëU@%.7!bzᎥ;SOaZV*75~isC.^>~jzw=p5\L@X,\5Bg=G0۶S"{gEsCȦYH`X$" k`XEa! y2O- >=o;uG,XVa-^xЎ/N:|o(wR\Ġqg]k q#[G!^L{/cG!?߃BYf;b0J=|V.HEQLbtLJySo.YCXh$TVXg>ib"Դ{K9d?Jo+[m{՜mCPȨӦt<Ŭ̂H;f#BA.ZK|F-\ȘݨBzO{ɟ pR-x bg~߫->mHE웟]Pן.y>8"CN;+v]eQ6}?M]ieE%ѨBx񣲆]1D%cOw(r25{Ot||Cݎ6So|{K)]vWĖSsDf­yj?8~vOv陯g:<ĊO9GmuEEE7Uy>..N[tu9udp> |Sw=!ިP_Kəm.|y rC~ASTqv^WDjmE>6[0u4ɣS[A~SEEgq7u&u 3z4盢KCQQNA0u^SAAiPև A4K:$a** uifOqף*dzLjQeeUHH** uif6?eRARJY?ْ$9+t) ui7Vwan="˲(:^. יGJC]'uk~jXS^~A] ϳqO$Ij΅^.jST((#[r/sP)jhkH&m]'T?JM5`00KU6EH ZNj B`X4AɨwsQQ3Yol u* uiF/aSLRM)P 2ͧv Wvu:.`&w+Wi*xw8ʦWiK8k KGp@)P SuO@ OqWeG\8/OY7SQ ނx* uiM yQqUJ/%~p6懷U;6?U6S_=UU2UP _l!@S?њuYgGU~Uh|=JqX{% +G)vif E Zo 9COq72Ia'6!pA#h*Am VXm!lSDR"F'57ګO&6H_%lQVlA`ŨAm@ktw=SRRr: L&ӠA̰6rg8m>`˥=ًo?Rp]hsdF֟SBw|%g~Ɔ_tRŹjg b[6|3ԥ*> <16Y@` gqGnݲeKaûF.-aCbLiצݒ0w]2rt+lqlN RWytm:+7^}g "/KO%)oU8gx8c2U*<6ηk'*pbmH3bֈ=6JnO%_.DYMQ/Pk(Nyv]ʼn"SR^^n;d25~)?uUcYVl/o JJnS00tm vЖ=''O^mP`ͥC$]:v *Y-\ԣO_e[o;ҥqk7*}-U@Jʉ3}9z@΁݆i҉Z}`4VTCnUC~}~JKv|c[ɜvxk b_,C75><"@⹽v|XtF$'$$$ٙ|aswV55Q|qۚ19ޜҫrf>}BcdFL&7-ZQB`hc[mP p2.w~I~!O}9sņV䗐֭rO ~gA|eww\Y]l|Tșf\{ ylvwi¢E jX+绪g~񱚻%Lә^ Jd0t |c5#f,Uuk'?- {M|}S{|c$G aAKz'\Hĝp!uyb!iڣ#Ǥwu\z6&AHh 9=Zt Mb0")eO>("!~TϮxWtT#{MQ1ǒ,جd@[v졗էEEEэ;]ab'Q=`GKOIgs:gn^C=Nj?ucSvLvKXyk9.7.OOl촛c ˑ#^;'N\x]vގ'@z Owc0af}dņ0J֪%6oZ14!u[4\fʕ+AA}ʽMOhh#7_-^aUZ%&&&&&z;&jB R A~Q j(A&Gݥ&&:*i5Ic~ 3z$S}\Y*9|4m#4 >/F٬DmЫ4ԥee[U>zT_,^iqBPqs8~:~UF)zfBp`** uig*언@xuK~~J)eKץ4ԥY5EkXM˱fJ-Rj ynq@n%˲(^ի4ԥAEp&ucO:INKO}||XRAiޛV@${* ui g# p+K=~J?hsq'ϟWkHeJf'% !eBeZMy8/fʲ촶r^.FJPaJT`odyURzT9-I_ک#QZx%KuNQQf3PJFPPx$d AtBG T_+@լ!y2%J j5V̔#`WOWYSA܈R#8yJDd T)*!}ρO,*"!8^aTO(^V- ZAi@?Ei(**v onep%d]IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/rad.png000066400000000000000000000010761423020056600300740ustar00rootroot00000000000000PNG  IHDR"":G IDATXGLqnaA6RePXػBJlDؐKJYRnK3b~9|L11" HIE.N"Gd^cYҗ w q[tIlܷK,7>ab?^xجywl:  qp(S7b>R`f= ,Fc KUV 'H(p= 25gFk;G@RL?di$F!>SuHsP٣N:a̸oBB<%2Cp9 j}#$ >*˓9Jc"ty 9a R:BO0UM1;4vH$RKA,͜R!QjrSZI%1ًQҜ*)BH#0 w9C "nw"OfBL&?yO`@}QB E-aE2H#@wB> @XY+Fq;BL"˵[`=25 S q7%qɀ05ap|Ҏ1JsS iJ3*kc V(TYg;C)Ա0H$,* 2#AhHU)0TSk=u`is jgYWgt@ЏKp=JELXO$yM`5X0L>?)+!?E5d`d Qicì0 EƧc⛢|!t} $Q$$|gxQR:_*|u j2)BHshH"H u(YWz-1$SPR0!| p>'iG!Quh)8) $$)$I!IIR`h`\,|(?SJ8<!ST J0+K٩}+)I1 A (gDC! S5Oá^mgJUiVs.Gg?55>ox!ST=RiLLLjj*k׊D"kkk==_"!)_ @ ؔ\5!kx'B!؁yBBǧ!SbB8>E!v!؁Sb)B!";p|Bh社:\4ga}]|{7~:mUì}%26Pݳ[E3vF-/Ы׻u[Sl+]ΈT6a"0t4sVN/si4eCԒ? нd+}j?$H\3CW۔Qi{z U8G)`$i i]գQ_Z{5y~yh B*8 n9YOF UI}nK KϬL|ײa|[D ǧ!E4F`` R`痯m״>n>66sP/L_0TY;s 5P9&>>C^XyR@gA]' -W[RHLo%̈́Fժ[<Q^L|cUǽ^/.ztKIa>YƷoV=IЄQD/>BHy3 3j,]ң_=xp@.n$0_|"*t4! ªjM6p,Mǃ}o},\:5˟-"'ܔr6|Ipn 퐻3! YcS3eBK "*.o')҅["sbL3O/|  _˧(J/SPt.ng>1^e6sg>ZrxpHٝWn>z×8}UW/_M<)ґ''XxO\З:ݵg%>rBHZ-(i#V5W?Cs?¤%'HQ)S*ahjNgIOc(R8S/1) 2J;~eRQiL3x!GL⧗SaI)4Nlo>'lԨQ_&&y*y!&۩4Pe}=* <,[1=彈.}sRvHa"Gˉ4kviQC?czvnn^;koдN<կ4G;1OB|#u V-, anD/kje_~Vmת3GqfѶub}ףB"~84GKeHiFCCTȾ\!#L]-GSeLV%Qeφe)Y̛O1t !O/y:cFj/ԓe IJe*S??7\z'MZ6.&9)H23w:oХ 4rhmaI_;dHçvs/룈0!(6~s~kOMk>EDxjdm4k~HQk_ͬf8>EqYs6vyrݐ~n`[٥wXTǧ!Ăh\B!v`";0OB!Sb)B!؁yBZLw"W0w->n$gA~SfҮ) [)R\[Ua& ]V6dB'293%L7pfo }… O v>fS٣׭.*S2lt` Z; Ҫ~kW=^/;ݙgx\%8xˆ.Y/-:|Ū @wvY&8tpͺj\gpXŅO~EjVeUKzg2˽Qmh.ߊo֜#.]Lh4ɼy&M(d6 k=d`hk5㯝vMTٍ?{zB^]94MŚ!#haf 02]"ǼUvZ-!PZ.ħ2@]$iQ|X`3 F|rZԾmi>R+dn#/{^Y 'e';i|rJ5+! Δ*SZc֬}\j *JooyXd#Zx7ɻW͚;(ܷo}_ti KƒlQ w( 0U$2Thґ̏oe]ɽҩEbqFj|cWI٣'*לzaG[BS.N+WJnkj ikxoɀ6l.{a_:{ݬEy~bڵk'MJ4Vvom5!&=.'5ҙvnc-Z֕=+?SV͕qirjͲР>imI pFRϤ6Gڲ鹈,s?k_z:gmD#,ۨq%{mҕm2_HvԧeьW.p _۷>R+ZD͙{XWqqqyBk}/?jK_&F)Nz1d %xN%}YzNCU:d&Kn6(jJ4>$+83t|c& Ԫe{jg:BMEԜ.n[y6Z>U3^M5WՖzg& ܲG78qℓSյ]? l\Zv]O?tvl[pOmk5+6ht S6pa3 mV34-MVhK=jU)mLǾqx] kuVe .u+S;=UqfN~yV bT|mN]޾x_T``^jn,#dv^ӽuz5s */Z\CvUo~~˗/3fH:at~mn Qi^ƨKxiG\Z%OK >w1,/532eVڂ5k֬˗/G>qDtޣ=5~V^ -EOKj|*p|!KPٸ>G\bbbRn]mGIG5k\&M>|¢$Rq|͛7wUa"52 *dS撀5k֬TZZA~XEߗRjOikW*_!\f|]2Wo%XsI5kP#OF&)k`š5k})zT*挃i4[*Y3f(^ߗH$\{dIao5k ;KAqJ2($0 M*űbÚ5kʭכ2 #f5k <!؁yB~8{l@;dȐmۊ3g~A,'%%nذ|%¯)Y/ٗdS鬟t72Bu޼yPP޽{ݼysŊ]6w\Js ޽oܰa+WDGG$&&ob IDATTcaaWųHP͊,%1->#^ujvyq\HHȣGvgmڴJOO xy'ݿ w}H$3fի6@r߂5jBdǎ;v옽ƍ Ҹqci: ϟ\|dߣchA<6Աɠ5[qQn0R}y+(W*`/CSc}n[޶gJ_gwy a\f}*Mێ6m3f5jH)S,YLD+J`Сl}){ 7n8::Kw3ax0)G;$iPAuO;kf6mb.eo8Qeu8 yw^u(s1npOFԪ.4^f}0doOz {㞶z{k֩tNeZtt"[l!Pdɒ)Sȓ,Y;O1ct-44ǏZZp!(8|-?dpR ODTt|= }϶ԵSSL6 p~e|iRmAd/L*YqJ)P`O>}4{E| -Zhӹ|*U=`rskLSF~%ɫ:6Xg;iXnV榣NNpnjzP/ AG\lSŹ'H$:|֭?*?f*?Z8c O3[q{ՔZXۄsOP0 ngEBdçέZ:QaCIȹ~%I_G'yΎ$eS%` af̘Ѹqcy$|}T~,Uʳ=?n휥#ce]Ά[5/GVjժM;mt|ʩS{l3%Rm}d7!&{_OV,_|ɔ^|)*?*^|"8Kǧ?=T*Pv\z.Q79jJ0 ]IT@96lX =O.>TDmƕ2Xqa nxڶ4v9&7&3{OV=60v/ʰav{ҥKGBpҥZܹh"###H'/8n9Pv 53 Gd/.?aX׭w^v)J[7ot@Fe$oVg~84O;oI.vzD:c3:[l1>\Yfu-X@۵+y ߿?~7onaao߾  1m۶,& Fy#i_YU¼صoɗ%cQT~'(:~xJ/N:-jݺ˗cbbZ)B)ƍglIRDKDnJLL H$>>>B۷?]vʕK.]H$yoQӘ₎6)Trr2]*NPQMjj*a s!eddd]'R*::'! ] !a8>Ց$¥:.t)[ j)o6:*ߛF_ЍSɦnߧ%n,ABISB'R~ JQT<%I*0 ߟ2,|_ÔUBc$ ѬH$u_* UAӴSu)8R;DD"GE:r| D"A&rN6W~IPHQMgK9*OH$/ p/ )TK*d2'3̠ K'KA1Gd〮p̝ya\Xt) Bk0OB!SbG1e:8n_AҪN6ؗiz}_,bNE.j_/ (d,t)8@=OOOE(J[W,zBQTA6W~X,cbXCڗ8u)8IݳSKY9Hĺڗ|ڢzBQ±6l /SWAS\.t/?ɦnߧ7>-V1򖿓ɦnߧTr!>oRTJXUS !a0G!.?cِ/IBk6CFwe TSw^ Xjᐪw.L.BD2'&wQ )ID)aW\0)6Nwk{v\mrA/NnʇTÍ^)reKs"KZڮ(t3m~R=˒gۦHC;w9tĄE50q"O Kk]F0/mI+Yr)~fSM/p|V;1 NEdHC404v!(:S~ЯѼà.NVB~NhJïLKԺyMXz84EeW̽v眡۶hѶٻ%[5^bܘTwܮ#jdҌPfO~FK/=*V>psG"[Lҝ^K`Ո"iG73vx܎ :NwK]ju&`5ր K45.J[j`h@ 9z8ߨcLhGr6 &`k-hYݫXْV)lIpwMpuڔA8Tؼ2iBnZMңSU- G14ʺ4*~*u5ˤe55ϒ /vql?^8&k@m7msWΝsӹzSgttzEsvOXgҙ 燧ͬ[Zh2?'ʦz/;@?ŲOP`4ͭLOTA==7^}q [7n_{O.͎)N6/[-z\zeI/adbILvt &pS\u,{iH0ifꄆ|VZ13:qk2Va^3֎~*DI9NNH^T#׸ӉtZj*@4ָTZ;WsN i׌413!RRR;jHdyGgi-lmd?.~TŤDIx}HwDCɡ$kt LPKL1+ii`h`hWĘ gf\? Bdn'޵5$NNHIOY\ln0?eeo]"7UzW%>fQ1Ge{K=xuzV3.,u:zjTXB)Awm|~#hґ6{F{~gnWI ޲ls Ƕ/ntڡ3WX5iU73-h{ƈ΃gQ%8>}dn^x,Й]FMZu3^LIqq \A$wӃN^+w\![펪7fJkZӺ_[sL_rg!WvLu0| pS k.թнvLKSQ+ŤȄU7%8T%Lݍ'Tǵ r`p֝ go$m-jMl{T7}ുAQ&Ɗ'kYӳӺ}V#]/GO_Rf.0iIA6m;~ YjSWؐ`>tZ[#-ඤU)8EG+dpO~qB9;nPRF3W'aaa666욚Zha_bn-6 +WR1)vVˊuCjDIp:lGE~草;3!`מtΞ\2.~~%qX/1Ou/SmF:/oTTS/]"o`";tHPDsk݃Sb)B!ءFw}!4 TgbxtK)tM)GO_Q#OIRBWi]W lJ>}*Q"Uվd2]sB:ٔ-|UƧ|@t|}1 gL&?׽0}DH$$IHj_R.R%7ɦBRJhN %H8@dIɦ"ʯ8 "ea.A|:SWJ2($9~204M2ɦRPY!sL^վQk :`_|׃!5!SbG1O#бuݾнl /mzX,qey&#R Ф} ǻr(d,t)8@=OOOE(J젫} B-V1ܢɦnߧTr!>Y)*?V%,}$BW*0]#`";0OB!Sb1do.oИtU!8o;m8>BdڲUKF]^KB;'j,BZyuӪNrVPe,ջs 1u3x] m4g2tZ7r ṮEN}$:f)}hWA*.% _мyc͙׳}&62v-T6 KEc&꿏m\ǣ3{}:$fdwG]`|}8k,h֩0g&Ѡ q7օ @T{_/&xמ.WIݾѱs?v/| k uTujӲux†i]۶l-p3oFzoռy=N]w5ãq᭚\z/1~:v}GBdQ_5_;咽9s ^^ FƑOj_CGK31"([;&:; tezhcK?5N䜓If"ߞC:gfnk@˱Y6G1x 驝&M\ge!ܲ9{Dϯ%xHsRwҰufz6-P˫Fy^V픋s+Yby_BҰ.o3 $I#4 돥\ܫ ;8 )~vؚöhK@Ã]@W=ZCGoߝXl$ 4Wn+w|ksv#ߌQ- I #2!C`0sL~e('ڲCuS LT o~A׭H3zI1?3t̷,cpmZCg<e6k?]_`7/>0N >?hV^aeև> kפ'wѡEJ< *u5ˤe55ϒK˼j:VQ_"%TYMï2q^mowjkэ}>R@o{g_3ᆬ֍ǭ\YV=2˛Rih)Hsyʤ&ҤID&9)/= IDATMMr=yI3cHMNfX;ݵ}Y>%do)31Qq&%:2^x}b C:qЅ +t\~ozޜnjh;aȚ ˕3KĀ%~Ń25OU|T**7=AZrO46uo9$:o\{׻ vEl#M &91?⠓SH^)#֦v? ;hGDw> >m {4cqjFM^VЩ[.Ԡď'Qt/d'_ΨXڄhr *ex zXh=WWicgC¾FҠk+RtH1icg y @G^.zt[kFOl!DCk[ U6iiCXMZAvv.]ҶU{:@Ԩ\#uib.{miy ,oݸ|B :9=p\)﫻gIT´ju;Whr)_|M:׍A[U9_u/>Tj 1`1~9m]?jf}η;ap҆#5R ^JrSa:hlUwݐqa&P^6ۏ޽Wg:5%4z>FS4 ;uiuw3&[v3!W" Õ<%lllT55Wd143վJpD,{OϾַćr9hSLIzt%~Q$ )Ttt. .PU61yR] k$MPd"  7n~ x?TLeW93d_:rzW'(l_:9ɦ<#Fa";0OBj)lBWBi{zB'R~ FfGw}Ѵ.ܮD lJ>}*Q"="w}d} ]dSJWA=zN0 ߟ2,|_ÔU"c$E"վR)'\4MKu)8R;D8젫}I$>d2DRu)8Ⱦ+ND"@ aKxA!Ϋ2վRL&($I0 MӪ̰t)8@sDVt/aԚN6!Bq )B!؁yB(z,[ [Zɦ6Mb^3Qȅ{]K P~W(LVB'Kt^T^j_B/( |oxl /)SXKb҇t/pPAUɦ$uoF^AJ/%վdS}qҾ F=tw}y,ЅN6t >}Di疷dЅN6t >}_yK}mU¢Mwt`l_! Ӆ8Bq)B!؁yBnuݚlyqbQ) ;QWKұOl :rD¼[0ɥ y`-F#S .e4Y]&)#lQwqor.V킊(gQ|K^q-Ƙr)Vu0j>9$}tOm;@۵&њ#F71 5yCEljڊCEj0U`cb6T-OjŽ跕}t8=&:Ȩ}n޼g6[av3Smr_g=^_`r yrOVoV߄N/7rmvW" a <~hӢibƅ$ ػS:4#j=wO.ջ};FDS8tVz.5#Oٮiٗ~0| Z({$o!޽KuC3gjfu6adn.V4ؓ+I-=M2"L<rח}qg*,_9ʑ0 AnM ('(=1峠VaV79B훹i.]4mؿ@sR m Nd:vS=ߑcZ@X`o]S&cafMzpGNm'$ܷZJW^HSdIy+Ya}ܑ!W48' ̭-ehimc{ ^je{ܻxIꎘ5!K7<~ΔwV>psG"[f J/[ƭ;y_I(߫G.PDM]3!iA7mZ˟m;/Y?Ɲ/{ ɌYGXF"(m8.{5'8uadY2ҳO#9zBfe ԔT-:AWO8f[C闕$\zXF|ahި .3Ob+ծP﫦"˧X?! )11eR8JV:չC^!2.9CJKR^BpS:AN5)v|+S&f=`bo/2$xM2ڶfÔVmPG4c!K zL`ɓ?,igg84Iy*}s#x萩BɆ˾i 01Qq&%:2^qY-]{OJ×s}?ٺHtu%̭m4G#c]<ӯEE&Ye#vO+;OjZq^htdAQ#g-ӑ~Ӿn֥-ͩ >?$:o\{׻%ïI]j~ODž xAD~HցgЬSYSwO= _Ͽ-SʺAC|MF_!$8ik;rT KsOO$ɒOju[v8lpj b,#@QLܥy \fEGGc=6ꩳ9:s9.¼?u;Dw` oooe=e%BĐGGH.eg=.B!)BS!d6SBGB9SnsQSp#,*9,  5jfɗPfaQe Dx_0m/>¢IOE)e}kVxP4l.KlzvGǂ 5,TUe32`.M*$Y6www{s$^sF;2`.)2WAũ z^$nRSxBi8oM\,+" @)UU՚siM)f1&xE)i.Cb BHk"}`=E!zBQQiY~sB;e(\th*$y\$蜶=%GNEEQ / Klʕ,&N>,gee^st:VDQt2`.)2WAScSYZWP4=li륬dRb^s-.iXsi\POY/:&S$_ .C}E%'%Om)9K޲;-_ .C}E%'WZC5;&% b}WĎJMwxe Sns!8BiS!dXOB>"}`=E!zB=-3KSb{wH(%Ԇs=f<n mon a %ogm3M?+o:cXk}.m{-<|ۗT9͗;*6(j1yؓrSƦח\>v7taۼ;CWI̝[ӈ{bDd꭬ U@VS'$Zv(ܩۼ5[=k8c-b":hܭ[4cjRN'L-ANx)QW婩IIwZD؄_6kVM| {>s?so۽KރFl:qǕG ҥNjy%uѨe_Y7cxx^ N'hn;;P׸sʏj% /og3l_w\Z5kjM=h)BTɉioG9y_lb1ugiego=h̀b|+zozo_=iyxnϦS,[7|tǑnWkұbp3oJ*{Y QI-:Uiv{tJB\ƙv@}ʕC,oMcqGT+X4#-C|J>iZjxɵ|J{CFZwj4=j4|iMmɼ^׌mؑ.y!sjޭKi/g㾑a*2֕`0R53L{ciVԷk04ljۊ-ҒSsutԔ.n hRBRt4=1!K(S4 GFKobԐsAtrg7$οwW7)/oOո3Oįi18>FZ)Ul;q*_ OJԤQ_j׏zQQ 5fϐ7Si227kTfʗ~;kL~?}b合ե{-;Vlv Y@=|U&fݿ“͙Y["' nu3gԮz)92 ۸K>ٯYE }XkȌ|?m۠oMIWarLM[vPEt,h{& nb~ڐkFY1ϬW{!3Kp+>/woQHB6/ۭgz43\9|_Zm2 n~ p v]LTbK<Ŝ W`Vi:\NwO6|>X۬/ 3"/۫uU]KeYܞϷ/vXv^o鵩žPZ}{eg]ݶ"ykѫлeU]o\Zl}AyiFF[yN+z{Q'~ ~߲v롿n%jcĘ~G-~>͑gg?90P4]k69~ƽ VBH6؁rGY4Jk<{3.#nXϑ^}8-eVtt4Snsq)s 0YYOY>܎BZ!)BS!dXOB>l0;a;)xͅr2梔EʗPfaQe Tx88P0T%2GXTrrYbC)$Wws)xͥ(,5#_ .C}E%'%OY/=$rR֬(J>si\6쎎A\,;RUU 1P4\f\DYI^k2,vE1-P4\zILJfOB!5O^sɲ(( h|2TUUkFX\̥6ʧ=BƘL5Ԧa  e4D!zB!죘OM8;o"w*P\ ǕM5T"%I*D$IE6giȉ(JsiMyDG嬬B^k.Nv(:śpr 0 ``R`)^sY@@,]e(\d6+ 2{L^DQwP4l.Kl)xvl/>¢j%d/>¢+?dgXxU-s^sY\!'7BZ!)BS!Vm:7ænG!dXOB>\RO}w_u&mzKO,yn)ǖ ob<6ƝC{?ߢyXx38z3L1Ɲ~Q:}-v8~<\Q!xvkϧ۶f JjNޱsoݦ4n4fSJN:Us3_;e×cri Sdnq"v1/)_9 k7b'PT=EԞwкoYv _YͣWR_^QuPh|k=z2l1j?m?}<];wʤx`|k޷k}ͣK \ k?¸?YEyסcN1R~jX* bR>$MSZ1i '6޹|kސznVS+gaSGJM'ߛjZ+_43ЅFMK\"Ѷ7ɮn(1c]J5xZrzRrl̈ QIDAT}ȶ52G 4ITQ_>:ivwfGRj [5irJpϽZ]Huk,@5ԉ#?tuQ>4b}۾զ 8CFlѷNɫ^ty$/- ^^f5+Ԙ#s_yнbXK lߡy7X:-Sq~҃7kcz-^?~*&4KjĐ:5g>P?yAsd?_jJXY-|.fedQ<-4@MKx |_ GT?j%tޫ s?O'=,uu\U}}E [SVNhfbBFޏQﻬ }VqF7y >oWw6Ư-qE>Ȑʆ4/rimb,/ÇnsIGSO-~}e8sOڵuM{*oƏ95{⮞ܷ[ZՍ)t-/7Zj',8W/wNoKѤngS%7M.X ‡/%.nvΈ+Qe/'=ܼ[Owu+@2t顮nZ]8W$zLY;ݲi~4ʡy<7? P$*** fdd85K'oF.YܵSG٪ Z9s O|c].;;߹ K2+::$t{'BdjBS!d6SBx8 ]0BN\2yn>Rp#,*9,  5J\2JN.Kl(%䪂)xͥ(KZb_Rp#,*9,z$l\RַfEQ KĶ^gwt,^o~ ^sɲKUUY61siR!̲؛$ݽRh4APhx#.CҘ"sT %I2v(=G!t?y%˲(( RUUaq 0ؔ+b c2\R-L2`.z!)BS!d<eyp7!S\~sũth*$y\$"3QE)2F"}M8u_I,Ys{ wVԞ5Ip(,Fvt^\~sAe﯊{!лƳޖ][ttmo``SYZWPo.0(0eQ@)P *.KRV 2{)1L1^DQw Po.e?@)P RPaKԜ*m{Sl8~z1e9G^s4E1e(7H$SF!KzERBS ﮈ}jp,ն/֬-2GXdnH{H ESnf"ֿY% mc}WĎJMwN(5WT7%@{ʷ)r9BL#TÕ4"T@L:*0@ii<> Ő'2DzO!(N@kFzr%##L͖Ukb=Ea! ɱ~ `5]XOBP$ Ծ:u l==5۱5 u$-)>Ý>$<؃ Jk&K?wZf;ȿʃ#Y\Uk;V{]b.w=O )1U>GnwÎJ=jsĸ˰@o=:?"o{P}TDӛf?~ _Y#^t v (Y˱| j'KJXs E׵;)wn5G:dzwTm>t,M XXDBߙdnm^R[;+c'=h{ToR̮8gZZS'S WS>qXO5#S7y$A0}J sbHws>XWStx_0:PpˏȺn?W|u.! >[vmb)^#W/,tl|uONa~̘Շ\ٲCSķo/eR>q!5f)$ߟN5&]ݿq$RY׎MW,ؼsң#C&toT\ـڝtuF9pҠf|+l;rTLLkzU7HR5~ؐ06$6)15י9I-ɣE-@F#%:}޺ degU +֯rs Rs cBx?|';bPziGM6|j{"W)pz~>J|л2=4HW_P}?gF{Ӭ\ڤ3 JMDQ(1QpYW69Ǭ[44V{&?""ѷ?l6}#j}.W΃^OTUJB\"x4)6VX8P9jv .xʠg+zqV ~Jn ׯӆ.r}j8%PNX: {@7oݦRAzsEg<[O vnSTn i+԰G KW35CGCY0$s;^0Ys=L|#x[vVۻը }';01WTfV-+tw_-ٝ|ԢFܗC\/k3nf@l;#QQQּ4##ѭqOO_+M3ҞFkҒ#C9UvޙX2$)C-zN1mo yڒJ+^"K%"TJix_Sg(Ld:hOl8c=E9JDI[5BhqA`=E9ˏZطKzrj1zQBi S!dXOB>"}`=E!zB!@ttB?aEIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/scientific_notation.png000066400000000000000000002441231423020056600333630ustar00rootroot00000000000000PNG  IHDRi!w IDATxxGtr@3066qifwwwfߛyfw]Or۳N`6htSU8 kk [:U]ԩS&MRH$_i,,..UoFo$3"iZ^zza۶lO+.F"H>}Z¶mU"- ]#D"|vªlDD"H$AD"H$4%D"H$+iK$D"H$W'UT_8(? D"|e}o$ɗK2vX >ME} q:M Ct~ Q[J$+'7fqMD-9RH$/ f;Jb@FP6?MYh,qļ(p_qoGUH$OX*B$k7+[! O c<}8}(7G.o }c[D%c x%1PaIk3}p?:Uq7}(t&޸o"D"㜾u'[8Oߘ&M{:"鍝7lbD%ccĊ~ϣ.~aX*41pSuiJ"0 -I OhpWEW%I$ŶmBATU#-50i!\!7 /zMg<}oD6i oÏJ}#H.?B_4]w/9?`d@A>qnM;&)L R˒yy%zFFEd0<_ERB[[ǹv0-wSTCjJDr%_ߌʀdH7qa$H6B@t!s>)o9H>3IO]ԹUDC5|CJikk ]CK6Eطp- 4b8D#FAѨבN6nbym!I3ϭf׾RSB>exU9p+\kK~2 .+ UQ`wشm/}f}\\L`ȇa.J}#|}b;lܼ5G$'a*R<ԋ T疭݇ghݎB"T&@h&R( H>>JjH P\(R_'zȡ&Փ˸ R.=}y[l߱~nO?ր_` l3А3qES^fLF~kkkbp /#O-wձw-?ûQ JD蛀K7}¡xhSɗA"|B_O?=>X,oGO_S^V̝߬߿#u=t7Bcǎu~XMgsɤt^h^g()zƸpsf^گL$⾪."2W`0 _@ Qy}\bb^2!*DX}YB466'^x`>߸‘ HH?~& WIt_;/J"dLX{5$úȍ$τk^A,nkBra*QO8Ycn43S^b@~}'*Yz~8HOq[Kw cu% 50s,'3#/ 4l{Pqˍ7/.ʣ7l6RXVp J$WBԵ?4}pu%T҆No$ʇuG׹;7`/OQp8ʷe˅g+=N~^;i8>`cm/mɐr ǹph S~/ sa1xd2I$aڤLj\$ߛ;.YxSRB>).I^ߜ@[ۭT5oDxo$ώFU~DCGGe5͸?㎛wL1S^.u>K}q7&/47 D d1.6i^|PCdjPO좗He%g_(0uK/^Dċg:ŅDZQ8M萖ʫkf#"{X??,qEMg#P(M[zN8I2.7fbs'WՈpNUgEi!+A}.k*>)˵G:ƺ ټm/8C;?{o3e%O%eqX$:KAA*jߔ0ƣ;TvޓA4%<"-ՓO`ێP:jb&=!>Ĕ533qpwGUķſ@J ^CS鉸FK =73t7~2k'o>q }&2]"\!(T1Cph,:r|T\@|>}-s~4\Ľ0?jWfIՄqLl@ 4l]-,j! >B؟:ʗ NbB7"G0CWw/Bꝧ Ɓt8|*pO p75fB߈sLis$|6Lt^\_\_y$Id{OO8wO_;~}}1QC6CKZoD^F3օuI>FXGiJNɐ0H4!_%D;y?,go; ~- 3n鉸~S]9S.$D'Vڞq^xW/oD4mQEDcגQQq&TD 5=Bz{1J$fLetaуcy|b7ȏ7}qoBH#HD|7H חRuBVDr8HD"HSHO'7+#'pQ176H$%f'{H$DݔED"P䆨D"H$4%D"H$+iK$D"H$WҀH$D"H /H$D"\AYhEqDD˅7D?^"H$D"xD"eCD"HD"H$Dr" xD"H$ BΔSWH.RH$g1Dˆ7D?/j*?GbbsN_044 N @Sc01~_Y ?_Da(Q5 )p8(4Oo0QKrr  ^0 N7 w {׉ 4-qqL;hc +D,߆K|R荀(Oɉ+DݖP9'W<MaDE"osNpk~")Z'|N)tTx?"j8^}ßD"H$W>_@^AU!Fރv5XܺJUʼni4 $Smlw@ٹcK5 "j/KF_ۈ^74=N i;o#CQl=̖8Oe1 \볶0NU6r*m0 :FWXPakxFgshQTKaM*)6w;jya^e4{sAC*DZq͸<%^u'-aa(qvIek2%Cmt!pVga1#24SaՍ lFy ʲ*aJr+&s8ըae19!fzm:N@Vl Sqtެhr%mϘXqXpX*rp߾ScMashMo8MȎۘ1>Yn^;2QOZD"H$/~B_CкVZc1*Gc`iRU>;_g~*b\.[[[&4|= .#EwiJA2>dj:{IgGD!QxjN0n?XVo3&C呗}<\00i9)?ynbUm:: 0kuC%oMuU2S!&  x01 w`!%Fc*8 s^szOUU%GSRRN]]]#F}|>;ck[')ζ}>t!+C;%ΩX7~^vC vsbq^ѝEN:>߇g8ֹ: _}]ŶmWM>Q_;ߖ`}m ~B._}򹭮jm坓O~!k'fųwBtq>|>} ;/ޯ."G|Fpɇ# QF )0TӲ?{za_sh}3I't0 M'L*F E4uZxAJ &'IJ<. hLFc ωͨcgƊUtO[PgMq676n;Bذqٻ|wqN|TWo :(DŽ;x;Bf҉7U))%'IZ=*Y J&,kl91!0s- P5( 96^epM)ޫpX< *+lbpþ-:/v#>X0b8RTmAec2!#֩F[ *7lj1a ˽kGZ> ?]c\9y6MX<&wD ls8} ^G8fe,X]a1> 23LYdx}qxa:׎sM ?}@˷YjFGYPesh+1>pbpSc'ot ŃliK0./(Gk;ւO!#%cB _Qj e2- CHsӳH2裷ښz:L)(cċ_zN[#Iu^@(}#ulA@G5X-5'(!2ғP9Q㭨I'nA?юfjjhvH X`@(5di њ#4H 5 ˭u#쌓IPsUAæx=GhId'?X}- m4Ғ <i;AMQZz21 GWi;^Ǒc:A23D}45ICaNwO$5@0'yZNwYgl,Oа8TGmIz2AwPBv7 5Gh8َNZHvTA8RsO Z|>u֟ LOƱl@5AJ@Ųq&5= jh~ũ56"p a@3i=BC~5,[%4ii(t 5DzZ;q勴SW[^$lG9ROKMZfLN64/l;it'LR*}# 43RхѭLc-5D$2B/#Jݑ#o J PlR0|>E]&'hlj:gARMIt{::o6H=Ks_1zU HMކ #,@UpGO9CqܸuOx8_\xƦҊ6jo;nn}Ҁ!mgL(w/$w?t%39 )+prTōօw[~s$ahﯯ({5L`npKm"*N) +)'EkaR=*[!-aիtm-pܠ겁^:ʶz<1 Ja|"t*l=0!KP${;)40m#RMaM ٙ6Ui7.N)`4l2'6m"ͮ I6ҁAvө0$ `4ڠsBn}zqBG7ftI cJT!{fli0}U6*x\l{Ž@Ǎk[K1ey , "*FcS*MI$_nT͇^˫7Psp"8\5w5no#(ͻ_ck{@>/fDʼnٰ$b/ɼWS4>iUP,S2{B1J$vX' /`uNxuoKat믦0׍H[VֽFuscpBUl^C\׉t>t L%3U:O1鉇pBW}|7+Wmt\EGBh1U96^ɆMh>pO3;k4)f\]=4XQ30{LGa:v %k8 Φ$ݡv+~Љ9t7OrO#k_Ý~%FIfuVI{{]M5ڍ^εsRc{ 6=33hLI֮cOs;`{"f /;{8v=g30Цn %*\3@;?æd)szz OQaJ\w0G1sv%v8~AH~xlq;WŵĨCX+7ݐXq4X˪wrUg3"/@$-{S{.$=tvb}t}4#D `ގ*K/Fjmq+yL4wq!MH@5H,/;TB6˿aR]' E' O4Z,&]W L g_񘊦Þ:^9 s{y"O_yzƙۤ fY{XtN!ldÍ1=:]x߳41EQxAe?N\<ֳDPqcSg/bFW+mRUK*gƋM*CFf%Rƶ=Q&e@wTY&T2)+nu5|Ά?NW;uƖb,*f d0NVܙg)t(UP/0rlf;u>6l^cix+f>7 H|nFxĸ8* :V8;_ɼY鹇ye?x#EJ^IwYl{֮LׯE9m?ɘ%19-k)Kz}̢k }k-%12K%wR> pR^3ô6xm~Gͤzp#xXV}saG"آ/p,,-Dk;@} (>r4#KSyI~|ťSdb1gYY[T|k.°s1|xyG3eՌ*;k1! sոhgxYa߻eLk1]Y]03sdե_(/YɠߠX(˘jS#za֬ϠkӨ6 #J}?MŃ7Tß9ê]AgxWT%jX yg|}!߿uDTWW;[y6V'UεQYW~[OY=j%4vEv^}?Y'u(ƍ,!Z:?ro*a~/UUTgQBm/UQHU4*'1u( C-<}-f1fس_ZGN`fk$e0khؿqk딗A/W1|(2uVS(tv}Z SFWϗgh0J73qƍ5Tŝ1.>[RQ1q|*')NgҶgW0#_/iOu=5A}B >h2 }LгEØ^I ]U'/A|n}-3aznM< W$zp)5wCWjkY6|}~t= |\TFLeP_\kğDŽy瞥ϏnV@A% L2~>b4P]'ad1nyu\=(Q!E^~~TO|LI*ds*O57>i@537' >LyN?;Cӽ29FKxxu/!d3K'|A ~W>f*CK㶕?%nKX4Wޏ2ΪzftdT3&qo~6pyh< ۊ$3giǔbD[d qT>ɛ9b0;K >PKv+l"wL>Z11O.xLs*o|6%M6 R"#۱(FS׹"fq5E,00{Բu>v uLnj(utuV=Cz!&Bxjs> f, xF1ϰ{6V¯]Cmظ}/')4٣LT==A[cLFFhXshXn7$D^#5'IZIbZ5;7yÍ ISTݧٵukPrÂHLm{ټ=NSpbfVebS&u;c>:`ʒ1DN l}Gꉦ9qlU~6nCC 2^L ЮlWN? -`P"n+]'xwfvl$']`ێ>ŀoeVU&v<̎i<2m u f{#7nPC ,n j<6a˦Ԝl!cfu۷c!ZI,^:E,.fӏev;'tOyQƐ71ch{5=ٺGP~BX#.V͛[ߌS0[nP4]l}=7vsREa-=tXsnYp);;9X_OohΛa lm9~-`JIfBQ8c+:ș^? nYHYX4Zϖm9XsZɧhԽǖ]odM\;,4~2F 0vpR}X·^o?Ppvkll Ϋ9i;l`P}-]Z"T@K$v9Ѩ@04ȫZsT݇Ԏ,9ՔdvH#ӧ1fSp!)DRbB2Mr;r 9vh?-j%: ذ =:fJƒPc2cQRJ'qk/kMZV,Z\>8&-pXO 羌xBg఩W.>u:^"~PCDZ1ĺ:莐 GFZMV{㤤1ML[Eutm#Z.z᪖X3 օzm$. 0M^ܠgؖEGk;3qc]vPJ4-„,]%N{w {hk#bE6-rK5X7mhXS,Uz[鎈L µL6_>FAlF{hoa@AEwω:쉓؉GNֶvbeuFh8.Zۻ)NIsg3mpYdkyŻD,H,+GӉwwKa~0xW,bt5ӓOO1v`ϥ X;K/9ūeJww:Pu7Ug>m^i,ƅ%jXv3}7q uk= Ybk-qVΎHNFϟ実l;搪solʼnvxq7vHr"뎒y,n=]tF '3#ݴ 4pΨ0m"Ytho|ThQuϹVN8ёjۿ;7'A(=t{P^AEpMix3TmV53;^A<sc5c+9#7;ޖ,<&~hd~y6-zLn; WF2rR8Nٌ?vDN9ГBMU%(OS/{JGDg~MX}+SYk4zE#POA(mQǴ*?^=Љʒ`I6]na +4m~rS g*ɰxV;TtS083a:S !-MJQt CU64RݱEL]XjxcĠ!<.},z5ir A]'F0j k~8" ;05o؋[\Uf4Tk^c=Q$aw7]>{BslW_s[xoP>V,E ~)^{o8sT0ϰɧhL}K O2X` 2"Ս޽spox᠟md\+_W=?4U7q׵nR 6ngߢd̯R6*b=Zln&7CG/Z &`;Uxw_ qK]շ<[bU_ٕ/`sݰĺUes{YHvt7SL;C<7 |s!n>\1aי^ϘɦJ:~m;qϋ^ׯ71X!;3ľW ͌6\uyz&)D3=ӭO_< yRj&)TT zi86y#_0x,eX 5K>΄ Uc 1/ǘC9O斥߀6r"#ƣD14n.fe_};#̡4+3[߳i䧨FN2?r@QXa{UOoUX-\?~7[q/Hꇚ#!_^gDʋ+Yw[ܕ0q/䔚/; E6׀o;y.%tl6nN"'[Q('հ9yɰBia· G4 IDAT:l]T>~FȾ>珂Yh!KZPda{*kqw" хĉIq$9{/Ď^ Л@; PC[HHT;1|k3}>ΞWTS-'֦[DG֖"C,+F`mTvQPKur;m *2őE]C-.5m(RK)2GfVРX$]ߨvzk5"053QA8XGc@90+먯!xQTջpUSe$R<q,jg=֐-ƀvzȯOM#Qa~5S][CU)pJd?**갅FEZUxꍄujQ'kꡨt"q-*kh# UȬYWMM~XqPS@}-PfzKm)vQ UUSU_ 8D]C5Ÿ`]Ȱ@*֍o98@Z;vQX\GډBf@څPw:7&O(E=%Vr"Û}Zj\Blz Ñ]C]C#UGkֈvUR瘟J.jxma@dukp5RR߈_Df?$A6+TޤS@5zch'!7:kw\ UZyh'FHocnXº1*5[ǕgAL6}yE٠!K=GۊDžk(H^tӉOT#]Ms0¡֟&NރdqMqINXC<8{]z[?۠&_{u|6ŀӡ/!Y0bB=No}@FvݞSNjf (vn\vzt5˃_x//4맍gh 0j5iw-Լsjt(/5mBګnz ӱ夭Hbh5IA Dz=I7!Dkǐ]C7ki̘ ۿ#%fq)È0Wȅi G' 40A4gɲXcnҙԄQTKcŞ|:'AƑDH,YEW;)hU )We(tkGɹc>)=5KA䡋č/.Xm(:ù;{zNIt{Jd_ `R)c|z2s$Բur"1΢3"uro|jαp6a*H( bCF#ݓTr% {.> lZs $GHC(K7&ΡfrNصRx` VOCg:n6u2r1$u 05QCqҗ@(;dm[,f?oGV?>ml^ 0qfr8\tN@t !ɐ-#h-qI=G.itUx%E$ņSyW8{.>@:5F~aѽL֖-zbssXMo%.!Оݢppi(R|%ދ@vŐX?rL S# .BV.Iҧè=Ycg (Ϫ5@L\Un#=-LXB;igau2$t}#'&u#vVh./!1$uuk_zL-ܻyzV]8ME8:m_o%tV>=yXUtK\Я|(MgZ\.5p -Xj?9oI\1hqVuu[Cs򋦶hUަƛgnut"x6q45Ѷn8_35&]wgZ>kw+hx '7J]]ݷzQ# 7p{`w#l'N!s4JeY*iw4)Cz`Q'ӹC՗s@ѩ vтYy2>h9W>9SO #0;*˧iTvP^ZЁ:Ѿ]JM19yT}3jɉQ| PM^Q%$&LKG?3aPRHdRG%f'<,OM!E42a"b1 QYGna8R&k~jsr)o c3Y B.\O1 /P#rTROޤNM?HMQR}QLJM/WE!9yE421l(!\륞2q1A>aWɽKyAI(uR/8~"C°oR.5vˤd|vΥM>͇а d3GPV@ΥR<510C 4PM~^0qH (%;'3#Rۯ#&/ၸ*/Ir$v bWTQ_kTQYUAIqt _4ňj-jltipO;Xz[+'#s%*_A}DjW+H416aqLE;.+=b:QI{{?ne8{K/XT[bN6dz?AUF^jkcZg2c\e OvtŇpZ]cX׃6hZY*brŇy(xYsZL -~|ZkTۺ{f1_I?jwi~C`6c5__x~̷yY7:. q}eoxۨm)5B/~M->~|oԧk/)ߺ(,ZsK;5CxDK _`fup3*=u J$whD"H$0BzdG%nvܸNH$I[@D"Ce@r]"!d/H$H_jDM$D"H$w K$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$mK$D"H$Bl6R+D"H$D a2 77W@D"H$7b_fŊo2H$D"HAed/H$D"!d/H$D"!d/H$D"!YD"iS0[<0\g.j6vU+ G`0hL;+Dxp:<`02 &+ ;OPӎc'2G&`>D\j04 z`7yMkײt!ѽH<VhA>aCW86sCLLߟ j+,6gS:{ϖӗ 9Ȯl- N2waӁL<1JLAZQf2Xv Y?`mͣ7pl]j>`!ԓc=vg,edDF'n2j~6kM4 zËnCĦ8z:~-bfR9;RgmǐIĬʀn:7 JHݤTa]:'LDډM־46ӑ)p:M`'ixRw׾gNnSq6r<Ù8av~Rec3987M{3ǐ:?ڨ;evq%.@7NnXĶt+19J9s#[g pcn5RtzT 艌 Dž`Xú+8݈ 76LGvEx=xV^ bQ8.\}xG㱚omҋ_|vK$zut䛢koL6Vw>s_yƼ}|:c9x V*mf< `üY<\K1#1Qsf={7|qÙ-Kl!"&SwzgŠ8gaNX&8M[.Q0Ǭ:CF &f[r+>XuaPpp݀5ncwﯥ`Up93iƘX.-CT L_0l џƜ]zA+h6Bz';:NF}^f|~NfS}.KbsQh?"sva)d^Ŭ 3^0f1/9[q-TeaG )Mά{Xl]0G8JGݹ/6_0k""/L>ۂ},V*2TE`Db&U~c,R,c CF&DU/d!V>gt4nv էx~?mQ~2ia #0YϿ>+g!bNJͅ}dE!}ѫc?3/)덈lV:m%$IDΎ<xN;ٳx_(WhL3~_flV>>3 #iATgi쩈bD&Oz]ٶˎyP2#|4K\B٩L w@vha/׾ eA);3fs>Q#11Vc!hdʊ2 ޗAI0z(79F3Vÿa]Q;^q*[֥ٮ= 7)((v\pȗ|K P Jz݊˫[bޖ -JXebEwg(^qb,"~Bl|] ~>}P֊wߘ&;K[#z?&7Ū6NmFGE\ױcU;W|,ޞ&?EVګb@xg_ i2|(6(w:)~?H|K!Gs[b¥P/dѹ$ө{4֜ZAd.?7Y;HΪVʏ+⧾).CxĂ 7ex_a9bǂŇ ݸ_?YI|K BbxrT+RyV tц(~"{?!k3[:y[uOԟJ3]e86vzO,?.p~,}_,U4\3C9+];鯋];g??]|l;űzݣcŸG+V(e4fLqG5w gDeAtM/.8ox*}4_)I"Q gkYT/~7Et>U]piߵM2ql".j[Ev;w\G>9_&}ib_-3~"_ԉm.%tCs~-"{76ic^x/Y}QԘh؛ukNY-n)>6@Ďح\`!Ѩ+v+VyHxOɒ`Fh19B2C|]v(O>ƋQ^*AY}YĆQĬJgR;_ߤT(«(o1@c>nNƈAGI+L|'z:MkB#H$6rtᑟ>^j72~ ^ٶFK=8;@JK( &d~ѧeHsdG3*Pk$wV2팚LY]T}{Oʐ&0_/9g޲CPOR1s%ʪ!.<j=/_ƥ o kG(~-;c8%@>1#x" 3VfS^]Bs-:7a${((m@FN #[;>׷[ t%(~<$1l0zŲooeh#ϽbmC 'hn*c '0,8W M_$lE"e`o_BОuS;RG)Pw73GW78]^"ecGלÈV2@/֐ #๑-#lK=<3g/qps:yèGct0n 3ʯPC̘yNad߱5/_?ٲvMHЇ7PR}2$M\ȯ6~ٯE9:#+j7&įZ cɧJ < Z&jaqMjͶVb -]׼}}@i(LV8ۜ /bnz-0̿B#H$V`;q{#1,->BH+ttX0!1L2 n~uËYSo'F͒UN.NϢEp$<¤Qژn $r<@e9:镌;=CXme\/OXdRUZ.àؾh)ޡ<4ī6ɨ>rtmMwP1ov1")@+T;-2-ϝzjnUOWj P IDATN`"MVp{~_<< ԜV2.'+sߔ:XBQ_^}G>gm])r~ښpy4ǁy;=am\+9y'C rzcZ&. ag} R׮ף+^L-jΰ`A1=|fiJk.&ݽ5jtRKάL8@_п|< ogDWV0,CTusOrW-Mq7CR'տŎ,\zS&ӿY+maw) c0C[ ErP-,f/}K^-FJvGjx⹟g. D"HVe}oG?GлF-*5}mkxq Ͼ Oһqŝ6zٓYΨ彟ƨvu(?ƴsظ7ȉ|k A ,6ғ#V8BfE3uP flf/G>`M}ZZ -ϛcn{G3'ڥhfg,g IN V#w.al?st1 W"*2G,vB}{O&Gqq`2 ZW302<3xpKjTva]i>֋Tvlӧp2w3x~Z0aۿi=ħ_".C[W#|ǹX8}w&ŝVC!+ߙ[9?}̟ӫu f'ebCf~[̠i[?5R`ks>eRWVk06X.z_>ɱZЫʅ3mZ=mO`q_^[ygl6m?J}o|6C el:/ yC}bzM_W6sx=A_0 G/~Tīo Fwil>>\O[QqRS&vCWwHZ5śOc SRku%wk0P jԅR̾AXc`GwKmLf `B|\&hnBi9.8pԭ/"|A(ZW\2J v` o\Ft4Vq:?)}`Rփ(?M^@\NЮB8s٥XCҝ>]07Z.dBlSpy$M j^z!&܎j;PWt*at; W0 *23Q#>I[\d&DX[}R?:[Fj ϒ_vr>ѡ- ?2N_i*pHOY4ݥpyza!v.!]UƲ<Ξ/ū+"16]W+8w2 O>F7.c}uϨ+rOm" eSbo:-ԍޱPٳY8m=x!zC쳧(qc6׷/FEy]Igrv`O BSZ7B٫ >Ea0?{KՂ0\NAdB_:[zW"s  [$zEtkq%̾~X^HAm`ihK(Ⱦ] &0 Nq=~޷<;K||͘2Z$v lpfFV_>S {%ُRؼa-!Q 8Pʗ|׭y"V6^xԋ"4bN?V-O+Ls]sN+A!6ţj١xb/B(^]f!+ 4e{]ŽY-5ܝ-;xJ'Cst8D " nu.dT[ &)~%Mp?O="5j2T=Ğ?IFw2l1(9MOOYԢ?U2ǓE=Eަy>xZ9FLSPhe̺kFt\-YEϻ~+NUŊ^BH{QѽD1PjldԜY!(R֠t6f)ÃD{^1Z ~tu:k5Dy񽿬jnV;T}1Ef]k]bϋ C[RU(3]ֳxm1ZvHI~wlY-pm?%{(&-;]^=Sh\F*~/FQʸ?=ѭ1He[BdoxC I+O(kjϊ??8D wxQ+V#n8;Obpg/#~Q\IMQCH<:%[Fy XOOT *dzia?CJQn9SaUS2|b̠}yl[ג0Ztf[ҝl*NcYu5'( }Iv5eVw1 _ hTW\ZS ֲ3-2gOi4C?ʏpb*.hIۮ ܋?r5;VI˲5XUuW#=SH߰Kkm3?L-׮p5[ē-g݆×ׄb F<ٰbŞ&[Ye(`S8^Of`el+ vLyڶ>yGc`ٛX)ؿ'1n1>_)52U9_ELb"WK.pG*ÙDv6,N?A To79A􈍠^K¢|4za (WsՠN)^ם(#Z72Ҫ<@I aTgna [lW{bGѽ+s,j \{gavj ]wŒ^Ǣ]Zq<=A')H;oʣ*ңG7|B^pJ\ЁSX+OdڵJl/%'3w>k(nPsX> zZltOž X?Wr~:u#)ƇCXr?V2-h?ϊy8Vaўƪ=u]'jH}~Xۮb34$ҭSY c9c$1;,\e?4g acyՃpM>;(XϜ%p4C>.Uܣ;Tf` U[4[i:tLJ"Tź.`˩bu =F`L !&J`N[٪.ŠdX5Kp8"esH;ՁC(8xjK]_´8-k"^2k; ,#Qr1h(ɵjmd_{z'1Tv#`ּ̜>3g0cƧrBl_1yTG.5ܲZY*H$6Ʉ1! N!uPwY^sc<pm_s<3ԇ 'i1e4ݜؼyყio>};'ӫK0;X;gop:&%ŷ>mQ0WY>)wO'.gCI@N>~xS%+w3xgo0w6& ǧ.˗L~_<>VkKqgH:ڪ9ejM_3?d;I,_Ͼ9ς?b6<S9.]i<{O=ۼmܑ2*v-cm QQ(>ϙ;n_0JeLR uhYe+R?,QzuKW4W<o,.pj'u"n3\ڬh^zǴ8rb=wNPOnfl>6)ec_vF[tUV;:g>_.Xٯ;VVNj\).ٖs1swcCt\6vsN.cBs{O0WX6]h,<꥛K<9: 2-Νc)dӲ%t{~44Ur m>20yZ ;u0¥MWPkw?YHQMQXXx 7j̽\c%xLt:DZܦY|V]1q(Ul^3pBb0# z`ض_Q5 cF%`ua4ˣA,NnBk˨d%m [Hx>1Qcqܘn+IȔ)nX,#YE~OsTgq ?OUDt=MeHg]ŹY~ 1D1xL?v@陽^sx ȣObUz +EFqC?ۃwb^rJkE|76JNbMPHI(݃4F[X eBbu<02N I!VV̙KU`ר;xdBLj ʋl\u6{~u*oZ),k72L审]U}Xc q1(S5.;ˆիy$jȸA;Fv+\۰uۏQ\/{;ftNf>"qdz 6J3Yr {NiCP{t*}Yy%I_ņ=(RœzT&m4 c+W'#Db=Hb4iVT =GCihc[VjAK갇0Ω7;FVt+m2=&7a.8kVѩRۛZ* L{5O+47z4TUpOST\\oL%ƻҳ?O<䓗S|2H$2|+ܚ=Wj;rcվmxNׅ-^uFZuvPsd=F,V˵y‹KgnrM(%p\ ks`ǍS~yiחhd(WS%2V-2L^m ouHk2>nCq-0^[b4a\+C꿡Z0[[ e e4L oPdaNںT3F֦,˩?VrC.PVPvj7㫢m0d[D"-tuڮyNnvW\{MwPJz-م;3aK楏ݐq[2Bޛe0|| >WlMdJ|a2t5涺 a^ȸ M7*$x\ KSeh"VD"H$ !xD"H$ĭ|8] %D"H$ov- s%D"H$o5FD"H$7z^uhd/H$D"|9/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$D"!d/H$,Bj_UC uknS3H$Fɤk0M]Q^z.6Ajd/H$$ln@@}YubHZvmQWD"|h] [uYb uv:;zYm)xoMxK$;z.4ߚoM[Y}|{%S7ڢWauni[KWɉƾFŐU F!d0xp'ˀlljU;e}ԘM6š4qf/a!IՍRUӱ@iG Yբ8u%s.fۡ$*nJ~г ;F+0PjesYf3q)K2bM* BEIlM2vc:o* ]<&>l"Æ IMmf+7K{o8Av3&Kw\poPťދֺaYPU}1~>cLq&c1[D{?ۇwi[+{Y~a&.۶]v/ 3e1'OӧTax`Jg.Cϕrֿ+U_+b^`W;έy~ckA;}93f% TRW>qm3[4FNn]%8LL׾^d ޚŔ/N xw`maX9kkcKڷ_򉁔|7?̳(*9أԅ_?Tnkg<CeG0/t2ww¬^ IO4cXDxڸg×OSKBqd#Oүmm9|÷w[e!ty ̯9/Qȼry3r֫4.U Rv?7e}$L”/Cb-S1*$>Cxf>b# T;pBa]o.47o"K0,4@ÐEsd#=fh4b sHOސrORI-Vɮ"[4[ZrOTD:)%H_6i7Rt|T)hzz4obXbҶcRs?-9~.r4H+^(֖>\}IbY f/\'ŚrQ MR k MۛhkK7--!lj:'}2]ixiOs?VөeRRoJ,g-;mYRRRsDMʌ=.-3WqN_'K^o,إ#k9?,-e?*T^{>[^&UܢMf?Hm)f3IlZ$]= l祷{֒*uƁ)xވbvbKɉR|\RlllYMRF zh/J )1wvݿ ,RfF7)KOI^"]OJ߯/,n`tR):e0lO!],]|UJ0߳w- )Ә9h. Y)KJ;̶wӿ&2%!ɐ2\U']+%$?`䜛3cGI:b4qvĉs]˺%Nrtb}^hjCX^CҦZ`4 (ը5 #HOH0nwYt7GMٿC%q 9}sP: ,?GQ2/"z,xWj!}"\]6oFDTIw Ɉ(vB4jۂFƏ0Dh_(h EzŸ4٬F> _lr[VQHH"1)KnkUбPz6du%7UҴR(s\78yVat[{v[Z1v'Ji\DM:eb64QpBHT'I% I2hܸɜ!?b M3l@BpdШm3H=> m?<_&Lc"qs9>K֤rK^GSiVEb́+RFcgI,9_q ֊p|u\p!_>E60ɧ5r8?6W]> c:cWfs}7ߐ+o ӷݺhIfGvl =M=y/gʅ*dV!_[Jp{6¥ Smܰ ;c͈'Y]LK)=6O^ƻB/Rmdgh;;7lz<.i{[A:d$Tٺ6ZfϞs%K/\HzڛK{شlV%ڐXA]乏?ei%g^ֺaK֙:dv슥JxWEجYhܸ1Ṯ+Cм\N=IDZ , őL$sQ-R30u\ 9W7fS1ds:M]EɮOhEoe7gj2Xyh*)/Y:tWر;fV1t)KfC,]Y,yhƒUcH2R19o#sf,DxmPԒ BR#RvYJ93 4bj5fa*/3r3Z7\?!@~|!d>BBEHDU%;^!_"!"#ҧrs;M[ŠSv䛽޼vBBU4ۭmHˀTvMm뼚ƭf/ Oh~4?z{dtYW2>۸!Qu~Fafx-,Au|7Ӭs'Rر]h:L%$3:kƑ[4}̱1cYDl!k/*ã*u(WG(}{3hH^hV҄^/38g6 -ek>qAÁcJ3츗j¤?0E#5͡ |Y.1mGψN-CV*/by}JZd7 ;}c,Jr2?~$ Vͥ3d[4wYF3φ՗F*ck };Pŋ_՞L(wZ'1YڭxoƤo0߄MrȫpƁVk8ǒXh6MO+/BG sf>&"(R4w]F|@5!+0e@Bf,JN˹oG;lVqp .0kjɱ~٢%;6m[f8ckNٴ]pmKrPv߆hcUѴUyvʟŭHA2ThGRi i.]S"Y¦Q};G vl"ѫ:ʥshOcm9)V,Mfã ]nUQK=ӯfK Ҭ9)`ɢ (q|VqGW0Z+V,Ow io7@Vx3jxzzFM{ 55$bdL֫K {œ^EZ4!8_!V}{EnR,D֍^Oa*Fեֳ9KRq $ͩ,ԫbB[ xDth"ܳ8w.ÉBYxjįde5G"#{Uj%m2j+JԢqxcٿ HU*{t*/*ՊQRd^=Y !r擛"2Q^#V$av2h@I?My+PzS~Cj}>> ]p!dffz#,{'wƪ͇9$7fm$hQGשgwݜpױz/KArhLfeĸ?!'ygBʎ_+Ճ|9YU!ѳyU\̥mOl9֍9\end]Ő.4-+d\<[ ti<Һd\`բ8socŒM5Gu:翢9"n9kܘ<,5r,u ʹmxjk)U>K֦S75WY7O5FɾVJR)XS⏟Ǣ^țkruTaZ0V W0^72&v,p!X,kГOzX^^+?*DvqRѴ vs~t9OqGs%цѢ()ʎٌR,Yʊ\*g9z<1:[F1c^9;HƎ␗_}?˸G^GBa3D۰YC 2gӼ2)~blrlº.*(݉;e/xn /f7n8ZPxt̖_dȳTş$8{,YH!4vo6G0d*РO7q ݐ2/0oIѮĞ|,QK]޽Z] Go/OVyoxЩ͔j5/o퉧(mPAԱ UGzڵ8¸65H;3T,_ zw7-d،5:);Zj[/(ϸlßgti3ЖIơ|s )p,ɓ~j5. SÍmSx{o(_ܷ 3)ݠ=%Mń~^TS%p _2t`TH DeM$jXRӕO~Ĺ}+͏yѤe[= oo7Y]-4if#;v`„Wea1u^Yg-BAE᜽nd6cZ";ձ ؿ|[Php 9agAϒ7eGMVy}\Sm_޵S7TGOg^o?fh1{5g[M|AYYvЪPșZmNJy+Hhom݃K/v/ۅNRłyd AXTo|3{cŖ2_jB)2-_.ޔV߈2Q&l_]e2+Ѿ_sbߐ2̨^K1f,DEZʖ7e`IG2 T סdbqDv]kl8#FTőG?c29**c6@Tm%alAmhӲm>BH6u[1m(s&}Z᭗'ot^ <>bC䑖d\]Z*k5=(< T-PXʗjkjx.˂MH IDATr&5Hٳ})jH&ҭjvi/|9m%RDy.V![@58:7D4}q-_N]\3A|[D0<bJ́96ш0Lh<9jV+qhwʵnGHN2Ztq**5|ε|E+¿7U9D2 s@z(Q_> LgR@ʕ߳hB xWCQ. Hh |CꖙB(nGki #nKV ./@|zR3EvEgYliT5šKsXReg[eK&RV⎟?!HK-Lb[Hj\?8]F&r(P E@fcU#˝YňUjټZXmrnAҠ!_aaYE5ٙk,lzaU"m27 a$U琷7"P\ةU-JC'|:ZexaMOAnMWV uZ.J䐁EnETC>3M8lnY,j4j|XHgB}d \s/ۜIDf[U R>KRjح1 .-d,[s.j%DӣJt.ZD4[0+sQp1xmx!keѣ^^Π[a`SJreq3]X8Z(8^B0zy|Mڳ1&9SXr܏g|fe )1Ĭe?ӿ +Meׅ֭p?lضt^ӭnϲIq#z\ _L)X2ghWA F=i7ֻٺ?=!SEʹ=n6z4sj-FҥQ|56Ƭi3Z7AHy5 OzX|h_O mNr5#k%xl@EF.e׎̜yGCBKc_pVFLHl]:k5q2W&Y~`mBGQq& w[x㉴(ȸt>c ޘ'Yr>a$]'_.gtnZ@7ne7sH-׍O!YzNX9y0FKiߘ9' G|Vr NG?f4,]+z/ co$U@!cLyl}[P6cIV|?UyiXBy+ Rϱf:*IL,V hR=^ ~%l"I8'`BͨCxٮV.Z*6hG \mjm9VC=+zdQJL>-71?cHEvq-&|N;E%ګ"c?ˠݽ+J!5~ u&j(\Fm_j[~|}7k(LZ(IDS:UXC?$s;  R,ϫ# f:(< yZ(7:O`y;馜TR{H4 = *۶m x͚5qՂEMxk0X}B)-ڱ9?,ec\LH#,uϠa<&"BEJ>=-b9{JPG5{ cWH s-fcK-5[ Xwu~ZN)D֘A07f+Jc,a+KdMjuhqF C˕F.q hfN[Ȝ .'fT[oؓ<ּ,ZZO{@iɔk2Kdf?q?lZ5}cZtLY1iE܃`)3ËX#pvnjjZgbs͂N4. yiQnE?FQl0xw=z4e˖M:3ƿdk/NR+$<i29 ^W@$]'-ӄӏaxwfh9{5i qdCD Qߊ]]$F8ndQh ]!e0fWRݳ]6L$%ȾjB#}h7ctvww'3 "<Ud a2 Ώh6*Up).\ K/AQ|.]رc ({Q -nϋ |0ߊ\J_ɡm[CY7\jhjIP ZS>U\Ťopo i{2Kv; /_{ي}2۶0Av=O]_;]C.w\x "!WcK@c^<4+ i]gRyW+ .  °M֢\Y)Q>yz,>UEB 9fQ5'""" ^| ŷg\p\ I]|k6a9oy滕a9Xiva^ q/j .BjYKAb{p\4p\4pƟGP#'_rq\pXiv?HWiy-o ;ws}p0|/W¥ .Pl\Ԋr 9}]43h.h.>B .BEq+-.\4 \4z]x\p5~~UI"OzKw\pa:#pg]Q,Z/a=׌OWKw\p!gF gPZqV❋9/qu7E8X["wW~#sB|'  .BSʕsQ{\NbAvss/R9Soڃ@΍xdSVy†S~JΗ'/?LiW蔹 .}bV\t/Ω? {N82L0B<5ɓP2"_Nzqa3w^O\ . Źӽ"g.'9$Ìx?ʠ&_޹{i/*8Kͯ+gPS{v7<;SEN]w/'}t⤱ߑ4>쓙 ?qM#UN^ ʼn9Y9? >*/S;\p;/j_@~A8x7"oKP>ND>p!T0v=H='* 8DF;6h9q>~{N8eʯ8xW5 .'uZ=<<.JPYnܳTL ;*nA4y[V2V\@VϞ=|p}AJY0X$+r;I,/M);CqI_qLŽ]p 14wm)O8!_#/~)->;Kʃj ^E 8釯kc 3Z-ycݬ;yv#}9'M9 BewމVvڔ-[NRn:lقhKV;w..\K.jJϟ?_N(:uD  RUwu/r4^5X"bɒ\%^GUz]p҈O6W" -,W ;7btmzPfJi& hKNB t& w`*UKX2OHGJw.M- @o¦HH»%yHMFH_:8M|Xrt6H?ϕ$=nϣ( \HSdtm >-Y*Kٷ WCt4-pp„S9߿?f#44JPw̙3ׯ'O$99Y>}iӆ~IעEZ* 2hРBzH(p={.,Jtp~}v Nd^)7N0w`ΝtO*yE"WwNi4#Ƿͥ]_:_WtԳiOSᩲNѯ2MZ6X~?%ӭ\EHwW㺶Dda8=WX 1{خdˆyޟ(U$.:7ɺɄէ"%OcA m| ;vp5ŝ:ȮJxO&wU3-ymJK׹]lAג}_xv{qUVO' ,Y~UѳmQ4A]2aD۷7:m;qDuX/ཙ{ $K"ÌٻkzG۳sjʔ$K$^]6ģJ\.1.R.|~mZlɂ x7o*d+Ff,/|B=bU&[g̘A*U9[~`yƜ^#jo ˗/b&Lp_{ t~(}Ѩz6T^bθׯB{ GeqG;_OéYG6vŐ&$zK(Ʊ8I`lԑ!VLJ5^^'R c'H/< Z씬ޔ=yvVlhѰ V%oOmgHU>Y *ۀfXq9C&QK{_AA2aѺUmnMY u$2؊bsB<0ƔMMٚu_|mrD1VujG3_q)w^ AvS<ҤDP ۋpGtt4Æ ՝ʷ k?̒%KHHHț4iBll2##CVE!Q*G,t@ ua%|6& fDyWաc*Uޙo(^ 03d&Jz ]k'H%>f+myoRWLrob'.\q>*$WCq+%~~:2s.q"\QWY.p ՐZOzFt]m;Nޠ)iOݥs.׋BB5#R`>{S<ɝH U2x*{r~^~8VmDDd| NjS6 y. vJ z?y"?a{;Gy=?GD]:EWRvVmۖg inA -]KWgL}\I[7ybs'dѦM)vn9Qhxn#q_&>8gīJ$p8aDDDиq\T>}Z#^unٲe$&&2vF}N!IѪs;ԗwGw/փ-뢰Qdt È[pmkoVڱmoNJR3J'>4ཧQ'>62nkӉҙGtF\ƣkӒ36I!Op"qədsE.\Ih\dUhځi21^zv3c: bNɌ n#.m{gl*ee%V$Q=ekg#1-6 `c]߾YVޱ̰:r#%:vPҺuk>ss)d~۷W^wtMv'x7xݻ>ǎE;Ki j1Jz2xnQZ* nGS#a(*Y2KՠR) 1^4}=}_/Ħ-ϳ}AEj+8ń١jɻSf2Q$!o.ifx%f%S /RA#Jkh!a-Wgc)Քu{k9kGS1͹wy)1Wf֭k[({sFeZR;0cubnS>f2 MC ;B 10ޜXLٚW)ߪ ǒíl m{ރ$%U%ZFWFick6u>|w2GS&M~t!vV} uT?Swxfg,%i۬,D+g?rw$_G{8ʱiל  q@5:%?Nfo'*VM,Ēm#?Qc'bԼ%t B(bޱcGoK!P];^ffY믲?Z#>bBRa+Cn }Ӯ4ȘcbɎlb`b= *E`_||CJpH(" \ g"Gf_}'^ҹ;~[b@`LG[ -JZ8t2$p/iգ֩Uk_˻vqye;&Piݥ;ս dj>'`ʔ)swb~7nj'NDy(- =^tlU}=-vBeXj9K"UiOMLS$m$bּoˆ w "5i<;SzꅜQa3]j >:$wTI[(,庙Pi(W|Gmeǟaw: 26X>λ<澋8bR4[!%1V1P+29]pA(Bq_ִ XuYfrg xK/ӎ0~$ČQdc[0JV$ 0SЧ/]ejcV GQCa7f Y(.eF4.N*#o& Zf_W*UˍKظ5vĘ1cԲO=\A6,qWS[;][YYf/xׇ  "T XPP콀 AE *XQQRCBO_6@}g%lݙ͹瞳aCOs,^U;NǕKnCvΗ i7M nyysyd(st˜疐[MÁ`ǶI˙0n%'=qmKoPX`ߋMoud9\Cjs[4$Zg(?^ƴ7`W?||>/'20ӏ>yhBqyvo|:ӸU+ eSo~+6q/"#_8;vl<2k֬rYS7^pgP5zĚr9爲~{鏱r;^|-^{ >zE /&|OSo+USb?óy鱋 ;[%QdFz(M2K~).Lxctej׮ALn<5HoASrj]jW4@xPlԮJQ%pI+P%ul.S$yƸU.鱏;5 ~oF`Y75c_bIʸvȲT6y;ӻGO_ЪQ[/X _$!" TZ5#X_Ņ\Ԉn VQS'5 O<8\[A2nrs}>}7 봸ǭt9kMۇ٤ {LVR?qI]ծ;Law`z0Vcu;O?緩Zs Ј&NGwX1?qba)Ak%Q6(Jl2{LSM$V"9YRDQ&(s,޿3Y/?͏({Hb|J=i5αH  1cǎe~/s*:Mm۶eʕVѭUDĿb@ЈɓVN09AOE=i"qFLT>+2Ý\6lMdpҨ]uEԳK'sGv'[pà:K圳\jS"uT=8<:t>IJo`DP| ͎%8%M6OMOVPޑ};lԪƋpt?˼D]dI0r?hР3sfE'jvNwq+eGR&g4xı*L(0䢜hw}_>XRԋFN=~!t)eC([VȧFjd2-Ӷm%T7k9P*GO{_9.HX"scDl`j5aEޫ0r1 V:i$9[PZDz,HX^+Gs%FCuJ3,nRkqS:FvL%Mm IhKr93GcDOpƇBC/+~UV4tסji%*}M$D cМyEWIՈGJAnRLO;\UW:H$P^j4M1\&^Y?&D *Ej]WaZimbU#el|O1)4r x(˿rE wT:SeYY(Ǜ0"J>fE1-6k)+ $\rC"4wAb&ͤ8+ǎt)¯ow:(JldI׃1PZq%Plr.;U,x6s%-Z/CyS9E5+a5G sӨ^V+ܯ<%ME+.JT"btyJ>_QSJqi^kTα~POUOV"Q;9j'Z:FK9ϔW!s5!uӽ>G|VImb/k$*X_ϱDE2= IDEP>4 %BNF9QxVg$\NEI@ʝ2pAsK⨈s,D˄VJ|$Uf+ =?Pr9U^kKA E)NG~s$DYL+ 5ZQVDn{aUh%zХT6B@ٔ+桸UJ9c-,f8zեB GxD"ż+)oZV(rSVN%P,O*4. VnQ˺gLQH$D*M^5{1M Х'-a_"ԃ:UW/I$D!Jn7^+f7tI\UT? -v y2J|i]ЋRd8_! D"HT7vFBa}'QTFp OQ(:8H$K}p 7zѯ^"H$D"K$D"H$BJHl D"F(gYB$ 42a…[ԯ_?ݮ]xǸ u1Is`&nkI$]bu]9wKjTƝ'K$@rq`=󗮧f>\Ҭڿܹ Gܩ)bƌq\z /-[tcH/~[\eb~rNdƈQgd”ߟp۪ 2/U[Ÿs45s:q+3푵c6lH߾}KZ*UUrZWBh\"&ts1U N\>YڀK3֬|Mp컿*e' ..Yfǽ[ncH$ `0'Y(mL&Hiy ST6撕4G4i۩#16nԚ0n0Y7eӰUjXp87bst:8$֘;2fpWٹxPg| /&OU}_ mM-P3mӢо2Dnў'!?+y6TNNi\ش}?u%l;AjKh]'wǖ|ZtlN"s[MT:a"UXoڦ.ZP]>˷u#& YW KpHwAtڕ"* ?&Awr.WqNߛֽYtٽ{7;v`̘1/tЁɓ'ʶmx"피ve@L@ -QK$z@TL;~c 14r_̄%Y[X>}?DBew{oEyz45tf$ɂyȅc?0|[VukSez}~.D9nT: d43oMﶯYyu};A^m5i@F0^E)d#Xh_M,yW]-ގ]ꏟeTO7y5`w;C^܈msY9:<~{[f[uSw<`oThrXt/{,'T*ѩ;P 5є6Mu"E=?}Ի86yDL[Lb,2ʯ0?E,)r cذaze˖Qzu8=֥Ca(Pn䯕H$`0e|=~F;?Nş>+`$CƁcԺ 2tDTk}|bwcҤӫ ʗxgT5i~Ӫ=p/nFtn. 4h sQƯKځnuwx}:}/X2gRMjժ_}UРp ~0>j(N''qI̺R2$6k4&0]y OɅWϑ^{|l≚iZ'r}viO޺O'jZ[ݜHϿ#;Ct)$: }{4>N>UCp?l#Uծ~?&Zo@"=1.'&x"s wm>d[[htyA9xT?.(6hv*.!EuVP&V+&rdolUhJˬ0oȣ~ĹV*'&_=# w}ÇgV^͛}Ĉ4jԈO>Ds$'QwMY11*{G/-{>?~πɬ&<\ܯqaW^_VZ=iڼ cz5[B2o׬?V>BSJrPor]DKͯ'V6hVطaƠo8WӲYr^ՂxplӋ5.> bs}و߯mtUZr8t,C,uUOM IDAT<=efW`{.AD+1VG|DJɚQu >&PDC7 U7M \\Ht'ru{ۓ~o4 7 _oՙfLK 'dL-y?\) 6\Ӆ[D^&WKM3w7'Hʀᤦ/⭕5fwፙ~gnj1W#Z5HLNeȘq<+LyeƍA$]!,kpxΓ!;f;VjpU,'ARDէk~r1U8[06!CG+ls8|NF/G\X+,|K25g.5Ӯ' lDM{Yk]NTޛ;`LLnegpT'dz?m-{=e^ץ\C{ش*J "]n`ȏ0qw^s .cDw3O~34G=FoP?.S(_MF6v3Sft~[~J"#e8ڀʶ>u/O>WHF{[O~YXS/ hsrjTKydOL7hЀ+D?rYCD%Iih\^UKfٚ)>՟N)Vv6ŭ7tbٙnkL87N@ ߆'5Kf{,'6cy4y'`ht/5{2BKk'{ׂYA3MWWrK_\Do}Y|pU=i+$_;AME-<{)x6_|}p=S /\HTN- &;)wڵ8Έ_Ź{Vg:n.xbC< DFh͒GM~ࣸlq-]]}\2s]ku<=J1f'{*Wx"-<&>D>q~f6ѬuN(Y{X5[f?vή?pov\uiT MiYڬݛؚiu&(3;iy~ N"G+ΉgړUshܶ5U;_S9ֽyj܀|}1'>wQη/x1_2k5-S]a3``VF4YTЅG^r>i+ފ4KBYx5P>cőcŕI\$k7(t |R<)omAӳ.o]E^ߎ\"H$a0pŅGv)'o$5ܾ?H"ND"H$IPiWn*۳J$D"H$^"H$D"K$DU%[l6+{>?V{EeBQ6THuH/H$U!MaWehp]z4N%iACﺊCxD"Lxh\CK*DE-=d)L({eP k!DDiHUK$DU , A yf7<)1,Nx^*-G/4 3%*bKaC_\$D h0kDE"5BhRXQD hϵ%y(8)=Я%MwRiQWI+Kdz'[Q{Nީs,h%kۃ6Gv5VE0dE0kċ^7Vk*f0͉UbɹQy4Ud] .Nws{ķ&z/* KD C<WmZH$DmJjUrDVʆS(QL)r_,Vaa(zk9]RMKZH8յPAIoB^uIR2KA 2IQ=h,J5cR:ZQ^\.MmbTX]-mb=.~j@ZS5tRJMW8Z8_D:Mcm#ͻD(]xt_afW|ܔcT1ZBb܊Phm_XhT]9W˺gLQWQ!K$DU @ C4>%D?|E/TnJ8.8i90|Ja KIѪ㌔VHeE92.2YV̮rBRZCIDC'r޵0u*J3Ϧt)%XC|EJsZ^OX#yլUH49&%cD(;V?%\^5%Z((p嚠Pt]Wq&PNF(Qsq9.αDV:Y^S)&P !^# PvYBαd%D"h]6E.pz[U,os cD"H$'"M*šN(fGYBӣUP"J^c:`dW3FF";=pg3:rIEWD 9Ξ]Ira1@|$@Uǐv fJ %D],6c[YlV%`J \CzH$<< $ᙋ!JY$D" ~?V=3bmƬ>aכya!Nͻ/3av<¹xv`qyk5 D"HE0]Ā-&J*v Qh!.㱙 ňq-WdPuRd $O:ucCF0{O}_B'FݯoRƎvO Fs0Ǒ[nq4Ho~ʘdc .߃8 laiڃt{c $ D;fͱFpW$ RMD" F Ƌo.f?s-̣8Lq4nws2Y>dؽSsGnZ m9Xu.'~7&M;~۫|юw>x{W$g(Ly:Cc5<:ְx#u?psЪ:<le`' D"Hth&eWkojo~߈~gwN炄}cOw9wF<'dd=$Te;H4'o'os5n~lcT}q"ClZVŕRPۃ'*UT0Lrϱ|HѨc#K&Hڏ/>ܮ/bg|./g2I@އ;:9,H/H$]1-׽.ܞ-X=b1c !b[;&F˅s27KĒ(| \ܯk:h'f]u~nͻGFښf)jGə&p룍 XE?G{ޮvdD"Ht?#z#qV#.뒻{=vzB&~]A ȏ傁w\{_eƤ+K 'dL-y?\) 6ۍ%n^ ;ZEѮp6,) z9&=6 Atp[cu.ZhHJNQrH^AwdF`$֞a/sDgRn0='⟎ٿzm7~fCξtmύS b5&/`Ԝ2׌O0q y; FzfTUs>}"I'ߦ`gU$!TreV%mߩT2_*+˞.;9p]%NM. ^Ί7t` O{tp+ qBKxm|:t(H cKM27y{z7&p)]G{hlsMuۆspUA.lrb:9Ԩ {Y Fs69wRM+6f&MWN[qele{%47V !ÝK [%? iiiYIIIb2E# |x'21 FL&$ԑ.7x0 wX,J@?~0KᏭàVeSzI,(xٸMl?ثG)ljŒO{om LְXT`'_0xPL4h4rر씔D駼ވiA]gXD#'؄x'T~WN;1;ssy1$&yN2c<@8sKTTT볢$Fl:Y6$x-QfjjM83^ٿU͢1x,~kD -b~Ŀh-϶{lϘύ-KM;(]Clrڭoh߲3P5lR@`JPi!<*E'뵊 |[Wa|,6sm~M]J=ߧ< wᆑu_cr;/~&~ /0b[W֊w?zfqw^s: /5;_zJ_Ԇ D5Wi?&[ 1V\y<2sTF,)k]"0'>+EjUC4i܅umƕ~0w]ya|RtuB6 HR{S:_Øh oh3~pbg)N8/@f_tҥN" ; wA#~IWqd(o~±4  Ҽ2o.)nnזy=MUhx{|:-sanv|˜UG>βYjs7c 4~R<א.llkz͈o]{2ᾯag]"H"nq-o1 f@IEzQ3vlŻ+T0ңAGt]ex>\x~ ϼ-xӒD(6N>s|">[kEuu&" r?<jdD"H$J3S"&4jk}Dh7z% FWU3׭p FSD3W0{^ dxuG+ed/q rw>Ww7+<jZV+h$"`%!.`W1Z1W_x^1h(]8]yejԤ.8x=q=R8TkK'"Q'Z@SdI/̋|i 9IB$Ȯh֢DԎb`yE\/ K(t)k)JI,8)+BZҤЫ.eHoTȩ}o)6ҥKHKɸK$ZFMU+*bfM^t)a0`{L7Vk*f04 Rnϡ)pZC"H$: 4'^ DN/̡4)ђK$QtSH$Kp bkyIKH/H$U qIL^uˋ́5!u;{^"H$DIyաjR:R<3zեT+ǧB+8:gJϺ$B^"H$C) r4PG)(*UFRhS"JI* ԥܐZ$ƪT:*lsuTPtϠ*JWQH/H$U\ө⦃yQI|- mU 7z%nÏ!*wddD"DB6Ę{Ks $rgϢcϛRIoCxD"%J]d5ޚ_iTNjZv04]jPjkz+T4D"QW;Z/pz0NbPPѡOz1EWqDVjz-PMoa둊pJ^>:䱨 tIS6tVY+Xa^"H$8/ {ӣQ[o(y9drCas,H$D(aHA(R+(M NhshsTH$D/N0;%)VB; 혧7EWr% b2s" Ctr.`0^|#<=vS\yYݖId<*`%SjqZ oo:_MZOӨ|x^ֲY(ihqhbrGIX"lvv om5\NǞ7qycXt1oN'[TX6b$sei+{q+\ī=2Yqdꢿi~ŵ\8 :/Atk?, 3 o#Ҙ9S!t }jg̛}tfվe>ˀj쾒7XwPKޘ'7/5Q%M |2/03 O.6^pE_ 0sZ79 AU 3\`>4 W.Rαd%}(ڱ-$T&f5bc1gobŊ9UYxud0!sY4}sOq#6Ɨoc8>XҹgG=KFCj]b;ڦPb"ϭA>~=ЯqfU균u}~}Yq @YJD9s(m/֜qٖ_̖<M]W %mzy$^an,WTnEP4)scDx\B&_`lП{uşE w==x8r0_Q̤C&u`xqNچ'_y6.Ծ^GuoDhxnU#`|6&t! &?r59hy$ FwԨo4k?͒Wp(7{Q/hZ`/X>Li3\%QYavDž#J=\cPK$z&Uq"'`%6:֕Ya^cmKtZךh`޶ߋ+*=:rHׇ`;YX; No+όogFF K-$_@e2^?W.-mkSDT&gz5uiٕˑn*WN"J] JE=н>Du(_@I1CzAQ%$ȥ'UL9s,TbKŊ lO{3ሪF:));^|^<>?Lx5kŞCbxn8 &+q (+7|`Dv  R<g69/ c1ʾ] O~Y+Ւ*ap;X n:91+'%{Ȅ?j-Mk)ɕJ5BhRGirdxf>ƨxWM,Եt'x}f8;3朵o£U뵌K$DW/|~9!\dfBw+Zd.h1 nEY*΂<LRJu|N6*ildQc*S3F{J#*>ZZT=D5 4D"h B>/n|H$FnbH$D"H44D"H$^"H$B/ uȞ l! D"H$^ |tz_g^}h3RIDCxD" QPJY:?k]'GA`B˛E)?#4(]ŕq EERvT Mց]0&RFeig7G^7i֨WV 9m{gbIKuIG-ꊻ2+C.4(VQrEC({1gZv]I(B^K޳+tgbpbT0 g>dǪ'%1j~c?A'qf[.F'yv=4tiDrP)uF-Z@16߆q klF4Ӄ.<OP㤬,(>ZDh RE{.NFčM{q Q?"=.j 9=}=>Lteݻt, tgѲ^e|.&}/7H$tVQ1WjNPn2yƨTR aƩbv.-iR 3@WQ&7TEWQ1c"{:q5GTJXraˮ,ڗ”,QD"/IQ\ߪgH|h{{5MjZӤbgǹ헨!෴KvvbsBhKNZw#yr-\'=Ie-wh>"灆Z4`D(6fDM׫͒Z ӤEMY^u)?M/ѽN4N0u]*E}{h9OgoM<8cf<{kfeLxE.ۖP9*́ZJ/ޡc]^KJ]DEYٕz=n|l`$mD~= yf^ލLYcs4K4&\݇W? ^Y>#< 3$OI6S^N'1<:DąLlDs8V7 Ƈ0.+(*Ntq4 ;Z01ţEX B+uu].-TDWQ&o՚!s粯oia6su+R \M;4v|o%5 crV./RwW1DRf(&WF4˪S!j\1hX0( ZW\1 B͠Sl M7]zUتtVF:L.pW'}GrSh.;4x+NR!L2dVDR" 0ucULVu)Cu)QD-V.JBQ(U»j]@|ޔs'-6p $ iiiYIIIŕQB!)ʕE3'Wi[<;ױcDzSRRtp Ezz)7w-_+Bq=z= e( beHQ2)H$I)PXNK4t+\:/JOHK$DUK$GxD"H$DCH/H$D"hi%D"H$ !KoK$DDьb&s7hLz e,vp{j1r8ņ99xD"TxXblE,O7ڢ>Aaf[4Q'ga;V,~̅ o>xcdݦ'y{x2eU g_p nuKz@F%DRجMBjI^uEяŞ@|_?|'_Ng5MdKgn&UɃ#muaϽ\@X<{8{w'D&]|2n^b'UkW%3<;kZJTƮ㥷r(߃Z?ϐU4KH/H$]TmDG1!ۙOӋEɸ5^|XX~|G 73=TKmiَ)w3&ዊt3و  U;ʛcbܤX~q8)uqAxi~.3{'2Iq䕗n{& 4d#4vlgf]_=1(\і8{B FO%5%0cY,c"]ʰ~ql[䙟a*zʖ2cɯd-86B^[QH8rܜ'^_&O`_~A:Z/ZGoq-<~1?1+Y2H/bSy/ոƾmTHIqg匣i~^,]L/BZ_f?Ϋc}RU"Q0sgˠM* 慧gW^ ژ=?|KO<9U{.a Й:գp9c}^'*{Eę8+0|nb#ٛdqrrD7hD5wuРy_ٛERM8 @]1O͢_/oj'8z Ǿ͒jСc4= G*Y M;ti(dς#`p oX+Zxq/L͎'"rVO?5=pOߪ{sabL9G|.SGзs)Ù\-#ZPIߞ] RK}nTOYmZ6NI ei'F.V8/&ly+Y_.<۟}vGuM._vO|070/@hMw* VàĜQ~YMZ/(ā=fl-6 a$-!}l_rcAp"z2Ny!F]-CK3wCa#Oq3a0q ^er@$(>=|<{͂92!թ5v2a"ɵԿLYZK0k/cl(ݑ 2㨶te(z҇AKzJ"Y$6I \Ey&d^G},NDOĈ /"t\@sc0nϿx\j2qLN9C?}gMr5S@ 7O=8\| `zy~loߤf"vM$(>nD! YW 嫉iw,'TH s ,_ӈ^Hb:I7窻ưb}RH!F`1@2LDzx7yq!͉Ghf}밝c9-$]{ѣR^eCo.?{.nUq+Va3IOSLb+++VUVVny7EcSlVRk׮A`WV\FݿX,ڼVD<ˍG]w,T:xt:bM7ϊҶe2PZVk *PPT?uN=N8"rv>([T \|/P6e]F=*g֜73#'G+o6Kۗ,%-ړ SBWOLŢ?̚$u5wf#S%d8,ն9N:d(QSd(QU3{kH%  86 x/)yMѦDڊi '7Eyf^lL!cAAKΊŌ{sbN%vk'ze{K;XAjQ TZ މbLH;>;ЯA-AN3y"dz+MoQjz>v&f uqϞ+2vmAEV_9>e\ywH&3Q'=au]f<'${ʆ̴NLXaw$ ^AJgV( lFlfje&>?e [3{]iI.E-'"AK&a%~Yvm|ʘ .%8jWsAJ4vQf={݉velS 7m5¹'Ab FrRv03?)ޒ@w]dxvP!e^w[Jc:!׽%p]-L{gr%D $S bqO9":.;Û"5YIծ\DSD `Y2h}թv)ɦ|viSڇyE %k'Ou.w]avYN&v %13K%V܌'XS28%D]k |kծ\b%^-JBx% ah4Zg/^xgG1~a.y3NVڳ BK4j+]:%ӇiG(;69.cͅ\3>Y.Y_2i 0k⿎!t>{Ja-ac~s8xTƺy|۳i[ g-SS 폵b(f>@Z~Dt+ʮgw{jE"-g>GhܖCeItr^4N# Ʊw} ՟J 'xώG1cZϞ漿=ZVFr2YNy>Y ^հ^W[7U)  lF>Fw573= ]FNa_<6{dhݖa03eeU{[(^j{( Z&``G,`|8箻رs oQ9{?d~`')cnGh?@p渭"AO\n.t층,T~l H`Xr4zXB4C<8Qo>{r}~qƄ'%'*.> C`5R))#AוZ@S9c+χڇ PCGϓWbF"B~g8 +Rm:pj ұ1v)JС:"'tgp[ :e}ޱm܂Ky7 `>ѿ%|y6%oyFDZ4ee,3Ǿ`GQ#f9Hsy(4ĝngq-ТM'Q`a;~:g=;څ<~ǭJU!LOW~yXTQsW6'x}r޾#/B!v=N.?tq\2^zx$q_u' tN Tદ\CnaCq%M}Vy"tL|c${RTXi48PH/*qaIIp{5" Dֈ(-'(B-c] j}9}wV}^v!ZGVo~$jݍO?;{8.vUyYƢ;oz[gm/?:cD#QhiCT8DcG9}*tڍ2o7@C Q1*DOe9GrMIǯ%=9m!6y=wU /%ռLy;BzG4@<>6b%}q0"K3cbAc;F\z̽BlZU߮\q/_ 8dۼG`c?S/˅ؾۭ]=EQ[*ڷ"٢MYyESVط(m>*%v@y}ٮk~!&1OuGům9mZ^m ,i}WÚ:-e©ZqVygD] a ePu_1~[wgK V04 xŬ'\N]ŴY_F+kۇ'_ߝp+؍rXz`>x%13ca(wPT%9} k.Gy/8kl&|Kh58K礼CLO3T]zd-/ F" TYd9U$h"\tuO**( ]z2֬.LR]{еt~j'B߾xݽox;9`yR2][.UNeq$ %~E2p0n\B5C$ EQIapx\9GgfltNYz\z2/VwuWv'Bf-51 e{8t3z ůrFݶڎY4[vt-u7!q =U ^App;.x((⬛a;@xAbGp#h=L}mڋri$" G,Dc(L?+`z5=A,$n$ӵOT0/fG^öڿ8K#O$YwWs@;6m?'~?f9뚉kՖ!  jD   SLkHC ü@L:OD'Ē}xby_vIiASALm^ H ëi~͑w`0HҰoh}-E}'pڥCm U\% X>/74ft]W{"K߈L^|xv9`fx[B`j\[誢yΔVtI_I&61D #IOOUo36:eѴ/m>v6 h~*"AG xv},v) l;d!-–"g%b)ZsNAٞgjohP:8e40 veۄ*3Ia.cEx% TpCl7-Je3fSlgK.6 UQI-ڝyFe/vk˴Is9{Θs[fRR6:>R/U_C2cslc{͂`UԽzFj|)1TvHv)~Mgv}+[:6E3#ivf-UQ ǂ lm0ŠD)jUەmJ~[ee[^xkbGo=̐Re\Bej=;]NiW[v6K;!ި-7oK,Bcx5#S/% ESɳ*d)v=v^šnWK"7.Ů$A򅙃`7I>OEC卋%SY6L1 k;PT2)r[#ydc]e>w]l7Nl*;Cdb YypB3/)i=[PEk4^͢H<-Bv٣ArU]= MvU:.C+ؕ6 xS; r3ʠ{AT 6#@MS\{jZNs:5ah72綆]j\3 iu:W {SSiQ3خ*tt|غ0]{^dq\fQHg+屶✺62b6xi.KV sAAAbWd:.%vV3$vKi:>k.ݢREׯ?DcpnŲzXbKq :%&|&Z%ؿ^o[PՕw d{Aj,2E)f&^쟙vgKv <'®(Ä`j{vF=#K'nM7sSQ^nǒ95_DB{$T xn3]̂ J7ƴԃ$?DmK.S(ڹ"r i`r{lpB ve/@ܚZC_xkOjG]*+MaV{)ԙBK>I42m,$ZWM)bETNBV$3';7.Mnunn#uMe`3#8iM*\\|Rch )gKĻ luĝPٚfpReO-pYw5Ra3&nlPxUee|JKgBbĖTta(Ic\!v 52H(Q}q%^Lj  8uOp3w m( !^AA%hϪ-eD Hz#1omV-xB# 6Cyߢ:ↇB.UU:Qg~6h A0ttwfDd妸 ۷i7"X\F3Hۢ-io"o6^Գ.JIe'fP/ h~$%Ņu*Bd"MeGÄ#@(?wfhG?Dݻ5DSx]В0t%'պ}dz}U>3^YiHR^ kwp0l(z8t~g硜W׭޺-Bp-YgUN>r7>2loOTC4Um^_w^e.2 6xt;lSՍq729]qP7P.څ|]O9 ]bĽt]=A5|ﻥDU7>>֯Zʨ"j>zo>ZL7R_"̄n؃%Bh6DK~,ܿAYbay0`(ҎN^=z7/1{<r&l:]UEqIR" zΩ>Œ7_f1mwO#`H2Ƿg)95'A0x):|Z(l._x~\wiϣ?Y_0Q~C7IZ " 棢`vdui 1y+5w]_gAP#y^xKzYt\(̘Cqé72Gy}T.?g:EWQ,bv-Z$7bv"gO%@@ٟI^e{wv?wL { O, AM"9[ot.R=:>n` :hKrvḛb]cwtpe}ddiJw&M%oG!<+߁bndǽ _ ͨCFϧg^OVCQ?>8v+(C_߯S]3odA߿NwPd\%Fqy<7,4  Gbh.+?*\@7wL&QLwGCy³(D8S{}8{^MйƎٛ h1,N_[t5FqGHe]sChTk`+j r~Yq-Fz*dW Řae&J=.NJ֡jWq2>74ơ!J1 0!jFtD8f`PVW%̟/ }m8WP:(ʊRYhgFzӦ]a3^g ewrU׽jeOzW0y!Yh>Cw 2ǐʢt kÿ>CPWμă \9djxBu=]&X@]]Wω\xnDꨩQ5\!bH:x hA8b~'X/HDՇAI=Lɐ=8mh$oĉ` KZf΃wm9pU&vrwŜw:Nq`30*mjW븨0ey\I8+osfMA} [q1 <0IDAT=;:X}WcVw^RV6 2r|)P%wAh*.݈KF"J}Y>L},WsU*;XX8H毙B:k ό&Aͺ:66d=8aF~=]ٸȫ_ hψ6B:skXxo3jJ}&rM-ВKɈoa#oqxj'/Ň@mut,].W`*&BSSЖ+7 eC椾ʴKkWU6IUAM;j]>DSv$^{EvDBG${hT~ĺSRVl}6>Ӥzez]v9Q"E2lc0 nfyFeS'(N^gItV:֊#1DQ[y T"ӞiW,5L/Iy& TLnS6&̨g/`_ە>t+Ib7ԨhhnoZ`J=ꩅGB𹍟+n BSЧ@ NMp>-,,LMjⶲWb i-L&S;.2Dycɴb^M4y{*Rmdhؙl頻9%~( )ם{m|C=* >Y,_n#e{bIShr9TLQR5ɉ60MN_S~[|D Ss{pQMxzjR[qjE$ubɶA;5kRk0L&!8imlcx%zact-fX-qdzj+uF&Qz]-:."8fxē^C2 N9$riw6ƶ9xN)ahg\lǓa1`iѢ͇>V1sIRWy[C+վlڂX3*h3l  ]o*tU2sYedGfz,ZZd~.،A+ CcpNJگЅMa4o:N-wAAp$MQۚ.*Nsv̖W=^i\A8Nlk:TxTEۆ  ؃J#-o'64nްZkÓ:n6h. C B7[y>(lBPך7gϞ=A|<| `q& Ki|IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/shift.png000066400000000000000000001271211423020056600304430ustar00rootroot00000000000000PNG  IHDR@T}r IDATx|>4'xll+2۴Iڴɯ;i Y썱{`lmYsҝ}%x<|.t=!77W /,,%ADDZUUtT E"""CHP$""R0 E"""CHP$""R0 E"""ۂЬGQtL= @,VVb`,f| % ia<> ÃDWDD-)^0:QjH΋Dz_E{YEˌoGY%"UT1 =":/C (/$~}@DD«:9ߔ7agjR9͚6zKDD)^ NͥZ-.RՌ(;W/R,n2&敶'J 4J ZDDD]PZKj0a `' GkېtHHDDǻPc /_8~"W®3=2{6sku!kj&nstbĚ"Q]^wq8gZZ;h=(:tWti:L_ $jQY܅]>""_<2>hkԷK޼g&4ρJDZε oj8Ռ[u1v9:DU;P{P9K|r:6ST^xMky*w~E`F2D:o'N5Eie!"".5Z,Tv@Ir,!Nͧ8\8"u#)^UN ʀr{Q<STy!1xAz uBXEM8!,(kI*nSð@?DD93l?'76kf(}ZmEMErZD5׋/r"uB/vцLf],r *8:Pu BqRŸv Nhфd6j9/A`ΖЛʐ΃DD=(X,p v\l>>>owcޟ%Cc0 &&""38HDD`()DDD "HDD`()DDD "6 ,""XS$""R0l>%""RHDD`()|JDD`MH"5E"""CDZ UMVl>%"6"–h_?~n]s.v)D}l;B#)CQ?]OliBc\j:Y%TS#K{?ĦJ܉8]|׍t!A,߆.JĜ*nĬFZs,Kǚ"3?] İ@*Pt 6?cSDzY%{';Rq~|01Gֶϵu0qhHBcf\Ni^5ط^OWB:;3g#Q8}QQ.o^:=t(;pb%6F݋kFApzw&C F/k_,J)<A)7)9K&}#-y?Z"pXqQx "aFQ(DY˗HD$1sf#8p3FLÀ|X2y8bF>yHj58pE"1vĩŨŸH}"|Ա F#RRg:a8&Db)OCTޔob)3H&? I0xv!J!V!ɏ=Ȉ rTôO uʯ!xdLGS)uI 1_y k6}XA0d:ݟbB)RYA7ͧnK"Jjg{tQu=Hos _G?o.FvS&E#`$OrؚPNocMu $S#%Ѿ>N|!Hh4I뭬8. X0F?V zmPC[pN= ^_} `.`bİK6 G!9ZqrNe|z VΗo8E"":Ҁ!zD |s+aNZ]$$hjE lLi߰7TB8U]ֱї}JDZ{m3A@tS "O|Aonl^"FbjLLc[y z:[ͧřk}O38kߏ80r1#vt~-߮S""Uc> ,E'b(5u-䛈vzť`cZ~GwnO?BaawqZ7`ȎAx&FORED4 s3gAٌA |CH4؆8SGֿ/ >si! 8uΌC1EWQsE# rͬDV6@LpZdu?Ք9& hR@Dtqqg2;D?IM(:%ͨ,G,z# Z > _|Lʓ{pJL‚ImYJ0q`D5<13y@;q !xRI5(8JkY%Dw '`t.ݹK %8}&Hx1 ,5<,s0 y؉gJ136s D?I 8k|)X8j&:LfIDze>ؙy;MxWbV;;q4o Qz[12u y94끋8Vc`EoǔߘS"~Ro9v ؼGՋ8(b%vsshF#<C?|_XS$"#n^_{l~hbŊش' gw˾aop#su.:?L|o}ccc\hLXoʢtW\+O}ktK 3a|{?tbXa(Qlj.D# Viq8!ؾ"qwQEa6b_n"C:L,ߏ{ 0{` xL Vlc pgcw"S0,8K= E"" 7boiC a0c|CTQQxurB ]Zt"ǓYe0wP$"cL4Ay0Wy.)3&".n؆RQDEI6P Dz]8 痢 E""l6kQhCę'W6b:M45ښB`=?CԍoC:@D龍Ȕ31lfuz#r*bcsNE&߷(+5ԁᏗ C'`߆}hs30&>S "7oZ$ВRRN} xx1]bI&6ht1i|!lSa7aZ&T~ N3l t4ц!8sڦƚ.OŦ-،Ym 4=CZ4Xl7&5jKNL3~XS$"""3S‰ۼkuE"C~(JpSR"lTnL*#ka&6#;8%#7QV[})a@\2u|9%f k8S+V(C8_-[{"\IP㐉TW"X,! 5YpXC1ut$''"Z=_5L cC9aAD-8Tڄ*EƬ``F\jJ<]_n|F؝D"y`߃O}E}0aDĴBFBbP0.Í5*iJ8 o^Qyw]!ܞS">N-FNv ŵD&\?,4Cc{I[&ɱI ;˺Fl|`҄7&<~F3ӪEeC^jW(>1<8;kn E">|fX; 쇩aקlc #bJ|ǚ2qȘuѸc3VB50Lywe/bj^$_DD5w֟E"Λ1># >7q;6E-=V$\W1bz|vvF) &aU):v9!77W'Rv!""R1 E"""CHP$""R0 E"""CHP$""R0 E"""CHP$""R0 E"""CHP$""R0 E"""SA%%r kADDkDDD 5EUoq.]^ǀ^v`%""סXmrKDD HDDA+Z[G(hNmGOK>6!qËl)&g'6>@$d`^`g׺|ZyĈ2z̀[_ =_ώ˨/u:g|\y$`ǾURo~%JOrԚ,p)ld7kFv>SVI30?= >%0y-""j_)%[\~uODhz,"='Z&\$/En~ +Nz- JϠ1q:K{p0s'VYꑽj[c(H87Zl+JDԯ6Q"ep fϲbY=>,iI\5pW";QG`H4egXZPP("zpl?%!’>[$DD]{j]JN17 = a|pFD"6ٗYKUrJ )~P+̂ `BuM#$WWn Ek7T)IxPs)3D|=3fگ&")SL(CLv f'$@g1, 1}4XXS$"V>Њ,HQkecHcw~ܹf pJD\k}YːsB/K/57L@N@-%͖P%`0C1z6ǀX1Z+p|jDXv;,B|TB .7A UjGǦS""/Pt8(|Uf eX1=˷I;+d87<ړTj85EVNfF#1ASyEhf}ZW $Grv""oPt8 &ɂOboO+e):ܱŀk M,,FYDy%`"*ADNV|BG?#FYl : {VmW ňz;9k]ƛ56}z5&4]V.afduѺv '^ز:0Í ɳ{ H39YZ=6چ0F,MmQ'J111.C=YIgTM?ypDDDrBp"""W/*aA͓Ӭ/1E"""CHP$""R0 E"""CHP$""R0kGbm(7#vD̜1Q<08%\ +49,'߄8OBfi>cuX +m8gq0-/$IDQhPg"Jd>Muዼ0LLc d,3y[jނ2d h~7X$H UaO&a#({VOFa#Ril^8h1 !3v9=\-~͘m njI3.A4BD 3㇯o^ۙuKBR!S+~ے5ÔiX$ Ԁ[<7ꂦ>Q,EMHۧ1%cB R,@q:{( P<[cH4`3&.$mSiD]topHԀ ЅpaX 9m.fED+Fq4(Q`=7p޴]1b˷ƢI0c&܌8 SOF nNLd,AlHaac[W$źjT 4Pnvh>"(<jI@H F ؈}Q'  ufT,6= @8˖LD\d!;l=^I{Qua(7} S02S0qbǮBɌhj'7]{?[+V`X2d~s=7  ABmAA:XvX""r=5EK-*J[[__Dၿ }xLQck7׿3GV_^Qv1Ms)sESĀ0< /E~1!cS""uK(eӷFx8L<?}&L}1E98>b_ƿֽVcd|<)cFqQ%Lb5*Mr"> ߐTE/S+Df -l DD@͕bbb\B]RoP^^*޶5E VX4ná0s09>2TZZP$""X)DDD "HDD`()DDD "HDD`()DDD "HDD DZc)!b0ƤĴ IDAT5$՞oY4D(?c,'m^. ,y"fϝXLtC(Jh,؎]͙9$N¬k !j_HBߺ K|C,kcoWⷋƀt7V~4(9TDԀ[pQ\ ^1=E`է:y$ dݟk]V'[ SWf"8xMS31@7 "ܾ`5(oQ`A&6ĦHLPج*ɽ8ia0r@#ۃE)?v*c@[N)H,7nx}xI g_#A @[M4H$$&4!VRC>1@q D4aϦ#Rn$a ۥFAXM H ܅sxK]jObo2+h;|&'c0eƚYX2qgn >Jr)'aKv!Vm'l0I):TWI0RX P]U ϖQPEq ƒ*BBkP]z}8BO'X-a9^=5X.6fa\.V-hlm> 0H ,ݿ9DD}F6 A@eYnkC @DXBg 'h0 bܵ7`NABN>ۺ%AW !.(=l6% rg].) A0-MĶGPi4em#1}\|N܀zMӟs61@0;&! h*DN X X!6e7A:u+DU BFjD}`O$"][Eb`dz!㎴X[ӏ_zƻ=a^:`XvoKbn^Mq" X[\sCX8A"7ESqmH{QguQv@QC R20/u0\J;""RtKMQ,NGzz:fZ/|t-¦&b~KC0akq^Rl(̞7/lǪOB)'N䡢!TzGϖd|w;GOf`+V~v`]vmy8 >^*~L4~~[ϽW??V52DN_yGa;G3OFeG'-”c0uBLgcrq^ł%i3j"/NEH.GkwNS pw1p7y^f $#{!$Ҍq2K3bQ?5u]\^DDn<苐QMƘԥX.k 3`z l*uxyP$Ƈ)o/b!磤YDua>j|4cGe~1jFAKDRZ؀J\O;ѦZRBу`K[AqI!SED}A7b3/,'|8m|]>V8&<0U{j#AjL_` t*TYQ[]) -~Q'֡J10-GJ;yzH 5 k  5M=+ʋhc>/)Woijn,iw=1KP6M #0b~`6"YaFS0h Y,cMl $ l6 @ډZ`zGyQ׍'wb-X Ƌx'oh.j.z % W$`0@@mgsA/dAo{lnmI%Fe{^ϵf#w^S^Du8E/B0at +;rOU#~վ7UzԷ T_Q = 4ԡmς&a#4LԈz /} 5qgg0>*cp˷ܶ>U$jV)ǴL(+A>:%!s)  ?%@*;+  mg=ګCY^lY&( IHw걽/cwn:?'ٷ௿[ahԻ]UmIi1xzlSv&o9lb#}|&A<X:6:1?Ŧ<E2Q?  @i(GYKܑĄʢ\7 $&PYXj* $K5Jr DTR= ֕!RyKP^s E\X M=]ƅUbDL~oq{""rssERd׫Ww -]в>CKpL;)N3lݴY-< s3XKP`|!?9bv.v:b7ò.Ph:)^:Y Nf(j D¸yF""+--e(A ER!""R0i6Ge))<Q E"""CHP$""R0 E"""CHP$""R0, @C.5$AEXVeΔmy(Q̪g,ιP4 oX:,g,λP4_\`6Y>.t|@,V.jd22UZ|}}3iRg,x]b/C-o',;)6 TNrhIm~8/w:rǫgLjfx.ߦz!˽m^~qӞ?xUr9jfع+ꘖSHSu6?y*kܙr`ر.%0Jj9o6㶳\q㙷ճb^o+@t]?Wvxm9'Q_Q߶z"QPp,u2 ]~W*l5E"io$km0z+Y3}%֑aL݉Hԏy8 )F OwE"&5-bQE`7XwR}RpPJ1<ﱾn"gayTVV???-9ϝ;gɓT}iP5x˗/oW)y+Ǚawgh?4Ǧw_ˏ7%1:I?;' v쮃?`z\(ȶEb!(ԩ I5C'?%5a¹kڣ)WB?y'B6W< Wbn=1y8C{㥇ǵVh"MQ(7E'2'ߥ_MCVߑJ{]d:fmƵ4hwRf|73`Vyak~q]Xkaw 'OVPPP^^AP?~ǏkYF@G/5eߝ,D\rr(R 6o}oA QV|HLHvccRX4w,1 Z߁]S욳b~4,PhNO#Wk0o燷>f* ?"V]NP~ >D8cʱg%AXfb>X6;j fon hkK j=oZB FIƜ%u|* 3[~Ո(۰"ّ4}"O,[i[-..-(322w\FC :uy1([ '_SSbFLF qzppxTmۄfbȅ_(ڏډQqܩ0݊ö5#&b[q6rn4sa^qlqn COwbilܒ Z#bՖwj 6nVnc3M Qbb]zXoEܢ0VM 3f"ٲ/Chu}|066ve䰔k=a{zEMqW}87{ ً~t| [^F~v?ӧO;ۖF,FIJ u1\S iS15 ;t˓DqCg!vb$YcfL1NJJě$D CDL_ֺsG8O{Z`ma ܣ~y:b5]h!}'>>b<5 Zi I9K [5s#DļX{j00w81~?SX~[&|[`Dh(7FFFBPHY]].^h;ή ޤW , =&l{()vW(=֭[pYw^ڵ1ct*v\Gv36D|y sx<2?_[Oy1(I̩!#UwfZZlD+ :X֠ ~X6(߷0̎mߦm6m{}X`TuVׄ^F^Ń' i۰铏r՛a]NjO>rCl';^풛EiJWu>䩧uq.}QK ȗc_ܼj0y G|`Mxۅ1v.fM=pcz E|l؄/n(XmrQaHlГl'XB)xPr oBf7/( 3{ns%$I]_K"S6 |)^}p5^Rם+bbbl cr7W\{*^K5CoLœtx rN|kŀ9󑢼S1aYwj;[Tv2f!kZoPe56ՌܙQ_ MH\r%Ӓvv,Ή_63cl= ^[p?m0yP ,6Z|]>KmVw0S|êqX~(z+[05Ċ ^M`@CEr.nlSXc?(>OmڟVHHHK'PSSp|GB0;Ŕow1Ѿh*= oهS[9"bZ?~X96`3ݎnO>ㆴpv'xe,ws֨x걵p] :\()FL)=}_>+'_m=7sǘ4%%v)G'07g@VH0>0CGz3f{n[7(?|5&_[u83`?_xgvΜ9ؼyc=-[8'݂ތ[}V5"{HM1mj8^)ɚ/nfd$oB:9v!Oג_+<#f,=+!ڻEsWG@!f?F/(ۍ?x^cSG6 D`>AXYwnw8#&"be|vwvًA(c~{8x hsϵubذa=z}#sx>G g\.)7Ap/u$6ܩ^s]'7QA%= iQxyN%HjBҔ*ιл7|'aAxD,G4lǪF$õgenQi܋9}&Myd*b#7vBnn St7ו3O+KJXZ˾%7"PwAyyj~wB(J>M`y6N3P" Yo|E[:ShMCyM~Zq㙫񤴴5Etы񋿘bGNkDppI! gǐ !Ghy,枆D w=RahMHjq{(sc8RP$G Tk&졧|n&@eRP$'krǚ6aK]Qi&mXZCt1)*Q/P$$Aj0 8v ߭g@tn>es*f E>U *:HDQj< T[:|GΫPyǡ|e㍺nھwrr -ɡZ.eg EyWI%+X>+Zj0Kj*[~@R DIُ, \kTeg EBW,C]#\;52qAKi뢓COv:5vEs*_vx^{j`/ +hzvz3(ZKPU-ZŖEOQfX5M:@dZks5©x9/;X,/I?#8g֑姗Tg_ӑJl6&2y{Q3w.yHjU]mJkf&o,GZr|ͷMT764zz:vm6_G岺$aРA.M>zAaRN،EG{^ ? Fڹ8˧.8EyE.ױ|]= IDAT!}DM9 ȷ9Yڱ۠=[8]{8&.'"uLLR{S5 E!&':* s$;)U}?4g;$~<㏆]˹:ameoIIJA[.$e[s$*MrmbưC:*9ÆUZ]vu۔%R9 Ed|)Wm-UE˒<^Վ4rTn.kfm;lذK/?W~ ו t^l L-mCT(GLLe۾zcC/UpuWI3˨/zIܧ{5iw4vˏ˳J>uǧjs_j eQʧ˾}r .ͺ:8jtv5??m9^3dFK-jkC:݄jϯ\ljjZ</;cR˧3jl5D5\\*9lkjjpEV#6eC5Ϧ[tU>;o~~\~Nԡ3p3;X8eW(햷SۦSc?_jjq׬|z]@4LR Tꐍ2jlvܔCCc8>.ut[?н1v:/u^@mJu76 0jxaԟO-jss&Su@.>>ޫޒh۩ GOH6G,$2p1H9߮:R0Mt:{ rpU[6&>r\2r57K[>Q^Hr6ZIې )W^7uݵC5͓*) K3NnvЮwgtlsF_.kWe᪷]6U\uɐK٨s/_w\VM|p{c᥯;\sꭚ| m̓߾5X[~*ױƹsLyg"|ڢsffmH}r:=m}=E %h̛7"a%5C?z9W_ZN&!5vQHT4DEŞ{6tvgV{癇ewfvݙs?~KKTz- YAbjG}Ҩ:.4nXQjB>C 5=ͣŧ 0"&g4q5gͬyo׳3ؔjT (HϲLQ}ޤhSiO?U=6Dn`kI MBz0̧|0GCҤ284lkQ8T̴6UmLt( tLBANgD.Z1(}XVDmjiiYdkR Dg:bnoΜ9*wI K(Ye36mJ븑K0;e/ve^25k/=Es1|PqWoL-Hqviű_,9"2)(S!=TVM5ed%tҤITREINTh1g8t2CVҷ7$2&?~ը Y1 ñ?S&ߑp{/{iQѶ,ǂE#<|xѦ #Q,a=/ dYH&QLϮ1_L Csl]*Qg2 fEJTF'8v^A.|Qg|~ZT̡qż)INϾZ%kqmjiF$q E}y)ׂ4rHh;9}woRoH_L1h&ys-:}& ʼnuT$dҦN q)i߿?*wXKJ.]E*{Q = I2҄D~<4yS}=H%qwho,䎑j7Rx1>R =i+ќS!%gm \'6LdFɋܾ[RbcߎBYL+qJ" "1)9m6$o6'>euK٭](șyV8) z옻92.%b}'ql~(Q>]|]^ROhUw.Q %"O~Lr\G $bXq dk8;9T5+.Ľgl=-ʣm$/VϪzǵ@EZ)+0=cT %qq=.JEt)3(Æ SQԩ#,wѥw2e$QN,jjkO*T 金:53Rf+K߫:e%kb)7fm|.֡SJ;(CIzԚxǘV˦98צҡn0ƹ4y ίm* BnjI#=*b[d0yp07DMF 5՚2.(m]>6qdm,{r)яw,!⏞ΔzWz2|-:&T+c|cNQOqo2)MaxJv`u]]Z;f#XĖ}b<+W"yQ~M?wN@hLI 9ۊʌ3pss{) R_PQz-j( T HXcf{ | ѷ_ ת ЅӤ++SʱbY փf}\)C {wb,\ ]¸j{Zղťr WT!no,\ʢET+Ob{GՍ^salz-(ZcSH_y}؛olz]p&# ԩS_OOO&=jCubE1!!A2ڨ-$zX"y{@T0x;>8S|WR#MgS!!Gʋ9t {^ƨZe[UbFXTdq4*AL:L.$(p)(H wH(@%?666y:T2dmcA:OQ;11{{xC^rfE~,ưOxrEŘj3^ ŘW,.j!@P0O{/KQ}=qD@ (="uCQK.>@ (z_@ Q u+9#DQ t(j(j@{tpb!@ xo) %6 z!\CHt2%)S˛/{U%\g)X!MFA[+*46um؅@$o<!Qu_ʐk``V*o׋k ɨڅ (`wiOq(cGb-NIn3v$P:T껔1 H6)Ȗ~o'Db#sg''q+'% Anڋ`)2?n%.js je065[5ͭ)Y8_ Wi PZyӴ mF{m1ȗ(IW8}>J-[wrD9lsKL\K{ u1ҕ+ (KQ)\\֍V+&'!/و~fQl#Ez}¦o0O G4@PP(655B0@Šh<{XclLԟhk*&r&L\1,!\k'?ʵYcqdu W1&/18X,J^5!3&y#S0z؞fZ4-R[E*VHJUߊSW0 -[!((Q& .5>i[ /L,>vR$ѫ$p)5n'^&|[b}nAA2-ٻoр)X(3nﯩ7{Aܺx&3~Vj9.;ugI2S\Ň`. -a6mWJDf|o(3vvl5qYxv3Y¿+?׶J,A9}SV P+:j5WE>?4ǜ6O;YQ <ȤI^ ׳gO aBJ|Ӳo͌S6sF73gYe߷vF8Შ+P`kYX }͛9OY(/Aq9) g6 IDAT߈ o 1@۵Wy[}R|)ݽ`Oٹ+T\t $H[YTzu7𿗈<1vrw-lx䷊aDZ7(}jS֬Z,aSX9( v֍)S0rHWt 2 ,}kA풅~dQ@;iZpLo0}7%СC̜9Se!n޼77!ì.40{ii-7ՋitJ9e)v.n[GrtsB1ďL -=4i]BbR #Cȋ[ \8Cg{w;vi_F0):9B)K=ǔT <%$1:T#sL;@(cǎUFfA,T$%%=/7( >0Mp҂BSwܡW^*iѢEDBOdݧ|w!s3 ngmWWѵ2]-d|ƍ3嚝tK%hj_ãȲ56S4)<הdE{ݾ?%DZf@rK+|bNFY C܌N0`:O@xy"Ω$Lh8EQIO޺tئL<"+-+N:M۶m?~[:4P *hd[r=ڰd堌c4nɰl8Wv><ѥj1s4ě?>ƴX66u0 7ΥɃl3dE*8~,;ӷ00 &WHtR<'$0["j4eϟzATMmԱ/ד( 6o\eEFFvڌ5ʕcJ*lKᾁ*"L/3{fIPg6_s?)ImK*rI qoO0)Vc)MaxO}Yg0mևyppD47ح4&՝zxϊ#hlꑒ;ns iZe$7Tv#۷Yի|Z ;Wr9ׯ_CX= ^;k,[bhtc!*LN3.V}|[v]) o6t?ϞL0**B9O,zl~+:pcaNlܿ+k_bZWmOkw]ZTNj@ '(w{c:p/^$u"ݻjժe̙Ê+4>bLQ(Q*AvÇpBkCNڣص[v MsPnr4PLOgDEM◂Z3&Ws~+og,.O BQG9S|'K[]ČkGcnE :a\Wj:رCBȑ#Æ YM籐^7YIBFA2H&(bq3Ru)}5 ԦXqR$E|}VckZq,*pjV3ٹAuies8_W2O k7O\D'j,V}a,* At^ KAm`MV(q埻xI=?Of<_;|8l2vqez3\2ڔr%f#@\s{ uA2~kHVH}%u̝yR7f)(׉Soi(sLNburt)↵dj:-ƁrQUd4iB5L~*ϢMJl,CV QLGFi ]Ǭ_}|bοog TY]fCG{T|FeT鳋cȴbll5֙F݇φU?ynZd£ jIN֞)7?ߜEWi¸k.UWF$aVR>㼒/KQӅQ*vd a|8Ξ*6PYeŨpo3O<6)ȴuy0.`}OI2clWv.-:0hзJ#Ō4ȀhUP]^sru@Kv%cS5B}* T@)&Q%1܁oCjΏEDZq~Sin(㓜LLL޾yÇ6N^vLk/g& 6Hơw"aRەW?OQ\ED ɏ.#D5jROBJYmqW4;zQR=,@ _^L3ΦK(*(qJzz@Pun ]3@ HG@ Q !@ ΁6@>%46|@ (HꭰS,0ѧRRQlQ(rJ7G^"m7@ ;Ƈ#KݧRFMK&W*wnzXB"R_%+eH~ۜZ@C[n+QQfڌCj3gQtAT]=AA~|YAM`8G4[  }*D1 Q@P>@ (A:BGYO3$< cG`rk7GI}9g|/3J.d́/I SZ5BCCE} ( >0.GG-kY:o*cmQ{ߏQ(rt+/3ֲkカ3/sp oI0; ^Q$."(ǜ6O6'>M'jԨAڵi֬!!!R08iY~iD9!@🢌Oәߜ~GXqkQձQg1g](WciWپ瘒@!-ObtFwF>L[ٱc[s&''ӽ{w _ \}EpNal~17VǢtTeks4X9vٍr*c(&Qˁ̨)}mFϣXˍ7$Y Xfw rEgE =h޶ݭ0Hy8 Q.l \\iUr 8{b!:Zv`x $ID%>&.ؚA[Vr8)u%%,>ĵMi0S=Hr 5" wvƷL4ǚnfUXZZ NrJ(m]I)SˎXš}ŒfY(~ao1ԛ u_R2m54]BǒI(mSt\3&D×X5Zz:'e7 eM5(&z7%9I .GE 2=Sjrh "!G.1ldžr^3e,mahUdQkM⇟a~3oVM]1[7‚l3*wL:(8~,;ӷ/1W.75$  <xNH` .Ul1DDDPD|R$RZɋ/RzYmjDqVWjaD F$Z _s*XwX>mI4eX|ҊOLnqBh +)ؽRtSagcY^OjCԲϰ54T!Pl;E),Z=Oe +#)+O"A$6VjK϶锻4Mr²=՜)ik5W}O9zbh̍HUnȫj+DMgƍk.sϞ=W@=rۖ a=Kj9v%Q Yz)<QbSZs#gKk^@13rk)&?iL8Œ}KZ i, %O8k+v}i"Swfvn:yq/FOTշ̡3ANf"%OTLxZieԐI(ya&OGIiNe Z hlAfAT#KSXR\,*B{39jLV*ż%h~kLc$X2̭^(O)$:ECQ5j/^Pe ̞=N:jO5-CeZ*MgbcAPvZJʤ-wnǙpa=怉2Kغ,]N{rVB1ߗEy:x2AqpQEo ˙ 1S)\_߆1iVsą(kO7ǫ˔k9#Ǫ~kHVR_sgsgnAr~ԍ5%8:qJX<uN^ ]C.]ܰ6V!Y|?[n-K)HՂNKA4[@.7Ed&TNL\x%+S2z4uA^GB*:R~*D}({2cъUpY.*K}u!I gêؼ7-Z2fQp$'kO_y}؛olz]pS5)SXݛӧO 3 J%&gTS؄#vC=3-3gCзZfCx-hugƘ }@Sթ8n&dxzi7 %+ۈR攪 Wct-Ce~_3}ΟcW̱g-3¡QKLGUUɍ.fAElG䠆2}3hgǴipuMKZ_QY'U,QMaFY``&HA 4}I?ټ'KȳچX,Mχ0g5 3TfܤISRRTiT!lCjtuuQeޑHZMpJFi)d/E.i@~Rە[D>⢃Ūti˦L3@ (- C>~~\Y.!@ 3Wl$yLQ @E@ ((sCgQ h!D1dWJ)0IYrq%z 㓟8 'Md_Ҥ€ %ie)j0JR"@PT>hU*Tң 7@ $$XR+!&%4Q*onJ9C(ݕN&YLP-#ub颂v:Et?v/J~+ 2;zq'j2_3 d^%CڤU2M }g]݁WW2-*{b~@ Q !@ #f L>gϞ /ٳquu?EA@}-O8`(lSg&u{3sWQqY\DK˻\AS֠UuJj>%Qv3 ]?+ neDe|rD=нUYL3( {{w LtY2Tb j7N~_IV(]f͚LGaܹlذA1|'I)ٟL ѧ|G!9{;1$Z"giz~UK87v0QU&1!hQ٣?vMY1fNJٴ;;SMͺ}+97=zHP}n^>1X cZƅ&1W+$[=SܨXd[UD'A؏s2Zґ6`u,ԷI\\E8;)Y*,X;ՇN?;a$SpOZ㋽)d#ID%>&.ؚA[Vr8)u%%,^$mjM9皒|O۷3g8֬HuWi~'x3˗/gy^}Yv-^^^Bڕ1<  g/~f?1^WF),#<,E ȳiq_? Ɲԗ&_!0B Reb:,,qTQKN%,1dbGD%fJB~ߐj7HȑK̨oD?[~eⱡWLr[ZzԚxg̛&SwLäVAs`!Jy ;m۶z9nݺ=ΫfRd_mUgO0r||c U^)/Vhܾ؎\XՅMhO+MpLyuu(gh_EG5s62r*Ms7*m#S/UTH眜W.ѥG)J[ΰ.w0Q!Ώ;z~ws L}y\i|nݺԩuVQ@~c!DBۅCҢ-[ܺ7\%SaKFi^KƲTEsf~oJ+(TBҭsXTEjt< M y@J2KI :[':k1zuSTo7ʥޫLN=z]yKж6Iޔ̱ mZLj oo ÇzEA!FIҭtt2i%5ҟezU-u͠i7e(m$(ЕdӔ%a( Xď~q2)7fٚ~JLSCq; #O\=TCφU?ynZd£ jINm>'?jRro)i^ܼ-RU~((`~29miadLna"SJ~䄛*EShc,˞GK::Rc "ǮN/99ӺK +rYCڦ87*=U7.Ο1$F7*n)s|JZqͱG.3¡QKLGUUɍ.fAElG䠆-5ksro)5ɓ*mllrMR )03zzo>(J4UڤvRW{{{ E`')9Y07,,CE&si= \gmvO~}e({G_x͛is^D$Z E"6nLƍiҤ9:b q/0"]*UJ[5Uƭ6d}o\ Y/@ӟ8+C_+'$ "(Gczϗ?8@[ck[uGem^v$Kd"!l񞸊5k~`ղL.ybw{IEQ ]` k-bu?փC7ѯEF]oeX`k_5>LkȯKq( U^uݱVf(O|.t=A;$+@ j4-$ɰWƆA.{, Ҡa5y3 _/FNʽ̄qs}҄*R6,4-)g A)Cߣ;Û>eGPWQEYʐgP@ fq6sB@Yh43D۶dhcX&k1";qIS:{chkG2R~.Òtxl=vTRU7zZ%g3[&Q 2?Yf὾_Ѩ7c0êxy?z;%3krKlՕrS |dFzHM]rQ$c:#O_3u(zL4ndvA6B _SڀtOۉvۓg3'cӭ |x8윾7#Gu\ Ͼ xuV?#<,wrVwMWJ>Pj&Zm oOXd(_<ı8OZ7ΤkZ8{qr6/dfߟo<7ޙIBR DAQA% UQ+ J ZHq (X@\Ԅ*!ɔp3{g*<{WgQߟ0kZod,*kC}ԛx8NC&4?B̅8-??{[88&{7"h6Hyf@>5ON$ 9-[]{' ErK۠(7_ 3g 1!"cĀ.PlYaJ'Xg xUĦ(Dq_>!R1"qM^^w!#6q=_PQmziSTuD#K;"EhV(Ĭƨg9%B_E?S? QB`Y꣍[j}R00 z+!^@DVCtPǜ #4D1BeZݨKUQ}*L.F-}D8723Ge|'ĔK%՝/`f1DpNKDXnQ piD%__ 6k*J6D{%uc}j'>Ҝj^DVgbeChT_*Bf$ހHVfȬT袤RNWY?﨡^tZ#EN-ҋl}(\>q&ڧ>,(0ZX4U^?]N:(j`f,-N2Z)oDc ꣏֤>iF@s%?I>gu FMQSaʸ`2ꪯPljJ#C}BT5Ҋ+#QS}j}+>E5}2ؔ9JuNjt>P!Ff8b -w B!N0iZDdI̬FpPP}OhQ̈́rObGU!xĪOJ D٫5 u@:>Zh8GYCZD)gT֝#vPq`JÚ~e>ԇ衧B\R\:ES-VzF5RA}tiEfH_1)mQRmF>t>>>: OIZ#}%bS3zi CeQ}>}eV$ZC/caDAu#/0V+C.4CB!~hB"!+ۀV6hB"!⇷"}Y=<yvR غ~Q璎;zF\7'μmXy8 xԨWw i /LC.˜y G?ƒc|ɧӪx|PAt8h[?DUpѥ]0ѸA|4xzZ%V,YL q|+?n;(x?QV=t3DBǭC7l^-~:bɃs^WNսnFOeLS/cfS&#E UV7 C-S ]n do'ߦcf(w!n|1M_1cZ1<E@JG@,64AC0m_Ӟ*JDѣISNÚ.fUWiQপՐ:5<29SPhGƥX3F٨˱pityd2w6mO , T.1HLaYuqq|l.B&K mt VS\q8 >mO.;<{A=3ٔKѪ#Yk9R!)IO1.$MC2;[Ǘ^']eL75ǭ" Nj7[vr6KG2 +LՑzF2.>;t ndVpI{Z׷Vn*ѝT &ƉZyi]L*);xl^$2\_g{TcTa  gplش=L_?OnB5 l:cs{ !ډ^[,yEBPbUSu|8pl?7`f?t 3?wx|"|[z#q]k&&I:eȬؼ}|']+CRYa)X[9<捄F>06˼"]3&Be\7Š pKNGFcH;_1ݻSPPOBBBX٢PTTyjt`QsP}uESF8tB!DSB!PFB"!'bS$nRu SBS4BjCK1#:Dl63\@|h@}|P}8BcD`*ttpD#z:P#Z:PGPhuc׊En)*C5>'c rMvr,5׈P-8BF0lUT\(+Nr35^pFP}OhQD$BPLUOTFB"!⇦H!)B!~]ha`՗>Hh3E IDAT!rbqq+W_c$`53I<Ġ?P#}>'|vb [p P*vk?iv-GBK fl?OqC}>Qfiv(N Mܘ|I2("D+$گTl\j>ZDr0{9';< ͘m-.!>)gTRVF_omkD}O(B1!~}w"|a !W#J}K#5E!AP#ZQG1?R*sD4G7INߋHOlǀ ED[ބهȇGOa|d+#M*EEF8RdI-XnPSA}A\6fF@th+F|QbDFh@VD$](km0u:OM:^ !!D(NTqPݜuJp  !dB'ʖH!FV%_w+rGDF ~݂Kb֓Q1h5Y-#y۟ ==(#P fU r_O`j4]=ܻ`v ;OL;ߚG` 7/UoĠyCpXu [&r&cIVP+WG$ (-܈~30}B+$_fE*2^_Zr᫒Z,kX6OƗ_&1duVw).-hW/crZX g>WxTiHƀWӼAR#VtR s[^nɷbݜEX:> wvL^\|WNCTչ}=Vhumv'Ror~8AF1;=Hnv4h ]iW9CH%" r8߅%a]w08B݌`̋jµ<@ I5=;Ա)8~W=#w /V`XY8P-ZYz Ti坅N.I)κvɨo mrhӖQ3+"[\N4K͸O  #p\X0ga {_t'zùdmMۏ8I2N;^ڜ(fHYEb5MQO_am0! 78 s\yZ#Q.֮ގZB]9ɗZoT mM/c/jj'mѬ _eSGk1׹-^yp)N}UaCJzЃkW⫢鄤?$̎[,y.YDx?-Փ(<G<ڦ%0uJ41'1Q| `ZܹE)Xwxyk _<t߆a=Zؒk3:v5g~nt>4}UpI.Di_q1VJ6HCeS_fwpe E꩖ ^–a9z Ksc;P`r+@Zġbo3E4zy65ݫt(_=?MݏŒחnO=ṛDN  #wF=Etk1ŷ̓Xz6+~mg5~Dt& p!dee!6()5hےQq(%)IJ26bUh;1v隀't X3|iR)7+?^[3L[†eprht]V]ҷ0۷o޽{QTTf͚YZ>7wT~x)1=1}s: +FLU!%f#wl>;^gcQQ;yf tJZxHI1h&qTze'?[>'- QF?LӸqcG ޯOrK!qo~ J١Bn b. WR^"HBʅ!o҅jFB !|MF_8R@f\G*㏤iA6r Ӂҁ>ҡFu2Mf2$ttx<D#z:P#Z:PGP:I)flpp::ݼ+B@|h@}|P}BЫu3 ݫɓH(گ)h)5ֈPPcbDTkVwCrMA\8תiTP\.˦xDECA5>GpF`QݸҨ-jvDҰURrhhw88NfE{EÅC}>eQҥ 6 Pd `v{XcL1/6ۮcv_m`))!z"| #K%#C4Q@w"Oeo؛: !d(Ba”iD?jM-z ? #Da]24EB1!J*{ k|hфE5"e*5D !ļԑ[_tClQ:\QDt)L !HQ>nSlrD 4EB19q#)Ɍf~v !"rynoyA!)B!~hB8B4AoZ&8IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/shift1.png000066400000000000000000001210001423020056600305120ustar00rootroot00000000000000PNG  IHDR@s6% pHYs+ IDATxw|u?̖l6M@ @HBD,X.;vy==yߩzH NH萐Fz#m31ɖIIG;~>|>B0)v1Bhhknn !4L`"80OBH!$S)B!āyB @OUx$qMt9BH]>t0ڧ[i!LXKԅ`!481*JaT'QFUNPp!I잺n}Sl`gH` B a05ߋ]~`%R0~ @9sooOxW(m잂*lxNpa.'=T5̚蠍6hcMm '4ϔoW5Tаbkyf#Y2TR{XXv )b!4l8r-A2lv"GGj \$P@E +?aj5wcNJr???#!dWr~)TA! D!q`"80OBH!$S)B!āyBE!q`"8B)B!ā}OBH>E!q`!āyr!#LpU%:3\aӛ~rL[rdLp}SNU(Jpu i/;sTΕ.נ  ѴVWU˺xax8氅O,2A-yzXѕux$aCahI#4 Wtbg))]u-'ԁqMynj_aR6㷤0cÞb@j7)?a% :)4$yۡϰ}АE)FOOLK9uW/LYuS-5Xd'٥sV;_l/󹊃ם1'aυE@yа NYvekic<ʊYɑr)<*\vJuzxh.'/$2&ao}&\Rա2+yDrWˮvVd} 2=>CH%Ś<~]oo5W4y~D~QݴZav .: /$)o_ N`[ډCIHbN+plm;|dN<G>Uj{YS^P%MLPWyVƥi6nq`"4m}y]q)*"DZXPP,.\SF蹇^ڤqpH> WִrYR/YĿUWMc8~kth^AmJ`MA, Y&jmkc]ՕViJ (1SNo!~172:;>$柲!"6:[?{U7=-CёZK&9u7HkyNI#KFҋ2E5.S!« MW@*rJJjοGcўGL v)BCQ[B;xL3vP72ŋDz.e8FϹkDɋVf9v\FϺk$_ @:<'=W?9ȩV)/cϙN.["Ӷ׏h.s$+YXQ2=*ꔠknP%%%BhR!$S)B!āyBBh0GY+0i8qSn(ak?I5(ւ;wɛCdx-W47V +}81wg\5o=\ÙG55&P4Ù*ip䈚٘EMگﴛi.?P1OB;?͜&%:i#5;|Qm+N9bB4))qrݕ윫}½&SN?2'LK@*9 hHW/Չ]PS}f;=!hiqra\Cu!@;Y7/T uմ@Z\Km\_XK7%a!Ug;efx' OrARr#\&V@9;~?[\U־3Zhy[-v๧pӇىvҦḟPIg[ ӵΧg>E+< k8xB"{]TbOBvw^ HO'Ι}Smg8#՝=]#]ܢj:<++hQa~S}b+O~A H3K߬Y[~~?Ldb1b93)gƑ||({A D))B.e{stI3b<ÅN}(L!P)U2WwNvKQ9>BhpmUEԗE9`t lɽ:yɁ}i);;diLE(=s/r;W^/vW̧$)Bh.g~i7Y5nGsd_̽u1iS{SnR9y4L9|RSZ_ɵwrqu+i[// Z1SaK2dӯ5IyLLIejBO_8P ͅ0JQXeRYwj`b#J9H"u&bj :CN%g Be@: ϶Cx'r:U<1(;Bh0 PTH|p_.ܗ s"3gH~)H☛< b`k ;|ƌ *,[Lmyr fJˮ[R@}QWi~Аm:uR%WiPǛ8S f߽MMq f[S6>ÃXTuk C9)|#rtrMKk'gjv#yvҷ/hdfe$X ~n@T%iLVX9Vy4B3 gT4UߞT&@`D<8YO11|Vzl f,bkj REdoCĂ'rwV;VPT3S$(1&%NG@* o+{Q+d-PW[9uET~Q͌`_W7)i"HgG;(CN!q PvP2L?D&j9ŽAct(}W[dn[qO9[W//Vܝ(^YZ/ M 4 Pv2"%i5D 1} `(4U-:!LKuI1C;f!gcؘPIQ~am̈̍w&7;ZoˆaTII5Szid=c \لr=eDtlYq}KfPET餚0}VRSSyB"B}xk \[Ѿu?<|T:fڼ;\'0"Z.eБv٠\ @LL\B?D]t`Kэʻz]Z;9ǰ=%FhS)&uS,-%4%s 𐖝Ψ]<=0Д?0x=Uv3}Y6}/GNܥV5`/M/lk/w{:5 9_{m$SMٿw qydN(&*B#H)H{9Q \qK;W;T-2]};!چ@?[L"x~ ~忇. [Z!4,(i?wIS,D;̞ƳS]]tjUܾnݺu\m E;C4^c!4>ej*KjogV [{=SVϏ0NfL^ %pOu?H&˽R1͙S*b)W:!vcj#@@8~ @,z ^gg=$L{klp-jJrG/bTbϺ!^EWee5$-ƃ%Qz'&l3{9[ɨLtU9tlUۨ3S';)FS^? !DyB±NXZbhv;"Z~ה{2Qr1\e,6ADsuM|4@vœ_;N|?b&%/$M'ӵ>Po;kuYAd.o>s_R ]v?`JBQ 1qc#;Kқ>yk] )eC%֦6pw*\/7T?@7MCIfYv(9pjeh]!$6"w_O_+ԅLD8S 鵯}][cRuS{ 4c{Cy񷎵:}jہ=1Y3bȂ׋Rx@fNE<`2oS1Ё[X\j:RSSyB"~7B !$S)B!āyB}XښN5P> |gEesg̫ecgk*t!'7ZC>_`l[E΅yژ{VRoY .]-]Z8SvRŤ'9>D#Bmr[ūmg8QSСrSɻpMb+\KɅ܊fӔڰ.tڬ`-OTĩ#B'v_6~ŗ[6OMnzm*l_ZŦ-=]3u~ı.H켐J=Y8y)͙$)̼Tה{2?{~RY]+3U2@,FYP?M=.mYh>xZu#g[CSL3sAJ`éS]6 RBuDhimzܱ?o5c姠z"p}觽U-e nA:@WSVz9ӎ!Z 5׻q> "!PSSyB"/)B!āyB9uBp Һɓ$͸>P9: :YjSu닜_>G}G*P.nNU:`|x1byJ~^=w[&9^m(i%jucc2)rpp}XdW& tK?(oώSt^:g\z'y'֙ ` hwӇOv, \~*?mf-ݡoy,W8$| "o &+h?zY4h(=˷}ϿX6qFA:jڹ5^ P ﷒@)OtŁ;<79ɘ%1cIi cS^E<0+GGGDR^^m\UWWP]]/qsstĉ`p:t,o :Y%K tQL_~|'K#5)qr#}}bSw}̜( vznlvKcQpGz#7>x7hJR_ Iw@` 84r/=<{c}ԩeϑoo%5]G*ROI_P\uѐ|R]:BJϟ8q*BfSRRR&r(/vQ^ ]! 2id|rBymMl>|8̩ :~lԻe'Ry*6q+;r;gz>WtKGZH%@ӴO/7> 蝰qʇiU5~J>L\vBSf+ V}p׉ ȴjpȗorW{q\``NBeԚl0n|u `p<Sam+l۶m۶mƻQQQ/|yyyz뭷:;=dž 634ԥ$~}iI(whiI> .:}d'`/VVC!&'ܑ #U }~6Joݙ`gE5 a. .Fk9;GP6KBϟ:ښ6ϕta7-Br K:hx,>nc}}||)..Θn04Cr,N2Ȭ8򴰰p׮]ƻ---'O?~ܸ<::zKKP@QҨ)-Yi꣗SVю3t|v(Wptux/ zi҆)Va}R%1rk" dشV-9WX@5}Zt߱='~-ssvG-&• {lYa/i^C!SU*ٳg5Cyy`n(/X4h ,R`X4tiʕׯ痯_^|ʕ\0#0бg+k,-is v1Ie?9K^[yWKG}^OQTuu5q*ʮNa5y:5V&QN2X +nCqjqɎ7o-^[uY12qM:%-i썇r$FIVۻP dHMZ'MտQE+{۪ J6mx#p#ٿkUj<'):CT;lZA̟.?kٝ{bmJ.ޒs+>r򆆆Π.Qoz58 F{VЁr⛟ƻ|>''GxG\ӟ|zɇgE9t\ܷf-\of'>!S}WANa%tĽ+ܛOɪݖFdnYh/Nwʧv%ȟ`뫫*AZSW{B{]O)ɿkUj`elR}Z`̮S\w3NSouϦyS7I[]r"RN8P(8= fnχAr3Z5oOG< NT#`ɤA,o|MԌ xꩧ4X?_zׇ|j_!| qF${*26s5q~ 嚸ÿZg?)s^ﲛ#-}с|kg7+-/ܺeJwQ/;{wFk_ת'2|?69Iש3vNPTDŽ6p Ә|ܔ|d]OOO/<#""bKo.]ڧ[U&W .Vn1K?cc= s狟ŧU9p}I^q"j!"OG|;L}_J`goRJNY'=?MC܂Yw.f Q-]D<6|8{)H$2.)Ėb [#^\WyWUxih&"8B鞮_I{)80!T'C;pEtoP ?@>LeQMM~P/ͺ 9ŝ*at_w2f+ ` } H?`d˄[0إX|cGga9JQ@Bjx,*2yF>F&!K!REVaE2%^>#eW۪=G«4G*E ~c>:) TǾ?*)>HMaQV[jqU@<;>^̼^.a1A}S<~1mR#Uh 6Tmw K8,_Z/klSCg^̼^r\C7KI*XL!3mh"ۦ}~}\=k[`!qk0˞B5z SBgIJDZDz,˲ 0 f98q|aU?k899,p5)!doe-G^ɤ^|kN&991Y%gQaƻ,+ҕTaSsrRJzk(a(Կ"8a,^vj2 LRcal7cD@~~A{iDBG41qbU{NupppuuXz zYԷJtm_^vzQdohY7?a2n|1n,0oxoonuR*=<! ?B?5_L&xӞ]L:Eu0dѣYFDze9X'⟝2m#:r:썄*#vY7P?3!&eYe DZ 2 1:ѧy<4MGDDP_`§>HrR ->?!8w?t G[R EQCe# E{!P_qO/c~(8::^ՇªiLb`q_^祶VazTn+ת-OZCg81 #Jå{!JQt^mDX53ÈZk׋$ؕ'NT*ojZXaé|er0{ɿoĕ7~l`򴫫5ue2a[|ck!Q5sd*|1j\|Va>nmmmjj2v!oe1T`8\jR/a ׋g|ufuyd^/U?/E?$R)95X>Dl,uIX DTbOew"f ZSe-ʼ|r7\Ԝx7_SNg1Cv㉺Akk(+橝2i O!K -XCVFZVR8/ 磪ڧ)…CZ8Bz`r*!8=ZV\ODš}!>OG'GT_rd1eLSajˍ-@_8d`(G*1ScLc\.wppd'6d2YdddGG`dqhYkR?oׅ Uk㏟:ueXbOQWև̻ӂ 29_=iОk{OWdoYa5P#+88x*P h4֚FFVVVEE#e F;2ׯmg-MK77oFW*GÒD"Q*yMSNiڛn >22^z饗^{ogorv;;5Z6{t=PB(O~Nk^ |L7喛hO\8?nV!|7N<== 4OOޛdoٳgϞ=ogv֜쁹s̙\mž]5=֡ܧX>65:^wY*I@]LWsYzʬ$EG[[:pfzxKƖ =&5nnn7 cE0yd\{n~etjlllll쫯jIC??%m'v&?qi9+we-ULR֬YcrKR{꫗.]Z[rw],V\:]W\[2J=:J"S8ɏ)Ӕ޲!oK׽qɨ{.=K_ֆPm?Bhذ#uŊ>.wwe2?ЅJJJ9ExΤ_CMTn3/k ѵxg}թ S_>{6fӡRԼ}9(tջ?~'wSoP*o=3iŃÃXRZYƜ0.jW?|?\~Ǭ/'[aOm!؇UhK6~kRqwX~؅4»X?P( 7g`GBHYyEGGwOQ,9uSYo00r[_`Ȣkgr6pp */YQ\$6G(JLgΜ !!!ϟoVZ3Su:9Ǔ&YR|&vQh&h23"IYԟ#+f׊7KaMg:ozl6ϓ]lٲ>"pR>˰'}ġCVm>)>z-"?~GŜSBޓ 6'PaPz"SjfiFѦj+L-.cj;+?r2LSR'{TRiVGG[]x!3~k/ k.I~)/ >/kԒj-Ϗ[n5ہ lqCk;_;5tb \G[;Ej.@|L-qp0WU$TO>ֹW3!IRnwN@? 9mW>NsUPܱ71|v_N~b@-}I6v'KMA:UO6jr}A;vhupF>,woϦS#b]ic?$''ru0dhyq~C0Z^ddiNz O͛éϟ߹sgttbHO50G}}  }} &N)?oom7,2cֵ5n˜1ԩ)^!Kߕ?5Ku.O cmoina /㎚S0cj&=@d=Qx8bccccc,Y[tRHHȕ+WmC,(>iE/j7e&uGT-q8/WwZl.?} $L] ;}b%_n<NnOevwؠW'Hbi'CԩNWdJD"$G$I]$ٷo_E[ =mirꕺѴ' Z1ۤrCĀ,wfL o 3V_u[-Ԓ@Ki|* ^PxhDxDDHR F^mRg=VBNkj_R èo9st<22揤!DEnb\V"3zNmg`ja/-`,k5af^꛹vu0Ib"4zUQQ;/e y-*S^畑{rmۗ$zT ={P/[n￿{ᾑ]Ţ2E݌CO.OObdɇQ_,[tc :3655_TUDr#_ݎ{}hhƺi\n<|Y>[섃=v~ϹnN-F$l2@/u}ğظaddl2K______#`5zr8?kYb).N,VK}kw#84ȜX-Bdf>o ͞k6{u5w5Sb6cٰ".haϗLE}"Ӛ)JUHd*K)xVVVr6Pjjj oWC(U4U9j^! @EIO.^ 1E  V7cI/c);2jL6/NHzSQ}USGP@ @  h.̖0PA@З\r够HOoqo0фMhwiEf¹g|>ֳl:p oc&ug20&[3`Yr6kAy7*HpK]ٳÀ1ݝD3O!W=f\Y+!(xjyIwG-nގ%]L(ayL6,7鯣{#b;kBE1El4/QC*lk*9:R!Io(Ud#^;ҁ9ܼϘ#93ASbأ'YcXӬWSh޺ 5Cnܾ=-`D"G⽸ѳxåRV\a03p.Rᖝ'[5QrxLÕ/0uwlBC6! h=";6!?=t8_KHw},Tڬ2le:f/2ti`}WF c)(֩#SZ{}=r!F5(% {ZxW)7ܪgjii:ph#8;{xv5vmMH=Er @-.J rXܨtW K K3~eյ}cǥ.%YԾ+oSwz2I.G??9drSL-$)5=5I%᧊Nݲny ~3ٵA10'GS<+@r۷}ûO DN\o )ZWH_:jk#<[;le YY{^e99E◓ȿwjfRvoȯ%'}0}}q.3[b2t]ͼ2%&|Yd-H\یa7p1M58fkI}o\.&n +x'z|}]s3οzlB+{[[}v>.]N~r=\( ]|ޥz Æ 366^ݻwEtŖwem:9x٦\/cX./&#c\ـ똕] ^՜+*c ^)L:tgM"Ύy3vg{M< Жz윙C<5*d#> ^[LRPa60˓ns9T#F,]t֬YP%#^ə퉐f?KE"=mYW#&_ cuLZYtr<]j* Î=TC)LW1sE~1CWHmu3ÇO2šALϚ,H` 56Y!D]VoˢS7]5##ٟ5åBܣ(.ji٣HL͛?\= HOUvO7(ֆߏ3$+VCjAQfz^hX5sîu:9ܱR0>d[%!̋s3s h3}:J{,â^Y};Ux;·- 4̜4L<_l]9q-;T%S@&6U)֗5 < ,~ּy;/?_ٱ;9X[[[[7q_>86 ̠;:xgv hmy~r/u?|l`ӯhZv|ɲG:k0$"5 f88k!5U(111bWeS_@hch;)}޽{=DEcP...e _~-tq6QCNh8<=333s3L}۸`@ǟ?s&yǑԹsr8͛7#=4k#Mό_j3tONj (/-*2n1ڻYF~׊ҳ SP|c4᷌׮bq~/)3*S^畑{rmۗ$zT]FN2͛ R\]]m}p8l6b1L8Q7)՝%ԒA|>_u#dV~Lf-b |>_`@4*BbJQ7}dTß *yr0&/@ ԓP"j,Qxq6]w)?$IʧX@PLB G@ԍ :~@z@ S"DP( To|z|e,Xav?>ǣ,)< &ӄ6Pmdc\.bZ @rk)b"I Œzh:)S e-,K!LRٳZk8޳ggϞǤqiaɮb@n"*AzH){?t+ enL s14%':F:jtYff8Xn۫&tp،gjOaҡ>hwv̛;kɤCfY)@=upjŤ+Urj3[ kOrӼ/!c)gXE?YUOuV!4"K>dR*|zMYsꦰ &a`䶾6W,Jܿf.g ׈ 2g(.ji٣kbѢE'Oi:5j!O( ]S%8+. rjՎYH֒%O9esg7nq(OYuNˆ pM#Yg,<ֽAꂯ^?VR" Swq˽`Ӌ7z=!NX &9(wpu U/NKv0Ɓ,+6npR>˰'}ġCVm>)>z5ȏn1g(aygԴ?rd͉k6ovaȚ@+61v\<.&x651,Mc3]!99͕p!C+(ܡeJ6@g;;[T\r >>b \,mp )GOILsMȴm*d K00*:WmmA癠㿟6ְ*h>rѬf8K%Jߚ:` K1 40WqGM)e 1z S^(VnjaS3ݸLTVqҢ~+C]S~Zܡ V^6xNmۚ_>f1!Wu-m~xKU-Xu~SEzW*^S@&**j.]jҤы/5kV=~o|tX-["ϡrܪaqsw_rZHtQV1J5-065ƅM5Xtšh{oO- ]8qHtk׭'wWSW.]`3`~ ; n<nִA #;.?$3YPk Oٳ}֭[ZʘFDD V&JMgmo Vv@@߱%rݸsj&q> L;$4zUQQ;/%e"?u^Ip:oYnJN ׶}IҫW8L%̚5k޽ǎsrrZᘘ(jJ13pI t4ϝG+0mi[FkrLľEGwuٲz9pns[gȃv?c8>agf'ܽ+o{tsjgm!'Qe?9z#=|cҥA;֊6Ra]ARZOY~/x9x`KеCk L7p2`8Z9{'yܳ_/[#u([~!umlfڍqtbt5!0 Rc,eԥiZwӖR;3f厎r6qq0 1Pbfff*++5 K55*grهB.зlo`oQ~A! xVVV f$\dddld2 8c\}1J+>ET~)ΦEazsЯ'f~A3A'[hg: \a8HO=`s~J';"DT(*@/2jPZh B&=qU !!2jLBY˶4B jC1EG.AGrȨƧtT&)$XIE ʏP(>lqg/P'P%B Xp2t(JE B>/{#f2TLG-QG좺)d P(_haJ!'/f-mgZCQ.I|})@x<|LB G4ԍ Z_J舚9K.QP6"D@ #+V(,,iI##GGG9XE 6j'Q[Ll.|snY~xѣ#[LXk3/u2ޤIee!r<$[11Ȗ|~ޙ,z|T.]XbM5"ޑsmFj#Z xEi?V8t h 9K3׵.W]uӿ XbzESܸqcڵUunU|)-ɗ)K@+󞟋GO _xyW;Gwm [K E Á?)x%S0,TⴡM~ة37'Szj)A:MJnogg-v>Y9FAu/,g^yMɓ܎p7)J_]6{e9\g]eRXXح[I&ׯ_߿__ͮQrߗSǓ[RA@ `2?M𢮜|lS XNpӬuVLc<̹8sНs>6?͕'qJmvzM/$kiü̯ΙNѧ[?)Oݛˡξbn:.]gK&E>ikaXڛ ~>ҩk{1/| 01;&F ]1 *yQ7aOQ,9uSYo00r[_[CF;)6lTf̙m6 Æ &Om(c()iEjWN*WI q>va99X&i9]c=/mn%qN\C8{3[s`fNw&OM c/xO6.؜`Yzy'lt'Fg n_^#>[$KzFJV$;-9K\~Ԯ܂ˇgߺmޫ}:J{,â^Y};U^}l̝;2H T_TbJ!WL|O+Sk-cgE9zT7%Ԇ,{t`A^/\G[;Ej.k53ӼrȞ,z|`mZ2n(/<0:ymn Nt~yώvy97tP/m Z/~[>n; \:<䲁Knz9MdêH=ծ];9X ,2(k|Q<^4Ζwޛh ůUt,ONzx1iȉ_Jv,I V;Nk̎yƷǂA7L .iyoA8˫6]c@$׻ZNl,\|èct8Qg fĜ0=oy{Z]溜EO-/"LX7|#CT؈Ȅ MA˩QWhg\)9Xd )m^TB9TϴQZ&q8nmCꋅ~ZJ,fʔkY4i֬! 0 q&[o9tćLv$ !WPg)ܡeJ6@g;;[Qa0cucL&yҷJYb,}}lޔ5VlLc첹Z{x\LYqg6lj:5b׋/X.e>f:Crr+l+WCv6vFFǎSurEFhzڨa:t>G3[o9>ղK^_Ymi=~xaygmZxx;q̜=< $:֛<>t>LguÛ@K5&嬩l))~ۼgN[zi4hV3%ȒGw%oRw~ӥBz[[˫縣&2T۷o9L<"@oSEzW*^#\SODGZS~Zܡ V^66 c|1\mg$o ^ۂ ]M` 7ܹsYf^tiMӧ.]* F?!DioŐxy͕&K.Z6L >f^C}f"d ltO|?a9e$Y~‰cGs^n=ĭF}>귰c^~mM0SK-?d1MR+00&˗/h!K:4eZhTvv&l:L:hd`BY׭NL"?u^Ip:oYnJN ׶}IҫW8LEH}Jb;3AcY@`X)v"wof̩-j;1a!᷌׮bq~/IFm neM_)Pٞ?ijkkqgW_qa IDATpG"cG^56' >V%Qe?9zc 3_%eaPvf-Oؙu w=z[s7ݜY[&lgƍ_~i;wԔ8AzڨaY9fbE8G:?։uyۿb,fkRq,ڌiokgX*wgԱT_sTޫ-"]PSiZwӖڽ밍$K/5tQ]t% {cf>R%LǷm>#fۧ}=fE2̬W(Fd-А3sfK__w}%]ڤܼ!1iNxd^0';;Ӈw߳`G~DNo+iLRGLyY@(,Q T#1g4JLA3pH(r-̷O=>{_%206!!MJ>Zw 1r^K7ro鰰Y=MjYc)ɔ~nf3Ox"1(noZZa. nq^ě*t_:{S)DSNB!\.HPQQb-EM%7EknYNa8KC#p}[[JC jlJPd~ )B)++c2@(i=iۗ#jPq/))ӣQB IŚTLJS@(5 FQ0 55Z@4(>]@zH$ǠI-++ 2h@AYY|!j-TY&"I:222m#QdffhTI1Z[ IEjjjVlEXeۦRݐ%BTkSJ+@ QQV[_<)dǤM3׃RW1`?,% 0 CTdffjhh(D]!IL]]]JL*ʤ8Dumo K`?fMQ]dx?@ HOOP.XD](+++..p8TëZd*UR.2 Lzd2U`#YYP$z 5Kj2T|>???ڿH@(jgIPhTg*RR-}P1;dO.L&S2>%IR%PK*&:B@ (..=S:Z+hoCMf*xM5`)Lb㒓D)IM"4PAKR@0_HMǪ )%p.Je2O~T'Lj5Iԗ*.$IRAHL)D$I5j sjjt_Z"fxX 7(ٚBNW6N QV*DI@ uIOD(2TjX ?E)wusʢ)T2\QmT^^nIɼ}I1UKVi h+SME}5%k]T/xb?S7ZM] 4TRūV6֤(BUBX t) ~ "^?D !h SE\.1i JLԮG^oOqF E-~tjYOl,߇J;ZmdI4XV 5uTE~)a&* rߧK)40&IeQ㤢SR=\/eIC~)ªfI\S*NL:)˥K8T4ԸRI)I=y<2pM5>_SRS@5~Ukzx<Ŕ q3qIZMk Ikh)ĔK&L4U95ѥm%$lש('L&?IC/_P]F %Q]&LC)tST/hI/_ʌ,UQ2J2^ YfR }W"\Rp yRfĽ&WEH&=Uڼ:!%K^(߫Osi|o%5TK&F^n$:`ȂQ|@ S"s9t#m =E )@P }dQA02v9~-%5͛?=7?zt3 Hu#O2Q C)AKnYOܳm} ^G_R8BYjԱ+w_})4=;ࠁ02vk?xn is=kAy7*~byzh+D"1!r.ҥ稞:ω:iwd#]nc7OU|dչ|DCǧrjՎYHj YtkXSVz@q?׎o{y1.A1]nj(/Hwj*ROLpkj^a>Y`˪iik9B2 μDGZ [VVVe*`sԘA@/qv=_2eCY_Js8ZsΎic[4Qip=%3:..tω{Br)&3 F*ǬX?̕cD^2fg ti}:N5A+wdyp폍&۽aj \U+&$5CV22I JvAW18$TH{N)0VV (iaĔIUavm[ߡA3oض#>thIŭrCkBnU=cݗJI-|l܎~ ޱJ~si[_㪫5teDwc6ѢMB "֚iKnpmC3 eWfUax%D`퀙AsGVJ"n?`J;o>erZ6-t^(u:u#Dέ5S_WiϜ6*Nr˸$lU|Z(r7LA3pu$›O0qzK}fl8H1RL97)Y^XPRB=ϖ47 _skb0ޡk{J}?n9d׵!_3n2 ȲOoª= ,yeڢKzԟm1Mh1*әcݝl,ycIi>ߎ@̾iUgA~}oz)IE )@2jl^ Q)I^k/eQUEȤ8 ^K^k/eQUE$L*Hz! bI" Uu 4(YSK*ɔOI 55T5تTdmȳlqgm!Ը𚪺RBgUp2LH|>B^FU]C~)*VnfL&!IRiG0 0ꦐ%B`8 $I!{DU]C~)T%sYKۙ֐$){TO/T5Pa(%@ S"D@ :GQX*6OEUGU5bU)ǣ3̟&$0L{P7 \ Uu pZ)>b3o($M5ׂL89!Q\.p%btA'k/eUxB;*sPaaп0-ӭGx<)񤞒C@ }]Uu t~y- $ZL$ [Ư2yu% VD b{ !MU]C~)-5UEOp I HjG6ؿZ2R'YGu.2]L)AT` !yT52#*BRdTK1cp11}ƧSr$oJ^k/eF$ E!)R7X/F>J"#5oI#]KqB,,UZA!Gb8 BYPS$|$XIE89߀ O=Uhe 0-ca(!*cBٞHODR9tSS1)P$hl&-}I(LiHOD ES%S`lWA<~)?N:c+nRlj@{JDgME>X 4wi?p̑>(@TfTOӎj_IzH,zdY-0A?=SaC٧1CZug20&[3`#G _&sUԝTa D+qk&/k7xV+g+hMCЉSܼ猱?3O#pz۹}0M3>253BCPrT̗o[icⶹ5eI۱o\ CGѡ}6ɾ`(kW_ FmOn%Gޘ%=z55r,L~K Rz[*:8Nݜ>M Oⓡ鴾nU M?p qJD ue-G= ^WV}Fk޽=b {77ż[/ݧe>>S1*tˉ}Nk ǷX#36(,)G?Ԟ<9YL+jjfim,xO]q'n83rfgeVpMC3ݟl@;%\+9+:pdɗ>o/HJswvケ<$LK LI!ń0F3F2X4%G?j:dAFCAdT[0 !9ckBM6}Y~Lc9g/]s< 8xVtĢ;R\>}w$=yj]ɽKa}K?zVahvۜ'u%>yjK-e$8yۜעuAhW/_Z1w'9=DǑ#FKc"4MrMۍǫUDHXcߍK-v?s$2Ǥ'q߯.*c5#|y^%#+ŦШv`N&>kv9d|_5c;Uxג2ӥܞ#M0-}ǂhz/iUu fJL(]9{qv/++k{ۜ$7%Ųx?ȣN[|b][=DM۽󝒆[gfS#P^^^^^^[.tÈ/E8 LY Dxur= "X[͍b[:(qs`$cM)AҀb%Sxq8CAHGBD6_DHM$2{RS.;NEWnuoOsB7@[EHNFL8Ertdnց* TTi΄SQ>qB~.;R-E*Z/٩)RCթV73-뺼Qszw*tِAt!CXRhܑ!_/K ,) kiBBU {S4K04M|J#]".33Wgs fP{`  =[[[333y" !l{Q즰XV#(1fBpfPF;vIDAT8U/Vt ̀. A3+~+;y/_Gp7<*yE᭢lN FY $;Kb,5NF$@Cp) \@vb" [hV;A rL3km)Cp1Qj} %?%"ŀ+ lY"n/ t bIENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/square_root.png000066400000000000000000000010261423020056600316640ustar00rootroot00000000000000PNG  IHDR;0IDATHKջQߥ(PHqūHxF=*D"*n)^J!HHO&㜙o=4笵k2Ggjxו_9tKJRo <&\!Kī)=a0rwA[_C/2 GqB类oۈ3fjOq=Lcm|"T݌#gpoMM1!}3E*_S*#lK/U+؍d ({]q[: 6mӵU{B UlMrGX^JK)sQ0 ,G,-}$0r4v+cçpgSW2(Qa88ʅ[8"SJ2?2Tgom%W6klX !}]=$O9'Tq5(.)Q.IENDB`deepin-calculator-5.7.21/src/assets/deepin-calculator/calculator/zh_TW/fig/standard_mode.png000066400000000000000000000532171423020056600321360ustar00rootroot00000000000000PNG  IHDRZ#D pHYs+ IDATxw\.R4Q5Jbbbbb)77䦘%{P`ADwvgyء,;O"royf!B8:: 1!$! BHq` $! BHq` $! i"jX7s"<4ޑ!*VBmj޶cɂH|_Xz P.9ުā Be2_W5Xk_XG4~5(ђ-۰ нkBW'^jrjhjnܛmv Btt`@ tpA{І_P2^/HB&U[up:_l祴\@Ɇ1q@e A}pA4傈q8. (1vف5?աu)?ߊzƁnCX?:Za;iBASGBHZ:;F6<5=hm8@U|?+#F FnD M/zb,j>k+:e_no9ޒ3)jzG0n48>I#Ji{f#R:B{q&F&;Z-4P7F& ZG7F޳@q ݗF+@]#uEm"U@7~vaR %]H? w@PpcIa$`nF 5/޳iґ׉zӖS8Ԏ ju_5YN=``i` (j)&`Ej7y?)K50 ֻ?Bho4jFAnB_[!lj ?) @$s@Xi oO q&QPwA~E5Ps ™9x>$T[{GhP>쁯Oԝ N?a&jT8w\gT;Z3@!!^ [pfA%?gPKzQBHnZR;E0s'2v5;m,xzP;q3w"2 ́w v4]2RLdq`2 =  `GtPˠ^[]TjxP[j-+.iK_wWb;*V^^lam0yEW$\͸Wm7&E9DIѫ"'?;6Du/6PŮHbw$H(ѹa#%w=S[: ~7C~r j\O8Qp.b[*!JvyfOxz1|b0FOGjTUMLF$i YЖ0[EBez휸)}vMTɾ#-``)zsM9#Τ,'w"("{U+?*8r7\ZԸP? ή[+>{~LѕSG73  bVdP|Qef0nczK@e50x1JzB+7;|9@.%dO2HWWJ?dkͥ N8qߧj*Y@~fjs8:hO{âI'DM&T[UgXLlUϢv q q0*.C'Xٳ/kΝN+ m^&=ck{:l̐0;8-b'wՏ_3EPL%30 Kv }K*2()&tJU CX71<" 8Bx 20-~ .C1'!@Eet9HD"O+_J [1c36T8h\$N6V* 7Ywn/,&!&O,sԾsGu5תJ?s*ϡ׈0&Sץh]G`Vm^ Tld&NwiHI%U-aCHaeZ<)FjGJ7TT7+:""V(IB%TeD].Up~'lCy% juc¨C$;TXP_n6jH7SgN1ڷdͶ/.Jk"~mBTLX1X;;9uq^zئYNrfۙUͯ-]|kjZb4 Ӫ]#T3u蘗^ctw% Vt9(C@ѵJh2O - $ptH%Op`բ'-+ݩ] Ę(`:~kLv aw/ VQ"hݤ*%Y??ȥ}!!\RS6XM+ʙYldWVB%]cnKT }aX,=i&eբ~\`кͱ&} 5ptΕ9Ǝp *~?OaxW/n鲣NgѪ}]hـ dbϚ;3ztHYAiﶜ6_l.Qdv[_atvw<=UC3fR,`7ކaDzՇ'h6'ԔF-^?>ѓA$?'L|I+װW1/ d,qP.$ wW`{&uo6qp7G󝢦5Ws8z.;/0#zJ^}Dž܈dT]=J항 mca̙ 7XLcQŒ$KˑHQz[Tցs $Gl̙ X@&PWOA58,^nF&:KkQ9@髞Tڳ̍rPS5j'𳺲c.15 GSr"x~"h)􋮋uBn,4MUyppu/!qWuteߺ]H:JA,3.N\S<-kFq&F8D! \%vdNEԄi9sXa!؃T1E XagaJ9ܻAC-8b &"-x6VHXKةӂ~ @qo~kӒ4ZyxC'DՎĒGO,ku5%q6bt"C˨&̡ꚉZU 2ĪkmvвJltә1A]s֛x"&d%` ҃:|ɭ?$Tdfq:*WE&z^LsO.F~6Lx0VU*"wQ9~"9%BGݤbeP\(f'1-g;M k1y.&v~/~.Q"싩STBʁ՛h&j5O"mROP 7һ(Rz;3Οq6JMޕAᎍJmafڙ}{ϟtd3Sht UWv.xQ=tփ1κhuErHgH=-Q+DIo?AvZEPYҺTUN~Ա=ÜrWŊ*huJA!ܲn-d6e ;BU7ၡ`;ǮA9Tھb$K6aǺԤgd?2?'u*8z*2 N.l]cy<ަ= <\_aN<"ە4[PA^(7oSMĢKGj)@Aꁝ57Âã>pDr_섄0-<0Ⱦ!*ة9zJէqqjK@kNeM%Tk?{3g!2@X;\cm*#U15[}O1e*ОGZ]u81е;~_r W:pP6ٿL˅ ڱm?WaBJ'2*2^c׻7)- ih\3j`6hDCdզ:IJDUeڼ?*b|`+? Sw;~CXMZfkHWql҃ێ=>X jH`|) Xḿ;elwq?e<_ȅԭ40qR¬#N=uDsi\ѓM=NG(P"XY2MK4 R$MΩkdX0%_,PMD7NWDž;bIvV Bk[ [0' _\fOY&%܊;^mMuR2Ⱥߨ+Ԫ8VVVVV|^Mƞ囮eS`{EʾWաؽhjf~qII~f2DcAyAu*;?q"L`pRZǭWF73f<>nxu10w(ݼV]-r xt|tEN e_umKqR0h`eggc pG#B>!$8@I0B!$8@I0B!$8@I0B!$8@I0Bu0ZW);e*lkt"cU^=nk_i+X^Uu8΂P-9u*1?iwhe7O<|Zoԣo^x-H;y<ʍۥj7}FNJ,;|tuN=w5s ٯ/֮K(b}{Ot5x 5mAډI)w-}Bt$j8GnF o# UBs4]pL 6ulL:B8RB61?N}mсd:CD)%䱳7ڟwj͛Ztਾ?Wζ Of]|׵  g6,_$C;Ȫ'uEN==ғNZt,Tܪ.Zz-eWwܘ%3Zy5dzzi۲'K\{ S{i۲nU="eO؄jWxv !G`Յ7ZrDenZKBYF5nO*'1};LG8:P;)ܛS OVR?C/"Е~z 13%Cu^xHAВԽnX.6 ίsۗ/;1w6r`ߞnj 'EMa@v͝6zԮi̓k֜v`[sľK|##l@ ۿ79WF#ǎ@t_wM1*H:k⍪06x%=W{BUfW8sD QQd8P J&3ž.T$*;nqMPOm= v!݃ rx{s7a}j*ǚEY,}ˑ ÉXTTF&j qU[q=]8Zyh$mÂm@䔃:uۿҵy:Pu%'6OwSxUsϬ@)hs*PWLHm6@Y jfcJdޡv(+-ߢ'n1NWbeyHlɆ;Wm& u00?`4`LB+~ltΦm;~c=$xZN#h<ƇX>*嵷1_Yҁ6[?K.c2c KxkW7{ѡ E)۷LZ.Tx8VQ+[jcU81gӡƁR0v4B K8TiZDei fgejTޮ,;W5M+-A%CҪT>qSrߐ"׮9^1!qxdqՎU@"sЦgfV] ."}i}<䏦 l̰ѓ5$^6'RBq 8$~q=9Pgp#pb;kn'mvN5>жَ≳EC!Veg R)*YЊ#u:!M0 -jB"lXHwf@|BcT /Q`lA@,gͦ~CGG:4\~ 'G[mɋl*ݛٕitLK6ZnIwicƁ+ŽpnLJN>j5O"mROP Ʒ[%XxvzYrVXQ_J/cK[b~ZrJ}̴8ok2v׉1ܡBp̾۵ODžDpkeNa~0ZG$wsUJ߭I$2HPYс4,29ItG3Ѕ¬r'cd: .+o$==ӳ}hy_X{rtݍ&$>xō3g5w9Vh4MpTwե WN&WvpVQdz?)}M2>,P}ubmyp"BHq` $! BHq` $! BHq` $!  fQ8 ˗u<Ӫv3n^+wܾֆϯ >kւ4r+>+s ZӋCr7zc5-9(7a02y%蝓^j@}{s8_1x{qay$ |og[{w cuuVN}YC$` $36oS#g=>_0Kyf5i!!=f| miqo5i.2ScUX^͙h/l?[[BXGoh_Q{0D' Bai%Bʦ*j} u"yiq\Q!Xx9F'U^s q_dBmA;ƍės[?篹󗞝6:QX~}rA ec{;q f]]VY:/#Z ebm[ T)\^If3ȹ~vPY(79[Jd*jI=sstssScu/oE{zz3#ԉUr +?lw+3׽4P5olTHV#>\H^{zar16^A5P\\l\oMBmgK$ѨG^/jķ~>Ç~3fo+#A  ԉB!$8@I0B!$8@I0B::$Q!$8@I0B!$8@I0BJ$,0 !p&PJEQһ^ʼ<}2/:CZDZ,{5˲ <7sOW(@ʼ< dƂJ2I,R5y:YW(@ʼ< 6Ÿ88ad10 ȼBPAgq%#emɼBPAgyFāiT+yyȨ kT+yyȨX0?T3U%Mi45a% x: xW 3P#bκ&kK}g\JǁlvI_%,ƐoH+F0rsoiXT=መ蘸~CL?oWhJӨhIy|h>Mך:5{U$(~vyfb`s[r-:0?vxṿd}sQZPeWny7]7_|Rb=_>܏#nL$:[Xg>^?*ڲF-ӦHu2ȡ_viq;kH n9n0kݒN!OzM~Oxw;-XɳYh7Ѷo}UbO3FqZVxcBqÇ3}mV'paNtۢ]i'݋l;QY{k)&fnY8xOH +ClBܼv_5ߣ־Q XcZZ'u?>Ծyvӻb߶-bέ|F Bg>qQ2,Uhvf.utwU˶Ž&:[T0 ?G+нA'(%nCGhn;TB۷^ ot 4NNzzbF*h4E~:sY>}*{nBLLLLLJ+j?_阹i -+x[lָOˎ]^v[!(•mۮ&ZZ# }䗗Y-Ъܥ+VXbu,ߑ{:EmueN-zccòϞǝ\ɳ:A;C ig&G'Ƿ-ou=ٷrLk:ߔ-Yj{Dh{NY!fl=u:ƌ1u i??2ΐWɦc؈Yo/\]n,}}WQuvľvgٺN1=2нwI?x6Zt/+=zї Wo*4Ot~gl ks={cqLn_jw`3>mGI!WL1Tbjow!.tƿݒrcv hЄ3wN ;ՌcвxwR*nP ڎ@'7}O5Ĕ#m.^ۮW[Za{G~a߯-zנOF:w;ֲ gVzb+ف-Lo޳Ř]|=]młVqzǣLr ][D:378락OzesJMǽw!4v|Ѳd\#:+_uk.;7}p)2xIzzgKja1+lTWmhȼBPAgBqкS5F%ɼB x*Ɉ8EdfHd^VGFdDhRd^VGFdƂտԌ+yy e^t gT"2h"32P+yy*l{ZOȼBPAg)9*yA|9JW(@ʼ< ʃ) dGy2/d_˃P>< !$8@I0B!$iu;x'J2vZVZȖiMp'K޳,+]w)e lY * ^XU;SZVZȖ 2.8c3n` ֲECZ~W8Ȓ: eֲE #_5ֲ5x1A#,T7֯[̌Q `|1I*0 c[<3FPa $! BHq` $! BHq` $! BHs%"dz<}tc* F9q:… ,X`ԣکvn­RᮦX01{?z'g;eʼn&$튉vN>=w\SbbCBWS93}߇]-kgf=;,XCw։~ׂܵDO+@͟b6Yp<dBL,~l"%8~+Zv5yvb_t35beh6$%%͟?ԅW>x{E.x)޹fCfMZU{s*=mIn=ǃ-a6[q .|g+L>=66VmRRҊ+>/ՑէGz,0WR`20 "}js3}|JJJOLL_}դ$^}ӧwx93!QjS7WҼjNw=.N;ߟӾ{o3+ʡo%-\pܹ;o޼W_}u֬Y/7o^H 550VBNVzZ3,z%Dw۸7K|Ϝ?ql};1kco7GM]i5kW_}5k,sikLNNs?K{h\?-$tv=5Ӱ`\]ɯ%봣9s|III/׿xHsJ^ϷF#dݼm6;ܛ ]6nٵ헇+/NxAys@l}|ng`Z...Wn`޼y>nA7`XҚ/S0~Q{}ΊqKKa=) !W`y$q̙?7}Ŋy+V@TGNq#ٴYRމWF7}"`ܽ;%^v;bccCCC.\?All,e49Y!|0wuO>0ßVl{׮7@-;/g3܉pϖVglٔd0g8gΜ+W^~ԅإ|xl=Wm*Q%e!ktl,9k'ѓt ﶪ&w̌ozWG8N|A{p_'Lff(b IOOl]-,,ڻZn~&|/ϾQM8ht ΖBȄ0B!$8@I0B!$8@I0B!$1"(_iֲ5x1A#@ELTZJ-fƨA0S7֯[̌Q `Ư GjYi"[nqS<ϛJE7|f~A-7= ZTVֲElPkN ,2 C:E((p4/(e}<2qHg/(F0$!$8@I0B{!J%/(FZDZ,ۊʊgYV^RZJٲ>7T*j,R5wh~A-d\p0f80 ()e lɇq%u,o1*e lFāj: *ek3cTFāYoPi-+_4ncb:#ITa7LUIyf8@I0B!$8@I0B!$8@I0Bv킊]'B n0j,8~ 8߁5gRn…5UŽqt3.>7:wPv>hʓsǸY9Ă3ys%)0jk|. >z'.e\ 2Ezd=m2eâ=q)?ϯ(˳ʮka鿢L][;'~湥#|!Ou>|??Ե1k|6D$dKY nW? @}VjhNn|z iOU6[>W$fmauiF_;S'|jYfM%<d>wbHټ^m,jNYCl Ij/Oj%vfDÅ{2̳c]"twB+,Y-tqH{`.9W"-Mcɞ zSVR vv8uqӯ}΢Q"6 @V 6.U7vf|6;0_.׳1Kޝ7}݋֦=;|j uU-/M[^ ,4g\qk!}´}6γ (ߔ7c}IeyWkK0j s3iЂ]6r9o(Ђ=ļ-޲oƟ^X浙O~TҚ+nʟe?|g]' 0pCxj`+lBùr#H@4 М?{D/b^O=ECW<ߝ{ce{Ǽt+=|mo-~oqh.#,׽ǗDOO&iiwH@\LC,iWs|*ЈPo{Nؽ2?<_?aۗnu4 JZXyݢ^^|GS}8n#}njlA~QeǪguƒYg߸9}XEU˖a_~0>ҴB{hrS&f80밷898 jB 쇇COv*Ĉ8BfGpVLBU0B!$8@I0B!$8@I0B!$1"(5jPi-+_4"DwՍC,`YVQi-+_Pd0"UoPi-+_4"r@U~JkYiՠq әI`J:3hDBHq` $! BHq` $! BHq` $! BH3)wZ4geEiax{S>?}7l{<˷II-ղ/>j29-;uB uɏ=k |zѢ qЖBۙ3hىeGykigbqQ:|/-;ۿ]y_u4\~ң|NC]\;S ˈR 1gے-,!%7g| &ّjʫ3?Ztg@EEnTZ|lT=> fi%Ţ6}߭)pO{慙}=δ 1 -ןQ"Z{vE[f'ppߗna=ޭ0K'DK('vvq 렡=98oBllMu#Ӆ-ShP3:/?-\ `&}F_3U@llm `2D' K6tlԛ<{tjszG絳4Ueު.pwb 3FvI_cG4vNp809HX[1eX!zp}s{&u頪sȖM2Gdkkϔ=Dn^1ugӻcu6EbMteu+]zMz'2nYD^/?.j+ψ9_?X3 ΅{zz3۔SJkYi"[nJvvٮB8@I0B!$8@I0B!$8@I0B!$1"(57֯[̌Q h'oPi-+_4"s~JkYiՠq f `p$/(f7YDQyֲE,hZ3KSAZm3wPZJٲA9u* ,0 !RQ[8RZJٲVIRj8SZJr#xBHq` $! BH= QZJr#X_oW޳,+]w/)e lY * ^XUTAi-+_Pd1N70 qJJkYi"[n!-nbdI˲[JkYi"[nq`Ư~JkYiՠq`TZJ-fƨX0H$tSU1-nG#B0B!$8@I0B!$8@I0B3t ]b"q` $`9ӣ]p$Ԣlѧ}o<~1l#c쵷mXKgn}Afˋ_|fqIalͿ{/K)D(7yŁgo/;/.1nCxw-Ƈ:ͭz~T3>mjN5iJݱʓf~N@^C4=,n }8я[sوNDQ@ `<єeΡ. D!^ ԕ+m//*{-\^|̸Cfqt4N5|ז|ʏ3=S Sin.h{mZq #͵~ Nfxv}+n]?G^YYbJ49w}gI~x/9@9q/<6 f4wz^7.0()f<Ĝ=행}>||*/jEQс9{>~Ϳ-?_rVUTQPJ ARڇOv, d,,h"eݖcP\3DK7f8I:3u?a=6,\3jɻ|l7S0L]LΨBα?k 飻ko^,=zkO{wq;66 '(I F.- i J"j>TJiBM4KZP,"(`,46.vػ3;6gln67d!c1Vg$ihh(..NWc`&p-myGMdb!:\, tB BH:@)X!!` uRB BH:@)u w>H h[d&ajԁ [b@"ۖ7O P8$ml[ޤ?1V@łj7PA? @t~hHo03GB #m AH (yJٽ[/dB|V4;@ B¥y-p5$p* t0fYp%:#KLKNa ƔN.\, {GX&/8Mez>4鮀q _2 X!!` uRB BH ]t|,]i1޺vbnO:u pW}? =M߭-k׾~#q#Լ+Vr/o3N>?/%sתVYBig֩kV!=g7<5]m=~.IrӶ܊a5g%b'ٳ=2螚fM#^ytËe'urHivoyJF(6lO9 SsӒezMZ8tg͘bT TL!:-]_ݳ/C{ssH<(9y݉`iYҏ/+&|MN7995R5Ӈ-W+I${Dwv5*4s.9fd73_?5Du@bnAq$D"ѠFlok$7/w %ͬ:P\Z_ `a,y5U/7BVaϣOJ!\B4/! ՗h8Nrv>uAS5N&N`>&Kќ"?ok}HK 0@]p+^p%L߲y׎}ogX,8xh+_^X:Ԭ"-]xFq(o<9#F0Bem^7IE訯z՚?wey~ggȯlmk~ڤ"ۓן8DF"aLp~A:3&1 aK<aaɨM"9y1F)ո|H)I'llI^@ D)=Jy3x_ÐlP(QԿ H֤ p ؊DRg8Erw(Hۊc{ Z5sx? SNrG@vUeOrz$^Tgq X !ͶKVs %_hover Created with Sketch. % deepin-calculator-5.7.21/src/assets/images/dark/%_normal.svg000077500000000000000000000015721423020056600237030ustar00rootroot00000000000000 %_normal Created with Sketch. % deepin-calculator-5.7.21/src/assets/images/dark/%_press.svg000077500000000000000000000016061423020056600235450ustar00rootroot00000000000000 %_press Created with Sketch. % deepin-calculator-5.7.21/src/assets/images/dark/( )_hover.svg000077500000000000000000000015741423020056600236540ustar00rootroot00000000000000 ( )_hover Created with Sketch. ( ) deepin-calculator-5.7.21/src/assets/images/dark/( )_normal.svg000077500000000000000000000015771423020056600240240ustar00rootroot00000000000000 ( )_normal Created with Sketch. ( ) deepin-calculator-5.7.21/src/assets/images/dark/( )_press.svg000077500000000000000000000016151423020056600236610ustar00rootroot00000000000000 ( )_press Created with Sketch. ( ) deepin-calculator-5.7.21/src/assets/images/dark/+_hover.svg000066400000000000000000000014341423020056600235360ustar00rootroot00000000000000 +_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/+_normal.svg000077500000000000000000000012521423020056600237040ustar00rootroot00000000000000 +_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/+_press.svg000077500000000000000000000012651423020056600235540ustar00rootroot00000000000000 +_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/-_hover.svg000066400000000000000000000011541423020056600235370ustar00rootroot00000000000000 -_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/-_normal.svg000077500000000000000000000011521423020056600237050ustar00rootroot00000000000000 -_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/-_press.svg000077500000000000000000000011551423020056600235540ustar00rootroot00000000000000 -_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/AC_hover.svg000077500000000000000000000015721423020056600236750ustar00rootroot00000000000000 AC_hover Created with Sketch. AC deepin-calculator-5.7.21/src/assets/images/dark/AC_normal.svg000077500000000000000000000015751423020056600240450ustar00rootroot00000000000000 AC_normal Created with Sketch. AC deepin-calculator-5.7.21/src/assets/images/dark/AC_press.svg000077500000000000000000000016121423020056600237010ustar00rootroot00000000000000 AC_press Created with Sketch. AC deepin-calculator-5.7.21/src/assets/images/dark/clear_hover.svg000066400000000000000000000022411423020056600244670ustar00rootroot00000000000000 clear_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/clear_normal.svg000066400000000000000000000022431423020056600246360ustar00rootroot00000000000000 clear_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/clear_press.svg000066400000000000000000000022631423020056600245040ustar00rootroot00000000000000 clear_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/cos-1_hover.svg000066400000000000000000000106261423020056600243310ustar00rootroot00000000000000 cos-1_hover deepin-calculator-5.7.21/src/assets/images/dark/cos-1_normal.svg000066400000000000000000000075771423020056600245110ustar00rootroot00000000000000 cos-1_normal deepin-calculator-5.7.21/src/assets/images/dark/cos-1_press.svg000066400000000000000000000075771423020056600243550ustar00rootroot00000000000000 cos-1_press deepin-calculator-5.7.21/src/assets/images/dark/cot-1_hover.svg000066400000000000000000000073061423020056600243330ustar00rootroot00000000000000 cot-1_hover deepin-calculator-5.7.21/src/assets/images/dark/cot-1_normal.svg000066400000000000000000000063551423020056600245030ustar00rootroot00000000000000 cot-1_normal deepin-calculator-5.7.21/src/assets/images/dark/cot-1_press.svg000066400000000000000000000063551423020056600243470ustar00rootroot00000000000000 cot-1_press deepin-calculator-5.7.21/src/assets/images/dark/cuberoot_hover.svg000066400000000000000000000057061423020056600252340ustar00rootroot00000000000000 cube root_hover deepin-calculator-5.7.21/src/assets/images/dark/cuberoot_normal.svg000066400000000000000000000054451423020056600254010ustar00rootroot00000000000000 cube root_normal deepin-calculator-5.7.21/src/assets/images/dark/cuberoot_press.svg000066400000000000000000000054551423020056600252460ustar00rootroot00000000000000 cube root_normal deepin-calculator-5.7.21/src/assets/images/dark/deg_hover.svg000066400000000000000000000202701423020056600241420ustar00rootroot00000000000000 deg_hover deepin-calculator-5.7.21/src/assets/images/dark/deg_normal.svg000066400000000000000000000174211423020056600243130ustar00rootroot00000000000000 deg_normal deepin-calculator-5.7.21/src/assets/images/dark/deg_press.svg000066400000000000000000000174211423020056600241570ustar00rootroot00000000000000 deg_press deepin-calculator-5.7.21/src/assets/images/dark/divide_hover.svg000066400000000000000000000022611423020056600246470ustar00rootroot00000000000000 ÷_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/divide_normal.svg000077500000000000000000000021211423020056600250120ustar00rootroot00000000000000 ÷_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/divide_press.svg000077500000000000000000000021471423020056600246660ustar00rootroot00000000000000 ÷_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/empty_hover.svg000066400000000000000000000023171423020056600245430ustar00rootroot00000000000000 empty_hover deepin-calculator-5.7.21/src/assets/images/dark/empty_normal.svg000066400000000000000000000021311423020056600247020ustar00rootroot00000000000000 empty_normal deepin-calculator-5.7.21/src/assets/images/dark/empty_press.svg000066400000000000000000000024041423020056600245510ustar00rootroot00000000000000 empty_press deepin-calculator-5.7.21/src/assets/images/dark/grad_hover.svg000066400000000000000000000166541423020056600243330ustar00rootroot00000000000000 grad_hover_dark deepin-calculator-5.7.21/src/assets/images/dark/grad_normal.svg000066400000000000000000000157301423020056600244720ustar00rootroot00000000000000 grad_normal_dark deepin-calculator-5.7.21/src/assets/images/dark/grad_press.svg000066400000000000000000000157301423020056600243360ustar00rootroot00000000000000 grad_press_dark deepin-calculator-5.7.21/src/assets/images/dark/icon_as_hover.svg000066400000000000000000000037611423020056600250240ustar00rootroot00000000000000 icon_as_hover deepin-calculator-5.7.21/src/assets/images/dark/icon_as_iconhover.svg000066400000000000000000000040301423020056600256630ustar00rootroot00000000000000 icon_as_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_as_iconnormal.svg000066400000000000000000000037541423020056600260440ustar00rootroot00000000000000 icon_as_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_as_normal.svg000066400000000000000000000037541423020056600251730ustar00rootroot00000000000000 icon_as_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_binarysystem_hover.svg000066400000000000000000000022741423020056600271500ustar00rootroot00000000000000 icon_binarysystem_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_binarysystem_normal.svg000066400000000000000000000021211423020056600273040ustar00rootroot00000000000000 icon_binarysystem_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_binarysystem_press.svg000066400000000000000000000021221423020056600271510ustar00rootroot00000000000000 icon_generalkeyboard_press deepin-calculator-5.7.21/src/assets/images/dark/icon_generalkeyboard_hover.svg000066400000000000000000000021611423020056600275500ustar00rootroot00000000000000 icon_generalkeyboard_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_generalkeyboard_normal.svg000066400000000000000000000021511423020056600277140ustar00rootroot00000000000000 icon_generalkeyboard_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_generalkeyboard_press.svg000066400000000000000000000021441423020056600275620ustar00rootroot00000000000000 icon_generalkeyboard_press deepin-calculator-5.7.21/src/assets/images/dark/icon_history_checked.svg000066400000000000000000000025771423020056600263710ustar00rootroot00000000000000 icon_history_checked deepin-calculator-5.7.21/src/assets/images/dark/icon_history_normal.svg000066400000000000000000000031541423020056600262630ustar00rootroot00000000000000 icon_history_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_ls_hover.svg000066400000000000000000000032471423020056600250360ustar00rootroot00000000000000 icon_ls_hover deepin-calculator-5.7.21/src/assets/images/dark/icon_ls_iconhover.svg000066400000000000000000000034551423020056600257100ustar00rootroot00000000000000 icon_ls_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_ls_iconnormal.svg000066400000000000000000000034551423020056600260550ustar00rootroot00000000000000 icon_ls_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_ls_normal.svg000066400000000000000000000034551423020056600252040ustar00rootroot00000000000000 icon_ls_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_memory_checked.svg000066400000000000000000000043171423020056600261720ustar00rootroot00000000000000 icon_memory_checked deepin-calculator-5.7.21/src/assets/images/dark/icon_memory_normal.svg000066400000000000000000000037651423020056600261020ustar00rootroot00000000000000 icon_memory_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_rc_hover.svg000066400000000000000000000070661423020056600250270ustar00rootroot00000000000000 icon_rc_hover deepin-calculator-5.7.21/src/assets/images/dark/icon_rc_iconhover.svg000066400000000000000000000076051423020056600256770ustar00rootroot00000000000000 icon_rc_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_rc_iconnormal.svg000066400000000000000000000075011423020056600260370ustar00rootroot00000000000000 icon_rc_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_rc_normal.svg000066400000000000000000000075011423020056600251660ustar00rootroot00000000000000 icon_rc_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_ro_hover.svg000066400000000000000000000057011423020056600250350ustar00rootroot00000000000000 icon_ro_hover deepin-calculator-5.7.21/src/assets/images/dark/icon_ro_iconhover.svg000066400000000000000000000061251423020056600257070ustar00rootroot00000000000000 icon_ro_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_ro_iconnormal.svg000066400000000000000000000062411423020056600260530ustar00rootroot00000000000000 icon_ro_normal deepin-calculator-5.7.21/src/assets/images/dark/icon_ro_normal.svg000066400000000000000000000062411423020056600252020ustar00rootroot00000000000000 icon_ro_normal deepin-calculator-5.7.21/src/assets/images/dark/memory_hover.svg000066400000000000000000000050301423020056600247100ustar00rootroot00000000000000 memory_hover deepin-calculator-5.7.21/src/assets/images/dark/memory_normal.svg000066400000000000000000000045451423020056600250670ustar00rootroot00000000000000 memory_normal deepin-calculator-5.7.21/src/assets/images/dark/memory_press.svg000066400000000000000000000050041423020056600247220ustar00rootroot00000000000000 memory_press deepin-calculator-5.7.21/src/assets/images/dark/rad_hover.svg000066400000000000000000000215751423020056600241620ustar00rootroot00000000000000 rad_normal_hover deepin-calculator-5.7.21/src/assets/images/dark/rad_normal.svg000066400000000000000000000200721423020056600243160ustar00rootroot00000000000000 rad_normal deepin-calculator-5.7.21/src/assets/images/dark/rad_press.svg000066400000000000000000000176171423020056600241750ustar00rootroot00000000000000 rad_press deepin-calculator-5.7.21/src/assets/images/dark/sin-1_hover.svg000066400000000000000000000073501423020056600243360ustar00rootroot00000000000000 sin-1_hover deepin-calculator-5.7.21/src/assets/images/dark/sin-1_normal.svg000066400000000000000000000063741423020056600245100ustar00rootroot00000000000000 sin-1_normal deepin-calculator-5.7.21/src/assets/images/dark/sin-1_press.svg000066400000000000000000000063741423020056600243540ustar00rootroot00000000000000 sin-1_press deepin-calculator-5.7.21/src/assets/images/dark/squareroot_hover.svg000066400000000000000000000044261423020056600256140ustar00rootroot00000000000000 square root_hover deepin-calculator-5.7.21/src/assets/images/dark/squareroot_normal.svg000066400000000000000000000042211423020056600257520ustar00rootroot00000000000000 square root_normal deepin-calculator-5.7.21/src/assets/images/dark/squareroot_press.svg000066400000000000000000000042311423020056600256170ustar00rootroot00000000000000 square root_normal deepin-calculator-5.7.21/src/assets/images/dark/tan-1_hover.svg000066400000000000000000000073131423020056600243260ustar00rootroot00000000000000 tan-1_hover deepin-calculator-5.7.21/src/assets/images/dark/tan-1_normal.svg000066400000000000000000000063331423020056600244740ustar00rootroot00000000000000 tan-1_normal deepin-calculator-5.7.21/src/assets/images/dark/tan-1_press.svg000066400000000000000000000063331423020056600243400ustar00rootroot00000000000000 tan-1_press deepin-calculator-5.7.21/src/assets/images/dark/x_hover.svg000066400000000000000000000014401423020056600236500ustar00rootroot00000000000000 *_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/x_normal.svg000077500000000000000000000014141423020056600240210ustar00rootroot00000000000000 *_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/x_press.svg000077500000000000000000000014231423020056600236650ustar00rootroot00000000000000 *_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/dark/yroot_hover.svg000066400000000000000000000043221423020056600245570ustar00rootroot00000000000000 y root_hover deepin-calculator-5.7.21/src/assets/images/dark/yroot_normal.svg000066400000000000000000000042041423020056600247230ustar00rootroot00000000000000 y root_normal deepin-calculator-5.7.21/src/assets/images/dark/yroot_press.svg000066400000000000000000000042141423020056600245700ustar00rootroot00000000000000 y root_normal deepin-calculator-5.7.21/src/assets/images/deepin-calculator.svg000066400000000000000000000065001423020056600246520ustar00rootroot00000000000000 deepin-calculator Created with Sketch. deepin-calculator-5.7.21/src/assets/images/delete_dark_hover.svg000066400000000000000000000022451423020056600247270ustar00rootroot00000000000000 delete_dark_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/delete_dark_normal.svg000066400000000000000000000022471423020056600250760ustar00rootroot00000000000000 delete_dark_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/delete_dark_press.svg000066400000000000000000000022451423020056600247400ustar00rootroot00000000000000 delete_dark_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/delete_light_hover.svg000066400000000000000000000022331423020056600251120ustar00rootroot00000000000000 delete_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/delete_light_normal.svg000066400000000000000000000022351423020056600252610ustar00rootroot00000000000000 delete_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/delete_light_press.svg000066400000000000000000000022331423020056600251230ustar00rootroot00000000000000 delete_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/div_normal.svg000066400000000000000000000011511423020056600234060ustar00rootroot00000000000000 deepin-calculator-5.7.21/src/assets/images/light/000077500000000000000000000000001423020056600216445ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/images/light/%_hover.svg000077500000000000000000000015641423020056600237250ustar00rootroot00000000000000 %_hover Created with Sketch. % deepin-calculator-5.7.21/src/assets/images/light/%_normal.svg000077500000000000000000000015671423020056600240750ustar00rootroot00000000000000 %_normal Created with Sketch. % deepin-calculator-5.7.21/src/assets/images/light/%_press.svg000077500000000000000000000016031423020056600237300ustar00rootroot00000000000000 %_press Created with Sketch. % deepin-calculator-5.7.21/src/assets/images/light/( )_hover.svg000077500000000000000000000015731423020056600240410ustar00rootroot00000000000000 ( )_hover Created with Sketch. ( ) deepin-calculator-5.7.21/src/assets/images/light/( )_normal.svg000077500000000000000000000015761423020056600242110ustar00rootroot00000000000000 ( )_normal Created with Sketch. ( ) deepin-calculator-5.7.21/src/assets/images/light/( )_press.svg000077500000000000000000000016121423020056600240440ustar00rootroot00000000000000 ( )_press Created with Sketch. ( ) deepin-calculator-5.7.21/src/assets/images/light/+_hover.svg000066400000000000000000000014311423020056600237210ustar00rootroot00000000000000 +_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/+_normal.svg000077500000000000000000000012471423020056600240760ustar00rootroot00000000000000 +_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/+_press.svg000077500000000000000000000012621423020056600237370ustar00rootroot00000000000000 +_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/-_hover.svg000066400000000000000000000011511423020056600237220ustar00rootroot00000000000000 -_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/-_normal.svg000077500000000000000000000011471423020056600240770ustar00rootroot00000000000000 -_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/-_press.svg000077500000000000000000000011521423020056600237370ustar00rootroot00000000000000 -_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/clear_hover.svg000066400000000000000000000022421423020056600246560ustar00rootroot00000000000000 clear_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/clear_normal.svg000066400000000000000000000022441423020056600250250ustar00rootroot00000000000000 clear_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/clear_press.svg000066400000000000000000000022641423020056600246730ustar00rootroot00000000000000 clear_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/cos-1_hover.svg000066400000000000000000000106271423020056600245200ustar00rootroot00000000000000 cos-1_hover deepin-calculator-5.7.21/src/assets/images/light/cos-1_normal.svg000066400000000000000000000076001423020056600246620ustar00rootroot00000000000000 cos-1_normal deepin-calculator-5.7.21/src/assets/images/light/cos-1_press.svg000066400000000000000000000076001423020056600245260ustar00rootroot00000000000000 cos-1_press deepin-calculator-5.7.21/src/assets/images/light/cot-1_hover.svg000066400000000000000000000073071423020056600245220ustar00rootroot00000000000000 cot-1_hover deepin-calculator-5.7.21/src/assets/images/light/cot-1_normal.svg000066400000000000000000000063561423020056600246720ustar00rootroot00000000000000 cot-1_normal deepin-calculator-5.7.21/src/assets/images/light/cot-1_press.svg000066400000000000000000000063561423020056600245360ustar00rootroot00000000000000 cot-1_press deepin-calculator-5.7.21/src/assets/images/light/cuberoot_hover.svg000066400000000000000000000057111423020056600254160ustar00rootroot00000000000000 cube root_hover deepin-calculator-5.7.21/src/assets/images/light/cuberoot_normal.svg000066400000000000000000000054501423020056600255630ustar00rootroot00000000000000 cube root_normal deepin-calculator-5.7.21/src/assets/images/light/cuberoot_press.svg000066400000000000000000000054601423020056600254300ustar00rootroot00000000000000 cube root_normal deepin-calculator-5.7.21/src/assets/images/light/deg_hover.svg000066400000000000000000000202731423020056600243330ustar00rootroot00000000000000 deg_hover deepin-calculator-5.7.21/src/assets/images/light/deg_normal.svg000066400000000000000000000174241423020056600245040ustar00rootroot00000000000000 deg_normal deepin-calculator-5.7.21/src/assets/images/light/deg_press.svg000066400000000000000000000174241423020056600243500ustar00rootroot00000000000000 deg_press deepin-calculator-5.7.21/src/assets/images/light/divide_hover.svg000066400000000000000000000022561423020056600250410ustar00rootroot00000000000000 ÷_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/divide_normal.svg000077500000000000000000000021161423020056600252040ustar00rootroot00000000000000 ÷_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/divide_press.svg000077500000000000000000000021441423020056600250510ustar00rootroot00000000000000 ÷_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/empty_hover.svg000066400000000000000000000023201423020056600247230ustar00rootroot00000000000000 empty_hover deepin-calculator-5.7.21/src/assets/images/light/empty_normal.svg000066400000000000000000000021321423020056600250710ustar00rootroot00000000000000 empty_normal deepin-calculator-5.7.21/src/assets/images/light/empty_press.svg000066400000000000000000000024051423020056600247400ustar00rootroot00000000000000 empty_press deepin-calculator-5.7.21/src/assets/images/light/grad_hover.svg000066400000000000000000000166421423020056600245160ustar00rootroot00000000000000 grad_hover deepin-calculator-5.7.21/src/assets/images/light/grad_normal.svg000066400000000000000000000157161423020056600246640ustar00rootroot00000000000000 grad_normal deepin-calculator-5.7.21/src/assets/images/light/grad_press.svg000066400000000000000000000157161423020056600245300ustar00rootroot00000000000000 grad_press deepin-calculator-5.7.21/src/assets/images/light/icon_as_hover.svg000066400000000000000000000040231423020056600252020ustar00rootroot00000000000000 icon_as_normal deepin-calculator-5.7.21/src/assets/images/light/icon_as_iconhover.svg000066400000000000000000000040231423020056600260530ustar00rootroot00000000000000 icon_as_normal deepin-calculator-5.7.21/src/assets/images/light/icon_as_iconnormal.svg000066400000000000000000000037471423020056600262340ustar00rootroot00000000000000 icon_as_normal deepin-calculator-5.7.21/src/assets/images/light/icon_as_menuhover.svg000066400000000000000000000037541423020056600261010ustar00rootroot00000000000000 icon_as_hover deepin-calculator-5.7.21/src/assets/images/light/icon_as_normal.svg000066400000000000000000000037471423020056600253630ustar00rootroot00000000000000 icon_as_normal deepin-calculator-5.7.21/src/assets/images/light/icon_binarysystem_hover.svg000066400000000000000000000022671423020056600273400ustar00rootroot00000000000000 icon_binarysystem_normal deepin-calculator-5.7.21/src/assets/images/light/icon_binarysystem_normal.svg000066400000000000000000000021141423020056600274740ustar00rootroot00000000000000 icon_binarysystem_normal deepin-calculator-5.7.21/src/assets/images/light/icon_binarysystem_press.svg000066400000000000000000000021221423020056600273370ustar00rootroot00000000000000 icon_generalkeyboard_press deepin-calculator-5.7.21/src/assets/images/light/icon_generalkeyboard_hover.svg000066400000000000000000000021541423020056600277400ustar00rootroot00000000000000 icon_generalkeyboard_normal deepin-calculator-5.7.21/src/assets/images/light/icon_generalkeyboard_normal.svg000066400000000000000000000021441423020056600301040ustar00rootroot00000000000000 icon_generalkeyboard_normal deepin-calculator-5.7.21/src/assets/images/light/icon_generalkeyboard_press.svg000066400000000000000000000021441423020056600277500ustar00rootroot00000000000000 icon_generalkeyboard_press deepin-calculator-5.7.21/src/assets/images/light/icon_history_checked.svg000066400000000000000000000025721423020056600265520ustar00rootroot00000000000000 icon_history_checked deepin-calculator-5.7.21/src/assets/images/light/icon_history_normal.svg000066400000000000000000000031471423020056600264530ustar00rootroot00000000000000 icon_history_normal deepin-calculator-5.7.21/src/assets/images/light/icon_ls_hover.svg000066400000000000000000000034501423020056600252200ustar00rootroot00000000000000 icon_ls_normal deepin-calculator-5.7.21/src/assets/images/light/icon_ls_iconhover.svg000066400000000000000000000034501423020056600260710ustar00rootroot00000000000000 icon_ls_normal deepin-calculator-5.7.21/src/assets/images/light/icon_ls_iconnormal.svg000066400000000000000000000034501423020056600262360ustar00rootroot00000000000000 icon_ls_normal deepin-calculator-5.7.21/src/assets/images/light/icon_ls_menuhover.svg000066400000000000000000000032421423020056600261040ustar00rootroot00000000000000 icon_ls_hover deepin-calculator-5.7.21/src/assets/images/light/icon_ls_normal.svg000066400000000000000000000034501423020056600253650ustar00rootroot00000000000000 icon_ls_normal deepin-calculator-5.7.21/src/assets/images/light/icon_memory_checked.svg000066400000000000000000000043121423020056600263530ustar00rootroot00000000000000 icon_memory_checked deepin-calculator-5.7.21/src/assets/images/light/icon_memory_normal.svg000066400000000000000000000037601423020056600262630ustar00rootroot00000000000000 icon_memory_normal deepin-calculator-5.7.21/src/assets/images/light/icon_rc_hover.svg000066400000000000000000000076001423020056600252070ustar00rootroot00000000000000 icon_rc_normal deepin-calculator-5.7.21/src/assets/images/light/icon_rc_iconhover.svg000066400000000000000000000076001423020056600260600ustar00rootroot00000000000000 icon_rc_normal deepin-calculator-5.7.21/src/assets/images/light/icon_rc_iconnormal.svg000066400000000000000000000074741423020056600262360ustar00rootroot00000000000000 icon_rc_normal deepin-calculator-5.7.21/src/assets/images/light/icon_rc_menuhover.svg000066400000000000000000000070611423020056600260750ustar00rootroot00000000000000 icon_rc_hover deepin-calculator-5.7.21/src/assets/images/light/icon_rc_normal.svg000066400000000000000000000074741423020056600253650ustar00rootroot00000000000000 icon_rc_normal deepin-calculator-5.7.21/src/assets/images/light/icon_ro_hover.svg000066400000000000000000000061201423020056600252170ustar00rootroot00000000000000 icon_ro_normal deepin-calculator-5.7.21/src/assets/images/light/icon_ro_iconhover.svg000066400000000000000000000061201423020056600260700ustar00rootroot00000000000000 icon_ro_normal deepin-calculator-5.7.21/src/assets/images/light/icon_ro_iconnormal.svg000066400000000000000000000062341423020056600262430ustar00rootroot00000000000000 icon_ro_normal deepin-calculator-5.7.21/src/assets/images/light/icon_ro_menuhover.svg000066400000000000000000000056741423020056600261210ustar00rootroot00000000000000 icon_ro_hover deepin-calculator-5.7.21/src/assets/images/light/icon_ro_normal.svg000066400000000000000000000062341423020056600253720ustar00rootroot00000000000000 icon_ro_normal deepin-calculator-5.7.21/src/assets/images/light/iconmemory_normal.svg000066400000000000000000000037571423020056600261320ustar00rootroot00000000000000 iconmemory_normal deepin-calculator-5.7.21/src/assets/images/light/memory_hover.svg000066400000000000000000000045351423020056600251070ustar00rootroot00000000000000 memory_hover deepin-calculator-5.7.21/src/assets/images/light/memory_normal.svg000066400000000000000000000045301423020056600252470ustar00rootroot00000000000000 memory_normal deepin-calculator-5.7.21/src/assets/images/light/memory_press.svg000066400000000000000000000045111423020056600251120ustar00rootroot00000000000000 memory_press deepin-calculator-5.7.21/src/assets/images/light/rad_hover.svg000066400000000000000000000216001423020056600243350ustar00rootroot00000000000000 rad_normal_hover deepin-calculator-5.7.21/src/assets/images/light/rad_normal.svg000066400000000000000000000201231423020056600245010ustar00rootroot00000000000000 rad_normal deepin-calculator-5.7.21/src/assets/images/light/rad_press.svg000066400000000000000000000176221423020056600243570ustar00rootroot00000000000000 rad_press deepin-calculator-5.7.21/src/assets/images/light/sin-1_hover.svg000066400000000000000000000073511423020056600245250ustar00rootroot00000000000000 sin-1_hover deepin-calculator-5.7.21/src/assets/images/light/sin-1_normal.svg000066400000000000000000000063771423020056600247010ustar00rootroot00000000000000 sin-1_normal deepin-calculator-5.7.21/src/assets/images/light/sin-1_press.svg000066400000000000000000000063751423020056600245430ustar00rootroot00000000000000 sin-1_press deepin-calculator-5.7.21/src/assets/images/light/squareroot_hover.svg000066400000000000000000000044311423020056600257760ustar00rootroot00000000000000 square root_hover deepin-calculator-5.7.21/src/assets/images/light/squareroot_normal.svg000066400000000000000000000042241423020056600261430ustar00rootroot00000000000000 square root_normal deepin-calculator-5.7.21/src/assets/images/light/squareroot_press.svg000066400000000000000000000042341423020056600260100ustar00rootroot00000000000000 square root_normal deepin-calculator-5.7.21/src/assets/images/light/tan-1_hover.svg000066400000000000000000000073141423020056600245150ustar00rootroot00000000000000 tan-1_hover deepin-calculator-5.7.21/src/assets/images/light/tan-1_normal.svg000066400000000000000000000063341423020056600246630ustar00rootroot00000000000000 tan-1_normal deepin-calculator-5.7.21/src/assets/images/light/tan-1_press.svg000066400000000000000000000063341423020056600245270ustar00rootroot00000000000000 tan-1_press deepin-calculator-5.7.21/src/assets/images/light/x_hover.svg000066400000000000000000000014351423020056600240420ustar00rootroot00000000000000 *_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/x_normal.svg000066400000000000000000000014111423020056600242010ustar00rootroot00000000000000 *_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/x_press.svg000066400000000000000000000014201423020056600240450ustar00rootroot00000000000000 *_press Created with Sketch. deepin-calculator-5.7.21/src/assets/images/light/yroot_hover.svg000066400000000000000000000043251423020056600247500ustar00rootroot00000000000000 y root_hover deepin-calculator-5.7.21/src/assets/images/light/yroot_normal.svg000066400000000000000000000042071423020056600251140ustar00rootroot00000000000000 y root_normal deepin-calculator-5.7.21/src/assets/images/light/yroot_press.svg000066400000000000000000000042171423020056600247610ustar00rootroot00000000000000 y root_normal deepin-calculator-5.7.21/src/assets/images/min_normal.svg000066400000000000000000000003251423020056600234110ustar00rootroot00000000000000 deepin-calculator-5.7.21/src/assets/images/mult_normal.svg000066400000000000000000000005741423020056600236150ustar00rootroot00000000000000 deepin-calculator-5.7.21/src/assets/images/plus_normal.svg000066400000000000000000000004251423020056600236120ustar00rootroot00000000000000 deepin-calculator-5.7.21/src/assets/images/title_icon.svg000066400000000000000000000054601423020056600234140ustar00rootroot00000000000000 deepin-calculator Created with Sketch. deepin-calculator-5.7.21/src/assets/images/÷_hover.svg000066400000000000000000000021431423020056600233320ustar00rootroot00000000000000 ÷_hover Created with Sketch. deepin-calculator-5.7.21/src/assets/images/÷_normal.svg000066400000000000000000000021161423020056600234770ustar00rootroot00000000000000 ÷_normal Created with Sketch. deepin-calculator-5.7.21/src/assets/images/÷_press.svg000066400000000000000000000021441423020056600233440ustar00rootroot00000000000000 ÷_press Created with Sketch. deepin-calculator-5.7.21/src/assets/qss/000077500000000000000000000000001423020056600200765ustar00rootroot00000000000000deepin-calculator-5.7.21/src/assets/qss/dark.qss000066400000000000000000000026661423020056600215610ustar00rootroot00000000000000QListView { background-color: #111111; border: none; } QLineEdit { background-color: transparent; color: #B4B4B4; border: none; } #TextButton { font-size: 18px; font-weight: 300; color: #E0E0E0; background-color: #202020; border: none; margin: 0px; } #TextButton:hover { color: #FFFFFF; font-size: 20px; font-weight: 400; border: 1px solid #2D2D2D; background-color: #2D2D2D; } #TextButton:pressed { font-size: 18px; color: #606060; background-color: #101010; border: none; } #SymbolButton { font-weight: 400; font-size: 22px; color: #2CA7F8; background-color: #202020; border: none; } #SymbolButton:hover { font-weight: 500; font-size: 24px; border: 1px solid #2D2D2D; background-color: #2D2D2D; } #SymbolButton:pressed { font-weight: 400; font-size: 22px; background-color: #101010; border: none; } #EqualButton { font-weight: 400; font-size: 22px; color: #FFFFFF; border: none; background-color: #2CA7F8; } #EqualButton:hover { font-weight: 500; font-size: 24px; background-color: qlineargradient(x1:0 y1:0, x2:0 y2:1, stop:0 #31c9ff, stop:1 #00abff); border: 1px solid #2CA7F8; } #EqualButton:pressed { font-weight: 400; font-size: 22px; color: #A8CFF8; border: none; background-color: qlineargradient(x1:0 y1:0, x2:0 y2:1, stop:0 #2472e8, stop:1 #2ca7fb); } deepin-calculator-5.7.21/src/assets/qss/light.qss000066400000000000000000000027201423020056600217360ustar00rootroot00000000000000QListView { background-color: #FBFBFB; border: none; } QLineEdit { background-color: transparent; color: #303030; border: none; } #TextButton { font-size: 18px; font-weight: 300; color: #545454; background-color: #FFFFFF; border: none; margin: 0px; } #TextButton:hover { color: #000000; font-size: 20px; font-weight: 400; border: 1px solid #A7E0FF; background-color: #FFFFFF; } #TextButton:pressed { font-size: 18px; color: #606060; background-color: #EFEFEF; border: 1px solid #CBCBCB; } #SymbolButton { font-weight: 400; font-size: 22px; color: #2CA7F8; background-color: #FFFFFF; border: none; } #SymbolButton:hover { font-weight: 500; font-size: 24px; border: 1px solid #A7E0FF; background-color: #FFFFFF; } #SymbolButton:pressed { font-weight: 400; font-size: 22px; background-color: #EFEFEF; border: 1px solid #CBCBCB; } #EqualButton { font-weight: 400; font-size: 22px; color: #FFFFFF; border: none; background-color: #2CA7F8; } #EqualButton:hover { font-weight: 500; font-size: 24px; background-color: qlineargradient(x1:0 y1:0, x2:0 y2:1, stop:0 #31c9ff, stop:1 #00abff); border: 1px solid #2CA7F8; } #EqualButton:pressed { font-weight: 400; font-size: 22px; color: #A8CFF8; border: none; background-color: qlineargradient(x1:0 y1:0, x2:0 y2:1, stop:0 #2472e8, stop:1 #2ca7fb); } deepin-calculator-5.7.21/src/control/000077500000000000000000000000001423020056600174465ustar00rootroot00000000000000deepin-calculator-5.7.21/src/control/basickeypad.cpp000066400000000000000000000224511423020056600224350ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "basickeypad.h" #include #include #include #include "dthememanager.h" const int KEYPAD_HEIGHT = 316; //键盘界面高度 const int KEYPAD_SPACING = 3; //键盘按键间距,按钮比ui大2pix,此处小2pix const int LEFT_MARGIN = 12; //键盘左边距 const int RIGHT_MARGIN = 13; //键盘右边距 const int BOTTOM_MARGIN = 11; //键盘下边距 const QSize STANDARD_TEXTBTNSIZE = QSize(78, 58); //标准模式按钮大小,为画边框比ui大2pix const BasicKeypad::KeyDescription BasicKeypad::keyDescriptions[] = { // {"MC", Key_MC, 1, 0, 1, 2}, {"MR", Key_MR, 1, 2, 1, 2}, // {"M+", Key_Mplus, 1, 4, 1, 2}, {"M-", Key_Mminus, 1, 6, 1, 2}, // {"MS", Key_MS, 1, 8, 1, 2}, {"M^", Key_Mlist, 1, 10, 1, 2}, {"C", Key_Clear, 1, 0, 1, 3}, {"%", Key_Percent, 1, 3, 1, 3}, {"", Key_Backspace, 1, 6, 1, 3}, {"", Key_Div, 1, 9, 1, 3}, {"7", Key_7, 2, 0, 1, 3}, {"8", Key_8, 2, 3, 1, 3}, {"9", Key_9, 2, 6, 1, 3}, {"", Key_Mult, 2, 9, 1, 3}, {"4", Key_4, 3, 0, 1, 3}, {"5", Key_5, 3, 3, 1, 3}, {"6", Key_6, 3, 6, 1, 3}, {"", Key_Min, 3, 9, 1, 3}, {"1", Key_1, 4, 0, 1, 3}, {"2", Key_2, 4, 3, 1, 3}, {"3", Key_3, 4, 6, 1, 3}, {"", Key_Plus, 4, 9, 1, 3}, {"0", Key_0, 5, 0, 1, 3}, {".", Key_Point, 5, 3, 1, 3}, {"( )", Key_Brackets, 5, 6, 1, 3}, {"=", Key_Equals, 5, 9, 1, 3} }; /** * @brief 初始化并设置iconbutton */ //static DPushButton *createSpecialKeyButton(BasicKeypad::Buttons key) //{ // IconButton *button = new IconButton; // QString path; // if (DGuiApplicationHelper::instance()->themeType() == 2) // path = QString(":/assets/images/%1/").arg("dark"); // else // path = QString(":/assets/images/%1/").arg("light"); // if (key == BasicKeypad::Key_Div) { // button->setIconUrl(path + "divide_normal.svg", path + "divide_hover.svg", path + "divide_press.svg"); // } else if (key == BasicKeypad::Key_Mult) { // button->setIconUrl(path + "x_normal.svg", path + "x_hover.svg", path + "x_press.svg"); // } else if (key == BasicKeypad::Key_Min) { // button->setIconUrl(path + "-_normal.svg", path + "-_hover.svg", path + "-_press.svg"); // } else if (key == BasicKeypad::Key_Plus) { // button->setIconUrl(path + "+_normal.svg", path + "+_hover.svg", path + "+_press.svg"); // } else if (key == BasicKeypad::Key_Backspace) { // button->setIconUrl(path + "clear_normal.svg", path + "clear_hover.svg", path + "clear_press.svg"); // } // return button; //} BasicKeypad::BasicKeypad(QWidget *parent) : DWidget(parent), m_layout(new QGridLayout(this)), m_mapper(new QSignalMapper(this)) { this->setFixedHeight(KEYPAD_HEIGHT); m_layout->setMargin(0); m_layout->setSpacing(KEYPAD_SPACING); m_layout->setContentsMargins(0, 0, 0, 0); // setFocusPolicy(Qt::StrongFocus); installEventFilter(this); initButtons(); initUI(); connect(m_mapper, SIGNAL(mapped(int)), SIGNAL(buttonPressed(int))); } BasicKeypad::~BasicKeypad() { } /** * @brief 防止鼠标点击拖拽可拖动窗口 */ void BasicKeypad::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } /** * @brief 根据枚举值返回相应button * @param key 按钮名 */ DPushButton *BasicKeypad::button(Buttons key) { return m_keys.value(key).first; } DPushButton *BasicKeypad::button(int key) { return m_keys.value(Buttons(key)).first; } /** * @brief 按钮点击动画效果 */ void BasicKeypad::animate(Buttons key, bool isspace) { if (button(key)->text().isEmpty()) { IconButton *btn = static_cast(button(key)); btn->animate(isspace); } else { if (button(key)->text() == "=") { EqualButton *btn = dynamic_cast(button(key)); btn->animate(isspace); } else { TextButton *btn = static_cast(button(key)); btn->animate(isspace); } } } /** * @brief 焦点是否在该button上 */ bool BasicKeypad::buttonHasFocus() { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { return true; } } return false; } /** * @brief 初始化button */ void BasicKeypad::initButtons() { const int count = sizeof(keyDescriptions) / sizeof(keyDescriptions[0]); for (int i = 0; i < count; ++i) { const KeyDescription *desc = keyDescriptions + i; DPushButton *button; if (desc->text.isEmpty()) { button = new IconButton(this); // button = createSpecialKeyButton(desc->button); // button->setParent(this); } else { if (desc->text == "=") { button = new EqualButton(desc->text, this); connect(static_cast(button), &EqualButton::focus, this, &BasicKeypad::getFocus); //获取上下左右键 connect(static_cast(button), &EqualButton::space, this, [ = ]() { Buttons spacekey = Key_Equals; emit buttonPressedbySpace(spacekey); }); } else { button = new TextButton(desc->text, false, this); } } button->setFixedSize(STANDARD_TEXTBTNSIZE); m_layout->addWidget(button, desc->row, desc->column, desc->rowcount, desc->columncount, Qt::AlignHCenter | Qt::AlignVCenter); const QPair hashValue(button, desc); m_keys.insert(desc->button, hashValue); //key为枚举值,value.first为DPushButton *, value.second为const KeyDescription * if (desc->text != "=") { connect(static_cast(button), &TextButton::focus, this, &BasicKeypad::getFocus); //获取上下左右键 connect(static_cast(button), &TextButton::space, this, [ = ]() { Buttons spacekey = m_keys.key(hashValue); emit buttonPressedbySpace(spacekey); }); } connect(button, &DPushButton::clicked, m_mapper, static_cast(&QSignalMapper::map)); m_mapper->setMapping(button, desc->button); //多个按钮绑定到一个mapper上 } } void BasicKeypad::initUI() { button(Key_Div)->setObjectName("SymbolButton"); button(Key_Mult)->setObjectName("SymbolButton"); button(Key_Min)->setObjectName("SymbolButton"); button(Key_Plus)->setObjectName("SymbolButton"); this->setContentsMargins(LEFT_MARGIN, 0, RIGHT_MARGIN, BOTTOM_MARGIN); } /** * @brief 切换相应主题切图 */ void BasicKeypad::buttonThemeChanged(int type) { QString path; if (type == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); IconButton *btn = static_cast(button(Key_Div)); btn->setIconUrl(path + "divide_normal.svg", path + "divide_hover.svg", path + "divide_press.svg"); btn = static_cast(button(Key_Mult)); btn->setIconUrl(path + "x_normal.svg", path + "x_hover.svg", path + "x_press.svg"); btn = static_cast(button(Key_Min)); btn->setIconUrl(path + "-_normal.svg", path + "-_hover.svg", path + "-_press.svg"); btn = static_cast(button(Key_Plus)); btn->setIconUrl(path + "+_normal.svg", path + "+_hover.svg", path + "+_press.svg"); btn = static_cast(button(Key_Backspace)); btn->setIconUrl(path + "clear_normal.svg", path + "clear_hover.svg", path + "clear_press.svg", 1); } /** * @brief 获取button上下左右键信号setfocus * @param direction 0-上 1-下 2-左 3-右 */ void BasicKeypad::getFocus(int direction) { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { break; //获取焦点按钮 } } switch (direction) { case 0: if (i.key() / 4 > 0) button(static_cast(i.key() - 4))->setFocus(); //根据上下左右信号重置焦点 break; case 1: if (i.key() / 4 < 4) button(static_cast(i.key() + 4))->setFocus(); break; case 2: if (i.key() % 4 > 0) button(static_cast(i.key() - 1))->setFocus(); break; case 3: if (i.key() % 4 < 3) button(static_cast(i.key() + 1))->setFocus(); break; default: break; } } deepin-calculator-5.7.21/src/control/basickeypad.h000066400000000000000000000046201423020056600221000ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BASICKEYPAD_H #define BASICKEYPAD_H #include "textbutton.h" #include "iconbutton.h" #include "memorybutton.h" #include "equalbutton.h" #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE class BasicKeypad : public DWidget { Q_OBJECT public: /** * @brief 标准模式键盘 */ enum Buttons { Key_Clear, Key_Percent, Key_Backspace, Key_Div, //C, %, 退格符, 除号 Key_7, Key_8, Key_9, Key_Mult, //7, 8, 9, 乘号 Key_4, Key_5, Key_6, Key_Min, //4, 5, 6, 减号 Key_1, Key_2, Key_3, Key_Plus, //1, 2, 3, 加号 Key_0, Key_Point, Key_Brackets, Key_Equals //0, ., (), = }; explicit BasicKeypad(QWidget *parent = nullptr); ~BasicKeypad() override; void mouseMoveEvent(QMouseEvent *e) override; DPushButton *button(Buttons key); DPushButton *button(int key); void animate(Buttons key, bool isspace = false); bool buttonHasFocus(); static const struct KeyDescription { QString text; //按钮text Buttons button; //按钮枚举值名 int row; //行 int column; //列 int rowcount; //所占行数 int columncount; //所占列数 } keyDescriptions[]; public slots: void initButtons(); void buttonThemeChanged(int type); void getFocus(int); signals: void buttonPressed(int); void buttonPressedbySpace(int); void equalPressed(); private: void initUI(); private: QGridLayout *m_layout; QSignalMapper *m_mapper; QHash> m_keys; }; #endif deepin-calculator-5.7.21/src/control/bitbutton.cpp000066400000000000000000000111001423020056600221550ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "bitbutton.h" const QSize PROGRAMMER_BITBTNSIZE = QSize(16, 26); BitButton::BitButton(QWidget *parent) : DPushButton(parent) { setText("0"); setFlat(true); setFixedSize(PROGRAMMER_BITBTNSIZE); setFocusPolicy(Qt::TabFocus); init(); } BitButton::~BitButton() { } void BitButton::init() { m_font.setPixelSize(18); m_font.setFamily("Noto Sans"); m_font.setStyleName("Light"); m_font.setWeight(2); } void BitButton::animate(bool isspace, int msec) { if (m_isPress == false) { //edit for bug-20492 20200416 m_isHover = false; //edit for bug-20508 20200414 if (!isspace) setDown(true); m_isPress = true; QTimer::singleShot(msec, this, [ = ] { if (!isspace) setDown(false); m_isPress = false; update(); }); } } /** * @brief BitButton::setButtonState * @param b:false--0 true--1 * 设置按键的状态 0/1 */ void BitButton::setButtonState(bool b) { if (b) setText("1"); else setText("0"); m_btnState = b; } void BitButton::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) return; // setFocus(); m_isPress = true; m_isHover = false; //20200722删除foucus状态 DPushButton::mousePressEvent(e); } void BitButton::mouseReleaseEvent(QMouseEvent *e) { // clearFocus(); if (e->button() == Qt::RightButton) return; if (text() == QString("0")) { setText("1"); m_btnState = true; } else { setText("0"); m_btnState = false; } m_isPress = false; if (this->rect().contains(e->pos())) { m_isHover = true; } DPushButton::mouseReleaseEvent(e); } void BitButton::enterEvent(QEvent *e) { m_isHover = true; DPushButton::enterEvent(e); } void BitButton::leaveEvent(QEvent *e) { m_isHover = false; DPushButton::leaveEvent(e); } void BitButton::paintEvent(QPaintEvent *e) { Q_UNUSED(e); QColor press = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name();//活动色 QColor text, disabletext; QPainter painter(this); QPen pen; QRect focusrect(rect().left(), rect().top(), rect().width() - 1, rect().height() - 1); int type = DGuiApplicationHelper::instance()->themeType(); if (type == 1) { //浅色主题设置 text = QColor("#303030"); disabletext = QColor("#555555"); disabletext.setAlphaF(0.4); } else { text = QColor("#C0C6D4"); disabletext = QColor("#C0C6D4"); disabletext.setAlphaF(0.4); } if (m_isPress || m_btnState) { if (m_isPress) press.setAlphaF(0.7); else press.setAlphaF(1); pen.setColor(press); painter.setPen(pen); } else { if (this->isEnabled()) pen.setColor(text); else pen.setColor(disabletext); painter.setPen(pen); } painter.setFont(m_font); QTextOption opt(Qt::AlignCenter); painter.drawText(this->rect(), this->text(), opt); if (hasFocus()) { painter.setPen(Qt::NoPen); pen.setWidth(1); pen.setColor(press); painter.setPen(pen); painter.setBrush(Qt::NoBrush); painter.drawRect(focusrect); } // DPushButton::paintEvent(e); } void BitButton::focusOutEvent(QFocusEvent *e) { QPushButton::focusOutEvent(e); } void BitButton::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Up: emit focus(0); break; case Qt::Key_Down: emit focus(1); break; case Qt::Key_Left: emit focus(2); break; case Qt::Key_Right: emit focus(3); break; case Qt::Key_Space: emit space(); break; default: DPushButton::keyPressEvent(e); break; } } deepin-calculator-5.7.21/src/control/bitbutton.h000066400000000000000000000035161423020056600216360ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BITBUTTON_H #define BITBUTTON_H #include #include #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE /** * @brief 程序员模式0-1二进制按钮 */ class BitButton : public DPushButton { Q_OBJECT public: explicit BitButton(QWidget *parent = nullptr); ~BitButton() override; void init(); void animate(bool isspace = false, int msec = 100); void setButtonState(bool b); public: void mousePressEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; void enterEvent(QEvent *) override; void leaveEvent(QEvent *) override; void paintEvent(QPaintEvent *e) override; void focusOutEvent(QFocusEvent *) override; void keyPressEvent(QKeyEvent *e) override; signals: void focus(int direction); //direction 0-上 1-下 2-左 3-右 void space(); private: bool m_isHover = false; bool m_isPress = false; bool m_btnState = false; //true-1, false-0 QFont m_font; }; #endif // BITBUTTON_H deepin-calculator-5.7.21/src/control/equalbutton.cpp000066400000000000000000000220451423020056600225200ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "equalbutton.h" #include #include #include #include #include const qreal BLURRADIUS = 4; //阴影模糊半径 const int FONT_PIXELSIZE = 36; //字号 const qreal ROUND_XRADIUS = 8; //按钮圆角x轴半径 const qreal ROUND_YRADIUS = 8; //按钮圆角y轴半径 EqualButton::EqualButton(const QString &text, QWidget *parent) : DSuggestButton(text, parent), m_effect(new QGraphicsDropShadowEffect(this)) { setFocusPolicy(Qt::TabFocus); setObjectName("TextButton"); init(); m_isHover = m_isPress = false; m_effect->setOffset(0, 4); //阴影偏移 m_effect->setBlurRadius(BLURRADIUS); //阴影模糊半径 } EqualButton::~EqualButton() { } /** * @brief 设置字体 */ void EqualButton::init() { m_font.setPixelSize(FONT_PIXELSIZE); m_font.setFamily("Noto Sans"); m_font.setStyleName("Light"); } /** * @brief 动画效果 * @param msec 100ms */ void EqualButton::animate(bool isspace, int msec) { if (m_isPress == false) { //edit for bug-20492 20200416 m_isHover = false; //edit for bug-20508 20200414 if (!isspace) setDown(true); m_isPress = true; QTimer::singleShot(msec, this, [ = ] { if (!isspace) setDown(false); m_isPress = false; update(); }); } } /** * @brief 设置点击下的标置位 */ void EqualButton::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) return; // setFocus(); m_isPress = true; m_isHover = false; //20200722删除foucus状态 DPushButton::mousePressEvent(e); } /** * @brief 设置鼠标松开时的标志位 */ void EqualButton::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) return; this->setPalette(m_palette); m_isPress = false; if (this->rect().contains(e->pos())) { m_isacting = true; m_isHover = true; } else m_isacting = false; DPushButton::mouseReleaseEvent(e); } void EqualButton::enterEvent(QEvent *e) { //m_font.setPixelSize(20); //m_font.setStyleName(""); m_isHover = true; DPushButton::enterEvent(e); } void EqualButton::leaveEvent(QEvent *e) { //m_font.setPixelSize(18); //m_font.setStyleName("Light"); m_isHover = false; m_isacting = false; DPushButton::leaveEvent(e); } void EqualButton::paintEvent(QPaintEvent *e) { Q_UNUSED(e); QRectF rect = this->rect(); QRectF focusBase(rect.left() + 1, rect.top() + 1, rect.width() - 2, rect.height() - 2); QRectF normal(rect.left() + 2, rect.top() + 2, rect.width() - 4, rect.height() - 4); QLinearGradient linearGradient(rect.width() / 2, 0, rect.width() / 2, rect.height()); //线性渐变,起始点坐标rect.width() / 2, 0 QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); //反锯齿 painter.setRenderHint(QPainter::SmoothPixmapTransform, true); //光滑的象素映射变换算法 painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setFont(m_font); QRectF textRect = painter.fontMetrics().boundingRect("="); textRect.moveCenter(rect.center()); QColor actcolor = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name();//活动色 QColor base, text, pressText, hover0, hover1, press0, press1, frame; QColor shadow; base = actcolor; base.setAlphaF(1); text = Qt::white; pressText = QColor(255, 255, 255); pressText.setAlphaF(0.6); press0 = actcolor; press1 = actcolor; hover0 = actcolor; hover1 = actcolor; int type = DGuiApplicationHelper::instance()->themeType(); if (type == 1) { //浅色主题设置 frame = Qt::white; press0.setAlphaF(0.8); press1.setAlphaF(1); hover0.setAlphaF(0.6); hover1.setAlphaF(0.8); } else { //深色主题设置 frame = QColor(0, 0, 0); frame.setAlphaF(0.6); press0.setAlphaF(0.7); press1.setAlphaF(0.5); hover0.setAlphaF(1); hover1.setAlphaF(0.8); } shadow = actcolor; shadow.setAlphaF(0.2); if (hasFocus()) { painter.setPen(Qt::NoPen); if (m_isPress) { linearGradient.setColorAt(0, press0); linearGradient.setColorAt(1, press1); QPen pen; painter.setPen(Qt::NoPen); painter.setBrush(QBrush(base)); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 painter.setPen(Qt::NoPen); painter.setBrush(QBrush(frame)); painter.drawRoundedRect(focusBase, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 painter.setBrush(QBrush(linearGradient)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 pen.setColor(pressText); painter.setPen(pen); painter.setFont(m_font); painter.drawText(textRect, "="); m_effect->setColor(shadow); this->setGraphicsEffect(m_effect); } else { QPen pen; // if (m_isacting) { // painter.setPen(Qt::NoPen); // painter.setBrush(QBrush(base)); // painter.drawRoundedRect(normal, 8, 8); //圆角半径单位为像素 // } else { base.setAlphaF(0.8); painter.setPen(Qt::NoPen); painter.setBrush(QBrush(base)); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 painter.setPen(Qt::NoPen); painter.setBrush(QBrush(frame)); painter.drawRoundedRect(focusBase, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 painter.setPen(Qt::NoPen); painter.setBrush(QBrush(base)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 // } //painter.drawRoundRect(rect,10,10); pen.setColor(text); painter.setPen(pen); painter.setFont(m_font); painter.drawText(textRect, "="); m_effect->setColor(shadow); this->setGraphicsEffect(m_effect); } } else { painter.setPen(Qt::NoPen); if (m_isHover) { //hover的绘制 linearGradient.setColorAt(0, hover0); linearGradient.setColorAt(1, hover1); painter.setBrush(linearGradient); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(text); painter.setPen(pen); painter.setFont(m_font); painter.drawText(textRect, "="); m_effect->setColor(shadow); this->setGraphicsEffect(m_effect); } else if (m_isPress) { //press的绘制 linearGradient.setColorAt(0, press0); linearGradient.setColorAt(1, press1); painter.setBrush(QBrush(linearGradient)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(pressText); painter.setPen(pen); painter.setFont(m_font); painter.drawText(textRect, "="); m_effect->setColor(shadow); this->setGraphicsEffect(m_effect); } else { //normal的绘制 base.setAlphaF(0.8); painter.setBrush(QBrush(base)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(text); painter.setPen(pen); painter.setFont(m_font); painter.drawText(textRect, "="); m_effect->setColor(shadow); this->setGraphicsEffect(m_effect); } } } void EqualButton::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Up: emit focus(0); break; case Qt::Key_Down: emit focus(1); break; case Qt::Key_Left: emit focus(2); break; case Qt::Key_Right: emit focus(3); break; case Qt::Key_Space: emit space(); break; default: DPushButton::keyPressEvent(e); break; } } deepin-calculator-5.7.21/src/control/equalbutton.h000066400000000000000000000035351423020056600221700ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef EQUALBUTTON_H #define EQUALBUTTON_H #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE class EqualButton : public DSuggestButton { Q_OBJECT public: EqualButton(const QString &text = QString(), QWidget *parent = nullptr); ~EqualButton() override; void init(); //void showShadow(); //void hideShadow(); void animate(bool isspace = false, int msec = 100); signals: void focus(int direction); //direction 0-上 1-下 2-左 3-右 void space(); public: void mousePressEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; void enterEvent(QEvent *) override; void leaveEvent(QEvent *) override; void paintEvent(QPaintEvent *e) override; void keyPressEvent(QKeyEvent *e) override; private: QGraphicsDropShadowEffect *m_effect; DPalette m_palette; bool m_isHover; bool m_isPress; QFont m_font; bool m_isacting = false; //规避鼠标在button内release时出现foucus状态的框 }; #endif // EQUALBUTTON_H deepin-calculator-5.7.21/src/control/iconbutton.cpp000066400000000000000000000407541423020056600223500ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "iconbutton.h" #include #include #include #include const QSize HISTORY_WIDGET_CLEARBUTTONSIZE = QSize(36, 36); //历史记录区垃圾桶大小 const qreal BLURRADIUS = 12; //阴影模糊半径 const qreal ROUND_XRADIUS = 8; //按钮圆角x轴半径 const qreal ROUND_YRADIUS = 8; //按钮圆角y轴半径 IconButton::IconButton(QWidget *parent, int b, bool page) : TextButton("", parent) , m_effect(new QGraphicsDropShadowEffect(this)) , m_iconRenderer(new QSvgRenderer(this)) { if (b == 1) setFixedSize(HISTORY_WIDGET_CLEARBUTTONSIZE); m_isHover = false; m_isPress = false; m_isEmptyBtn = (b == 1); m_page = page; m_effect->setOffset(0, 4); //阴影偏移 m_effect->setBlurRadius(BLURRADIUS); //阴影模糊半径 } IconButton::~IconButton() { } /** * @brief 设置图片路径 * @param normalFileName normal图片路径 * @param hoverFileName hover图片路径 * @param pressFileName press图片路径 * @param mode 区分不同XML元素标签名 */ void IconButton::setIconUrl(const QString &normalFileName, const QString &hoverFileName, const QString &pressFileName, int mode) { m_normalUrl = normalFileName; m_hoverUrl = hoverFileName; m_pressUrl = pressFileName; m_currentUrl = m_normalUrl; m_buttonStatus = 0; //0-normal 1-hover 2-press //setIcon(QIcon(m_pixmap)); //setIconSize(QSize(30,30)*devicePixelRatioF()); m_mode = mode; } QStringList IconButton::getIconUrl() const { QStringList list; list << m_normalUrl.right(m_normalUrl.length() - m_normalUrl.indexOf("icon")) << m_hoverUrl.right(m_hoverUrl.length() - m_hoverUrl.indexOf("icon")) << m_pressUrl.right(m_pressUrl.length() - m_pressUrl.indexOf("icon")); return list; } /** * @brief iconbutton物理键盘点击动画效果 * @param msec 100ms */ void IconButton::animate(bool isspace, int msec) { if (m_isPress == false) { //edit for bug-20492 20200416 m_isHover = false; //edit for bug-20508 20200414 if (!isspace) setDown(true); m_isPress = true; m_currentUrl = m_pressUrl; m_buttonStatus = 2; if ((m_mode & 1) == 1) ++m_mode; QTimer::singleShot(msec, this, [ = ] { if (!isspace) setDown(false); m_currentUrl = m_normalUrl; m_buttonStatus = 0; if ((m_mode & 1) != 1) --m_mode; m_isPress = false; update(); }); } } /** * @brief 设置垃圾桶tooltip * @param ismemory true-内存垃圾桶 false-历史记录垃圾桶 */ void IconButton::showtooltip(bool ismemory) { if (ismemory == true) { m_cleartooltip = tr("Clear all memory"); this->setToolTip(m_cleartooltip); } else { m_cleartooltip = tr("Clear history"); this->setToolTip(m_cleartooltip); } } /** * @brief IconButton::updateWhenBtnDisable * 当拥有焦点时同时按下空格和鼠标后会导致问题,将其置回普通状态 */ void IconButton::updateWhenBtnDisable() { m_isPress = false; m_buttonStatus = 0; m_mode = 1; update(); } /** * @brief IconButton::setBtnPressing * 用于数据长度和移位类型的按键,点开列表后,保持press的状态 */ void IconButton::setBtnPressing(bool press) { if (press) { m_currentUrl = m_pressUrl; if ((m_mode & 1) == 1) ++m_mode; m_isPress = true; m_buttonStatus = 2; m_isHover = false; //20200722删除foucus状态 m_isPressing = true; } else { m_currentUrl = m_normalUrl; if ((m_mode & 1) != 1) --m_mode; m_isPress = false; m_buttonStatus = 0; m_isPressing = false; } } /** * @brief IconButton::setBtnHighlight * @param light:是否高亮 * 设置全键盘/位键盘切换按钮高亮显示 */ void IconButton::setBtnHighlight(bool light) { m_highlight = light; } /** * @brief 点击时改变标置位 */ void IconButton::mousePressEvent(QMouseEvent *e) { m_currentUrl = m_pressUrl; m_buttonStatus = 2; if ((m_mode & 1) == 1) ++m_mode; m_isPress = true; m_isHover = false; //20200722删除foucus状态 //pixmap.setDevicePixelRatio(devicePixelRatioF()); //DPushButton::setIcon(QIcon(pixmap)); TextButton::mousePressEvent(e); } /** * @brief 鼠标松开时改变标志位 */ void IconButton::mouseReleaseEvent(QMouseEvent *e) { // if (m_isHistorybtn) // clearFocus(); m_currentUrl = m_normalUrl; if ((m_mode & 1) != 1) --m_mode; if (m_isPress == true && this->rect().contains(e->pos())) { m_currentUrl = m_hoverUrl; m_buttonStatus = 1; emit isclicked(); } else { m_buttonStatus = 0; } m_isPress = false; if (this->rect().contains(e->pos())) { m_isacting = true; m_isHover = true; } else m_isacting = false; TextButton::mouseReleaseEvent(e); } void IconButton::enterEvent(QEvent *e) { m_currentUrl = m_hoverUrl; m_buttonStatus = 1; m_isHover = true; //pixmap.setDevicePixelRatio(devicePixelRatioF()); //DPushButton::setIcon(QIcon(pixmap)); TextButton::enterEvent(e); } void IconButton::leaveEvent(QEvent *e) { if (!m_isPressing) { m_currentUrl = m_normalUrl; m_buttonStatus = 0; m_isHover = false; m_isacting = false; } //pixmap.setDevicePixelRatio(devicePixelRatioF()); //DPushButton::setIcon(QIcon(pixmap)); TextButton::leaveEvent(e); } void IconButton::paintEvent(QPaintEvent *) { QPixmap pixmap(m_currentUrl); m_pixmap = pixmap; //保存以取图片rect,move到该按钮中间 QPainter painter(this); if (m_isEmptyBtn == false) { QRectF frameRect = this->rect(); QRectF rect(frameRect.left() + 1, frameRect.top() + 1, frameRect.width() - 2, frameRect.height() - 2); QRectF hover(frameRect.left() + 1, frameRect.top() + 1, frameRect.width() - 2, frameRect.height() - 2); // if (m_isHistorybtn) // rect = hover = frameRect; painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHint(QPainter::SmoothPixmapTransform, true); //m_pixmap = m_pixmap.scaled(m_pixmap.size() * devicePixelRatioF()); QColor actcolor = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name();//活动色 QColor pressBrush, focus, hoverFrame, base, hoverbrush; QColor hoverShadow, focusShadow; hoverShadow = actcolor; hoverShadow.setAlphaF(0.1); focusShadow = QColor(0, 0, 0); focusShadow.setAlphaF(0.05); int type = DGuiApplicationHelper::instance()->themeType(); if (type == 1) { //浅色主题设置 pressBrush = QColor(0, 0, 0); pressBrush.setAlphaF(0.1); focus = actcolor; hoverFrame = actcolor; hoverFrame.setAlphaF(0.2); if (m_page) { base = QColor(240, 240, 240); hoverbrush = QColor(240, 240, 240); } else { base = Qt::white; hoverbrush = Qt::white; } } else { //深色主题设置 pressBrush = QColor(0, 0, 0); pressBrush.setAlphaF(0.5); focus = actcolor; hoverFrame = actcolor; hoverFrame.setAlphaF(0.2); if (m_page) { base = QColor(60, 60, 60); hoverbrush = QColor(60, 60, 60); } else { base = QColor("#303030"); hoverbrush = QColor(60, 60, 60); } } if (hasFocus()) { if (m_isPress) { painter.setBrush(QBrush(pressBrush)); QPen pen; pen.setColor(pressBrush); painter.setPen(pen); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 pen.setColor(focus); pen.setWidth(2); painter.setPen(pen); painter.setBrush(Qt::NoBrush); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //focus边框 } else { painter.setPen(Qt::NoPen); painter.setBrush(QBrush(base)); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; // if (m_isacting) { // painter.setPen(Qt::NoPen); // } else { pen.setColor(focus); pen.setWidth(2); painter.setPen(pen); // } painter.setBrush(Qt::NoBrush); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 m_effect->setColor(focusShadow); this->setGraphicsEffect(m_effect); } } else { if (m_isHover) { //hover状态设置 QPen pen; pen.setColor(hoverFrame); pen.setWidth(1); painter.setPen(pen); painter.setBrush(QBrush(hoverbrush)); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 m_effect->setColor(hoverShadow); this->setGraphicsEffect(m_effect); } else if (m_isPress) { //press状态设置 painter.setPen(Qt::NoPen); painter.setBrush(QBrush(pressBrush)); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 } else { //normal状态设置 painter.setPen(Qt::NoPen); painter.setBrush(QBrush(base)); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 m_effect->setColor(QColor(0, 0, 0, 0)); this->setGraphicsEffect(m_effect); } } } else { QRectF frameRect = this->rect(); QRectF rect(frameRect.left() + 1, frameRect.top() + 1, frameRect.width() - 2, frameRect.height() - 2); painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHint(QPainter::SmoothPixmapTransform, true); QColor actcolor = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name();//活动色 QColor focus; focus = actcolor; if (hasFocus()) { QPen pen; pen.setColor(focus); pen.setWidth(2); painter.setPen(pen); painter.setBrush(Qt::NoBrush); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //focus边框 } else { painter.setPen(Qt::NoPen); painter.setBrush(Qt::NoBrush); painter.drawRoundedRect(rect, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 } } drawCenterPixMap(painter); } void IconButton::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Up: emit focus(0); break; case Qt::Key_Down: emit focus(1); break; case Qt::Key_Left: emit focus(2); break; case Qt::Key_Right: emit focus(3); break; case Qt::Key_Space: emit space(); break; case Qt::Key_Enter: case Qt::Key_Return: if (m_isEmptyBtn) emit space(); break; default: DPushButton::keyPressEvent(e); break; } } /** * @brief SetAttrRecur * @param elem * @param strtagname XML元素标签名 * @param strattr setAttribute(name) * @param strattrval setAttribute(value) * 修改加载的svg图片的颜色 */ void IconButton::SetAttrRecur(QDomElement elem, QString strtagname, QString strattr, QString strattrval) { if ((m_mode != 1 && m_mode != 3 && m_mode != 5 && m_mode != 7) || m_highlight) { if (elem.tagName().compare(strtagname) == 0 && elem.attribute(strattr) != "none" && elem.attribute(strattr) != "") { elem.setAttribute(strattr, strattrval); if (m_buttonStatus == 0) elem.setAttribute("fill-opacity", QLatin1String("0.75")); //在svg文件中添加透明度 if (m_buttonStatus == 1) elem.setAttribute("fill-opacity", QLatin1String("0.65")); if (m_buttonStatus == 2) elem.setAttribute("fill-opacity", 1); } if (m_mode == 0) { elem.setAttribute(strattr, strattrval); if (m_buttonStatus == 0) elem.setAttribute("fill-opacity", QLatin1String("0.75")); if (m_buttonStatus == 1) elem.setAttribute("fill-opacity", QLatin1String("0.65")); if (m_buttonStatus == 2) elem.setAttribute("fill-opacity", 1); } if (m_isEmptyBtn == true || (m_mode == 4)) { strtagname = "path"; if (elem.tagName().compare(strtagname) == 0 && elem.attribute(strattr) != "none" && elem.attribute(strattr) != "") { if (m_buttonStatus == 2) { elem.setAttribute(strattr, strattrval); } } } if (m_mode == 6) { if (elem.tagName().compare(strtagname) == 0 && elem.attribute(strattr) != "none" && elem.attribute(strattr) != "") { elem.setAttribute(strattr, strattrval); } } if (m_mode == 8) { strattr = "fill"; if (elem.attribute(strattr) != "none" && elem.attribute(strattr) != "") { elem.setAttribute(strattr, strattrval); } strattr = "stroke"; if (elem.attribute(strattr) != "none" && elem.attribute(strattr) != "") { elem.setAttribute(strattr, strattrval); } } if (m_highlight) { strtagname = "path"; if (elem.tagName().compare(strtagname) == 0 && elem.attribute(strattr) != "none" && elem.attribute(strattr) != "") { elem.setAttribute(strattr, strattrval); } } for (int i = 0; i < elem.childNodes().count(); i++) { if (!elem.childNodes().at(i).isElement()) { continue; } SetAttrRecur(elem.childNodes().at(i).toElement(), strtagname, strattr, strattrval); } } } /** * @brief 更改iconbutton图片为活动色,且将图片移至iconbutton中间 */ void IconButton::drawCenterPixMap(QPainter &painter) { painter.save(); QFile file(m_currentUrl); file.open(QIODevice::ReadOnly); QByteArray baData = file.readAll(); QDomDocument doc; doc.setContent(baData); file.close(); //将svg文件中的fill颜色设置改为当前活动色 SetAttrRecur(doc.documentElement(), "g", "fill", Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name()); QRectF frameRect = this->rect(); QRectF rect(frameRect.left(), frameRect.top(), frameRect.width(), frameRect.height()); QRectF pixRect = m_pixmap.rect(); pixRect.moveCenter(rect.center()); //将图片移至button中间 // m_iconRenderer = new DSvgRenderer(doc.toByteArray(), this); m_iconRenderer->load(doc.toByteArray()); m_iconRenderer->render(&painter, pixRect); painter.restore(); } /*void IconButton::setIconSize(const int &size) { const int scaledSize = size * devicePixelRatioF(); const QSize iconSize(scaledSize, scaledSize); const QImage image = m_iconRenderer->toImage(iconSize); QPixmap pix; pix.convertFromImage(image); pix.setDevicePixelRatio(devicePixelRatioF()); //m_iconWidget->setAlignment(Qt::AlignCenter); //m_iconWidget->setPixmap(pix); this->DPushButton::setIcon(QIcon(pix)); //m_iconWidget->setFixedSize(iconSize); }*/ deepin-calculator-5.7.21/src/control/iconbutton.h000066400000000000000000000063301423020056600220050ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ICONBUTTON_H #define ICONBUTTON_H #include "textbutton.h" #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE class IconButton : public TextButton { Q_OBJECT public: /** * @brief IconButton * @param parent * @param b 1-垃圾桶 2-科学计算器titlebar历史区按钮 * @param page 科学模式第二页的IconButton */ IconButton(QWidget *parent = nullptr, int b = 0, bool page = false); ~IconButton() override; void setIconUrl(const QString &normalFileName, const QString &hoverFileName, const QString &pressFileName, int mode = 0); QStringList getIconUrl() const; void animate(bool isspace = false, int msec = 100); void showtooltip(bool ismemory); //ismemory-true-内存区垃圾桶 false-历史区垃圾桶 void updateWhenBtnDisable(); void setBtnPressing(bool press); void setBtnHighlight(bool light); protected: void mousePressEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; void enterEvent(QEvent *) override; void leaveEvent(QEvent *) override; void paintEvent(QPaintEvent *) override; void keyPressEvent(QKeyEvent *e) override; private: //void setIconSize(const int &size); // DLabel *m_iconWidget; QGraphicsDropShadowEffect *m_effect; // DSvgRenderer *m_iconRenderer; QSvgRenderer *m_iconRenderer; //改用QSvgRenderer bool m_isHover; bool m_isPress; QPixmap m_pixmap; QString m_normalUrl = QString(); QString m_hoverUrl; QString m_pressUrl; int m_mode = 0; //0-四则运算符 1-退格符 2-退格符press 3-根号 4-根号press 5-deg 6-degpress QString m_currentUrl; int m_buttonStatus = 0; //0-normal 1-hover 2-press bool m_isEmptyBtn; //内存中的清空按钮 // int m_themetype; bool m_page; bool m_isHistorybtn = false; //打开历史记录的按钮,暂时保存 QString m_cleartooltip = QString(); bool m_isacting = false; //规避鼠标在button内release时出现foucus状态的框 bool m_isPressing = false; //对于两个rectangle的特殊按钮,点击后需要持续显示press状态 bool m_highlight = false; //用于设置程序员模式下全键盘/位键盘切换持续高亮 private: void SetAttrRecur(QDomElement elem, QString strtagname, QString strattr, QString strattrval); void drawCenterPixMap(QPainter &painter); signals: void isclicked(); }; #endif deepin-calculator-5.7.21/src/control/memhiskeypad.cpp000066400000000000000000000116121423020056600226330ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memhiskeypad.h" const MemHisKeypad::KeyDescription MemHisKeypad::keyDescriptions[] = { {"F-E", Key_FE, 1, 0, 1, 1}, {"MC", Key_MC, 1, 1, 1, 1}, {"MR", Key_MR, 1, 2, 1, 1}, {"M+", Key_Mplus, 1, 3, 1, 1}, {"M-", Key_Mmin, 1, 4, 1, 1}, {"MS", Key_MS, 1, 5, 1, 1}, {"MH˅", Key_MHlist, 1, 6, 1, 1}, }; MemHisKeypad::MemHisKeypad(QWidget *parent) : DWidget(parent), m_layout(new QGridLayout(this)), m_mapper(new QSignalMapper(this)) { this->setFixedHeight(41); m_layout->setMargin(0); m_layout->setSpacing(3); //按钮比ui大2pix,此处比ui小2pix m_layout->setContentsMargins(0, 0, 0, 0); initButtons(); this->setContentsMargins(12, 0, 13, 0); connect(m_mapper, SIGNAL(mapped(int)), SIGNAL(buttonPressed(int))); } MemHisKeypad::~MemHisKeypad() { } void MemHisKeypad::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } /** * @brief 根据枚举值返回相应button * @param key 按钮名 */ DPushButton *MemHisKeypad::button(Buttons key) { return m_keys.value(key).first; } /** * @brief 按钮点击动画效果 */ void MemHisKeypad::animate(Buttons key, bool isspace) { MemoryButton *btn = static_cast(button(key)); btn->animate(isspace); } bool MemHisKeypad::buttonHasFocus() { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { return true; } } return false; } /** * @brief 初始化button */ void MemHisKeypad::initButtons() { const int count = sizeof(keyDescriptions) / sizeof(keyDescriptions[0]); for (int i = 0; i < count; ++i) { const KeyDescription *desc = keyDescriptions + i; DPushButton *button; if (desc->text == "F-E") button = new TextButton(desc->text, false, this); else button = new MemoryButton(desc->text, false, this); QFont font = button->font(); font.setFamily("Noto Sans"); button->setFont(font); if (desc->text == "MH˅") button->setFixedSize(69, 38); else button->setFixedSize(57, 38); m_layout->addWidget(button, desc->row, desc->column, desc->rowcount, desc->columncount, Qt::AlignTop); const QPair hashValue(button, desc); m_keys.insert(desc->button, hashValue); //key为枚举值,value.first为DPushButton *, value.second为const KeyDescription * connect(static_cast(button), &TextButton::focus, this, &MemHisKeypad::getFocus); //获取上下左右键 connect(button, &DPushButton::clicked, m_mapper, static_cast(&QSignalMapper::map)); connect(static_cast(button), &TextButton::space, this, [ = ]() { Buttons spacekey = m_keys.key(hashValue); emit buttonPressedbySpace(spacekey); }); m_mapper->setMapping(button, desc->button); //多个按钮绑定到一个mapper上 } } /** * @brief 获取button上下左右键信号setfocus * @param direction 0-上 1-下 2-左 3-右 */ void MemHisKeypad::getFocus(int direction) { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { break; //获取焦点按钮 } } switch (direction) { case 2: if ((i.key() - 52) % 7 > 0) { int enablekey = i.key() - 1; while (!button(static_cast(enablekey))->isEnabled() && enablekey > 52) { enablekey -= 1; } button(static_cast(enablekey))->setFocus(); } break; case 3: if ((i.key() - 52) % 7 < 6) { int enablekey = i.key() + 1; while (!button(static_cast(enablekey))->isEnabled() && enablekey < 58) { enablekey += 1; } button(static_cast(enablekey))->setFocus(); } break; default: break; } } deepin-calculator-5.7.21/src/control/memhiskeypad.h000066400000000000000000000042771423020056600223110ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MEMHISKEYPAD_H #define MEMHISKEYPAD_H #include "textbutton.h" #include "iconbutton.h" #include "memorybutton.h" #include "equalbutton.h" #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE /** * @brief 简易计算器内存按键栏 */ class MemHisKeypad : public DWidget { Q_OBJECT public: /** * @brief 内存按键栏 */ enum Buttons {Key_FE = 52, Key_MC, Key_MR, Key_Mplus, Key_Mmin, Key_MS, Key_MHlist}; //FE, MC, MR, M+, M-, MS, MH^ explicit MemHisKeypad(QWidget *parent = nullptr); ~MemHisKeypad() override; void mouseMoveEvent(QMouseEvent *e) override; DPushButton *button(Buttons key); void animate(Buttons key, bool isspace = false); bool buttonHasFocus(); static const struct KeyDescription { QString text; //按钮text Buttons button; //按钮枚举值名 int row; //行 int column; //列 int rowcount; //所占行数 int columncount; //所占列数 } keyDescriptions[]; public slots: void initButtons(); void getFocus(int); signals: void buttonPressed(int); void buttonPressedbySpace(int); void equalPressed(); private: QGridLayout *m_layout; QSignalMapper *m_mapper; QHash> m_keys; }; #endif // MEMHISKEYPAD_H deepin-calculator-5.7.21/src/control/memorybutton.cpp000066400000000000000000000472161423020056600227300ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memorybutton.h" #include #include #include #include #include "dthememanager.h" const qreal BLURRADIUS = 12; //阴影模糊半径 const qreal ROUND_XRADIUS = 8; //按钮圆角x轴半径 const qreal ROUND_YRADIUS = 8; //按钮圆角y轴半径 MemoryButton::MemoryButton(const QString &text, bool listwidgetbtn, QWidget *parent) : TextButton(text, parent) , m_effect(new QGraphicsDropShadowEffect(this)) , m_isallgray(false) { m_settings = DSettingsAlt::instance(); setObjectName("MemoryButton"); m_widgetbtn = listwidgetbtn; //是否是内存列表按键 init(); m_isHover = m_isPress = false; showtips(); m_effect->setOffset(0, 4); //阴影偏移 m_effect->setBlurRadius(BLURRADIUS); //阴影模糊半径 } MemoryButton::~MemoryButton() { // delete m_effect; } void MemoryButton::init() { m_font.setPixelSize(16); m_font.setFamily("Noto Sans"); m_font.setStyleName("Light"); if (!m_widgetbtn) { m_isgray = true; //初始化时按键均不可用 this->setEnabled(false); } } /** * @brief 物理键盘按下动画效果 * @param msec 100ms */ void MemoryButton::animate(bool isspace, int msec) { if (m_isPress == false) { //edit for bug-20492 20200416 m_isHover = false; //edit for bug-20508 20200414 if (!isspace) setDown(true); m_isPress = true; QTimer::singleShot(msec, this, [ = ] { if (!isspace) setDown(false); m_isPress = false; update(); }); } } /** * @brief 切换M˅, */ void MemoryButton::setbtnlight(bool light) { int mode = m_settings->getOption("mode").toInt(); if (mode != 1) { if (light == true) setText("M˄"); else setText("M˅"); } else { if (light == true) setText("MH˄"); else setText("MH˅"); } } /** * @brief 设置tooltip */ void MemoryButton::showtips() { QString tooltext; if (this->text() == "MC") { if (m_widgetbtn) tooltext = tr("Clear memory item"); else tooltext = tr("Clear all memory"); } else if (this->text() == "MR") tooltext = tr("Memory recall"); else if (this->text() == "M+") { if (m_widgetbtn) tooltext = tr("Add to memory item"); else tooltext = tr("Memory add"); } else if (this->text() == "M-") { if (m_widgetbtn) tooltext = tr("Subtract from memory item"); else tooltext = tr("Memory subtract"); } else if (this->text() == "MS") tooltext = tr("Memory store"); else tooltext = tr("Memory"); this->setToolTip(tooltext); } /** * @brief MemoryButton::setbuttongray * @param memorywidgetshow 历史区域是否显示 * 历史区域显示,除mlist外按钮置灰 */ void MemoryButton:: setbuttongray(bool memorywidgetshow) { //20200701 精简代码 m_isallgray = memorywidgetshow; update(); } /** * @brief IconButton::updateWhenBtnDisable * 当拥有焦点时同时按下空格和鼠标后会导致问题,将其置回普通状态 */ void MemoryButton::updateWhenBtnDisable() { this->setPalette(m_palette); m_isPress = false; } /** * @brief 鼠标按下 */ void MemoryButton::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) return; // setFocus(); m_palette = this->palette(); m_isPress = true; m_isHover = false; //20200722删除foucus状态 DPushButton::mousePressEvent(e); } /** * @brief 鼠标松开 */ void MemoryButton::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) return; this->setPalette(m_palette); m_isPress = false; if (this->rect().contains(e->pos())) { m_isacting = true; m_isHover = true; } else m_isacting = false; DPushButton::mouseReleaseEvent(e); } void MemoryButton::enterEvent(QEvent *e) { m_font.setPixelSize(17); m_font.setStyleName(""); m_isHover = true; DPushButton::enterEvent(e); } void MemoryButton::leaveEvent(QEvent *e) { m_font.setPixelSize(16); m_font.setStyleName("Light"); m_isHover = false; m_isacting = false; DPushButton::leaveEvent(e); } void MemoryButton::paintEvent(QPaintEvent *e) { Q_UNUSED(e); if (isEnabled() == false) { m_font.setPixelSize(16); m_font.setStyleName("Light"); m_isHover = false; m_isgray = true; } else { m_isgray = false; } QRectF rect = this->rect(); QRectF normal(rect.left() + 1, rect.top() + 1, rect.width() - 2, rect.height() - 2); QRectF hover(rect.left() + 1, rect.top() + 1, rect.width() - 2, rect.height() - 2); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); //反锯齿 painter.setRenderHint(QPainter::SmoothPixmapTransform, true); //光滑的象素映射变换算法 painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setFont(m_font); QRectF textRect = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, this->text()); QColor actcolor = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name();//活动色 QColor pressBrush, focus, hoverFrame, base, text, hoverbrush; QColor pressText = actcolor; QColor hoverShadow, focusShadow; hoverShadow = actcolor; hoverShadow.setAlphaF(0.1); focusShadow = QColor(0, 0, 0); focusShadow.setAlphaF(0.05); int type = DGuiApplicationHelper::instance()->themeType(); if (type == 1) { pressBrush = QColor(0, 0, 0); pressBrush.setAlphaF(0.1); focus = actcolor; hoverFrame = actcolor; hoverFrame.setAlphaF(0.2); base = Qt::white; hoverbrush = Qt::white; text = QColor("#303030"); if (m_isgray == true || m_isallgray == true) { base = QColor("#FFFFFF"); hoverbrush = QColor("#FFFFFF"); text = QColor("#303030"); text.setAlphaF(0.4); pressBrush = QColor("#FFFFFF"); } if (this->text() == "M˄" || this->text() == "MH˄") { text = actcolor; } } else { pressBrush = QColor(0, 0, 0); pressBrush.setAlphaF(0.5); focus = actcolor; hoverFrame = actcolor; hoverFrame.setAlphaF(0.2); if (m_widgetbtn == false) base = QColor(48, 48, 48); else base = QColor(65, 65, 65); if (m_isHover) text = Qt::white; else text = QColor(224, 224, 224); hoverbrush = QColor(60, 60, 60); if (m_isgray == true || m_isallgray == true) { base = QColor(48, 48, 48); base.setAlphaF(0.4); text = QColor(224, 224, 224); text.setAlphaF(0.4); pressText = Qt::black; pressBrush = QColor("#FFFFFF"); hoverbrush = QColor(48, 48, 48); hoverbrush.setAlphaF(0.4); if (m_widgetbtn) { //内存界面中的memorybutton在深色模式下底色不同 base = QColor(65, 65, 65); text = QColor(224, 224, 224); text.setAlphaF(0.3); } } if (this->text() == "M˄" || this->text() == "MH˄") { text = actcolor; } } if (hasFocus()) { painter.setPen(Qt::NoPen); if (m_isPress) { painter.setBrush(QBrush(pressBrush)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(pressText); painter.setPen(pen); painter.setFont(m_font); pen.setColor(focus); pen.setWidth(2); painter.setPen(pen); painter.setBrush(Qt::NoBrush); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //focus边框 if (this->text() == "MH˅") { QRectF textRect1 = QRectF(normal.left() + 22, normal.top() + 7, 10, 17); QFont a1; a1.setPixelSize(12); a1.setFamily("Noto Sans"); painter.setFont(a1); painter.drawText(textRect1, "M"); QRectF textRect2 = QRectF(normal.left() + 29, normal.top() + 12, 10, 17); painter.drawLine(textRect2.bottomLeft(), textRect2.topRight()); QRectF textRect3 = QRectF(normal.left() + 37, normal.top() + 14, 9, 17); QFont a3; a3.setPixelSize(12); a3.setFamily("Noto Sans"); painter.setFont(a3); painter.drawText(textRect3, "H"); QRectF textRect4 = QRectF(normal.left() + 45, normal.top() + 5, 9, 17); QFont a4; a4.setPixelSize(20); a4.setFamily("Noto Sans"); painter.setFont(a4); painter.drawText(textRect4, "˅"); } else if (this->text() == "MH˄") { QRectF textRect1 = QRectF(normal.left() + 22, normal.top() + 7, 10, 17); QFont a1; a1.setPixelSize(12); a1.setFamily("Noto Sans"); painter.setFont(a1); painter.drawText(textRect1, "M"); QRectF textRect2 = QRectF(normal.left() + 29, normal.top() + 12, 10, 17); painter.drawLine(textRect2.bottomLeft(), textRect2.topRight()); QRectF textRect3 = QRectF(normal.left() + 37, normal.top() + 14, 9, 17); QFont a3; a3.setPixelSize(12); a3.setFamily("Noto Sans"); painter.setFont(a3); painter.drawText(textRect3, "H"); QRectF textRect4 = QRectF(normal.left() + 45, normal.top() + 5, 9, 17); QFont a4; a4.setPixelSize(20); a4.setFamily("Noto Sans"); painter.setFont(a4); painter.drawText(textRect4, "˄"); } else painter.drawText(textRect, this->text()); } else { painter.setPen(Qt::NoPen); painter.setBrush(QBrush(base)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; // if (m_isacting) { // painter.setPen(Qt::NoPen); // } else { pen.setColor(focus); pen.setWidth(2); painter.setPen(pen); // } painter.setBrush(Qt::NoBrush); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 pen.setColor(text); painter.setPen(pen); painter.setFont(m_font); if (this->text() == "MH˅") { QRectF textRect1 = QRectF(normal.left() + 22, normal.top() + 7, 10, 17); QFont a1; a1.setPixelSize(12); a1.setFamily("Noto Sans"); painter.setFont(a1); painter.drawText(textRect1, "M"); QRectF textRect2 = QRectF(normal.left() + 29, normal.top() + 12, 10, 17); pen.setWidth(1); painter.setPen(pen); painter.drawLine(textRect2.bottomLeft(), textRect2.topRight()); QRectF textRect3 = QRectF(normal.left() + 37, normal.top() + 14, 9, 17); QFont a3; a3.setPixelSize(12); a3.setFamily("Noto Sans"); painter.setFont(a3); painter.drawText(textRect3, "H"); QRectF textRect4 = QRectF(normal.left() + 45, normal.top() + 5, 9, 17); QFont a4; a4.setPixelSize(20); a4.setFamily("Noto Sans"); painter.setFont(a4); painter.drawText(textRect4, "˅"); } else painter.drawText(textRect, this->text()); m_effect->setColor(focusShadow); this->setGraphicsEffect(m_effect); } } else { painter.setPen(Qt::NoPen); if (m_isHover) { //hover状态 painter.setPen(QPen(hoverFrame)); painter.setBrush(QBrush(hoverbrush)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(text); painter.setPen(pen); painter.setFont(m_font); if (this->text() == "MH˅") { QRectF textRect1 = QRectF(normal.left() + 22, normal.top() + 7, 12, 17); QFont a1; a1.setPixelSize(13); a1.setFamily("Noto Sans"); painter.setFont(a1); painter.drawText(textRect1, "M"); QRectF textRect2 = QRectF(normal.left() + 30, normal.top() + 12, 10, 17); painter.drawLine(textRect2.bottomLeft(), textRect2.topRight()); QRectF textRect3 = QRectF(normal.left() + 37, normal.top() + 14, 9, 17); QFont a3; a3.setPixelSize(13); a3.setFamily("Noto Sans"); painter.setFont(a3); painter.drawText(textRect3, "H"); QRectF textRect4 = QRectF(normal.left() + 45, normal.top() + 5, 9, 17); QFont a4; a4.setPixelSize(22); a4.setFamily("Noto Sans"); painter.setFont(a4); painter.drawText(textRect4, "˅"); } else painter.drawText(textRect, this->text()); m_effect->setColor(hoverShadow); this->setGraphicsEffect(m_effect); } else if (m_isPress) { //press状态 painter.setBrush(QBrush(pressBrush)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(pressText); painter.setPen(pen); painter.setFont(m_font); if (this->text() == "MH˅") { QRectF textRect1 = QRectF(normal.left() + 22, normal.top() + 7, 10, 17); QFont a1; a1.setPixelSize(12); a1.setFamily("Noto Sans"); painter.setFont(a1); painter.drawText(textRect1, "M"); QRectF textRect2 = QRectF(normal.left() + 29, normal.top() + 12, 10, 17); painter.drawLine(textRect2.bottomLeft(), textRect2.topRight()); QRectF textRect3 = QRectF(normal.left() + 37, normal.top() + 14, 9, 17); QFont a3; a3.setPixelSize(12); a3.setFamily("Noto Sans"); painter.setFont(a3); painter.drawText(textRect3, "H"); QRectF textRect4 = QRectF(normal.left() + 45, normal.top() + 5, 9, 17); QFont a4; a4.setPixelSize(20); a4.setFamily("Noto Sans"); painter.setFont(a4); painter.drawText(textRect4, "˅"); } else if (this->text() == "MH˄") { QRectF textRect1 = QRectF(normal.left() + 22, normal.top() + 7, 10, 17); QFont a1; a1.setPixelSize(12); a1.setFamily("Noto Sans"); painter.setFont(a1); painter.drawText(textRect1, "M"); QRectF textRect2 = QRectF(normal.left() + 29, normal.top() + 12, 10, 17); painter.drawLine(textRect2.bottomLeft(), textRect2.topRight()); QRectF textRect3 = QRectF(normal.left() + 37, normal.top() + 14, 9, 17); QFont a3; a3.setPixelSize(12); a3.setFamily("Noto Sans"); painter.setFont(a3); painter.drawText(textRect3, "H"); QRectF textRect4 = QRectF(normal.left() + 45, normal.top() + 5, 9, 17); QFont a4; a4.setPixelSize(20); a4.setFamily("Noto Sans"); painter.setFont(a4); painter.drawText(textRect4, "˄"); } else painter.drawText(textRect, this->text()); } else { //normal状态 painter.setBrush(QBrush(base)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(text); painter.setPen(pen); painter.setFont(m_font); if (this->text() == "MH˄") { QRectF textRect1 = QRectF(normal.left() + 22, normal.top() + 7, 10, 17); QFont a1; a1.setPixelSize(12); a1.setFamily("Noto Sans"); painter.setFont(a1); painter.drawText(textRect1, "M"); QRectF textRect2 = QRectF(normal.left() + 29, normal.top() + 12, 10, 17); painter.drawLine(textRect2.bottomLeft(), textRect2.topRight()); QRectF textRect3 = QRectF(normal.left() + 37, normal.top() + 14, 9, 17); QFont a3; a3.setPixelSize(12); a3.setFamily("Noto Sans"); painter.setFont(a3); painter.drawText(textRect3, "H"); QRectF textRect4 = QRectF(normal.left() + 45, normal.top() + 5, 9, 17); QFont a4; a4.setPixelSize(20); a4.setFamily("Noto Sans"); painter.setFont(a4); painter.drawText(textRect4, "˄"); } else if (this->text() == "MH˅") { QRectF textRect1 = QRectF(normal.left() + 22, normal.top() + 7, 10, 17); QFont a1; a1.setPixelSize(12); a1.setFamily("Noto Sans"); painter.setFont(a1); painter.drawText(textRect1, "M"); QRectF textRect2 = QRectF(normal.left() + 29, normal.top() + 12, 10, 17); painter.drawLine(textRect2.bottomLeft(), textRect2.topRight()); QRectF textRect3 = QRectF(normal.left() + 37, normal.top() + 14, 9, 17); QFont a3; a3.setPixelSize(12); a3.setFamily("Noto Sans"); painter.setFont(a3); painter.drawText(textRect3, "H"); QRectF textRect4 = QRectF(normal.left() + 45, normal.top() + 5, 9, 17); QFont a4; a4.setPixelSize(20); a4.setFamily("Noto Sans"); painter.setFont(a4); painter.drawText(textRect4, "˅"); } else painter.drawText(textRect, this->text()); m_effect->setColor(QColor(0, 0, 0, 0)); this->setGraphicsEffect(m_effect); } } } void MemoryButton::focusOutEvent(QFocusEvent *e) { QPushButton::focusOutEvent(e); } deepin-calculator-5.7.21/src/control/memorybutton.h000066400000000000000000000044461423020056600223730ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MEMORYBUTTON_H #define MEMORYBUTTON_H #include "textbutton.h" #include "../dsettings.h" #include #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE /** * @brief 标准模式内存按键 */ class MemoryButton : public TextButton { Q_OBJECT public: MemoryButton(const QString &text = QString(), bool listwidgetbtn = false, QWidget *parent = nullptr); //listwidgetbtn-是否是内存界面中的按钮 ~MemoryButton() override; void init(); // void showShadow(); // void hideShadow(); void animate(bool isspace = false, int msec = 100); void setbtnlight(bool light); void showtips(); public slots: void setbuttongray(bool memorywidgetshow); void updateWhenBtnDisable(); public: void mousePressEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; void enterEvent(QEvent *) override; void leaveEvent(QEvent *) override; void paintEvent(QPaintEvent *e) override; void focusOutEvent(QFocusEvent *) override; private: QGraphicsDropShadowEffect *m_effect; DSettingsAlt *m_settings; DPalette m_palette; bool m_isHover; bool m_isPress; bool m_isgray; //按键不可用置灰 QFont m_font; bool m_widgetbtn; //内存列表按键 bool m_isallgray; //内存区显示置灰 bool m_isacting = false; //规避鼠标在button内release时出现foucus状态的框 }; #endif // MEMORYBUTTON_H deepin-calculator-5.7.21/src/control/memorykeypad.cpp000066400000000000000000000110341423020056600226570ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memorykeypad.h" const QSize MEMORYBUTTON_SIZE = QSize(52, 32); //标准模式大小,为画边框比ui大2pix const MemoryKeypad::KeyDescription MemoryKeypad::keyDescriptions[] = { {"MC", Key_MC, 1, 0, 1, 1}, {"MR", Key_MR, 1, 1, 1, 1}, {"M+", Key_Mplus, 1, 2, 1, 1}, {"M-", Key_Mminus, 1, 3, 1, 1}, {"MS", Key_MS, 1, 4, 1, 1}, {"M˅", Key_Mlist, 1, 5, 1, 1}, }; MemoryKeypad::MemoryKeypad(QWidget *parent) : DWidget(parent), m_layout(new QGridLayout(this)), m_mapper(new QSignalMapper(this)) { this->setFixedHeight(35); m_layout->setMargin(0); m_layout->setSpacing(2); //按钮比ui大2pix,此处比ui小2pix m_layout->setContentsMargins(0, 0, 0, 0); initButtons(); this->setContentsMargins(12, 0, 13, 0); connect(m_mapper, SIGNAL(mapped(int)), SIGNAL(buttonPressed(int))); } MemoryKeypad::~MemoryKeypad() { } void MemoryKeypad::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } /** * @brief 根据枚举值返回相应button * @param key 按钮名 */ DPushButton *MemoryKeypad::button(Buttons key) { return m_keys.value(key).first; } DPushButton *MemoryKeypad::button(int key) { return m_keys.value(Buttons(key)).first; } /** * @brief 按钮点击动画效果 */ void MemoryKeypad::animate(Buttons key, bool isspace) { MemoryButton *btn = static_cast(button(key)); btn->animate(isspace); } /** * @brief 焦点是否在该button上 */ bool MemoryKeypad::buttonHasFocus() { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { return true; } } return false; } /** * @brief 初始化button */ void MemoryKeypad::initButtons() { const int count = sizeof(keyDescriptions) / sizeof(keyDescriptions[0]); for (int i = 0; i < count; ++i) { const KeyDescription *desc = keyDescriptions + i; DPushButton *button; button = new MemoryButton(desc->text, false, this); QFont font = button->font(); font.setFamily("Noto Sans"); button->setFont(font); button->setFixedSize(MEMORYBUTTON_SIZE); m_layout->addWidget(button, desc->row, desc->column, desc->rowcount, desc->columncount, Qt::AlignTop); const QPair hashValue(button, desc); m_keys.insert(desc->button, hashValue); //key为枚举值,value.first为DPushButton *, value.second为const KeyDescription * connect(static_cast(button), &MemoryButton::focus, this, &MemoryKeypad::getFocus); //获取上下左右键 connect(button, &DPushButton::clicked, m_mapper, static_cast(&QSignalMapper::map)); connect(static_cast(button), &MemoryButton::space, this, [ = ]() { Buttons spacekey = m_keys.key(hashValue); emit buttonPressedbySpace(spacekey); }); m_mapper->setMapping(button, desc->button); //多个按钮绑定到一个mapper上 } } /** * @brief 获取button上下左右键信号setfocus * @param direction 0-上 1-下 2-左 3-右 */ void MemoryKeypad::getFocus(int direction) { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { break; //获取焦点按钮 } } switch (direction) { case 2: if ((i.key() - 20) % 6 > 0) button(static_cast(i.key() - 1))->setFocus(); break; case 3: if ((i.key() - 20) % 6 < 5) button(static_cast(i.key() + 1))->setFocus(); break; default: break; } } deepin-calculator-5.7.21/src/control/memorykeypad.h000066400000000000000000000043251423020056600223310ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MEMORYKEYPAD_H #define MEMORYKEYPAD_H #include "textbutton.h" #include "iconbutton.h" #include "memorybutton.h" #include "equalbutton.h" #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE /** * @brief 简易计算器内存按键栏 */ class MemoryKeypad : public DWidget { Q_OBJECT public: /** * @brief 内存按键栏 */ enum Buttons {Key_MC = 20, Key_MR, Key_Mplus, Key_Mminus, Key_MS, Key_Mlist}; //MC, MR, M+, M-, MS, M^ explicit MemoryKeypad(QWidget *parent = nullptr); ~MemoryKeypad() override; void mouseMoveEvent(QMouseEvent *e) override; DPushButton *button(Buttons key); DPushButton *button(int key); void animate(Buttons key, bool isspace = false); bool buttonHasFocus(); static const struct KeyDescription { QString text; //按钮text Buttons button; //按钮枚举值名 int row; //行 int column; //列 int rowcount; //所占行数 int columncount; //所占列数 } keyDescriptions[]; public slots: void initButtons(); void getFocus(int); signals: void buttonPressed(int); void buttonPressedbySpace(int); void equalPressed(); private: QGridLayout *m_layout; QSignalMapper *m_mapper; QHash> m_keys; }; #endif // MEMORYKEYPAD_H deepin-calculator-5.7.21/src/control/procheckbtnkeypad.cpp000066400000000000000000000135641423020056600236630ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "procheckbtnkeypad.h" const QSize BUTTON_SIZE = QSize(69, 42); //程序员模式大小,为画边框比ui大2pix const ProCheckBtnKeypad::KeyDescription ProCheckBtnKeypad::keyDescriptions[] = { {"", Key_GeneralKeypad, 0, 0}, {"", Key_BinaryKeypad, 0, 1}, {"QWORD", Key_System, 0, 2}, {"", Key_Option, 0, 3}, {"MS", Key_MS, 0, 4}, {"M˅", Key_Mlist, 0, 5} }; ProCheckBtnKeypad::ProCheckBtnKeypad(QWidget *parent) : DWidget(parent), m_layout(new QGridLayout(this)), m_mapper(new QSignalMapper(this)) { this->setFixedHeight(45); m_layout->setMargin(0); m_layout->setSpacing(2); //按钮比ui大2pix,此处比ui小2pix m_layout->setContentsMargins(0, 0, 0, 0); initButtons(); this->setContentsMargins(10, 0, 10, 0); connect(m_mapper, SIGNAL(mapped(int)), SIGNAL(buttonPressed(int))); } ProCheckBtnKeypad::~ProCheckBtnKeypad() { } void ProCheckBtnKeypad::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } /** * @brief 根据枚举值返回相应button * @param key 按钮名 */ DPushButton *ProCheckBtnKeypad::button(ProCheckBtnKeypad::Buttons key) { return m_keys.value(key).first; } /** * @brief 按钮点击动画效果 */ void ProCheckBtnKeypad::animate(ProCheckBtnKeypad::Buttons key, bool isspace) { MemoryButton *btn = static_cast(button(key)); btn->animate(isspace); } /** * @brief 焦点是否在该button上 */ bool ProCheckBtnKeypad::buttonHasFocus() { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { return true; } } return false; } /** * @brief 初始化button */ void ProCheckBtnKeypad::initButtons() { const int count = sizeof(keyDescriptions) / sizeof(keyDescriptions[0]); for (int i = 0; i < count; ++i) { const KeyDescription *desc = keyDescriptions + i; DPushButton *button; if (desc->text.isEmpty()) { button = new IconButton(this); } else if (desc->text == "QWORD") { button = new TextButton(desc->text, false, this); } else { button = new MemoryButton(desc->text, false, this); } button->setFixedSize(BUTTON_SIZE); m_layout->addWidget(button, desc->row, desc->column, Qt::AlignTop); const QPair hashValue(button, desc); m_keys.insert(desc->button, hashValue); //key为枚举值,value.first为DPushButton *, value.second为const KeyDescription * connect(static_cast(button), &TextButton::focus, this, &ProCheckBtnKeypad::getFocus); //获取上下左右键 connect(button, &DPushButton::clicked, m_mapper, static_cast(&QSignalMapper::map)); connect(static_cast(button), &TextButton::space, this, [ = ]() { emit buttonPressedbySpace(m_keys.key(hashValue)); }); m_mapper->setMapping(button, desc->button); //多个按钮绑定到一个mapper上 } static_cast(button(Key_GeneralKeypad))->setBtnHighlight(true); } /** * @brief ProCheckBtnKeypad::buttonThemeChanged * @param type:主题类型 * @param index:当前需要高亮的图片 0-Key_GeneralKeypad 1-Key_BinaryKeypad * 切换主题时切换相应的svg图片 */ void ProCheckBtnKeypad::buttonThemeChanged(int type) { QString path; if (type == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); IconButton *btn; btn = static_cast(button(Key_GeneralKeypad)); btn->setIconUrl(path + "icon_generalkeyboard_normal.svg", path + "icon_generalkeyboard_hover.svg", path + "icon_generalkeyboard_press.svg", 3); btn = static_cast(button(Key_BinaryKeypad)); btn->setIconUrl(path + "icon_binarysystem_normal.svg", path + "icon_binarysystem_hover.svg", path + "icon_binarysystem_press.svg", 3); btn = static_cast(button(Key_Option)); if (btn->getIconUrl().at(0) != "icon_as_iconnormal.svg" && btn->getIconUrl().at(0) != QString()) { btn->setIconUrl(path + btn->getIconUrl().at(0), path + btn->getIconUrl().at(1), path + btn->getIconUrl().at(2), 5); } else { btn->setIconUrl(path + "icon_as_iconnormal.svg", path + "icon_as_iconhover.svg", path + "icon_as_iconhover.svg", 5); } } /** * @brief 获取button上下左右键信号setfocus * @param direction 0-上 1-下 2-左 3-右 */ void ProCheckBtnKeypad::getFocus(int direction) { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { break; //获取焦点按钮 } } switch (direction) { case 2: if (i.key() % 6 > 0) button(static_cast(i.key() - 1))->setFocus(); break; case 3: if (i.key() % 6 < 5) button(static_cast(i.key() + 1))->setFocus(); break; default: break; } } deepin-calculator-5.7.21/src/control/procheckbtnkeypad.h000066400000000000000000000042601423020056600233210ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROCHECKBTNKEYPAD_H #define PROCHECKBTNKEYPAD_H #include "textbutton.h" #include "iconbutton.h" #include "memorybutton.h" #include "equalbutton.h" #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE /** * @brief 程序员第一排按钮 */ class ProCheckBtnKeypad : public DWidget { Q_OBJECT public: /** * @brief 按键栏 */ enum Buttons {Key_GeneralKeypad = 36, Key_BinaryKeypad, Key_System, Key_Option, Key_MS, Key_Mlist}; //普通键盘, 二进制键盘, 位数, 计算方法选项, MS, M^ explicit ProCheckBtnKeypad(QWidget *parent = nullptr); ~ProCheckBtnKeypad() override; void mouseMoveEvent(QMouseEvent *e) override; DPushButton *button(Buttons key); void animate(Buttons key, bool isspace = false); bool buttonHasFocus(); static const struct KeyDescription { QString text; //按钮text Buttons button; //按钮枚举值名 int row; //行 int column; //列 } keyDescriptions[]; public slots: void initButtons(); void buttonThemeChanged(int type); void getFocus(int); signals: void buttonPressed(int); void buttonPressedbySpace(int); void equalPressed(); private: QGridLayout *m_layout; QSignalMapper *m_mapper; QHash> m_keys; }; #endif // PROCHECKBTNKEYPAD_H deepin-calculator-5.7.21/src/control/programmerkeypad.cpp000066400000000000000000000341021423020056600235230ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "programmerkeypad.h" const int KEYPAD_HEIGHT = 279; //键盘界面高度 const int KEYPAD_SPACING = 3; //键盘按键间距,按钮比ui大2pix,此处小2pix const int LEFT_MARGIN = 10; //键盘左边距,按钮比ui大2pix,此处小2pix const int RIGHT_MARGIN = 10; //键盘右边距,按钮比ui大2pix,此处小2pix const int BOTTOM_MARGIN = 10; //键盘下边距,按钮比ui大2pix,此处小2pix const QSize STANDARD_TEXTBTNSIZE = QSize(69, 42); //程序员模式按钮大小,为画边框比ui大2pix const ProgrammerKeypad::KeyDescription ProgrammerKeypad::keyDescriptions[] = { {"AND", Key_AND, 0, 0}, {"A", Key_A, 0, 1}, {"<<", Key_moveL, 0, 2}, {">>", Key_moveR, 0, 3}, {"C", Key_Clear, 0, 4}, {"", Key_Backspace, 0, 5}, {"OR", Key_OR, 1, 0}, {"B", Key_B, 1, 1}, {"(", Key_leftBracket, 1, 2}, {")", Key_rightBracket, 1, 3}, {"%", Key_percent, 1, 4}, {"", Key_Div, 1, 5}, {"NOT", Key_NOT, 2, 0}, {"C", Key_C, 2, 1}, {"7", Key_7, 2, 2}, {"8", Key_8, 2, 3}, {"9", Key_9, 2, 4}, {"", Key_Mult, 2, 5}, {"NAND", Key_NAND, 3, 0}, {"D", Key_D, 3, 1}, {"4", Key_4, 3, 2}, {"5", Key_5, 3, 3}, {"6", Key_6, 3, 4}, {"", Key_Min, 3, 5}, {"NOR", Key_NOR, 4, 0}, {"E", Key_E, 4, 1}, {"1", Key_1, 4, 2}, {"2", Key_2, 4, 3}, {"3", Key_3, 4, 4}, {"", Key_Plus, 4, 5}, {"XOR", Key_XOR, 5, 0}, {"F", Key_F, 5, 1}, {"+/-", Key_opposite, 5, 2}, {"0", Key_0, 5, 3}, {".", Key_point, 5, 4}, {"=", Key_equal, 5, 5} }; ProgrammerKeypad::ProgrammerKeypad(QWidget *parent) : DWidget(parent), m_layout(new QGridLayout(this)), m_mapper(new QSignalMapper(this)), m_leftBracket(new DLabel(this)), m_rightBracket(new DLabel(this)) { this->setFixedHeight(KEYPAD_HEIGHT); m_layout->setMargin(0); m_layout->setSpacing(KEYPAD_SPACING); m_layout->setContentsMargins(0, 0, 0, 0); // setFocusPolicy(Qt::StrongFocus); m_leftBracket->setFixedSize(24, 14); m_rightBracket->setFixedSize(24, 14); installEventFilter(this); initButtons(); initUI(); connect(m_mapper, SIGNAL(mapped(int)), SIGNAL(buttonPressed(int))); } ProgrammerKeypad::~ProgrammerKeypad() { } /** * @brief 防止鼠标点击拖拽可拖动窗口 */ void ProgrammerKeypad::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } /** * @brief 根据枚举值返回相应button * @param key 按钮名 */ DPushButton *ProgrammerKeypad::button(ProgrammerKeypad::Buttons key) { return m_keys.value(key).first; } /** * @brief 按钮点击动画效果 */ void ProgrammerKeypad::animate(ProgrammerKeypad::Buttons key, bool isspace) { if (button(key)->text().isEmpty()) { IconButton *btn = static_cast(button(key)); btn->animate(isspace); } else { if (button(key)->text() == "=") { EqualButton *btn = dynamic_cast(button(key)); btn->animate(isspace); } else { TextButton *btn = static_cast(button(key)); btn->animate(isspace); } } } /** * @brief 焦点是否在该button上 */ bool ProgrammerKeypad::buttonHasFocus() { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { return true; } } return false; } /** * @brief 初始化button */ void ProgrammerKeypad::initButtons() { const int count = sizeof(keyDescriptions) / sizeof(keyDescriptions[0]); for (int i = 0; i < count; ++i) { const KeyDescription *desc = keyDescriptions + i; DPushButton *button; if (desc->text.isEmpty()) { button = new IconButton(this); } else { if (desc->text == "=") { button = new EqualButton(desc->text, this); connect(static_cast(button), &EqualButton::focus, this, &ProgrammerKeypad::getFocus); //获取上下左右键 connect(static_cast(button), &EqualButton::space, this, [ = ]() { emit buttonPressedbySpace(Key_equal); }); } else { if (i % 6 == 0) button = new TextButton(desc->text, true, this); else button = new TextButton(desc->text, false, this); } } if (i % 6 == 1) { m_decdisable << static_cast(button); m_octdisable << static_cast(button); m_bindisable << static_cast(button); } if (i == 15 || i == 16) { m_octdisable << static_cast(button); m_bindisable << static_cast(button); } if (i == 14 || i == 20 || i == 21 || i == 22 || i == 27 || i == 28) { m_bindisable << static_cast(button); } if (desc->text == "=") button->setFixedSize(69, 43); else button->setFixedSize(STANDARD_TEXTBTNSIZE); m_layout->addWidget(button, desc->row, desc->column, Qt::AlignHCenter | Qt::AlignVCenter); const QPair hashValue(button, desc); m_keys.insert(desc->button, hashValue); //key为枚举值,value.first为DPushButton *, value.second为const KeyDescription * if (desc->text != "=") { connect(static_cast(button), &TextButton::focus, this, &ProgrammerKeypad::getFocus); //获取上下左右键 connect(static_cast(button), &TextButton::space, this, [ = ]() { Buttons spacekey = m_keys.key(hashValue); emit buttonPressedbySpace(spacekey); }); } connect(button, &DPushButton::clicked, m_mapper, static_cast(&QSignalMapper::map)); m_mapper->setMapping(button, desc->button); //多个按钮绑定到一个mapper上 } static_cast(this->button(Key_point))->setButtonGray(true); radixChanged(1); } /** * @brief 切换相应主题切图 */ void ProgrammerKeypad::buttonThemeChanged(int type) { m_themetype = type; QString path; if (type == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); IconButton *btn = static_cast(button(Key_Div)); btn->setIconUrl(path + "divide_normal.svg", path + "divide_hover.svg", path + "divide_press.svg"); btn = static_cast(button(Key_Mult)); btn->setIconUrl(path + "x_normal.svg", path + "x_hover.svg", path + "x_press.svg"); btn = static_cast(button(Key_Min)); btn->setIconUrl(path + "-_normal.svg", path + "-_hover.svg", path + "-_press.svg"); btn = static_cast(button(Key_Plus)); btn->setIconUrl(path + "+_normal.svg", path + "+_hover.svg", path + "+_press.svg"); btn = static_cast(button(Key_Backspace)); btn->setIconUrl(path + "clear_normal.svg", path + "clear_hover.svg", path + "clear_press.svg", 1); } /** * @brief 获取button上下左右键信号setfocus * @param direction 0-上 1-下 2-左 3-右 */ void ProgrammerKeypad::getFocus(int direction) { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { break; //获取焦点按钮 } } switch (direction) { case 0: if (i.key() / 6 > 0) { for (int j = 1; i.key() >= 6 * j; j++) { if (button(static_cast(i.key() - 6 * j))->isEnabled()) { button(static_cast(i.key() - 6 * j))->setFocus(); //根据上下左右信号重置焦点 break; } } } break; case 1: if (i.key() / 6 < 5) { for (int j = 1; i.key() + 6 * j < 36; j++) { if (button(static_cast(i.key() + 6 * j))->isEnabled()) { button(static_cast(i.key() + 6 * j))->setFocus(); //根据上下左右信号重置焦点 break; } } } break; case 2: if (i.key() % 6 > 0) { for (int j = 1; (i.key() - j + 1) % 6 > 0; j++) { if (button(static_cast(i.key() - j))->isEnabled()) { button(static_cast(i.key() - j))->setFocus(); //根据上下左右信号重置焦点 break; } } } break; case 3: if (i.key() % 6 < 5) { for (int j = 1; (i.key() + j - 1) % 6 < 5; j++) { if (button(static_cast(i.key() + j))->isEnabled()) { button(static_cast(i.key() + j))->setFocus(); //根据上下左右信号重置焦点 break; } } } break; default: break; } } /** * @brief ProgrammerKeypad::radixChanged * @param row:进制列表的行数 0-16 1-10 2-8 3-2 * 根据当前进制,屏蔽或开放数字键盘的对应按键 */ void ProgrammerKeypad::radixChanged(int row) { switch (row) { case 0: foreach (TextButton *button, m_bindisable) { if (!button->isEnabled()) button->setEnabled(true); } m_currentBase = 16; break; case 1: foreach (TextButton *button, m_bindisable) { if (!button->isEnabled()) button->setEnabled(true); } foreach (TextButton *button, m_decdisable) { if (button->isEnabled()) button->setEnabled(false); } m_currentBase = 10; break; case 2: foreach (TextButton *button, m_bindisable) { if (!button->isEnabled()) button->setEnabled(true); } foreach (TextButton *button, m_octdisable) { if (button->isEnabled()) button->setEnabled(false); } m_currentBase = 8; break; case 3: foreach (TextButton *button, m_bindisable) { button->setEnabled(false); } m_currentBase = 2; break; default: foreach (TextButton *button, m_bindisable) { if (!button->isEnabled()) button->setEnabled(true); } foreach (TextButton *button, m_decdisable) { if (button->isEnabled()) button->setEnabled(false); } m_currentBase = 10; break; } } void ProgrammerKeypad::bracketsNum(int direction, QString num) { if (num == "0") num = ""; if (direction == 0) m_leftBracket->setText(num); else if (direction == 1) m_rightBracket->setText(num); } void ProgrammerKeypad::initUI() { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.key() == Key_leftBracket) { m_leftBracket->setParent(i.value().first); m_leftBracket->move(i.value().first->rect().x() + 37, i.value().first->rect().y() + 22); connect(i.value().first, &DPushButton::pressed, [ = ]() { m_leftBracket->setStyleSheet(QString("font-family:Noto Sans;color:%1;font-size:14px;") .arg(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name())); }); connect(static_cast(i.value().first), &TextButton::mouseRelease, [ = ]() { //考虑focus状态,在鼠标松开时再更改label字体颜色 if (m_themetype == 1) m_leftBracket->setStyleSheet(QString("font-family:Noto Sans;color:black;font-size:14px;")); else m_leftBracket->setStyleSheet(QString("font-family:Noto Sans;color:white;font-size:14px;")); }); } if (i.key() == Key_rightBracket) { m_rightBracket->setParent(i.value().first); m_rightBracket->move(i.value().first->rect().x() + 37, i.value().first->rect().y() + 22); connect(i.value().first, &DPushButton::pressed, [ = ]() { m_rightBracket->setStyleSheet(QString("font-family:Noto Sans;color:%1;font-size:14px;") .arg(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name())); }); connect(static_cast(i.value().first), &TextButton::mouseRelease, [ = ]() { if (m_themetype == 1) m_rightBracket->setStyleSheet(QString("font-family:Noto Sans;color:black;font-size:14px;")); else m_rightBracket->setStyleSheet(QString("font-family:Noto Sans;color:white;font-size:14px;")); }); } } button(Key_Div)->setObjectName("SymbolButton"); button(Key_Mult)->setObjectName("SymbolButton"); button(Key_Min)->setObjectName("SymbolButton"); button(Key_Plus)->setObjectName("SymbolButton"); this->setContentsMargins(LEFT_MARGIN, 0, RIGHT_MARGIN, BOTTOM_MARGIN); } deepin-calculator-5.7.21/src/control/programmerkeypad.h000066400000000000000000000057721423020056600232030ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROGRAMMERKEYPAD_H #define PROGRAMMERKEYPAD_H #include "textbutton.h" #include "iconbutton.h" #include "memorybutton.h" #include "equalbutton.h" #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE /** * @brief 程序员模式普通键盘 */ class ProgrammerKeypad : public DWidget { Q_OBJECT public: enum Buttons { Key_AND, Key_A, Key_moveL, Key_moveR, Key_Clear, Key_Backspace, //AND, A, <<, >>, AC, 退格 Key_OR, Key_B, Key_leftBracket, Key_rightBracket, Key_percent, Key_Div, //OR, B, (, ), %, / Key_NOT, Key_C, Key_7, Key_8, Key_9, Key_Mult, //NOT, C, 7, 8, 9, * Key_NAND, Key_D, Key_4, Key_5, Key_6, Key_Min, //NAND, D, 4, 5, 6, - Key_NOR, Key_E, Key_1, Key_2, Key_3, Key_Plus, //NOR, E, 1, 2, 3, + Key_XOR, Key_F, Key_opposite, Key_0, Key_point, Key_equal //XOR, F, +/-, 0, ., = }; explicit ProgrammerKeypad(QWidget *parent = nullptr); ~ProgrammerKeypad() override; void mouseMoveEvent(QMouseEvent *e) override; DPushButton *button(Buttons key); void animate(Buttons key, bool isspace = false); bool buttonHasFocus(); static const struct KeyDescription { QString text; //按钮text Buttons button; //按钮枚举值名 int row; //行 int column; //列 } keyDescriptions[]; public slots: void initButtons(); void buttonThemeChanged(int type); void getFocus(int); void radixChanged(int row); void bracketsNum(int direction, QString num); //direction 0-左括号 1-右括号 signals: void buttonPressed(int); void buttonPressedbySpace(int); void equalPressed(); private: void initUI(); private: QGridLayout *m_layout; QSignalMapper *m_mapper; QHash> m_keys; QList m_decdisable; //十进制置灰按钮 QList m_octdisable; //八进制置灰按钮 QList m_bindisable; //二进制置灰按钮 int m_currentBase = 10;//当前进制 DLabel *m_leftBracket; //存放左括号不匹配数 DLabel *m_rightBracket; //存放右括号不匹配数 int m_themetype; }; #endif // PROGRAMMERKEYPAD_H deepin-calculator-5.7.21/src/control/prosystemkeypad.cpp000066400000000000000000000202401423020056600234130ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "prosystemkeypad.h" #include #include "../../3rdparty/core/settings.h" const QSize SYSTEMKEYPADSIZE = QSize(451, 279); const int LEFT_MARGIN = 10; //键盘左边距 const int BOTTOM_MARGIN = 14; //键盘下边距 ProSystemKeypad::ProSystemKeypad(QWidget *parent) : DWidget(parent), m_layout(new QGridLayout(this)) { this->setFocusPolicy(Qt::ClickFocus); this->setFixedSize(SYSTEMKEYPADSIZE); m_layout->setContentsMargins(LEFT_MARGIN, 0, 0, BOTTOM_MARGIN); initUI(); m_binaryValue.fill('0', 64); } ProSystemKeypad::~ProSystemKeypad() { } /** * @brief 设置当前显示位数 * @param system 64, 32, 16, 8 */ void ProSystemKeypad::setSystem(int system, int oldsystem) { QHashIterator i(m_keys); if (system == 64) { while (i.hasNext()) { i.next(); i.value()->setButtonEnabled(true); } if (oldsystem < system && m_binaryValue.at(64 - oldsystem) == '1') { for (int j = 63; j >= oldsystem; j--) { m_buttons.value(j)->setButtonState(true); m_binaryValue.replace(63 - j, 1, "1"); } emit valuechanged(m_binaryValue); } } else if (system == 32) { while (i.hasNext()) { i.next(); if (i.key() >= 32) i.value()->setButtonEnabled(false); else i.value()->setButtonEnabled(true); } if (oldsystem < system && m_binaryValue.at(64 - oldsystem) == '1') { for (int j = 31; j >= oldsystem; j--) { m_buttons.value(j)->setButtonState(true); m_binaryValue.replace(63 - j, 1, "1"); } emit valuechanged(m_binaryValue); } if (oldsystem > system) { bool isdiff = m_binaryValue.contains("1"); for (int j = oldsystem - 1; j > 31; j--) { m_buttons.value(j)->setButtonState(false); m_binaryValue.replace(63 - j, 1, "0"); } if (isdiff) emit valuechanged(m_binaryValue); } } else if (system == 16) { while (i.hasNext()) { i.next(); if (i.key() >= 16) i.value()->setButtonEnabled(false); else i.value()->setButtonEnabled(true); } if (oldsystem < system && m_binaryValue.at(64 - oldsystem) == '1') { for (int j = 15; j >= oldsystem; j--) { m_buttons.value(j)->setButtonState(true); m_binaryValue.replace(63 - j, 1, "1"); } emit valuechanged(m_binaryValue); } if (oldsystem > system) { bool isdiff = m_binaryValue.contains("1"); for (int j = oldsystem - 1; j > 15; j--) { m_buttons.value(j)->setButtonState(false); m_binaryValue.replace(63 - j, 1, "0"); } if (isdiff) emit valuechanged(m_binaryValue); } } else { while (i.hasNext()) { i.next(); if (i.key() < 8) i.value()->setButtonEnabled(true); else i.value()->setButtonEnabled(false); } if (oldsystem > system) { bool isdiff = m_binaryValue.contains("1"); for (int j = oldsystem - 1; j > 7; j--) { m_buttons.value(j)->setButtonState(false); m_binaryValue.replace(63 - j, 1, "0"); } if (isdiff) emit valuechanged(m_binaryValue); } } // qDebug() << m_binaryValue; } bool ProSystemKeypad::buttonHasFocus() { QHashIterator i(m_buttons); while (i.hasNext()) { i.next(); if (i.value()->hasFocus()) { return true; } } return false; } void ProSystemKeypad::mouseMoveEvent(QMouseEvent *event) { Q_UNUSED(event); } /** * @brief ProSystemKeypad::getFocus * @param dir:键盘方向键方向 * @param key:按键的序号 * 处理bitbutton的focus事件s */ void ProSystemKeypad::getFocus(int dir, int key) { switch (dir) { case 0: if (key < 48 && m_buttons.value(key + 16)->isEnabled()) m_buttons.value(key + 16)->setFocus(); break; case 1: if (key > 15 && m_buttons.value(key - 16)->isEnabled()) m_buttons.value(key - 16)->setFocus(); break; case 2: if (key < 63 && m_buttons.value(key + 1)->isEnabled()) m_buttons.value(key + 1)->setFocus(); break; case 3: if (key > 0 && m_buttons.value(key - 1)->isEnabled()) m_buttons.value(key - 1)->setFocus(); break; default: break; } } /** * @brief ProSystemKeypad::setvalue * @param num:当前输入栏中光标所在位置对应的数字 * 当输入栏中输入或修改数字时,修改对应的bitbutton的状态 */ void ProSystemKeypad::setvalue(QString num) { num.remove(" ").remove(","); int length = num.length(); if (length > Settings::instance()->proBitLength) { num = num.right(Settings::instance()->proBitLength); length = num.length(); m_binaryValue.fill('0', 64).replace(64 - length, length, num); emit valuechanged(m_binaryValue); longBitCut(num); } else m_binaryValue.fill('0', 64).replace(64 - length, length, num); // qDebug() << m_binaryValue; for (int i = 0; i < Settings::instance()->proBitLength; i++) { if (m_binaryValue.at(63 - i) == '1') { m_buttons.value(i)->setButtonState(true); } else m_buttons.value(i)->setButtonState(false); } } void ProSystemKeypad::longBitCut(const QString &num) { QString number = "0b" + num; Quantity ans(HNumber(number.toLatin1().data())); if (!ans.isNan()) emit longbitcut(ans); } void ProSystemKeypad::initUI() { for (int i = 0; i < 16; i++) { ProBitWidget *probitwidget = new ProBitWidget(this); probitwidget->findChild()->setText(QString::number(60 - i * 4, 10)); m_layout->addWidget(probitwidget, i / 4, i % 4, Qt::AlignHCenter | Qt::AlignVCenter); //每块ProBitWidget对应一个key m_keys.insert(60 - i * 4, probitwidget); for (int j = 0; j < 4; j++) { m_buttons.insert(63 - i * 4 - j, probitwidget->getbutton(j)); } } initconnects(); } void ProSystemKeypad::initconnects() { for (int i = 0; i < 64; i++) { connect(m_buttons.value(i), &DPushButton::clicked, this, [ = ]() { emit bitbuttonclicked(); changeBinaryValue(i); }); connect(m_buttons.value(i), &BitButton::focus, this, [ = ](int direction) { getFocus(direction, i); }); //获取上下左右键 connect(m_buttons.value(i), &BitButton::space, this, [ = ]() { if (m_buttons.value(i)->text() == QString("0")) m_buttons.value(i)->setButtonState(true); else m_buttons.value(i)->setButtonState(false); changeBinaryValue(i); }); } } /** * @brief ProSystemKeypad::changeBinaryValue * @param i:按键序号 * 修改位键盘对应的2进制的值并传给输入框 */ void ProSystemKeypad::changeBinaryValue(int i) { if (m_binaryValue.at(63 - i) == '0') m_binaryValue.replace(63 - i, 1, '1'); else m_binaryValue.replace(63 - i, 1, '0'); // qDebug() << m_binaryValue; emit valuechanged(m_binaryValue); } deepin-calculator-5.7.21/src/control/prosystemkeypad.h000066400000000000000000000036561423020056600230740ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROSYSTEMKEYPAD_H #define PROSYSTEMKEYPAD_H #include "../../3rdparty/core/evaluator.h" #include "../widgets/probitwidget.h" #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE /** * @brief 二进制按钮键盘 */ class ProSystemKeypad : public DWidget { Q_OBJECT public: explicit ProSystemKeypad(QWidget *parent = nullptr); ~ProSystemKeypad() override; void setSystem(int system, int oldsystem); //system-64, 32, 16, 8 oldsystem-转换前的位数 bool buttonHasFocus(); void mouseMoveEvent(QMouseEvent *event) override; signals: void valuechanged(QString num); void bitbuttonclicked(); void longbitcut(Quantity ans); public slots: void getFocus(int dir, int key); void setvalue(QString num); void longBitCut(const QString &num); private: void initUI(); void initconnects(); void changeBinaryValue(int i); QGridLayout *m_layout; QHash m_keys; //存储每一块ProBitWidget,以便设置不同位数 QHash m_buttons; //存储所有按键 // QChar m_binaryValue[64]; QString m_binaryValue; }; #endif // PROSYSTEMKEYPAD_H deepin-calculator-5.7.21/src/control/scientifickeypad.cpp000066400000000000000000000650451423020056600235020ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "scientifickeypad.h" #include #include #include #include #include "dthememanager.h" const int KEYPADHEIGHT = 350; //整体键盘的高度 const QSize BUTTON_SIZE = QSize(69, 46); //科学模式的固定大小 const ScientificKeyPad::KeyDescription ScientificKeyPad::keyDescriptions[] = { {"", Key_deg, 2, 0, 1, 1}, {"2ⁿᵈ", Key_page, 2, 1, 1, 1}, {"π", Key_PI, 2, 2, 1, 1}, {"e", Key_e, 2, 3, 1, 1}, {"Mod", Key_Mod, 2, 4, 1, 1}, {"", Key_Backspace, 2, 5, 1, 1}, {"sin", Key_sin, 3, 0, 1, 1}, {"x²", Key_x2, 3, 1, 1, 1}, {"1/x", Key_Derivative, 3, 2, 1, 1}, {"x!", Key_Factorials, 3, 3, 1, 1}, {"exp", Key_exp, 3, 4, 1, 1}, {"C", Key_Clear, 3, 5, 1, 1}, {"cos", Key_cos, 4, 0, 1, 1}, {"x³", Key_x3, 4, 1, 1, 1}, {"(", Key_left, 4, 2, 1, 1}, {")", Key_right, 4, 3, 1, 1}, {"%", Key_Percent, 4, 4, 1, 1}, {"", Key_Div, 4, 5, 1, 1}, {"tan", Key_tan, 5, 0, 1, 1}, {"xʸ", Key_xy, 5, 1, 1, 1}, {"7", Key_7, 5, 2, 1, 1}, {"8", Key_8, 5, 3, 1, 1}, {"9", Key_9, 5, 4, 1, 1}, {"", Key_Mult, 5, 5, 1, 1}, {"cot", Key_cot, 6, 0, 1, 1}, {"10ˣ", Key_10x, 6, 1, 1, 1}, {"4", Key_4, 6, 2, 1, 1}, {"5", Key_5, 6, 3, 1, 1}, {"6", Key_6, 6, 4, 1, 1}, {"", Key_Min, 6, 5, 1, 1}, {"|x|", Key_Modulus, 7, 0, 1, 1}, {"log", Key_log, 7, 1, 1, 1}, {"1", Key_1, 7, 2, 1, 1}, {"2", Key_2, 7, 3, 1, 1}, {"3", Key_3, 7, 4, 1, 1}, {"", Key_Plus, 7, 5, 1, 1}, {"Rand", Key_Rand, 8, 0, 1, 1}, {"ln", Key_ln, 8, 1, 1, 1}, {"+/-", Key_opposite, 8, 2, 1, 1}, {"0", Key_0, 8, 3, 1, 1}, {".", Key_Point, 8, 4, 1, 1}, {"=", Key_Equals, 8, 5, 1, 1}, }; const ScientificKeyPad::KeyDescription1 ScientificKeyPad::keyDescriptions1[] = { {"", Key_arcsin, 3, 0, 1, 1}, {"", Key_sqrt2, 3, 1, 1, 1}, {"", Key_arccos, 4, 0, 1, 1}, {"", Key_sqrt3, 4, 1, 1, 1}, {"", Key_arctan, 5, 0, 1, 1}, {"", Key_ysqrtx, 5, 1, 1, 1}, {"", Key_arccot, 6, 0, 1, 1}, {"2ˣ", Key_2x, 6, 1, 1, 1}, {"logᵧx", Key_logyx, 7, 1, 1, 1}, {"eˣ", Key_ex, 8, 1, 1, 1}, }; /** * @brief 初始化并设置iconbutton */ //static DPushButton *createSpecialKeyButton(ScientificKeyPad::Buttons key, bool page) //{ // IconButton *button; // if (page) // button = new IconButton(nullptr, 0, true); // else // button = new IconButton(); // QString path; // if (DGuiApplicationHelper::instance()->themeType() == 2) // path = QString(":/assets/images/%1/").arg("dark"); // else // path = QString(":/assets/images/%1/").arg("light"); // if (key == ScientificKeyPad::Key_Div) { // button->setIconUrl(path + "divide_normal.svg", path + "divide_hover.svg", path + "divide_press.svg"); // } else if (key == ScientificKeyPad::Key_Mult) { // button->setIconUrl(path + "x_normal.svg", path + "x_hover.svg", path + "x_press.svg"); // } else if (key == ScientificKeyPad::Key_Min) { // button->setIconUrl(path + "-_normal.svg", path + "-_hover.svg", path + "-_press.svg"); // } else if (key == ScientificKeyPad::Key_Plus) { // button->setIconUrl(path + "+_normal.svg", path + "+_hover.svg", path + "+_press.svg"); // } else if (key == ScientificKeyPad::Key_Backspace) { // button->setIconUrl(path + "clear_normal.svg", path + "clear_hover.svg", path + "clear_press.svg", 1); // } else if (key == ScientificKeyPad::Key_sqrt2) { // button->setIconUrl(path + "squareroot_normal.svg", path + "squareroot_hover.svg", path + "squareroot_press.svg", 3); // } else if (key == ScientificKeyPad::Key_sqrt3) { // button->setIconUrl(path + "cuberoot_normal.svg", path + "cuberoot_hover.svg", path + "cuberoot_press.svg", 3); // } else if (key == ScientificKeyPad::Key_ysqrtx) { // button->setIconUrl(path + "yroot_normal.svg", path + "yroot_hover.svg", path + "yroot_press.svg", 3); // } else if (key == ScientificKeyPad::Key_deg) { // button->setIconUrl(path + "deg_normal.svg", path + "deg_hover.svg", path + "deg_press.svg", 5); // } // //connect(button, &IconButton::updateInterface, this, &ScientificKeyPad::updateInterface); // return button; //} ScientificKeyPad::ScientificKeyPad(QWidget *parent) : DWidget(parent) , m_gridlayout1(new QGridLayout(this)) , m_mapper(new QSignalMapper(this)) , m_leftBracket(new DLabel(this)) , m_rightBracket(new DLabel(this)) , m_arcsinwidget(new QStackedWidget(this)) , m_arccoswidget(new QStackedWidget(this)) , m_arctanwidget(new QStackedWidget(this)) , m_arccotwidget(new QStackedWidget(this)) , m_sqrtwidget(new QStackedWidget(this)) , m_cbrtwidget(new QStackedWidget(this)) , m_yrootwidget(new QStackedWidget(this)) , m_2xwidget(new QStackedWidget(this)) , m_logyxwidget(new QStackedWidget(this)) , m_exwidget(new QStackedWidget(this)) { this->setFixedHeight(KEYPADHEIGHT); m_leftBracket->setFixedSize(24, 14); m_rightBracket->setFixedSize(24, 14); initButtons(); initUI(); m_gridlayout1->setMargin(0); m_gridlayout1->setSpacing(3); //按钮比ui大2pix,此处小2pix m_gridlayout1->setContentsMargins(0, 0, 0, 0); this->setLayout(m_gridlayout1); connect(m_mapper, SIGNAL(mapped(int)), SIGNAL(buttonPressed(int))); connect(this, &ScientificKeyPad::buttonPressed, this, &ScientificKeyPad::turnPage); //按下2nd事件 connect(this, &ScientificKeyPad::buttonPressedbySpace, this, &ScientificKeyPad::turnPage); } ScientificKeyPad::~ScientificKeyPad() { } void ScientificKeyPad::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } /** * @brief 根据枚举值返回相应button * @param key 按钮名 */ DPushButton *ScientificKeyPad::button(Buttons key) { if (key == Key_arcsin || key == Key_arccos || key == Key_arccot || key == Key_arctan || key == Key_sqrt2 || key == Key_sqrt3 || key == Key_ysqrtx || key == Key_2x || key == Key_logyx || key == Key_ex) { return m_keys1.value(key).first; } else { return m_keys.value(key).first; } } DPushButton *ScientificKeyPad::button(int key) { if (key == Key_arcsin || key == Key_arccos || key == Key_arccot || key == Key_arctan || key == Key_sqrt2 || key == Key_sqrt3 || key == Key_ysqrtx || key == Key_2x || key == Key_logyx || key == Key_ex) { return m_keys1.value(Buttons(key)).first; } else { return m_keys.value(Buttons(key)).first; } } /** * @brief 按钮点击动画效果 */ void ScientificKeyPad::animate(Buttons key, bool isspace) { if (button(key)->text().isEmpty()) { IconButton *btn = static_cast(button(key)); btn->animate(isspace); } else { if (button(key)->text() == "=") { EqualButton *btn = dynamic_cast(button(key)); btn->animate(isspace); } else { TextButton *btn = static_cast(button(key)); btn->animate(isspace); } } } bool ScientificKeyPad::buttonHasFocus() { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { return true; } } return false; } /** * @brief 初始化button */ void ScientificKeyPad::initButtons() { const int count = sizeof(keyDescriptions) / sizeof(keyDescriptions[0]); for (int i = 0; i < count; ++i) { const KeyDescription *desc = keyDescriptions + i; DPushButton *button; if (desc->text.isEmpty()) { if (i % 6 == 0 || i % 6 == 1) button = new IconButton(this, 0, true); else button = new IconButton(this, 0, false); } else { if (desc->text == "=") { button = new EqualButton(desc->text, this); connect(static_cast(button), &EqualButton::focus, this, &ScientificKeyPad::getFocus); //获取上下左右键 connect(static_cast(button), &EqualButton::space, this, [ = ]() { Buttons spacekey = Key_Equals; emit buttonPressedbySpace(spacekey); }); } else if (desc->text == "MC" || desc->text == "MR" || desc->text == "M+" || desc->text == "M-" || desc->text == "MS") { button = new MemoryButton(desc->text, false, this); } else { if (i % 6 == 0 || i % 6 == 1) button = new TextButton(desc->text, true, this); else { button = new TextButton(desc->text, false, this); } } } //stackwidget中按钮初始化 if ((i / 6 > 0) && (i % 6 == 0 || i % 6 == 1) && i != 30 && i != 36) { DPushButton *pagebutton; //翻页按键初始化 if (desc->button == Key_sin) { const KeyDescription1 *desc1 = keyDescriptions1; pagebutton = new TextButton("arcsin", true, this); initStackWidget(m_arcsinwidget, button, pagebutton, desc1); } else if (desc->button == Key_x2) { const KeyDescription1 *desc1 = keyDescriptions1 + 1; pagebutton = new IconButton(this, 0, true); initStackWidget(m_arccoswidget, button, pagebutton, desc1); } else if (desc->button == Key_cos) { const KeyDescription1 *desc1 = keyDescriptions1 + 2; pagebutton = new TextButton("arccos", true, this); initStackWidget(m_arctanwidget, button, pagebutton, desc1); } else if (desc->button == Key_x3) { const KeyDescription1 *desc1 = keyDescriptions1 + 3; pagebutton = new IconButton(this, 0, true); initStackWidget(m_arccotwidget, button, pagebutton, desc1); } else if (desc->button == Key_tan) { const KeyDescription1 *desc1 = keyDescriptions1 + 4; pagebutton = new TextButton("arctan", true, this); initStackWidget(m_sqrtwidget, button, pagebutton, desc1); } else if (desc->button == Key_xy) { const KeyDescription1 *desc1 = keyDescriptions1 + 5; pagebutton = new IconButton(this, 0, true); initStackWidget(m_cbrtwidget, button, pagebutton, desc1); } else if (desc->button == Key_cot) { const KeyDescription1 *desc1 = keyDescriptions1 + 6; pagebutton = new TextButton("arccot", true, this); initStackWidget(m_yrootwidget, button, pagebutton, desc1); } else if (desc->button == Key_10x) { const KeyDescription1 *desc1 = keyDescriptions1 + 7; pagebutton = new TextButton("2ˣ", true, this); initStackWidget(m_2xwidget, button, pagebutton, desc1); } else if (desc->button == Key_log) { const KeyDescription1 *desc1 = keyDescriptions1 + 8; pagebutton = new TextButton("logᵧx", true, this); initStackWidget(m_logyxwidget, button, pagebutton, desc1); } else { const KeyDescription1 *desc1 = keyDescriptions1 + 9; pagebutton = new TextButton("eˣ", true, this); initStackWidget(m_exwidget, button, pagebutton, desc1); } pagebutton->setFixedSize(BUTTON_SIZE); connect(static_cast(pagebutton), &TextButton::focus, this, &ScientificKeyPad::getFocus); //获取上下左右键 } else { m_gridlayout1->addWidget(button, desc->row, desc->column, desc->rowcount, desc->columncount, Qt::AlignCenter/* | Qt::AlignTop*/); } button->setFixedSize(BUTTON_SIZE); const QPair hashValue(button, desc); m_keys.insert(desc->button, hashValue); //key为枚举值,value.first为DPushButton *, value.second为const KeyDescription * if (desc->text != "=") { connect(static_cast(button), &TextButton::focus, this, &ScientificKeyPad::getFocus); //获取上下左右键 connect(static_cast(button), &TextButton::space, this, [ = ]() { Buttons spacekey = m_keys.key(hashValue); emit buttonPressedbySpace(spacekey); }); } connect(button, &DPushButton::clicked, m_mapper, static_cast(&QSignalMapper::map)); m_mapper->setMapping(button, desc->button); //多个按钮绑定到一个mapper上 } } /** * @brief 连接窗口缩放与按钮大小变化的信号槽,设置左右括号不匹配数label的状态颜色 */ void ScientificKeyPad::initUI() { QHashIterator> i(m_keys); while (i.hasNext()) { i.next(); if (i.key() == Key_left) { m_leftBracket->setParent(i.value().first); m_leftBracket->move(i.value().first->rect().x() + 37, i.value().first->rect().y() + 22); connect(i.value().first, &DPushButton::pressed, [ = ]() { m_leftBracket->setStyleSheet(QString("font-family:Noto Sans;color:%1;font-size:14px;") .arg(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name())); }); connect(static_cast(i.value().first), &TextButton::mouseRelease, [ = ]() { //考虑focus状态,在鼠标松开时再更改label字体颜色 if (m_themetype == 1) m_leftBracket->setStyleSheet(QString("font-family:Noto Sans;color:black;font-size:14px;")); else m_leftBracket->setStyleSheet(QString("font-family:Noto Sans;color:white;font-size:14px;")); }); } if (i.key() == Key_right) { m_rightBracket->setParent(i.value().first); m_rightBracket->move(i.value().first->rect().x() + 37, i.value().first->rect().y() + 22); connect(i.value().first, &DPushButton::pressed, [ = ]() { m_rightBracket->setStyleSheet(QString("font-family:Noto Sans;color:%1;font-size:14px;") .arg(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name())); }); connect(static_cast(i.value().first), &TextButton::mouseRelease, [ = ]() { if (m_themetype == 1) m_rightBracket->setStyleSheet(QString("font-family:Noto Sans;color:black;font-size:14px;")); else m_rightBracket->setStyleSheet(QString("font-family:Noto Sans;color:white;font-size:14px;")); }); } } QHashIterator> i1(m_keys1); button(Key_Div)->setObjectName("SymbolButton"); button(Key_Mult)->setObjectName("SymbolButton"); button(Key_Min)->setObjectName("SymbolButton"); button(Key_Plus)->setObjectName("SymbolButton"); this->setContentsMargins(12, 0, 12, 12); } /** * @brief ScientificKeyPad::initStackWidget * @param widget * @param button index(0)的按键 * @param pagebutton index(1)的按键 * @param desc1 index(1)按键信息 * page2按键初始化设置 */ void ScientificKeyPad::initStackWidget(QStackedWidget *widget, DPushButton *button, DPushButton *pagebutton, const KeyDescription1 *desc1) { widget->addWidget(button); widget->addWidget(pagebutton); widget->setCurrentIndex(0); widget->setFixedSize(BUTTON_SIZE.width(), BUTTON_SIZE.height() + 4); //预留4pix给阴影 m_gridlayout1->addWidget(widget, desc1->row, desc1->column, desc1->rowcount, desc1->columncount, Qt::AlignCenter/* | Qt::AlignTop*/); const QPair hashValue1(pagebutton, desc1); m_keys1.insert(desc1->button, hashValue1); //key为枚举值,value.first为DPushButton *, value.second为const KeyDescription1 * connect(pagebutton, &DPushButton::clicked, m_mapper, static_cast(&QSignalMapper::map)); connect(static_cast(pagebutton), &TextButton::space, this, [ = ]() { Buttons spacekey = m_keys1.key(hashValue1); emit buttonPressedbySpace(spacekey); }); m_mapper->setMapping(pagebutton, desc1->button); //多个按钮绑定到一个mapper上 } /** * @brief 切换相应主题切图 */ void ScientificKeyPad::buttonThemeChanged(int type) { m_themetype = type; QString path; if (type == 2) { path = QString(":/assets/images/%1/").arg("dark"); m_leftBracket->setStyleSheet(QString("font-family:Noto Sans;color:white;font-size:14px;")); m_rightBracket->setStyleSheet(QString("font-family:Noto Sans;color:white;font-size:14px;")); } else { path = QString(":/assets/images/%1/").arg("light"); m_leftBracket->setStyleSheet(QString("font-family:Noto Sans;color:black;font-size:14px;")); m_rightBracket->setStyleSheet(QString("font-family:Noto Sans;color:black;font-size:14px;")); } IconButton *btn = static_cast(button(Key_Div)); btn->setIconUrl(path + "divide_normal.svg", path + "divide_hover.svg", path + "divide_press.svg"); btn = static_cast(button(Key_Mult)); btn->setIconUrl(path + "x_normal.svg", path + "x_hover.svg", path + "x_press.svg"); btn = static_cast(button(Key_Min)); btn->setIconUrl(path + "-_normal.svg", path + "-_hover.svg", path + "-_press.svg"); btn = static_cast(button(Key_Plus)); btn->setIconUrl(path + "+_normal.svg", path + "+_hover.svg", path + "+_press.svg"); btn = static_cast(button(Key_Backspace)); btn->setIconUrl(path + "clear_normal.svg", path + "clear_hover.svg", path + "clear_press.svg", 1); btn = static_cast(button(Key_sqrt2)); btn->setIconUrl(path + "squareroot_normal.svg", path + "squareroot_hover.svg", path + "squareroot_press.svg", 3); btn = static_cast(button(Key_sqrt3)); btn->setIconUrl(path + "cuberoot_normal.svg", path + "cuberoot_hover.svg", path + "cuberoot_press.svg", 3); btn = static_cast(button(Key_ysqrtx)); btn->setIconUrl(path + "yroot_normal.svg", path + "yroot_hover.svg", path + "yroot_press.svg", 3); if (m_deg == 1) { btn = static_cast(button(Key_deg)); btn->setIconUrl(path + "rad_normal.svg", path + "rad_hover.svg", path + "rad_press.svg", 5); } else if (m_deg == 2) { btn = static_cast(button(Key_deg)); btn->setIconUrl(path + "grad_normal.svg", path + "grad_hover.svg", path + "grad_press.svg", 7); } else if (m_deg == 3) { btn = static_cast(button(Key_deg)); btn->setIconUrl(path + "deg_normal.svg", path + "deg_hover.svg", path + "deg_press.svg", 5); } } /** * @brief 点击2nd时切换stackwidget */ void ScientificKeyPad::turnPage(int key) { if (key == Key_page) { if (m_arcsinwidget->currentIndex() == 0) { m_arcsinwidget->setCurrentIndex(1); m_arccoswidget->setCurrentIndex(1); m_arctanwidget->setCurrentIndex(1); m_arccotwidget->setCurrentIndex(1); m_sqrtwidget->setCurrentIndex(1); m_cbrtwidget->setCurrentIndex(1); m_yrootwidget->setCurrentIndex(1); m_2xwidget->setCurrentIndex(1); m_logyxwidget->setCurrentIndex(1); m_exwidget->setCurrentIndex(1); } else { m_arcsinwidget->setCurrentIndex(0); m_arccoswidget->setCurrentIndex(0); m_arctanwidget->setCurrentIndex(0); m_arccotwidget->setCurrentIndex(0); m_sqrtwidget->setCurrentIndex(0); m_cbrtwidget->setCurrentIndex(0); m_yrootwidget->setCurrentIndex(0); m_2xwidget->setCurrentIndex(0); m_logyxwidget->setCurrentIndex(0); m_exwidget->setCurrentIndex(0); } } } /** * @brief ScientificKeyPad::getdeg * @param deg 当前为deg/rad/grad * 切换deg按键图标 */ void ScientificKeyPad::getdeg(int deg) { m_deg = deg; QString path; if (m_themetype == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); IconButton *btn; //m_deg == 1,点击后为rad if (m_deg == 1) { btn = static_cast(button(Key_deg)); QTimer::singleShot(100, this, [ = ] { //延迟出focus按下动画效果 btn->setIconUrl(path + "rad_normal.svg", path + "rad_hover.svg", path + "rad_press.svg", 5); btn->update(); }); } else if (m_deg == 2) { btn = static_cast(button(Key_deg)); QTimer::singleShot(100, this, [ = ] { btn->setIconUrl(path + "grad_normal.svg", path + "grad_hover.svg", path + "grad_press.svg", 7); btn->update(); }); } else if (m_deg == 3) { btn = static_cast(button(Key_deg)); QTimer::singleShot(100, this, [ = ] { btn->setIconUrl(path + "deg_normal.svg", path + "deg_hover.svg", path + "deg_press.svg", 5); btn->update(); }); } } /** * @brief ScientificKeyPad::bracketsNum * @param direction 0-左括号, 1-右括号 * @param num 不匹配括号数 * 显示左右括号不匹配数 */ void ScientificKeyPad::bracketsNum(int direction, QString num) { if (num == "0") num = ""; if (direction == 0) m_leftBracket->setText(num); else if (direction == 1) m_rightBracket->setText(num); } /** * @brief 获取button上下左右键信号setfocus * @param direction 0-上 1-下 2-左 3-右 */ void ScientificKeyPad::getFocus(int direction) { QHashIterator> i(m_keys); bool ihasfocus = false; //i是否有focus按钮 int number = -1; //记录focus的Buttons while (i.hasNext()) { i.next(); if (i.value().first->hasFocus()) { ihasfocus = true; number = i.key(); break; //获取焦点按钮 } } if (ihasfocus == false) { QHashIterator> i1(m_keys1); while (i1.hasNext()) { i1.next(); if (i1.value().first->hasFocus()) { ihasfocus = true; number = i1.key(); break; //获取焦点按钮 } } } if (number == -1) return; if (m_arcsinwidget->currentIndex() == 0) { switch (direction) { case 0: if (number / 6 > 0) button(static_cast(number - 6))->setFocus(); //根据上下左右信号重置焦点 break; case 1: if (number / 6 < 6) button(static_cast(number + 6))->setFocus(); break; case 2: if (number % 6 > 0) button(static_cast(number - 1))->setFocus(); break; case 3: if (number % 6 < 5) button(static_cast(number + 1))->setFocus(); break; default: break; } } else { switch (direction) { case 0: if (number == Key_arcsin) //focus在arcsin button(Key_deg)->setFocus(); else if (number == Key_sqrt2) button(Key_page)->setFocus(); else if (number == Key_Modulus) button(Key_arccot)->setFocus(); else if (number >= 42 && number <= 51) //focus在剩余第二页界面 button(static_cast(number - 1))->setFocus(); else if (number / 6 > 0) button(static_cast(number - 6))->setFocus(); //根据上下左右信号重置焦点 break; case 1: if (number == Key_deg) //focus在deg button(Key_arcsin)->setFocus(); else if (number == Key_page) button(Key_sqrt2)->setFocus(); else if (number == Key_arccot) button(Key_Modulus)->setFocus(); else if (number >= 42 && number < 51) //focus在剩余第二页界面 button(static_cast(number + 1))->setFocus(); else if (number / 6 < 6) button(static_cast(number + 6))->setFocus(); break; case 2: if (number == Key_logyx) //focus在logyx button(Key_Modulus)->setFocus(); else if (number == Key_ex) button(Key_Rand)->setFocus(); else if (number >= 46 && number <= 51) //二行以下第二列 button(static_cast(number - 4))->setFocus(); else if (number < 42 && number / 6 > 0 && number % 6 == 2) //二行以下第三列 button(static_cast(number + 13 + 5 * (6 - number / 6)))->setFocus(); else if (number < 42 && number % 6 > 0) button(static_cast(number - 1))->setFocus(); break; case 3: if (number == Key_Modulus) //focus在logyx button(Key_logyx)->setFocus(); else if (number == Key_Rand) button(Key_ex)->setFocus(); else if (number >= 42 && number <= 45) //二行以下第一列 button(static_cast(number + 4))->setFocus(); else if (number >= 46 && number <= 51) //二行以下第二列 button(static_cast(number - 13 - 5 * (51 - number)))->setFocus(); else if (number < 42 && number % 6 < 5) button(static_cast(number + 1))->setFocus(); break; default: break; } } } deepin-calculator-5.7.21/src/control/scientifickeypad.h000066400000000000000000000105261423020056600231410ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include "textbutton.h" #include "iconbutton.h" #include "equalbutton.h" #include "memorybutton.h" #include #include #include #include #include #include #include #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE /** * @brief 科学模式键盘区域界面 */ class ScientificKeyPad : public DWidget { Q_OBJECT public: /** * @brief 科学模式键盘 */ enum Buttons { Key_deg, Key_page, Key_PI, Key_e, Key_Mod, Key_Backspace, //deg, 2ⁿᵈ, π, e, mod, 退格符 Key_sin, Key_x2, Key_Derivative, Key_Factorials, Key_exp, Key_Clear, //sin, x², 1/x, x!, exp, C Key_cos, Key_x3, Key_left, Key_right, Key_Percent, Key_Div, //cos, x³, (, ), %, 除号 Key_tan, Key_xy, Key_7, Key_8, Key_9, Key_Mult, //tan, xʸ, 7, 8, 9, 乘号 Key_cot, Key_10x, Key_4, Key_5, Key_6, Key_Min, //cot, 10ˣ, 4, 5, 6, 减号 Key_Modulus, Key_log, Key_1, Key_2, Key_3, Key_Plus, //|x|, log, 1, 2, 3, 加号 Key_Rand, Key_ln, Key_opposite, Key_0, Key_Point, Key_Equals, //随机数, ln, +/-, 0, ., = Key_arcsin, Key_arccos, Key_arctan, Key_arccot, //arcsin, arccos, arctan, arccot Key_sqrt2, Key_sqrt3, Key_ysqrtx, Key_2x, Key_logyx, Key_ex //√x, ³√x, ʸ√x, 2ˣ, logᵧx, eˣ }; explicit ScientificKeyPad(QWidget *parent = nullptr); ~ScientificKeyPad() override; void mouseMoveEvent(QMouseEvent *e) override; DPushButton *button(Buttons key); DPushButton *button(int key); void animate(Buttons key, bool isspace = false); bool buttonHasFocus(); //科学模式第一页 static const struct KeyDescription { QString text; //按钮text Buttons button; //按钮枚举值名 int row; //行 int column; //列 int rowcount; //所占行数 int columncount; //所占列数 } keyDescriptions[]; //科学模式第二页 static const struct KeyDescription1 { QString text; //按钮text Buttons button; //按钮枚举值名 int row; //行 int column; //列 int rowcount; //所占行数 int columncount; //所占列数 } keyDescriptions1[]; public slots: void initButtons(); void buttonThemeChanged(int type); void turnPage(int key); void getdeg(int deg); void bracketsNum(int direction, QString num); //direction 0-左括号 1-右括号 void getFocus(int); signals: void buttonPressed(int); void buttonPressedbySpace(int); private: void initUI(); void initStackWidget(QStackedWidget *widget, DPushButton *button, DPushButton *pagebutton, const KeyDescription1 *desc); private: QGridLayout *m_gridlayout1; QSignalMapper *m_mapper; DLabel *m_leftBracket; //存放左括号不匹配数 DLabel *m_rightBracket; //存放右括号不匹配数 QHash> m_keys; QHash> m_keys1; QPoint m_mousepoint; int m_themetype; int m_deg = 3; //1-deg 2-rad 3-grad QStackedWidget *m_arcsinwidget; QStackedWidget *m_arccoswidget; QStackedWidget *m_arctanwidget; QStackedWidget *m_arccotwidget; QStackedWidget *m_sqrtwidget; QStackedWidget *m_cbrtwidget; QStackedWidget *m_yrootwidget; QStackedWidget *m_2xwidget; QStackedWidget *m_logyxwidget; QStackedWidget *m_exwidget; }; deepin-calculator-5.7.21/src/control/textbutton.cpp000066400000000000000000000552141423020056600224010ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "textbutton.h" const qreal BLURRADIUS = 12; //阴影模糊半径 const qreal ROUND_XRADIUS = 8; //按钮圆角x轴半径 const qreal ROUND_YRADIUS = 8; //按钮圆角y轴半径 TextButton::TextButton(const QString &text, bool page, QWidget *parent) : DPushButton(text, parent) , m_effect(new QGraphicsDropShadowEffect(this)) { setFocusPolicy(Qt::TabFocus); setObjectName("TextButton"); init(); m_isHover = m_isPress = false; m_page = page; m_effect->setOffset(0, 4); //阴影偏移 m_effect->setBlurRadius(BLURRADIUS); //阴影模糊半径 } TextButton::~TextButton() { // delete m_effect; } void TextButton::init() { //按钮初始化时确认当前是否是上标按钮 if (text() == "2ⁿᵈ") { m_btn = 1; } else if (text() == "xʸ") { m_btn = 2; } else if (text() == "10ˣ") { m_btn = 3; } else if (text() == "2ˣ") { m_btn = 4; } else if (text() == "eˣ") { m_btn = 5; } else if (text() == "arcsin") { m_btn = 6; } else if (text() == "arccos") { m_btn = 7; } else if (text() == "arctan") { m_btn = 8; } else if (text() == "arccot") { m_btn = 9; } if (text() == "Rand") m_font.setPixelSize(15); else if (text() == "logᵧx") { m_font.setPixelSize(14); } else if (text() == "log") { m_font.setPixelSize(16); } else if (text() == "|x|") { m_font.setPixelSize(14); } else if (text() == "Mod") { m_font.setPixelSize(14); } else if (text() == "exp") { m_font.setPixelSize(16); } else if (text() == "sin") { m_font.setPixelSize(16); } else if (text() == "cos") { m_font.setPixelSize(16); } else if (text() == "tan") { m_font.setPixelSize(16); } else if (text() == "cot") { m_font.setPixelSize(16); } else if (text() == "+/-") { m_font.setPixelSize(20); } else if (text() == "QWORD" || text() == "DWORD" || text() == "WORD" || text() == "BYTE" || text() == "AND" || text() == "OR" || text() == "NOT" || text() == "NAND" || text() == "NOR" || text() == "XOR") { m_font.setPixelSize(14); } else if (text() == "A" || text() == "B" || text() == "C" || text() == "D" || text() == "E" || text() == "F") { m_font.setPixelSize(17); } else m_font.setPixelSize(18); m_font.setFamily("Noto Sans"); m_font.setStyleName("Light"); m_font.setWeight(2); } /** * @brief iconbutton物理键盘点击动画效果 * @param msec 100ms */ void TextButton::animate(bool isspace, int msec) { if (m_isPress == false) { //edit for bug-20492 20200416 m_isHover = false; //edit for bug-20508 20200414 if (!isspace) setDown(true); m_isPress = true; QTimer::singleShot(msec, this, [ = ] { if (!isspace) setDown(false); m_isPress = false; update(); }); } } /** * @brief 判断FE与2nd按键是否被按下 */ void TextButton::setButtonDown(bool down) { m_Btnisdown = down; update(); } /** * @brief TextButton::setBtnPressing * 用于数据长度和移位类型的按键,点开列表后,保持press的状态 */ void TextButton::setBtnPressing(bool press) { if (press) { m_palette = this->palette(); m_font.setPixelSize(14); m_isPress = true; m_isHover = false; //20200722删除foucus状态 } else { m_isPress = false; } } void TextButton::setButtonGray(bool gray) { // m_isgray = gray; this->setEnabled(!gray); update(); } /** * @brief 鼠标按下 */ void TextButton::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) return; // setFocus(); m_palette = this->palette(); m_isPress = true; m_isHover = false; //20200722删除foucus状态 DPushButton::mousePressEvent(e); } /** * @brief 鼠标松开 */ void TextButton::mouseReleaseEvent(QMouseEvent *e) { // clearFocus(); if (e->button() == Qt::RightButton) return; this->setPalette(m_palette); m_isPress = false; if (this->rect().contains(e->pos())) { m_isacting = true; m_isHover = true; } else m_isacting = false; emit mouseRelease(); DPushButton::mouseReleaseEvent(e); } void TextButton::enterEvent(QEvent *e) { if (text() == "Rand") m_font.setPixelSize(17); else if (text() == "logᵧx") { m_font.setPixelSize(16); } else if (text() == "log") { m_font.setPixelSize(18); } else if (text() == "|x|") { m_font.setPixelSize(16); } else if (text() == "Mod") { m_font.setPixelSize(16); } else if (text() == "exp") { m_font.setPixelSize(18); } else if (text() == "sin") { m_font.setPixelSize(18); } else if (text() == "cos") { m_font.setPixelSize(18); } else if (text() == "tan") { m_font.setPixelSize(18); } else if (text() == "cot") { m_font.setPixelSize(18); } else if (text() == "+/-") { m_font.setPixelSize(22); } else if (text() == "QWORD" || text() == "DWORD" || text() == "WORD" || text() == "BYTE" || text() == "AND" || text() == "OR" || text() == "NOT" || text() == "NAND" || text() == "NOR" || text() == "XOR") { m_font.setPixelSize(16); } else if (text() == "A" || text() == "B" || text() == "C" || text() == "D" || text() == "E" || text() == "F") { m_font.setPixelSize(19); } else if (text() == "arcsin" || text() == "arccos" || text() == "arctan" || text() == "arccot") { m_font.setPixelSize(18); } else m_font.setPixelSize(20); m_font.setStyleName(""); m_isHover = true; DPushButton::enterEvent(e); } void TextButton::leaveEvent(QEvent *e) { if (text() == "Rand") m_font.setPixelSize(15); else if (text() == "logᵧx") { m_font.setPixelSize(14); } else if (text() == "log") { m_font.setPixelSize(16); } else if (text() == "|x|") { m_font.setPixelSize(14); } else if (text() == "Mod") { m_font.setPixelSize(14); } else if (text() == "exp") { m_font.setPixelSize(16); } else if (text() == "sin") { m_font.setPixelSize(16); } else if (text() == "cos") { m_font.setPixelSize(16); } else if (text() == "tan") { m_font.setPixelSize(16); } else if (text() == "cot") { m_font.setPixelSize(16); } else if (text() == "+/-") { m_font.setPixelSize(20); } else if (text() == "QWORD" || text() == "DWORD" || text() == "WORD" || text() == "BYTE" || text() == "AND" || text() == "OR" || text() == "NOT" || text() == "NAND" || text() == "NOR" || text() == "XOR") { m_font.setPixelSize(14); } else if (text() == "A" || text() == "B" || text() == "C" || text() == "D" || text() == "E" || text() == "F") { m_font.setPixelSize(17); } else if (text() == "arcsin" || text() == "arccos" || text() == "arctan" || text() == "arccot") { m_font.setPixelSize(16); } else m_font.setPixelSize(18); m_font.setStyleName("Light"); m_isHover = false; m_isacting = false; DPushButton::leaveEvent(e); } void TextButton::paintEvent(QPaintEvent *e) { Q_UNUSED(e); if (isEnabled() == false) { m_font.setPixelSize(18); m_font.setStyleName("Light"); m_isHover = false; m_isgray = true; } else { m_isgray = false; } QRectF rect = this->rect(); QRectF normal(rect.left() + 1, rect.top() + 1, rect.width() - 2, rect.height() - 2); QRectF hover(rect.left() + 1, rect.top() + 1, rect.width() - 2, rect.height() - 2); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); //反锯齿 painter.setRenderHint(QPainter::SmoothPixmapTransform, true); //光滑的象素映射变换算法 painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setFont(m_font); QRectF textRect = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, this->text()); QColor actcolor = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name();//活动色 QColor pressBrush, focus, hoverFrame, base, text, hoverbrush; QColor hoverShadow, focusShadow; QColor pressText = actcolor; hoverShadow = actcolor; hoverShadow.setAlphaF(0.1); focusShadow = QColor(0, 0, 0); focusShadow.setAlphaF(0.05); int type = DGuiApplicationHelper::instance()->themeType(); if (type == 1) { //浅色主题设置 pressBrush = QColor(0, 0, 0); pressBrush.setAlphaF(0.1); focus = actcolor; hoverFrame = actcolor; hoverFrame.setAlphaF(0.2); if (m_page) { base = QColor(238, 238, 238); hoverbrush = QColor(238, 238, 238); } else { base = QColor("#FFFFFF"); hoverbrush = QColor("#FFFFFF"); } text = QColor("#303030"); if (m_isgray == true) { base = QColor("#FFFFFF"); hoverbrush = QColor("#FFFFFF"); text = QColor("#303030"); text.setAlphaF(0.4); pressBrush = QColor("#FFFFFF"); } } else { //深色主题设置 pressBrush = QColor(0, 0, 0); pressBrush.setAlphaF(0.5); focus = actcolor; hoverFrame = actcolor; hoverFrame.setAlphaF(0.2); if (m_page) { base = QColor(60, 60, 60); hoverbrush = QColor(60, 60, 60); } else { base = QColor("#303030"); hoverbrush = QColor(60, 60, 60); } if (m_isHover) text = Qt::white; else text = QColor(224, 224, 224); if (m_isgray == true) { base = QColor(48, 48, 48); base.setAlphaF(0.4); text = QColor(224, 224, 224); text.setAlphaF(0.4); pressText = Qt::black; pressBrush = QColor("#FFFFFF"); hoverbrush = QColor(48, 48, 48); hoverbrush.setAlphaF(0.4); } } if (m_Btnisdown) text = actcolor; //FE,2nd设置 if (hasFocus()) { painter.setPen(Qt::NoPen); if (m_isPress) { painter.setBrush(QBrush(pressBrush)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(pressText); painter.setPen(pen); pen.setColor(focus); pen.setWidth(2); painter.setPen(pen); painter.setBrush(Qt::NoBrush); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //focus边框 paintspecialbtn(painter, rect, textRect); } else { painter.setPen(Qt::NoPen); painter.setBrush(QBrush(base)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; // if (m_isacting) { // painter.setPen(Qt::NoPen); // } else { pen.setColor(focus); pen.setWidth(2); painter.setPen(pen); // } painter.setBrush(Qt::NoBrush); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 pen.setColor(text); painter.setPen(pen); painter.setFont(m_font); paintspecialbtn(painter, rect, textRect); m_effect->setColor(focusShadow); this->setGraphicsEffect(m_effect); } } else { painter.setPen(Qt::NoPen); if (m_isHover) { //hover状态 painter.setPen(QPen(hoverFrame)); painter.setBrush(QBrush(hoverbrush)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(text); painter.setPen(pen); paintspecialbtn(painter, rect, textRect); m_effect->setColor(hoverShadow); this->setGraphicsEffect(m_effect); } else if (m_isPress) { //press状态 painter.setBrush(QBrush(pressBrush)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(pressText); painter.setPen(pen); paintspecialbtn(painter, rect, textRect); } else { //normal状态 painter.setBrush(QBrush(base)); painter.drawRoundedRect(normal, ROUND_XRADIUS, ROUND_YRADIUS); //圆角半径单位为像素 QPen pen; pen.setColor(text); painter.setPen(pen); paintspecialbtn(painter, rect, textRect); m_effect->setColor(QColor(0, 0, 0, 0)); this->setGraphicsEffect(m_effect); } } } void TextButton::focusOutEvent(QFocusEvent *e) { QPushButton::focusOutEvent(e); } void TextButton::keyPressEvent(QKeyEvent *e) { switch (e->key()) { case Qt::Key_Up: emit focus(0); break; case Qt::Key_Down: emit focus(1); break; case Qt::Key_Left: emit focus(2); break; case Qt::Key_Right: emit focus(3); break; case Qt::Key_Space: emit space(); break; default: DPushButton::keyPressEvent(e); break; } } /** * @brief 绘制有上标的按钮 * @param painter * @param rect 按钮rect * @param textRect 字体rect */ void TextButton::paintspecialbtn(QPainter &painter, QRectF rect, QRectF textRect) { painter.save(); int powersize = 10; //次方字体大小 int trisize = 16; //三角函数字体大小 int vpadding = 0; //纵向微调距 if (!hasFocus() && (m_isHover || m_isPress)) { powersize = 12; trisize = 18; } if (m_btn == 1) { vpadding = -1; QRectF textRect1 = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, "2ⁿ"); painter.setFont(m_font); painter.drawText(textRect1, "2"); QFont a; a.setPixelSize(powersize); if (!hasFocus() && (m_isHover || m_isPress)) { a.setPixelSize(11); vpadding = 0; } QRectF textRect2 = painter.fontMetrics().boundingRect(int(rect.width()) / 2, int(rect.height() / 4 - vpadding), int(rect.width()) / 2, int(rect.height() / 2), Qt::AlignLeft, "nd"); a.setFamily("Noto Sans"); painter.setFont(a); painter.drawText(textRect2, "nd"); } else if (m_btn == 2) { vpadding = 2; if (!hasFocus() && (m_isHover || m_isPress)) { vpadding = 4; } QRectF textRect1 = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, "xʸ"); painter.setFont(m_font); painter.drawText(textRect1, "x"); QRectF textRect2 = painter.fontMetrics().boundingRect(int(rect.width()) / 2 + 2, int(rect.height() / 4 - vpadding), int(rect.width()) / 2, int(rect.height() / 2), Qt::AlignLeft, "y"); QFont a; a.setPixelSize(powersize); a.setFamily("Noto Sans"); painter.setFont(a); painter.drawText(textRect2, "y"); } else if (m_btn == 3) { vpadding = 2; if (!hasFocus() && (m_isHover || m_isPress)) { vpadding = 4; } QRectF textRect1 = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, "10ˣ"); painter.setFont(m_font); painter.drawText(textRect1, "10"); QRectF textRect2 = painter.fontMetrics().boundingRect(int(rect.width()) / 2 + 8, int(rect.height() / 4 - vpadding), int(rect.width()) / 2, int(rect.height() / 2), Qt::AlignLeft, "x"); QFont a; a.setPixelSize(powersize); a.setFamily("Noto Sans"); painter.setFont(a); painter.drawText(textRect2, "x"); } else if (m_btn == 4) { vpadding = 2; if (!hasFocus() && (m_isHover || m_isPress)) { vpadding = 4; } QRectF textRect1 = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, "2ˣ"); painter.setFont(m_font); painter.drawText(textRect1, "2"); QRectF textRect2 = painter.fontMetrics().boundingRect(int(rect.width()) / 2 + 2, int(rect.height() / 4 - vpadding), int(rect.width()) / 2, int(rect.height() / 2), Qt::AlignLeft, "x"); QFont a; a.setPixelSize(powersize); a.setFamily("Noto Sans"); painter.setFont(a); painter.drawText(textRect2, "x"); } else if (m_btn == 5) { vpadding = 2; if (!hasFocus() && (m_isHover || m_isPress)) { vpadding = 4; } QRectF textRect1 = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, "eˣ"); painter.setFont(m_font); painter.drawText(textRect1, "e"); QRectF textRect2 = painter.fontMetrics().boundingRect(int(rect.width()) / 2 + 2, int(rect.height() / 4 - vpadding), int(rect.width()) / 2, int(rect.height() / 2), Qt::AlignLeft, "x"); QFont a; a.setPixelSize(powersize); a.setFamily("Noto Sans"); painter.setFont(a); painter.drawText(textRect2, "x"); } else if (m_btn == 6) { vpadding = 2; if (!hasFocus() && (m_isHover || m_isPress)) { vpadding = 4; } QRectF textRect1 = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, "sinˣ"); m_font.setPixelSize(trisize); painter.setFont(m_font); painter.drawText(textRect1, "sin"); QRectF textRect2 = painter.fontMetrics().boundingRect(int(rect.width()) / 2 + 8, int(rect.height() / 4 - vpadding), int(rect.width()) / 2, int(rect.height() / 2), Qt::AlignLeft, "-1"); QFont a; a.setPixelSize(powersize); a.setFamily("Noto Sans"); painter.setFont(a); painter.drawText(textRect2, "-1"); } else if (m_btn == 7) { vpadding = 2; if (!hasFocus() && (m_isHover || m_isPress)) { vpadding = 4; } QRectF textRect1 = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, "cosˣ"); m_font.setPixelSize(trisize); painter.setFont(m_font); painter.drawText(textRect1, "cos"); QRectF textRect2 = painter.fontMetrics().boundingRect(int(rect.width()) / 2 + 8, int(rect.height() / 4 - vpadding), int(rect.width()) / 2, int(rect.height() / 2), Qt::AlignLeft, "-1"); QFont a; a.setPixelSize(powersize); a.setFamily("Noto Sans"); painter.setFont(a); painter.drawText(textRect2, "-1"); } else if (m_btn == 8) { vpadding = 2; if (!hasFocus() && (m_isHover || m_isPress)) { vpadding = 4; } QRectF textRect1 = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, "tanˣ"); m_font.setPixelSize(trisize); painter.setFont(m_font); painter.drawText(textRect1, "tan"); QRectF textRect2 = painter.fontMetrics().boundingRect(int(rect.width()) / 2 + 8, int(rect.height() / 4 - vpadding), int(rect.width()) / 2, int(rect.height() / 2), Qt::AlignLeft, "-1"); QFont a; a.setPixelSize(powersize); a.setFamily("Noto Sans"); painter.setFont(a); painter.drawText(textRect2, "-1"); } else if (m_btn == 9) { vpadding = 2; if (!hasFocus() && (m_isHover || m_isPress)) { vpadding = 4; } QRectF textRect1 = painter.fontMetrics().boundingRect(0, 0, int(rect.width()), int(rect.height()), Qt::AlignCenter, "cotˣ"); m_font.setPixelSize(trisize); painter.setFont(m_font); painter.drawText(textRect1, "cot"); QRectF textRect2 = painter.fontMetrics().boundingRect(int(rect.width()) / 2 + 8, int(rect.height() / 4 - vpadding), int(rect.width()) / 2, int(rect.height() / 2), Qt::AlignLeft, "-1"); QFont a; a.setPixelSize(powersize); a.setFamily("Noto Sans"); painter.setFont(a); painter.drawText(textRect2, "-1"); } else { painter.setFont(m_font); painter.drawText(textRect, this->text()); } painter.restore(); } deepin-calculator-5.7.21/src/control/textbutton.h000066400000000000000000000046661423020056600220530ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef TEXTBUTTON_H #define TEXTBUTTON_H #include #include #include #include #include #include #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE class TextButton : public DPushButton { Q_OBJECT public: TextButton(const QString &text = QString(), bool page = false, QWidget *parent = nullptr); //page-是否是科学计算器中两页中的按钮 ~TextButton() override; void init(); void animate(bool isspace = false, int msec = 100); void setButtonDown(bool down); void setBtnPressing(bool press); void setButtonGray(bool gray); signals: void mouseRelease(); void focus(int direction); //direction 0-上 1-下 2-左 3-右 void space(); public: void mousePressEvent(QMouseEvent *) override; void mouseReleaseEvent(QMouseEvent *) override; void enterEvent(QEvent *) override; void leaveEvent(QEvent *) override; void paintEvent(QPaintEvent *e) override; void focusOutEvent(QFocusEvent *) override; void keyPressEvent(QKeyEvent *e) override; private: void paintspecialbtn(QPainter &painter, QRectF rect, QRectF textRect); private: QGraphicsDropShadowEffect *m_effect; DPalette m_palette; bool m_isHover; bool m_isPress; QFont m_font; bool m_page; //m_page-是否是科学计算器中两页中的按钮 bool m_Btnisdown = false; bool m_isacting = false; //规避鼠标在button内release时出现foucus状态的框 int m_btn = 0; //1-2ⁿᵈ, 2-xʸ, 3-10ˣ, 4-2ˣ, 5-eˣ, 6-arcsin, 7-arccos, 8-arctan, 9-arccot bool m_isgray = false; //置灰按钮 }; #endif deepin-calculator-5.7.21/src/deepin-calculator.qrc000066400000000000000000000252511423020056600220750ustar00rootroot00000000000000 assets/images/dark/-_hover.svg assets/images/dark/-_normal.svg assets/images/dark/-_press.svg assets/images/dark/( )_hover.svg assets/images/dark/( )_normal.svg assets/images/dark/( )_press.svg assets/images/dark/%_hover.svg assets/images/dark/%_normal.svg assets/images/dark/%_press.svg assets/images/dark/+_hover.svg assets/images/dark/+_normal.svg assets/images/dark/+_press.svg assets/images/dark/AC_hover.svg assets/images/dark/AC_normal.svg assets/images/dark/AC_press.svg assets/images/dark/clear_hover.svg assets/images/dark/clear_normal.svg assets/images/dark/clear_press.svg assets/images/dark/divide_hover.svg assets/images/dark/divide_normal.svg assets/images/dark/divide_press.svg assets/images/dark/empty_hover.svg assets/images/dark/empty_normal.svg assets/images/dark/empty_press.svg assets/images/dark/x_hover.svg assets/images/dark/x_normal.svg assets/images/dark/x_press.svg assets/images/light/-_hover.svg assets/images/light/-_normal.svg assets/images/light/-_press.svg assets/images/light/( )_hover.svg assets/images/light/( )_normal.svg assets/images/light/( )_press.svg assets/images/light/%_hover.svg assets/images/light/%_normal.svg assets/images/light/%_press.svg assets/images/light/+_hover.svg assets/images/light/+_normal.svg assets/images/light/+_press.svg assets/images/light/clear_hover.svg assets/images/light/clear_normal.svg assets/images/light/clear_press.svg assets/images/light/divide_hover.svg assets/images/light/divide_normal.svg assets/images/light/divide_press.svg assets/images/light/empty_hover.svg assets/images/light/empty_normal.svg assets/images/light/empty_press.svg assets/images/light/x_hover.svg assets/images/light/x_normal.svg assets/images/light/x_press.svg assets/images/deepin-calculator.svg assets/images/delete_dark_hover.svg assets/images/delete_dark_normal.svg assets/images/delete_dark_press.svg assets/images/delete_light_hover.svg assets/images/delete_light_normal.svg assets/images/delete_light_press.svg assets/images/div_normal.svg assets/images/min_normal.svg assets/images/mult_normal.svg assets/images/plus_normal.svg assets/images/title_icon.svg assets/qss/dark.qss assets/qss/light.qss assets/images/light/squareroot_hover.svg assets/images/light/squareroot_normal.svg assets/images/light/squareroot_press.svg assets/images/light/cuberoot_hover.svg assets/images/light/cuberoot_normal.svg assets/images/light/cuberoot_press.svg assets/images/light/yroot_hover.svg assets/images/light/yroot_normal.svg assets/images/light/yroot_press.svg assets/images/dark/yroot_hover.svg assets/images/dark/yroot_normal.svg assets/images/dark/yroot_press.svg assets/images/dark/squareroot_hover.svg assets/images/dark/squareroot_normal.svg assets/images/dark/squareroot_press.svg assets/images/dark/cuberoot_hover.svg assets/images/dark/cuberoot_normal.svg assets/images/dark/cuberoot_press.svg assets/images/dark/memory_hover.svg assets/images/dark/memory_normal.svg assets/images/dark/memory_press.svg assets/images/light/memory_hover.svg assets/images/light/memory_normal.svg assets/images/light/memory_press.svg assets/images/light/sin-1_hover.svg assets/images/light/sin-1_normal.svg assets/images/light/sin-1_press.svg assets/images/light/tan-1_hover.svg assets/images/light/tan-1_normal.svg assets/images/light/tan-1_press.svg assets/images/light/cos-1_hover.svg assets/images/light/cos-1_normal.svg assets/images/light/cos-1_press.svg assets/images/light/cot-1_hover.svg assets/images/light/cot-1_normal.svg assets/images/light/cot-1_press.svg assets/images/dark/cos-1_hover.svg assets/images/dark/cos-1_normal.svg assets/images/dark/cos-1_press.svg assets/images/dark/cot-1_hover.svg assets/images/dark/cot-1_normal.svg assets/images/dark/cot-1_press.svg assets/images/dark/tan-1_hover.svg assets/images/dark/tan-1_normal.svg assets/images/dark/tan-1_press.svg assets/images/dark/sin-1_hover.svg assets/images/dark/sin-1_normal.svg assets/images/dark/sin-1_press.svg assets/images/light/deg_hover.svg assets/images/light/deg_normal.svg assets/images/light/deg_press.svg assets/images/light/grad_hover.svg assets/images/light/grad_normal.svg assets/images/light/grad_press.svg assets/images/light/rad_hover.svg assets/images/light/rad_normal.svg assets/images/light/rad_press.svg assets/images/dark/grad_hover.svg assets/images/dark/grad_normal.svg assets/images/dark/grad_press.svg assets/images/dark/rad_hover.svg assets/images/dark/rad_normal.svg assets/images/dark/rad_press.svg assets/images/dark/deg_hover.svg assets/images/dark/deg_normal.svg assets/images/dark/deg_press.svg assets/images/dark/icon_history_checked.svg assets/images/dark/icon_history_normal.svg assets/images/dark/icon_memory_checked.svg assets/images/dark/icon_memory_normal.svg assets/images/light/icon_history_checked.svg assets/images/light/icon_history_normal.svg assets/images/light/icon_memory_checked.svg assets/images/light/icon_memory_normal.svg assets/images/light/icon_binarysystem_hover.svg assets/images/light/icon_binarysystem_normal.svg assets/images/light/icon_generalkeyboard_hover.svg assets/images/light/icon_generalkeyboard_normal.svg assets/images/light/icon_rc_hover.svg assets/images/light/icon_rc_normal.svg assets/images/dark/icon_binarysystem_hover.svg assets/images/dark/icon_rc_normal.svg assets/images/dark/icon_rc_hover.svg assets/images/dark/icon_generalkeyboard_normal.svg assets/images/dark/icon_generalkeyboard_hover.svg assets/images/dark/icon_binarysystem_normal.svg assets/images/light/icon_as_hover.svg assets/images/light/icon_as_normal.svg assets/images/light/icon_ls_hover.svg assets/images/light/icon_ls_normal.svg assets/images/light/icon_ro_hover.svg assets/images/light/icon_ro_normal.svg assets/images/light/icon_as_menuhover.svg assets/images/light/icon_ls_menuhover.svg assets/images/light/icon_ro_menuhover.svg assets/images/light/icon_rc_menuhover.svg assets/images/dark/icon_as_hover.svg assets/images/dark/icon_as_normal.svg assets/images/dark/icon_ls_hover.svg assets/images/dark/icon_ls_normal.svg assets/images/dark/icon_ro_hover.svg assets/images/dark/icon_ro_normal.svg assets/images/light/icon_binarysystem_press.svg assets/images/light/icon_generalkeyboard_press.svg assets/images/dark/icon_binarysystem_press.svg assets/images/dark/icon_generalkeyboard_press.svg assets/images/light/icon_as_iconhover.svg assets/images/light/icon_ls_iconhover.svg assets/images/light/icon_ro_iconhover.svg assets/images/light/icon_rc_iconhover.svg assets/images/light/icon_as_iconnormal.svg assets/images/light/icon_ls_iconnormal.svg assets/images/light/icon_ro_iconnormal.svg assets/images/light/icon_rc_iconnormal.svg assets/images/dark/icon_as_iconhover.svg assets/images/dark/icon_ls_iconhover.svg assets/images/dark/icon_ro_iconhover.svg assets/images/dark/icon_rc_iconhover.svg assets/images/dark/icon_as_iconnormal.svg assets/images/dark/icon_ls_iconnormal.svg assets/images/dark/icon_ro_iconnormal.svg assets/images/dark/icon_rc_iconnormal.svg deepin-calculator-5.7.21/src/dsettings.cpp000066400000000000000000000125771423020056600205120ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "dsettings.h" #include #include #include #include #include "utils.h" DWIDGET_USE_NAMESPACE static DSettingsAlt *INSTANCE = nullptr; /** * @brief 初始化 */ DSettingsAlt *DSettingsAlt::instance() { if (!INSTANCE) { INSTANCE = new DSettingsAlt(); qAddPostRoutine(deleteInstance); } return INSTANCE; } /** * @brief 相关信息保存在config.config文件中 */ DSettingsAlt::DSettingsAlt(QObject *parent) : QObject(parent), m_settings(new QSettings(QDir(Utils::getConfigDir()).filePath("config.config"), QSettings::IniFormat, this)) { initConfig(); loadConfig(); } DSettingsAlt::~DSettingsAlt() { // delete m_settings; //saveConfig(); } void DSettingsAlt::loadConfig() { m_standardSeparate = m_settings->value("standardSeparate", 3).toInt(); //默认3位 m_scientificSeparate = m_settings->value("scientificSeparate", 3).toInt(); m_programmerSeparate = m_settings->value("programmerSeparate", 3).toInt(); } void DSettingsAlt::saveConfig() { m_settings->setValue("standardSeparate", m_standardSeparate); m_settings->setValue("scientificSeparate", m_scientificSeparate); m_settings->setValue("programmerSeparate", m_programmerSeparate); } void DSettingsAlt::initConfig() { if (m_settings->value("theme").toString().isEmpty()) { setOption("theme", "light"); //主题初始化为浅色 } if (m_settings->value("mode").toString().isEmpty()) { setOption("mode", 0); //模式初始化为标准模式 } if (m_settings->value("history").toString().isEmpty()) { setOption("history", 0); //历史记录初始化关闭 } if (m_settings->value("windowX").toString().isEmpty()) { setOption("windowX", 0); //保存当前打开位置x } if (m_settings->value("windowY").toString().isEmpty()) { setOption("windowY", 0); //保存当前打开位置y } if (m_settings->value("windowWidth").toString().isEmpty()) { setOption("windowWidth", 0); //保存窗口width } if (m_settings->value("windowHeight").toString().isEmpty()) { setOption("windowHeight", 0); //保存窗口height } } /** * @brief 获取相关参数 */ QVariant DSettingsAlt::getOption(const QString &key) { return m_settings->value(key); } /** * @brief 以相关键值保存参数 * @param key 键 * @param value 值 */ void DSettingsAlt::setOption(const QString &key, const QVariant &value) { m_settings->setValue(key, value); } void DSettingsAlt::deleteInstance() { delete INSTANCE; INSTANCE = nullptr; } /** * @brief DSettingsAlt::getSeparate * @return 根据配置文件中的计算器类型返回相应的计算器分隔位数 */ int DSettingsAlt::getSeparate() { int separate = 3; //数字分割位数 switch (m_settings->value("mode", 0).toInt()) { case 0: separate = getStandardSeparate(); break; case 1: separate = getScientificSeparate(); break; case 2: separate = getProgrammerSeparate(); break; } //间隔位数小于1时转为3,防止发生一些意外情况 if (separate < 1) { separate = 3; } return separate; } /** * @brief DSettingsAlt::setSeparate * 根据配置文件中的计算器类型设置相应的计算器分隔位数 * @param separate 间隔位数 */ void DSettingsAlt::setSeparate(int separate) { switch (m_settings->value("mode", 0).toInt()) { case 0: setStandardSeparate(separate); break; case 1: setScientificSeparate(separate); break; case 2: setProgrammerSeparate(separate); break; } saveConfig(); } /** * @brief getStandardSeparate * 获取标准计算器分隔位数 * @return 标准计算器分隔位数 */ int DSettingsAlt::getStandardSeparate() { return m_standardSeparate; } /** * @brief setStandardSeparate * 设置标准计算器分隔位数 */ void DSettingsAlt::setStandardSeparate(int separate) { this->m_standardSeparate = separate; } /** * @brief getScientificSeparate * 获取科学计算器分隔位数 * @return */ int DSettingsAlt::getScientificSeparate() { return m_scientificSeparate; } /** * @brief setScientificSeparate * 设置科学计算器分隔位数 */ void DSettingsAlt::setScientificSeparate(int separate) { this->m_scientificSeparate = separate; } /** * @brief getProgrammerSeparate * @return 程序员计算器分隔位数 */ int DSettingsAlt::getProgrammerSeparate() { return m_programmerSeparate; } /** * @brief setProgrammerSeparate * 设置程序员计算器分隔位数 */ void DSettingsAlt::setProgrammerSeparate(int separate) { this->m_programmerSeparate = separate; } deepin-calculator-5.7.21/src/dsettings.h000066400000000000000000000041371423020056600201500ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SETTINGS_H #define SETTINGS_H #include #include class DSettingsAlt : public QObject { Q_OBJECT private: explicit DSettingsAlt(QObject *parent = nullptr); ~DSettingsAlt(); public: static DSettingsAlt *instance(); QVariant getOption(const QString &key); void setOption(const QString &key, const QVariant &value); static void deleteInstance(); int getSeparate(); //根据配置文件中的计算器类型自动获取计算器分隔位数 void setSeparate(int separate); //根据配置文件中的计算器类型自动设置相应的计算器分隔位数 int getStandardSeparate(); //获取标准计算器分隔位数 void setStandardSeparate(int separate); //设置标准计算器分隔位数 int getScientificSeparate(); //获取科学计算器分隔位数 void setScientificSeparate(int separate); //设置科学计算器分隔位数 int getProgrammerSeparate(); //获取程序员计算器分隔位数 void setProgrammerSeparate(int separate); //设置程序员计算器分隔位数 private: void initConfig(); void loadConfig(); void saveConfig(); private: QSettings *m_settings; int m_standardSeparate = 3; //标准计算器分隔位数 int m_scientificSeparate = 3; //科学计算器分隔位数 int m_programmerSeparate = 3; //程序员计算器分隔位数 }; #endif deepin-calculator-5.7.21/src/environments.h.in000066400000000000000000000001651423020056600212750ustar00rootroot00000000000000#ifndef __ENVIRONMENTS_H_ #define __ENVIRONMENTS_H_ #define VERSION "@VERSION@" #endif // __ENVIRONMENTS_H_ deepin-calculator-5.7.21/src/globaldefine.h000066400000000000000000000016411423020056600205540ustar00rootroot00000000000000#ifndef GLOBALDEFINE_H #define GLOBALDEFINE_H //中文符号 #define CN_ADD QString::fromUtf8("+") #define CN_MIN QString::fromUtf8("-") #define CN_MUL QString::fromUtf8("×") #define CN_Asterisk QString::fromUtf8("*") #define CN_DIV QString::fromUtf8("÷") #define CN_LBracket QString::fromUtf8("(") #define CN_RBracket QString::fromUtf8(")") #define CN_Period QString::fromUtf8("。") #define CN_Underscore QString::fromUtf8("——") #define CN_Percent QString::fromUtf8("%") //英文符号 #define EN_Comma QString::fromUtf8(",") #define EN_PI QString::fromUtf8("π") #define EN_Eular QString::fromUtf8("e") #define EN_ADD QString("+") #define EN_MIN QString("-") #define EN_MUL QString("*") #define EN_DIV QString("/") #define EN_LBracket QString("(") #define EN_RBracket QString(")") #define EN_Percent QString("%") #define EN_Underscore QString("_") #define EN_Period QString(".") #endif // GLOBALDEFINE_H deepin-calculator-5.7.21/src/main.cpp000066400000000000000000000132311423020056600174160ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mainwindow.h" #include "environments.h" #include "utils.h" #include #include #include #include #include #include #include #include #include #include #include #include DWIDGET_USE_NAMESPACE static QString g_appPath; //全局路径 static bool oldversion = false; //旧版本升级新版本 //20200702 edit for bug-36389,旧版本有设置过的第一次读取后不再读取themetype.cfg //获取配置文件主题类型,并重新设置 DGuiApplicationHelper::ColorType getThemeTypeSetting() { //需要找到自己程序的配置文件路径,并读取配置,这里只是用home路径下themeType.cfg文件举例,具体配置文件根据自身项目情况 QString t_appDir = g_appPath + QDir::separator() + "themetype.cfg"; QFile t_configFile(t_appDir); int t_readType = 0; if (t_configFile.exists()) { t_configFile.open(QIODevice::ReadOnly | QIODevice::Text); QByteArray t_readBuf = t_configFile.readAll(); t_readType = QString(t_readBuf).toInt(); t_configFile.remove(); oldversion = true; } //获取读到的主题类型,并返回设置 switch (t_readType) { case 0: // 跟随系统主题 return DGuiApplicationHelper::UnknownType; case 1: // 浅色主题 return DGuiApplicationHelper::LightType; case 2: // 深色主题 return DGuiApplicationHelper::DarkType; default: return DGuiApplicationHelper::UnknownType; } } //保存当前主题类型配置文件 //void saveThemeTypeSetting(int type) //{ // //需要找到自己程序的配置文件路径,并写入配置,这里只是用home路径下themeType.cfg文件举例,具体配置文件根据自身项目情况 // QString t_appDir = g_appPath + QDir::separator() + "themetype.cfg"; // QFile t_configFile(t_appDir); // t_configFile.open(QIODevice::WriteOnly | QIODevice::Text); // //直接将主题类型保存到配置文件,具体配置key-value组合根据自身项目情况 // QString t_typeStr = QString::number(type); // t_configFile.write(t_typeStr.toUtf8()); // t_configFile.close(); //} int main(int argc, char *argv[]) { if (!QString(qgetenv("XDG_CURRENT_DESKTOP")).toLower().startsWith("deepin")) { setenv("XDG_CURRENT_DESKTOP", "Deepin", 1); } // DApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); DApplication app(argc, argv); app.setAttribute(Qt::AA_UseHighDpiPixmaps); g_appPath = QDir::homePath() + QDir::separator() + "." + qApp->applicationName(); QDir t_appDir; t_appDir.mkpath(g_appPath); app.loadTranslator(); app.setOrganizationName("deepin"); app.setApplicationName("deepin-calculator"); app.setApplicationAcknowledgementPage( "https://www.deepin.org/acknowledgments/deepin-calculator"); QIcon t_icon = QIcon::fromTheme("deepin-calculator"); app.setProductIcon(t_icon); app.setProductName(DApplication::translate("MainWindow", "Calculator")); app.setApplicationDescription( DApplication::translate("MainWindow", "Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes.")); app.setApplicationVersion(VERSION); app.setQuitOnLastWindowClosed(true); app.setApplicationDisplayName(QObject::tr("Calculator")); // app.setStyle("chameleon"); using namespace Dtk::Core; Dtk::Core::DLogManager::registerConsoleAppender(); Dtk::Core::DLogManager::registerFileAppender(); QCommandLineParser cmdParser; cmdParser.setApplicationDescription("deepin-calculator"); cmdParser.addHelpOption(); cmdParser.addVersionOption(); cmdParser.process(app); MainWindow window; window.setWindowFlag(Qt::WindowMaximizeButtonHint, false); DSettingsAlt *m_dsettings = DSettingsAlt::instance(); QDBusConnection dbus = QDBusConnection::sessionBus(); if (dbus.registerService("com.deepin.calculator")) { Dtk::Widget::moveToCenter(&window); m_dsettings->setOption("windowX", window.pos().x()); m_dsettings->setOption("windowY", window.pos().y()); } else { window.move(m_dsettings->getOption("windowX").toInt() + 10, m_dsettings->getOption("windowY").toInt() + 10); } DGuiApplicationHelper::ColorType oldpalette = getThemeTypeSetting(); DApplicationSettings savetheme(&app); if (oldversion == true) { DGuiApplicationHelper::instance()->setThemeType(oldpalette); } // 20200330 主题记忆更改为规范代码 // DApplicationSettings savetheme(&app); // Register debus service. dbus.registerObject("/com/deepin/calculator", &window, QDBusConnection::ExportScriptableSlots); window.show(); window.switchModeBack(); return app.exec(); } deepin-calculator-5.7.21/src/mainwindow.cpp000066400000000000000000000205001423020056600206430ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "mainwindow.h" #include "dtitlebar.h" #include "dthememanager.h" #include "dhidpihelper.h" #include "utils.h" #include "../3rdparty/core/settings.h" #include #include #include #include #include #include #include #include #include #include DGUI_USE_NAMESPACE const QSize STANDARD_SIZE = QSize(344, 545); //标准模式的固定大小 const QSize SCIENTIFIC_MIN_SIZE = QSize(451, 542); //科学模式的最小size const QSize PROGRAMM_SIZE = QSize(451, 574); //程序员模式固定大小 MainWindow::MainWindow(QWidget *parent) : DMainWindow(parent) { m_settings = DSettingsAlt::instance(); m_mainLayout = new QStackedLayout(); m_tbMenu = new DMenu(this); QIcon t_icon = QIcon::fromTheme("deepin-calculator"); titlebar()->setIcon(t_icon); titlebar()->setMenu(m_tbMenu); titlebar()->setTitle(""); m_simpleAction = new QAction(tr("Standard"), this); m_scAction = new QAction(tr("Scientific"), this); m_programmerAction = new QAction(tr("Programmer"), this); m_pActionGroup = new QActionGroup(this); //实现互斥checked m_pActionGroup->addAction(m_simpleAction); m_pActionGroup->addAction(m_scAction); m_pActionGroup->addAction(m_programmerAction); m_simpleAction->setCheckable(true); m_scAction->setCheckable(true); m_programmerAction->setCheckable(true); #ifdef ENABLE_SCIENTIFIC m_modeshowmenu = new DMenu(tr("Mode"), this); m_tbMenu->addSeparator(); //添加分隔符 m_modeshowmenu->addAction(m_simpleAction); m_modeshowmenu->addAction(m_scAction); m_modeshowmenu->addAction(m_programmerAction); m_tbMenu->addMenu(m_modeshowmenu); #endif initModule(); initTheme(); setWindowTitle(tr("Calculator")); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &MainWindow::initTheme); connect(m_simpleAction, &QAction::triggered, this, &MainWindow::switchToSimpleMode); connect(m_scAction, &QAction::triggered, this, &MainWindow::switchToScientificMode); connect(m_programmerAction, &QAction::triggered, this, &MainWindow::switchToProgrammerMode); } MainWindow::~MainWindow() { } void MainWindow::switchModeBack() { int mode = m_settings->getOption("mode").toInt(); switch(mode){ case 0: switchToScientificMode(); switchToSimpleMode(); break; case 1: switchToSimpleMode(); switchToScientificMode(); break; case 2: switchToSimpleMode(); switchToProgrammerMode(); break; default: switchToScientificMode(); switchToSimpleMode(); } } void MainWindow::initTheme() { int type = DGuiApplicationHelper::instance()->themeType(); if (type == 1) { DPalette titlePa = titlebar()->palette(); titlePa.setColor(DPalette::Light, QColor(240, 240, 240)); titlePa.setColor(DPalette::Dark, QColor(240, 240, 240)); titlePa.setColor(DPalette::Base, QColor(240, 240, 240)); titlebar()->setPalette(titlePa); } else { DPalette titlePa = titlebar()->palette(); QColor normalbackground = QColor(0, 0, 0); normalbackground.setAlphaF(0.1); titlePa.setColor(DPalette::Light, normalbackground); titlePa.setColor(DPalette::Dark, normalbackground); titlePa.setColor(DPalette::Base, normalbackground); // titlePa.setColor(DPalette::Light, QColor(37, 37, 37)); // titlePa.setColor(DPalette::Dark, QColor(37, 37, 37)); // titlePa.setColor(DPalette::Base, QColor(37, 37, 37)); titlebar()->setPalette(titlePa); } } void MainWindow::initModule() { int mode = m_settings->getOption("mode").toInt(); QWidget *centralWidget = new QWidget(this); centralWidget->setLayout(m_mainLayout); setCentralWidget(centralWidget); m_mainLayout->setContentsMargins(0, 0, 0, 0); m_isinit = true; Settings::instance()->programmerBase = 10;//默认程序员模式的基础进制是10 switch (mode) { case 0: m_basicModule = new BasicModule(this); m_mainLayout->addWidget(m_basicModule); m_simpleAction->setChecked(true); switchToSimpleMode(); break; case 1: m_scientificModule = new scientificModule(this); m_mainLayout->addWidget(m_scientificModule); m_scAction->setChecked(true); switchToScientificMode(); break; case 2: m_programmerModule = new ProgramModule(this); m_mainLayout->addWidget(m_programmerModule); m_programmerAction->setChecked(true); switchToProgrammerMode(); break; default: m_basicModule = new BasicModule(this); m_mainLayout->addWidget(m_basicModule); m_simpleAction->setChecked(true); switchToSimpleMode(); break; } m_isinit = false; } void MainWindow::switchToSimpleMode() { if (Settings::instance()->programmerBase != 0) programmerOldBase = Settings::instance()->programmerBase; Settings::instance()->programmerBase = 0; if (!m_basicModule) { m_basicModule = new BasicModule(this); m_mainLayout->addWidget(m_basicModule); emit DGuiApplicationHelper::instance()->themeTypeChanged(DGuiApplicationHelper::instance()->themeType()); } if (m_settings->getOption("mode") != 0 || m_isinit) { m_settings->setOption("mode", 0); m_mainLayout->setCurrentWidget(m_basicModule); setFixedSize(STANDARD_SIZE); } } void MainWindow::switchToScientificMode() { if (Settings::instance()->programmerBase != 0) programmerOldBase = Settings::instance()->programmerBase; Settings::instance()->programmerBase = 0; if (!m_scientificModule) { m_scientificModule = new scientificModule(this); m_mainLayout->addWidget(m_scientificModule); emit DGuiApplicationHelper::instance()->themeTypeChanged(DGuiApplicationHelper::instance()->themeType()); } if (m_settings->getOption("mode") != 1 || m_isinit) { m_settings->setOption("mode", 1); m_mainLayout->setCurrentWidget(m_scientificModule); m_scientificModule->checkLineEmpty(); setFixedSize(SCIENTIFIC_MIN_SIZE); } } void MainWindow::switchToProgrammerMode() { Settings::instance()->programmerBase = programmerOldBase; if (!m_programmerModule) { m_programmerModule = new ProgramModule(this); m_mainLayout->addWidget(m_programmerModule); emit DGuiApplicationHelper::instance()->themeTypeChanged(DGuiApplicationHelper::instance()->themeType()); } if (m_settings->getOption("mode") != 2 || m_isinit) { m_settings->setOption("mode", 2); m_mainLayout->setCurrentWidget(m_programmerModule); setFixedSize(PROGRAMM_SIZE); } } /** * @brief 焦点不在basicmodul时也触发keypress */ void MainWindow::keyPressEvent(QKeyEvent *event) { if (m_mainLayout->currentWidget() == m_basicModule) m_basicModule->setKeyPress(event); else if (m_mainLayout->currentWidget() == m_scientificModule) m_scientificModule->setKeyPress(event); else if (m_mainLayout->currentWidget() == m_programmerModule) { m_programmerModule->setKeyPress(event); } return; } void MainWindow::moveEvent(QMoveEvent *event) { m_settings->setOption("windowX", event->pos().x()); m_settings->setOption("windowY", event->pos().y()); } void MainWindow::resizeEvent(QResizeEvent *event) { m_settings->setOption("windowWidth", event->size().width()); m_settings->setOption("windowHeight", event->size().height()); DMainWindow::resizeEvent(event); } deepin-calculator-5.7.21/src/mainwindow.h000066400000000000000000000040671423020056600203220ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include "dsettings.h" #include "control/iconbutton.h" #include "widgets/basicmodule.h" #include "widgets/scientificmodule.h" #include "widgets/programmodule.h" #include "control/iconbutton.h" #include #include #include #define ENABLE_SCIENTIFIC 1 DWIDGET_USE_NAMESPACE class MainWindow : public DMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); //switch to another mode and switch back void switchModeBack(); protected: void keyPressEvent(QKeyEvent *event); void moveEvent(QMoveEvent *event); void resizeEvent(QResizeEvent *event); private: void initTheme(); void initModule(); void switchToSimpleMode(); void switchToScientificMode(); void switchToProgrammerMode(); private: DSettingsAlt *m_settings; QStackedLayout *m_mainLayout; DMenu *m_tbMenu; DMenu *m_modeshowmenu; QAction *m_simpleAction; QAction *m_scAction; QAction *m_programmerAction; QActionGroup *m_pActionGroup; BasicModule *m_basicModule = nullptr; scientificModule *m_scientificModule = nullptr; ProgramModule *m_programmerModule = nullptr; bool m_isinit = true;//初始化 int programmerOldBase = 10;//切换前程序员计算器的进制 }; #endif deepin-calculator-5.7.21/src/memorypublic.cpp000066400000000000000000000110531423020056600212010ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memorypublic.h" #include "utils.h" #include "../3rdparty/core/settings.h" static MemoryPublic *INSTANCE = nullptr; const int MAXSIZE = 500; //内存保存最大数 static void s_deletemempub() { delete INSTANCE; INSTANCE = nullptr; } /** * @brief 实例 */ MemoryPublic *MemoryPublic::instance() { if (!INSTANCE) { INSTANCE = new MemoryPublic; qAddPostRoutine(s_deletemempub); } return INSTANCE; } void MemoryPublic::deleteInstance() { delete INSTANCE; INSTANCE = nullptr; } MemoryPublic::MemoryPublic(QObject *parent) : QObject(parent) { m_standard_l = new MemoryWidget(0); m_scientific_r = new MemoryWidget(1); m_programmer_l = new MemoryWidget(2); m_evaluator = Evaluator::instance(); m_standard_l->setMemoryPublic(this); m_scientific_r->setMemoryPublic(this); m_programmer_l->setMemoryPublic(this); initconnects(); memoryclean(); } /** * @brief 相关信号槽 */ void MemoryPublic::initconnects() { connect(m_standard_l, &MemoryWidget::widgetclean, this, &MemoryPublic::widgetclean); connect(m_scientific_r, &MemoryWidget::widgetclean, this, &MemoryPublic::widgetclean); connect(m_programmer_l, &MemoryWidget::widgetclean, this, &MemoryPublic::widgetclean); } /** * @brief 根据模式获取不同memorywidget */ MemoryWidget *MemoryPublic::getwidget(memorymode mode) { switch (mode) { case standardleft: return m_standard_l; case programmerleft: return m_programmer_l; default: return m_scientific_r; } } QList MemoryPublic::getList() { return m_list; } /** * @brief 向数字内存中同时增加一个数字 */ void MemoryPublic::generateData(Quantity answer) { bool ismax = false; if (m_list.count() == MAXSIZE) { m_list.pop_back(); ismax = true; } emit generateDataSig(answer, ismax); m_list.insert(0, answer); } /** * @brief 同时进行M+操作 */ void MemoryPublic::memoryplus(Quantity answer) { if (!m_list.isEmpty()) { Quantity ans; ans = m_list.value(0) + answer; emit memoryAnsSig(0, ans); m_list.replace(0, ans); } else generateData(answer); } /** * @brief 同时进行M-操作 */ void MemoryPublic::memoryminus(Quantity answer) { if (!m_list.isEmpty()) { Quantity ans; ans = m_list.value(0) - answer; emit memoryAnsSig(0, ans); m_list.replace(0, ans); } else generateData(Quantity(-1)*answer); } /** * @brief 同时进行清除内存操作 */ void MemoryPublic::memoryclean() { m_list.clear(); emit memorycleanSig(); } /** * @brief 用于从列表中item里的按钮,对指定行号的内存数据进行M+ */ void MemoryPublic::widgetplus(int row, Quantity answer) { if (!answer.isZero()) { Quantity ans; ans = m_list.value(row) + answer; emit memoryAnsSig(row, ans); m_list.replace(row, ans); } } /** * @brief 用于从列表中item里的按钮,对指定行号的内存数据进行M- */ void MemoryPublic::widgetminus(int row, Quantity answer) { if (!answer.isZero()) { Quantity ans; ans = m_list.value(row) - answer; emit memoryAnsSig(row, ans); m_list.replace(row, ans); } } /** * @brief 用于从列表中item里的按钮,对指定行号的内存数据进行MC */ void MemoryPublic::widgetclean(int row, int mode, bool ismenu) { m_list.removeAt(row); emit widgetcleanSig(row, mode, ismenu); } /** * @brief 根据主题变换垃圾桶及内存中没有数据字体颜色 */ void MemoryPublic::setThemeType(int type) { emit setThemeTypeSig(type); } /** * @brief 返回内存中是否有数据 */ bool MemoryPublic::isEmpty() { return m_list.isEmpty(); } MemoryPublic::~MemoryPublic() { } deepin-calculator-5.7.21/src/memorypublic.h000066400000000000000000000044031423020056600206470ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MEMORYPUBLIC_H #define MEMORYPUBLIC_H #include "../3rdparty/core/evaluator.h" #include "views/memorywidget.h" #include #include /** * @brief 同步处理数字内存 */ class MemoryPublic : public QObject { Q_OBJECT private: explicit MemoryPublic(QObject *parent = nullptr); void initconnects(); public: /** * @brief 当前内存界面所在计算器模式 */ enum memorymode { standardleft, //标准模式 scientificright, //科学模式 programmerleft //程序员 }; static MemoryPublic *instance(); static void deleteInstance(); ~MemoryPublic(); MemoryWidget *getwidget(memorymode mode); QList getList(); void generateData(Quantity answer); void memoryplus(Quantity answer); void memoryminus(Quantity answer); void memoryclean(); void widgetplus(int row, Quantity answer); void widgetminus(int row, Quantity answer); void widgetclean(int row, int mode, bool ismenu); void setThemeType(int type); bool isEmpty(); private: MemoryWidget *m_standard_l; MemoryWidget *m_scientific_r; MemoryWidget *m_programmer_l; QList m_list; Evaluator *m_evaluator; signals: void generateDataSig(Quantity answer, bool ismax); void memorycleanSig(); void memoryAnsSig(int row, Quantity answer); void widgetcleanSig(int row, int mode, bool ismenu); void setThemeTypeSig(int type); public slots: }; #endif // MEMORYPUBLIC_H deepin-calculator-5.7.21/src/utils.cpp000066400000000000000000000164331423020056600176410ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "utils.h" #include "dsettings.h" #include #include #include #include #include #include const static QString ATOE = "ABCDEF"; Utils::Utils() { } Utils::~Utils() { } /** * @brief 返回程序文件路径 */ QString Utils::getConfigDir() { QDir dir(QDir(QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).first()) .filePath(qApp->organizationName())); return dir.filePath(qApp->applicationName()); } /** * @brief 获取文件内容(暂未使用) */ QString Utils::getQssContent(const QString &filePath) { QFile file(filePath); QString qss = nullptr; if (file.open(QIODevice::ReadOnly)) { qss = file.readAll(); } return qss; } /** * @brief 补充千位符(针对结果) */ QString Utils::formatThousandsSeparators(const QString &str) { int separate = DSettingsAlt::instance()->getSeparate(); //数字分割位数 QString result = str; int startPos = result.indexOf(QRegularExpression("[0-9]")); if (startPos >= 0) { int endPos = result.indexOf('.'); if (endPos < 0) { endPos = result.indexOf('E'); if (endPos < 0) endPos = result.length(); } for (int i = endPos - separate; i >= startPos + 1; i -= separate) { result.insert(i, ","); } } return result; } /** * @brief 该string是否是数字 */ bool Utils::stringIsDigit(const QString &str) { bool isDigit = true; for (auto &ch : str) { if (!ch.isDigit() && ch != '.' && ch != ',' && ch != '-') { //非数字条件为非数字小数点分隔符负号 isDigit = false; break; } } return isDigit; } /** * @brief 针对输入框内容重新设置千位符 */ QString Utils::reformatSeparators(const QString &exp) { QString seg; QStringList expList; int count = 0; for (auto ch : exp) { if (ch.isDigit() || ch == '.') { seg.append(ch); } else { expList << seg; seg.clear(); seg.append(ch); expList << seg; seg.clear(); } if (count == exp.count() - 1) { expList << seg; } ++count; } QString formatStr; for (auto item : expList) { if (stringIsDigit(item)) { item = formatThousandsSeparators(item); } formatStr.append(item); } return formatStr; } QString Utils::formatThousandsSeparatorsPro(const QString &str, const int Base) { QString result = str; int startPos = result.indexOf(QRegularExpression("[0-9]")); int startPosHex = result.indexOf(QRegularExpression("[A-F0-9]")); switch (Base) { case 16: case 2: if (startPosHex >= 0) { int endPos = result.length(); for (int i = endPos - 4; i >= startPosHex + 1; i -= 4) { result.insert(i, " "); } } break; case 10: if (startPos >= 0) { int endPos = result.length(); int separate = DSettingsAlt::instance()->getSeparate(); //数字分割位数 for (int i = endPos - separate; i >= startPos + 1; i -= separate) { result.insert(i, ","); } } break; case 8: if (startPos >= 0) { int endPos = result.length(); for (int i = endPos - 3; i >= startPos + 1; i -= 3) { result.insert(i, " "); } } break; default: break; } return result; } /** * @brief Utils::stringIsDigitPro * @param str:待判断字符串 * @param Base:进制 * @return 是否是数字 * 程序员模式下判断字符串是否为数字 */ bool Utils::stringIsDigitPro(const QString &str, const int Base) { bool isDigit = true; switch (Base) { case 16: for (auto &ch : str) { if (!ch.isDigit() && ch != ' ' && !isAtoE(ch)) { isDigit = false; break; } } break; case 10: for (auto &ch : str) { if (!ch.isDigit() && ch != ',' && ch != '-') { isDigit = false; break; } } break; case 8: case 2: for (auto &ch : str) { if (!ch.isDigit() && ch != ' ') { isDigit = false; break; } } break; default: for (auto &ch : str) { if (!ch.isDigit() && ch != ',' && ch != '-') { isDigit = false; break; } } break; } return isDigit; } QString Utils::reformatSeparatorsPro(const QString &exp, const int Base) { QString seg; QStringList expList; int count = 0; for (auto ch : exp) { if (ch.isDigit() || isAtoE(ch)) { seg.append(ch); } else { expList << seg; seg.clear(); seg.append(ch); expList << seg; seg.clear(); } if (count == exp.count() - 1) { expList << seg; } ++count; } QString formatStr; for (auto item : expList) { if (stringIsDigitPro(item, Base)) { item = formatThousandsSeparatorsPro(item, Base); } formatStr.append(item); } for (int i = 0; i < formatStr.length();) { if (formatStr.at(i).isLower()) { if (formatStr.at(i) == 'n' && formatStr.at(i + 1) == 'a') { i += 4; } else if (formatStr.at(i) == 'o') { i += 2; } else { i += 3; } if (i <= formatStr.length() - 1) { formatStr.insert(i, " "); i++; } } else if (i < formatStr.length() - 1 && formatStr.at(i + 1).isLower()) { formatStr.insert(i + 1, " "); i += 2; } else { i++; } } return formatStr; } QString Utils::toHalfWidth(const QString &str) { QString result = str; if (str.length() <= 0) return QString(); for (int i = 0; i < result.length(); i++) { int charIntValue = result.at(i).unicode(); if (charIntValue >= 65281 && charIntValue <= 65374) { result.replace(i, 1, QChar(charIntValue - 65248)); } else if (charIntValue == 12288) { result.replace(i, 1, QChar(32)); } } return result; } bool Utils::isAtoE(const QChar &num) { return ATOE.contains(num); } deepin-calculator-5.7.21/src/utils.h000066400000000000000000000030241423020056600172760ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef UTILS_H #define UTILS_H #include class Utils : public QObject { Q_OBJECT public: Utils(); ~Utils(); static QString getConfigDir(); static QString getQssContent(const QString &filePath); static QString formatThousandsSeparators(const QString &str); static bool stringIsDigit(const QString &str); static QString reformatSeparators(const QString &exp); //程序员计算器format static QString formatThousandsSeparatorsPro(const QString &str, const int Base); static bool stringIsDigitPro(const QString &str, const int Base); static QString reformatSeparatorsPro(const QString &exp, const int Base); //全角转半角符号 static QString toHalfWidth(const QString &str); private: static bool isAtoE(const QChar &num); }; #endif deepin-calculator-5.7.21/src/views/000077500000000000000000000000001423020056600171235ustar00rootroot00000000000000deepin-calculator-5.7.21/src/views/memoryitemdelegate.cpp000066400000000000000000000052711423020056600235160ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memoryitemdelegate.h" #include #include MemoryItemDelegate::MemoryItemDelegate(QObject *parent) : QStyledItemDelegate(parent) { } MemoryItemDelegate::~MemoryItemDelegate() { } /** * @brief 绘制memorylistwidget背景色 */ void MemoryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { MemoryListWidget *dragWidget = qobject_cast(option.styleObject); //将该object强转为memorylistwidget QRectF rect = dragWidget->rect(); //获取memorylistwidget.rect绘制背景色 painter->setRenderHint(QPainter::Antialiasing, true); int type = DGuiApplicationHelper::instance()->themeType(); if (type == 1) { painter->setPen(Qt::NoPen); painter->setBrush(QColor("#F8F8F8")); painter->drawRect(rect); } else { painter->setPen(Qt::NoPen); painter->setBrush(QColor("#252525")); painter->drawRect(rect); } //内存焦点选中边框绘制 if (dragWidget->hasFocus()) { QRectF itemrect(dragWidget->visualItemRect(dragWidget->currentItem())); QRectF frame(itemrect.left() + 1, itemrect.top() + 1, itemrect.width() - 2, itemrect.height() - 2); QPen pen; pen.setColor(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name()); pen.setWidth(2); painter->setPen(pen); painter->setBrush(Qt::NoBrush); painter->drawRoundedRect(frame, 8, 8); //focus边框 } QStyledItemDelegate::paint(painter, option, index); } /** * @brief 可以通过editor->setGeometry()更新编辑组件大小,保证editor显示的位置及大小,保证控件塞满计算器 */ void MemoryItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(index); editor->setGeometry(option.rect); } deepin-calculator-5.7.21/src/views/memoryitemdelegate.h000066400000000000000000000026601423020056600231620ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef TESTITEMDELEGATE_H #define TESTITEMDELEGATE_H #include "memorylistwidget.h" #include "memoryitemwidget.h" #include #include /** * @brief 内存ListWidget委托 */ class MemoryItemDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit MemoryItemDelegate(QObject *parent = nullptr); ~MemoryItemDelegate() override; protected: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; #endif // TESTITEMDELEGATE_H deepin-calculator-5.7.21/src/views/memoryitemwidget.cpp000066400000000000000000000230651423020056600232300ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memoryitemwidget.h" #include #include #include #include #include #include #include #include const QSize MEMORYBUTTON_SIZE = QSize(52, 32); //内存按键大小,为画边框比ui大2pix MemoryItemWidget::MemoryItemWidget(QWidget *parent) : QWidget(parent) , m_btnplus(new MemoryButton(QString("M+"), true, this)) , m_btnminus(new MemoryButton(QString("M-"), true, this)) , m_btnclean(new MemoryButton(QString("MC"), true, this)) , m_label(new QLabel(this)) { setFocusPolicy(Qt::NoFocus); QVBoxLayout *layV = new QVBoxLayout(this); //存放四个控件 QHBoxLayout *lay = new QHBoxLayout(); //存放三个按钮 lay->addStretch(); lay->setSpacing(3); //按钮比ui大2pix m_btnplus->setFixedSize(MEMORYBUTTON_SIZE); m_btnminus->setFixedSize(MEMORYBUTTON_SIZE); m_btnclean->setFixedSize(MEMORYBUTTON_SIZE); lay->addWidget(m_btnclean); lay->addWidget(m_btnplus); lay->addWidget(m_btnminus); layV->setMargin(0); layV->addWidget(m_label); layV->addStretch(); QFont font; font.setPixelSize(29); m_label->setFont(font); m_label->setAttribute(Qt::WA_TranslucentBackground); //label窗体透明 m_label->setAlignment(Qt::AlignRight | Qt::AlignTop); //label字体居右,居上 m_label->setAttribute(Qt::WA_TransparentForMouseEvents, true); //label鼠标穿透 layV->addLayout(lay); layV->setContentsMargins(0, 0, 20, 6); //右边距20,下边距6 this->setLayout(layV); connect(m_btnplus, &QPushButton::clicked, this, &MemoryItemWidget::plusbtnclicked); connect(m_btnminus, &QPushButton::clicked, this, &MemoryItemWidget::minusbtnclicked); connect(m_btnclean, &QPushButton::clicked, this, &MemoryItemWidget::cleanbtnclicked); m_btnplus->setFocusPolicy(Qt::NoFocus); m_btnminus->setFocusPolicy(Qt::NoFocus); m_btnclean->setFocusPolicy(Qt::NoFocus); m_btnplus->setHidden(true); m_btnminus->setHidden(true); m_btnclean->setHidden(true); // m_font.setPixelSize(18); } void MemoryItemWidget::enterEvent(QEvent *event) { m_ishover = true; m_btnplus->setHidden(false); //进入时显示按钮 m_btnminus->setHidden(false); m_btnclean->setHidden(false); update(); // this->setAttribute(Qt::WA_StyledBackground, true); // this->setStyleSheet("background-color: rgb(245,245,245)"); QWidget::enterEvent(event); } void MemoryItemWidget::leaveEvent(QEvent *event) { // clearFocus(); m_ishover = false; m_btnplus->setHidden(true); //离开时隐藏按钮 m_btnminus->setHidden(true); m_btnclean->setHidden(true); update(); // this->setAttribute(Qt::WA_StyledBackground, true); // this->setStyleSheet("background-color: rgb(255,255,255)"); QWidget::leaveEvent(event); } void MemoryItemWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) return; // setFocus(); m_ispress = true; DPalette pl1 = this->palette(); //按下时给label字体设置颜色 if (m_themetype == 1) { pl1.setColor(DPalette::Text, QColor("#303030")); pl1.setColor(DPalette::HighlightedText, QColor("#303030")); } else { pl1.setColor(DPalette::Text, QColor("#FFFFFF")); pl1.setColor(DPalette::HighlightedText, QColor("#FFFFFF")); } m_label->setPalette(pl1); update(); QWidget::mousePressEvent(event); } void MemoryItemWidget::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) return; // clearFocus(); m_ispress = false; DPalette pl1 = this->palette(); //松开鼠标时给label字体重新设置颜色 if (m_themetype == 1) { pl1.setColor(DPalette::Text, QColor("#303030")); pl1.setColor(DPalette::HighlightedText, QColor("#303030")); } else { pl1.setColor(DPalette::Text, QColor("#B4B4B4")); pl1.setColor(DPalette::HighlightedText, QColor("#B4B4B4")); } m_label->setPalette(pl1); QWidget::mouseReleaseEvent(event); } void MemoryItemWidget::contextMenuEvent(QContextMenuEvent *event) { QMenu *menu = new QMenu(this); //添加各item的菜单项 QAction *copy = new QAction(tr("Copy"), menu); //复制 QAction *clean = new QAction(tr("Clear memory item"), menu); //MC QAction *plus = new QAction(tr("Add to memory item"), menu); //M+ QAction *minus = new QAction(tr("Subtract from memory item"), menu); //M- menu->addAction(copy); menu->addAction(clean); menu->addAction(plus); menu->addAction(minus); if (m_isExpressionEmpty) { plus->setEnabled(false); minus->setEnabled(false); } else { plus->setEnabled(true); minus->setEnabled(true); } connect(copy, &QAction::triggered, this, &MemoryItemWidget::menucopy); connect(clean, &QAction::triggered, this, &MemoryItemWidget::menuclean); connect(plus, &QAction::triggered, this, &MemoryItemWidget::menuplus); connect(minus, &QAction::triggered, this, &MemoryItemWidget::menuminus); menu->exec(event->globalPos()); //当前鼠标位置显示菜单 delete menu; } /** * @brief 当做出内存操作时对label->settext * @param s-text */ void MemoryItemWidget::setTextLabel(QString s) { m_label->setText(s); } /** * @brief 获取当前label的text */ QString MemoryItemWidget::textLabel() { return m_label->text(); } void MemoryItemWidget::paintEvent(QPaintEvent *e) { Q_UNUSED(e); QRectF rect = this->rect(); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); //防走样 painter.setPen(Qt::NoPen); QColor press, hover; int type = DGuiApplicationHelper::instance()->themeType(); if (type == 1) { press = QColor(0, 0, 0); press.setAlphaF(0.2); hover = QColor(0, 0, 0); hover.setAlphaF(0.05); } else { press = QColor(255, 255, 255); press.setAlphaF(0.2); hover = QColor(255, 255, 255); hover.setAlphaF(0.05); } if (m_ishover) { painter.setPen(Qt::NoPen); // painter.setFont(m_font); painter.setBrush(hover); painter.drawRect(rect); //hover状态下对item进行颜色填充 if (m_ispress) { painter.setPen(Qt::NoPen); painter.setBrush(press); painter.drawRect(rect); //press状态下对item进行颜色填充 } } } void MemoryItemWidget::setLineHight(int line, int height) { m_label->setFixedHeight(height * line); m_line = line; } int MemoryItemWidget::getLine() { return m_line; } void MemoryItemWidget::showTextEditMenuByAltM() { QMenu *menu = new QMenu(this); //添加各item的菜单项 QAction *copy = new QAction(tr("Copy"), menu); //复制 QAction *clean = new QAction(tr("Clear memory item"), menu); //MC QAction *plus = new QAction(tr("Add to memory item"), menu); //M+ QAction *minus = new QAction(tr("Subtract from memory item"), menu); //M- menu->addAction(copy); menu->addAction(clean); menu->addAction(plus); menu->addAction(minus); if (m_isExpressionEmpty) { plus->setEnabled(false); minus->setEnabled(false); } else { plus->setEnabled(true); minus->setEnabled(true); } connect(copy, &QAction::triggered, this, &MemoryItemWidget::menucopy); connect(clean, &QAction::triggered, this, &MemoryItemWidget::menuclean); connect(plus, &QAction::triggered, this, &MemoryItemWidget::menuplus); connect(minus, &QAction::triggered, this, &MemoryItemWidget::menuminus); QPoint menupoint; menupoint.setX(mapToGlobal(m_label->rect().center()).x()); menupoint.setY(mapToGlobal(m_label->rect().bottomLeft()).y()); menu->exec(menupoint); //当前鼠标位置显示菜单 delete menu; } void MemoryItemWidget::themetypechanged(int type) { m_themetype = type; DPalette pl1 = this->palette(); //itemwidget字体颜色设置 if (m_themetype == 1) { pl1.setColor(DPalette::Text, QColor("#303030")); } else { pl1.setColor(DPalette::Text, QColor("#B4B4B4")); } m_label->setPalette(pl1); } /** * @brief 当输入栏为空时,内存列表中的加减按钮置灰 */ void MemoryItemWidget::isexpressionempty(bool b) { m_isExpressionEmpty = b; if (m_isExpressionEmpty) { m_btnplus->setEnabled(false); m_btnminus->setEnabled(false); } else { m_btnplus->setEnabled(true); m_btnminus->setEnabled(true); } } /** * @brief MemoryItemWidget::setNextItemHover * 上一个item清除后,鼠标自动到下一个item上,此时为hover状态 */ void MemoryItemWidget::setNextItemHover() { m_ishover = true; m_btnplus->setHidden(false); //进入时显示按钮 m_btnminus->setHidden(false); m_btnclean->setHidden(false); } MemoryItemWidget::~MemoryItemWidget() { } deepin-calculator-5.7.21/src/views/memoryitemwidget.h000066400000000000000000000045121423020056600226710ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MEMORYITEMWIDGET_H #define MEMORYITEMWIDGET_H #include "../control/memorybutton.h" #include #include #include #include #include #include #include #include /** * @brief 内存列表Item界面 */ class MemoryItemWidget : public QWidget { Q_OBJECT public: explicit MemoryItemWidget(QWidget *parent = nullptr); ~MemoryItemWidget() override; void enterEvent(QEvent *event) override; void leaveEvent(QEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void contextMenuEvent(QContextMenuEvent *event) override; void setTextLabel(QString s); QString textLabel(); void paintEvent(QPaintEvent *e) override; void setLineHight(int line, int height); int getLine(); signals: void plusbtnclicked(); void minusbtnclicked(); void cleanbtnclicked(); void menuclean(); void menucopy(); void menuplus(); void menuminus(); public slots: void themetypechanged(int type); void isexpressionempty(bool b); void setNextItemHover(); void showTextEditMenuByAltM(); public: // QPainter *getpainter(); private: MemoryButton *m_btnplus; MemoryButton *m_btnminus; MemoryButton *m_btnclean; QLabel *m_label; int m_type = 0; int m_themetype = 1; bool m_isExpressionEmpty = false; bool m_ispress = false; bool m_ishover = false; QFont m_font; int m_line = 0; }; #endif // MEMORYITEMWIDGET_H deepin-calculator-5.7.21/src/views/memorylistwidget.cpp000066400000000000000000000116141423020056600232420ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memorylistwidget.h" #include #include #include #include #include #include "programmeritemwidget.h" DGUI_USE_NAMESPACE MemoryListWidget::MemoryListWidget(QWidget *parent, bool isarrowlist) : QListWidget(parent) { // DPalette pal = this->palette(); // pal.setColor(DPalette::Light, QColor(248, 248, 248)); // this->setPalette(pal); // this->setAttribute(Qt::WA_StyledBackground, false); // DPalette pal = this->palette(); // pal.setColor(DPalette::Light, QColor(248, 248, 248)); // this->setPalette(pal); setFocusPolicy(Qt::NoFocus); //防止内存无内容时被focus setVerticalScrollMode(ScrollPerPixel); //鼠标滚轮滚动一次一个像素 m_isarrowlist = isarrowlist; if (isarrowlist) { setMouseTracking(true); installEventFilter(this); } } /** * @brief 获取当前点击row; */ void MemoryListWidget::mousePressEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { m_mousemovepoint = event->globalPos(); m_mousepoint = event->pos(); if (this->itemAt(m_mousepoint)) { m_clickrow = this->row(this->itemAt(m_mousepoint)); // this->itemAt(mousepoint)->setBackground(QBrush(QColor(0, 0, 0))); emit itempressed(m_clickrow); } } if (m_isarrowlist) { static_cast(itemWidget(currentItem()))->cleanFocusState(); emit mousemoving(); } QListWidget::mousePressEvent(event); } /** * @brief 发送内存被选行信号 */ void MemoryListWidget::mouseReleaseEvent(QMouseEvent *event) { if (this->itemAt(event->pos()) && this->row(this->itemAt(event->pos())) == m_clickrow) { emit itemselected(m_clickrow, true); } else { emit itemselected(m_clickrow, false); } m_clickrow = -1; QListWidget::mouseReleaseEvent(event); } /** * @brief focus时上下左右与空格键的信号 * @param 0-上 1-下 2-左 3-右 */ void MemoryListWidget::keyPressEvent(QKeyEvent *e) { bool ispressalt = e->modifiers() == Qt::AltModifier; switch (e->key()) { case Qt::Key_Up: emit focus(0); break; case Qt::Key_Down: emit focus(1); break; case Qt::Key_Left: emit focus(2); break; case Qt::Key_Right: emit focus(3); break; case Qt::Key_Space: case Qt::Key_Enter: case Qt::Key_Return: emit space(); break; case Qt::Key_M: if (ispressalt) emit altAndM(); break; default: QWidget::keyPressEvent(e); break; } } /** * @brief 焦点进入时设置焦点在第一条记录 */ void MemoryListWidget::focusInEvent(QFocusEvent *event) { // setCurrentRow(0); //暂定 // if (currentRow() == -1) // setCurrentRow(0); scrollToItem(this->item(currentRow())); if (m_isarrowlist) { cleanState(); static_cast(itemWidget(currentItem()))->setFocus(); } QWidget::focusInEvent(event); } void MemoryListWidget::focusOutEvent(QFocusEvent *event) { if (m_isarrowlist) { cleanState(true); } QListWidget::focusOutEvent(event); } bool MemoryListWidget::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::MouseMove && m_isarrowlist) { if (this->hasFocus()) { static_cast(itemWidget(currentItem()))->cleanFocusState(); emit mousemoving(); } return true; } return QListWidget::eventFilter(obj, event); } /** * @brief MemoryListWidget::cleanState * @param isfocus:是否清除的是focus状态 * 用于arrowrectangle中的listwidget,清除所有行的当前状态 */ void MemoryListWidget::cleanState(bool isfocus) { if (m_isarrowlist) { for (int i = 0; i < 4; i++) { if (isfocus) static_cast(itemWidget(item(i)))->cleanFocusState(); else static_cast(itemWidget(item(i)))->cleanHoverState(); } } } MemoryListWidget::~MemoryListWidget() { } deepin-calculator-5.7.21/src/views/memorylistwidget.h000066400000000000000000000036721423020056600227140ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MEMORYLISTWIDGET_H #define MEMORYLISTWIDGET_H #include /** * @brief 内存ListWidget */ class MemoryListWidget : public QListWidget { Q_OBJECT public: explicit MemoryListWidget(QWidget *parent = nullptr, bool isarrowlist = false); ~MemoryListWidget() override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void keyPressEvent(QKeyEvent *e) override; void focusInEvent(QFocusEvent *event) override; void focusOutEvent(QFocusEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override; void cleanState(bool isfocus = false); signals: void itempressed(int row); void itemselected(int row, bool isselect); void focus(int direction); //direction 0-上 1-下 2-左 3-右 void space(); void altAndM(); void mousemoving(); private: QPoint m_mousepoint; QPoint m_mousemovepoint;//鼠标的实时全局位置 int m_clickrow = -1; bool m_isarrowlist = false; public slots: // void on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous); }; #endif // MEMORYLISTWIDGET_H deepin-calculator-5.7.21/src/views/memorywidget.cpp000066400000000000000000000575361423020056600223630ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memorywidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "../utils.h" #include "../../3rdparty/core/settings.h" #include "../memorypublic.h" #include "../globaldefine.h" const int STANDARD_MWIDGET_HEIGHT = 260; //标准模式memorywidget高度 const int SCIENTIFIC_MWIDGET_HEIGHT = 302; //科学模式memorywidget高度 const int PROGRAMMER_MWIDGET_HEIGHT = 230; //程序猿模式memorywidget高度 const int STANDARD_ITEM_WIDTH = 344; //标准模式宽度 const int PRO_SCI_ITEM_WIDTH = 451; //科学-程序猿模式最小宽度 const int STANDARD_FORMAT_PREC = 15; //标准模式科学计数位数 const int SCIENTIFIC_FORMAT_PREC = 31; //科学模式科学计数位数 const int MAXSIZE = 500; //内存保存最大数 //无内存时item高度 #define NOMEMORYHEIGHT(mode,labelheight)\ {\ if(mode != 1){\ labelheight = m_listwidget->frameRect().height() + 30;\ }\ else {\ labelheight = 302;\ }\ } MemoryWidget::MemoryWidget(int mode, QWidget *parent) : QWidget(parent) , m_listwidget(new MemoryListWidget(this)) , m_clearbutton(new IconButton(this, 1)) , m_memoryDelegate(new MemoryItemDelegate(this)) { this->setAttribute(Qt::WA_DeleteOnClose); m_label = new QLabel(this); m_calculatormode = mode; m_evaluator = Evaluator::instance(); this->setContentsMargins(0, 0, 0, 0); QVBoxLayout *lay = new QVBoxLayout(this); QHBoxLayout *layH = new QHBoxLayout(); lay->setSpacing(0); lay->setMargin(0); lay->addWidget(m_listwidget); m_listwidget->setFrameShape(QFrame::NoFrame); //设置边框类型,无边框 switch (mode) { case 0: m_listwidget->setFixedHeight(STANDARD_MWIDGET_HEIGHT); m_itemwidth = STANDARD_ITEM_WIDTH; m_precision = STANDARD_FORMAT_PREC; break; case 1: m_listwidget->setFixedHeight(SCIENTIFIC_MWIDGET_HEIGHT); m_itemwidth = PRO_SCI_ITEM_WIDTH; m_precision = SCIENTIFIC_FORMAT_PREC; break; default: m_listwidget->setFixedHeight(PROGRAMMER_MWIDGET_HEIGHT); m_itemwidth = PRO_SCI_ITEM_WIDTH; m_precision = STANDARD_FORMAT_PREC; break; } m_listwidget->setVerticalScrollMode(QListView::ScrollPerPixel); //鼠标滚轮滚动一次一个像素 m_listwidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); //设置垂直滚条 m_listwidget->setAutoScroll(false); //鼠标在视口边缘时是否自动滚动内容 m_listwidget->setSelectionRectVisible(false); //选择矩形框是否可见 m_listwidget->setItemDelegate(m_memoryDelegate); m_label->hide(); memoryclean(); lay->addStretch(); layH->addStretch(); layH->addWidget(m_clearbutton); layH->addSpacing(10); if (mode == 1) m_clearbutton->hide(); lay->addLayout(layH); lay->addSpacing(6); this->setLayout(lay); m_label->setText(tr("Nothing saved in memory")); m_label->setAlignment(Qt::AlignCenter); //label字体居右,居上 int labelheight = 0; NOMEMORYHEIGHT(m_calculatormode, labelheight); m_label->setFixedSize(QSize(m_itemwidth, labelheight)); m_label->setAttribute(Qt::WA_TranslucentBackground); //label窗体透明 QFont font; font.setPixelSize(16); m_label->setFont(font); m_label->setAttribute(Qt::WA_TransparentForMouseEvents, true); //label鼠标穿透 m_listwidget->installEventFilter(this); m_clearbutton->installEventFilter(this); this->installEventFilter(this); if (m_calculatormode != 1) setTabOrder(m_listwidget, m_clearbutton); } /** * @brief MemoryWidget::generateData * 向数字内存中增加一个数字,同时向保存Quantity的list中添加数据,一一对应 * @param answer * 将输入的数字转换为quantity类型 */ void MemoryWidget::generateData(const Quantity answer, bool ismax) { m_label->hide(); if (ismax) m_listwidget->takeItem(MAXSIZE - 1); if (m_memorypublic->isEmpty()) { m_listwidget->clear(); } QListWidgetItem *item1 = new QListWidgetItem(); item1->setFlags(Qt::ItemIsEditable); QFont font; font.setPixelSize(30); item1->setFont(font); item1->setSizeHint(QSize(m_itemwidth, 40 + 45 * m_line)); MemoryItemWidget *widget = new MemoryItemWidget(this); widget->setFixedSize(QSize(m_itemwidth, 40 + 45 * m_line)); m_listwidget->insertItem(0, item1); m_listwidget->setItemWidget(item1, widget); QString formatResult = QString(); if (m_calculatormode == 2) { const QString result = programmerResult(answer); formatResult = Utils::formatThousandsSeparatorsPro(result, Settings::instance()->programmerBase); } else { const QString result = DMath::format(answer, Quantity::Format::General() + Quantity::Format::Precision(m_precision)); formatResult = Utils::formatThousandsSeparators(result); } formatResult = setitemwordwrap(formatResult); widget->setTextLabel(formatResult); connect(widget, &MemoryItemWidget::plusbtnclicked, this, [ = ]() { int row = m_listwidget->row(item1); emit MemoryWidget::widgetplus(row); }); connect(widget, &MemoryItemWidget::minusbtnclicked, this, [ = ]() { int row = m_listwidget->row(item1); emit MemoryWidget::widgetminus(row); }); connect(widget, &MemoryItemWidget::cleanbtnclicked, this, [ = ]() { emit widgetclean(m_listwidget->row(item1), m_calculatormode, false); m_listwidget->takeItem(m_listwidget->row(item1)); delete item1; if (m_listwidget->count() == 0) { m_memorypublic->memoryclean(); } }); widget->themetypechanged(m_themetype); connect(this, &MemoryWidget::themechange, widget, &MemoryItemWidget::themetypechanged); connect(widget, &MemoryItemWidget::menuclean, this, [ = ]() { //item菜单MC emit widgetclean(m_listwidget->row(item1), m_calculatormode, true); m_listwidget->takeItem(m_listwidget->row(item1)); delete item1; if (m_listwidget->count() == 0) { m_memorypublic->memoryclean(); } }); connect(widget, &MemoryItemWidget::menucopy, this, [ = ]() { //item菜单复制 QClipboard *clipboard = QApplication::clipboard(); MemoryItemWidget *w1 = static_cast(m_listwidget->itemWidget(item1)); clipboard->setText(w1->textLabel().remove("\n")); }); connect(widget, &MemoryItemWidget::menuplus, this, [ = ]() { //item菜单M+ int row = m_listwidget->row(item1); emit MemoryWidget::widgetplus(row); }); connect(widget, &MemoryItemWidget::menuminus, this, [ = ]() { //item菜单M- int row = m_listwidget->row(item1); emit MemoryWidget::widgetminus(row); }); } void MemoryWidget::mousePressEvent(QMouseEvent *event) { QMouseEvent *pEvent = static_cast(event); m_mousepoint = pEvent->pos(); QRect rect(this->frameGeometry()); if (rect.contains(m_mousepoint) == true) emit insidewidget(); QWidget::mousePressEvent(event); } /** * @brief 利用事件过滤器防止打开内存界面时focus到titlebar上 */ bool MemoryWidget::eventFilter(QObject *obj, QEvent *event) { if (obj == this && event->type() == QEvent::KeyPress) { QKeyEvent *key_event = static_cast < QKeyEvent *>(event); //将事件转化为键盘事件 if (key_event->key() == Qt::Key_Tab) { if (!m_memorypublic->isEmpty()) { m_listwidget->setCurrentRow(m_currentrow); m_listwidget->setFocus(); } else { setFocus(); } return true; } } if (m_calculatormode != 1) { if (event->type() == QEvent::FocusOut && !(m_listwidget->hasFocus() || m_clearbutton->hasFocus() || this->hasFocus())) { emit hideWidget(); } if (obj == m_listwidget || obj == m_clearbutton) { if (event->type() == QEvent::KeyPress) { QKeyEvent *key_event = static_cast < QKeyEvent *>(event); //将事件转化为键盘事件 if (key_event->key() == Qt::Key_Tab) { if (m_listwidget->hasFocus()) { m_clearbutton->setFocus(Qt::TabFocusReason); } else if (m_clearbutton->hasFocus()) { m_listwidget->setFocus(Qt::TabFocusReason); } return true; } if (key_event->key() == Qt::Key_Escape) { emit hideWidget(); return true; } } } } return QWidget::eventFilter(obj, event); } /** * @brief 设置焦点到该widget时转移至listwidget */ void MemoryWidget::focusInEvent(QFocusEvent *event) { if (!m_memorypublic->isEmpty() && event->reason() == Qt::TabFocusReason) { m_listwidget->setCurrentRow(m_currentrow); m_listwidget->setFocus(); } QWidget::focusInEvent(event); } void MemoryWidget::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) emit hideWidget(); else return; } void MemoryWidget::memoryAnsChanged(int row, const Quantity answer) { QString formatResult = QString(); if (m_calculatormode == 2) { const QString result = programmerResult(answer); formatResult = Utils::formatThousandsSeparatorsPro(result, Settings::instance()->programmerBase); } else { const QString result = DMath::format(answer, Quantity::Format::General() + Quantity::Format::Precision(m_precision)); formatResult = Utils::formatThousandsSeparators(result); } formatResult = setitemwordwrap(formatResult, row); MemoryItemWidget *w1 = static_cast(m_listwidget->itemWidget(m_listwidget->item(row))); w1->setTextLabel(formatResult); } /** * @brief MemoryWidget::memoryclean * 清空内存列表,同步清空quantity list */ void MemoryWidget::memoryclean() { m_listwidget->setFocusPolicy(Qt::NoFocus); //内存无内容时NoFocus m_label->show(); m_listwidget->clear(); QListWidgetItem *item1 = new QListWidgetItem(m_listwidget); m_listwidget->insertItem(0, item1); if (m_calculatormode != 1) m_listwidget->item(0)->setSizeHint(QSize(m_itemwidth, m_listwidget->frameRect().height())); //标准模式 else m_listwidget->item(0)->setSizeHint(QSize(m_itemwidth, SCIENTIFIC_MWIDGET_HEIGHT)); //科学模式 m_listwidget->item(0)->setFlags(Qt::NoItemFlags); emptymemoryfontcolor(); m_clearbutton->hide(); } /** * @brief 内存中没有数据的字体颜色 */ void MemoryWidget::emptymemoryfontcolor() { DPalette pl = this->palette(); if (m_themetype == 1) { QColor color(85, 85, 85); color.setAlphaF(0.4); pl.setColor(DPalette::WindowText, QColor(color)); } else { QColor color(192, 198, 212); color.setAlphaF(0.4); pl.setColor(DPalette::WindowText, QColor(color)); } m_label->setPalette(pl); } /** * 程序员专用换行 */ QString MemoryWidget::programmerWrap(QString result) { QFont font = qApp->font(); font.setPixelSize(29); QFontMetrics fm(font); int validwidth = PRO_SCI_ITEM_WIDTH - 30; int l = 0, r = 0; int last = result.length(); int block; if (16 == Settings::instance()->programmerBase || 2 == Settings::instance()->programmerBase) block = 5; else block = 4; while (r < result.length()) { if (fm.width(result.mid(l, r - l)) < validwidth) ++r; else { while (result.at(r) != QLatin1String(" ") && result.at(r) != QLatin1String(",")) { --r; if (r <= l) break; } if (last < r - l) { r -= block; } result.insert(r + 1, "\n"); ++m_line; last = r - l; r += 2; l = r; } } return result; } int MemoryWidget::fontHeight() { QFont font = qApp->font(); font.setPixelSize(29); QFontMetrics fm(font); return fm.height() + 1; } /** * 字体变化需要重设高度 */ void MemoryWidget::resetItemHeight() { //程序员模式不在这里处理 if (2 == m_calculatormode || m_memorypublic->isEmpty()) return; for (int i = 0; i < m_listwidget->count(); i++) { if (m_listwidget->item(i)) { int line = static_cast(m_listwidget->itemWidget(m_listwidget->item(i)))->getLine(); //设置item高度 m_listwidget->item(i)->setSizeHint(QSize(m_itemwidth, 40 + fontHeight() * line)); m_listwidget->itemWidget(m_listwidget->item(i))->setFixedSize(QSize(m_itemwidth, 40 + fontHeight() * line)); static_cast(m_listwidget->itemWidget(m_listwidget->item(i)))->setLineHight(line, fontHeight()); } } } /** * @brief MR */ QPair MemoryWidget::getfirstnumber() { QPair p1; if (!m_memorypublic->isEmpty()) { MemoryItemWidget *w1 = static_cast(m_listwidget->itemWidget(m_listwidget->item(0))); QString str = w1->textLabel(); p1.first = str.remove("\n"); p1.second = m_memorypublic->getList().at(0); return p1; } else { p1.first = QString(); p1.second = Quantity(0); return p1; } } MemoryListWidget *MemoryWidget::getMemoryWidget() { return m_listwidget; } /** * @brief MemoryWidget::programmerResult * 根据当前进制显示相应的内存结果 */ QString MemoryWidget::programmerResult(const Quantity answer) { QString result; Quantity ans = DMath::integer(answer); switch (Settings::instance()->programmerBase) { case 16: return result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); case 8: return result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); case 2: return result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); default: return result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); } } /** * @brief MemoryWidget::resetAllLabelByBase * 打开内存列表时,根据当前进制刷新显示 */ void MemoryWidget::resetAllLabelByBase() { if (m_memorypublic->isEmpty()) return; QString text; if (m_calculatormode == 2) { for (int i = 0; i < m_listwidget->count(); i++) { text = Utils::reformatSeparatorsPro(programmerResult(m_memorypublic->getList().at(i)), Settings::instance()->programmerBase); text = setitemwordwrap(text, i); static_cast(m_listwidget->itemWidget(m_listwidget->item(i)))->setTextLabel(text); } } } /** * @brief MemoryWidget::resetLabelBySeparator * 按分割符位数重新设置文本 */ void MemoryWidget::resetLabelBySeparator() { if (m_memorypublic->isEmpty()) return; QString text; for (int i = 0; i < m_listwidget->count(); i++) { auto wgt = static_cast(m_listwidget->itemWidget(m_listwidget->item(i))); text = Utils::formatThousandsSeparators(wgt->textLabel().remove(",")); wgt->setTextLabel(text); } } void MemoryWidget::initConnect() { connect(m_memorypublic, &MemoryPublic::generateDataSig, this, &MemoryWidget::generateData); connect(m_memorypublic, &MemoryPublic::memorycleanSig, this, &MemoryWidget::memoryclean); connect(m_memorypublic, &MemoryPublic::memoryAnsSig, this, &MemoryWidget::memoryAnsChanged); connect(m_memorypublic, &MemoryPublic::widgetcleanSig, this, &MemoryWidget::widgetcleanslot); connect(m_memorypublic, &MemoryPublic::setThemeTypeSig, this, &MemoryWidget::setThemeType); connect(m_clearbutton, &TextButton::space, this, [ = ]() { m_memorypublic->memoryclean(); setFocus(); }); //focus下空格按下 connect(m_clearbutton, &DPushButton::clicked, this, [ = ]() { m_memorypublic->memoryclean(); setFocus(); }); connect(m_listwidget, &MemoryListWidget::itemselected, this, [ = ](int row, bool isselect) { if (!m_memorypublic->isEmpty() && isselect) { QPair p; MemoryItemWidget *w1 = static_cast(m_listwidget->itemWidget(m_listwidget->item(row))); p.first = w1->textLabel(); p.second = m_memorypublic->getList().at(row); if (m_listwidget->item(row)->flags() != Qt::NoItemFlags) emit itemclick(p); } }); connect(m_listwidget, &MemoryListWidget::space, this, [ = ] { if (!m_memorypublic->isEmpty()) //只有listwidget在focus状态才会触发keypress,所以此处未进行hasfocus判断 { QPair p; int row = m_listwidget->currentRow(); MemoryItemWidget *w1 = static_cast(m_listwidget->itemWidget(m_listwidget->item(row))); p.first = w1->textLabel(); p.second = m_memorypublic->getList().at(row); if (m_listwidget->item(row)->flags() != Qt::NoItemFlags) emit itemclick(p); } }); connect(m_listwidget, &MemoryListWidget::focus, this, [ = ](int direction) { switch (direction) { //只有listwidget在focus状态才会触发keypress,所以此处未进行hasfocus判断 case 0: if (m_listwidget->currentRow() > 0) { m_listwidget->setCurrentRow(m_listwidget->currentRow() - 1); m_currentrow = m_listwidget->currentRow(); m_listwidget->scrollToItem(m_listwidget->item(m_listwidget->currentRow())); //滚动条跟随焦点项 } break; case 1: if (m_listwidget->currentRow() < (m_listwidget->count() - 1)) { m_listwidget->setCurrentRow(m_listwidget->currentRow() + 1); m_currentrow = m_listwidget->currentRow(); m_listwidget->scrollToItem(m_listwidget->item(m_listwidget->currentRow())); //滚动条跟随焦点项 } break; default: break; } }); connect(m_listwidget, &MemoryListWidget::altAndM, this, [ = ]() { int row = m_listwidget->currentRow(); MemoryItemWidget *w1 = static_cast(m_listwidget->itemWidget(m_listwidget->item(row))); w1->showTextEditMenuByAltM(); }); connect(qApp, &QApplication::fontChanged, this, &MemoryWidget::resetItemHeight); } /** * @brief MemoryWidget::expressionempty * 当输入栏为空时,内存列表中的加减按钮置灰 * @param b * true = 空,false = 输入栏有内容 */ void MemoryWidget::expressionempty(bool b) { if (!m_memorypublic->isEmpty()) { for (int i = 0; i < m_listwidget->count(); i++) { static_cast(m_listwidget->itemWidget(m_listwidget->item(i)))->isexpressionempty(b); } } } /** * @brief MemoryWidget::widgetcleanslot * 内存列表item里的清除按钮,指定行数清除 * @param row * 指定的行数 * @param mode * 用于区分是标准还是科学型的删除,防止同步删除时重复删除 */ void MemoryWidget::widgetcleanslot(int row, int mode, bool ismenu) { if (m_calculatormode != mode) { delete m_listwidget->takeItem(row); } else { if (row + 1 < m_listwidget->count() && !ismenu) static_cast(m_listwidget->itemWidget(m_listwidget->item(row + 1)))->setNextItemHover(); } } void MemoryWidget::setMemoryPublic(MemoryPublic *pub) { m_memorypublic = pub; initConnect(); } /** * @brief 替换text中的中文字符为英文字符 */ QString MemoryWidget::formatExpression(const QString &text) { return QString(text) .replace(CN_ADD, EN_ADD) .replace(CN_MIN, EN_MIN) .replace(CN_MUL, EN_MUL) .replace(CN_DIV, EN_DIV) .replace(EN_Comma, ""); } /** * @brief MemoryWidget::setitemwordwrap * @param text * @param row * 分行函数 * @return */ QString MemoryWidget::setitemwordwrap(const QString &text, int row) { QString result = text; result.replace('-', "-").replace('+', "+"); int index = result.indexOf("E"); m_line = 1; if (m_calculatormode == 0) { if (index > 0 && result.left(index).length() > 13) { result.insert(index, "\n"); m_line = 2; } else if (index <= 0 && result.length() > 21) { result.insert(20, "\n"); m_line = 2; } if (m_clearbutton->isHidden() == true) { m_clearbutton->show(); m_clearbutton->updateWhenBtnDisable(); m_clearbutton->showtooltip(true); } } else if (m_calculatormode == 1) { if (index > 15) { result.insert(index, "\n"); m_line = 2; if (index > 20) { result.remove("\n"); result.insert(20, "\n"); m_line = 2; } } else if (index <= 0 && result.length() > 21) { result.insert(20, "\n"); m_line = 2; } } else { result = programmerWrap(result); if (m_clearbutton->isHidden() == true) { m_clearbutton->show(); m_clearbutton->updateWhenBtnDisable(); m_clearbutton->showtooltip(true); } } if (m_listwidget->item(row)) { //设置item高度 m_listwidget->item(row)->setSizeHint(QSize(m_itemwidth, 40 + fontHeight() * m_line)); m_listwidget->itemWidget(m_listwidget->item(row))->setFixedSize(QSize(m_itemwidth, 40 + fontHeight() * m_line)); } static_cast(m_listwidget->itemWidget(m_listwidget->item(row)))->setLineHight(m_line, fontHeight()); //设置item中label高度 return result; } /** * @brief 根据主题变换垃圾桶及内存中没有数据字体颜色 */ void MemoryWidget::setThemeType(int type) { m_listwidget->update(); //刷新widget int typeIn = type; if (typeIn == 0) { typeIn = DGuiApplicationHelper::instance()->themeType(); } m_themetype = typeIn; emit themechange(m_themetype); QString path; if (m_themetype == 1) { path = QString(":/assets/images/%1/").arg("light"); m_clearbutton->setIconUrl(path + "empty_normal.svg", path + "empty_hover.svg", path + "empty_press.svg", 1); if (m_memorypublic->isEmpty()) { emptymemoryfontcolor(); //更改内存中没有数据字体颜色 } } else { path = QString(":/assets/images/%1/").arg("dark"); m_clearbutton->setIconUrl(path + "empty_normal.svg", path + "empty_hover.svg", path + "empty_press.svg", 1); if (m_memorypublic->isEmpty()) { emptymemoryfontcolor(); //更改内存中没有数据字体颜色 } } } MemoryWidget::~MemoryWidget() { } deepin-calculator-5.7.21/src/views/memorywidget.h000066400000000000000000000064521423020056600220170ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * Maintainer: xiajing * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MEMORYWIDGET_H #define MEMORYWIDGET_H #include "../../3rdparty/core/evaluator.h" #include "../control/iconbutton.h" #include "memoryitemwidget.h" #include "memorylistwidget.h" #include "memoryitemdelegate.h" #include #include #include #include #include #include #include /** * @brief 标准模式内存界面 */ class MemoryPublic; class MemoryWidget : public QWidget { Q_OBJECT public: explicit MemoryWidget(int mode = 0, QWidget *parent = nullptr); ~MemoryWidget() override; void generateData(const Quantity answer, bool ismax); void mousePressEvent(QMouseEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override; void focusInEvent(QFocusEvent *event) override; void keyPressEvent(QKeyEvent *event) override; void memoryAnsChanged(int row, const Quantity answer); void memoryclean();//内存列表为空时插入一个item QPair getfirstnumber();//MR MemoryListWidget *getMemoryWidget(); QString programmerResult(const Quantity answer); void resetAllLabelByBase(); void resetLabelBySeparator(); public slots: void setThemeType(int type); void expressionempty(bool b); void widgetcleanslot(int row, int mode, bool ismenu); void setMemoryPublic(MemoryPublic *pub); signals: void widgetplus(int row); void widgetminus(int row); void insidewidget(); void itemclick(const QPair); void themechange(int type); void widgetclean(int row, int mode, bool ismenu); //是否通过menu点击发出,用于区分是否下一个item直接进入hover状态 void hideWidget(); private: void initConnect(); QString formatExpression(const QString &text); QString setitemwordwrap(const QString &text, int row = 0); void emptymemoryfontcolor(); QString programmerWrap(QString result); int fontHeight(); private slots: void resetItemHeight(); private: MemoryListWidget *m_listwidget; QPoint m_mousepoint; IconButton *m_clearbutton; Evaluator *m_evaluator; Quantity m_ans; bool m_ansVaild; int m_themetype = 0; int m_calculatormode;//0-标准下拉 1-科学右侧 int m_line = 1; //item数字行数 MemoryItemDelegate *m_memoryDelegate; int m_itemwidth = 0; int m_precision = -1;//计算精度 QLabel *m_label;//内存为空item int m_currentrow = 0;//listwidget当前行 MemoryPublic *m_memorypublic = nullptr; }; #endif // MEMORYWIDGET_H deepin-calculator-5.7.21/src/views/programmerarrowdelegate.cpp000066400000000000000000000044571423020056600245620ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "programmerarrowdelegate.h" #include #include #include "memorylistwidget.h" #include "programmeritemwidget.h" ProgrammerArrowDelegate::ProgrammerArrowDelegate(QObject *parent) : QStyledItemDelegate(parent) { } ProgrammerArrowDelegate::~ProgrammerArrowDelegate() { } void ProgrammerArrowDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { //边框绘制 MemoryListWidget *dragWidget = qobject_cast(option.styleObject); QRectF rect = dragWidget->rect(); //获取memorylistwidget.rect绘制背景色 painter->setRenderHint(QPainter::Antialiasing, true); int type = DGuiApplicationHelper::instance()->themeType(); if (type == 1) { painter->setPen(Qt::NoPen); painter->setBrush(QColor("#F8F8F8")); painter->drawRect(rect); } else { painter->setPen(Qt::NoPen); painter->setBrush(QColor("#252525")); painter->drawRect(rect); } if (dragWidget->hasFocus()) { QRectF itemrect(dragWidget->visualItemRect(dragWidget->currentItem())); QColor color(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name()); painter->setBrush(color); painter->drawRect(itemrect); //背景填充 } QStyledItemDelegate::paint(painter, option, index); } void ProgrammerArrowDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(index); editor->setGeometry(option.rect); } deepin-calculator-5.7.21/src/views/programmerarrowdelegate.h000066400000000000000000000025761423020056600242270ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROGRAMMERARROWDELEGATE_H #define PROGRAMMERARROWDELEGATE_H #include #include #include #include DWIDGET_USE_NAMESPACE class ProgrammerArrowDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit ProgrammerArrowDelegate(QObject *parent = nullptr); ~ProgrammerArrowDelegate() override; protected: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; #endif // PROGRAMMERARROWDELEGATE_H deepin-calculator-5.7.21/src/views/programmeritemwidget.cpp000066400000000000000000000273501423020056600240740ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "programmeritemwidget.h" #include #include ProgrammerItemWidget::ProgrammerItemWidget(QString label, const int width, const QString path, QWidget *parent) : QWidget(parent) , m_iconbtn(new DIconButton(this)) , m_label(new QLabel(label)) , m_iconRenderer(new QSvgRenderer(this)) { m_width = width; setMouseTracking(true); setFocusPolicy(Qt::NoFocus); m_iconbtn->setFocusPolicy(Qt::NoFocus); setFixedSize(QSize(width, 34)); setAttribute(Qt::WA_TranslucentBackground, true); m_currentUrl = path; m_iconbtn->setFlat(true); m_iconbtn->setIconSize(QSize(34, 34)); //图片有边框,不能与ui图大小一致ui(20, 20) m_iconbtn->setAttribute(Qt::WA_TransparentForMouseEvents, true); QWidget *markWidget = new QWidget(this); markWidget->setFixedSize(12, 10); QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->addSpacing(10); hlayout->addWidget(markWidget); hlayout->addSpacing(2); hlayout->addWidget(m_label); m_label->setFixedWidth(width - 70); QFont font; font.setWeight(2); font.setPixelSize(14); m_label->setFont(font); hlayout->addStretch(); hlayout->addWidget(m_iconbtn); hlayout->setMargin(0); hlayout->setContentsMargins(0, 0, 16, 0); //图片比ui大10,此处边框比ui小5 setLayout(hlayout); this->installEventFilter(this); setMouseTracking(true); m_label->installEventFilter(this); m_label->setMouseTracking(true); m_iconbtn->installEventFilter(this); m_iconbtn->setMouseTracking(true); markWidget->installEventFilter(this); markWidget->setMouseTracking(true); initMark(); m_isshift = true; connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &ProgrammerItemWidget::themetypechanged); } ProgrammerItemWidget::ProgrammerItemWidget(QString label, QWidget *parent) : QWidget(parent) , m_label(new QLabel(label)) { setFixedSize(QSize(250, 34)); setFocusPolicy(Qt::NoFocus); setAttribute(Qt::WA_TranslucentBackground, true); QWidget *markWidget = new QWidget(this); markWidget->setFixedSize(12, 10); QHBoxLayout *hlayout = new QHBoxLayout(); hlayout->addSpacing(10); hlayout->addWidget(markWidget); hlayout->addSpacing(2); hlayout->addWidget(m_label); QFont font; font.setWeight(2); font.setPixelSize(14); m_label->setFont(font); hlayout->setMargin(0); hlayout->setContentsMargins(0, 0, 21, 0); setLayout(hlayout); this->installEventFilter(this); setMouseTracking(true); m_label->installEventFilter(this); m_label->setMouseTracking(true); markWidget->installEventFilter(this); markWidget->setMouseTracking(true); initMark(); m_isshift = false; connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &ProgrammerItemWidget::themetypechanged); } ProgrammerItemWidget::~ProgrammerItemWidget() { } void ProgrammerItemWidget::enterEvent(QEvent *event) { m_ishover = true; update(); QWidget::enterEvent(event); } void ProgrammerItemWidget::leaveEvent(QEvent *event) { m_ishover = false; update(); QWidget::leaveEvent(event); } void ProgrammerItemWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) return; // setFocus(); m_ispress = true; update(); QWidget::mousePressEvent(event); } void ProgrammerItemWidget::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) return; if (m_ispress == true && this->rect().contains(event->pos())) { m_ishover = true; } m_ispress = false; update(); QWidget::mouseReleaseEvent(event); } void ProgrammerItemWidget::paintEvent(QPaintEvent *e) { Q_UNUSED(e); QRectF rect = this->rect(); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); //防走样 painter.setPen(Qt::NoPen); QColor press, hover, text, background; QColor actcolor = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name();//活动色 press = actcolor; hover = actcolor; text = QColor("#FFFFFF"); if (m_themetype == 1) background = QColor("#F8F8F8"); else background = QColor("#252525"); if (m_ispress) { painter.setPen(Qt::NoPen); painter.setBrush(press); painter.drawRect(rect); //press状态下对item进行颜色填充 DPalette pl1 = this->palette(); //按下时给label字体设置颜色 text.setAlphaF(0.5); pl1.setColor(DPalette::Text, text); pl1.setColor(DPalette::HighlightedText, text); m_label->setPalette(pl1); m_currentUrl = m_pressUrl; } else if (m_ishover || m_isfocus) { painter.setPen(Qt::NoPen); painter.setBrush(press); painter.drawRect(rect); //press状态下对item进行颜色填充 DPalette pl1 = this->palette(); //按下时给label字体设置颜色 text.setAlphaF(1); pl1.setColor(DPalette::Text, text); pl1.setColor(DPalette::HighlightedText, text); m_label->setPalette(pl1); m_currentUrl = m_hoverUrl; } else { DPalette pl1 = this->palette(); //按下时给label字体设置颜色 if (m_themetype == 1) { pl1.setColor(DPalette::Text, QColor("#000000")); pl1.setColor(DPalette::HighlightedText, QColor("#000000")); } else { pl1.setColor(DPalette::Text, QColor("#FFFFFF")); pl1.setColor(DPalette::HighlightedText, QColor("#FFFFFF")); } m_label->setPalette(pl1); m_currentUrl = m_normalUrl; } drawMark(&painter); if (m_isshift) { m_pixmap.load(m_currentUrl); drawIcon(&painter); } } bool ProgrammerItemWidget::eventFilter(QObject *obj, QEvent *event) { //bug 101004 if(QEvent::Show == event->type()){ m_ishover=false; m_isfocus=false; m_ispress=false; } if (event->type() == QEvent::MouseMove) { if (!m_ispress) { m_ishover = true; } return false; } return QWidget::eventFilter(obj, event); } void ProgrammerItemWidget::cleanHoverState() { m_ishover = false; update(); } /** * @brief ProgrammerItemWidget::cleanFocusState * 取消focus状态 */ void ProgrammerItemWidget::cleanFocusState() { m_isfocus = false; update(); } /** * @brief ProgrammerItemWidget::isMarkHide * @param ishide:是否隐藏勾 * 当前已选中和点击的行显示勾,其他行隐藏 */ void ProgrammerItemWidget::isMarkHide(bool ishide) { m_isMarkHide = ishide; } void ProgrammerItemWidget::drawMark(QPainter *painter) const { if (!m_isMarkHide) { QPen pen; QColor color; if (m_ispress) { color = QColor("#FFFFFF"); color.setAlphaF(0.5); } else if (m_ishover || m_isfocus) { color = QColor("#FFFFFF"); } else { if (m_themetype == 1) { color = QColor("#000000"); } else { color = QColor("#FFFFFF"); } } pen.setColor(color); pen.setWidth(2); painter->setPen(pen); painter->drawPolyline(m_pointVec); } } /** * @brief ProgrammerItemWidget::initMark * 初始化勾所需要的点和容器 */ void ProgrammerItemWidget::initMark() { m_markstart = QPoint(this->rect().x() + 10, this->rect().y() + 18); m_markmid = QPoint(this->rect().x() + 14, this->rect().y() + 22); m_markend = QPoint(this->rect().x() + 22, this->rect().y() + 12); m_pointVec << m_markstart; m_pointVec << m_markmid; m_pointVec << m_markend; } /** * @brief ProgrammerItemWidget::iconChanged * @param status:0-normal 1-hover 2-press * 根据不同鼠标事件修改icon图片 */ void ProgrammerItemWidget::drawIcon(QPainter *painter) const { painter->save(); QFile file(m_currentUrl); file.open(QIODevice::ReadOnly); QByteArray baData = file.readAll(); QDomDocument doc; doc.setContent(baData); file.close(); if (m_ispress) { doc.documentElement().setAttribute("fill-opacity", QLatin1String("0.5")); } QRectF frameRect = m_iconbtn->rect(); frameRect.moveTo(m_width - 50, 0); m_iconRenderer->load(doc.toByteArray()); m_iconRenderer->render(painter, frameRect); painter->restore(); } void ProgrammerItemWidget::themetypechanged(int type) { //主题改变时切换悬浮框图片 QString path; if (DGuiApplicationHelper::instance()->themeType() == 2) { path = QString(":/assets/images/%1/").arg("dark"); if (m_label->text() == tr("Arithmetic shift")) { m_normalUrl = path + "icon_as_normal.svg"; m_hoverUrl = path + "icon_as_hover.svg"; m_pressUrl = path + "icon_as_hover.svg"; } else if (m_label->text() == tr("Logical shift")) { m_normalUrl = path + "icon_ls_normal.svg"; m_hoverUrl = path + "icon_ls_hover.svg"; m_pressUrl = path + "icon_ls_hover.svg"; } else if (m_label->text() == tr("Circular shift")) { m_normalUrl = path + "icon_ro_normal.svg"; m_hoverUrl = path + "icon_ro_hover.svg"; m_pressUrl = path + "icon_ro_hover.svg"; } else if (m_label->text() == tr("Rotate through carry circular shift")) { m_normalUrl = path + "icon_rc_normal.svg"; m_hoverUrl = path + "icon_rc_hover.svg"; m_pressUrl = path + "icon_rc_hover.svg"; } } else { path = QString(":/assets/images/%1/").arg("light"); if (m_label->text() == tr("Arithmetic shift")) { m_normalUrl = path + "icon_as_normal.svg"; m_hoverUrl = path + "icon_as_menuhover.svg"; m_pressUrl = path + "icon_as_menuhover.svg"; } else if (m_label->text() == tr("Logical shift")) { m_normalUrl = path + "icon_ls_normal.svg"; m_hoverUrl = path + "icon_ls_menuhover.svg"; m_pressUrl = path + "icon_ls_menuhover.svg"; } else if (m_label->text() == tr("Circular shift")) { m_normalUrl = path + "icon_ro_normal.svg"; m_hoverUrl = path + "icon_ro_menuhover.svg"; m_pressUrl = path + "icon_ro_menuhover.svg"; } else if (m_label->text() == tr("Rotate through carry circular shift")) { m_normalUrl = path + "icon_rc_normal.svg"; m_hoverUrl = path + "icon_rc_menuhover.svg"; m_pressUrl = path + "icon_rc_menuhover.svg"; } } m_themetype = type; DPalette pl1 = this->palette(); //itemwidget字体颜色设置 if (m_themetype == 1) { pl1.setColor(DPalette::Text, QColor("#000000")); } else { pl1.setColor(DPalette::Text, QColor("#FFFFFF")); } m_label->setPalette(pl1); } void ProgrammerItemWidget::setFocus() { m_isfocus = true; update(); } void ProgrammerItemWidget::resetWidth(const int width) { m_width = width; setFixedSize(QSize(width, 34)); m_label->setFixedWidth(width - 80); update(); } deepin-calculator-5.7.21/src/views/programmeritemwidget.h000066400000000000000000000051771423020056600235440ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROGRAMMERITEMWIDGET_H #define PROGRAMMERITEMWIDGET_H #include #include #include #include #include #include #include #include #include #include DWIDGET_USE_NAMESPACE class ProgrammerItemWidget : public QWidget { Q_OBJECT public: ProgrammerItemWidget(QString label, const int width, const QString path, QWidget *parent = nullptr); ProgrammerItemWidget(QString label, QWidget *parent = nullptr); ~ProgrammerItemWidget() override; void enterEvent(QEvent *event) override; void leaveEvent(QEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void paintEvent(QPaintEvent *e) override; bool eventFilter(QObject *obj, QEvent *event) override; void cleanHoverState(); void cleanFocusState(); void isMarkHide(bool ishide); public slots: void themetypechanged(int type); void setFocus(); void resetWidth(const int width); // 重设宽度,用于字体改变的时候 private: void drawMark(QPainter *painter) const; void initMark(); void drawIcon(QPainter *painter) const; private: DIconButton *m_iconbtn; QLabel *m_label; bool m_ispress = false; bool m_ishover = false; bool m_isfocus = false; int m_themetype = 1; QSvgRenderer *m_iconRenderer; bool m_isshift = false; //判断是数据的列表还是移位的列表 int m_width = 0;//宽度 //画一个勾 QPoint m_markstart; QPoint m_markmid; QPoint m_markend; QVector m_pointVec; QPen m_markPen; bool m_isMarkHide = true; //画一张图 QPixmap m_pixmap; QString m_normalUrl = QString(); QString m_hoverUrl; QString m_pressUrl; QString m_currentUrl = QString(); }; #endif // PROGRAMMERITEMWIDGET_H deepin-calculator-5.7.21/src/views/prolistdelegate.cpp000066400000000000000000000143551423020056600230260ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "prolistdelegate.h" #include #include #include #include #include "prolistmodel.h" #include "prolistview.h" #include "../utils.h" DWIDGET_USE_NAMESPACE const int LEFT_MARGIN = 12; //prolistview左边距 ProListDelegate::ProListDelegate(QObject *parent) : QStyledItemDelegate(parent) { } ProListDelegate::~ProListDelegate() { } void ProListDelegate::setThemeType(int type) { m_themeType = type; } void ProListDelegate::currentfocusindex(QModelIndex index) { m_focusindex = index; } void ProListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->setRenderHint(QPainter::HighQualityAntialiasing, true); const QString expression = index.data(ProListModel::ExpressionRole).toString(); ProListView *listview = qobject_cast(option.styleObject); QRect selectrect(option.rect.x() + LEFT_MARGIN, option.rect.y() + 2, 3, option.rect.height() - 4); //被选中行选中标记 QRect hoverrect(option.rect.x() + LEFT_MARGIN, option.rect.y() + 1, 427, option.rect.height() - 2); //hover背景色 QRect textrect(option.rect.x() + 80 + LEFT_MARGIN, option.rect.y(), 268, 24); //textrect QRect systemrect(option.rect.x() + 10 + LEFT_MARGIN, option.rect.y(), 24, 24); //进制字体框 QRect systemrectbin(option.rect.x() + 10 + LEFT_MARGIN, option.rect.y(), 24, 28); //BIN进制字体框 QColor hoverbackground, fontColor, systemfontColor; if (m_themeType == 1) { hoverbackground = QColor(0, 0, 0); hoverbackground.setAlphaF(0.03); fontColor = QColor("#838483"); systemfontColor = QColor("#303030"); } else { hoverbackground = QColor(255, 255, 255); hoverbackground.setAlphaF(0.05); fontColor = QColor("#B4B4B4"); systemfontColor = QColor("#C0C6D4"); } QFont font; //结果字体 font.setPixelSize(14); // font.setLetterSpacing(QFont::PercentageSpacing, 0); //字间距0,未发现有效果 QFont systemfont; //进制字体 systemfont.setPixelSize(12); //选中框绘制 if (index == listview->currentIndex()) { painter->setPen(Qt::NoPen); painter->setBrush(QBrush(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color())); painter->drawRoundedRect(selectrect, 2, 2); } //进制字体绘制 painter->setFont(systemfont); if (index == listview->currentIndex()) painter->setPen(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color()); else painter->setPen(systemfontColor); switch (index.row()) { case 0: painter->drawText(systemrect, "HEX", Qt::AlignHCenter | Qt::AlignVCenter); break; case 1: painter->drawText(systemrect, "DEC", Qt::AlignHCenter | Qt::AlignVCenter); break; case 2: painter->drawText(systemrect, "OCT", Qt::AlignHCenter | Qt::AlignVCenter); break; case 3: painter->drawText(systemrectbin, "BIN", Qt::AlignHCenter | Qt::AlignVCenter); break; } //悬浮背景绘制 if (option.state & QStyle::State_MouseOver) { painter->setBrush(hoverbackground); painter->setPen(Qt::NoPen); painter->drawRoundedRect(hoverrect, 4, 4); } //结果字体绘制 painter->setFont(font); painter->setPen(fontColor); if (index.row() == 3) { if (expression.size() > 39) { //显示64位时 //第一行 painter->drawText(QRect(option.rect.x() + 80 + LEFT_MARGIN, option.rect.y(), 280, 14), expression.mid(0, 39), Qt::AlignLeft | Qt::AlignVCenter); //第二行 painter->drawText(QRect(option.rect.x() + 80 + LEFT_MARGIN, option.rect.y() + 14, 280, 14), expression.mid(40, -1), Qt::AlignLeft | Qt::AlignVCenter); } else { painter->drawText(QRect(option.rect.x() + 80 + LEFT_MARGIN, option.rect.y(), 280, 28), expression, Qt::AlignLeft | Qt::AlignVCenter); } } else painter->drawText(textrect, expression, Qt::AlignLeft | Qt::AlignVCenter); drawFocusStatus(painter, option); //焦点边框 } QSize ProListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(option); if (index.row() == 3) return QSize(451, 28); else return QSize(451, 24); } bool ProListDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { Q_UNUSED(event); Q_UNUSED(model); Q_UNUSED(option); emit obtainingHistorical(index); return true; } void ProListDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(index); editor->setGeometry(option.rect); } void ProListDelegate::drawFocusStatus(QPainter *painter, const QStyleOptionViewItem &option) const { ProListView *listview = qobject_cast(option.styleObject); if (listview->hasFocus()) { QRectF itemrect(listview->visualRect(m_focusindex)); QRectF frame(itemrect.left() + 1, itemrect.top() + 1, itemrect.width() - 2, itemrect.height() - 2); QPen pen; pen.setColor(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name()); pen.setWidth(2); painter->setPen(pen); painter->setBrush(Qt::NoBrush); painter->drawRect(frame); //focus边框 } } deepin-calculator-5.7.21/src/views/prolistdelegate.h000066400000000000000000000036061423020056600224700ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROLISTDELEGATE_H #define PROLISTDELEGATE_H #include #include #include DGUI_USE_NAMESPACE class ProListDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit ProListDelegate(QObject *parent = nullptr); ~ProListDelegate() override; public slots: void setThemeType(int type); void currentfocusindex(QModelIndex index); protected: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void drawFocusStatus(QPainter *painter, const QStyleOptionViewItem &option) const; signals: void obtainingHistorical(const QModelIndex &index); private: int m_themeType = 0; QModelIndex m_focusindex; }; #endif // PROLISTDELEGATE_H deepin-calculator-5.7.21/src/views/prolistmodel.cpp000066400000000000000000000075521423020056600223550ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "prolistmodel.h" #include "../utils.h" ProListModel::ProListModel(QObject *parent) : QAbstractListModel(parent) { clearItems(); } ProListModel::~ProListModel() {} void ProListModel::refrushModel() { beginResetModel(); endResetModel(); } int ProListModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_expressionList.size(); } QVariant ProListModel::data(const QModelIndex &index, int role) const { const int r = index.row(); switch (role) { case ExpressionRole: return m_expressionList.at(r); case ExpressionCount: return m_expressionList.count(); case ExpressionPrevious: return m_expressionList.value(r - 1); case ExpressionNext: return m_expressionList.value(r + 1); default: return QVariant(); } } /** * @brief 显示区清零 */ void ProListModel::clearItems() { m_expressionList.clear(); beginInsertRows(QModelIndex(), 0, 0); m_expressionList << ""; endInsertRows(); beginInsertRows(QModelIndex(), 1, 1); m_expressionList << ""; endInsertRows(); beginInsertRows(QModelIndex(), 2, 2); m_expressionList << ""; endInsertRows(); beginInsertRows(QModelIndex(), 3, 3); m_expressionList << ""; endInsertRows(); } /** * @brief 更新显示区 * @param text 输入栏中的结果内容 * @param index 当前选中行 * 由当前选中行结果计算出其他行结果,同时更新四行数据 */ void ProListModel::updataList(const Quantity ans) { m_expressionList.clear(); QString hex, dec, otc, bin; hex = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); otc = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); bin = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); dec = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); while (bin.startsWith('0') && bin.length() > 1) { bin.remove(0, 1); } int i = bin.length() % 4; if (bin != "0") { while (i != 4 && i != 0) { bin.insert(0, "0"); i++; } } hex = Utils::reformatSeparatorsPro(hex, 16); otc = Utils::reformatSeparatorsPro(otc, 8); bin = Utils::reformatSeparatorsPro(bin, 2); dec = Utils::reformatSeparatorsPro(dec, 10); //十六进制行 beginInsertRows(QModelIndex(), 0, 0); m_expressionList << hex; endInsertRows(); //十进制行 beginInsertRows(QModelIndex(), 1, 1); m_expressionList << dec; endInsertRows(); //八进制行 beginInsertRows(QModelIndex(), 2, 2); m_expressionList << otc; endInsertRows(); //二进制行 beginInsertRows(QModelIndex(), 3, 3); m_expressionList << bin; endInsertRows(); } void ProListModel::copyToClipboard(const int index) { QClipboard *clipboard = QApplication::clipboard(); QString copy = m_expressionList.at(index); clipboard->setText(copy.replace(" ", "")); } deepin-calculator-5.7.21/src/views/prolistmodel.h000066400000000000000000000031631423020056600220140ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROLISTMODEL_H #define PROLISTMODEL_H #include "../../3rdparty/core/evaluator.h" #include #include #include class ProListModel : public QAbstractListModel { Q_OBJECT public: explicit ProListModel(QObject *parent = nullptr); ~ProListModel() override; void refrushModel(); //model的data数据类型 enum Role { ExpressionRole = Qt::DisplayRole, //无提示文本 ExpressionCount = 4, //数据数量 ExpressionPrevious, //前一个数据 ExpressionNext //下一个数据 }; int rowCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; void clearItems(); void updataList(const Quantity ans); void copyToClipboard(const int index); private: QList m_expressionList; }; #endif // PROLISTMODEL_H deepin-calculator-5.7.21/src/views/prolistview.cpp000066400000000000000000000107061423020056600222220ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "prolistview.h" ProListView::ProListView(DWidget *parent) : DListView(parent) { setSelectionBehavior(QAbstractItemView::SelectRows); //选中一行 setSelectionMode(QAbstractItemView::SingleSelection); //选中单个目标 setFixedSize(451, 106); setMouseTracking(true); setFocusPolicy(Qt::TabFocus); connect(this, &DListView::clicked, [ = ](const QModelIndex & index) { itemclicked(index, false); }); } ProListView::~ProListView() { } void ProListView::contextMenuEvent(QContextMenuEvent *event) { QMenu *menu = new QMenu(this); //缺翻译 QAction *copy = new QAction(tr("Copy"), menu); menu->addAction(copy); connect(copy, &QAction::triggered, this, [ = ]() { static_cast(model())->copyToClipboard(indexAt(event->pos()).row()); }); menu->exec(event->globalPos()); delete menu; } void ProListView::showTextEditMenuByAltM(const QModelIndex &index) { m_isMenuAltM = true; QMenu *menu = new QMenu(this); //缺翻译 QAction *copy = new QAction(tr("Copy"), menu); menu->addAction(copy); connect(copy, &QAction::triggered, this, [ = ]() { static_cast(model())->copyToClipboard(index.row()); }); QPoint menupoint; menupoint.setX(mapToGlobal(visualRect(index).bottomRight()).x() - 10); menupoint.setY(mapToGlobal(visualRect(index).center()).y()); menu->exec(menupoint); delete menu; } /** * @brief ProListView::focusIndex * @return 返回当前focus的索引 */ QModelIndex ProListView::focusIndex() const { return model()->index(m_focusrow, 0); } QModelIndex ProListView::indexBeforeFocusOut() const { return model()->index(m_currentrow, 0); } /** * @brief ProListView::itemclicked * @param index:点击索引 * @param isspace:是否为键盘交互 * 进制列表的点击事件 */ void ProListView::itemclicked(const QModelIndex &index, bool isspace) { m_currentrow = index.row(); this->setCurrentIndex(index); emit obtainingHistorical(index, isspace); } void ProListView::keyPressEvent(QKeyEvent *e) { bool ispressalt = e->modifiers() == Qt::AltModifier; switch (e->key()) { case Qt::Key_Up: if (m_focusrow) m_focusrow--; else m_focusrow = 3; static_cast(itemDelegate(currentIndex()))->currentfocusindex(focusIndex()); update(); break; case Qt::Key_Down: if (m_focusrow < 3) m_focusrow++; else m_focusrow = 0; static_cast(itemDelegate(currentIndex()))->currentfocusindex(focusIndex()); update(); break; case Qt::Key_Space: case Qt::Key_Enter: case Qt::Key_Return: itemclicked(model()->index(m_focusrow, 0), true); // emit obtainingHistorical(model()->index(m_focusrow, 0)); break; case Qt::Key_M: if (ispressalt) showTextEditMenuByAltM(model()->index(m_focusrow, 0)); break; default: DListView::keyPressEvent(e); break; } } /** * @brief 焦点进入时设置焦点在第一条历史记录 */ void ProListView::focusInEvent(QFocusEvent *event) { // setCurrentIndex(this->model()->index(currentIndex().row(), 0)); //当alt+M的菜单取消后,focus到原本的焦点行 if (m_isMenuAltM) { static_cast(itemDelegate(currentIndex()))->currentfocusindex(focusIndex()); } else { setCurrentIndex(indexBeforeFocusOut()); static_cast(itemDelegate(currentIndex()))->currentfocusindex(currentIndex()); m_focusrow = currentIndex().row(); } scrollTo(this->model()->index(currentIndex().row(), 0)); DListView::focusInEvent(event); } deepin-calculator-5.7.21/src/views/prolistview.h000066400000000000000000000036121423020056600216650ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROLISTVIEW_H #define PROLISTVIEW_H #include "prolistmodel.h" #include "prolistdelegate.h" #include #include #include #include #include #include #include #include DWIDGET_USE_NAMESPACE class ProListView : public DListView { Q_OBJECT public: explicit ProListView(DWidget *parent = nullptr); ~ProListView() override; void contextMenuEvent(QContextMenuEvent *event) override; void showTextEditMenuByAltM(const QModelIndex &index); QModelIndex focusIndex() const; QModelIndex indexBeforeFocusOut() const; public slots: void itemclicked(const QModelIndex &index, bool isspace); protected: // void mouseMoveEvent(QMouseEvent *e); // void mousePressEvent(QMouseEvent *event); // void mouseReleaseEvent(QMouseEvent *event); void keyPressEvent(QKeyEvent *e) override; void focusInEvent(QFocusEvent *event) override; Q_SIGNALS: void obtainingHistorical(const QModelIndex &index, bool isspace); private: int m_focusrow = 1; int m_currentrow = 1; bool m_isMenuAltM = false; //是否是altM的菜单 }; #endif // PROLISTVIEW_H deepin-calculator-5.7.21/src/views/simplelistdelegate.cpp000066400000000000000000000426431423020056600235200ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "simplelistdelegate.h" #include #include #include #include #include #include #include "dthememanager.h" #include "simplelistmodel.h" #include "simplelistview.h" #include "../utils.h" DWIDGET_USE_NAMESPACE const int PADDING = 15; //历史记录区边距 const int NOHISTORYHEIGHT = 302; // 无历史记录rect高度 const int HISWIDTH = 451; //历史记录宽度 SimpleListDelegate::SimpleListDelegate(int mode, QObject *parent) : QStyledItemDelegate(parent) { m_mode = mode; m_selected = false; m_simpleListDelegate = this; } SimpleListDelegate::~SimpleListDelegate() { // delete m_simpleListDelegate; // m_simpleListDelegate = NULL; } /** * @brief 设置联动项 */ void SimpleListDelegate::setHisLink(const int link) { m_linkItem.push_back(link); } /** * @brief 设置被联动项 */ void SimpleListDelegate::setHisLinked(const int linked) { m_linkedIten.push_back(linked); } /** * @brief SimpleListDelegate::删除联动(暂未使用) * @param link 联动项 * @param linked 被联动项 */ void SimpleListDelegate::removeLine(const int link, const int linked) { for (int i = 0; i < m_linkItem.size(); ++i) { if (m_linkItem[i] == link) m_linkItem.remove(i); } for (int i = 0; i < m_linkedIten.size(); ++i) { if (m_linkedIten[i] == linked) m_linkedIten.remove(i); } } /** * @brief 删除单项联动 */ void SimpleListDelegate::removeLine(int index) { if (index < m_linkItem.size()) m_linkItem.remove(index); if (index < m_linkedIten.size()) m_linkedIten.remove(index); } /** * @brief 删除最后一项联动 */ void SimpleListDelegate::removeHisLink() { if (!m_linkItem.isEmpty()) m_linkItem.removeLast(); } /** * @brief 删除所有联动 */ void SimpleListDelegate::removeAllLink() { m_linkedIten.clear(); m_linkItem.clear(); } /** * @brief 删除最后一项被联动项 */ void SimpleListDelegate::removeHisLinked() { if (!m_linkedIten.isEmpty()) m_linkedIten.removeLast(); } void SimpleListDelegate::setThemeType(int type) { m_type = type; } /** * @brief 为paint提供参数 * @param index 行 * @param state 当前状态0-normal 1-hover 2-press */ void SimpleListDelegate::paintback(const QModelIndex &index, int state) { m_row = index.row(); m_state = state; } void SimpleListDelegate::currentfocusindex(QModelIndex index) { m_focusindex = index; } void SimpleListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { drawFocusStatus(painter, option); //焦点边框 if (m_mode == 0) { const QString expression = index.data(SimpleListModel::ExpressionRole).toString(); QRect rect(option.rect); rect.setRight(option.widget->width() - 13); QString errorFontColor; QString fontColor; QString linkColor; painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); QFont font; for (int i = 16; i > 12; --i) { // edit for bug-17238 font.setPixelSize(i); QFontMetrics fm(font); int fontWidth = fm.width(expression); int editWidth = rect.width() - 24; if (fontWidth < editWidth) break; } painter->setFont(font); QStringList splitList = expression.split("="); QString resultStr = splitList.last(); int resultWidth = painter->fontMetrics().width(resultStr); if (resultWidth > rect.width() / 1.4) { resultStr = painter->fontMetrics().elidedText(resultStr, Qt::ElideRight, int(rect.width() / 1.4) + PADDING); resultWidth = painter->fontMetrics().width(resultStr); } if (m_type == 1) { errorFontColor = "#FF5736"; //edit for bug-21508 linkColor = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name(); fontColor = "#838483"; } else { errorFontColor = "#9A2F2F"; //edit for bug-21508 linkColor = Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name(); fontColor = "#838483"; } // check result text is error. if (resultStr == tr("Expression error")) { painter->setPen(QColor(errorFontColor)); } else { painter->setPen(QColor(fontColor)); for (int i = 0; i < m_linkItem.size(); ++i) { if (m_linkItem[i] == index.row()) painter->setPen(QColor(linkColor)); } } int equalStrWidth = painter->fontMetrics().width(" = "); QString expStr = painter->fontMetrics().elidedText( splitList.first(), Qt::ElideLeft, rect.width() - resultWidth - PADDING * 2 - equalStrWidth); // QString expStr = splitList.first(); if (m_state == 2 && m_row == index.row()) { //edit for bug--21508 QRectF resultRect(rect.topRight().x() - resultWidth - PADDING - 2, rect.y() + 4.8, resultWidth + 7, rect.height() - 9.6); QPainterPath path; path.addRoundedRect(resultRect, 4, 4); // Setting Gradient // QLinearGradient linear(resultRect.topLeft(), resultRect.bottomRight()); // linear.setColorAt(0, QColor(0, 151, 231, 255)); // linear.setColorAt(1, QColor(0, 122, 219, 255)); // linear.setColorAt(0, QColor("#0081FF")); // linear.setColorAt(1, QColor("#0081FF")); // linear.setSpread(QGradient::PadSpread); //edit for bug--21476 if (m_type == 1) { QBrush brush(QColor(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name())); painter->fillPath(path, brush); } else { QBrush brush(QColor(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name())); painter->fillPath(path, brush); } painter->setPen(QPen(QColor(Qt::white))); // m_simpleListDelegate->setSelect(false); } if (splitList.size() == 1) { // draw expression text; painter->setPen(QColor(fontColor)); painter->drawText( QRect(rect.x() + PADDING, rect.y(), rect.width() - PADDING * 2, rect.height()), Qt::AlignVCenter | Qt::AlignRight, expStr); } else { // draw result text. painter->drawText( QRect(rect.x() + PADDING, rect.y(), rect.width() - PADDING * 2, rect.height()), Qt::AlignVCenter | Qt::AlignRight, resultStr); QString linkNum, exp; m_simpleListDelegate->cutApart(expStr, linkNum, exp); //剪切出可能被联动项 exp = exp + " = "; // draw expression text; painter->setPen(QColor(fontColor)); painter->drawText(QRect(rect.x() + PADDING, rect.y(), rect.width() - resultWidth - PADDING * 2, rect.height()), Qt::AlignVCenter | Qt::AlignRight, exp); painter->setPen(QColor(fontColor)); for (int i = 0; i < m_linkedIten.size(); ++i) { if (m_linkedIten[i] == index.row() && resultStr != tr("Expression error")) // 错误表达式不联动 painter->setPen(QColor(linkColor)); //判断第一个数是否是被联动项,如果是,设置字体颜色为高亮 } int expWidth = painter->fontMetrics().width(exp); painter->drawText(QRect(rect.x() + PADDING, rect.y(), rect.width() - resultWidth - expWidth - PADDING * 2, rect.height()), Qt::AlignVCenter | Qt::AlignRight, linkNum); } } else if (m_mode == 1) { const QString expression = index.data(SimpleListModel::ExpressionWithOutTip).toString(); QRect rect(option.rect); rect.setRight(option.widget->width() - 5); //设置矩形右边缘,会导致rect宽度改变 QString errorFontColor; QString fontColor; QString resultColor; QColor normalbackground, pressbackground, nohistory; painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); QTextOption textoption(Qt::AlignRight | Qt::AlignVCenter); textoption.setWrapMode(QTextOption::WrapAnywhere); //单词可在任意地方分行 QFontMetrics fm1 = painter->fontMetrics(); QFont font; font.setPixelSize(16); QFont fontresult; //结果字体 fontresult.setPixelSize(30); painter->setFont(font); QStringList splitList = expression.split("="); QString resultStr = splitList.last(); QString exp = splitList.first() + " = "; int expHeight; int expline = (painter->fontMetrics().width(exp) % (rect.width() - PADDING * 2)) ? (painter->fontMetrics().width(exp) / (rect.width() - PADDING * 2) + 1) : (painter->fontMetrics().width(exp) / (rect.width() - PADDING * 2)); expHeight = painter->fontMetrics().height() * expline; if (m_type == 1) { errorFontColor = "#FF5736"; //edit for bug-21508 resultColor = "#303030"; fontColor = "#838483"; normalbackground = QColor(0, 0, 0); normalbackground.setAlphaF(0.05); pressbackground = QColor(0, 0, 0); pressbackground.setAlphaF(0.2); nohistory = QColor(85, 85, 85); nohistory.setAlphaF(0.4); } else { errorFontColor = "#9A2F2F"; //edit for bug-21508 resultColor = "#B4B4B4"; fontColor = "#838483"; normalbackground = QColor(255, 255, 255); normalbackground.setAlphaF(0.05); pressbackground = QColor(255, 255, 255); pressbackground.setAlphaF(0.2); nohistory = QColor(192, 198, 212); nohistory.setAlphaF(0.4); } // check result text is error. painter->setPen(QColor(fontColor)); if (splitList.size() == 1) { painter->setPen(QColor(nohistory)); painter->drawText( QRectF(rect.x() + PADDING, rect.y(), rect.width() - PADDING * 2, NOHISTORYHEIGHT), expression, Qt::AlignHCenter | Qt::AlignVCenter); } else { // draw result text. painter->drawText( QRectF(rect.x() + PADDING, rect.y() + 10, rect.width() - PADDING * 2, expHeight), exp, textoption); //exp与上方空隙5pix painter->setFont(fontresult); int resultHeight; int resultline = (painter->fontMetrics().width(resultStr) % (rect.width() - PADDING * 2 - 1)) ? (painter->fontMetrics().width(resultStr) / (rect.width() - PADDING * 2 - 1) + 1) : (painter->fontMetrics().width(resultStr) / (rect.width() - PADDING * 2 - 1)); //由于结果字体较大,暂以此避免 resultHeight = painter->fontMetrics().height() * resultline; if (resultStr == tr("Expression error")) { painter->setPen(QColor(errorFontColor)); } else { painter->setPen(QColor(resultColor)); } painter->drawText( QRectF(rect.x() + PADDING, rect.y() + expHeight + 12, rect.width() - PADDING * 2, resultHeight), resultStr, textoption); //result与exp空隙12pix if (option.state & QStyle::State_MouseOver && m_state == 0) { painter->setBrush(normalbackground); painter->setPen(Qt::NoPen); painter->drawRect(rect.x(), rect.y(), rect.width() + 5, rect.height()); } else if (m_state == 1 && m_row == index.row()) { painter->setBrush(normalbackground); painter->setPen(Qt::NoPen); painter->drawRect(rect.x(), rect.y(), rect.width() + 5, rect.height()); } if (m_state == 2 && m_row == index.row()) { painter->setPen(Qt::NoPen); painter->setBrush(pressbackground); painter->drawRect(rect.x(), rect.y(), rect.width() + 5, rect.height()); } } } } /** * @brief 绘制焦点状态 */ void SimpleListDelegate::drawFocusStatus(QPainter *painter, const QStyleOptionViewItem &option) const { SimpleListView *listview = qobject_cast(option.styleObject); if (listview->hasFocus()) { painter->setRenderHint(QPainter::Antialiasing, true); QRectF itemrect(listview->visualRect(m_focusindex)); QRectF frame(itemrect.left() + 1, itemrect.top() + 1, HISWIDTH - 2, itemrect.height() - 2); QPen pen; pen.setColor(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name()); pen.setWidth(2); painter->setPen(pen); painter->setBrush(Qt::NoBrush); painter->drawRoundedRect(frame, 8, 8); //focus边框 } } /** * @brief 大小设置 */ QSize SimpleListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(option); if (m_mode == 1) { const QString expression = index.data(SimpleListModel::ExpressionWithOutTip).toString(); const int rectwidth = 447; //paintevent设置右边缘后的宽度 QStringList splitList = expression.split("="); if (splitList.size() == 1) return QSize(-1, 302); //历史记录无内容时大小 QString resultStr = splitList.last(); QString exp = splitList.first() + "="; QFont font; font.setPixelSize(16); QFontMetrics fmexp(font); QFont fontresult; //结果字体 fontresult.setPixelSize(30); QFontMetrics fmresult(fontresult); int expHeight; int expline = (fmexp.width(exp) % (rectwidth - PADDING * 2)) ? (fmexp.width(exp) / (rectwidth - PADDING * 2) + 1) : (fmexp.width(exp) / (rectwidth - PADDING * 2)); expHeight = fmexp.height() * expline; int resultHeight; int resultline = (fmresult.width(resultStr) % (rectwidth - PADDING * 2 - 1)) ? (fmresult.width(resultStr) / (rectwidth - PADDING * 2 - 1) + 1) : (fmresult.width(resultStr) / (rectwidth - PADDING * 2 - 1)); //由于结果字体较大,暂以此避免 resultHeight = fmresult.height() * resultline; return QSize(HISWIDTH, expHeight + resultHeight + 25); //多出25pix空隙 } else return QSize(-1, 33); } //bool SimpleListDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, // const QStyleOptionViewItem &option, const QModelIndex &index) //{ // Q_UNUSED(event); // Q_UNUSED(model); // Q_UNUSED(option); // m_selected = true; // if (m_mode == 0) // emit obtainingHistorical(index); // return true; //} /** * @brief 将等于号左侧表达式中被联动项与剩余部分分开 * @param text 表达式 * @param linkNum 第一个数字 * @param expStr 剩余项 */ void SimpleListDelegate::cutApart(const QString text, QString &linkNum, QString &expStr) { QString exp = text; QStringList list; list = exp.split(QRegExp("[+-×÷/()]"), QString::SkipEmptyParts); if (list.isEmpty() || list.size() == 1) { linkNum = ""; expStr = exp; return; } if (exp.at(0) != "-") { int index = 0; while (exp.at(index) == "(") { ++index; linkNum.append("("); if (exp.at(index) == "-") linkNum.append("-"); } linkNum.append(list.at(0)); } else { linkNum.append("-"); if (exp.at(1) == "(") linkNum.append("("); linkNum.append(list.at(0)); } if (linkNum.at(linkNum.size() - 1) == "E") linkNum = linkNum + exp.at(exp.indexOf("E") + 1) + list.at(1); expStr = text.right(text.length() - linkNum.length()); } /** * @brief 更新编辑器组件的大小 */ void SimpleListDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(index); editor->setGeometry(option.rect); } deepin-calculator-5.7.21/src/views/simplelistdelegate.h000066400000000000000000000053731423020056600231640ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SIMPLELISTDELEGATE_H #define SIMPLELISTDELEGATE_H #include #include #include DGUI_USE_NAMESPACE class SimpleListDelegate : public QStyledItemDelegate { Q_OBJECT Q_PROPERTY(bool m_selected READ isSelected WRITE setSelect) public: SimpleListDelegate(int mode, QObject *parent = nullptr);//mode:0-标准模式 1-科学模式 ~SimpleListDelegate() override; void setHisLink(const int link); void setHisLinked(const int linked); void removeLine(const int link, const int linked); void removeLine(int index); void removeHisLink(); void removeAllLink(); void removeHisLinked(); // add 20200318 for fix cleanlinkcache bool isSelected() const {return m_selected;} void setSelect(bool isSelect) { m_selected = isSelect; } public slots: void setThemeType(int type); void paintback(const QModelIndex &index, int state);//state 0-normal 1-hover 2-press void currentfocusindex(QModelIndex index); protected: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void drawFocusStatus(QPainter *painter, const QStyleOptionViewItem &option) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; // bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, // const QModelIndex &index); void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override; signals: void obtainingHistorical(const QModelIndex &index); void historicalLinkage(const QModelIndex &index); private: void cutApart(const QString text, QString &linkNum, QString &expStr); SimpleListDelegate *m_simpleListDelegate; QVector m_linkItem; QVector m_linkedIten; bool m_selected; int m_type = 0; int m_mode = 0; int m_row = -1; int m_state = 0; QModelIndex m_focusindex; }; #endif deepin-calculator-5.7.21/src/views/simplelistmodel.cpp000066400000000000000000000333641423020056600230460ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "simplelistmodel.h" #include #include #include #include "../utils.h" #include "../globaldefine.h" #include "../../3rdparty/core/settings.h" const QString AtoF = "ABCDEF"; SimpleListModel::SimpleListModel(int mode, QObject *parent) : QAbstractListModel(parent) { m_selectedStatus = false; if (mode == 1) { m_mode = mode; clearItems(); } } SimpleListModel::~SimpleListModel() {} /** * @brief 返回历史记录条数 */ int SimpleListModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_expressionList.size(); } /** * @brief delegate中获取表达式;ExpressionRole:显示提示文本 */ QVariant SimpleListModel::data(const QModelIndex &index, int role) const { const int r = index.row(); switch (role) { case ExpressionWithOutTip: return m_expressionList.at(r); case ExpressionRole: if (m_mode == 1) return QVariant(); return m_expressionList.at(r); case ExpressionCount: return m_expressionList.count(); case ExpressionPrevious: return m_expressionList.value(r - 1); case ExpressionNext: return m_expressionList.value(r + 1); default: return QVariant(); } } /** * @brief 科学模式上方历史记录区 */ void SimpleListModel::appendText(const QString &text, bool sci) { auto expression = text.simplified(); const int size = m_expressionList.size(); if (sci) { beginRemoveRows(QModelIndex(), 0, 0); m_expressionList.removeAt(0); endRemoveRows(); beginInsertRows(QModelIndex(), 0, 0); m_expressionList << expression; endInsertRows(); } else { beginInsertRows(QModelIndex(), size, size); m_expressionList << expression; endInsertRows(); } } /** * @brief 清空历史记录 */ void SimpleListModel::clearItems() { beginRemoveRows(QModelIndex(), 0, m_expressionList.size()); m_expressionList.clear(); endRemoveRows(); m_answerlist.clear(); if (m_mode == 1) { beginInsertRows(QModelIndex(), 0, 0); m_expressionList << tr("No history"); endInsertRows(); } } /** * @brief ResetModel */ void SimpleListModel::refrushModel() { beginResetModel(); endResetModel(); } /** * @brief 科学模式上方历史记录区与标准模式添加历史记录 */ void SimpleListModel::updataList(const QString &text, const int index, bool sci) { if (m_expressionList.count() == 500) { if (sci) deleteItem(499); else deleteItem(0); } QString exp = text; exp = exp.replace(EN_ADD, CN_ADD) .replace(EN_MIN, CN_MIN) .replace(EN_MUL, CN_MUL); if (index == -1) { appendText(exp, sci); //科学模式上方历史记录区 } else { if (sci) { beginInsertRows(QModelIndex(), index, index); m_expressionList.insert(index, exp); endInsertRows(); } else { beginRemoveRows(QModelIndex(), index, index); m_expressionList.removeAt(index); m_expressionList.insert(index, exp); endRemoveRows(); } } } /** * @brief 添加历史记录 */ void SimpleListModel::updataList(Quantity ans, const QString &text, const int index) { if (m_expressionList.count() == 500) { deleteItem(499); //历史记录不超过500条 m_answerlist.pop_back(); } QString exp = text; exp = exp.replace(EN_ADD, CN_ADD) .replace(EN_MIN, CN_MIN) .replace(EN_MUL, CN_MUL); beginInsertRows(QModelIndex(), index, index); m_expressionList.insert(index, exp); endInsertRows(); m_answerlist.insert(0, ans); } /** * @brief 删除单条历史记录 */ void SimpleListModel::deleteItem(const int index) { beginRemoveRows(QModelIndex(), index, index); m_expressionList.removeAt(index); endRemoveRows(); if (m_answerlist.count() > 0) m_answerlist.removeAt(index); if (m_expressionList.count() == 0) { emit hisbtnhidden(); //发送历史记录无数据信号 } } /** * @brief 复制到粘贴板 */ void SimpleListModel::copyToClipboard(const int index) { QClipboard *clipboard = QApplication::clipboard(); QString copy = m_expressionList.at(index); clipboard->setText(copy.replace(" ", "")); } /** * @brief 返回所点击历史记录的answer.Quantity */ Quantity SimpleListModel::getAnswer(const int index) { if (m_answerlist.count() > index) return m_answerlist.at(index); return Quantity(); } void SimpleListModel::radixChanged(int baseori, int basedest) { if (m_expressionList.count() <= 0) return; m_numvec.clear(); m_opvec.clear(); m_textorder = QString(); m_numchanged = false; QString oldtext = m_expressionList.at(0).left(m_expressionList.at(0).indexOf("=") + 1); QString resultnum = m_expressionList.at(0).split("=").last(); oldtext.remove(",").remove(" "); resultnum.remove(",").remove(" "); for (int i = 0; i < oldtext.length();) { if (isNumber(oldtext.at(i))) { for (int j = 0; j < oldtext.length() - i; j++) { if (i + j == oldtext.length() - 1) { if (isNumber(oldtext.at(i + j))) { m_numvec.append(oldtext.mid(i, j + 1)); m_textorder += "0"; i += j + 1; } else { m_numvec.append(oldtext.mid(i, j)); m_textorder += "0"; i += j; } break; } if (!isNumber(oldtext.at(i + j))) { m_numvec.append(oldtext.mid(i, j)); m_textorder += "0"; i += j; break; } } } else { if (oldtext.at(i).isLower()) { if (oldtext.at(i) == 'n' && oldtext.at(i + 1) == 'a') { m_opvec.append(oldtext.mid(i, 4)); m_textorder += "1"; i += 4; } else if (oldtext.at(i) == 'o') { m_opvec.append(oldtext.mid(i, 2)); m_textorder += "1"; i += 2; } else { m_opvec.append(oldtext.mid(i, 3)); m_textorder += "1"; i += 3; } } else if ((i == 0 || !isNumber(oldtext.at(i - 1))) && oldtext.at(i) == CN_MIN && oldtext.length() > i + 1 && isNumber(oldtext.at(i + 1))) { i++; for (int j = 0; j < oldtext.length() - i; j++) { if (!isNumber(oldtext.at(i + j))) { m_numvec.append(oldtext.mid(i - 1, j + 1)); m_textorder += "0"; i += j; break; } if (i + j == oldtext.length() - 1) { m_numvec.append(oldtext.mid(i - 1, j + 2)); m_textorder += "0"; i += j + 1; break; } } } else { m_opvec.append(oldtext.at(i)); m_textorder += "1"; i++; } } } for (int i = 0; i < m_numvec.size(); i++) { QString num = formatExpression(baseori, m_numvec.at(i)); Quantity ans(HNumber(num.toLatin1().data())); switch (basedest) { case 16: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); break; case 8: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); break; case 2: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); break; default: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); break; } if (m_numvec.at(i) != num) m_numchanged = true; m_numvec.replace(i, num); } QString result = formatExpression(baseori, resultnum); Quantity ans(HNumber(result.toLatin1().data())); switch (basedest) { case 16: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); break; case 8: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); break; case 2: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); break; default: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); break; } QString newtext = QString(); for (int i = 0; i < m_textorder.length(); i++) { if (m_textorder.at(i) == "0") { newtext.append(m_numvec.first()); m_numvec.pop_front(); } else { newtext.append(m_opvec.first()); m_opvec.pop_front(); } } newtext = newtext + (ans.isNan() ? m_expressionList.at(0).split("=").last() : result); newtext = Utils::reformatSeparatorsPro(newtext, basedest).replace(EN_ADD, CN_ADD) .replace(EN_MIN, CN_MIN) .replace(EN_MUL, CN_MUL) .replace(EN_DIV, CN_DIV); m_expressionList.clear(); beginInsertRows(QModelIndex(), 0, 0); m_expressionList << newtext; endInsertRows(); } bool SimpleListModel::isNumber(QChar a) { if (a.isDigit() || a == " " || a == "," || AtoF.contains(a)) return true; else return false; } QString SimpleListModel::formatExpression(const int &probase, const QString &text) { QString formattext = text; formattext.replace(CN_ADD, EN_ADD) .replace(CN_MIN, EN_MIN) .replace(CN_MUL, EN_MUL) .replace(CN_DIV, EN_DIV) .replace(EN_Comma, "") .replace(QString::fromUtf8(" "), "") .replace(EN_Percent, "mod"); QString base = QString(); switch (probase) { case 16: base = "0x"; break; case 8: base = "0o"; break; case 2: base = "0b"; break; default: break; } if (base != QString()) { for (int i = 0; i < formattext.length();) { if ((i == 0) && isNumber(formattext.at(i))) { formattext.insert(i, base); i += 3; continue; } else if ((i < formattext.length() - 1) && !isNumber(formattext.at(i)) && isNumber(formattext.at(i + 1))) { formattext.insert(i + 1, base); i += 3; continue; } i++; } } return formattext; } void SimpleListModel::answerOutOfRange(Quantity ans) { QString resultnum; switch (Settings::instance()->programmerBase) { case 16: resultnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); break; case 8: resultnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); break; case 2: resultnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); break; default: resultnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); break; } if (m_expressionList.count() > 0) { QString expression = m_expressionList.at(0); expression = Utils::reformatSeparatorsPro((expression.left(expression.indexOf("=") + 1) + resultnum), Settings::instance()->programmerBase) .replace(EN_ADD, CN_ADD) .replace(EN_MIN, CN_MIN) .replace(EN_MUL, CN_MUL) .replace(EN_DIV, CN_DIV);; m_expressionList.clear(); beginInsertRows(QModelIndex(), 0, 0); m_expressionList << expression; endInsertRows(); } } void SimpleListModel::expOutofRange() { radixChanged(Settings::instance()->programmerBase, Settings::instance()->programmerBase); } /** * @brief SimpleListModel::updataOfSeparate * 更新所有历史记录算式的分割位数 */ void SimpleListModel::updataOfSeparate() { for (int i = 0; i < m_expressionList.count(); ++i) { QString expression = m_expressionList.at(i); //获取原算式 expression.replace(",", ""); //清空逗号分隔符 QString newExp = Utils::reformatSeparators(expression); //重新填充分割符 //更新数据 beginInsertRows(QModelIndex(), 0, 0); m_expressionList[i] = newExp; endInsertRows(); } } deepin-calculator-5.7.21/src/views/simplelistmodel.h000066400000000000000000000050741423020056600225100ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SIMPLELISTMODEL_H #define SIMPLELISTMODEL_H #include "../../3rdparty/core/evaluator.h" #include class SimpleListModel : public QAbstractListModel { Q_OBJECT public: SimpleListModel(int mode = 0, QObject *parent = nullptr);//mode:0-标准模式 1-科学模式 ~SimpleListModel() override; void refrushModel(); //model的data数据类型 enum Role { ExpressionWithOutTip = Qt::DisplayRole,//无提示文本 ExpressionRole = Qt::ToolTipRole, //有提示文本 ExpressionCount = 4, //数据数量 ExpressionPrevious, //前一个数据 ExpressionNext, //下一个数据 }; int rowCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; void appendText(const QString &text, bool sci); void clearItems(); void updataList(const QString &text, const int index, bool sci = false); void updataList(Quantity ans, const QString &text, const int index); void deleteItem(const int index); void copyToClipboard(const int index); Quantity getAnswer(const int index); //进制切换 void radixChanged(int baseori, int basedest); bool isNumber(QChar a);//判断是否为数字(分隔符) QString formatExpression(const int &probase, const QString &text); void answerOutOfRange(Quantity ans); void expOutofRange(); //更改数据分割位数 void updataOfSeparate(); signals: void hisbtnhidden(); private: QList m_expressionList; bool m_selectedStatus; int m_mode = 0; //0-标准模式 1-科学模式 QList m_answerlist; //对应历史记录的answer //进制切换时用于替换所有数字 QVector m_numvec; QVector m_opvec; QString m_textorder; bool m_numchanged = false; }; #endif deepin-calculator-5.7.21/src/views/simplelistview.cpp000066400000000000000000000207401423020056600227120ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "simplelistview.h" #include #include #include #include #include #include #include #include #include #include "simplelistmodel.h" SimpleListView::SimpleListView(int mode, QWidget *parent) : DListView(parent) { m_mode = mode; setVerticalScrollMode(ScrollPerPixel); //鼠标滚轮滚动一次一个像素 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); //设置垂直滚条 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::DoubleClicked); //单击已选中的内容双击单元格时编辑 // setFocusPolicy(Qt::TabFocus); setAutoScroll(false); setSelectionBehavior(QAbstractItemView::SelectRows); //选中一行 setSelectionMode(QAbstractItemView::SingleSelection); //选中单个目标 setFocusPolicy(Qt::NoFocus); if (m_mode == 0) { setFixedHeight(99); } if (m_mode == 1) { setMouseTracking(true); setFixedHeight(302); } connect(verticalScrollBar(), &QScrollBar::rangeChanged, this, &SimpleListView::adjustScrollbarMargins); } SimpleListView::~SimpleListView() { } /** * @brief 添加右键菜单 */ void SimpleListView::contextMenuEvent(QContextMenuEvent *event) { QMenu *menu = new QMenu(this); //缺翻译 QAction *copy = new QAction(tr("Copy"), menu); QAction *clean = new QAction(tr("Delete"), menu); menu->addAction(copy); menu->addAction(clean); connect(copy, &QAction::triggered, this, [ = ]() { static_cast(model())->copyToClipboard(indexAt(event->pos()).row()); }); connect(clean, &QAction::triggered, this, [ = ]() { static_cast(model())->deleteItem(indexAt(event->pos()).row()); }); if (indexAt(event->pos()).row() >= 0 && m_itemfill) { menu->exec(event->globalPos()); } delete menu; } /** * @brief 给私有变量赋值,历史记录有数据 */ void SimpleListView::listItemFill(bool itemfill) { m_itemfill = itemfill; } void SimpleListView::showTextEditMenuByAltM(const QModelIndex &index) { QMenu *menu = new QMenu(this); //缺翻译 QAction *copy = new QAction(tr("Copy"), menu); QAction *clean = new QAction(tr("Delete"), menu); menu->addAction(copy); menu->addAction(clean); connect(copy, &QAction::triggered, this, [ = ]() { static_cast(model())->copyToClipboard(index.row()); }); connect(clean, &QAction::triggered, this, [ = ]() { static_cast(model())->deleteItem(index.row()); }); if (index.row() >= 0 && m_itemfill) { QPoint menupoint; menupoint.setX(mapToGlobal(visualRect(index).center()).x()); menupoint.setY(mapToGlobal(visualRect(index).bottomLeft()).y() - 20); menu->exec(menupoint); } delete menu; } /** * @brief 更改delegate参数,实现delegate的hover状态 */ void SimpleListView::mouseMoveEvent(QMouseEvent *e) { if (m_mode == 1 && m_itemfill) { if (m_ispressed == true) { if (indexAt(m_presspoint) != indexAt(e->pos())) m_presschanged = true; else m_presschanged = false; QListView::mouseMoveEvent(e); } else { if (indexAt(e->pos()).isValid()) static_cast(itemDelegate(indexAt(e->pos())))->paintback(indexAt(e->pos()), 0); QWidget::mouseMoveEvent(e); } } else if (m_mode == 0 && this->count() > 0) { if (m_ispressed == true) { if (indexAt(m_presspoint) != indexAt(e->pos())) m_presschanged = true; else m_presschanged = false; QListView::mouseMoveEvent(e); } else { if (indexAt(e->pos()).isValid()) static_cast(itemDelegate(indexAt(e->pos())))->paintback(indexAt(e->pos()), 0); QWidget::mouseMoveEvent(e); } // if (e->x() < width() - 12) { // QWidget::mouseMoveEvent(e); // } else { // DListView::mouseMoveEvent(e); // } } } /** * @brief 设置滚动区域边距 */ void SimpleListView::adjustScrollbarMargins() { if (!isVisible()) { return; } QEvent event(QEvent::LayoutRequest); QApplication::sendEvent(this, &event); if (!verticalScrollBar()->visibleRegion().isEmpty()) { setViewportMargins(0, 0, -verticalScrollBar()->sizeHint().width(), 0); } else { setViewportMargins(0, 0, 0, 0); } } /** * @brief 更改delegate参数,实现delegate的press状态 */ void SimpleListView::mousePressEvent(QMouseEvent *event) { DListView::mousePressEvent(event); static_cast(model())->refrushModel(); if (event->buttons() & Qt::LeftButton) { if (indexAt(event->pos()).row() > -1) { m_presspoint = event->pos(); static_cast(itemDelegate(indexAt(m_presspoint)))->paintback(indexAt(m_presspoint), 2); m_currentrow = indexAt(m_presspoint).row(); m_ispressed = true; } } } /** * @brief 更改delegate参数,实现delegate的release状态 */ void SimpleListView::mouseReleaseEvent(QMouseEvent *event) { static_cast(model())->refrushModel(); if (m_currentrow == indexAt(event->pos()).row() && m_currentrow >= 0) { if (m_mode == 1) emit obtainingHistorical(indexAt(event->pos())); else emit obtainingHistoricalSimple(indexAt(event->pos())); static_cast(itemDelegate(indexAt(m_presspoint)))->paintback(indexAt(m_presspoint), 1); } else { if (m_presschanged == true) { static_cast(itemDelegate(indexAt(event->pos())))->paintback(indexAt(event->pos()), 1); } else static_cast(itemDelegate(indexAt(m_presspoint)))->paintback(indexAt(m_presspoint), 0); } m_ispressed = false; m_presspoint = QPoint(); DListView::mouseReleaseEvent(event); } void SimpleListView::keyPressEvent(QKeyEvent *e) { bool ispressalt = e->modifiers() == Qt::AltModifier; switch (e->key()) { case Qt::Key_Up: if (currentIndex().row() > 0) { setCurrentIndex(this->model()->index(currentIndex().row() - 1, 0)); static_cast(itemDelegate(currentIndex()))->currentfocusindex(currentIndex()); m_currentindexrow = currentIndex().row(); scrollTo(this->model()->index(currentIndex().row(), 0)); } break; case Qt::Key_Down: if (currentIndex().row() < this->count() - 1) { setCurrentIndex(this->model()->index(currentIndex().row() + 1, 0)); static_cast(itemDelegate(currentIndex()))->currentfocusindex(currentIndex()); m_currentindexrow = currentIndex().row(); scrollTo(this->model()->index(currentIndex().row(), 0)); } break; case Qt::Key_Space: case Qt::Key_Enter: case Qt::Key_Return: emit obtainingHistorical(currentIndex()); break; case Qt::Key_M: if (ispressalt) showTextEditMenuByAltM(currentIndex()); break; default: DListView::keyPressEvent(e); break; } } /** * @brief 焦点进入时设置焦点在第一条历史记录 */ void SimpleListView::focusInEvent(QFocusEvent *event) { setCurrentIndex(this->model()->index(m_currentindexrow, 0)); static_cast(itemDelegate(currentIndex()))->currentfocusindex(currentIndex()); scrollTo(this->model()->index(0, 0)); DListView::focusInEvent(event); } deepin-calculator-5.7.21/src/views/simplelistview.h000066400000000000000000000037761423020056600223710ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SIMPLELISTVIEW_H #define SIMPLELISTVIEW_H #include "simplelistdelegate.h" #include "simplelistmodel.h" #include #include #include DWIDGET_USE_NAMESPACE class SimpleListView : public DListView { Q_OBJECT public: explicit SimpleListView(int mode = 0, DWidget *parent = nullptr); //mode:0-标准模式 1-科学模式 ~SimpleListView() override; void contextMenuEvent(QContextMenuEvent *event) override; void listItemFill(bool itemfill); //itemfill中是否有历史记录 void showTextEditMenuByAltM(const QModelIndex &index); protected: void mouseMoveEvent(QMouseEvent *) override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void keyPressEvent(QKeyEvent *e) override; void focusInEvent(QFocusEvent *event) override; void adjustScrollbarMargins(); Q_SIGNALS: void clickrow(QString str); void obtainingHistorical(const QModelIndex &index); void obtainingHistoricalSimple(const QModelIndex &index); private: int m_mode = 0; int m_currentrow = -1; bool m_itemfill = false; bool m_ispressed = false; QPoint m_presspoint = QPoint(); bool m_presschanged = false; int m_currentindexrow = 0;//当前row }; #endif deepin-calculator-5.7.21/src/widgets/000077500000000000000000000000001423020056600174345ustar00rootroot00000000000000deepin-calculator-5.7.21/src/widgets/arrowrectangle.cpp000066400000000000000000000054501423020056600231630ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "arrowrectangle.h" #include "../views/memorylistwidget.h" #include #include //static int init = 0; ArrowRectangle::ArrowRectangle(ArrowDirection direction, FloatMode floatMode, QWidget *parent) : DArrowRectangle(direction, floatMode, parent) { this->installEventFilter(this); setMouseTracking(true); } ArrowRectangle::~ArrowRectangle() { } bool ArrowRectangle::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::FocusOut) { //点击标题栏及外部桌面失去焦点时切换至scientifickeypad QFocusEvent *focus_Event = static_cast(event); if (focus_Event->reason() == Qt::MouseFocusReason || focus_Event->reason() == Qt::ActiveWindowFocusReason) { emit hidearrowrectangle(); } } if (event->type() == QEvent::KeyPress) { QKeyEvent *key_event = static_cast < QKeyEvent *>(event); //将事件转化为键盘事件 if (key_event->key() == Qt::Key_Escape) { emit hidearrowrectangle(true); return true; } else if (key_event->key() == Qt::Key_Tab && getContent()) { if (obj == this) { static_cast(getContent())->cleanState(); static_cast(getContent())->setFocus(Qt::TabFocusReason); return true; } else { this->setFocus(Qt::TabFocusReason); return true; } } } return QWidget::eventFilter(obj, event); } void ArrowRectangle::focusInEvent(QFocusEvent *event) { if (event->reason() == Qt::TabFocusReason) { static_cast(getContent())->cleanState(); static_cast(getContent())->setFocus(); } DArrowRectangle::focusInEvent(event); } /** * @brief ArrowRectangle::keyPressEvent * 防止按其他键时焦点移到输入栏 */ void ArrowRectangle::keyPressEvent(QKeyEvent *event) { Q_UNUSED(event); return; } void ArrowRectangle::mouseMoveToClearFocus() { this->setFocus(); } deepin-calculator-5.7.21/src/widgets/arrowrectangle.h000066400000000000000000000025751423020056600226350ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ARROWRECTANGLE_H #define ARROWRECTANGLE_H #include #include DWIDGET_USE_NAMESPACE class ArrowRectangle : public DArrowRectangle { Q_OBJECT public: explicit ArrowRectangle(ArrowDirection direction, FloatMode floatMode, QWidget *parent = nullptr); ~ArrowRectangle(); bool eventFilter(QObject *obj, QEvent *event); void focusInEvent(QFocusEvent *event); void keyPressEvent(QKeyEvent *event); // void mouseMoveEvent(QMouseEvent *event); public slots: void mouseMoveToClearFocus(); signals: void hidearrowrectangle(bool isesc = false);//判断是否为esc退出 }; #endif // ARROWRECTANGLE_H deepin-calculator-5.7.21/src/widgets/basicmodule.cpp000066400000000000000000000736621423020056600224450ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "basicmodule.h" #include "dthememanager.h" #include "../utils.h" #include "../../3rdparty/math/quantity.h" #include #include #include #include #include BasicModule::BasicModule(QWidget *parent) : DWidget(parent) { m_keypadLayout = new QStackedWidget(this); m_basicKeypad = new BasicKeypad(this); m_memoryKeypad = new MemoryKeypad(this); m_insidewidget = false; m_memCalbtn = false; m_memRCbtn = false; m_isallgray = false; m_memoryPublic = MemoryPublic::instance(); m_memorylistwidget = m_memoryPublic->getwidget(MemoryPublic::standardleft); QVBoxLayout *layout = new QVBoxLayout(this); m_expressionBar = new ExpressionBar(this); layout->addWidget(m_expressionBar); layout->addWidget(m_memoryKeypad); layout->addSpacing(1); //按钮边框多1pix layout->addWidget(m_keypadLayout); m_keypadLayout->addWidget(m_basicKeypad); m_keypadLayout->addWidget(m_memorylistwidget); layout->setSpacing(0); layout->setMargin(0); layout->setContentsMargins(0, 0, 0, 0); setMouseTracking(true); setFocus(); m_expressionBar->initTheme(DGuiApplicationHelper::instance()->themeType()); //信号槽连接 connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_expressionBar, &ExpressionBar::initTheme); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &BasicModule::initTheme); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_basicKeypad, &BasicKeypad::buttonThemeChanged); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_memoryPublic, &MemoryPublic::setThemeType); connect(m_expressionBar, &ExpressionBar::keyPress, this, &BasicModule::handleEditKeyPress); connect(m_expressionBar, &ExpressionBar::clearStateChanged, this, &BasicModule::handleClearStateChanged); connect(m_basicKeypad, &BasicKeypad::buttonPressed, this, &BasicModule::handleKeypadButtonPress); connect(m_basicKeypad, &BasicKeypad::buttonPressedbySpace, this, &BasicModule::handleKeypadButtonPressByspace); connect(m_memoryKeypad, &MemoryKeypad::buttonPressed, this, &BasicModule::handleKeypadButtonPress); connect(m_memoryKeypad, &MemoryKeypad::buttonPressedbySpace, this, &BasicModule::handleKeypadButtonPressByspace); connect(m_memorylistwidget, &MemoryWidget::widgetplus, this, [ = ](int row) { m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) m_memoryPublic->widgetplus(row, m_expressionBar->getInputEdit()->getMemoryAnswer().second); }); connect(m_memorylistwidget, &MemoryWidget::widgetminus, this, [ = ](int row) { m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) m_memoryPublic->widgetminus(row, m_expressionBar->getInputEdit()->getMemoryAnswer().second); }); connect(m_memorylistwidget, &MemoryWidget::insidewidget, this, [ = ]() { m_insidewidget = true; }); connect(m_memoryPublic, &MemoryPublic::memorycleanSig, this, &BasicModule::mUnAvailableEvent); connect(m_memoryPublic, &MemoryPublic::generateDataSig, this, &BasicModule::mAvailableEvent); connect(m_memorylistwidget, &MemoryWidget::itemclick, this, [ = ](const QPair p) { QString str = p.first; m_expressionBar->getInputEdit()->setAnswer(str.remove("\n"), p.second); m_expressionBar->getInputEdit()->setFocus(); //点击item清除键状态改变 this->handleClearStateChanged(false); if (m_keypadLayout->currentIndex() == 1) { m_keypadLayout->setCurrentIndex(0); m_memoryKeypad->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_expressionBar->setAttribute(Qt::WA_TransparentForMouseEvents, false); MemoryButton *btn = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MC)); btn->setEnabled(true); btn->setbuttongray(false); MemoryButton *btn1 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MR)); btn1->setEnabled(true); btn1->setbuttongray(false); MemoryButton *btn2 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mplus)); btn2->setEnabled(true); btn2->setbuttongray(false); MemoryButton *btn3 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mminus)); btn3->setEnabled(true); btn3->setbuttongray(false); MemoryButton *btn4 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MS)); btn4->setEnabled(true); btn4->setbuttongray(false); MemoryButton *btn5 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mlist)); btn5->setEnabled(true); btn5->setbtnlight(false); m_memRCbtn = true; m_memCalbtn = true; m_isallgray = false; } }); connect(m_expressionBar->getInputEdit(), &InputEdit::emptyExpression, this, [ = ](bool b) { if (b == false) { MemoryButton *btn2 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mplus)); btn2->setEnabled(true); MemoryButton *btn3 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mminus)); btn3->setEnabled(true); MemoryButton *btn4 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MS)); btn4->setEnabled(true); m_memCalbtn = true; m_memorylistwidget->expressionempty(b); } else { MemoryButton *btn2 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mplus)); btn2->setEnabled(false); MemoryButton *btn3 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mminus)); btn3->setEnabled(false); MemoryButton *btn4 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MS)); btn4->setEnabled(false); m_memCalbtn = false; m_memorylistwidget->expressionempty(b); } }); connect(m_memorylistwidget, &MemoryWidget::hideWidget, this, &BasicModule::closeListWidget); //获取科学模式内存是否为空,处理分开初始化科学模式下增加内存切到标准模式Mlist不能点击情况 if (!m_memoryPublic->isEmpty()) mAvailableEvent(); else mUnAvailableEvent(); setBasicTabOrder(); } BasicModule::~BasicModule() {} void BasicModule::initTheme(int type) { m_expressionBar->initTheme(type); update(); } /** * @brief 物理键盘press事件 */ void BasicModule::handleEditKeyPress(QKeyEvent *e) { if (m_keypadLayout->currentIndex() == 1) return; const bool isPressCtrl = e->modifiers() == Qt::ControlModifier; const QString keyText = e->text(); switch (e->key()) { case Qt::Key_0: m_expressionBar->enterNumberEvent("0"); //进入按键0事件 m_basicKeypad->animate(BasicKeypad::Key_0); //按键0动画效果 break; case Qt::Key_1: m_expressionBar->enterNumberEvent("1"); m_basicKeypad->animate(BasicKeypad::Key_1); break; case Qt::Key_2: m_expressionBar->enterNumberEvent("2"); m_basicKeypad->animate(BasicKeypad::Key_2); break; case Qt::Key_3: m_expressionBar->enterNumberEvent("3"); m_basicKeypad->animate(BasicKeypad::Key_3); break; case Qt::Key_4: m_expressionBar->enterNumberEvent("4"); m_basicKeypad->animate(BasicKeypad::Key_4); break; case Qt::Key_5: m_expressionBar->enterNumberEvent("5"); m_basicKeypad->animate(BasicKeypad::Key_5); break; case Qt::Key_6: m_expressionBar->enterNumberEvent("6"); m_basicKeypad->animate(BasicKeypad::Key_6); break; case Qt::Key_7: m_expressionBar->enterNumberEvent("7"); m_basicKeypad->animate(BasicKeypad::Key_7); break; case Qt::Key_8: m_expressionBar->enterNumberEvent("8"); m_basicKeypad->animate(BasicKeypad::Key_8); break; case Qt::Key_9: m_expressionBar->enterNumberEvent("9"); m_basicKeypad->animate(BasicKeypad::Key_9); break; case Qt::Key_Plus: m_expressionBar->enterSymbolEvent("+"); m_basicKeypad->animate(BasicKeypad::Key_Plus); break; case Qt::Key_Minus: case Qt::Key_Underscore: m_expressionBar->enterSymbolEvent("-"); m_basicKeypad->animate(BasicKeypad::Key_Min); break; case Qt::Key_Asterisk: m_expressionBar->enterSymbolEvent("*"); m_basicKeypad->animate(BasicKeypad::Key_Mult); break; case Qt::Key_Slash: m_expressionBar->enterSymbolEvent("/"); m_basicKeypad->animate(BasicKeypad::Key_Div); break; case Qt::Key_Enter: case Qt::Key_Return: case Qt::Key_Equal: m_basicKeypad->animate(BasicKeypad::Key_Equals); m_expressionBar->settingLinkage(); // setFocus(); break; case Qt::Key_Backspace: m_expressionBar->enterBackspaceEvent(); m_basicKeypad->animate(BasicKeypad::Key_Backspace); break; case Qt::Key_Period: m_basicKeypad->animate(BasicKeypad::Key_Point); m_expressionBar->enterPointEvent(); break; case Qt::Key_Escape: m_expressionBar->enterClearEvent(); m_basicKeypad->animate(BasicKeypad::Key_Clear); break; case Qt::Key_ParenLeft: m_basicKeypad->animate(BasicKeypad::Key_Brackets); m_expressionBar->enterLeftBracketsEvent(); break; case Qt::Key_ParenRight: m_basicKeypad->animate(BasicKeypad::Key_Brackets); m_expressionBar->enterRightBracketsEvent(); break; case Qt::Key_Percent: m_expressionBar->enterPercentEvent(); m_basicKeypad->animate(BasicKeypad::Key_Percent); break; case Qt::Key_C: if (isPressCtrl) { m_expressionBar->copyResultToClipboard(); setFocus(); } break; case Qt::Key_V: if (isPressCtrl) { m_expressionBar->copyClipboard2Result(); } break; case Qt::Key_A: if (isPressCtrl) { m_expressionBar->allElection(); } break; case Qt::Key_X: if (isPressCtrl) { m_expressionBar->shear(); } else { m_expressionBar->enterSymbolEvent("*"); m_basicKeypad->animate(BasicKeypad::Key_Mult); } break; case Qt::Key_Delete: m_expressionBar->enterClearEvent(); m_basicKeypad->animate(BasicKeypad::Key_Clear); break; case Qt::Key_Left: m_expressionBar->moveLeft(); break; case Qt::Key_Right: m_expressionBar->moveRight(); break; case Qt::Key_Z: if (isPressCtrl) m_expressionBar->Undo(); break; case Qt::Key_Y: if (isPressCtrl) m_expressionBar->Redo(); break; case Qt::Key_L: if (isPressCtrl && m_memRCbtn && !m_isallgray) { m_memoryKeypad->animate(MemoryKeypad::Key_MC); QTimer::singleShot(100, this, [ = ] { m_memoryPublic->memoryclean(); //延迟,让动画效果显示 }); } break; case Qt::Key_R: if (isPressCtrl && m_memRCbtn && !m_isallgray) { m_memoryKeypad->animate(MemoryKeypad::Key_MR); m_expressionBar->getInputEdit()->setAnswer(m_memorylistwidget->getfirstnumber().first, m_memorylistwidget->getfirstnumber().second); //点击item清除键状态改变 this->handleClearStateChanged(false); } break; case Qt::Key_P: if (isPressCtrl && m_memCalbtn && !m_isallgray) { m_memoryKeypad->animate(MemoryKeypad::Key_Mplus); m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) //如果输入栏中可计算出结果 m_memoryPublic->memoryplus(m_expressionBar->getInputEdit()->getMemoryAnswer().second); } break; case Qt::Key_Q: if (isPressCtrl && m_memCalbtn && !m_isallgray) { m_memoryKeypad->animate(MemoryKeypad::Key_Mminus); m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) m_memoryPublic->memoryminus(m_expressionBar->getInputEdit()->getMemoryAnswer().second); } break; case Qt::Key_M: if (isPressCtrl && m_memCalbtn && !m_isallgray) { m_memoryKeypad->animate(MemoryKeypad::Key_MS); m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) m_memoryPublic->generateData(m_expressionBar->getInputEdit()->getMemoryAnswer().second); } break; default: break; } if (!m_basicKeypad->buttonHasFocus() && !m_memoryKeypad->buttonHasFocus()) m_expressionBar->getInputEdit()->setFocus(); //edit 20200417 for bug--21146 } /** * @brief 计算器键盘点击事件 */ void BasicModule::handleKeypadButtonPress(int key) { bool pagefocus = false; m_basicKeypad->update(); //20200414 bug20294鼠标点击取消focus QPair p; switch (key) { case BasicKeypad::Key_0: m_expressionBar->enterNumberEvent("0"); //按键0事件 break; case BasicKeypad::Key_1: m_expressionBar->enterNumberEvent("1"); break; case BasicKeypad::Key_2: m_expressionBar->enterNumberEvent("2"); break; case BasicKeypad::Key_3: m_expressionBar->enterNumberEvent("3"); break; case BasicKeypad::Key_4: m_expressionBar->enterNumberEvent("4"); break; case BasicKeypad::Key_5: m_expressionBar->enterNumberEvent("5"); break; case BasicKeypad::Key_6: m_expressionBar->enterNumberEvent("6"); break; case BasicKeypad::Key_7: m_expressionBar->enterNumberEvent("7"); break; case BasicKeypad::Key_8: m_expressionBar->enterNumberEvent("8"); break; case BasicKeypad::Key_9: m_expressionBar->enterNumberEvent("9"); break; case BasicKeypad::Key_Plus: m_expressionBar->enterSymbolEvent("+"); break; case BasicKeypad::Key_Min: m_expressionBar->enterSymbolEvent("-"); break; case BasicKeypad::Key_Mult: m_expressionBar->enterSymbolEvent("*"); break; case BasicKeypad::Key_Div: m_expressionBar->enterSymbolEvent("/"); break; case BasicKeypad::Key_Percent: m_expressionBar->enterPercentEvent(); break; case BasicKeypad::Key_Equals: m_expressionBar->settingLinkage(); break; case BasicKeypad::Key_Clear: m_expressionBar->enterClearEvent(); break; case BasicKeypad::Key_Backspace: m_expressionBar->enterBackspaceEvent(); break; case BasicKeypad::Key_Point: m_expressionBar->enterPointEvent(); break; case BasicKeypad::Key_Brackets: m_expressionBar->enterBracketsEvent(); break; case MemoryKeypad::Key_MS: m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) //如果输入栏中可计算出结果 m_memoryPublic->generateData(m_expressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemoryKeypad::Key_MC: m_memoryPublic->memoryclean(); if (m_keypadLayout->currentIndex() == 1) { m_keypadLayout->setCurrentIndex(0); MemoryButton *btn5 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mlist)); btn5->setbtnlight(false); } break; case MemoryKeypad::Key_Mlist: showListWidget(); if (m_keypadLayout->currentIndex() == 1) { m_expressionBar->setAttribute(Qt::WA_TransparentForMouseEvents); //鼠标穿透 m_memoryKeypad->setAttribute(Qt::WA_TransparentForMouseEvents); //鼠标穿透 } else { m_expressionBar->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_memoryKeypad->setAttribute(Qt::WA_TransparentForMouseEvents, false); } m_memorylistwidget->setFocus(Qt::MouseFocusReason); pagefocus = true; break; case MemoryKeypad::Key_Mplus: m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) m_memoryPublic->memoryplus(m_expressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemoryKeypad::Key_Mminus: m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) m_memoryPublic->memoryminus(m_expressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemoryKeypad::Key_MR: p = m_memorylistwidget->getfirstnumber(); m_expressionBar->getInputEdit()->setAnswer(p.first, p.second); this->handleClearStateChanged(false); break; default: break; } if (!pagefocus) m_expressionBar->getInputEdit()->setFocus(); } /** * @brief 焦点空格事件 * @param key-button枚举值 */ void BasicModule::handleKeypadButtonPressByspace(int key) { m_basicKeypad->update(); m_memoryKeypad->update(); //20200414 bug20294鼠标点击取消focus // m_expressionBar->getInputEdit()->setFocus(); QPair p; switch (key) { case BasicKeypad::Key_0: m_expressionBar->enterNumberEvent("0"); //按键0事件 m_basicKeypad->animate(BasicKeypad::Key_0, true); break; case BasicKeypad::Key_1: m_expressionBar->enterNumberEvent("1"); m_basicKeypad->animate(BasicKeypad::Key_1, true); break; case BasicKeypad::Key_2: m_expressionBar->enterNumberEvent("2"); m_basicKeypad->animate(BasicKeypad::Key_2, true); break; case BasicKeypad::Key_3: m_expressionBar->enterNumberEvent("3"); m_basicKeypad->animate(BasicKeypad::Key_3, true); break; case BasicKeypad::Key_4: m_expressionBar->enterNumberEvent("4"); m_basicKeypad->animate(BasicKeypad::Key_4, true); break; case BasicKeypad::Key_5: m_expressionBar->enterNumberEvent("5"); m_basicKeypad->animate(BasicKeypad::Key_5, true); break; case BasicKeypad::Key_6: m_expressionBar->enterNumberEvent("6"); m_basicKeypad->animate(BasicKeypad::Key_6, true); break; case BasicKeypad::Key_7: m_expressionBar->enterNumberEvent("7"); m_basicKeypad->animate(BasicKeypad::Key_7, true); break; case BasicKeypad::Key_8: m_expressionBar->enterNumberEvent("8"); m_basicKeypad->animate(BasicKeypad::Key_8, true); break; case BasicKeypad::Key_9: m_expressionBar->enterNumberEvent("9"); m_basicKeypad->animate(BasicKeypad::Key_9, true); break; case BasicKeypad::Key_Plus: m_expressionBar->enterSymbolEvent("+"); m_basicKeypad->animate(BasicKeypad::Key_Plus, true); break; case BasicKeypad::Key_Min: m_expressionBar->enterSymbolEvent("-"); m_basicKeypad->animate(BasicKeypad::Key_Min, true); break; case BasicKeypad::Key_Mult: m_expressionBar->enterSymbolEvent("*"); m_basicKeypad->animate(BasicKeypad::Key_Mult, true); break; case BasicKeypad::Key_Div: m_expressionBar->enterSymbolEvent("/"); m_basicKeypad->animate(BasicKeypad::Key_Div, true); break; case BasicKeypad::Key_Percent: m_expressionBar->enterPercentEvent(); m_basicKeypad->animate(BasicKeypad::Key_Percent, true); break; case BasicKeypad::Key_Equals: m_expressionBar->settingLinkage(); m_basicKeypad->animate(BasicKeypad::Key_Equals, true); break; case BasicKeypad::Key_Clear: m_expressionBar->enterClearEvent(); m_basicKeypad->animate(BasicKeypad::Key_Clear, true); break; case BasicKeypad::Key_Backspace: m_expressionBar->enterBackspaceEvent(); m_basicKeypad->animate(BasicKeypad::Key_Backspace, true); break; case BasicKeypad::Key_Point: m_expressionBar->enterPointEvent(); m_basicKeypad->animate(BasicKeypad::Key_Point, true); break; case BasicKeypad::Key_Brackets: m_expressionBar->enterBracketsEvent(); m_basicKeypad->animate(BasicKeypad::Key_Brackets, true); break; case MemoryKeypad::Key_MS: m_memoryKeypad->animate(MemoryKeypad::Key_MS, true); m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) //如果输入栏中可计算出结果 m_memoryPublic->generateData(m_expressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemoryKeypad::Key_MC: m_memoryKeypad->animate(MemoryKeypad::Key_MC, true); m_memoryPublic->memoryclean(); if (m_keypadLayout->currentIndex() == 1) { m_keypadLayout->setCurrentIndex(0); MemoryButton *btn5 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mlist)); btn5->setbtnlight(false); } break; case MemoryKeypad::Key_Mlist: m_memoryKeypad->animate(MemoryKeypad::Key_Mlist, true); showListWidget(); if (m_keypadLayout->currentIndex() == 1) { m_expressionBar->setAttribute(Qt::WA_TransparentForMouseEvents); //鼠标穿透 m_memoryKeypad->setAttribute(Qt::WA_TransparentForMouseEvents); //鼠标穿透 } else { m_expressionBar->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_memoryKeypad->setAttribute(Qt::WA_TransparentForMouseEvents, false); } m_memorylistwidget->setFocus(Qt::TabFocusReason); break; case MemoryKeypad::Key_Mplus: m_memoryKeypad->animate(MemoryKeypad::Key_Mplus, true); m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) m_memoryPublic->memoryplus(m_expressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemoryKeypad::Key_Mminus: m_memoryKeypad->animate(MemoryKeypad::Key_Mminus, true); m_expressionBar->settingLinkage(); if (m_expressionBar->getInputEdit()->getMemoryAnswer().first) m_memoryPublic->memoryminus(m_expressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemoryKeypad::Key_MR: m_memoryKeypad->animate(MemoryKeypad::Key_MR, true); p = m_memorylistwidget->getfirstnumber(); m_expressionBar->getInputEdit()->setAnswer(p.first, p.second); this->handleClearStateChanged(false); break; default: break; } } /** * @brief 设置清楚按键状态 */ void BasicModule::handleClearStateChanged(bool isAllClear) { TextButton *btn = static_cast(m_basicKeypad->button(BasicKeypad::Key_Clear)); if (isAllClear) { btn->setText("AC"); } else { btn->setText("C"); } } void BasicModule::setBasicTabOrder() { this->setTabOrder(m_expressionBar->getInputEdit(), m_memoryKeypad->button(MemoryKeypad::Key_MC)); for (int i = 0; i < 5; i++) { this->setTabOrder(m_memoryKeypad->button(MemoryKeypad::Key_MC + i), m_memoryKeypad->button(MemoryKeypad::Key_MC + i + 1)); } this->setTabOrder(m_memoryKeypad->button(MemoryKeypad::Key_Mlist), m_basicKeypad->button(BasicKeypad::Key_Clear)); for (int i = 0; i < 20; i++) { this->setTabOrder(m_basicKeypad->button(BasicKeypad::Key_Clear + i), m_basicKeypad->button(BasicKeypad::Key_Clear + i + 1)); } } /** * @brief mainwindow焦点不在basicmodul时也触发keypress */ void BasicModule::setKeyPress(QKeyEvent *e) { handleEditKeyPress(e); } /** * @brief 向内存中存入数据时触发 */ void BasicModule::mAvailableEvent() { m_avail = true; MemoryButton *btn = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MC)); btn->setEnabled(true); MemoryButton *btn1 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MR)); btn1->setEnabled(true); MemoryButton *btn2 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mlist)); btn2->setEnabled(true); m_memRCbtn = true; } /** * @brief 清空内存列表触发 */ void BasicModule::mUnAvailableEvent() { m_avail = false; MemoryButton *btn = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MC)); btn->setEnabled(false); btn->updateWhenBtnDisable(); MemoryButton *btn1 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MR)); btn1->setEnabled(false); m_memRCbtn = false; if (m_keypadLayout->currentIndex() == 0) { MemoryButton *btn2 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mlist)); btn2->setEnabled(false); } } /** * @brief 显示内存列表 */ void BasicModule::showListWidget() { if (m_keypadLayout->currentIndex() == 0) { m_keypadLayout->setCurrentIndex(1); m_memorylistwidget->resetLabelBySeparator(); MemoryButton *btn2 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mplus)); btn2->setbuttongray(true); btn2->setEnabled(false); MemoryButton *btn3 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mminus)); btn3->setbuttongray(true); btn3->setEnabled(false); MemoryButton *btn4 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MS)); btn4->setbuttongray(true); btn4->setEnabled(false); MemoryButton *btn = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MR)); btn->setbuttongray(true); btn->setEnabled(false); MemoryButton *btn1 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MC)); btn1->setbuttongray(true); btn1->setEnabled(false); MemoryButton *btn5 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mlist)); btn5->updateWhenBtnDisable(); btn5->setbtnlight(true); btn5->setEnabled(false); m_isallgray = true; } /*else { m_keypadLayout->setCurrentIndex(0); }*/ } void BasicModule::closeListWidget() { //内存界面显示时,点击内存界面以外部分切换内存界面为键盘界面 if (m_keypadLayout->currentIndex() == 1 && m_insidewidget == false) { m_keypadLayout->setCurrentIndex(0); MemoryButton *btn2 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mplus)); btn2->setbuttongray(false); btn2->setEnabled(true); MemoryButton *btn3 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mminus)); btn3->setbuttongray(false); btn3->setEnabled(true); MemoryButton *btn4 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MS)); btn4->setbuttongray(false); btn4->setEnabled(true); MemoryButton *btn = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MR)); btn->setbuttongray(false); btn->setEnabled(true); MemoryButton *btn1 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MC)); btn1->setbuttongray(false); btn1->setEnabled(true); MemoryButton *btn5 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mlist)); btn5->setbtnlight(false); btn5->setEnabled(true); m_isallgray = false; m_expressionBar->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_memoryKeypad->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_expressionBar->getInputEdit()->setFocus(); } if (m_avail == true) { MemoryButton *btn = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MC)); btn->setEnabled(true); MemoryButton *btn4 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MR)); btn4->setEnabled(true); m_memRCbtn = true; } else { MemoryButton *btn = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MC)); btn->setEnabled(false); btn->updateWhenBtnDisable(); MemoryButton *btn1 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_MR)); btn1->setEnabled(false); MemoryButton *btn5 = static_cast(m_memoryKeypad->button(MemoryKeypad::Key_Mlist)); btn5->setEnabled(false); m_memRCbtn = false; } m_insidewidget = false; m_expressionBar->getInputEdit()->isExpressionEmpty(); //确认输入栏是否有内容,发送信号M+,M-,MS是否置灰 } void BasicModule::mousePressEvent(QMouseEvent *event) { closeListWidget(); QWidget::mousePressEvent(event); } void BasicModule::mouseMoveEvent(QMouseEvent *event) { Q_UNUSED(event); } deepin-calculator-5.7.21/src/widgets/basicmodule.h000066400000000000000000000045601423020056600221010ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BASICMODULE_H #define BASICMODULE_H #include "inputedit.h" #include "expressionbar.h" #include "../control/textbutton.h" #include "../control/iconbutton.h" #include "../control/basickeypad.h" #include "../control/memorykeypad.h" #include "../views/memorywidget.h" #include "../memorypublic.h" #include #include #include #include #include DGUI_USE_NAMESPACE DWIDGET_USE_NAMESPACE class BasicModule : public DWidget { Q_OBJECT public: explicit BasicModule(QWidget *parent = nullptr); ~BasicModule(); void setKeyPress(QKeyEvent *e); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); public slots: //memory func void mAvailableEvent(); void mUnAvailableEvent(); void showListWidget(); void closeListWidget(); private slots: void initTheme(int type); private: void handleEditKeyPress(QKeyEvent *); void handleKeypadButtonPress(int); void handleKeypadButtonPressByspace(int); void handleClearStateChanged(bool isAllClear); void setBasicTabOrder(); protected: //void paintEvent(QPaintEvent *); private: ExpressionBar *m_expressionBar; BasicKeypad *m_basicKeypad; MemoryKeypad *m_memoryKeypad; QStackedWidget *m_keypadLayout; MemoryWidget *m_memorylistwidget; bool m_insidewidget; bool m_avail = false; //内存中有数据 bool m_isinsidefun = false;//鼠标点击在函数widget内 bool m_memCalbtn; //m+,m-,ms可用 bool m_memRCbtn;//mr,mc可用 bool m_isallgray; //内存按钮全部置灰; MemoryPublic *m_memoryPublic; }; #endif deepin-calculator-5.7.21/src/widgets/expressionbar.cpp000066400000000000000000001564101423020056600230330ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "expressionbar.h" #include "../utils.h" #include #include #include #include #include const int STANDPREC = 15; const int WIDGET_FIXHEIGHT = 147; const int INPUTEDIT_HEIGHT = 55; const int HISTORYLINKAGE_MAXSIZE = 10; ExpressionBar::ExpressionBar(QWidget *parent) : DWidget(parent) { m_listView = new SimpleListView(0, this); m_listDelegate = new SimpleListDelegate(0, this); m_listModel = new SimpleListModel(0, this); m_inputEdit = new InputEdit(this); m_evaluator = Evaluator::instance(); m_isContinue = true; m_isAllClear = false; m_isResult = false; m_inputNumber = false; m_hisRevision = -1; m_linkageIndex = -1; m_isLinked = false; m_isUndo = false; m_Selected = -1; m_meanexp = true; // init inputEdit attributes. m_inputEdit->setFixedHeight(INPUTEDIT_HEIGHT); m_inputEdit->setAlignment(Qt::AlignRight); m_inputEdit->setTextMargins(10, 0, 10, 6); // m_inputEdit->setFocus(); m_listView->setModel(m_listModel); m_listView->setItemDelegate(m_listDelegate); // DPalette pl = this->palette(); // pl.setColor(DPalette::Light, QColor(0, 0, 0, 0)); // pl.setColor(DPalette::Dark, QColor(0, 0, 0, 0)); // pl.setColor(DPalette::Base, QColor(0, 0, 0, 0)); // this->setPalette(pl); QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(m_listView); layout->addWidget(m_inputEdit); layout->setMargin(0); layout->setSpacing(0); setFixedHeight(WIDGET_FIXHEIGHT); initConnect(); } ExpressionBar::~ExpressionBar() {} void ExpressionBar::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } /** * @brief ExpressionBar::enterNumberEvent * 输入0-9的数字 * @param text * 对应的数字 */ void ExpressionBar::enterNumberEvent(const QString &text) { // if (m_isLinked) // clearLinkageCache(); if (m_inputNumber && m_hisRevision == -1) { m_inputEdit->clear(); m_isResult = false; } /*当直接在点击等于号后出的结果后面进行输入,则替换结果*/ //20200615 按等于号后退格结果再输入十位数十位消失问题 if (m_isResult) { m_inputEdit->clear(); m_isResult = false; // clearLinkageCache(); } if (!m_isContinue) { // the cursor position at the end, it will clear edit text. if (cursorPosAtEnd()) m_inputEdit->clear(); m_isContinue = true; } m_inputNumber = false; m_isUndo = false; // 20200401 修改symbolFaultTolerance执行位置 replaceSelection(m_inputEdit->text()); m_inputEdit->insert(text); int nowcur = m_inputEdit->cursorPosition(); m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); m_inputEdit->setText(pointFaultTolerance(m_inputEdit->text())); m_inputEdit->setCursorPosition(nowcur); emit clearStateChanged(false); addUndo(); } /** * @brief ExpressionBar::enterSymbolEvent * 输入四则运算符 * @param text * 对应的运算符 */ void ExpressionBar::enterSymbolEvent(const QString &text) { QString symbol = text; symbol.replace('/', QString::fromUtf8("÷")); QString oldText = m_inputEdit->text(); if (!m_hisLink.isEmpty() && m_hisLink.last().linkedItem == -1) { m_hisLink.last().linkedItem = m_listModel->rowCount(QModelIndex()); m_hisLink.last().isLink = true; m_listDelegate->setHisLinked(m_hisLink.last().linkedItem); m_isLinked = false; if (m_hisLink.size() > HISTORYLINKAGE_MAXSIZE - 1) { m_hisLink.removeFirst(); m_listDelegate->removeLine(0); } } // clearSelectSymbol(); //fix for bug-14117 if (m_isUndo) { int row = m_listModel->rowCount(QModelIndex()); if (row != 0) { QString text = m_listModel->index(row - 1).data(SimpleListModel::ExpressionRole).toString(); QString result = text.split("=").last(); if (result == m_inputEdit->text()) { historicalLinkageIndex his; his.linkageTerm = row - 1; his.linkageValue = result; his.linkedItem = row; m_hisLink.append(his); m_listDelegate->setHisLink(row - 1); m_listDelegate->setHisLinked(row); } } } m_isResult = false; m_isUndo = false; // QString oldText = m_inputEdit->text(); // 20200213统一被选中光标复位代码 replaceSelection(m_inputEdit->text()); if (m_inputEdit->text().isEmpty()) { if (symbol != "-") { m_inputEdit->setText(oldText); } else { m_inputEdit->insert(symbol); } } else { int curPos = m_inputEdit->cursorPosition(); QString exp = m_inputEdit->text(); if (cursorPosAtEnd()) { if (m_inputEdit->text() == "-") { m_inputEdit->setText(oldText); } else { QString lastStr = exp.right(1); if (isOperator(lastStr)) exp.chop(1); m_inputEdit->setText(exp + symbol); } } else if (curPos == 0) { QString firstStr = exp.left(1); if (firstStr == QString::fromUtf8("-")) { m_inputEdit->setText(oldText); } else { if (symbol == QString::fromUtf8("-") || symbol == "-") m_inputEdit->insert(symbol); } } else { QString infront = exp.at(curPos - 1); QString behand = exp.at(curPos); if (isOperator(infront) || isOperator(behand)) { m_inputEdit->setText(oldText); } else m_inputEdit->insert(symbol); // 2020316修复添加符号后光标问题 //添加符号后左侧数字不会多分隔符,只需考虑添加符号后输入框光标前的数字与添加前是否一致 if (exp.mid(0, curPos).remove(QRegExp("[+-×÷,.%()E]")) == m_inputEdit->text().mid(0, curPos).remove(QRegExp("[+-×÷,.%()E]"))) { QString sRegNum = "[+-×÷]"; QRegExp rx; rx.setPattern(sRegNum); rx.exactMatch(m_inputEdit->text().at(curPos)) ? m_inputEdit->setCursorPosition(curPos + 1) : m_inputEdit->setCursorPosition(curPos); } else m_inputEdit->setCursorPosition(curPos - 1); } } m_isContinue = true; expressionCheck(); if (!m_inputEdit->text().isEmpty()) { emit clearStateChanged(false); } addUndo(); } /** * @brief ExpressionBar::enterPointEvent * 输入小数点 */ void ExpressionBar::enterPointEvent() { // if (m_isLinked) // clearLinkageCache(); replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); if (curpos == 0) { m_inputEdit->insert("0."); } else { if (exp.at(curpos - 1) == ".") return; //20200716修改在)及%后小数点不可输入问题 // if (exp.at(curpos - 1) != ")" && exp.at(curpos - 1) != "%") { QString sRegNum = "[0-9,]+"; QRegExp rx; rx.setPattern(sRegNum); if (rx.exactMatch(exp.at(curpos - 1))) { int index = exp.indexOf(QRegExp("[^0-9,]"), curpos); QString cut = exp.mid(curpos, index - curpos); int aftercurpos = cut.count(","); int before = exp.count(","); m_inputEdit->insert("."); int after = m_inputEdit->text().count(","); if (before - aftercurpos == after) { m_inputEdit->setCursorPosition(curpos + 1); } else { m_inputEdit->setCursorPosition(curpos); } } else m_inputEdit->insert("0."); // } } exp = pointFaultTolerance(m_inputEdit->text()); exp = m_inputEdit->symbolFaultTolerance(exp); if (exp != m_inputEdit->text()) m_inputEdit->setText(exp); m_isUndo = false; m_isResult = false; emit clearStateChanged(false); addUndo(); } /** * @brief ExpressionBar::enterBackspaceEvent * 输入退格键 */ void ExpressionBar::enterBackspaceEvent() { // if (m_isResult) // clearLinkageCache(); // m_inputEdit->backspace(); SSelection selection = m_inputEdit->getSelection(); int selcurPos = m_inputEdit->cursorPosition(); if (selection.selected != "") { QString text = m_inputEdit->text(); QString seloldtext = text; text.remove(selection.curpos, selection.selected.size()); m_inputEdit->setText(text); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); if (selcurPos > selection.curpos && selcurPos <= selection.curpos + selection.selected.size()) selcurPos = selection.curpos; // 20200316选中部分光标置位问题修复 if (seloldtext.mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length() == m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length()) m_inputEdit->setCursorPosition(selcurPos); else if (seloldtext.mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length() > m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length()) m_inputEdit->setCursorPosition(selcurPos + 1); else m_inputEdit->setCursorPosition(selcurPos - 1); } else { QString text = m_inputEdit->text(); int cur = m_inputEdit->cursorPosition(); if (text.size() > 0 && cur > 0 && text[cur - 1] == ",") { text.remove(cur - 2, 2); m_inputEdit->setText(text); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); m_inputEdit->setCursorPosition(cur - 2); } else { int proNumber = text.count(","); m_inputEdit->backspace(); int separator = proNumber - m_inputEdit->text().count(","); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(","); if (cur > 0) { QString sRegNum = "[0-9]+"; QRegExp rx; rx.setPattern(sRegNum); //退数字 if (rx.exactMatch(text.at(cur - 1)) && proNumber > newPro) { if (text.mid(cur, text.length() - cur) == m_inputEdit->text().mid(m_inputEdit->text().length() - (text.length() - cur), text.length() - cur)) { m_inputEdit->setCursorPosition(cur - 2); } else m_inputEdit->setCursorPosition(cur - 1); } else { if (separator < 0) { m_inputEdit->setCursorPosition(cur - 1 - separator); } else { m_inputEdit->setCursorPosition(cur - 1); } } //退小数点 if (text.at(cur - 1) == ".") { if (text.mid(0, cur).count(",") != m_inputEdit->text().mid(0, cur).count(",")) m_inputEdit->setCursorPosition(cur); else m_inputEdit->setCursorPosition(cur - 1); } } } } if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } QTimer::singleShot(5000, this, [ = ] { int curpos = m_inputEdit->cursorPosition(); m_inputEdit->setText(pointFaultTolerance(m_inputEdit->text())); m_inputEdit->setCursorPosition(curpos); }); m_isContinue = true; m_isUndo = false; m_isResult = false; addUndo(); } /** * @brief ExpressionBar::enterClearEvent * C/AC的清空事件 */ void ExpressionBar::enterClearEvent() { bool need_addundo = !m_inputEdit->text().isEmpty(); if (m_isAllClear) { m_listModel->clearItems(); m_listView->reset(); m_isAllClear = false; m_isLinked = false; //20200619 清空历史记录时将联动参数置为false m_isAutoComputation = false; m_hisRevision = -1; m_hisLink.clear(); m_listDelegate->removeAllLink(); emit clearStateChanged(false); } else { if (m_listModel->rowCount(QModelIndex()) == 0) emit clearStateChanged(false); else emit clearStateChanged(true); m_inputEdit->clear(); m_isAllClear = true; // clearLinkageCache(); } m_isResult = false; m_isUndo = false; m_Selected = -1; if (need_addundo) addUndo(); } /** * @brief ExpressionBar::enterEqualEvent * 输入栏中表达式的求值,以及求值后的格式化 */ void ExpressionBar::enterEqualEvent() { QString oldtext = m_inputEdit->text(); if (m_inputEdit->text().isEmpty()) return; if (!m_isLinked) clearLinkageCache(m_inputEdit->text(), true); if (m_hisRevision == -1) { const QString expression = formatExpression(m_inputEdit->expressionText()); QString exp = symbolComplement(expression); m_evaluator->setExpression(exp); } else { const QString expression = formatExpression(m_inputEdit->text()); QString exp = symbolComplement(expression); m_evaluator->setExpression(exp); } Quantity ans = m_evaluator->evalUpdateAns(); QString newResult; // 20200403 bug-18971 表达式错误时输数字加等于再重新输入表达式历史记录错误表达式未被替换 // 20200407 超过16位小数未科学计数 if (m_evaluator->error().isEmpty() && (oldtext.indexOf(QRegExp("[+-×÷.,%()E]")) != -1)) { if (ans.isNan() && !m_evaluator->isUserFunctionAssign()) return; //edit 20200413 for bug--19653 const QString result = DMath::format(ans, Quantity::Format::General() + Quantity::Format::Precision(STANDPREC)); QString formatResult = Utils::formatThousandsSeparators(result); formatResult = formatResult.replace(QString::fromUtf8("+"), "+") .replace(QString::fromUtf8("-"), "-") .replace(QString::fromUtf8("×"), "*") .replace(QString::fromUtf8("÷"), "/"); //.replace(QString::fromUtf8(","), ""); // QString tStr = m_inputEdit->text().replace(QString::fromUtf8(","), ""); QString tStr = m_inputEdit->text(); //edit 20200518 for bug-26628 QString StrToComp = formatResult; StrToComp = StrToComp.replace("+", QString::fromUtf8("+")) .replace("-", QString::fromUtf8("-")) .replace("*", QString::fromUtf8("×")) .replace("/", QString::fromUtf8("÷")); if (StrToComp == oldtext) return; //end edit 20200518 for bug-26628 // 20200402 需求3.2.1.6当输入的数字中有千位符,点击等号视为前后一致,不计入表达式 if (formatResult != tStr) { m_listModel->updataList(m_inputEdit->text() + "=" + formatResult, m_hisRevision); m_inputEdit->setAnswer(formatResult, ans); newResult = formatResult; } m_isContinue = false; } else { // 20200403 bug-18971 表达式错误时输数字加等于再重新输入表达式历史记录错误表达式未被替换 if (!m_evaluator->error().isEmpty()) { m_listModel->updataList(m_inputEdit->text() + "=" + tr("Expression error"), m_hisRevision); m_meanexp = false; // 20200409 输入错误表达式后,修改历史记录,再次输入表达式后高亮未取消 } else { m_meanexp = false; return; } if (m_hisRevision == -1) m_hisRevision = m_listModel->rowCount(QModelIndex()) - 1; else { for (int i = 0; i < m_hisLink.size(); ++i) { if (m_hisLink[i].linkageTerm == m_hisRevision) { // m_listDelegate->removeLine(m_hisLink[i].linkageTerm, // m_hisLink[i].linkedItem); m_listDelegate->removeLine(i); m_hisLink.removeAt(i); --i; } } } } QString selectedresult = QString(); if (m_isLinked) { if (m_hisRevision == -1) { m_isLinked = false; m_listView->scrollToBottom(); m_isResult = true; m_isUndo = false; addUndo(); return; } for (int i = 0; i < m_hisLink.size(); ++i) { if (m_hisRevision == m_hisLink[i].linkageTerm) { m_hisRevision = m_hisLink[i].linkedItem; if (m_hisRevision == -1) { m_hisLink.remove(i); m_listDelegate->removeHisLink(); break; } QString text = m_listModel->index(m_hisRevision) .data(SimpleListModel::ExpressionRole) .toString(); QString linkedExp = text.split("=").first(); int length = m_hisLink[i].linkageValue.length(); if (linkedExp.left(length) != m_hisLink[i].linkageValue || (!isOperator(linkedExp.at(length)) && (linkedExp.at(length) != "("))) { m_hisLink.remove(i); m_listDelegate->removeHisLink(); break; } if (newResult.isEmpty()) break; newResult = newResult.replace("+", QString::fromUtf8("+")) .replace("-", QString::fromUtf8("-")); m_hisLink[i].linkageValue = newResult; QString newText = newResult + linkedExp.right(linkedExp.length() - length); m_inputEdit->setText(newText); settingLinkage(); } } if (m_Selected != -1 && m_evaluator->error().isEmpty()) { selectedresult = m_listModel->index(m_Selected) .data(SimpleListModel::ExpressionRole) .toString() .split("=") .last(); m_inputEdit->setText(selectedresult); } // 20200403 表达式错误重新输入新表达式输入框无结果 // if (m_evaluator->error().isEmpty()) // m_inputEdit->clear(); } // 20200403 bug-18971 表达式错误时输数字加等于再重新输入表达式历史记录错误表达式未被替换 if (m_evaluator->error().isEmpty() && (oldtext.indexOf(QRegExp("[+-×÷,.%()E]")) != -1)) m_hisRevision = -1; m_listView->scrollToBottom(); m_isLinked = false; m_isResult = true; m_isUndo = false; addUndo(); } /** * @brief ExpressionBar::enterPercentEvent * 当前使用的输入百分号的事件 */ void ExpressionBar::enterPercentEvent() { if (m_inputEdit->text().isEmpty()) { // m_inputEdit->setText("0%"); return; } m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(","); bool isAtEnd = cursorPosAtEnd(); /* * 当光标位置的前一位是运算符时,在函数方法前面补0,当函数的运算优先级小于等于 * 前一位运算符时,则补(0 * %做特殊处理--0%无效,故不显示 */ int diff = 0; //补数字后光标位移的距离 QString sRegNum = "[+-×÷/(^!%E]"; QRegExp rx; rx.setPattern(sRegNum); if (curpos == 0 || rx.exactMatch(exp.at(curpos - 1))) { m_inputEdit->insert(""); diff = -1; } else m_inputEdit->insert("%"); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(","); m_isUndo = false; addUndo(); if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != ",") { m_inputEdit->setCursorPosition(curpos + diff); } else { m_inputEdit->setCursorPosition(curpos + 1 + diff); } } else { m_inputEdit->setCursorPosition(curpos + 1 + diff); } } /** * @brief ExpressionBar::enterBracketsEvent * 数字键盘中点击左右括号的事件,直接显示左右括号,光标位于中间 */ void ExpressionBar::enterBracketsEvent() { if (!m_hisLink.isEmpty() && m_hisLink.last().linkedItem == -1) { m_hisLink.last().linkedItem = m_listModel->rowCount(QModelIndex()); m_hisLink.last().isLink = true; m_listDelegate->setHisLinked(m_hisLink.last().linkedItem); m_isLinked = false; if (m_hisLink.size() > HISTORYLINKAGE_MAXSIZE - 1) { m_hisLink.removeFirst(); m_listDelegate->removeLine(0); } } // clearSelectSymbol(); //fix for bug-14117 if (m_isUndo) { int row = m_listModel->rowCount(QModelIndex()); if (row != 0) { QString text = m_listModel->index(row - 1).data(SimpleListModel::ExpressionRole).toString(); QString result = text.split("=").last(); if (result == m_inputEdit->text()) { historicalLinkageIndex his; his.linkageTerm = row - 1; his.linkageValue = result; his.linkedItem = row; m_hisLink.append(his); m_listDelegate->setHisLink(row - 1); m_listDelegate->setHisLinked(row); } } } m_isResult = false; replaceSelection(m_inputEdit->text()); QString oldText = m_inputEdit->text(); int currentPos = m_inputEdit->cursorPosition(); m_inputEdit->insert("()"); // 20200401 symbolFaultTolerance QString formatexp = m_inputEdit->symbolFaultTolerance(m_inputEdit->text()); if (oldText.mid(0, currentPos).count(",") == m_inputEdit->text().mid(0, currentPos).count(",")) m_inputEdit->setCursorPosition(currentPos + 1); else m_inputEdit->setCursorPosition(currentPos); if (formatexp == oldText) m_inputEdit->setText(formatexp); m_isUndo = false; emit clearStateChanged(false); addUndo(); } /** * @brief ExpressionBar::enterLeftBracketsEvent * 键盘左括号输入的事件,rightbrackets为右括号(数字键盘无法输入单个的左右括号) */ void ExpressionBar::enterLeftBracketsEvent() { if (!m_hisLink.isEmpty() && m_hisLink.last().linkedItem == -1) { m_hisLink.last().linkedItem = m_listModel->rowCount(QModelIndex()); m_hisLink.last().isLink = true; m_listDelegate->setHisLinked(m_hisLink.last().linkedItem); m_isLinked = false; if (m_hisLink.size() > HISTORYLINKAGE_MAXSIZE - 1) { m_hisLink.removeFirst(); m_listDelegate->removeLine(0); } } // clearSelectSymbol(); //fix for bug-14117 if (m_isUndo) { int row = m_listModel->rowCount(QModelIndex()); if (row != 0) { QString text = m_listModel->index(row - 1).data(SimpleListModel::ExpressionRole).toString(); QString result = text.split("=").last(); if (result == m_inputEdit->text()) { historicalLinkageIndex his; his.linkageTerm = row - 1; his.linkageValue = result; his.linkedItem = row; m_hisLink.append(his); m_listDelegate->setHisLink(row - 1); m_listDelegate->setHisLinked(row); } } } m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(","); bool isAtEnd = cursorPosAtEnd(); m_inputEdit->insert("("); // 20200401 symbolFaultTolerance QString formatexp = m_inputEdit->symbolFaultTolerance(m_inputEdit->text()); int newPro = m_inputEdit->text().count(","); m_isUndo = false; addUndo(); if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != ",") { m_inputEdit->setCursorPosition(curpos); } else { m_inputEdit->setCursorPosition(curpos + 1); } } if (formatexp == exp) m_inputEdit->setText(formatexp); emit clearStateChanged(false); } void ExpressionBar::enterRightBracketsEvent() { if (!m_hisLink.isEmpty() && m_hisLink.last().linkedItem == -1) { m_hisLink.last().linkedItem = m_listModel->rowCount(QModelIndex()); m_hisLink.last().isLink = true; m_listDelegate->setHisLinked(m_hisLink.last().linkedItem); m_isLinked = false; if (m_hisLink.size() > HISTORYLINKAGE_MAXSIZE - 1) { m_hisLink.removeFirst(); m_listDelegate->removeLine(0); } } // clearSelectSymbol(); //fix for bug-14117 if (m_isUndo) { int row = m_listModel->rowCount(QModelIndex()); if (row != 0) { QString text = m_listModel->index(row - 1).data(SimpleListModel::ExpressionRole).toString(); QString result = text.split("=").last(); if (result == m_inputEdit->text()) { historicalLinkageIndex his; his.linkageTerm = row - 1; his.linkageValue = result; his.linkedItem = row; m_hisLink.append(his); m_listDelegate->setHisLink(row - 1); m_listDelegate->setHisLinked(row); } } } m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(","); bool isAtEnd = cursorPosAtEnd(); m_inputEdit->insert(")"); // 20200401 symbolFaultTolerance QString formatexp = m_inputEdit->symbolFaultTolerance(m_inputEdit->text()); int newPro = m_inputEdit->text().count(","); m_isUndo = false; addUndo(); if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != ",") { m_inputEdit->setCursorPosition(curpos); } else { m_inputEdit->setCursorPosition(curpos + 1); } } if (formatexp == exp) m_inputEdit->setText(formatexp); emit clearStateChanged(false); } /** * @brief ExpressionBar::copyResultToClipboard * 将输入栏中的内容复制到剪贴板 */ void ExpressionBar::copyResultToClipboard() { // m_evaluator->unsetVariable(QLatin1String("e"), true); if (m_inputEdit->text().isEmpty()) return; // QApplication::clipboard()->setText(m_inputEdit->selectedText()); //edit for bug-37850 非全选不复制计算结果->输入栏复制的内容不是表达式的结果,而是选中的表达式 SSelection selection = m_inputEdit->getSelection(); QApplication::clipboard()->setText(selection.selected); //将选中项放入粘贴板 // SSelection selection = m_inputEdit->getSelection(); // if (selection.selected != "" && selection.selected != m_inputEdit->text()) { // QApplication::clipboard()->setText(selection.selected); // return; // } // const QString expression = formatExpression(m_inputEdit->text()); // m_evaluator->setExpression(expression); // Quantity ans = m_evaluator->evalUpdateAns(); // if (m_evaluator->error().isEmpty()) { // if (ans.isNan() && !m_evaluator->isUserFunctionAssign()) // return; // //edit 20200413 for bug--19653 // const QString result = DMath::format(ans, Quantity::Format::General() + Quantity::Format::Precision(STANDPREC)); // QString formatResult = Utils::formatThousandsSeparators(result); // formatResult = formatResult.replace('-', "-").replace('+', "+"); // // m_inputEdit->setAnswer(formatResult, ans); // QApplication::clipboard()->setText(formatResult); // } else { // QApplication::clipboard()->setText(m_inputEdit->text()); // } } /** * @brief ExpressionBar::copyClipboard2Result * 将剪贴板的内容复制到输入栏 */ void ExpressionBar::copyClipboard2Result() { if (!m_hisLink.isEmpty() && m_hisLink.last().linkedItem == -1) { m_hisLink.last().linkedItem = m_listModel->rowCount(QModelIndex()); m_hisLink.last().isLink = true; m_listDelegate->setHisLinked(m_hisLink.last().linkedItem); m_isLinked = false; if (m_hisLink.size() > HISTORYLINKAGE_MAXSIZE - 1) { m_hisLink.removeFirst(); m_listDelegate->removeLine(0); } } // clearSelectSymbol(); //fix for bug-14117 if (m_isUndo) { int row = m_listModel->rowCount(QModelIndex()); if (row != 0) { QString text = m_listModel->index(row - 1).data(SimpleListModel::ExpressionRole).toString(); QString result = text.split("=").last(); if (result == m_inputEdit->text()) { historicalLinkageIndex his; his.linkageTerm = row - 1; his.linkageValue = result; his.linkedItem = row; m_hisLink.append(his); m_listDelegate->setHisLink(row - 1); m_listDelegate->setHisLinked(row); } } } QString oldText = m_inputEdit->text(); //未粘贴操作的text int curpos = m_inputEdit->cursorPosition(); //未粘贴操作的光标位 replaceSelection(oldText); QString exp = m_inputEdit->text(); QString text = Utils::toHalfWidth(QApplication::clipboard()->text()); text = text.left(text.indexOf("=")); text = text.replace('+', QString::fromUtf8("+")) .replace('-', QString::fromUtf8("-")) .replace("_", QString::fromUtf8("-")) .replace('*', QString::fromUtf8("×")) .replace('x', QString::fromUtf8("×")) .replace('X', QString::fromUtf8("×")) .replace(QString::fromUtf8("*"), QString::fromUtf8("×")) .replace(QString::fromUtf8("("), "(") .replace(QString::fromUtf8(")"), ")") .replace(QString::fromUtf8("——"), QString::fromUtf8("-")) .replace(QString::fromUtf8("%"), "%") .replace('/', QString::fromUtf8("÷")); //对粘贴板中的内容进行英替中 text.remove(QRegExp("[^0-9+-×÷,.%()。]")); // text = pasteFaultTolerance(text); m_inputEdit->insert(text); QString faulttolerance = pointFaultTolerance(m_inputEdit->text()); faulttolerance = m_inputEdit->symbolFaultTolerance(faulttolerance); if (faulttolerance != m_inputEdit->text()) m_inputEdit->setText(faulttolerance); //如果经过容错处理的表达式有改变,重新设置表达式,不设置光标 if (m_inputEdit->text() == exp) { m_inputEdit->setText(oldText); m_inputEdit->setCursorPosition(curpos); qDebug() << "Invalid content"; //提示是否复制了无效内容,复制的内容全是字母等 } if (!m_inputEdit->text().isEmpty()) emit clearStateChanged(false); m_isResult = false; m_isUndo = false; addUndo(); } /** * @brief ExpressionBar::allElection * 全选事件 */ void ExpressionBar::allElection() { m_inputEdit->selectAll(); SSelection selection; selection.selected = m_inputEdit->text(); m_inputEdit->setSelection(selection); } /** * @brief ExpressionBar::shear * 剪切事件 */ void ExpressionBar::shear() { QString text = m_inputEdit->text(); int selcurPos = m_inputEdit->cursorPosition(); QString selectText = m_inputEdit->selectedText(); selectText = selectText.replace(",", ""); QApplication::clipboard()->setText(selectText); int start = m_inputEdit->selectionStart(); int length = m_inputEdit->selectionLength(); text.remove(start, length); m_inputEdit->setText(text); selcurPos -= length; m_isResult = false; addUndo(); m_isUndo = false; //设置剪切后光标位置 if (text.mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length() == m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length()) m_inputEdit->setCursorPosition(selcurPos); else if (text.mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length() > m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length()) m_inputEdit->setCursorPosition(selcurPos + 1); else m_inputEdit->setCursorPosition(selcurPos - 1); //发送C/AC切换信号 if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } } /** * @brief 删除事件,选中删除 */ void ExpressionBar::deleteText() { QString text = m_inputEdit->text(); int selcurPos = m_inputEdit->cursorPosition(); int start = m_inputEdit->selectionStart(); int length = m_inputEdit->selectionLength(); text.remove(start, length); m_inputEdit->setText(text); selcurPos -= length; addUndo(); m_isUndo = false; m_isResult = false; //设置删除后光标位置 if (text.mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length() == m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length()) m_inputEdit->setCursorPosition(selcurPos); else if (text.mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length() > m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[+-×÷,.%()E]")).length()) m_inputEdit->setCursorPosition(selcurPos + 1); else m_inputEdit->setCursorPosition(selcurPos - 1); //发送C/AC切换信号 if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } } /** * @brief ExpressionBar::handleTextChanged * 输入栏中为上一次计算的结果时,如果被修改,则输入数字时不进行整体的替换 * @param text */ void ExpressionBar::handleTextChanged(const QString &text) { Q_UNUSED(text); m_isAllClear = false; m_isContinue = true; } bool ExpressionBar::cursorPosAtEnd() { return m_inputEdit->cursorPosition() == m_inputEdit->text().length(); } /** * @brief ExpressionBar::formatExpression * 在进行计算前替换中文符号 * @param text * 需要计算的内容 * @return * 替换后的表达式 */ QString ExpressionBar::formatExpression(const QString &text) { return QString(text) .replace(QString::fromUtf8("+"), "+") .replace(QString::fromUtf8("-"), "-") .replace(QString::fromUtf8("×"), "*") .replace(QString::fromUtf8("÷"), "/") .replace(QString::fromUtf8(","), ""); } /** * @brief ExpressionBar::revisionResults * 点击历史记录后将表达式显示在输入栏 * @param index * 点击的行号/索引 */ void ExpressionBar::revisionResults(const QModelIndex &index) { clearLinkageCache(m_inputEdit->text(), false); QString text = index.data(SimpleListModel::ExpressionRole).toString(); QStringList historic = text.split(QString("="), QString::SkipEmptyParts); if (historic.size() != 2) return; QString expression = historic.at(0); m_hisRevision = index.row(); m_inputEdit->setText(expression); m_Selected = m_hisRevision; m_isResult = false; // fix addundo for history revision m_isUndo = false; addUndo(); emit clearStateChanged(false); } /** * @brief ExpressionBar::completedBracketsCalculation * 自动补全右括号,暂未用到 * @param text * @return */ //QString ExpressionBar::completedBracketsCalculation(QString &text) //{ // int leftBrack = text.count("("); // int rightBrack = text.count(")"); // QString newText = text; // if (leftBrack > rightBrack) { // for (int i = 0; i < leftBrack - rightBrack; i++) // newText += ")"; // } // return newText; //} // edit 20200318 for fix cleanlinkcache /** * @brief ExpressionBar::clearLinkageCache * 判断是否要清除最后一个联动项,如果联动项大于0,则判断表达式的第一位数字是否 * 和上一列历史记录的结果相等,不等则清除联动 * @param text * @param isequal * 区分是点击历史记录还是对表达式进行计算的事件 */ void ExpressionBar::clearLinkageCache(const QString &text, bool isequal) { if (m_hisLink.isEmpty()) return; QString linkedExp = text.split("=").first(); if (m_hisLink.count() > 0 && isequal == true) { int length = m_hisLink.last().linkageValue.length(); if (linkedExp.left(length) != m_hisLink.last().linkageValue || (linkedExp.length() > length && !isOperator(linkedExp.at(length)) && (linkedExp.at(length) != "("))) { m_hisLink.removeLast(); m_isLinked = false; m_listDelegate->removeHisLink(); m_listDelegate->removeHisLinked(); // m_isResult = false; } } else { if (m_hisLink.last().linkedItem == -1) { m_hisLink.removeLast(); m_isLinked = false; m_listDelegate->removeHisLink(); // m_listDelegate->removeHisLinked(); m_isResult = false; } } } /** * @brief ExpressionBar::settingLinkage * 点击等于号后的事件,进行历史记录联动的判断 */ void ExpressionBar::settingLinkage() { // m_evaluator->unsetVariable(QLatin1String("e"), true); const int hisRecision = m_hisRevision; if (hisRecision != -1) { // edit 20200403 删除错误表达式 if (m_Selected != m_hisRevision && m_hisRevision < m_hisLink.count() && m_hisLink[m_hisRevision].linkageValue.count(tr("Expression error")) > 0) { m_hisLink.removeAt(m_hisRevision); m_listModel->deleteItem(m_hisRevision); } for (int i = 0; i < m_hisLink.size(); i++) { if (m_hisLink[i].linkedItem == hisRecision) { if (cancelLink(i + 1) && i != 0) --i; if (m_hisLink.size() == 0) break; } if (m_hisLink[i].linkageTerm == hisRecision) { m_isLinked = true; enterEqualEvent(); return; } } historicalLinkageIndex hisIndex; hisIndex.linkageTerm = hisRecision; // hisIndex.isLink = true; enterEqualEvent(); QString exp = m_listModel->index(hisRecision).data(SimpleListModel::ExpressionRole).toString(); hisIndex.linkageValue = exp.split("=").last(); m_hisLink.push_back(hisIndex); } else { // 20200402 需求3.2.1.6当输入的数字中有千位符,点击等号视为前后一致,不计入表达式 // if (!m_hisLink.isEmpty() && m_hisLink.last().linkedItem == -1) // return; // judgeLinkageAgain(); enterEqualEvent(); m_isLinked = true; historicalLinkageIndex hisIndex; // hisIndex.isLink = true; hisIndex.linkageTerm = m_listModel->rowCount(QModelIndex()) - 1; QString exp = m_listModel->index(hisIndex.linkageTerm) .data(SimpleListModel::ExpressionRole) .toString(); hisIndex.linkageValue = exp.split("=").last(); m_hisLink.push_back(hisIndex); } if (m_meanexp == false) { m_hisLink.pop_back(); m_meanexp = true; } else { m_listDelegate->setHisLink(m_hisLink.last().linkageTerm); } } void ExpressionBar::initConnect() { connect(m_listView, &SimpleListView::obtainingHistoricalSimple, this, &ExpressionBar::revisionResults); connect(m_listView, &SimpleListView::obtainingHistoricalSimple, m_inputEdit, &InputEdit::hisexpression); connect(m_inputEdit, &InputEdit::textChanged, this, &ExpressionBar::handleTextChanged); connect(m_inputEdit, &InputEdit::keyPress, this, &ExpressionBar::keyPress); connect(m_inputEdit, &InputEdit::equal, this, &ExpressionBar::enterEqualEvent); connect(m_inputEdit, &InputEdit::cut, this, &ExpressionBar::shear); connect(m_inputEdit, &InputEdit::copy, this, &ExpressionBar::copyResultToClipboard); connect(m_inputEdit, &InputEdit::paste, this, &ExpressionBar::copyClipboard2Result); connect(m_inputEdit, &InputEdit::deleteText, this, &ExpressionBar::deleteText); connect(m_inputEdit, &InputEdit::selectAllText, this, &ExpressionBar::allElection); connect(m_inputEdit, &InputEdit::undo, this, &ExpressionBar::Undo); connect(m_inputEdit, &InputEdit::redo, this, &ExpressionBar::Redo); connect(m_inputEdit, &InputEdit::setResult, this, &ExpressionBar::setResultFalse); connect(m_inputEdit, &InputEdit::separateChange, this, &ExpressionBar::onSeparateChange); } /** * @brief ExpressionBar::symbolComplement * 当计算((()))这种超过3个括号嵌套的表达式时有问题,手动补乘号进行规避 * @param exp * @return */ QString ExpressionBar::symbolComplement(const QString exp) { QString text = exp; int index = text.indexOf("(", 0); while (index != -1) { if (index >= 1 && (text.at(index - 1).isNumber() || text.mid(index - 3, 3) == "ans")) { text.insert(index, "×"); ++index; } ++index; index = text.indexOf("(", index); } index = text.indexOf(")", 0); while (index != -1) { if (index < text.length() - 1 && text.at(index + 1).isNumber()) { text.insert(index + 1, "×"); ++index; } ++index; index = text.indexOf(")", index); } return text; } /** * @brief 粘贴容错(20200716,粘贴时不再使用此函数) * @param exp 复制的内容 * @return 粘贴后的text */ //QString ExpressionBar::pasteFaultTolerance(QString exp) //{ // exp = m_inputEdit->text().insert(m_inputEdit->cursorPosition(), exp); // exp = pointFaultTolerance(exp); //避免粘贴后的text有两个. // if (exp[0] == ",") // exp.remove(0, 1); // for (int i = 0; i < exp.size(); ++i) { // while (exp[i].isNumber()) { // if (exp[i] == "0" // && exp[i + 1] != "." // && (i == 0 || (exp[i - 1] != "," && exp[i - 1] != "." && !exp[i - 1].isNumber())) // && (i == 0 || !exp[i - 1].isNumber()) // && (exp.size() == 1 || exp[i + 1].isNumber())) { // exp.remove(i, 1); //0的容错处理,例:将0123的0去除 //在输入符号时也会进行此操作 // --i; // } // ++i; // } // if (exp[i] == "." && (i == 0 || !exp[i - 1].isNumber())) { // exp.insert(i, "0"); //补0操作,例:1+.2->1+0.2 //小数点容错处理会进行此操作 // ++i; // } // } // return exp; //} /** * @brief ExpressionBar::pointFaultTolerance * 符号的容错处理 * @param text * @return */ QString ExpressionBar::pointFaultTolerance(const QString &text) { QString oldText = text; // QString reformatStr = Utils::reformatSeparators(QString(text).remove(',')); QString reformatStr = oldText.replace('+', QString::fromUtf8("+")) .replace('-', QString::fromUtf8("-")) .replace("_", QString::fromUtf8("-")) .replace('*', QString::fromUtf8("×")) .replace(QString::fromUtf8("*"), QString::fromUtf8("×")) .replace('/', QString::fromUtf8("÷")) .replace('x', QString::fromUtf8("×")) .replace('X', QString::fromUtf8("×")) .replace(QString::fromUtf8("("), "(") .replace(QString::fromUtf8(")"), ")") .replace(QString::fromUtf8("——"), QString::fromUtf8("-")) .replace(QString::fromUtf8("%"), "%"); QStringList list = reformatStr.split(QRegExp("[+-×÷(]")); //20200717去掉),否则下方)小数点容错无法进入; //此处可不考虑多符号问题 QStringList symbollist; for (int i = 0; i < reformatStr.size(); ++i) { if (QRegExp("[+-×÷(]").exactMatch(reformatStr.at(i))) symbollist << reformatStr.at(i); } reformatStr.clear(); for (int i = 0; i < list.size(); ++i) { QString item = list[i]; int firstPoint = item.indexOf("."); if (item.contains(QString::fromUtf8("。"))) { if (firstPoint >= 0) item.remove(QString::fromUtf8("。")); else item.replace(QString::fromUtf8("。"), "."); firstPoint = item.indexOf("."); } if (firstPoint == -1) { reformatStr += item; if (!symbollist.isEmpty()) { reformatStr += symbollist.first(); symbollist.pop_front(); } continue; } if (firstPoint == 0) { item.insert(firstPoint, "0"); //小数点在数字前,进行补0;例:.123->0.123;此处未对reformatStr进行操作,导致只有两个.时才会进行补0 ++firstPoint; // oldText.replace(list[i], item); } else { if (item.at(firstPoint - 1) == ")" || item.at(firstPoint - 1) == "%") { item.remove(firstPoint, 1); item.insert(firstPoint, "0."); //20200717)及%后小数点补0;与小数点输入处理一致 } } if (item.count(".") > 1) { item.remove("."); item.insert(firstPoint, "."); } reformatStr += item; if (!symbollist.isEmpty()) { reformatStr += symbollist.first(); symbollist.pop_front(); } } for (int i = 0; i < reformatStr.size(); ++i) { if (reformatStr[i] == "." && (i == 0 || !reformatStr[i - 1].isNumber())) { reformatStr.insert(i, "0"); //补0操作,例:1+.2->1+0.2 ++i; } } return reformatStr; } void ExpressionBar::expressionCheck() { QString exp = m_inputEdit->text(); int cur = m_inputEdit->cursorPosition(); int n = m_inputEdit->cursorPosition(); int length = exp.length() - n;//原表达式光标右长度 int sum = 0; for (int i = 0; i < exp.size(); ++i) { if (exp[i] == ",") { exp.remove(i, 1); --i; if (i + 1 < cur) { --cur; } } } for (int i = 0; i < exp.size(); ++i) { int num = 0; int a = 0; while (exp[i].isNumber()) { // fix for delete 0 behind "." if (exp[i] == "0" && exp[i + 1] != "." && (i == 0 || exp[i - 1] != ".") && (i == 0 || !exp[i - 1].isNumber()) && (exp.size() == 1 || exp[i + 1].isNumber())) { exp.remove(i, 1); --i; if (i + 1 < cur) --cur; else { a++;//光标后每个数字段被去掉0的个数 } } ++i; if (i >= cur) num++;//光标后每个数字段长度 } sum = sum + ((num - 1) / 3 - (num - a - 1) / 3) + a; if (exp[i] == "." && (i == 0 || !exp[i - 1].isNumber())) { exp.insert(i, "0"); ++i; if (i < cur) ++cur; } } m_inputEdit->setText(exp); // m_inputEdit->setCursorPosition(cur + separator); m_inputEdit->setCursorPosition(m_inputEdit->text().length() - (length - sum)); //20200525数字前有0时容错删除0光标错位 } /** * @brief ExpressionBar::Undo * 撤销 */ void ExpressionBar::Undo() { if (m_undo.isEmpty()) return; // clearLinkageCache(); m_redo.append(m_undo.last()); m_inputEdit->setRedoAction(true); m_undo.removeLast(); m_isUndo = true; //20200619 从结果撤销到上一次表达式按下数字键不清空输入框 if (m_isResult) m_isResult = false; // 20200319修复选中某一数字按下相同数字无法清除选中内容的问题 if (!m_undo.isEmpty()) { if (m_undo.size() > 1) { for (int i = m_undo.size() - 1; i > 0; i--) { if (m_undo.at(i) == m_inputEdit->text() && m_undo.at(i - 1) == m_inputEdit->text()) m_undo.pop_back(); } } m_inputEdit->setText(m_undo.last()); } else { m_inputEdit->clear(); m_inputEdit->setUndoAction(false); } if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } } /** * @brief ExpressionBar::addUndo * 将当前的内容存入撤销的容器中 */ void ExpressionBar::addUndo() { // 20200319修复选中某一数字按下相同数字无法清除选中内容的问题 // if (!m_undo.isEmpty() && m_inputEdit->text() == m_undo.last()) // return; m_undo.append(m_inputEdit->text()); m_redo.clear(); m_inputEdit->setRedoAction(false); m_inputEdit->setUndoAction(true); SSelection selection; m_inputEdit->setSelection(selection); } void ExpressionBar::Redo() { if (m_redo.isEmpty()) return; // clearLinkageCache(); m_inputEdit->setText(m_redo.last()); m_undo.append(m_inputEdit->text()); m_redo.removeLast(); m_inputEdit->setRedoAction(!m_redo.isEmpty()); if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } } /** * @brief ExpressionBar::initTheme * 向历史记录的listview中传递当前应用主题 * @param type * 主题类型 */ void ExpressionBar::initTheme(int type) { //edit for bug-21476 int typeIn = type; if (typeIn == 0) { typeIn = DGuiApplicationHelper::instance()->themeType(); } m_listDelegate->setThemeType(typeIn); m_inputEdit->themetypechanged(typeIn); } //void ExpressionBar::setSelection() //{ // SSelection select = m_inputEdit->getSelection(); // if (select.selected.isEmpty()) // return; // if (m_inputEdit->text() == select.clearText) // m_inputEdit->setText(select.oldText); // select.selected = ""; //} //void ExpressionBar::getSelection() //{ // if (!m_inputEdit->selectedText().isEmpty()) { // int start = m_inputEdit->selectionStart(); // QString exp = m_inputEdit->text(); // exp = exp.remove(start, m_inputEdit->selectionLength()); // m_inputEdit->setText(exp); // m_inputEdit->setCursorPosition(start); // } //} void ExpressionBar::setResultFalse() { m_isResult = false; } /** * @brief ExpressionBar::replaceSelection * 清除选中的内容并设置光标位置 * @param text */ void ExpressionBar::replaceSelection(QString text) { QString seloldtext = text; SSelection selection = m_inputEdit->getSelection(); int selcurPos = m_inputEdit->cursorPosition(); if (selection.selected != "") { //删除选中部分 text.remove(selection.curpos, selection.selected.size()); m_inputEdit->setText(text); if (selcurPos > selection.curpos && selcurPos <= selection.curpos + selection.selected.size()) selcurPos = selection.curpos; // 20200313选中部分光标置位问题修复 if (seloldtext.mid(0, selcurPos).remove(QRegExp("[,]")).length() == m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[,]")).length()) m_inputEdit->setCursorPosition(selcurPos); else if (seloldtext.mid(0, selcurPos).remove(QRegExp("[,]")).length() > m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[,]")).length()) m_inputEdit->setCursorPosition(selcurPos + 1); else m_inputEdit->setCursorPosition(selcurPos - 1); } // reset selection selection = SSelection(); m_inputEdit->setSelection(selection); } bool ExpressionBar::cancelLink(int index) { bool isRemove = false; for (int i = 0; i < index; ++i) { if (m_hisLink[i].linkedItem == m_hisRevision) { QString exp = m_inputEdit->text(); exp = exp.replace(",", ""); QStringList list = exp.split(QRegExp("[+-×÷()]")); if (exp[0] == "-") list[0] = "-" + list[1]; QString linkvalue = m_hisLink[i].linkageValue; linkvalue = linkvalue.replace(",", ""); // if (list.at(0) != m_hisLink[i].linkageValue) { if (list.at(0) != linkvalue) { // m_listDelegate->removeLine(m_hisLink[i].linkageTerm, // m_hisLink[i].linkedItem); m_listDelegate->removeLine(i); m_hisLink.remove(i); isRemove = true; } } } return isRemove; } //void ExpressionBar::settingLinkage(const QModelIndex &index) //{ // int row = index.row(); // for (int i = 0; i < m_hisLink.size(); i++) { // if (m_hisLink[i].linkageTerm == row) { // m_hisLink[i].isLink = true; // m_inputEdit->clear(); // } // } //} bool ExpressionBar::isOperator(const QString &text) { if (text == QString::fromUtf8("+") || text == QString::fromUtf8("-") || text == QString::fromUtf8("×") || text == QString::fromUtf8("÷")) { return true; } else { return false; } } void ExpressionBar::moveLeft() { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() - 1); m_inputEdit->setFocus(); } void ExpressionBar::moveRight() { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() + 1); m_inputEdit->setFocus(); } //20200414 bug20294鼠标点击取消focus InputEdit *ExpressionBar::getInputEdit() { return m_inputEdit; } /** * @brief ExpressionBar::separateChange * 数字间隔位数发生改变 */ void ExpressionBar::onSeparateChange() { m_listModel->updataOfSeparate(); } deepin-calculator-5.7.21/src/widgets/expressionbar.h000066400000000000000000000102731423020056600224740ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef EXPRESSIONBAR_H #define EXPRESSIONBAR_H #include "../../3rdparty/core/evaluator.h" #include "inputedit.h" #include "../views/simplelistdelegate.h" #include "../views/simplelistmodel.h" #include "../views/simplelistview.h" #include #include #include #include #include #include DWIDGET_USE_NAMESPACE /** * @brief 存放联动信息 */ struct historicalLinkageIndex { int linkageTerm; int linkedItem; QString linkageValue; bool isLink; historicalLinkageIndex() { linkageTerm = -1; linkedItem = -1; isLink = false; } }; /** * @brief 暂未使用 */ struct strck { QString text; bool isResult; strck() { isResult = false; } }; class ExpressionBar : public DWidget { Q_OBJECT public: explicit ExpressionBar(QWidget *parent = nullptr); ~ExpressionBar(); void mouseMoveEvent(QMouseEvent *e); signals: void keyPress(QKeyEvent *); void clearStateChanged(bool); void themeChange(int type); void turnDeg(); public slots: //输入事件 void enterNumberEvent(const QString &text); void enterSymbolEvent(const QString &text); void enterPointEvent(); void enterBackspaceEvent(); void enterClearEvent(); void enterEqualEvent(); void enterPercentEvent(); // void enterPercentEventBak(); // void enterPercentEventCommon(); void enterBracketsEvent(); void enterLeftBracketsEvent(); void enterRightBracketsEvent(); void moveLeft(); void moveRight(); void copyResultToClipboard(); void copyClipboard2Result(); void allElection(); void shear(); void deleteText(); void clearLinkageCache(const QString &text, bool isequal); // void settingLinkage(const QModelIndex &index); void settingLinkage(); void Undo(); void addUndo(); void Redo(); void initTheme(int type); // void setSelection(); // void getSelection(); void setResultFalse(); void replaceSelection(QString text); InputEdit *getInputEdit(); private slots: void handleTextChanged(const QString &text); void revisionResults(const QModelIndex &index); void onSeparateChange();//数字间隔位数发生改变 private: bool cursorPosAtEnd(); QString formatExpression(const QString &text); // QString completedBracketsCalculation(QString &text); bool isOperator(const QString &text); bool cancelLink(int index); void initConnect(); QString symbolComplement(const QString exp); // QString pasteFaultTolerance(QString exp); QString pointFaultTolerance(const QString &text); void expressionCheck(); private: Evaluator *m_evaluator; SimpleListView *m_listView; SimpleListDelegate *m_listDelegate; SimpleListModel *m_listModel; InputEdit *m_inputEdit; bool m_isContinue; //点击结果左侧可继续输入,在结果最右侧清除结果 bool m_isAllClear; //C,AC切换标志 bool m_isResult; //计算结果 bool m_isAutoComputation; //自动计算 bool m_inputNumber; //输入数字 bool m_isUndo; int m_hisRevision; //历史记录修改项 bool m_isLinked; //联动状态 int m_linkageIndex; //联动索引缓存 int m_Selected; //历史记录选中项 QVector m_hisLink; //历史联动索引 QVector m_undo; QVector m_redo; bool m_meanexp; //是否表达式为纯数字 }; #endif deepin-calculator-5.7.21/src/widgets/inputedit.cpp000066400000000000000000001261221423020056600221510ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "inputedit.h" #include "../../3rdparty/core/settings.h" #include "../../3rdparty/math/floatconfig.h" #include "../utils.h" #include "../dsettings.h" #include #include #include #include #include #include #include const QString AtoF = "ABCDEF"; InputEdit::InputEdit(QWidget *parent) : QLineEdit(parent) , m_ans(0) , m_ansStartPos(0) , m_ansLength(0) , m_ansVaild(false) , m_currentInAns(false) , m_currentOnAnsLeft(false) , m_oldText("") , m_lastPos(0) , m_memoryans(0) { m_evaluator = Evaluator::instance(); setAttribute(Qt::WA_InputMethodEnabled, false); //禁止中文输入法 setAttribute(Qt::WA_TranslucentBackground); //设置窗口透明 setFocusPolicy(Qt::StrongFocus); //接受Tab键和鼠标单击做焦点 autoZoomFontSize(); initAction(); this->setFrame(false); this->setClearButtonEnabled(false); //不显示清除按钮 this->setContextMenuPolicy(Qt::CustomContextMenu); //信号(customContextMenuRequested)槽完成右击菜单事件 connect(this, &QLineEdit::textChanged, this, &InputEdit::handleTextChanged); connect(this, &QLineEdit::cursorPositionChanged, this, &InputEdit::handleCursorPositionChanged); connect(this, &QLineEdit::customContextMenuRequested, this, &InputEdit::showTextEditMenu); //右键菜单信号槽 connect(this, &QLineEdit::selectionChanged, this, &InputEdit::selectionChangedSlot); connect(this, &QLineEdit::selectionChanged, [ = ] { int pos = this->cursorPosition(); this->cursorPositionChanged(pos, pos); }); connect(this, &QLineEdit::textChanged, this, &InputEdit::isExpressionEmpty); connect(this, &QLineEdit::textChanged, this, &InputEdit::getCurrentAns); connect(this, &InputEdit::swietThreeSeparate, this, &InputEdit::onSwietThreeSeparateClicked); connect(this, &InputEdit::swietFourSeparate, this, &InputEdit::onswietFourSeparateClicked); m_funclist = {"and", "not", "xor", "nand", "nor", "mod", "or", "shl", "shr", "sal", "sar", "rol", "ror", "rcl", "rcr" }; } InputEdit::~InputEdit() {} /** * @brief 当对超过17位的数进行百分号处理时,保留超过精度的部分 * @return precentans * 由于百分号逻辑改变,此函数暂未使用 */ //QString InputEdit::expressionPercent(QString &str) //{ // QString t = str; // bool longnumber = false; // QString ans = DMath::format(m_ans, Quantity::Format::Fixed() + Quantity::Format::Precision(DECPRECISION)); // m_evaluator->setVariable(QLatin1String("precentans"), m_ans, Variable::BuiltIn); //把ans当作precentans保存 // /* // * 判断ans是否是长数字 // */ // if (ans.length() > 17) { // for (int i = 17; i < ans.length(); i++) { // if (ans.at(i) != "0") { // longnumber = true; // break; // } // } // } // /* // * 是长数字时返回ans // */ // if (longnumber && m_lastPos == m_ansStartPos + m_ansLength + 1) { // t = QLatin1String("precentans") + str.back(); // m_ispercentanswer = true; // } // // if (m_ansVaild) { // // QString ans = DMath::format(m_ans, Quantity::Format::Precision(DECPRECISION)); // // t.remove(m_ansStartPos, m_ansLength); // // t.insert(m_ansStartPos, ans); // // } // return t; //} /** * @brief 在点击等于号时使用此函数判断输入框中是否存在上一次结果的长数字 * return 将有上次结果长数字的部分替换为lastans返回 */ QString InputEdit::expressionText() { QString t = text(); // t.remove(","); //edit for bug-19653 20200416 当数字长度超过精度范围时,保留小数点最后的数。 bool longnumber = false; QString ans = DMath::format(m_ans, Quantity::Format::Fixed() + Quantity::Format::Precision(DECPRECISION)); m_evaluator->setVariable(QLatin1String("lastans"), m_ans, Variable::BuiltIn); /* * 判断ans是否是长数字 */ if (ans.length() > 17) { for (int i = 17; i < ans.length(); i++) { if (ans.at(i) != "0") { longnumber = true; break; } } } /* * 是长数字并且输入框中包含ans时输入框中的可见ans替换为lastans按长数字计算 */ //20200619输入框是否包含ans,长数字等于后撤销退格一位按等于计算错误;不撤销退格一位按等于号计算错误 if (m_ansVaild && longnumber && text().contains(m_strans)) { t.remove(m_ansStartPos, m_ansLength); if (m_ansLength != 0) { t.insert(m_ansStartPos, QLatin1String("lastans")); } } // if (m_ansVaild) { // QString ans = DMath::format(m_ans, Quantity::Format::Precision(DECPRECISION)); // t.remove(m_ansStartPos, m_ansLength); // t.insert(m_ansStartPos, ans); // } // qDebug() << t; return t; } /** * @brief 点击等于号可以出正确结果时settext,且更新私有参数有关ans的值 */ void InputEdit::setAnswer(const QString &str, const Quantity &ans) { m_ans = ans; m_ansStartPos = 0; m_ansLength = str.length(); m_oldText = ""; setText(str); m_strans = str; m_strans = m_strans.replace('+', QString::fromUtf8("+")) .replace('-', QString::fromUtf8("-")) .replace('*', QString::fromUtf8("×")) .replace(QString::fromUtf8("("), "(") .replace(QString::fromUtf8(")"), ")"); } /** * @brief InputEdit::setPercentAnswer * @param str1-完整表达式 * @param str2-百分比计算结果 * @param ans-百分比计算结果 * @param Pos-光标位置 * (由于百分号逻辑改变,暂未使用) */ //void InputEdit::setPercentAnswer(const QString &str1, const QString &str2, const Quantity &ans, // const int &Pos) //{ // if (m_ispercentanswer) { // m_ans = ans; // m_ansStartPos = Pos + ((Pos == 0) ? 0 : 1); //edit 20200416 // m_ansLength = str2.length(); // m_oldText = ""; // setText(str1); // int ansEnd = m_ansStartPos + m_ansLength; // while (ansEnd > str1.length()) { // --ansEnd; // } // m_ansVaild = /*m_ansLength > 10 &&*/ m_ansLength > 0 && (m_ansStartPos == 0 || !str1[m_ansStartPos - 1].isDigit()) && // (ansEnd == str1.length() || !str1[ansEnd].isDigit()); // } // m_ispercentanswer = false; //} /** * @brief 清空输入框且更新ans参数 */ void InputEdit::clear() { m_ansLength = 0; setText(""); } /** * @brief 由undo列表设置右键菜单中撤销状态 */ void InputEdit::setUndoAction(bool state) { m_undo->setEnabled(state); } /** * @brief 由redo列表设置右键菜单中撤销状态 */ void InputEdit::setRedoAction(bool state) { m_redo->setEnabled(state); } /** * @brief 跳过QLineEdit的物理键盘事件,由modul中handleEditKeyPress触发 */ void InputEdit::keyPressEvent(QKeyEvent *e) { if (hasFocus() && e->modifiers() == Qt::AltModifier && e->key() == Qt::Key_M) { showTextEditMenuByAltM(); } else Q_EMIT keyPress(e); return; } /** * @brief 鼠标双击事件 */ void InputEdit::mouseDoubleClickEvent(QMouseEvent *e) { //fix bug-47162保持触摸屏双击输入框与其他应用一致 QLineEdit::mouseDoubleClickEvent(e); selectAll(); m_selected.selected = text(); /*if (e->button() == Qt::LeftButton) { int position = this->cursorPositionAt(e->pos()); int posBegin = findWordBeginPosition(position); int posEnd = findWordEndPosition(position); this->setSelection(posBegin, posEnd - posBegin + 1); }*/ } void InputEdit::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { setFocus(); emit setResult(); //expression中m_isResult置为false // qDebug() << m_selected.selected; } QLineEdit::mousePressEvent(e); } void InputEdit::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::MiddleButton) { emit paste(); return; } QLineEdit::mouseReleaseEvent(event); } /** * @brief 右键菜单action初始化 */ void InputEdit::initAction() { //fix bug-47321 m_undo = new QAction(tr("Undo"), this); m_redo = new QAction(tr("Redo"), this); m_cut = new QAction(tr("Cut"), this); m_copy = new QAction(tr("Copy"), this); m_paste = new QAction(tr("Paste"), this); m_delete = new QAction(tr("Delete"), this); m_select = new QAction(tr("Select All"), this); m_threeSeparate = new QAction(tr("Use thousands separator"), this); m_fourSeparate = new QAction(tr("Use ten-thousands separator"), this); connect(m_undo, &QAction::triggered, this, &InputEdit::undo); connect(m_redo, &QAction::triggered, this, &InputEdit::redo); connect(m_cut, &QAction::triggered, this, &InputEdit::cut); connect(m_copy, &QAction::triggered, this, &InputEdit::copy); connect(m_paste, &QAction::triggered, this, &InputEdit::paste); connect(m_delete, &QAction::triggered, this, &InputEdit::deleteText); connect(m_select, &QAction::triggered, this, &InputEdit::selectAllText); connect(m_threeSeparate, &QAction::triggered, this, &InputEdit::swietThreeSeparate); connect(m_fourSeparate, &QAction::triggered, this, &InputEdit::swietFourSeparate); m_undo->setEnabled(false); m_redo->setEnabled(false); m_cut->setEnabled(false); m_copy->setEnabled(false); m_delete->setEnabled(false); m_select->setEnabled(false); } /** * 暂未使用 */ //bool InputEdit::isSymbolCategoryChanged(int pos1, int pos2) //{ // QString str = text(); // QChar::Category category1 = str.at(pos1).category(); // QChar::Category category2 = str.at(pos2).category(); // if (category1 == QChar::Number_DecimalDigit || category1 == QChar::Punctuation_Other) { // if (category2 == QChar::Number_DecimalDigit || category2 == QChar::Punctuation_Other) { // return false; // } // } // return true; //} /** * 暂未使用 */ //int InputEdit::findWordBeginPosition(int pos) //{ // QString str = text(); // if (0 >= pos) { // return 0; // } // while (pos > 0) { // pos--; // if (isSymbolCategoryChanged(pos, pos + 1)) { // return pos + 1; // } // } // return 0; //} /** * 暂未使用 */ //int InputEdit::findWordEndPosition(int pos) //{ // QString str = text(); // if (pos >= str.length()) { // return str.length() - 1; // } // while (pos < str.length() - 1) { // pos++; // if (isSymbolCategoryChanged(pos, pos - 1)) { // return pos - 1; // } // } // return str.length() - 1; //} /** * @brief InputEdit::输入框字号变化 */ void InputEdit::autoZoomFontSize() { QFont font; // the maximum font is 30, minimum font is 15. for (int i = 30; i > 16; --i) { font.setPixelSize(i); QFontMetrics fm(font); int fontWidth = fm.width(text()); int editWidth = width() - 45; if (fontWidth < editWidth) break; } setFont(font); } void InputEdit::themetypechanged(int type) { DPalette pl = this->palette(); //itemwidget字体颜色设置 if (type == 1) { pl.setColor(DPalette::Text, QColor("#303030")); } else { pl.setColor(DPalette::Text, QColor("#B4B4B4")); } pl.setColor(DPalette::Button, Qt::transparent); //inputedit背景色 pl.setColor(DPalette::Highlight, Qt::transparent); //边框高亮色 pl.setColor(DPalette::HighlightedText, Qt::blue); //全选字体高亮色 this->setPalette(pl); } /** * @brief InputEdit::valueChangeFromProSyskeypad * @param num:二进制数字 * 点击位键盘时,对应修改光标位置的数字 */ void InputEdit::valueChangeFromProSyskeypad(const QString num) { // qDebug() << "change"; QString text = this->text(); int pos = this->cursorPosition(); int numstart = pos, numend = pos; QString number = formatBinaryNumber(num); // qDebug() << "changenumber:" << number; if (text == QString()) { text = number; } else { while (numstart != 0 && (isNumber(text.at(numstart - 1)) || (text.length() > 1 && numstart == 1 && isNumber(text.at(1)) && text.at(0) == QString::fromUtf8("-")))) { numstart--; } while (numend < text.length() && isNumber(text.at(numend))) { numend++; } if (numstart > 0 && !isNumber(text.at(numstart - 1)) && number.at(0) == "-") { text.remove(numstart, numend - numstart).insert(numstart, "(" + number); numstart += 2; } else text.remove(numstart, numend - numstart).insert(numstart, number); } this->setText(text); //重新找到numend numend = numstart < 0 ? 0 : numstart; while (numend < this->text().length() && (isNumber(this->text().at(numend)) || ((numend == 0) && isNumber(text.at(1)) && text.at(0) == "-"))) { numend++; } this->setCursorPosition(numend); } /** * @brief 输入框textchange时触发 */ void InputEdit::handleTextChanged(const QString &text) { if (m_currentInAns) { m_ansLength = 0; //光标在ans中间且text改变,清空ans } else if (m_currentOnAnsLeft && m_oldText.length() != 0) { int textLength = text.length(); int oldTextLength = m_oldText.length(); // int minValue = std::min(textLength, oldTextLength); // int i = 1; // for (; i < minValue && text[textLength - i] == m_oldText[oldTextLength - i]; ++i) // ; //i=diff?不知为何又用到下侧int计算 i无用 // int diff = (textLength - i) - (oldTextLength - i); int diff = textLength - oldTextLength; m_ansStartPos += diff; } if (text.indexOf("=") != -1) { QString exp = text; exp.remove(text.indexOf("="), 1); setText(exp); Q_EMIT equal(); //当前外界键盘及计算器键盘中=均不走此;猜测为了复制粘贴等于式;当前粘贴会去除=,也不会走此;暂不删除 return; } int ansEnd = m_ansStartPos + m_ansLength; m_oldText = text; while (ansEnd > text.length()) { --ansEnd; } //ans是否有效;判断条件:ans未被改变,ans左侧右侧均不是小数点 m_ansVaild = /*m_ansLength > 10 &&*/ m_ansLength > 0 && (m_ansStartPos == 0 || !text[m_ansStartPos - 1].isDigit()) && (ansEnd == text.length() || !text[ansEnd].isDigit()); int oldPosition = this->cursorPosition(); QString reformatStr = QString(); if (Settings::instance()->programmerBase == 0) reformatStr = Utils::reformatSeparators(QString(text).remove(',')); else reformatStr = Utils::reformatSeparatorsPro(QString(text).remove(',').remove(" "), Settings::instance()->programmerBase); reformatStr = reformatStr.replace('+', QString::fromUtf8("+")) .replace('-', QString::fromUtf8("-")) .replace("_", QString::fromUtf8("-")) .replace('*', QString::fromUtf8("×")) .replace(QString::fromUtf8("*"), QString::fromUtf8("×")) // .replace('/', QString::fromUtf8("÷")) // .replace('x', QString::fromUtf8("×")) .replace('X', QString::fromUtf8("×")) .replace(QString::fromUtf8("("), "(") .replace(QString::fromUtf8(")"), ")") .replace(QString::fromUtf8("——"), QString::fromUtf8("-")) .replace(QString::fromUtf8("%"), "%"); multipleArithmetic(reformatStr); // reformatStr.remove(QRegExp("[^0-9+-×÷,.%()e]")); // reformatStr = pointFaultTolerance(reformatStr); // reformatStr = symbolFaultTolerance(reformatStr); setText(reformatStr); autoZoomFontSize(); // reformat text. int oldLength = text.length(); int newLength = reformatStr.length(); int pos; if (newLength > oldLength) pos = oldPosition + (newLength - oldLength); else pos = oldPosition; if (pos > newLength) pos = newLength; this->setCursorPosition(pos); m_selected.oldText = this->text(); //选中输入情况下清空被选部分 m_selected.selected = selectedText(); m_selected.curpos = selectionStart() < selectionEnd() ? selectionStart() : selectionEnd(); } /** * @brief InputEdit::radixChanged * 当进制表切换时,输入栏中对应的值需要同步切换 */ void InputEdit::radixChanged(int baseori, int basedest) { this->setText(scanAndExec(baseori, basedest)); } QString InputEdit::scanAndExec(int baseori, int basedest) { m_numvec.clear(); m_opvec.clear(); m_textorder = QString(); QString oldtext = this->text(); oldtext.remove(",").remove(" "); for (int i = 0; i < oldtext.length();) { if (isNumber(oldtext.at(i))) { for (int j = 0; j < oldtext.length() - i; j++) { if (i + j == oldtext.length() - 1) { if (isNumber(oldtext.at(i + j))) { m_numvec.append(oldtext.mid(i, j + 1)); m_textorder += "0"; i += j + 1; } else { m_numvec.append(oldtext.mid(i, j)); m_textorder += "0"; i += j; } break; } if (!isNumber(oldtext.at(i + j))) { m_numvec.append(oldtext.mid(i, j)); m_textorder += "0"; i += j; break; } } } else { if (oldtext.at(i).isLower()) { if (oldtext.at(i) == 'n' && oldtext.at(i + 1) == 'a') { m_opvec.append(oldtext.mid(i, 4)); m_textorder += "1"; i += 4; } else if (oldtext.at(i) == 'o') { m_opvec.append(oldtext.mid(i, 2)); m_textorder += "1"; i += 2; } else { m_opvec.append(oldtext.mid(i, 3)); m_textorder += "1"; i += 3; } } else if ((i == 0 || !isNumber(oldtext.at(i - 1))) && oldtext.at(i) == QString::fromUtf8("-") && oldtext.length() > i + 1 && isNumber(oldtext.at(i + 1))) { i++; for (int j = 0; j < oldtext.length() - i; j++) { if (!isNumber(oldtext.at(i + j))) { m_numvec.append(oldtext.mid(i - 1, j + 1)); m_textorder += "0"; i += j; break; } if (i + j == oldtext.length() - 1) { m_numvec.append(oldtext.mid(i - 1, j + 2)); m_textorder += "0"; i += j + 1; break; } } } else { m_opvec.append(oldtext.at(i)); m_textorder += "1"; i++; } } } for (int i = 0; i < m_numvec.size(); i++) { QString num = formatExpression(baseori, m_numvec.at(i)); Quantity ans(HNumber(num.toLatin1().data())); switch (basedest) { case 16: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); break; case 8: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Octal()).remove("0o"); break; case 2: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); break; default: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); break; } m_numvec.replace(i, num); } QString newtext = QString(); for (int i = 0; i < m_textorder.length(); i++) { if (m_textorder.at(i) == "0") { newtext.append(m_numvec.first()); m_numvec.pop_front(); } else { newtext.append(m_opvec.first()); m_opvec.pop_front(); } } return newtext; } /** * @brief 小数点容错处理,防止多小数点 */ QString InputEdit::pointFaultTolerance(const QString &text) { QString exp = text; QString oldText = text; QStringList list = exp.split(QRegExp("[+-×÷/()]")); for (int i = 0; i < list.size(); ++i) { QString item = list[i]; int firstPoint = item.indexOf("."); if (firstPoint == -1) continue; if (firstPoint == 0) { item.insert(firstPoint, "0"); //小数点在第一位补0操作,此处存在若无多小数点情况不会补零,虚在其余地方进行操作 ++firstPoint; // oldText.replace(list[i], item); } else { if (item.at(firstPoint - 1) == ")" || item.at(firstPoint - 1) == "%") { item.remove(firstPoint, 1); //原定义)及%右侧不能添加.,现在小数点输入事件中进行过补0操作,不会进入此判断 oldText.replace(list[i], item); } } if (item.count(".") > 1) { //多小数点只保留第一位小数点 int cur = cursorPosition(); item.remove("."); item.insert(firstPoint, "."); oldText.replace(list[i], item); setCursorPosition(cur); } } return oldText; } /** * @brief 保证数字中间的符号只有一个 * 防止输入栏中只有符号可输入*+ * e+/e-和数字间不可以插入非数字 * 去除从e到下一个运算符中的小数点 */ QString InputEdit::symbolFaultTolerance(const QString &text) { if (text.isEmpty()) return text; QString exp = text; QString newText; /*if (isSymbol(exp.at(0))) { if (exp.at(0) != QString::fromUtf8("-")) return ""; else { for (int i = 0; i < exp.length(); ++i) {} } }*/ QStringList symbolList; for (int i = 0; i < exp.length(); ++i) { /*if (isSymbol(exp.at(i)) && i < exp.length() - 2) { while (isSymbol(exp.at(i + 1)) && i < exp.length() - 2) { ++i; } newText.append(exp.at(i)); } else { newText.append(exp.at(i)); }*/ if (!isSymbol(exp.at(i))) { if (!symbolList.isEmpty()) { if (!newText.isEmpty()) newText.append(symbolList.last()); //保证数字中间的符号只有一个,去除多余符号 if (newText.isEmpty() && symbolList.last() == "-") newText.append(symbolList.last()); //保存负数的-号 } newText.append(exp.at(i)); symbolList.clear(); } else { symbolList.append(exp.at(i)); continue; } } // qDebug() << symbolList << " a " << newText; if (!symbolList.isEmpty() /*&& !newText.isEmpty()*/) { //防止输入栏中只有符号可输入*/+;暂未屏蔽% if ((newText.isEmpty() && symbolList.contains("-"))) { newText.append("-"); } else if (!newText.isEmpty()) { newText.append(symbolList.last()); } } //edit 20200526 for bug-28491 int expPos = newText.indexOf("E"); if (expPos > 0) { //e后非+/- if (newText.length() > expPos + 1 && newText.at(expPos + 1) != QString::fromUtf8("-") && newText.at(expPos + 1) != QString::fromUtf8("+") && newText.at(expPos + 1) != "-" && newText.at(expPos + 1) != "+") { while (newText.length() > expPos + 1 && (newText.at(expPos + 1) == "(" || newText.at(expPos + 1) == ")")) { newText.remove(expPos + 1, 1); //避免e后可输入()情况 } return newText; } //e+/e-后有数字 if (newText.length() > expPos + 2) { while (newText.length() > expPos + 2 && newText.at(expPos + 2).isNumber() == false) { newText.remove(expPos + 2, 1); //e+/e-和数字间不可以插入非数字 } int nextsymbolpos = newText.indexOf(QRegExp("[+-×÷/()]"), expPos + 2); //e+/e-右侧第一个符号 for (int i = expPos; i < (nextsymbolpos == -1 ? newText.length() : nextsymbolpos); i++) { if (newText.at(i) == "." || newText.at(i) == QString::fromUtf8("。")) newText.remove(i, 1); //去除从e到下一个运算符中的小数点 } } } return newText; } /** * @brief 判断是否是加减乘除 */ bool InputEdit::isSymbol(const QString &text) { if (text == QString::fromUtf8("+")) return true; else if (text == QString::fromUtf8("-")) return true; else if (text == QString::fromUtf8("×")) return true; else if (text == QString::fromUtf8("÷")) return true; else return false; } /** * @brief 判断光标在ans哪里 */ void InputEdit::handleCursorPositionChanged(int oldPos, int newPos) { Q_UNUSED(oldPos); int ansEnd = m_ansStartPos + m_ansLength; int selectStart = m_selected.curpos; //选中输入后选中部分被清空 不可用selectStart() int selectEnd = selectStart + m_selected.selected.length(); if (newPos > m_ansStartPos && newPos < ansEnd) { m_currentInAns = true; //当前光标在ans开始后结束前 } else if ((selectStart >= m_ansStartPos && selectStart < ansEnd && m_selected.selected.length() > 0) || (selectEnd > m_ansStartPos && selectEnd <= ansEnd) || (selectStart < m_ansStartPos && selectEnd > ansEnd)) { //选中->输入->selection为空->cursprchanged导致此处不会进入;删除hasSelectedText(); m_currentInAns = true; //选中区与ans有交集 } else if (newPos <= m_ansStartPos) { m_currentInAns = false; m_currentOnAnsLeft = true; //光标在ans左侧,保存以去计算ans开始位置 } else { m_currentInAns = false; m_currentOnAnsLeft = false; } m_lastPos = newPos; getCurrentCursorPositionNumber(newPos); } /** * @brief 括号补全,暂未使用 */ void InputEdit::BracketCompletion(QKeyEvent *e) { Q_UNUSED(e); QString oldText = text(); int curs = this->cursorPosition(); int right = oldText.length() - curs; int leftLeftParen = oldText.left(curs).count("("); int leftRightParen = oldText.left(curs).count(")"); int rightLeftParen = oldText.right(right).count("("); int rightrightParen = oldText.right(right).count(")"); //左右括号总数是否相等 if (oldText.count("(") != oldText.count(")")) { //光标左侧左括号大于右括号 if (leftLeftParen > leftRightParen) { if (leftLeftParen - leftRightParen + (rightLeftParen - rightrightParen) > 0) { oldText.insert(curs, ")"); } else if (leftLeftParen - leftRightParen + (rightLeftParen - rightrightParen) < 0) { oldText.insert(curs, "("); } else { oldText.insert(curs, "()"); } //如果左侧左括号小于等于左侧右括号 } else { //如果右侧左括号小于右括号 if (rightLeftParen < rightrightParen) { oldText.insert(curs, "("); } else { oldText.insert(curs, "()"); } } //相等则输入一对括号 } else { oldText.insert(curs, "()"); } this->setCursorPosition(curs); setText(oldText); } /** * @brief 猜测防止异常情况\n出现在)及%后补*,当前text中不会出现\n,故此函数无效 */ void InputEdit::multipleArithmetic(QString &text) { int index = text.indexOf("\n"); if (index != -1) { int count = text.count("\n"); for (int i = 0; i < count; ++i) { index = text.indexOf("\n", i); if (index == 0) continue; if (text.at(index - 1) == ")" || text.at(index - 1) == "%") text.replace(index, 1, "×"); } } } /** * @brief 在鼠标处显示菜单 */ void InputEdit::showTextEditMenu() { DMenu *menu = new DMenu(this); menu->addAction(m_undo); menu->addAction(m_redo); menu->addAction(m_cut); menu->addAction(m_copy); menu->addAction(m_paste); menu->addAction(m_delete); menu->addSeparator(); int separate = 3; switch (DSettingsAlt::instance()->getOption("mode").toInt()) { case 0: separate = DSettingsAlt::instance()->getStandardSeparate(); break; case 1: separate = DSettingsAlt::instance()->getScientificSeparate(); break; case 2: if (Settings::instance()->programmerBase == 10) { separate = DSettingsAlt::instance()->getProgrammerSeparate(); } else { separate = -1; } break; } if (separate == 3) { menu->addAction(m_fourSeparate); } else if (separate == 4) { menu->addAction(m_threeSeparate); } menu->addAction(m_select); if (QApplication::clipboard()->text().isEmpty()) m_paste->setEnabled(false); else m_paste->setEnabled(true); if (this->selectedText().isEmpty()) { m_cut->setEnabled(false); m_copy->setEnabled(false); m_delete->setEnabled(false); } else { m_cut->setEnabled(true); m_copy->setEnabled(true); m_delete->setEnabled(true); } //全选需要有内容 if (this->text() != QString()) { m_select->setEnabled(true); } else { m_select->setEnabled(false); } menu->move(cursor().pos()); menu->exec(); menu->deleteLater(); } /** * @brief 在光标处显示菜单 */ void InputEdit::showTextEditMenuByAltM() { DMenu *menu = new DMenu(this); menu->addAction(m_undo); menu->addAction(m_redo); menu->addAction(m_cut); menu->addAction(m_copy); menu->addAction(m_paste); menu->addAction(m_delete); menu->addSeparator(); int separate = 3; switch (DSettingsAlt::instance()->getOption("mode").toInt()) { case 0: separate = DSettingsAlt::instance()->getStandardSeparate(); break; case 1: separate = DSettingsAlt::instance()->getScientificSeparate(); break; case 2: if (Settings::instance()->programmerBase == 10) { separate = DSettingsAlt::instance()->getProgrammerSeparate(); } else { separate = -1; } break; } if (separate == 3) { menu->addAction(m_fourSeparate); } else if (separate == 4) { menu->addAction(m_threeSeparate); } menu->addAction(m_select); if (QApplication::clipboard()->text().isEmpty()) m_paste->setEnabled(false); else m_paste->setEnabled(true); if (this->selectedText().isEmpty()) { m_cut->setEnabled(false); m_copy->setEnabled(false); m_delete->setEnabled(false); } else { m_cut->setEnabled(true); m_copy->setEnabled(true); m_delete->setEnabled(true); } //全选需要有内容 if (this->text() != QString()) { m_select->setEnabled(true); } else { m_select->setEnabled(false); } menu->move(mapToGlobal(cursorRect().bottomRight())); menu->exec(); menu->deleteLater(); } /** * @brief InputEdit::formatAns * 按进制返回计算结果 */ QString InputEdit::formatAns(const QString &text) { QString num = formatExpression(2, text); Quantity ans(HNumber(num.toLatin1().data())); switch (Settings::instance()->programmerBase) { case 16: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); break; case 8: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); break; case 2: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); break; default: num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); break; } return num; } /** * @brief InputEdit::getCurrentAns * 输入时获取当前输入栏中的结果 */ QPair InputEdit::getCurrentAns() { QPair pair; QString expression; if (Settings::instance()->programmerBase == 8 || Settings::instance()->programmerBase == 16) { expression = InputEdit::formatExpression(2, scanAndExec(Settings::instance()->programmerBase, 2)); } else { expression = InputEdit::formatExpression(Settings::instance()->programmerBase, text()); } QString exp1 = symbolComplement(expression); m_evaluator->setExpression(exp1); Quantity ans = m_evaluator->evalUpdateAns(); if (m_evaluator->error().isEmpty()) { if (ans.isNan() && !m_evaluator->isUserFunctionAssign()) { pair.first = false; pair.second = Quantity(0); } else { pair.first = true; pair.second = ans; } } else { pair.first = false; pair.second = Quantity(0); } emit prolistAns(pair); return pair; } /** * @brief 选中改变的槽 */ void InputEdit::selectionChangedSlot() { if (!hasFocus()) return; //只有选中被改变情况下给m_selected赋值,选中输入不会改变;选中输入后优先级高于cursorchanged,去掉return无意义 m_selected.oldText = text(); m_selected.selected = selectedText(); m_selected.curpos = selectionStart() < selectionEnd() ? selectionStart() : selectionEnd(); } /** * @brief InputEdit::getMemoryAnswer * 点击m+,m-,ms时进行获取的计算结果 * @return pair.first-是否可计算 pair.second-计算结果 */ QPair InputEdit::getMemoryAnswer() { QPair pair; QString expression; expression = symbolComplement(expressionText()).replace(QString::fromUtf8("+"), "+") .replace(QString::fromUtf8("-"), "-") .replace(QString::fromUtf8("×"), "*") .replace(QString::fromUtf8("÷"), "/") .replace(QString::fromUtf8(","), ""); m_evaluator->setExpression(expression); m_memoryans = m_evaluator->evalUpdateAns(); if (m_evaluator->error().isEmpty()) { if (m_memoryans.isNan() && !m_evaluator->isUserFunctionAssign()) { pair.first = false; pair.second = Quantity(0); return pair; } pair.first = true; pair.second = m_memoryans; return pair; } else { pair.first = false; pair.second = Quantity(0); return pair; } } /** * @brief 输入栏是否为空,方便判断m-,m+,ms是否可用 */ void InputEdit::isExpressionEmpty() { if (text().isEmpty()) emit emptyExpression(true); else emit emptyExpression(false); } /** * @brief 当前输入框为历史记录点击时,清空ans */ void InputEdit::hisexpression() { m_ansLength = 0; } /** * @brief ExpressionBar::symbolComplement * 当计算((()))这种超过3个括号嵌套的表达式时有问题,手动补乘号进行规避 * @param exp * @return */ QString InputEdit::symbolComplement(const QString exp) { QString text = exp; int index = text.indexOf("(", 0); while (index != -1) { if (index >= 1 && text.at(index - 1).isNumber()) { text.insert(index, "×"); ++index; } ++index; index = text.indexOf("(", index); } index = text.indexOf(")", 0); while (index != -1) { if (index < text.length() - 1 && text.at(index + 1).isNumber()) { text.insert(index + 1, "×"); ++index; } ++index; index = text.indexOf(")", index); } return text; } /** * @brief InputEdit::CurrentCursorPositionNumber * 用于修改位键盘 */ QString InputEdit::CurrentCursorPositionNumber(const int pos, const int base) { QString text = this->text(); if (text.isEmpty()) { return ""; } QString currentnum = QString(); int numstart = pos, numend = pos; while (numstart != 0 && (isNumber(text.at(numstart - 1)) || (text.length() > 1 && numstart == 1 && isNumber(text.at(1)) && text.at(0) == QString::fromUtf8("-")))) { numstart--; } while (numend < text.length() && isNumber(text.at(numend))) { numend++; } currentnum = text.mid(numstart, numend - numstart); currentnum = formatExpression(Settings::instance()->programmerBase, currentnum); Quantity ans(HNumber(currentnum.toLatin1().data())); if (ans.isNan()) return ""; switch (base) { case 16: currentnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); break; case 8: currentnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); break; case 2: currentnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); break; default: currentnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); break; } return currentnum; } /** * @brief InputEdit::CurrentCursorPositionNumber * 获取当前光标前后的整个数字,光标前是符号则返回后面的数字 */ QString InputEdit::CurrentCursorPositionNumber(const int pos) { QString text = this->text(); if (text.isEmpty()) { return ""; } QString currentnum = QString(); int numstart = pos - 1, numend = pos - 1; if (numstart >= 0 && isNumber(text.at(numstart))) { while (numstart > 0 && (isNumber(text.at(numstart - 1)) || ((numstart == 1) && isNumber(text.at(1)) && text.at(0) == QString::fromUtf8("-")))) { numstart--; } while (numend < text.length() && isNumber(text.at(numend))) { numend++; } currentnum = text.mid(numstart, numend - numstart); } currentnum = formatExpression(Settings::instance()->programmerBase, currentnum); Quantity ans(HNumber(currentnum.toLatin1().data())); if (ans.isNan()) return ""; switch (Settings::instance()->programmerBase) { case 16: currentnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); break; case 8: currentnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); break; case 2: currentnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); break; default: currentnum = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); break; } return currentnum; } /** * @brief InputEdit::getCurrentCursorPositionNumber * @param pos:当前光标位置 * 获取当前光标所在位置对应的数字,用于修改位键盘 */ void InputEdit::getCurrentCursorPositionNumber(const int pos) { QString currentnum = CurrentCursorPositionNumber(pos, 2); if (currentnum == "") { emit cursorPositionNumberChanged("0"); } else { emit cursorPositionNumberChanged(currentnum); } // qDebug() << "currentnum" << currentnum; } bool InputEdit::isNumber(QChar a) { if (a.isDigit() || a == " " || a == "," || AtoF.contains(a)) return true; else return false; } QString InputEdit::formatBinaryNumber(const QString num) { QString str; for (int i = 0; i < num.length(); i++) { if (num.at(i) == '1') { str = num.right(num.length() - i); str = formatAns(str); return str; } if (i == num.length() - 1 && num.at(num.length() - 1) != '1') { str = "0"; return str; } } return "0"; } /** * @brief InputEdit::formatExpression * @param text:格式化前的内容 * @return 格式化后的text * 用于进制转换时和计算时插入进制标志 */ QString InputEdit::formatExpression(const int &probase, const QString &text) { QString formattext = text; formattext.replace(QString::fromUtf8("+"), "+") .replace(QString::fromUtf8("-"), "-") .replace(QString::fromUtf8("×"), "*") .replace(QString::fromUtf8("÷"), "/") .replace(QString::fromUtf8(","), "") .replace(QString::fromUtf8(" "), "") .replace("%", "mod"); QString base = QString(); switch (probase) { case 16: base = "0x"; break; case 8: base = "0o"; break; case 2: base = "0b"; break; default: break; } if (base != QString()) { for (int i = 0; i < formattext.length();) { if ((i == 0) && isNumber(formattext.at(i))) { formattext.insert(i, base); i += 3; continue; } else if ((i < formattext.length() - 1) && !isNumber(formattext.at(i)) && isNumber(formattext.at(i + 1))) { formattext.insert(i + 1, base); i += 3; continue; } i++; } } return formattext; } void InputEdit::focusInEvent(QFocusEvent *event) { int curtemp = cursorPosition(); QLineEdit::focusInEvent(event); if (event->reason() == Qt::TabFocusReason) { setCursorPosition(curtemp); } } /** * @brief onSwietThreeSeparateClicked * 切换为千分位菜单点击事件 */ void InputEdit::onSwietThreeSeparateClicked() { DSettingsAlt::instance()->setSeparate(3); handleTextChanged(m_oldText); //更新input中的算式 emit separateChange(); //发送更新信号 } /** * @brief onswietFourSeparateClicked * 切换为万分位菜单点击事件 */ void InputEdit::onswietFourSeparateClicked() { DSettingsAlt::instance()->setSeparate(4); handleTextChanged(m_oldText); //更新input中的算式 emit separateChange(); //发送更新信号 } deepin-calculator-5.7.21/src/widgets/inputedit.h000066400000000000000000000121151423020056600216120ustar00rootroot00000000000000/* * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. * * Author: rekols * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef INPUTEDIT_H #define INPUTEDIT_H #include "../../3rdparty/math/quantity.h" #include "../../3rdparty/core/evaluator.h" #include #include DGUI_USE_NAMESPACE DWIDGET_USE_NAMESPACE struct SSelection { QString oldText; //选中时的当前text QString selected; //被选中部分 QString clearText; bool isChanged; int curpos = 0; // fix for bug-14249选中的左侧光标所在位置 SSelection() { isChanged = false; } }; class InputEdit : public QLineEdit { Q_OBJECT public: explicit InputEdit(QWidget *parent = nullptr); ~InputEdit(); QString expressionText(); void setAnswer(const QString &str, const Quantity &ans); void clear(); SSelection getSelection() { return m_selected; } void setSelection(SSelection select) { m_selected = select; } QPair getMemoryAnswer(); //edit 20200507,获取上一次计算的全精度结果,用于数字内存。 QString symbolComplement(const QString exp); void getCurrentCursorPositionNumber(const int pos);//获取当前光标所在位置对应的数字并设置位键盘 QString CurrentCursorPositionNumber(const int pos, const int base); //获取当前光标所在位置对应的数字 QString CurrentCursorPositionNumber(const int pos); static bool isNumber(QChar a);//判断是否为数字(分隔符) QString formatBinaryNumber(const QString num);//清除二进制前多余的0 static QString formatExpression(const int &probase, const QString &text); QPair getCurrentAns(); void focusInEvent(QFocusEvent *event); public slots: void setUndoAction(bool state); void setRedoAction(bool state); QString symbolFaultTolerance(const QString &text); void isExpressionEmpty(); //edit 20200511,判断表达式是否有解,错误表达式无法存入内存 20200519 判断表达式是否为空 void hisexpression(); //点击简易历史记录及科学左侧历史记录后清空ans void autoZoomFontSize(); //输入框字号变化 void themetypechanged(int type); void valueChangeFromProSyskeypad(const QString num); void handleTextChanged(const QString &text); void radixChanged(int baseori, int basedest); QString scanAndExec(int baseori, int basedest); void onSwietThreeSeparateClicked(); void onswietFourSeparateClicked(); Q_SIGNALS: void keyPress(QKeyEvent *); void equal(); void undo(); void redo(); void paste(); void copy(); void cut(); void selectAllText(); void deleteText(); void setResult(); void emptyExpression(bool b); void cursorPositionNumberChanged(QString num); void prolistAns(QPair pair); void swietThreeSeparate(); //切换为千分位 void swietFourSeparate(); //切换为万分位 void separateChange(); protected: void keyPressEvent(QKeyEvent *); void mouseDoubleClickEvent(QMouseEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *event); private slots: void initAction(); void handleCursorPositionChanged(int oldPos, int newPos); void BracketCompletion(QKeyEvent *e); QString pointFaultTolerance(const QString &text); bool isSymbol(const QString &text); void multipleArithmetic(QString &text); void showTextEditMenu(); void selectionChangedSlot(); void showTextEditMenuByAltM(); QString formatAns(const QString &text); private: Quantity m_ans; int m_ansStartPos; int m_ansLength; bool m_ansVaild; bool m_currentInAns; //光标在ans中间 bool m_currentOnAnsLeft; //光标在ans左侧(包括左侧) QString m_oldText; SSelection m_selected; int m_lastPos; //最后进入计算时的光标位置 QAction *m_undo; QAction *m_redo; QAction *m_cut; QAction *m_copy; QAction *m_paste; QAction *m_delete; QAction *m_select; QAction *m_threeSeparate; //以三位分开 QAction *m_fourSeparate; //以四位分开 Quantity m_memoryans; //用于内存的结果 Evaluator *m_evaluator; bool m_ispercentanswer = false; //百分号结果是否需要转换为quantity //支持的功能列表 QList m_funclist; //科学模式下函数名列表 QString m_strans; //进制切换时用于替换所有数字 QVector m_numvec; QVector m_opvec; QString m_textorder; }; #endif deepin-calculator-5.7.21/src/widgets/memhiswidget.cpp000066400000000000000000000340631423020056600226340ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "memhiswidget.h" #include "dthememanager.h" #include "../utils.h" #include "../../3rdparty/math/quantity.h" #include #include MemHisWidget::MemHisWidget(QWidget *parent) : DWidget(parent) , m_stackWidget(new QStackedWidget) , m_listView(new SimpleListView(1)) , m_listDelegate(new SimpleListDelegate(1, this)) , m_listModel(new SimpleListModel(1, this)) , m_buttonBox(new DButtonBox(this)) , m_memoryBtn(new DButtonBoxButton(QIcon(), {}, this)) , m_historyBtn(new DButtonBoxButton(QIcon(), {}, this)) , m_clearButton(new IconButton(this, 1)) { m_memoryPublic = MemoryPublic::instance(); m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::scientificright); m_memoryWidget->setFocusPolicy(Qt::TabFocus); m_stackWidget->addWidget(m_memoryWidget); m_listView->setModel(m_listModel); m_listView->setItemDelegate(m_listDelegate); m_stackWidget->addWidget(m_listView); m_stackWidget->setCurrentWidget(m_memoryWidget); m_stackWidget->setFixedSize(451, 302); m_buttonBox->setFixedSize(60, 26); m_buttonBox->setFocusPolicy(Qt::NoFocus); m_memoryBtn->setObjectName("mButtonBoxButton"); m_memoryBtn->setFixedSize(31, 27); m_memoryBtn->setIconSize(QSize(30, 26)); m_historyBtn->setFixedSize(28, 26); m_historyBtn->setIconSize(QSize(32, 26)); m_memoryBtn->setFocusPolicy(Qt::TabFocus); QList listBtnBox; listBtnBox << m_memoryBtn << m_historyBtn; m_buttonBox->setButtonList(listBtnBox, true); m_buttonBox->setId(m_memoryBtn, 0); m_buttonBox->setId(m_historyBtn, 1); m_buttonBox->button(0)->setChecked(true); iconChanged(m_themeType, 0); QVBoxLayout *m_Vlayout = new QVBoxLayout(this); QWidget *hwidget = new QWidget(this); QHBoxLayout *m_Hlayout = new QHBoxLayout(); m_Hlayout->addSpacing(12); m_Hlayout->addWidget(m_buttonBox); m_Hlayout->addSpacing(333); QWidget *clearwidget = new QWidget(this); clearwidget->setFixedSize(36, 36); m_clearButton->setParent(clearwidget); m_clearButton->setObjectName("clearbtn"); m_clearButton->showtooltip(true); //设置内存垃圾桶tooltip if (m_memoryPublic->isEmpty()) //防止在其他模式下初始化有内存切换至科学模式清除按钮隐藏 m_clearButton->setHidden(true); else m_isshowM = true; m_Hlayout->addWidget(clearwidget); m_Hlayout->addSpacing(10); m_Hlayout->setMargin(0); hwidget->setLayout(m_Hlayout); hwidget->setFixedHeight(48); m_Vlayout->addWidget(m_stackWidget); m_Vlayout->addWidget(hwidget); m_Vlayout->setSpacing(0); m_Vlayout->setMargin(0); m_Vlayout->setContentsMargins(0, 0, 0, 0); this->setLayout(m_Vlayout); this->setContentsMargins(0, 0, 0, 0); m_historyBtn->installEventFilter(this); m_memoryBtn->installEventFilter(this); m_memoryWidget->findChild()->installEventFilter(this); m_listView->installEventFilter(this); m_clearButton->installEventFilter(this); m_stackWidget->installEventFilter(this); this->installEventFilter(this); setTabOrder(m_stackWidget, m_memoryBtn); setTabOrder(m_memoryBtn, m_clearButton); //信号槽 connect(m_buttonBox->button(0), &QAbstractButton::clicked, this, [ = ]() { if (!m_buttonBox->button(0)->hasFocus() && QApplication::focusWidget() != nullptr) this->setFocus(); m_clearButton->showtooltip(true); //设置历史垃圾桶tooltip m_stackWidget->setCurrentWidget(m_memoryWidget); m_clearButton->setHidden(!m_isshowM); iconChanged(m_themeType, 0); }); connect(m_buttonBox->button(1), &QAbstractButton::clicked, this, [ = ]() { if (!m_buttonBox->button(1)->hasFocus() && QApplication::focusWidget() != nullptr) this->setFocus(); m_clearButton->showtooltip(false); //设置内存垃圾桶tooltip m_listModel->updataOfSeparate(); m_stackWidget->setCurrentWidget(m_listView); m_clearButton->setHidden(!m_isshowH); iconChanged(m_themeType, 1); }); connect(m_clearButton, &IconButton::clicked, this, [ = ]() { this->setFocus(); //让下次焦点在m_memoryBtn if (m_stackWidget->currentWidget() != m_memoryWidget) { m_listModel->clearItems(); emit hisIsFilled(false); m_listView->listItemFill(false); m_isshowH = false; m_listView->setFocusPolicy(Qt::NoFocus); } else { m_memoryPublic->memoryclean(); m_isshowM = false; m_memoryWidget->setFocusPolicy(Qt::NoFocus); } m_clearButton->setHidden(true); }); connect(m_clearButton, &TextButton::space, this, [ = ]() { //清除焦点空格事件 this->setFocus(); //让下次焦点在m_memoryBtn if (m_stackWidget->currentWidget() != m_memoryWidget) { m_listModel->clearItems(); emit hisIsFilled(false); m_listView->listItemFill(false); m_isshowH = false; m_listView->setFocusPolicy(Qt::NoFocus); } else { m_memoryPublic->memoryclean(); m_isshowM = false; m_memoryWidget->setFocusPolicy(Qt::NoFocus); } m_clearButton->setHidden(true); }); //focus下空格按下 connect(m_listModel, &SimpleListModel::hisbtnhidden, this, [ = ]() { m_listModel->clearItems(); //历史记录无数据信号接收 m_listView->setFocusPolicy(Qt::NoFocus); m_listView->listItemFill(false); m_isshowH = false; emit hisIsFilled(false); if (m_stackWidget->currentWidget() != m_memoryWidget) m_clearButton->setHidden(true); }); connect(m_memoryPublic, &MemoryPublic::generateDataSig, this, [ = ]() { m_isshowM = true; //公共内存中有数据信号接收 m_memoryWidget->setFocusPolicy(Qt::TabFocus); if (m_stackWidget->currentWidget() == m_memoryWidget) m_clearButton->setHidden(false); }); connect(m_memoryPublic, &MemoryPublic::memorycleanSig, this, [ = ]() { m_isshowM = false; //公共内存中无数据信号接收 m_memoryWidget->setFocusPolicy(Qt::NoFocus); if (m_stackWidget->currentWidget() == m_memoryWidget) m_clearButton->setHidden(true); }); } MemHisWidget::~MemHisWidget() { } /** * @brief 现实历史记录侧时调用,设置buttonbox状态 */ void MemHisWidget::focusOnButtonbox(Qt::FocusReason Reason) { if (m_stackWidget->currentWidget() == m_memoryWidget) { m_buttonBox->button(0)->setChecked(true); } else { m_buttonBox->button(1)->setChecked(true); } this->setFocus(Reason); } /** * @brief 对公共内存进行操作 */ void MemHisWidget::memoryFunctions(MemHisWidget::memOperate operate, Quantity answer, int row) { switch (operate) { case memoryplus: m_memoryPublic->memoryplus(answer); break; case memoryminus: m_memoryPublic->memoryminus(answer); break; case memoryclean: m_memoryPublic->memoryclean(); break; case widgetplus: m_memoryPublic->widgetplus(row, answer); break; case widgetminus: m_memoryPublic->widgetminus(row, answer); break; default: m_memoryPublic->generateData(answer); break; } } void MemHisWidget::resetFocus() { m_isshowH ? m_listView->setFocusPolicy(Qt::TabFocus) : m_listView->setFocusPolicy(Qt::NoFocus); m_isshowM ? m_memoryWidget->setFocusPolicy(Qt::TabFocus) : m_memoryWidget->setFocusPolicy(Qt::NoFocus); } void MemHisWidget::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } /** * @brief 左右切换buttonbox焦点 */ void MemHisWidget::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Left && (m_historyBtn->hasFocus() || m_memoryBtn->hasFocus())) { // focusNextChild();//焦点移动 m_memoryBtn->setFocus(); } else if (e->key() == Qt::Key_Right && (m_historyBtn->hasFocus() || m_memoryBtn->hasFocus())) { // focusNextChild();//焦点移动 m_historyBtn->setFocus(); } else if (e->key() == Qt::Key_Escape) { emit hideWidget(); } } /** * @brief tab切焦点保证焦点在m_historyBtn * @param obj m_memoryBtn */ bool MemHisWidget::eventFilter(QObject *obj, QEvent *event) { //防止tab到m_historybtn if (obj == m_historyBtn && event->type() == QEvent::FocusIn) { QFocusEvent *focus_Event = static_cast(event); if (focus_Event->reason() == Qt::TabFocusReason) { m_memoryBtn->setFocus(); return true; } } if (obj == this) { if (event->type() == QEvent::KeyPress) { //焦点在该widget上点击tab切换到stackwidget QKeyEvent *key_event = static_cast (event); if (key_event->key() == Qt::Key_Tab && !m_clearButton->isHidden()) { m_stackWidget->currentWidget()->setFocus(Qt::TabFocusReason); return true; } } else if (event->type() == QEvent::FocusOut) { //点击标题栏及外部桌面失去焦点时切换至scientifickeypad QFocusEvent *focus_Event = static_cast(event); if (focus_Event->reason() == Qt::MouseFocusReason || focus_Event->reason() == Qt::ActiveWindowFocusReason) { emit hideWidget(); } } } if (obj == m_memoryWidget->findChild() || obj == m_clearButton || obj == m_listView || obj == m_memoryBtn || obj == m_historyBtn) { if (event->type() == QEvent::KeyPress) { //焦点循环 QKeyEvent *key_event = static_cast < QKeyEvent *>(event); //将事件转化为键盘事件 if (key_event->key() == Qt::Key_Tab) { if (m_memoryWidget->findChild()->hasFocus()) { m_memoryBtn->setFocus(Qt::TabFocusReason); } else if (m_listView->hasFocus()) { m_memoryBtn->setFocus(Qt::TabFocusReason); } else if ((m_memoryBtn->hasFocus() || m_historyBtn->hasFocus()) && !m_clearButton->isHidden()) { m_clearButton->setFocus(Qt::TabFocusReason); } else if (m_clearButton->hasFocus()) { if (m_stackWidget->currentWidget() == m_memoryWidget) m_memoryWidget->setFocus(Qt::TabFocusReason); else m_listView->setFocus(Qt::TabFocusReason); } return true; //在该对象点击tab不让焦点到窗口外 } else if (key_event->key() == Qt::Key_Escape) { emit hideWidget(); } } else if (event->type() == QEvent::FocusOut) { //点击标题栏及外部桌面失去焦点时切换至scientifickeypad QFocusEvent *focus_Event = static_cast(event); if (focus_Event->reason() == Qt::MouseFocusReason || focus_Event->reason() == Qt::ActiveWindowFocusReason) { emit hideWidget(); } } } return QWidget::eventFilter(obj, event); } void MemHisWidget::focusInEvent(QFocusEvent *event) { if (event->reason() == Qt::TabFocusReason) { if (m_stackWidget->currentWidget() == m_memoryWidget) { m_memoryWidget->setFocus(Qt::TabFocusReason); } else { m_listView->setFocus(Qt::TabFocusReason); } } QWidget::focusInEvent(event); } /** * @brief 根据主题变换更换垃圾桶切图 */ void MemHisWidget::themeChanged(int type) { QString path; int typeIn = type; if (typeIn == 0) { typeIn = DGuiApplicationHelper::instance()->themeType(); } if (typeIn == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); m_clearButton->setIconUrl(path + "empty_normal.svg", path + "empty_hover.svg", path + "empty_press.svg", 1); m_memoryPublic->setThemeType(typeIn); m_listDelegate->setThemeType(typeIn); m_themeType = typeIn; iconChanged(m_themeType, m_buttonBox->checkedId()); } /** * @brief MemHisWidget::iconChanged * @param type:主题 * @param id:buttonbox的checkid * buttonbox按键切换时,切换对应的切图 */ void MemHisWidget::iconChanged(int type, int id) { QString path; if (type == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); if (id == 0) { m_memoryBtn->setIcon(QIcon(path + "icon_memory_checked.svg")); m_historyBtn->setIcon(QIcon(path + "icon_history_normal.svg")); } else { m_memoryBtn->setIcon(QIcon(path + "icon_memory_normal.svg")); m_historyBtn->setIcon(QIcon(path + "icon_history_checked.svg")); } } /** * @brief 历史记录中有内容tab */ void MemHisWidget::historyfilled() { if (m_isshowH == false) m_listModel->deleteItem(1); m_listView->listItemFill(true); m_listView->setFocusPolicy(Qt::TabFocus); m_isshowH = true; emit hisIsFilled(true); if (m_stackWidget->currentWidget() != m_memoryWidget) m_clearButton->setHidden(false); } MemoryWidget *MemHisWidget::getMemoryWiget() { return m_memoryWidget; } SimpleListModel* MemHisWidget::getSimpleListModel() { return m_listModel; } deepin-calculator-5.7.21/src/widgets/memhiswidget.h000066400000000000000000000053501423020056600222760ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MEMHISWIDGET_H #define MEMHISWIDGET_H #include "../control/iconbutton.h" #include "../views/memorywidget.h" #include "../views/simplelistdelegate.h" #include "../views/simplelistmodel.h" #include "../views/simplelistview.h" #include "../memorypublic.h" #include #include #include #include #include #include DGUI_USE_NAMESPACE DWIDGET_USE_NAMESPACE /** * @brief 科学模式历史记录及内存记录界面 */ class MemHisWidget : public DWidget { Q_OBJECT public: /** * @brief 内存运算类型 */ enum memOperate { generateData, memoryplus, memoryminus, memoryclean, //MS, M+, M-, MC widgetplus, widgetminus //内存中的M+, M- }; explicit MemHisWidget(QWidget *parent = nullptr); ~MemHisWidget(); void focusOnButtonbox(Qt::FocusReason Reason); void memoryFunctions(memOperate operate = generateData, Quantity answer = Quantity(), int row = -1); void resetFocus(); void historyfilled(); MemoryWidget *getMemoryWiget(); SimpleListModel* getSimpleListModel(); void mouseMoveEvent(QMouseEvent *e); void keyPressEvent(QKeyEvent *e); bool eventFilter(QObject *obj, QEvent *event); void focusInEvent(QFocusEvent *event); signals: void hisIsFilled(bool isfilled); void hideWidget(); public slots: void themeChanged(int type); void iconChanged(int type, int id); private: QStackedWidget *m_stackWidget; SimpleListView *m_listView; SimpleListDelegate *m_listDelegate; SimpleListModel *m_listModel; MemoryWidget *m_memoryWidget; MemoryPublic *m_memoryPublic; DButtonBox *m_buttonBox; DButtonBoxButton *m_memoryBtn; DButtonBoxButton *m_historyBtn; IconButton *m_clearButton; //记录清除按钮 bool m_isshowM = false; //内存中无内容为false bool m_isshowH = false; int m_themeType = 0; //当前主题 }; #endif // MEMHISWIDGET_H deepin-calculator-5.7.21/src/widgets/probitwidget.cpp000066400000000000000000000050631423020056600226470ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "probitwidget.h" #include #include #include const QSize SIZE = QSize(76, 46); ProBitWidget::ProBitWidget(QWidget *parent) : DWidget(parent), m_firstbtn(new BitButton(this)), m_secondbtn(new BitButton(this)), m_thirdbtn(new BitButton(this)), m_fourthbtn(new BitButton(this)), m_label(new DLabel(this)) { setFixedSize(SIZE); QHBoxLayout *hlay = new QHBoxLayout(); QVBoxLayout *vlay = new QVBoxLayout(this); hlay->addWidget(m_firstbtn); hlay->addSpacing(1); hlay->addWidget(m_secondbtn); hlay->addSpacing(1); hlay->addWidget(m_thirdbtn); hlay->addSpacing(1); hlay->addWidget(m_fourthbtn); hlay->addSpacing(1); hlay->setMargin(0); hlay->setSpacing(4); hlay->setContentsMargins(0, 0, 0, 0); m_label->setFixedSize(70, 20); m_label->setAlignment(Qt::AlignRight); QFont font; font.setPixelSize(14); font.setFamily("Noto Sans"); m_label->setFont(font); vlay->addLayout(hlay); vlay->addWidget(m_label); vlay->setMargin(0); vlay->setSpacing(0); vlay->setContentsMargins(0, 0, 0, 0); } ProBitWidget::~ProBitWidget() { } /** * @brief 设置当前widget,button可用状态 * @param enabled true-可用 false-不可用 */ void ProBitWidget::setButtonEnabled(bool enabled) { m_firstbtn->setEnabled(enabled); m_secondbtn->setEnabled(enabled); m_thirdbtn->setEnabled(enabled); m_fourthbtn->setEnabled(enabled); } /** * @brief ProBitWidget::getbutton * @param i:第几个按钮 * @return 对应按钮 */ BitButton *ProBitWidget::getbutton(int i) { switch (i) { case 3: return m_fourthbtn; case 2: return m_thirdbtn; case 1: return m_secondbtn; case 0: return m_firstbtn; default: return m_firstbtn; } } deepin-calculator-5.7.21/src/widgets/probitwidget.h000066400000000000000000000025231423020056600223120ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROBITWIDGET_H #define PROBITWIDGET_H #include "../control/bitbutton.h" #include #include #include DWIDGET_USE_NAMESPACE DGUI_USE_NAMESPACE /** * @brief 一块二进制键盘控件 */ class ProBitWidget : public DWidget { Q_OBJECT public: explicit ProBitWidget(QWidget *parent = nullptr); ~ProBitWidget(); void setButtonEnabled(bool enabled); BitButton *getbutton(int i); private: BitButton *m_firstbtn; BitButton *m_secondbtn; BitButton *m_thirdbtn; BitButton *m_fourthbtn; DLabel *m_label; }; #endif // PROBITWIDGET_H deepin-calculator-5.7.21/src/widgets/proexpressionbar.cpp000066400000000000000000001630401423020056600235510ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "proexpressionbar.h" #include "../utils.h" #include "../../3rdparty/core/settings.h" #include #include #include const int LIST_HEIGHT = 35; //输入栏上方表达式的高度 const int INPUTEDIT_HEIGHT = 55; #define BASE_TAG(basetag) \ if (Settings::instance()->programmerBase == 16) \ basetag = "0x"; \ else if (Settings::instance()->programmerBase == 8) \ basetag = "0o"; \ else if (Settings::instance()->programmerBase == 2) \ basetag = "0b"; \ ProExpressionBar::ProExpressionBar(QWidget *parent) : DWidget(parent) { m_evaluator = Evaluator::instance(); m_listView = new SimpleListView(0, this); m_listDelegate = new SimpleListDelegate(0, this); m_listModel = new SimpleListModel(0, this); m_inputEdit = new InputEdit(this); m_isContinue = true; m_isAllClear = false; m_isResult = false; m_inputNumber = false; m_isUndo = false; m_listView->setModel(m_listModel); m_listView->setItemDelegate(m_listDelegate); m_listView->setFixedHeight(LIST_HEIGHT); m_inputEdit->setFixedHeight(INPUTEDIT_HEIGHT); m_inputEdit->setAlignment(Qt::AlignRight); m_inputEdit->setTextMargins(10, 0, 10, 6); QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(m_listView); layout->addWidget(m_inputEdit); layout->setMargin(0); layout->setSpacing(0); initConnect(); m_funclist = {"nand", "not", "xor", "and", "nor", "ror", "or", "shl", "shr", "sal", "sar", "rol", "rcl", "rcr" }; } ProExpressionBar::~ProExpressionBar() { } void ProExpressionBar::mouseMoveEvent(QMouseEvent *event) { Q_UNUSED(event); } InputEdit *ProExpressionBar::getInputEdit() { return m_inputEdit; } bool ProExpressionBar::isnumber(QChar a) { return m_inputEdit->isNumber(a); } /** * @brief ProExpressionBar::judgeinput * @return 是否正常输入 * 用于判断当前输入光标是否在函数间,不允许在函数中插入任何内容 */ bool ProExpressionBar::judgeinput() { QString sRegNum = "[a-z]"; QRegExp rx; rx.setPattern(sRegNum); SSelection selection = m_inputEdit->getSelection(); if (selection.selected != "") { //光标不在开头且光标左侧是字母或者光标右侧是字母 if ((selection.curpos > 0 && rx.exactMatch(m_inputEdit->text().at(selection.curpos - 1))) || (selection.curpos + selection.selected.size() < m_inputEdit->text().size() && rx.exactMatch(m_inputEdit->text().at(selection.curpos + selection.selected.size())))) { int funpos = -1; int rightfunpos = -1; for (int i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], selection.curpos - 1); if (funpos != -1 && (funpos <= selection.curpos) && (selection.curpos < funpos + m_funclist[i].length())) { return false; //选中左侧在函数中 } } for (int j = 0; j < m_funclist.size(); j++) { //记录离光标最近的右侧函数位 rightfunpos = m_inputEdit->text().lastIndexOf(m_funclist[j], selection.curpos + selection.selected.size() - 1); if (rightfunpos != -1 && (rightfunpos + m_funclist[j].length() > selection.curpos + selection.selected.size())) return false; //选中右侧在函数中 } } return true; } else { if (m_inputEdit->cursorPosition() > 0 && rx.exactMatch(m_inputEdit->text().at(m_inputEdit->cursorPosition() - 1))) { for (int i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 int funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], m_inputEdit->cursorPosition() - 1); if (funpos != -1 && (funpos < m_inputEdit->cursorPosition()) && (m_inputEdit->cursorPosition() < funpos + m_funclist[i].length())) return false; //光标在函数中 } } return true; } } void ProExpressionBar::enterNumberEvent(const QString &text) { if (!judgeinput()) return; if (m_inputNumber && m_isResult == true) { m_inputEdit->clear(); m_isResult = false; } if (m_isResult) { m_inputEdit->clear(); m_isResult = false; } if (!m_isContinue) { // the cursor position at the end, it will clear edit text. if (cursorPosAtEnd()) m_inputEdit->clear(); m_isContinue = true; // m_listView->setFocus(); } m_inputNumber = false; m_isUndo = false; //超过输入范围的不允许输入 QString oldtext = m_inputEdit->text(); int oldcurpos = m_inputEdit->cursorPosition(); // 20200401 修改symbolFaultTolerance执行位置 if (isNumberOutOfRange(text)) { m_inputEdit->setText(oldtext); m_inputEdit->setCursorPosition(oldcurpos); } else { replaceSelection(m_inputEdit->text()); m_inputEdit->insert(text); int nowcur = m_inputEdit->cursorPosition(); m_inputEdit->setText(symbolFaultTolerance(m_inputEdit->text())); // m_inputEdit->setText(pointFaultTolerance(m_inputEdit->text())); m_inputEdit->setCursorPosition(nowcur); } addUndo(); emit clearStateChanged(false); } void ProExpressionBar::enterSymbolEvent(const QString &text) { if (!judgeinput()) return; QString oldText = m_inputEdit->text(); QString symbol = text; symbol.replace('/', QString::fromUtf8("÷")); m_isResult = false; m_isUndo = false; // 20200213统一被选中光标复位代码 replaceSelection(m_inputEdit->text()); if (m_inputEdit->text().isEmpty()) { if (symbol != "-") { m_inputEdit->setText(oldText); } else { m_inputEdit->insert(symbol); } } else { int curPos = m_inputEdit->cursorPosition(); QString exp = m_inputEdit->text(); if (cursorPosAtEnd()) { if (m_inputEdit->text() == "-") { m_inputEdit->setText(oldText); } else { QString lastStr = exp.right(1); if (isOperator(lastStr)) exp.chop(1); m_inputEdit->setText(exp + symbol); } } else if (curPos == 0) { QString firstStr = exp.left(1); if (firstStr == QString::fromUtf8("-")) { m_inputEdit->setText(oldText); } else { if (symbol == QString::fromUtf8("-") || symbol == "-") m_inputEdit->insert(symbol); } } else { QString infront = exp.at(curPos - 1); QString behand = exp.at(curPos); if (isOperator(infront) || isOperator(behand)) { m_inputEdit->setText(oldText); } else m_inputEdit->insert(symbol); // 2020316修复添加符号后光标问题 //添加符号后左侧数字不会多分隔符,只需考虑添加符号后输入框光标前的数字与添加前是否一致 if (exp.mid(0, curPos).remove(QRegExp("[+-×÷/,%()\\s]")) == m_inputEdit->text().mid(0, curPos).remove(QRegExp("[+-×÷/,%()\\s]"))) { QString sRegNum = "[+-×÷/]"; QRegExp rx; rx.setPattern(sRegNum); rx.exactMatch(m_inputEdit->text().at(curPos)) ? m_inputEdit->setCursorPosition(curPos + 1) : m_inputEdit->setCursorPosition(curPos); qDebug() << curPos; } else m_inputEdit->setCursorPosition(curPos - 1); } } m_isContinue = true; expressionCheck(); if (!m_inputEdit->text().isEmpty()) { emit clearStateChanged(false); } addUndo(); } void ProExpressionBar::enterBackspaceEvent() { QString sRegNum = "[a-z]"; //20200811去除大写字母,否则E将被看作函数 QRegExp rx; rx.setPattern(sRegNum); SSelection selection = m_inputEdit->getSelection(); if (selection.selected != "") { selectedPartDelete(rx); } else { QString text = m_inputEdit->text(); int cur = m_inputEdit->cursorPosition(); int funpos = -1; int i; int Sepold = text.count(",") + text.count(" "); if (text.size() > 0 && cur > 1 && (text[cur - 1] == "," || (text[cur - 1] == " " && !text[cur - 2].isLower()))) { text.remove(cur - 2, 2); m_inputEdit->setText(text); // 20200401 symbolFaultTolerance m_inputEdit->setText(symbolFaultTolerance(m_inputEdit->text())); m_inputEdit->setCursorPosition(cur - 2); } else { //退函数 //光标不在开头且光标左侧是字母 if (m_inputEdit->cursorPosition() > 0 && rx.exactMatch(m_inputEdit->text().at(m_inputEdit->cursorPosition() - 1))) { for (i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], m_inputEdit->cursorPosition() - 1); if (funpos != -1 && (funpos <= m_inputEdit->cursorPosition()) && (m_inputEdit->cursorPosition() <= funpos + m_funclist[i].length())) break; //光标在函数开头和函数结尾之间 else funpos = -1; } if (funpos != -1) { m_inputEdit->setText(m_inputEdit->text().remove(funpos, m_funclist[i].length())); int Sepnew = m_inputEdit->text().count(",") + m_inputEdit->text().count(" "); m_inputEdit->setCursorPosition(funpos + Sepnew - Sepold + 1); } } else if (m_inputEdit->cursorPosition() > 1 && (text[cur - 1] == " " && text[cur - 2].isLower())) { for (i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], m_inputEdit->cursorPosition() - 2); if (funpos != -1 && (funpos <= m_inputEdit->cursorPosition()) && (m_inputEdit->cursorPosition() <= funpos + m_funclist[i].length() + 1)) break; //光标在函数开头和函数结尾之间 else funpos = -1; } if (funpos != -1) { m_inputEdit->setText(m_inputEdit->text().remove(funpos, m_funclist[i].length())); int Sepnew = m_inputEdit->text().count(",") + m_inputEdit->text().count(" "); m_inputEdit->setCursorPosition(funpos + Sepnew - Sepold + 1); } } else { int proNumber = text.count(",") + text.count(" "); m_inputEdit->backspace(); int separator = proNumber - m_inputEdit->text().count(",") - m_inputEdit->text().count(" "); // 20200401 symbolFaultTolerance m_inputEdit->setText(symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(",") + m_inputEdit->text().count(" "); if (cur > 0) { QString sRegNum1 = "[0-9A-F]+"; QRegExp rx1; rx1.setPattern(sRegNum1); //退数字 if (rx1.exactMatch(text.at(cur - 1)) && proNumber > newPro) { if (text.mid(cur, text.length() - cur) == m_inputEdit->text().mid(m_inputEdit->text().length() - (text.length() - cur), text.length() - cur)) { m_inputEdit->setCursorPosition(cur - 2); } else m_inputEdit->setCursorPosition(cur - 1); } else { if (separator < 0) { m_inputEdit->setCursorPosition(cur - 1 - separator); } else { m_inputEdit->setCursorPosition(cur - 1); } } } } } } if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } m_isResult = false; m_isContinue = true; m_isUndo = false; addUndo(); } void ProExpressionBar::enterClearEvent() { Settings::instance()->proRotateCarry = "00"; bool need_addundo = !m_inputEdit->text().isEmpty(); if (m_isAllClear) { m_listModel->clearItems(); m_listView->reset(); m_isAllClear = false; emit clearStateChanged(false); } else { if (m_listModel->rowCount(QModelIndex()) == 0) emit clearStateChanged(false); else emit clearStateChanged(true); m_inputEdit->clear(); m_isAllClear = true; } m_isResult = false; m_isUndo = false; // m_Selected = -1; if (need_addundo) addUndo(); } void ProExpressionBar::enterEqualEvent() { QString exp = m_inputEdit->text(); if (m_inputEdit->text().isEmpty()) { return; } QString expression = QString(); if (Settings::instance()->programmerBase == 8 || Settings::instance()->programmerBase == 16) { expression = InputEdit::formatExpression(2, m_inputEdit->scanAndExec(Settings::instance()->programmerBase, 2)); } else { expression = InputEdit::formatExpression(Settings::instance()->programmerBase, m_inputEdit->text()); } QString exp1 = symbolComplement(expression); m_evaluator->setExpression(exp1); Quantity ans = m_evaluator->evalUpdateAns(); Settings::instance()->proRotateCarry.replace(1, 1, Settings::instance()->proRotateCarry.front()); // 20200403 bug-18971 表达式错误时输数字加等于再重新输入表达式历史记录错误表达式未被替换 // 20200407 超过16位小数未科学计数 qDebug() << "m_evaluator->error()" << m_evaluator->error(); qDebug() << "ans" << m_inputEdit->expressionText(); if (m_evaluator->error().isEmpty() && (exp.indexOf(QRegExp("[a-z+-×÷,%()\\s]")) != -1)) { if (ans.isNan() && !m_evaluator->isUserFunctionAssign()) { m_expression = exp + "=" + tr("Expression error"); m_listModel->updataList(m_expression, -1, true); return; } //edit 20200413 for bug--19653 QString result; switch (Settings::instance()->programmerBase) { case 16: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); break; case 8: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); break; case 2: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); break; default: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65)); break; } while (result.startsWith('0') && result.length() > 1) { result.remove(0, 1); } QString formatResult = Utils::formatThousandsSeparatorsPro(result, Settings::instance()->programmerBase); formatResult = formatResult.replace(QString::fromUtf8("+"), "+") .replace(QString::fromUtf8("-"), "-") .replace(QString::fromUtf8("×"), "*") .replace(QString::fromUtf8("÷"), "/"); //.replace(QString::fromUtf8(","), ""); // QString tStr = m_inputEdit->text().replace(QString::fromUtf8(","), ""); QString tStr = m_inputEdit->text(); //edit 20200518 for bug-26628 QString StrToComp = formatResult; StrToComp = StrToComp.replace("+", QString::fromUtf8("+")) .replace("-", QString::fromUtf8("-")) .replace("*", QString::fromUtf8("×")) .replace("/", QString::fromUtf8("÷")); if (StrToComp == exp) { return; } //end edit 20200518 for bug-26628 // 20200402 需求3.2.1.6当输入的数字中有千位符,点击等号视为前后一致,不计入表达式 if (formatResult != tStr) { // m_listModel->updataList(m_inputEdit->text() + "=" + formatResult, m_hisRevision); m_inputEdit->setAnswer(formatResult, ans); } m_isContinue = false; m_inputEdit->setText(formatResult); formatResult = formatResult.replace(QString::fromUtf8("-"), "-"); m_expression = exp + "=" + formatResult; m_listModel->updataList(m_expression, -1, true); } else { if (!m_evaluator->error().isEmpty()) { m_expression = exp + "=" + tr("Expression error"); m_listModel->updataList(m_expression, -1, true); } else { return; } } m_isResult = true; m_isUndo = false; m_inputEdit->getCurrentCursorPositionNumber(m_inputEdit->cursorPosition()); addUndo(); } void ProExpressionBar::enterNotEvent() { if (!judgeinput()) return; emit clearStateChanged(false); if (m_inputEdit->text().isEmpty()) { m_inputEdit->setText("not(0)"); m_isResult = false; m_isUndo = false; addUndo(); return; } bool hasselect = (m_inputEdit->getSelection().selected != ""); QString oldText = m_inputEdit->text(); QString exp = m_inputEdit->text(); // 20200316百分号选中部分格式替代 replaceSelection(m_inputEdit->text()); int curPos = m_inputEdit->cursorPosition(); if (m_inputEdit->text() == QString()) { m_inputEdit->setText("not("); m_isResult = false; m_isUndo = false; addUndo(); return; } if (curPos == 0 && hasselect == false) { return; } if ((curPos == 0 && hasselect == true) || curposInNumber(curPos)) { return; } // start edit for task-13519 // QString sRegNum1 = "[^0-9,.×÷)]"; QString sRegNum1 = "[^A-F^0-9,\\s)]"; QRegExp rx1; rx1.setPattern(sRegNum1); if (rx1.exactMatch(exp.at(curPos - 1))) m_inputEdit->setText(oldText); else { QString newtext = m_inputEdit->text(); int percentpos = m_inputEdit->cursorPosition(); int operatorpos = newtext.lastIndexOf(QRegularExpression(QStringLiteral("[^A-F^0-9,\\s]")), percentpos - 1); /*出现以下情况: * 1. 负号在表达式的开头,如-1,-120等,视为一个整体的负数 * 2. 负号在左括号的后一位,如(-1, (-121等,也视为一个整体的负数 * 其中,当出现(-12)时,光标在右括号右侧时则会优先取到 ")",只有在右括号左侧才满足条件2*/ if ((operatorpos == 0 && newtext.at(0) == "-") || (operatorpos > 0 && newtext.at(operatorpos) == "-" && newtext.at(operatorpos - 1) == "(")) operatorpos--; bool nooperator = false; if (operatorpos < 0) { operatorpos++; nooperator = true; } QString exptext; //表达式 if (newtext.at(percentpos - 1) == ')') { if (operatorpos > 0 && newtext.at(operatorpos - 1) == '(') { m_inputEdit->setText(oldText); m_inputEdit->setCursorPosition(percentpos); return; } do { operatorpos = newtext.lastIndexOf('(', operatorpos - 1); if (operatorpos <= 0) { break; } } while (newtext.mid(operatorpos, newtext.size() - operatorpos).count('(') != newtext.mid(operatorpos, percentpos - operatorpos).count(')')); //匹配到的(不在开头且(左侧是字母 QString sRegNum2 = "[a-z]"; QRegExp latterrx; latterrx.setPattern(sRegNum2); if (operatorpos > 0 && latterrx.exactMatch(m_inputEdit->text().at(operatorpos - 1))) { int funpos = -1; //记录函数位 int i; for (i = 0; i < m_funclist.size(); i++) { //记录(左侧离(最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], operatorpos - 1); if (funpos != -1 && (funpos + m_funclist[i].length() == operatorpos)) break; //(在函数结尾 else funpos = -1; } if (funpos != -1) operatorpos = operatorpos - m_funclist[i].length(); //截取函数 } else if (operatorpos > 1 && m_inputEdit->text().mid(operatorpos - 2, 2) == "1/") { operatorpos = operatorpos - 2; //截取倒数 } exptext = newtext.mid(operatorpos, percentpos - operatorpos); //截取表达式 } else { exptext = newtext.mid(operatorpos + (nooperator == true ? 0 : 1), percentpos - operatorpos + (nooperator == true ? 1 : 0) - 1); //截取表达式 } // QString express = symbolComplement(exptext); if (exptext.count("(") == exptext.count(")")) { m_inputEdit->setCursorPosition(curPos - exptext.length()); m_inputEdit->insert("not("); int afterinsertpos = m_inputEdit->cursorPosition(); m_inputEdit->setCursorPosition(afterinsertpos + exptext.length()); m_inputEdit->insert(")"); } } m_isResult = false; m_isUndo = false; addUndo(); } /** * @brief ProExpressionBar::enterOperatorEvent * @param text:输入的操作符名称 * 包含了程序员计算器除not以外的所有逻辑、位运算操作符的输入 */ void ProExpressionBar::enterOperatorEvent(const QString &text) { if (!judgeinput()) return; emit clearStateChanged(false); QString zerotext = "0" + text; bool isreplace = false; int length = text.length(); if (m_inputEdit->text().isEmpty()) { m_inputEdit->setText(zerotext); m_isResult = false; m_isUndo = false; addUndo(); return; } m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().left(curpos).count(",") + m_inputEdit->text().left(curpos).count(" "); /* * 当光标位置的前一位是运算符时,在函数方法前面补0,当函数的运算优先级小于等于 * 前一位运算符时,则补(0 */ int diff = 0; //补数字后光标位移的距离 QString sRegNum = "[+-×÷(]"; QRegExp rx; rx.setPattern(sRegNum); if (curpos == 0 || rx.exactMatch(exp.at(curpos - 1))) { m_inputEdit->insert(zerotext); diff = 1; } else if (exp.at(curpos - 1).isLower()) { while (diff <= curpos - 1 && exp.at(curpos - 1 - diff).isLower()) { diff++; } exp.replace(curpos - diff, diff, text); m_inputEdit->setText(exp); isreplace = true; } else if (curpos > 1 && exp.at(curpos - 1) == " " && exp.at(curpos - 2).isLower()) { while (diff <= curpos - 2 && exp.at(curpos - 2 - diff).isLower()) { diff++; } exp.replace(curpos - 1 - diff, diff, text); m_inputEdit->setText(exp); isreplace = true; } else if (exp.at(curpos - 1) == "%") { diff = 1; exp.replace(curpos - diff, diff, text); m_inputEdit->setText(exp); isreplace = true; } else m_inputEdit->insert(text); // 20200401 symbolFaultTolerance bool isAtEnd = cursorPosAtEnd(); m_inputEdit->setText(symbolFaultTolerance(m_inputEdit->text())); m_isUndo = false; m_isResult = false; addUndo(); //计算光标位移的距离,区别是否是替换前面的。只考虑左边的分隔符变化的情况,如果为替换的情况,需要减去替换带来的长度差。 if (isreplace) { int newPro = m_inputEdit->text().left(curpos + length - diff).count(",") + m_inputEdit->text().left(curpos + length - diff).count(" "); diff += proNumber - newPro; m_inputEdit->setCursorPosition(curpos + length - diff); } else { int newPro = m_inputEdit->text().left(curpos + length).count(",") + m_inputEdit->text().left(curpos + length).count(" "); diff += newPro - proNumber; if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != "," && exp.at(curpos) != " ") { m_inputEdit->setCursorPosition(curpos + length - 1 + diff); } else { m_inputEdit->setCursorPosition(curpos + length + diff); } } else { m_inputEdit->setCursorPosition(curpos + length + diff); } } } void ProExpressionBar::enterOppositeEvent() { if (!judgeinput()) return; if (m_inputEdit->text().isEmpty()) { return; } emit clearStateChanged(false); m_isResult = false; m_isUndo = false; bool hasselect = (m_inputEdit->getSelection().selected != ""); QString oldText = m_inputEdit->text(); QString exp = m_inputEdit->text(); // 20200316百分号选中部分格式替代 replaceSelection(m_inputEdit->text()); int curPos = m_inputEdit->cursorPosition(); if (m_inputEdit->text() == QString()) { m_inputEdit->setText("(-"); m_isUndo = false; m_isResult = false; addUndo(); return; } if (curPos == 0 && hasselect == false) { return; } if ((curPos == 0 && hasselect == true) || curposInNumber(curPos)) { return; } // start edit for task-13519 // QString sRegNum1 = "[^0-9,.×÷)]"; QString sRegNum1 = "[^A-F^0-9,\\s)]"; QString sRegNum2 = "[A-F0-9,]"; QRegExp rx1, rx2; rx1.setPattern(sRegNum1); rx2.setPattern(sRegNum2); if (rx1.exactMatch(exp.at(curPos - 1))) return; else if (exp.at(curPos - 1) == "0" && (curPos <= 1 || !rx2.exactMatch(exp.at(curPos - 2)))) { return; } else if (curPos > 1 && exp.at(curPos - 1) == " " && exp.at(curPos - 2).isLower()) { return; } else { QString newtext = m_inputEdit->text(); int percentpos = m_inputEdit->cursorPosition(); int operatorpos = newtext.lastIndexOf(QRegularExpression(QStringLiteral("[^A-F^0-9,\\s]")), percentpos - 1); bool nooperator = false; if (operatorpos < 0) { operatorpos++; nooperator = true; } QString exptext; //表达式 if (newtext.at(percentpos - 1) == ')') { if (operatorpos > 0 && newtext.at(operatorpos - 1) == '(') { m_inputEdit->setText(oldText); m_inputEdit->setCursorPosition(percentpos); return; } do { operatorpos = newtext.lastIndexOf('(', operatorpos - 1); if (operatorpos <= 0) { break; } } while (newtext.mid(operatorpos, newtext.size() - operatorpos).count('(') != newtext.mid(operatorpos, percentpos - operatorpos).count(')')); //匹配到的(不在开头且(左侧是字母 QString sRegNum3 = "[a-z]"; QRegExp latterrx; latterrx.setPattern(sRegNum3); if (operatorpos > 0 && latterrx.exactMatch(m_inputEdit->text().at(operatorpos - 1))) { int funpos = -1; //记录函数位 int i; for (i = 0; i < m_funclist.size(); i++) { //记录(左侧离(最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], operatorpos - 1); if (funpos != -1 && (funpos + m_funclist[i].length() == operatorpos)) break; //(在函数结尾 else funpos = -1; } if (funpos != -1) operatorpos = operatorpos - m_funclist[i].length(); //截取函数 } exptext = newtext.mid(operatorpos, percentpos - operatorpos); //截取表达式 } else { exptext = newtext.mid(operatorpos + (nooperator == true ? 0 : 1), percentpos - operatorpos + (nooperator == true ? 1 : 0) - 1); //截取表达式 } if (exptext.count("(") == exptext.count(")")) { m_inputEdit->setCursorPosition(curPos - exptext.length()); if (Settings::instance()->programmerBase == 10) { m_inputEdit->insert("(-"); int afterinsertpos = m_inputEdit->cursorPosition(); m_inputEdit->setCursorPosition(afterinsertpos + exptext.length()); m_inputEdit->insert(")"); } else { QString basetag = QString(); BASE_TAG(basetag); m_evaluator->setExpression("0-" + basetag + exptext); Quantity ans = m_evaluator->evalUpdateAns(); if (m_evaluator->error().isEmpty()) { if (ans.isNan() && !m_evaluator->isUserFunctionAssign()) return; //edit 20200413 for bug--19653 QString result; switch (Settings::instance()->programmerBase) { case 16: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Hexadecimal()).remove("0x"); break; case 8: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Octal()).remove("0o"); break; case 2: result = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Precision(65) + Quantity::Format::Binary()).remove("0b"); break; default: return; } result = Utils::formatThousandsSeparatorsPro(result, Settings::instance()->programmerBase); QString text = m_inputEdit->text(); text.remove(curPos - exptext.length(), exptext.length()); text.insert(curPos - exptext.length(), result); m_inputEdit->setText(text); m_inputEdit->setCursorPosition(curPos - exptext.length() + result.length()); } else { return; } } } } m_isUndo = false; m_isResult = false; addUndo(); } void ProExpressionBar::enterLeftBracketsEvent() { if (!judgeinput()) return; if (m_inputEdit->text().count("(") >= 100) return; emit clearStateChanged(false); m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(",") + m_inputEdit->text().count(" "); m_inputEdit->insert("("); // 20200401 symbolFaultTolerance bool isAtEnd = cursorPosAtEnd(); m_inputEdit->setText(symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(",") + m_inputEdit->text().count(" "); m_isUndo = false; m_isResult = false; addUndo(); if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != "," && exp.at(curpos) != " ") { m_inputEdit->setCursorPosition(curpos); } else { m_inputEdit->setCursorPosition(curpos + 1); } } } void ProExpressionBar::enterRightBracketsEvent() { if (!judgeinput()) return; if (m_inputEdit->text().count(")") >= 100) return; emit clearStateChanged(false); m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(",") + m_inputEdit->text().count(" "); m_inputEdit->insert(")"); // 20200401 symbolFaultTolerance bool isAtEnd = cursorPosAtEnd(); m_inputEdit->setText(symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(",") + m_inputEdit->text().count(" "); m_isUndo = false; m_isResult = false; addUndo(); if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != "," && exp.at(curpos) != " ") { m_inputEdit->setCursorPosition(curpos); } else { m_inputEdit->setCursorPosition(curpos + 1); } } } void ProExpressionBar::moveLeft() { QString sRegNum = "[a-z]"; QRegExp rx; rx.setPattern(sRegNum); if (m_inputEdit->cursorPosition() > 0 && rx.exactMatch(m_inputEdit->text().at(m_inputEdit->cursorPosition() - 1))) { int funpos = -1; int i; for (i = 0; i < m_funclist.size(); i++) { funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], m_inputEdit->cursorPosition() - 1); if (funpos != -1 && funpos + m_funclist[i].length() == m_inputEdit->cursorPosition()) break; else funpos = -1; } if (funpos != -1) { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() - m_funclist[i].length()); } else { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() - 1); } } else { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() - 1); } m_inputEdit->setFocus(); } void ProExpressionBar::moveRight() { QString sRegNum = "[a-z]"; QRegExp rx; rx.setPattern(sRegNum); if (!cursorPosAtEnd() && rx.exactMatch(m_inputEdit->text().at(m_inputEdit->cursorPosition()))) { int funpos = -1; int i; for (i = 0; i < m_funclist.size(); i++) { funpos = m_inputEdit->text().indexOf(m_funclist[i], m_inputEdit->cursorPosition()); if (funpos != -1 && funpos == m_inputEdit->cursorPosition()) break; else funpos = -1; } if (funpos != -1) { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() + m_funclist[i].length()); } else { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() + 1); } } else { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() + 1); } m_inputEdit->setFocus(); } void ProExpressionBar::initTheme(int type) { m_listDelegate->setThemeType(type); m_inputEdit->themetypechanged(type); } void ProExpressionBar::revisionResults(const QModelIndex &index) { QString text = index.data(SimpleListModel::ExpressionRole).toString(); QStringList historic = text.split(QString("="), QString::SkipEmptyParts); if (historic.size() != 2) return; QString expression = historic.at(0); // m_hisRevision = index.row(); m_inputEdit->setText(expression); // m_Selected = m_hisRevision; m_isResult = false; // fix addundo for history revision m_isUndo = false; addUndo(); emit clearStateChanged(false); } void ProExpressionBar::addUndo() { m_undo.append(m_inputEdit->text()); m_redo.clear(); m_inputEdit->setRedoAction(false); m_inputEdit->setUndoAction(true); SSelection selection; m_inputEdit->setSelection(selection); } void ProExpressionBar::copyResultToClipboard() { if (m_inputEdit->text().isEmpty()) return; SSelection selection = m_inputEdit->getSelection(); QApplication::clipboard()->setText(selection.selected); //将选中项放入粘贴板 } void ProExpressionBar::copyClipboard2Result() { if (!judgeinput()) return; QString oldText = m_inputEdit->text(); //未粘贴操作的text int curpos = m_inputEdit->cursorPosition(); //未粘贴操作的光标位 QString text = Utils::toHalfWidth(QApplication::clipboard()->text()); text = text.left(text.indexOf("=")); text = text.replace('+', QString::fromUtf8("+")) .replace('-', QString::fromUtf8("-")) .replace("_", QString::fromUtf8("-")) .replace('*', QString::fromUtf8("×")) .replace('X', QString::fromUtf8("×")) .replace(QString::fromUtf8("*"), QString::fromUtf8("×")) .replace(QString::fromUtf8("("), "(") .replace(QString::fromUtf8(")"), ")") .replace(QString::fromUtf8("——"), QString::fromUtf8("-")) .replace('/', QString::fromUtf8("÷")); //对粘贴板中的内容进行英替中 //匹配函数方法 QStringList list; //根据不同进制,对应不同的筛选规则 switch (Settings::instance()->programmerBase) { case 16: text.remove(QRegExp("[G-Z]")); list = text.split(QRegExp("[A-F0-9+-×÷()%\\s]")); break; case 8: text.remove(QRegExp("[8-9]")); list = text.split(QRegExp("[0-7+-×÷()%\\s]")); break; case 2: text.remove(QRegExp("[2-9]")); list = text.split(QRegExp("[0-1+-×÷()%\\s]")); break; default: list = text.split(QRegExp("[0-9+-×÷(),%\\s]")); break; } for (int i = 0; i < list.size(); i++) { QString item = list[i]; for (int j = 0; j < m_funclist.size(); j++) { if (item.toLower().contains(m_funclist[j])) { item.replace(item, m_funclist[j]); //包含函数名的取出;item中若存在两个函数名,只可以替代最前面的函数名 break; } if (j == m_funclist.size() - 1) { item.replace(item, QString()); } } text.replace(list[i], item); } if (isNumberOutOfRange(text)) return; replaceSelection(oldText); QString exp = m_inputEdit->text(); while (exp.count("(") + text.count("(") > 100) { text.remove(text.lastIndexOf("("), 1); } while (exp.count(")") + text.count(")") > 100) { text.remove(text.lastIndexOf(")"), 1); } m_inputEdit->insert(text); QString faulttolerance = symbolFaultTolerance(m_inputEdit->text()); if (faulttolerance != m_inputEdit->text()) m_inputEdit->setText(faulttolerance); //如果经过容错处理的表达式有改变,重新设置表达式,不设置光标 if (m_inputEdit->text() == exp) { m_inputEdit->setText(oldText); m_inputEdit->setCursorPosition(curpos); qDebug() << "Invalid content"; //提示是否复制了无效内容,复制的内容全是字母等 } if (!m_inputEdit->text().isEmpty()) emit clearStateChanged(false); m_isResult = false; m_isUndo = false; addUndo(); } void ProExpressionBar::allElection() { m_inputEdit->selectAll(); SSelection selection; selection.selected = m_inputEdit->text(); m_inputEdit->setSelection(selection); } void ProExpressionBar::shear() { QString sRegNum = "[a-z]"; //20200811去除大写字母,否则E将被看作函数 QRegExp rx; rx.setPattern(sRegNum); QString text = m_inputEdit->text(); QString selectText = m_inputEdit->selectedText(); selectText = selectText.replace(",", "").remove(" "); QApplication::clipboard()->setText(selectText); selectedPartDelete(rx); addUndo(); m_isUndo = false; m_isResult = false; m_isContinue = true; //发送C/AC切换信号 if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } } void ProExpressionBar::deleteText() { QString sRegNum = "[a-z]"; //20200811去除大写字母,否则E将被看作函数 QRegExp rx; rx.setPattern(sRegNum); selectedPartDelete(rx); if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } m_isResult = false; m_isContinue = true; m_isUndo = false; addUndo(); } void ProExpressionBar::Undo() { if (m_undo.isEmpty()) return; // clearLinkageCache(); m_redo.append(m_undo.last()); m_inputEdit->setRedoAction(true); m_undo.removeLast(); m_isUndo = true; //20200619 从结果撤销到上一次表达式按下数字键不清空输入框 if (m_isResult) m_isResult = false; // 20200319修复选中某一数字按下相同数字无法清除选中内容的问题 if (!m_undo.isEmpty()) { if (m_undo.size() > 1) { for (int i = m_undo.size() - 1; i > 0; i--) { if (m_undo.at(i) == m_inputEdit->text() && m_undo.at(i - 1) == m_inputEdit->text()) m_undo.pop_back(); } } m_inputEdit->setText(m_undo.last()); } else { m_inputEdit->clear(); m_inputEdit->setUndoAction(false); } if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } } void ProExpressionBar::Redo() { if (m_redo.isEmpty()) return; // clearLinkageCache(); m_inputEdit->setText(m_redo.last()); m_undo.append(m_inputEdit->text()); m_redo.removeLast(); m_inputEdit->setRedoAction(!m_redo.isEmpty()); if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } } void ProExpressionBar::setResultFalse() { m_isResult = false; } void ProExpressionBar::initConnect() { connect(m_listView, &SimpleListView::obtainingHistoricalSimple, this, &ProExpressionBar::revisionResults); connect(m_listView, &SimpleListView::obtainingHistoricalSimple, m_inputEdit, &InputEdit::hisexpression); connect(m_inputEdit, &InputEdit::textChanged, this, &ProExpressionBar::handleTextChanged); connect(m_inputEdit, &InputEdit::keyPress, this, &ProExpressionBar::keyPress); connect(m_inputEdit, &InputEdit::equal, this, &ProExpressionBar::enterEqualEvent); connect(m_inputEdit, &InputEdit::cut, this, &ProExpressionBar::shear); connect(m_inputEdit, &InputEdit::copy, this, &ProExpressionBar::copyResultToClipboard); connect(m_inputEdit, &InputEdit::paste, this, &ProExpressionBar::copyClipboard2Result); connect(m_inputEdit, &InputEdit::deleteText, this, &ProExpressionBar::deleteText); connect(m_inputEdit, &InputEdit::selectAllText, this, &ProExpressionBar::allElection); connect(m_inputEdit, &InputEdit::undo, this, &ProExpressionBar::Undo); connect(m_inputEdit, &InputEdit::redo, this, &ProExpressionBar::Redo); connect(m_inputEdit, &InputEdit::setResult, this, &ProExpressionBar::setResultFalse); connect(m_inputEdit, &InputEdit::separateChange, this, &ProExpressionBar::onSeparateChange); } void ProExpressionBar::replaceSelection(QString text) { QString seloldtext = text; SSelection selection = m_inputEdit->getSelection(); int selcurPos = m_inputEdit->cursorPosition(); if (selection.selected != "") { text.remove(selection.curpos, selection.selected.size()); m_inputEdit->setText(text); if (selcurPos > selection.curpos && selcurPos <= selection.curpos + selection.selected.size()) selcurPos = selection.curpos; // 20200313选中部分光标置位问题修复 if (seloldtext.mid(0, selcurPos).remove(QRegExp("[,\\s]")).length() == m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[,\\s]")).length()) m_inputEdit->setCursorPosition(selcurPos); else if (seloldtext.mid(0, selcurPos).remove(QRegExp("[,\\s]")).length() > m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[,\\s]")).length()) m_inputEdit->setCursorPosition(selcurPos + 1); else m_inputEdit->setCursorPosition(selcurPos - 1); } // reset selection selection = SSelection(); m_inputEdit->setSelection(selection); } QString ProExpressionBar::symbolComplement(const QString exp) { QString text = exp; int index = text.indexOf("(", 0); while (index != -1) { if (index >= 1 && isnumber(text.at(index - 1))) { text.insert(index, "×"); ++index; } ++index; index = text.indexOf("(", index); } index = text.indexOf(")", 0); while (index != -1) { if (index < text.length() - 1 && isnumber(text.at(index + 1))) { text.insert(index + 1, "×"); ++index; } ++index; index = text.indexOf(")", index); } //20200811 fix bug-42274 e,π,lastans跟随函数表达式错误问题 // index = text.indexOf("e", 0); // while (index != -1) { // text.insert(index, "("); // text.insert(index + 2, ")"); // index = text.indexOf("e", index + 3); // } // index = text.indexOf("pi", 0); // while (index != -1) { // text.insert(index, "("); // text.insert(index + 3, ")"); // index = text.indexOf("pi", index + 4); // } index = text.indexOf("lastans", 0); while (index != -1) { text.insert(index, "("); text.insert(index + 8, ")"); index = text.indexOf("lastans", index + 9); } return text; } bool ProExpressionBar::cursorPosAtEnd() { return m_inputEdit->cursorPosition() == m_inputEdit->text().length(); } /** * @brief ProExpressionBar::isOperator * @param text * @return 是否为有效的四则运算符 */ bool ProExpressionBar::isOperator(const QString &text) { if (text == QString::fromUtf8("+") || text == QString::fromUtf8("-") || text == QString::fromUtf8("×") || text == QString::fromUtf8("÷")) { return true; } else { return false; } } void ProExpressionBar::expressionCheck() { QString exp = m_inputEdit->text(); int cur = m_inputEdit->cursorPosition(); //光标前的分隔符 int separator = 0; for (int i = 0; i < exp.size(); ++i) { if (exp[i] == ",") { exp.remove(i, 1); --i; if (i + 1 < cur) { ++separator; --cur; } } } for (int i = 0; i < exp.size(); ++i) { while (isnumber(exp[i])) { if (exp[i] == "0" && (i == 0 || !isnumber(exp[i - 1])) && (exp.size() == 1 || isnumber(exp[i + 1]))) { exp.remove(i, 1); --i; if (i + 1 < cur) --cur; } ++i; } } m_inputEdit->setText(exp); m_inputEdit->setCursorPosition(cur + separator); } /** * @brief ProExpressionBar::symbolFaultTolerance * @param text:输入栏中的内容 * @return 修改后的内容 * 处理当有多个四则运算符时,只保留最后输入的符号 */ QString ProExpressionBar::symbolFaultTolerance(const QString &text) { if (text.isEmpty()) return text; QString exp = text; QString newText; QStringList symbolList; for (int i = 0; i < exp.length(); ++i) { if (!isOperator(exp.at(i))) { if (!symbolList.isEmpty()) { if (!newText.isEmpty()) newText.append(symbolList.last()); //保证数字中间的符号只有一个,去除多余符号 if (newText.isEmpty() && symbolList.last() == "-") newText.append(symbolList.last()); //保存负数的-号 } newText.append(exp.at(i)); symbolList.clear(); } else { symbolList.append(exp.at(i)); continue; } } // qDebug() << symbolList << " a " << newText; if (!symbolList.isEmpty() /*&& !newText.isEmpty()*/) { //防止输入栏中只有符号可输入*/+;暂未屏蔽% if ((newText.isEmpty() && symbolList.contains("-"))) { newText.append("-"); } else if (!newText.isEmpty()) { newText.append(symbolList.last()); } } return newText; } bool ProExpressionBar::isNumberOutOfRange(const QString &text) { QString curtext = m_inputEdit->text(); int pos = m_inputEdit->cursorPosition(); SSelection selection = m_inputEdit->getSelection(); if (selection.selected != "") { curtext.remove(selection.curpos, selection.selected.size()); pos = selection.curpos; } curtext.insert(pos, text); m_numvec.clear(); curtext.remove(",").remove(" "); for (int i = 0; i < curtext.length();) { if (isnumber(curtext.at(i))) { for (int j = 0; j < curtext.length() - i; j++) { if (i + j == curtext.length() - 1) { if (isnumber(curtext.at(i + j))) { m_numvec.append(curtext.mid(i, j + 1)); i += j + 1; } else { m_numvec.append(curtext.mid(i, j)); i += j; } break; } if (!isnumber(curtext.at(i + j))) { m_numvec.append(curtext.mid(i, j)); i += j; break; } } } else { if (curtext.at(i).isLower()) { if (curtext.at(i) == 'n' && curtext.at(i + 1) == 'a') { i += 4; } else if (curtext.at(i) == 'o') { i += 2; } else { i += 3; } } else if ((i == 0 || !isnumber(curtext.at(i - 1))) && curtext.at(i) == QString::fromUtf8("-") && curtext.length() > i + 1 && isnumber(curtext.at(i + 1))) { i++; for (int j = 0; j < curtext.length() - i; j++) { if (!isnumber(curtext.at(i + j))) { m_numvec.append(curtext.mid(i - 1, j + 1)); i += j; break; } if (i + j == curtext.length() - 1) { m_numvec.append(curtext.mid(i - 1, j + 2)); i += j + 1; break; } } } else { i++; } } } for (int i = 0; i < m_numvec.size(); i++) { QString num = InputEdit::formatExpression(Settings::instance()->programmerBase, m_numvec.at(i)); Quantity ans(HNumber(num.toLatin1().data(), true)); if (ans.isNan()) return true; num = DMath::format(ans, Quantity::Format::Complement() + Quantity::Format::Binary() + Quantity::Format::NCut()).remove("0b"); if (Settings::instance()->programmerBase == 10) { Quantity posans; Quantity negans; switch (Settings::instance()->proBitLength) { case 8: posans = ans - Quantity(128); negans = ans + Quantity(129); if (!posans.isNegative() || !negans.isPositive()) return true; else break; case 16: posans = ans - Quantity(32768); negans = ans + Quantity(32769); if (!posans.isNegative() || !negans.isPositive()) return true; else break; case 32: posans = ans - Quantity(HNumber("2147483648")); negans = ans + Quantity(HNumber("2147483649")); if (!posans.isNegative() || !negans.isPositive()) return true; else break; case 64: posans = ans - Quantity(HNumber("9223372036854775808")); negans = ans + Quantity(HNumber("9223372036854775809")); if (!posans.isNegative() || !negans.isPositive()) return true; else break; } } else { if (num.length() > Settings::instance()->proBitLength) return true; } } return false; } /** * @brief ProExpressionBar::selectedPartDelete * 选中部分的删除处理 */ void ProExpressionBar::selectedPartDelete(const QRegExp &rx) { SSelection selection = m_inputEdit->getSelection(); int removepos = 0; //被删除位置 QString text = m_inputEdit->text(); QString seloldtext = text; //光标不在开头且光标左侧是字母或者光标右侧是字母 if ((selection.curpos > 0 && rx.exactMatch(m_inputEdit->text().at(selection.curpos - 1))) || (selection.curpos + selection.selected.size() < m_inputEdit->text().size() && rx.exactMatch(m_inputEdit->text().at(selection.curpos + selection.selected.size())))) { int selleftfunlen = 0; //选中左侧一部分函数长度 int funpos = -1; int rightfunpos = -1; int j; for (int i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], selection.curpos - 1); if (funpos != -1 && (funpos <= selection.curpos) && (selection.curpos < funpos + m_funclist[i].length())) { selleftfunlen = selection.curpos - funpos; break; //光标在函数开头和函数结尾之间 } else funpos = -1; } for (j = 0; j < m_funclist.size(); j++) { //记录离光标最近的右侧函数位 rightfunpos = m_inputEdit->text().lastIndexOf(m_funclist[j], selection.curpos + selection.selected.size() - 1); if (rightfunpos != -1 && (rightfunpos + m_funclist[j].length() > selection.curpos + selection.selected.size())) break; else rightfunpos = -1; } if (funpos != -1 || rightfunpos != -1) { if (funpos != -1 && rightfunpos == -1) { removepos = funpos; text.remove(funpos, selection.selected.size() + selleftfunlen); //仅左侧有函数 } else if (rightfunpos != -1 && funpos == -1) { removepos = selection.curpos; text.remove(selection.curpos, rightfunpos + m_funclist[j].length() - selection.curpos); //仅右侧有函数 } else { removepos = funpos; text.remove(funpos, rightfunpos + m_funclist[j].length() - funpos); //函数中或左右均有 } } else { removepos = selection.curpos; text.remove(selection.curpos, selection.selected.size()); } } else { removepos = selection.curpos; text.remove(selection.curpos, selection.selected.size()); } m_inputEdit->setText(text); //输入栏删除被选中 // 20200401 symbolFaultTolerance m_inputEdit->setText(symbolFaultTolerance(m_inputEdit->text())); // 20200316选中部分光标置位问题修复 // 选中部分删除后重新设置光标位置,用删除前的光标位置左侧(分隔符新增的只会影响左侧的数字)的数字部分去除分隔符后减去删除后的光标位置左侧数字部分的长度,为光标位置的差。 int diff = (seloldtext.mid(0, removepos).remove(QRegExp("[+-×÷/,%()\\s]")).length()) - m_inputEdit->text().mid(0, removepos).remove(QRegExp("[+-×÷/,%()\\s]")).length(); if (0 == diff) { m_inputEdit->setCursorPosition(removepos); } else { m_inputEdit->setCursorPosition(removepos + diff); } } /** * @brief ProExpressionBar::curposInNumber * @param curpos:当前光标 * 判断当前光标是否在数字前或数字内,用于输入not,+/-时禁止输入 */ bool ProExpressionBar::curposInNumber(int curpos) { if (m_inputEdit->text().length() <= curpos) { return false; } if (isnumber(m_inputEdit->text().at(curpos))) { if (curpos < m_inputEdit->text().length() - 1 && m_inputEdit->text().at(curpos) == " " && !isnumber(m_inputEdit->text().at(curpos + 1))) { return false; } else { return true; } } return false; } void ProExpressionBar::handleTextChanged() { m_isAllClear = false; m_isContinue = true; } /** * @brief ProExpressionBar::separateChange * 数字间隔位数发生改变 */ void ProExpressionBar::onSeparateChange() { m_listModel->updataOfSeparate(); } deepin-calculator-5.7.21/src/widgets/proexpressionbar.h000066400000000000000000000062401423020056600232140ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROEXPRESSIONBAR_H #define PROEXPRESSIONBAR_H #include "inputedit.h" #include "../views/simplelistview.h" #include "../views/simplelistmodel.h" #include "../views/simplelistdelegate.h" #include #include #include DWIDGET_USE_NAMESPACE class ProExpressionBar : public DWidget { Q_OBJECT public: explicit ProExpressionBar(QWidget *parent = nullptr); ~ProExpressionBar(); void mouseMoveEvent(QMouseEvent *event); InputEdit *getInputEdit(); bool isnumber(QChar a); bool judgeinput(); signals: // void keyPress(QKeyEvent *); void clearStateChanged(bool); void keyPress(QKeyEvent *); public slots: //输入事件 void enterNumberEvent(const QString &text); void enterSymbolEvent(const QString &text); void enterBackspaceEvent(); void enterClearEvent(); void enterEqualEvent(); // void enterModEvent(); void enterNotEvent(); void enterOperatorEvent(const QString &text); void enterOppositeEvent(); void enterLeftBracketsEvent(); void enterRightBracketsEvent(); void moveLeft(); void moveRight(); void initTheme(int type); void revisionResults(const QModelIndex &index); void addUndo(); void copyResultToClipboard(); void copyClipboard2Result(); void allElection(); void shear(); void deleteText(); void Undo(); void Redo(); void setResultFalse(); private: void initConnect(); void replaceSelection(QString text); QString symbolComplement(const QString exp); bool cursorPosAtEnd(); bool isOperator(const QString &text); void expressionCheck(); QString symbolFaultTolerance(const QString &text); bool isNumberOutOfRange(const QString &text); void selectedPartDelete(const QRegExp &rx); bool curposInNumber(int curpos); void onSeparateChange();//数字将位数发生改变 private slots: void handleTextChanged(); private: Evaluator *m_evaluator; SimpleListView *m_listView; SimpleListDelegate *m_listDelegate; SimpleListModel *m_listModel; InputEdit *m_inputEdit; bool m_isContinue; bool m_isAllClear; bool m_isResult; //计算结果 bool m_inputNumber; //输入数字 bool m_isUndo; QVector m_undo; QVector m_redo; QList m_funclist; //支持的函数 QString m_expression = QString(); QVector m_numvec; }; #endif // PROEXPRESSIONBAR_H deepin-calculator-5.7.21/src/widgets/programmodule.cpp000066400000000000000000001636441423020056600230330ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "programmodule.h" #include "probitwidget.h" #include "../../3rdparty/core/settings.h" #include #include #include const int EXPRESSIONBAR_HEIGHT = 95; ProgramModule::ProgramModule(QWidget *parent) : DWidget(parent) , m_proExpressionBar(new ProExpressionBar(this)) , m_proListView(new ProListView(this)) , m_proListModel(new ProListModel(this)) , m_proListDelegate(new ProListDelegate(this)) , m_checkBtnKeypad(new ProCheckBtnKeypad(this)) , m_programmerKeypad(new ProgrammerKeypad(this)) , m_proSystemKeypad(new ProSystemKeypad(this)) , m_stackWidget(new QStackedWidget(this)) , m_byteArrowRectangle(new ArrowRectangle(DArrowRectangle::ArrowTop, DArrowRectangle::FloatWidget, this)) , m_byteArrowListWidget(new MemoryListWidget(this, true)) , m_byteProgrammerArrowDelegate(new ProgrammerArrowDelegate(this)) , m_shiftArrowRectangle(new ArrowRectangle(DArrowRectangle::ArrowTop, DArrowRectangle::FloatWidget, this)) , m_shiftArrowListWidget(new MemoryListWidget(this, true)) , m_shiftProgrammerArrowDelegate(new ProgrammerArrowDelegate(this)) { m_memoryPublic = MemoryPublic::instance(); m_memorylistwidget = m_memoryPublic->getwidget(MemoryPublic::programmerleft); m_proExpressionBar->setFixedHeight(EXPRESSIONBAR_HEIGHT); m_proListView->setModel(m_proListModel); m_proListView->setItemDelegate(m_proListDelegate); m_proListView->setCurrentIndex(m_proListModel->index(1, 0)); m_stackWidget->addWidget(m_programmerKeypad); m_stackWidget->addWidget(m_proSystemKeypad); m_stackWidget->addWidget(m_memorylistwidget); m_stackWidget->setCurrentWidget(m_programmerKeypad); m_stackWidget->setFixedSize(451, 279); initArrowRectangle(); QVBoxLayout *vlay = new QVBoxLayout(this); vlay->addWidget(m_proExpressionBar); vlay->addWidget(m_proListView); vlay->addWidget(m_checkBtnKeypad); vlay->addWidget(m_stackWidget); vlay->setSpacing(0); vlay->setMargin(0); vlay->setContentsMargins(0, 0, 0, 0); //主题变换事件 connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &ProgramModule::checkBtnKeypadThemeChange); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_programmerKeypad, &ProgrammerKeypad::buttonThemeChanged); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_proListDelegate, &ProListDelegate::setThemeType); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_proExpressionBar, &ProExpressionBar::initTheme); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_memoryPublic, &MemoryPublic::setThemeType); //数字键盘事件--鼠标点击、键盘交互、键盘输入 connect(m_checkBtnKeypad, &ProCheckBtnKeypad::buttonPressed, this, &ProgramModule::handleKeypadButtonPress); connect(m_checkBtnKeypad, &ProCheckBtnKeypad::buttonPressedbySpace, this, &ProgramModule::handleKeypadButtonPressByspace); connect(m_programmerKeypad, &ProgrammerKeypad::buttonPressed, this, &ProgramModule::handleKeypadButtonPress); connect(m_programmerKeypad, &ProgrammerKeypad::buttonPressedbySpace, this, &ProgramModule::handleKeypadButtonPressByspace); connect(m_proExpressionBar, &ProExpressionBar::keyPress, this, &ProgramModule::handleEditKeyPress); connect(m_proSystemKeypad, &ProSystemKeypad::bitbuttonclicked, this, [ = ]() { m_proExpressionBar->getInputEdit()->setFocus(); }); //进制列表点击事件 connect(m_proListView, &ProListView::obtainingHistorical, this, &ProgramModule::radixListChange); //输入栏交互 connect(m_proExpressionBar->getInputEdit(), &InputEdit::cursorPositionNumberChanged, m_proSystemKeypad, &ProSystemKeypad::setvalue); connect(m_proSystemKeypad, &ProSystemKeypad::valuechanged, m_proExpressionBar->getInputEdit(), &InputEdit::valueChangeFromProSyskeypad); connect(m_proSystemKeypad, &ProSystemKeypad::longbitcut, [ = ](Quantity ans) { m_proExpressionBar->findChild()->answerOutOfRange(ans); }); connect(m_proExpressionBar, &ProExpressionBar::clearStateChanged, this, &ProgramModule::handleClearStateChanged); connect(m_proExpressionBar->getInputEdit(), &InputEdit::prolistAns, this, [ = ](QPair pair) { if (pair.first) { m_proListModel->updataList(pair.second); } else { m_proListModel->clearItems(); } }); //内存列表事件 connect(m_memorylistwidget, &MemoryWidget::widgetplus, this, [ = ](int row) { m_proExpressionBar->enterEqualEvent(); if (m_proExpressionBar->getInputEdit()->getCurrentAns().first) m_memoryPublic->widgetplus(row, m_proExpressionBar->getInputEdit()->getCurrentAns().second); }); connect(m_memorylistwidget, &MemoryWidget::widgetminus, this, [ = ](int row) { m_proExpressionBar->enterEqualEvent(); if (m_proExpressionBar->getInputEdit()->getCurrentAns().first) m_memoryPublic->widgetminus(row, m_proExpressionBar->getInputEdit()->getCurrentAns().second); }); if (!m_memoryPublic->isEmpty()) mAvailableEvent(); else mUnAvailableEvent(); connect(m_memorylistwidget, &MemoryWidget::insidewidget, this, [ = ]() { m_insidewidget = true; }); connect(m_memoryPublic, &MemoryPublic::memorycleanSig, this, &ProgramModule::mUnAvailableEvent); connect(m_memoryPublic, &MemoryPublic::generateDataSig, this, &ProgramModule::mAvailableEvent); connect(m_memorylistwidget, &MemoryWidget::itemclick, this, [ = ](const QPair p) { QString str = p.first; m_proExpressionBar->getInputEdit()->setAnswer(str.remove("\n"), p.second); m_proExpressionBar->getInputEdit()->setFocus(); //点击item清除键状态改变 this->handleClearStateChanged(false); if (m_stackWidget->currentIndex() == 2) { m_stackWidget->setCurrentIndex(m_stackwidgetLastIndex); setwidgetAttribute(false); MemoryButton *btn = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_MS)); btn->setEnabled(true); btn->setbuttongray(false); MemoryButton *btn1 = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Mlist)); btn1->setEnabled(true); btn1->setbtnlight(false); m_memCalbtn = true; m_isallgray = false; } }); connect(m_proExpressionBar->getInputEdit(), &InputEdit::emptyExpression, this, [ = ](bool b) { if (b == false) { MemoryButton *btn = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_MS)); btn->setEnabled(true); m_memCalbtn = true; m_memorylistwidget->expressionempty(b); } else { MemoryButton *btn = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_MS)); btn->setEnabled(false); m_memCalbtn = false; m_memorylistwidget->expressionempty(b); } }); connect(m_memorylistwidget, &MemoryWidget::hideWidget, this, &ProgramModule::closeListWidget); } ProgramModule::~ProgramModule() { } /** * @brief mainwindow焦点不在basicmodul时也触发keypress */ void ProgramModule::setKeyPress(QKeyEvent *e) { handleEditKeyPress(e); } void ProgramModule::mouseMoveEvent(QMouseEvent *event) { Q_UNUSED(event); } void ProgramModule::mousePressEvent(QMouseEvent *event) { m_byteArrowRectangle->setHidden(true); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_System))->setBtnPressing(false); m_shiftArrowRectangle->setHidden(true); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))->setBtnPressing(false); closeListWidget(); setwidgetAttribute(false); DWidget::mousePressEvent(event); } void ProgramModule::handleKeypadButtonPress(int key) { QString path; if (DGuiApplicationHelper::instance()->themeType() == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); m_checkBtnKeypad->update(); m_programmerKeypad->update(); bool pagefocus = false; QPair p; switch (key) { case ProCheckBtnKeypad::Key_GeneralKeypad: //点击后设置Key_GeneralKeypad为点击状态,Key_BinaryKeypad为普通状态 static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))-> setIconUrl(path + "icon_generalkeyboard_press.svg", path + "icon_generalkeyboard_hover.svg", path + "icon_generalkeyboard_press.svg", 3); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_BinaryKeypad))-> setIconUrl(path + "icon_binarysystem_normal.svg", path + "icon_binarysystem_hover.svg", path + "icon_binarysystem_press.svg", 3); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))->setBtnHighlight(true); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_BinaryKeypad))->setBtnHighlight(false); m_stackWidget->setCurrentWidget(m_programmerKeypad); break; case ProCheckBtnKeypad::Key_BinaryKeypad: //点击后设置Key_BinaryKeypad为点击状态,Key_GeneralKeypad为普通状态 static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_BinaryKeypad))-> setIconUrl(path + "icon_binarysystem_press.svg", path + "icon_binarysystem_hover.svg", path + "icon_binarysystem_press.svg", 3); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))-> setIconUrl(path + "icon_generalkeyboard_normal.svg", path + "icon_generalkeyboard_hover.svg", path + "icon_generalkeyboard_press.svg", 3); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))->setBtnHighlight(false); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_BinaryKeypad))->setBtnHighlight(true); m_stackWidget->setCurrentWidget(m_proSystemKeypad); break; case ProCheckBtnKeypad::Key_System: static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_System))->setBtnPressing(true); m_byteArrowRectangle->setHidden(false); setwidgetAttribute(true); m_byteArrowRectangle->setFocus(Qt::MouseFocusReason); pagefocus = true; break; case ProCheckBtnKeypad::Key_Option: static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))->setBtnPressing(true); resetArrowWidth(); m_shiftArrowRectangle->setHidden(false); setwidgetAttribute(true); m_shiftArrowRectangle->setFocus(Qt::MouseFocusReason); pagefocus = true; break; case ProCheckBtnKeypad::Key_Mlist: showListWidget(); if (m_stackWidget->currentIndex() == 2) { setwidgetAttribute(true); } else { setwidgetAttribute(false); } m_memorylistwidget->setFocus(Qt::MouseFocusReason); pagefocus = true; break; case ProCheckBtnKeypad::Key_MS: m_proExpressionBar->enterEqualEvent(); if (m_proExpressionBar->getInputEdit()->getCurrentAns().first) m_memoryPublic->generateData(m_proExpressionBar->getInputEdit()->getCurrentAns().second); break; case ProgrammerKeypad::Key_0: m_proExpressionBar->enterNumberEvent("0"); //按键0事件 break; case ProgrammerKeypad::Key_1: m_proExpressionBar->enterNumberEvent("1"); break; case ProgrammerKeypad::Key_2: m_proExpressionBar->enterNumberEvent("2"); break; case ProgrammerKeypad::Key_3: m_proExpressionBar->enterNumberEvent("3"); break; case ProgrammerKeypad::Key_4: m_proExpressionBar->enterNumberEvent("4"); break; case ProgrammerKeypad::Key_5: m_proExpressionBar->enterNumberEvent("5"); break; case ProgrammerKeypad::Key_6: m_proExpressionBar->enterNumberEvent("6"); break; case ProgrammerKeypad::Key_7: m_proExpressionBar->enterNumberEvent("7"); break; case ProgrammerKeypad::Key_8: m_proExpressionBar->enterNumberEvent("8"); break; case ProgrammerKeypad::Key_9: m_proExpressionBar->enterNumberEvent("9"); break; case ProgrammerKeypad::Key_A: m_proExpressionBar->enterNumberEvent("A"); break; case ProgrammerKeypad::Key_B: m_proExpressionBar->enterNumberEvent("B"); break; case ProgrammerKeypad::Key_C: m_proExpressionBar->enterNumberEvent("C"); break; case ProgrammerKeypad::Key_D: m_proExpressionBar->enterNumberEvent("D"); break; case ProgrammerKeypad::Key_E: m_proExpressionBar->enterNumberEvent("E"); break; case ProgrammerKeypad::Key_F: m_proExpressionBar->enterNumberEvent("F"); break; case ProgrammerKeypad::Key_Plus: m_proExpressionBar->enterSymbolEvent("+"); break; case ProgrammerKeypad::Key_Min: m_proExpressionBar->enterSymbolEvent("-"); break; case ProgrammerKeypad::Key_Mult: m_proExpressionBar->enterSymbolEvent("*"); break; case ProgrammerKeypad::Key_Div: m_proExpressionBar->enterSymbolEvent("/"); break; case ProgrammerKeypad::Key_percent: m_proExpressionBar->enterOperatorEvent("%"); break; case ProgrammerKeypad::Key_equal: m_proExpressionBar->enterEqualEvent(); break; case ProgrammerKeypad::Key_Clear: m_proExpressionBar->enterClearEvent(); break; case ProgrammerKeypad::Key_Backspace: m_proExpressionBar->enterBackspaceEvent(); break; case ProgrammerKeypad::Key_leftBracket: m_proExpressionBar->enterLeftBracketsEvent(); break; case ProgrammerKeypad::Key_rightBracket: m_proExpressionBar->enterRightBracketsEvent(); break; case ProgrammerKeypad::Key_AND: m_proExpressionBar->enterOperatorEvent("and"); break; case ProgrammerKeypad::Key_OR: m_proExpressionBar->enterOperatorEvent("or"); break; case ProgrammerKeypad::Key_NOT: m_proExpressionBar->enterNotEvent(); break; case ProgrammerKeypad::Key_XOR: m_proExpressionBar->enterOperatorEvent("xor"); break; case ProgrammerKeypad::Key_NAND: m_proExpressionBar->enterOperatorEvent("nand"); break; case ProgrammerKeypad::Key_NOR: m_proExpressionBar->enterOperatorEvent("nor"); break; case ProgrammerKeypad::Key_moveL: switch (m_shiftArrowCurrentRow) { case 0: m_proExpressionBar->enterOperatorEvent("sal"); break; case 1: m_proExpressionBar->enterOperatorEvent("shl"); break; case 2: m_proExpressionBar->enterOperatorEvent("rol"); break; case 3: m_proExpressionBar->enterOperatorEvent("rcl"); break; default: m_proExpressionBar->enterOperatorEvent("sal"); break; } break; case ProgrammerKeypad::Key_moveR: switch (m_shiftArrowCurrentRow) { case 0: m_proExpressionBar->enterOperatorEvent("sar"); break; case 1: m_proExpressionBar->enterOperatorEvent("shr"); break; case 2: m_proExpressionBar->enterOperatorEvent("ror"); break; case 3: m_proExpressionBar->enterOperatorEvent("rcr"); break; default: m_proExpressionBar->enterOperatorEvent("sar"); break; } break; case ProgrammerKeypad::Key_opposite: m_proExpressionBar->enterOppositeEvent(); break; default: break; } if (!pagefocus) m_proExpressionBar->getInputEdit()->setFocus(); int left = 0; int right = 0; QString text = m_proExpressionBar->getInputEdit()->text(); for (int i = 0; i < text.length(); i++) { if (text[i] == "(") left ++; else if (text[i] == ")") { if (left > 0) left--; else right++; } } m_programmerKeypad->bracketsNum(0, QString::number(left)); //写入左右括号不匹配数 m_programmerKeypad->bracketsNum(1, QString::number(right)); } void ProgramModule::handleKeypadButtonPressByspace(int key) { QString path; if (DGuiApplicationHelper::instance()->themeType() == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); m_checkBtnKeypad->update(); m_programmerKeypad->update(); if (key > 39 && key < 42) m_checkBtnKeypad->animate(ProCheckBtnKeypad::Buttons(key), true); else if (key <= 35) m_programmerKeypad->animate(ProgrammerKeypad::Buttons(key), true); switch (key) { case ProCheckBtnKeypad::Key_GeneralKeypad: //点击后设置Key_GeneralKeypad为点击状态,Key_BinaryKeypad为普通状态 static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))-> setIconUrl(path + "icon_generalkeyboard_press.svg", path + "icon_generalkeyboard_hover.svg", path + "icon_generalkeyboard_press.svg", 3); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_BinaryKeypad))-> setIconUrl(path + "icon_binarysystem_normal.svg", path + "icon_binarysystem_hover.svg", path + "icon_binarysystem_normal.svg", 3); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))->setBtnHighlight(true); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_BinaryKeypad))->setBtnHighlight(false); m_stackWidget->setCurrentWidget(m_programmerKeypad); break; case ProCheckBtnKeypad::Key_BinaryKeypad: //点击后设置Key_BinaryKeypad为点击状态,Key_GeneralKeypad为普通状态 static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_BinaryKeypad))-> setIconUrl(path + "icon_binarysystem_press.svg", path + "icon_binarysystem_hover.svg", path + "icon_binarysystem_press.svg", 3); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))-> setIconUrl(path + "icon_generalkeyboard_normal.svg", path + "icon_generalkeyboard_hover.svg", path + "icon_generalkeyboard_normal.svg", 3); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))->setBtnHighlight(false); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_BinaryKeypad))->setBtnHighlight(true); m_stackWidget->setCurrentWidget(m_proSystemKeypad); break; case ProCheckBtnKeypad::Key_System: static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_System))->setBtnPressing(true); m_byteArrowRectangle->setHidden(false); setwidgetAttribute(true); m_byteArrowRectangle->setFocus(Qt::TabFocusReason); break; case ProCheckBtnKeypad::Key_Option: static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))->setBtnPressing(true); resetArrowWidth(); m_shiftArrowRectangle->setHidden(false); setwidgetAttribute(true); m_shiftArrowRectangle->setFocus(Qt::TabFocusReason); break; case ProCheckBtnKeypad::Key_Mlist: showListWidget(); if (m_stackWidget->currentIndex() == 2) { setwidgetAttribute(true); } else { setwidgetAttribute(false); } m_memorylistwidget->setFocus(Qt::TabFocusReason); break; case ProCheckBtnKeypad::Key_MS: m_proExpressionBar->enterEqualEvent(); if (m_proExpressionBar->getInputEdit()->getCurrentAns().first) m_memoryPublic->generateData(m_proExpressionBar->getInputEdit()->getCurrentAns().second); break; case ProgrammerKeypad::Key_0: m_proExpressionBar->enterNumberEvent("0"); //按键0事件 break; case ProgrammerKeypad::Key_1: m_proExpressionBar->enterNumberEvent("1"); break; case ProgrammerKeypad::Key_2: m_proExpressionBar->enterNumberEvent("2"); break; case ProgrammerKeypad::Key_3: m_proExpressionBar->enterNumberEvent("3"); break; case ProgrammerKeypad::Key_4: m_proExpressionBar->enterNumberEvent("4"); break; case ProgrammerKeypad::Key_5: m_proExpressionBar->enterNumberEvent("5"); break; case ProgrammerKeypad::Key_6: m_proExpressionBar->enterNumberEvent("6"); break; case ProgrammerKeypad::Key_7: m_proExpressionBar->enterNumberEvent("7"); break; case ProgrammerKeypad::Key_8: m_proExpressionBar->enterNumberEvent("8"); break; case ProgrammerKeypad::Key_9: m_proExpressionBar->enterNumberEvent("9"); break; case ProgrammerKeypad::Key_A: m_proExpressionBar->enterNumberEvent("A"); break; case ProgrammerKeypad::Key_B: m_proExpressionBar->enterNumberEvent("B"); break; case ProgrammerKeypad::Key_C: m_proExpressionBar->enterNumberEvent("C"); break; case ProgrammerKeypad::Key_D: m_proExpressionBar->enterNumberEvent("D"); break; case ProgrammerKeypad::Key_E: m_proExpressionBar->enterNumberEvent("E"); break; case ProgrammerKeypad::Key_F: m_proExpressionBar->enterNumberEvent("F"); break; case ProgrammerKeypad::Key_Plus: m_proExpressionBar->enterSymbolEvent("+"); break; case ProgrammerKeypad::Key_Min: m_proExpressionBar->enterSymbolEvent("-"); break; case ProgrammerKeypad::Key_Mult: m_proExpressionBar->enterSymbolEvent("*"); break; case ProgrammerKeypad::Key_Div: m_proExpressionBar->enterSymbolEvent("/"); break; case ProgrammerKeypad::Key_percent: m_proExpressionBar->enterOperatorEvent("%"); break; case ProgrammerKeypad::Key_equal: m_proExpressionBar->enterEqualEvent(); break; case ProgrammerKeypad::Key_Clear: m_proExpressionBar->enterClearEvent(); break; case ProgrammerKeypad::Key_Backspace: m_proExpressionBar->enterBackspaceEvent(); break; case ProgrammerKeypad::Key_leftBracket: m_proExpressionBar->enterLeftBracketsEvent(); break; case ProgrammerKeypad::Key_rightBracket: m_proExpressionBar->enterRightBracketsEvent(); break; case ProgrammerKeypad::Key_AND: m_proExpressionBar->enterOperatorEvent("and"); break; case ProgrammerKeypad::Key_OR: m_proExpressionBar->enterOperatorEvent("or"); break; case ProgrammerKeypad::Key_NOT: m_proExpressionBar->enterNotEvent(); break; case ProgrammerKeypad::Key_XOR: m_proExpressionBar->enterOperatorEvent("xor"); break; case ProgrammerKeypad::Key_NAND: m_proExpressionBar->enterOperatorEvent("nand"); break; case ProgrammerKeypad::Key_NOR: m_proExpressionBar->enterOperatorEvent("nor"); break; case ProgrammerKeypad::Key_moveL: switch (m_shiftArrowCurrentRow) { case 0: m_proExpressionBar->enterOperatorEvent("sal"); break; case 1: m_proExpressionBar->enterOperatorEvent("shl"); break; case 2: m_proExpressionBar->enterOperatorEvent("rol"); break; case 3: m_proExpressionBar->enterOperatorEvent("rcl"); break; default: m_proExpressionBar->enterOperatorEvent("sal"); break; } break; case ProgrammerKeypad::Key_moveR: switch (m_shiftArrowCurrentRow) { case 0: m_proExpressionBar->enterOperatorEvent("sar"); break; case 1: m_proExpressionBar->enterOperatorEvent("shr"); break; case 2: m_proExpressionBar->enterOperatorEvent("ror"); break; case 3: m_proExpressionBar->enterOperatorEvent("rcr"); break; default: m_proExpressionBar->enterOperatorEvent("sar"); break; } break; case ProgrammerKeypad::Key_opposite: m_proExpressionBar->enterOppositeEvent(); break; default: break; } int left = 0; int right = 0; QString text = m_proExpressionBar->getInputEdit()->text(); for (int i = 0; i < text.length(); i++) { if (text[i] == "(") left ++; else if (text[i] == ")") { if (left > 0) left--; else right++; } } m_programmerKeypad->bracketsNum(0, QString::number(left)); //写入左右括号不匹配数 m_programmerKeypad->bracketsNum(1, QString::number(right)); } /** * @brief 算法悬浮框点击事件 */ void ProgramModule::shiftArrowListWidgetItemClicked(int row, bool isselect) { QString path; if (DGuiApplicationHelper::instance()->themeType() == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); //松开时与点击的不是同一行,则需要隐藏掉刚刚点击行的勾的显示 if (!isselect && m_shiftArrowPressRow > -1) { if (m_shiftArrowPressRow != m_shiftArrowCurrentRow) static_cast(m_shiftArrowListWidget->itemWidget(m_shiftArrowListWidget->item(m_shiftArrowPressRow)))->isMarkHide(true); } else { m_shiftArrowListWidget->setCurrentRow(row); static_cast(m_shiftArrowListWidget->itemWidget(m_shiftArrowListWidget->item(m_shiftArrowCurrentRow)))->isMarkHide(true); static_cast(m_shiftArrowListWidget->itemWidget(m_shiftArrowListWidget->currentItem()))->isMarkHide(false); m_shiftArrowRectangle->setHidden(true); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))->setBtnPressing(false); setwidgetAttribute(false); //计算方式选项按钮图标跟随选项改变 switch (m_shiftArrowListWidget->currentRow()) { case 0: static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))-> setIconUrl(path + "icon_as_iconnormal.svg", path + "icon_as_iconhover.svg", path + "icon_as_iconnormal.svg", 5); break; case 1: static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))-> setIconUrl(path + "icon_ls_iconnormal.svg", path + "icon_ls_iconhover.svg", path + "icon_ls_iconnormal.svg", 3); break; case 2: static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))-> setIconUrl(path + "icon_ro_iconnormal.svg", path + "icon_ro_iconhover.svg", path + "icon_ro_iconnormal.svg", 5); break; case 3: static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))-> setIconUrl(path + "icon_rc_iconnormal.svg", path + "icon_rc_iconhover.svg", path + "icon_rc_iconnormal.svg", 3); break; } m_shiftArrowCurrentRow = row; } } /** * @brief ProgramModule::shiftArrowListWidgetItemSpace * focus后空格点击 */ void ProgramModule::shiftArrowListWidgetItemSpace() { shiftArrowListWidgetItemClicked(m_shiftArrowListWidget->currentRow(), true); } /** * @brief ProgramModule::shiftArrowListWidgetItemPressed * 移位运算列表press事件 */ void ProgramModule::shiftArrowListWidgetItemPressed(int row) { static_cast(m_shiftArrowListWidget->itemWidget(m_shiftArrowListWidget->item(row)))->isMarkHide(false); m_shiftArrowPressRow = row; } /** * @brief 位数悬浮框点击事件 */ void ProgramModule::byteArrowListWidgetItemClicked(int row, bool isselect) { //松开时与点击的不是同一行,则需要隐藏掉刚刚点击行的勾的显示 if (!isselect && m_byteArrowPressRow > -1) { if (m_byteArrowPressRow != m_byteArrowCurrentRow) static_cast(m_byteArrowListWidget->itemWidget(m_byteArrowListWidget->item(m_byteArrowPressRow)))->isMarkHide(true); } else { m_byteArrowListWidget->setCurrentRow(row); static_cast(m_byteArrowListWidget->itemWidget(m_byteArrowListWidget->item(m_byteArrowCurrentRow)))->isMarkHide(true); static_cast(m_byteArrowListWidget->itemWidget(m_byteArrowListWidget->currentItem()))->isMarkHide(false); QString str = static_cast(m_byteArrowListWidget->itemWidget(m_byteArrowListWidget->currentItem()))->findChild()->text(); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_System))->setText(str); m_byteArrowRectangle->setHidden(true); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_System))->setBtnPressing(false); setwidgetAttribute(false); int oldsystem; switch (m_byteArrowCurrentRow) { case 0: oldsystem = 64; break; case 1: oldsystem = 32; break; case 2: oldsystem = 16; break; case 3: oldsystem = 8; break; default: oldsystem = 64; break; } //改变m_proSystemKeypad按钮状态 switch (m_byteArrowListWidget->currentRow()) { case 0: Settings::instance()->proBitLength = 64; m_proSystemKeypad->setSystem(64, oldsystem); break; case 1: Settings::instance()->proBitLength = 32; m_proSystemKeypad->setSystem(32, oldsystem); break; case 2: Settings::instance()->proBitLength = 16; m_proSystemKeypad->setSystem(16, oldsystem); break; case 3: Settings::instance()->proBitLength = 8; m_proSystemKeypad->setSystem(8, oldsystem); break; } m_byteArrowCurrentRow = row; m_proExpressionBar->findChild()->expOutofRange(); } } /** * @brief ProgramModule::byteArrowListWidgetItemSpace * focus后空格点击 */ void ProgramModule::byteArrowListWidgetItemSpace() { byteArrowListWidgetItemClicked(m_byteArrowListWidget->currentRow(), true); } /** * @brief ProgramModule::byteArrowListWidgetItemPressed * @param row:行号 * 数据长度列表点击事件 */ void ProgramModule::byteArrowListWidgetItemPressed(int row) { static_cast(m_byteArrowListWidget->itemWidget(m_byteArrowListWidget->item(row)))->isMarkHide(false); m_byteArrowPressRow = row; } /** * @brief 主题变换checkBtnKeypad切换图片 */ void ProgramModule::checkBtnKeypadThemeChange(int type) { QString path; if (DGuiApplicationHelper::instance()->themeType() == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); m_checkBtnKeypad->buttonThemeChanged(type); } /** * @brief ProgramModule::radixListChange * @param index:点击索引 * @param isspace:是否键盘交互 * 进制列表的点击事件 */ void ProgramModule::radixListChange(const QModelIndex &index, bool isspace) { // QString text = index.data(SimpleListModel::ExpressionWithOutTip).toString(); // m_proExpressionBar->getInputEdit()->setText(text); if (!isspace) m_proExpressionBar->getInputEdit()->setFocus(); m_programmerKeypad->radixChanged(index.row()); int oldbase = Settings::instance()->programmerBase; switch (index.row()) { case 0: Settings::instance()->programmerBase = 16; break; case 1: Settings::instance()->programmerBase = 10; break; case 2: Settings::instance()->programmerBase = 8; break; case 3: Settings::instance()->programmerBase = 2; break; default: Settings::instance()->programmerBase = 10; break; } m_proExpressionBar->getInputEdit()->radixChanged(oldbase, Settings::instance()->programmerBase); m_proExpressionBar->findChild()->radixChanged(oldbase, Settings::instance()->programmerBase); } /** * @brief 向内存中存入数据时触发 */ void ProgramModule::mAvailableEvent() { m_avail = true; MemoryButton *btn = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Mlist)); btn->setEnabled(true); } void ProgramModule::mUnAvailableEvent() { m_avail = false; if (m_stackWidget->currentIndex() < 2) { MemoryButton *btn = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Mlist)); btn->setEnabled(false); } } void ProgramModule::showListWidget() { if (m_stackWidget->currentIndex() != 2) { m_stackwidgetLastIndex = m_stackWidget->currentIndex(); m_stackWidget->setCurrentIndex(2); MemoryButton *btn = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_MS)); btn->setbuttongray(true); btn->setEnabled(false); MemoryButton *btn1 = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Mlist)); btn1->updateWhenBtnDisable(); btn1->setbtnlight(true); btn1->setEnabled(false); m_isallgray = true; m_memorylistwidget->resetAllLabelByBase(); } } void ProgramModule::closeListWidget() { //内存界面显示时,点击内存界面以外部分切换内存界面为键盘界面 if (m_stackWidget->currentIndex() == 2 && m_insidewidget == false) { m_stackWidget->setCurrentIndex(m_stackwidgetLastIndex); MemoryButton *btn = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_MS)); btn->setbuttongray(false); btn->setEnabled(true); MemoryButton *btn1 = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Mlist)); btn1->setbtnlight(false); btn1->setEnabled(true); m_isallgray = false; setwidgetAttribute(false); m_proExpressionBar->getInputEdit()->setFocus(); } if (!m_avail) { MemoryButton *btn2 = static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Mlist)); btn2->setEnabled(false); } m_insidewidget = false; m_proExpressionBar->getInputEdit()->isExpressionEmpty(); //确认输入栏是否有内容,发送信号M+,M-,MS是否置灰 } void ProgramModule::initArrowRectangle() { QString path; if (DGuiApplicationHelper::instance()->themeType() == 2) path = QString(":/assets/images/%1/").arg("dark"); else path = QString(":/assets/images/%1/").arg("light"); m_shiftArrowListWidget->setItemDelegate(m_shiftProgrammerArrowDelegate); m_shiftArrowListWidget->setFrameShape(QFrame::NoFrame); //设置边框类型,无边框 m_shiftArrowListWidget->setAttribute(Qt::WA_TranslucentBackground, true); QFont font; font.setPixelSize(14); font.setWeight(2); QFontMetrics fm(font); int width = fm.boundingRect(tr("Rotate through carry circular shift")).width(); int itemwidth = width > 170 ? (width + 80) : 250; QListWidgetItem *item1 = new QListWidgetItem(); ProgrammerItemWidget *itemwidget1 = new ProgrammerItemWidget(tr("Arithmetic shift"), itemwidth, path + "icon_as_normal.svg"); item1->setFlags(Qt::NoItemFlags); item1->setSizeHint(QSize(itemwidth, 34)); m_shiftArrowListWidget->insertItem(0, item1); m_shiftArrowListWidget->setItemWidget(item1, itemwidget1); QListWidgetItem *item2 = new QListWidgetItem(); ProgrammerItemWidget *itemwidget2 = new ProgrammerItemWidget(tr("Logical shift"), itemwidth, path + "icon_ls_normal.svg"); item2->setFlags(Qt::NoItemFlags); item2->setSizeHint(QSize(itemwidth, 34)); m_shiftArrowListWidget->insertItem(1, item2); m_shiftArrowListWidget->setItemWidget(item2, itemwidget2); QListWidgetItem *item3 = new QListWidgetItem(); ProgrammerItemWidget *itemwidget3 = new ProgrammerItemWidget(tr("Circular shift"), itemwidth, path + "icon_ro_normal.svg"); item3->setFlags(Qt::NoItemFlags); item3->setSizeHint(QSize(itemwidth, 34)); m_shiftArrowListWidget->insertItem(2, item3); m_shiftArrowListWidget->setItemWidget(item3, itemwidget3); QListWidgetItem *item4 = new QListWidgetItem(); ProgrammerItemWidget *itemwidget4 = new ProgrammerItemWidget(tr("Rotate through carry circular shift"), itemwidth, path + "icon_rc_normal.svg"); item4->setFlags(Qt::NoItemFlags); item4->setSizeHint(QSize(itemwidth, 34)); m_shiftArrowListWidget->insertItem(3, item4); m_shiftArrowListWidget->setItemWidget(item4, itemwidget4); //默认计算方式为算术移位 m_shiftArrowListWidget->setCurrentItem(m_shiftArrowListWidget->item(0)); static_cast(m_shiftArrowListWidget->itemWidget(m_shiftArrowListWidget->currentItem())) ->isMarkHide(false); // m_shiftArrowListWidget->setFixedSize(QSize(itemwidth, 136)); // m_shiftArrowRectangle->setWindowFlag(Qt::Popup); m_shiftArrowRectangle->setRadius(15); m_shiftArrowRectangle->setArrowWidth(48); m_shiftArrowRectangle->setArrowHeight(21); m_shiftArrowRectangle->setContent(m_shiftArrowListWidget); m_shiftArrowListWidget->installEventFilter(m_shiftArrowRectangle); // m_shiftArrowRectangle->move(this->rect().x() + 273, this->rect().y() + 238);//在module的138,238位置,x多出150原因未找出 // m_shiftArrowListWidget->move(m_shiftArrowRectangle->rect().x() + 15, // m_shiftArrowRectangle->rect().y() + m_shiftArrowRectangle->arrowHeight() + 11); // m_shiftArrowRectangle->setFixedWidth(itemwidth + 30); m_shiftArrowRectangle->setShadowXOffset(0); m_shiftArrowRectangle->setShadowYOffset(0); m_shiftArrowRectangle->setShadowBlurRadius(15); m_shiftArrowRectangle->setHeight(191); m_shiftArrowRectangle->setHidden(true); m_byteArrowListWidget->setItemDelegate(m_byteProgrammerArrowDelegate); m_byteArrowListWidget->setFrameShape(QFrame::NoFrame); //设置边框类型,无边框 m_byteArrowListWidget->setAttribute(Qt::WA_TranslucentBackground, true); QListWidgetItem *item5 = new QListWidgetItem(); ProgrammerItemWidget *itemwidget5 = new ProgrammerItemWidget("QWORD"); item5->setFlags(Qt::NoItemFlags); item5->setSizeHint(QSize(182, 34)); m_byteArrowListWidget->insertItem(0, item5); m_byteArrowListWidget->setItemWidget(item5, itemwidget5); QListWidgetItem *item6 = new QListWidgetItem(); ProgrammerItemWidget *itemwidget6 = new ProgrammerItemWidget("DWORD"); item6->setFlags(Qt::NoItemFlags); item6->setSizeHint(QSize(182, 34)); m_byteArrowListWidget->insertItem(1, item6); m_byteArrowListWidget->setItemWidget(item6, itemwidget6); QListWidgetItem *item7 = new QListWidgetItem(); ProgrammerItemWidget *itemwidget7 = new ProgrammerItemWidget("WORD"); item7->setFlags(Qt::NoItemFlags); item7->setSizeHint(QSize(182, 34)); m_byteArrowListWidget->insertItem(2, item7); m_byteArrowListWidget->setItemWidget(item7, itemwidget7); QListWidgetItem *item8 = new QListWidgetItem(); ProgrammerItemWidget *itemwidget8 = new ProgrammerItemWidget("BYTE"); item8->setFlags(Qt::NoItemFlags); item8->setSizeHint(QSize(182, 34)); m_byteArrowListWidget->insertItem(3, item8); m_byteArrowListWidget->setItemWidget(item8, itemwidget8); //默认位数64位 m_byteArrowListWidget->setCurrentItem(m_byteArrowListWidget->item(0)); static_cast(m_byteArrowListWidget->itemWidget(m_byteArrowListWidget->currentItem())) ->isMarkHide(false); m_byteArrowListWidget->setFixedSize(QSize(182, 136)); m_byteArrowRectangle->setRadius(15); m_byteArrowRectangle->setArrowWidth(48); m_byteArrowRectangle->setArrowHeight(21); m_byteArrowRectangle->setContent(m_byteArrowListWidget); m_byteArrowListWidget->installEventFilter(m_byteArrowRectangle); m_byteArrowRectangle->move(this->rect().x() + 200, this->rect().y() + 238);//在module的138,238位置,x多出150原因未找出 m_byteArrowListWidget->move(m_byteArrowRectangle->rect().x() + 15, m_byteArrowRectangle->rect().y() + m_byteArrowRectangle->arrowHeight() + 11); m_byteArrowRectangle->setWidth(212); m_byteArrowRectangle->setShadowXOffset(0); m_byteArrowRectangle->setShadowYOffset(0); m_byteArrowRectangle->setShadowBlurRadius(15); m_byteArrowRectangle->setHeight(191); m_byteArrowRectangle->setHidden(true); //信号槽 //点击press & 选中select事件 connect(m_byteArrowListWidget, &MemoryListWidget::itemselected, this, &ProgramModule::byteArrowListWidgetItemClicked); connect(m_byteArrowListWidget, &MemoryListWidget::space, this, &ProgramModule::byteArrowListWidgetItemSpace); connect(m_byteArrowListWidget, &MemoryListWidget::itempressed, this, &ProgramModule::byteArrowListWidgetItemPressed); connect(m_shiftArrowListWidget, &MemoryListWidget::itemselected, this, &ProgramModule::shiftArrowListWidgetItemClicked); connect(m_shiftArrowListWidget, &MemoryListWidget::space, this, &ProgramModule::shiftArrowListWidgetItemSpace); connect(m_shiftArrowListWidget, &MemoryListWidget::itempressed, this, &ProgramModule::shiftArrowListWidgetItemPressed); //隐藏rectangle connect(m_byteArrowRectangle, &ArrowRectangle::hidearrowrectangle, this, [ = ](bool isesc) { m_byteArrowRectangle->setHidden(true); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_System))->setBtnPressing(false); setwidgetAttribute(false); //esc按钮退出时需要focus到按钮上 if (isesc) static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_System))->setFocus(Qt::TabFocusReason); }); connect(m_shiftArrowRectangle, &ArrowRectangle::hidearrowrectangle, this, [ = ](bool isesc) { m_shiftArrowRectangle->setHidden(true); static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))->setBtnPressing(false); setwidgetAttribute(false); //esc按钮退出时需要focus到按钮上 if (isesc) static_cast(m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_Option))->setFocus(Qt::TabFocusReason); }); //focus事件 connect(m_byteArrowListWidget, &MemoryListWidget::focus, this, [ = ](int direction) { switch (direction) { //只有listwidget在focus状态才会触发keypress,所以此处未进行hasfocus判断 case 0: if (m_byteArrowListWidget->currentRow() > 0) { m_byteArrowListWidget->setCurrentRow(m_byteArrowListWidget->currentRow() - 1); m_byteArrowListWidget->scrollToItem(m_byteArrowListWidget->item(m_byteArrowListWidget->currentRow())); //滚动条跟随焦点项 } break; case 1: if (m_byteArrowListWidget->currentRow() < (m_byteArrowListWidget->count() - 1)) { m_byteArrowListWidget->setCurrentRow(m_byteArrowListWidget->currentRow() + 1); m_byteArrowListWidget->scrollToItem(m_byteArrowListWidget->item(m_byteArrowListWidget->currentRow())); //滚动条跟随焦点项 } break; default: break; } m_byteArrowListWidget->cleanState(true); static_cast(m_byteArrowListWidget->itemWidget(m_byteArrowListWidget->currentItem()))->setFocus(); }); connect(m_shiftArrowListWidget, &MemoryListWidget::focus, this, [ = ](int direction) { switch (direction) { //只有listwidget在focus状态才会触发keypress,所以此处未进行hasfocus判断 case 0: if (m_shiftArrowListWidget->currentRow() > 0) { m_shiftArrowListWidget->setCurrentRow(m_shiftArrowListWidget->currentRow() - 1); m_shiftArrowListWidget->scrollToItem(m_shiftArrowListWidget->item(m_shiftArrowListWidget->currentRow())); //滚动条跟随焦点项 } break; case 1: if (m_shiftArrowListWidget->currentRow() < (m_shiftArrowListWidget->count() - 1)) { m_shiftArrowListWidget->setCurrentRow(m_shiftArrowListWidget->currentRow() + 1); m_shiftArrowListWidget->scrollToItem(m_shiftArrowListWidget->item(m_shiftArrowListWidget->currentRow())); //滚动条跟随焦点项 } break; default: break; } m_shiftArrowListWidget->cleanState(true); static_cast(m_shiftArrowListWidget->itemWidget(m_shiftArrowListWidget->currentItem()))->setFocus(); }); //鼠标移动时清除focus状态 connect(m_byteArrowListWidget, &MemoryListWidget::mousemoving, m_byteArrowRectangle, &ArrowRectangle::mouseMoveToClearFocus); connect(m_shiftArrowListWidget, &MemoryListWidget::mousemoving, m_shiftArrowRectangle, &ArrowRectangle::mouseMoveToClearFocus); } void ProgramModule::handleEditKeyPress(QKeyEvent *e) { if (m_stackWidget->currentIndex() > 1) return; const bool isPressCtrl = e->modifiers() == Qt::ControlModifier; const QString keyText = e->text(); switch (e->key()) { case Qt::Key_0: m_proExpressionBar->enterNumberEvent("0"); //进入按键0事件 m_programmerKeypad->animate(ProgrammerKeypad::Key_0); //按键0动画效果 break; case Qt::Key_1: m_proExpressionBar->enterNumberEvent("1"); m_programmerKeypad->animate(ProgrammerKeypad::Key_1); break; case Qt::Key_2: m_proExpressionBar->enterNumberEvent("2"); m_programmerKeypad->animate(ProgrammerKeypad::Key_2); break; case Qt::Key_3: m_proExpressionBar->enterNumberEvent("3"); m_programmerKeypad->animate(ProgrammerKeypad::Key_3); break; case Qt::Key_4: m_proExpressionBar->enterNumberEvent("4"); m_programmerKeypad->animate(ProgrammerKeypad::Key_4); break; case Qt::Key_5: m_proExpressionBar->enterNumberEvent("5"); m_programmerKeypad->animate(ProgrammerKeypad::Key_5); break; case Qt::Key_6: m_proExpressionBar->enterNumberEvent("6"); m_programmerKeypad->animate(ProgrammerKeypad::Key_6); break; case Qt::Key_7: m_proExpressionBar->enterNumberEvent("7"); m_programmerKeypad->animate(ProgrammerKeypad::Key_7); break; case Qt::Key_8: m_proExpressionBar->enterNumberEvent("8"); m_programmerKeypad->animate(ProgrammerKeypad::Key_8); break; case Qt::Key_9: m_proExpressionBar->enterNumberEvent("9"); m_programmerKeypad->animate(ProgrammerKeypad::Key_9); break; case Qt::Key_A: if (isPressCtrl) { m_proExpressionBar->allElection(); } else { m_proExpressionBar->enterNumberEvent("A"); m_programmerKeypad->animate(ProgrammerKeypad::Key_A); } break; case Qt::Key_B: m_proExpressionBar->enterNumberEvent("B"); m_programmerKeypad->animate(ProgrammerKeypad::Key_B); break; case Qt::Key_C: if (isPressCtrl) { m_proExpressionBar->copyResultToClipboard(); setFocus(); } else { m_proExpressionBar->enterNumberEvent("C"); m_programmerKeypad->animate(ProgrammerKeypad::Key_C); } break; case Qt::Key_D: m_proExpressionBar->enterNumberEvent("D"); m_programmerKeypad->animate(ProgrammerKeypad::Key_D); break; case Qt::Key_E: m_proExpressionBar->enterNumberEvent("E"); m_programmerKeypad->animate(ProgrammerKeypad::Key_E); break; case Qt::Key_F: m_proExpressionBar->enterNumberEvent("F"); m_programmerKeypad->animate(ProgrammerKeypad::Key_F); break; case Qt::Key_L: if (isPressCtrl && m_avail && !m_isallgray) { m_memoryPublic->memoryclean(); } break; case Qt::Key_R: if (isPressCtrl && m_avail && !m_isallgray) { m_memorylistwidget->resetAllLabelByBase(); m_proExpressionBar->getInputEdit()->setAnswer(m_memorylistwidget->getfirstnumber().first, m_memorylistwidget->getfirstnumber().second); //点击item清除键状态改变 this->handleClearStateChanged(false); } break; case Qt::Key_M: if (isPressCtrl && m_memCalbtn && !m_isallgray) { m_checkBtnKeypad->animate(ProCheckBtnKeypad::Key_MS); m_proExpressionBar->enterEqualEvent(); if (m_proExpressionBar->getInputEdit()->getCurrentAns().first) m_memoryPublic->generateData(m_proExpressionBar->getInputEdit()->getCurrentAns().second); } break; case Qt::Key_P: if (isPressCtrl && m_memCalbtn && !m_isallgray) { m_proExpressionBar->enterEqualEvent(); if (m_proExpressionBar->getInputEdit()->getCurrentAns().first) //如果输入栏中可计算出结果 m_memoryPublic->memoryplus(m_proExpressionBar->getInputEdit()->getCurrentAns().second); } break; case Qt::Key_Q: if (isPressCtrl && m_memCalbtn && !m_isallgray) { m_proExpressionBar->enterEqualEvent(); if (m_proExpressionBar->getInputEdit()->getCurrentAns().first) m_memoryPublic->memoryminus(m_proExpressionBar->getInputEdit()->getCurrentAns().second); } break; case Qt::Key_V: if (isPressCtrl) { m_proExpressionBar->copyClipboard2Result(); } break; case Qt::Key_X: if (isPressCtrl) { m_proExpressionBar->shear(); } else { m_proExpressionBar->enterSymbolEvent("*"); m_programmerKeypad->animate(ProgrammerKeypad::Key_Mult); } break; case Qt::Key_Z: if (isPressCtrl) m_proExpressionBar->Undo(); break; case Qt::Key_Y: if (isPressCtrl) m_proExpressionBar->Redo(); break; case Qt::Key_Plus: m_proExpressionBar->enterSymbolEvent("+"); m_programmerKeypad->animate(ProgrammerKeypad::Key_Plus); break; case Qt::Key_Minus: case Qt::Key_Underscore: m_proExpressionBar->enterSymbolEvent("-"); m_programmerKeypad->animate(ProgrammerKeypad::Key_Min); break; case Qt::Key_Asterisk: m_proExpressionBar->enterSymbolEvent("*"); m_programmerKeypad->animate(ProgrammerKeypad::Key_Mult); break; case Qt::Key_Slash: m_proExpressionBar->enterSymbolEvent("/"); m_programmerKeypad->animate(ProgrammerKeypad::Key_Div); break; case Qt::Key_Enter: case Qt::Key_Return: case Qt::Key_Equal: m_programmerKeypad->animate(ProgrammerKeypad::Key_equal); m_proExpressionBar->enterEqualEvent(); break; case Qt::Key_Backspace: m_proExpressionBar->enterBackspaceEvent(); m_programmerKeypad->animate(ProgrammerKeypad::Key_Backspace); break; case Qt::Key_Escape: m_proExpressionBar->enterClearEvent(); m_programmerKeypad->animate(ProgrammerKeypad::Key_Clear); break; case Qt::Key_ParenLeft: m_programmerKeypad->animate(ProgrammerKeypad::Key_leftBracket); m_proExpressionBar->enterLeftBracketsEvent(); break; case Qt::Key_ParenRight: m_programmerKeypad->animate(ProgrammerKeypad::Key_rightBracket); m_proExpressionBar->enterRightBracketsEvent(); break; case Qt::Key_Percent: m_proExpressionBar->enterOperatorEvent("%"); m_programmerKeypad->animate(ProgrammerKeypad::Key_percent); break; case Qt::Key_Delete: m_proExpressionBar->enterClearEvent(); m_programmerKeypad->animate(ProgrammerKeypad::Key_Clear); break; case Qt::Key_Left: m_proExpressionBar->moveLeft(); break; case Qt::Key_Right: m_proExpressionBar->moveRight(); break; case Qt::Key_Ampersand: m_proExpressionBar->enterOperatorEvent("and"); m_programmerKeypad->animate(ProgrammerKeypad::Key_AND); break; case Qt::Key_AsciiTilde: m_proExpressionBar->enterNotEvent(); m_programmerKeypad->animate(ProgrammerKeypad::Key_NOT); break; case Qt::Key_AsciiCircum: m_proExpressionBar->enterOperatorEvent("xor"); m_programmerKeypad->animate(ProgrammerKeypad::Key_XOR); break; case Qt::Key_Backslash: m_proExpressionBar->enterOperatorEvent("nor"); m_programmerKeypad->animate(ProgrammerKeypad::Key_NOR); break; case Qt::Key_Bar: m_proExpressionBar->enterOperatorEvent("or"); m_programmerKeypad->animate(ProgrammerKeypad::Key_OR); break; case Qt::Key_Period: m_proExpressionBar->enterOperatorEvent("nand"); m_programmerKeypad->animate(ProgrammerKeypad::Key_NAND); break; case Qt::Key_Less: switch (m_shiftArrowCurrentRow) { case 0: m_proExpressionBar->enterOperatorEvent("sal"); break; case 1: m_proExpressionBar->enterOperatorEvent("shl"); break; case 2: m_proExpressionBar->enterOperatorEvent("rol"); break; case 3: m_proExpressionBar->enterOperatorEvent("rcl"); break; default: m_proExpressionBar->enterOperatorEvent("sal"); break; } m_programmerKeypad->animate(ProgrammerKeypad::Key_moveL); break; case Qt::Key_Greater: switch (m_shiftArrowCurrentRow) { case 0: m_proExpressionBar->enterOperatorEvent("sar"); break; case 1: m_proExpressionBar->enterOperatorEvent("shr"); break; case 2: m_proExpressionBar->enterOperatorEvent("ror"); break; case 3: m_proExpressionBar->enterOperatorEvent("rcr"); break; default: m_proExpressionBar->enterOperatorEvent("sar"); break; } m_programmerKeypad->animate(ProgrammerKeypad::Key_moveR); break; default: break; } switch (m_stackWidget->currentIndex()) { case 0: if (!m_programmerKeypad->buttonHasFocus() && !m_checkBtnKeypad->buttonHasFocus()) m_proExpressionBar->getInputEdit()->setFocus(); break; case 1: if (!m_proSystemKeypad->buttonHasFocus() && !m_checkBtnKeypad->buttonHasFocus()) m_proExpressionBar->getInputEdit()->setFocus(); break; default: m_proExpressionBar->getInputEdit()->setFocus(); break; } int left = 0; int right = 0; QString text = m_proExpressionBar->getInputEdit()->text(); for (int i = 0; i < text.length(); i++) { if (text[i] == "(") left ++; else if (text[i] == ")") { if (left > 0) left--; else right++; } } m_programmerKeypad->bracketsNum(0, QString::number(left)); //写入左右括号不匹配数 m_programmerKeypad->bracketsNum(1, QString::number(right)); } /** * @brief ProgramModule::setwidgetAttribute * 设置鼠标能否点击module中的其他控件,用于点出rectangle和内存列表 * @param b * true:无法点击 false:可以点击 */ void ProgramModule::setwidgetAttribute(bool b) { m_proExpressionBar->setAttribute(Qt::WA_TransparentForMouseEvents, b); m_programmerKeypad->setAttribute(Qt::WA_TransparentForMouseEvents, b); m_proSystemKeypad->setAttribute(Qt::WA_TransparentForMouseEvents, b); m_checkBtnKeypad->setAttribute(Qt::WA_TransparentForMouseEvents, b); m_proListView->setAttribute(Qt::WA_TransparentForMouseEvents, b); } void ProgramModule::handleClearStateChanged(bool isAllClear) { TextButton *btn = static_cast(m_programmerKeypad->button(ProgrammerKeypad::Key_Clear)); if (isAllClear) { btn->setText("AC"); } else { btn->setText("C"); } } /** * 重设rectangle的宽度,用于字体发生变化的时候 */ void ProgramModule::resetArrowWidth() { QFont font; font.setPixelSize(14); font.setWeight(2); QFontMetrics fm(font); int width = fm.boundingRect(tr("Rotate through carry circular shift")).width(); int itemwidth = width > 170 ? (width + 90) : 250; for (int i = 0; i < 4; i++) { m_shiftArrowListWidget->item(i)->setSizeHint(QSize(itemwidth, 34)); static_cast(m_shiftArrowListWidget->itemWidget(m_shiftArrowListWidget->item(i)))->resetWidth(itemwidth); } m_shiftArrowListWidget->setFixedSize(QSize(itemwidth, 136)); m_shiftArrowRectangle->setFixedWidth(itemwidth + 30); m_shiftArrowRectangle->move(this->rect().x() + 263, this->rect().y() + 238); //在module的138,238位置,x多出150原因未找出 m_shiftArrowListWidget->move(m_shiftArrowRectangle->rect().x() + 15, m_shiftArrowRectangle->rect().y() + m_shiftArrowRectangle->arrowHeight() + 11); } deepin-calculator-5.7.21/src/widgets/programmodule.h000066400000000000000000000075341423020056600224730ustar00rootroot00000000000000/* * Copyright (C) 2020 ~ 2021 Uniontech Software Technology Co.,Ltd. * * Author: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PROGRAMMODULE_H #define PROGRAMMODULE_H #include "../views/memorywidget.h" #include "../views/programmerarrowdelegate.h" #include "../views/programmeritemwidget.h" #include "../views/prolistview.h" #include "../views/prolistmodel.h" #include "../views/prolistdelegate.h" #include "../control/bitbutton.h" #include "../control/programmerkeypad.h" #include "../control/procheckbtnkeypad.h" #include "../control/prosystemkeypad.h" #include "proexpressionbar.h" #include "arrowrectangle.h" #include "../memorypublic.h" #include #include #include #include #include #include #include #include DGUI_USE_NAMESPACE DWIDGET_USE_NAMESPACE class ProgramModule : public DWidget { Q_OBJECT public: explicit ProgramModule(QWidget *parent = nullptr); ~ProgramModule(); void setKeyPress(QKeyEvent *e); void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); private slots: //数字键盘事件--鼠标点击、键盘交互、键盘输入 void handleKeypadButtonPress(int key); void handleKeypadButtonPressByspace(int key); //arrowrectangle处理 void shiftArrowListWidgetItemClicked(int row, bool isselect); void shiftArrowListWidgetItemSpace(); void shiftArrowListWidgetItemPressed(int row); void byteArrowListWidgetItemClicked(int row, bool isselect); void byteArrowListWidgetItemSpace(); void byteArrowListWidgetItemPressed(int row); void checkBtnKeypadThemeChange(int type); void radixListChange(const QModelIndex &index, bool isspace); public slots: void mAvailableEvent(); void mUnAvailableEvent(); void showListWidget(); void closeListWidget(); private: void initArrowRectangle(); void handleEditKeyPress(QKeyEvent *); void setwidgetAttribute(bool b); void handleClearStateChanged(bool isAllClear); void resetArrowWidth(); private: ProExpressionBar *m_proExpressionBar; ProListView *m_proListView; ProListModel *m_proListModel; ProListDelegate *m_proListDelegate; ProCheckBtnKeypad *m_checkBtnKeypad; ProgrammerKeypad *m_programmerKeypad; ProSystemKeypad *m_proSystemKeypad; QStackedWidget *m_stackWidget; MemoryPublic *m_memoryPublic; MemoryWidget *m_memorylistwidget; ArrowRectangle *m_byteArrowRectangle; MemoryListWidget *m_byteArrowListWidget; ProgrammerArrowDelegate *m_byteProgrammerArrowDelegate; ArrowRectangle *m_shiftArrowRectangle; MemoryListWidget *m_shiftArrowListWidget; ProgrammerArrowDelegate *m_shiftProgrammerArrowDelegate; //rectangle中当前选中的行数 int m_shiftArrowCurrentRow = 0; int m_byteArrowCurrentRow = 0; //rectangle中当前点击的行数 int m_shiftArrowPressRow = -1; int m_byteArrowPressRow = -1; //内存相关 bool m_insidewidget = false; bool m_avail = false; //内存中有数据 bool m_memCalbtn = false; //ms可用 bool m_isallgray = false; //内存按钮全部置灰; int m_stackwidgetLastIndex = 0; //切换至内存前的页面 }; #endif // PROGRAMMODULE_H deepin-calculator-5.7.21/src/widgets/scientificmodule.cpp000066400000000000000000001401341423020056600234710ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "scientificmodule.h" #include "dthememanager.h" #include "../utils.h" #include "../../3rdparty/math/quantity.h" #include #include #include #include #include #include const int EXPRESSIONBAR_HEIGHT = 100; scientificModule::scientificModule(QWidget *parent) : DWidget(parent) { m_stackWidget = new QStackedWidget(this); m_sciexpressionBar = new SciExpressionBar(this); m_memhiskeypad = new MemHisKeypad(this); m_scikeypadwidget = new ScientificKeyPad(this); m_memhiswidget = new MemHisWidget(this); m_memCalbtn = false; m_memRCbtn = false; QVBoxLayout *layout = new QVBoxLayout(this); m_memoryPublic = MemoryPublic::instance(); m_sciexpressionBar->setFixedHeight(EXPRESSIONBAR_HEIGHT); layout->addWidget(m_sciexpressionBar); layout->addWidget(m_memhiskeypad); m_stackWidget->addWidget(m_memhiswidget); m_stackWidget->addWidget(m_scikeypadwidget); m_stackWidget->setCurrentWidget(m_scikeypadwidget); layout->addWidget(m_stackWidget); layout->setSpacing(0); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); setMouseTracking(true); //默认false,默认下至少一个鼠标按键被按下才跟踪鼠标 setFocus(); m_sciexpressionBar->initTheme(DGuiApplicationHelper::instance()->themeType()); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_sciexpressionBar, &SciExpressionBar::initTheme); connect(m_memhiswidget->findChild(), &SimpleListView::obtainingHistorical, this, &scientificModule::clickListView); //点击切换界面的历史记录 connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, this, &scientificModule::initTheme); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_scikeypadwidget, &ScientificKeyPad::buttonThemeChanged); connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, m_memhiswidget, &MemHisWidget::themeChanged); connect(m_sciexpressionBar, &SciExpressionBar::keyPress, this, &scientificModule::handleEditKeyPress); connect(m_sciexpressionBar, &SciExpressionBar::clearStateChanged, this, &scientificModule::handleClearStateChanged); //判断C/AC connect(m_sciexpressionBar, &SciExpressionBar::turnDeg, this, &scientificModule::handleDegChanged); //点击deg按键 connect(m_sciexpressionBar, &SciExpressionBar::fEStateChanged, this, &scientificModule::handleFEStateChanged); connect(this, &scientificModule::changedeg, m_scikeypadwidget, &ScientificKeyPad::getdeg); //切换deg切图 connect(m_scikeypadwidget, &ScientificKeyPad::buttonPressed, this, &scientificModule::handleKeypadButtonPress); connect(m_scikeypadwidget, &ScientificKeyPad::buttonPressedbySpace, this, &scientificModule::handleKeypadButtonPressByspace); connect(m_memhiskeypad, &MemHisKeypad::buttonPressed, this, &scientificModule::handleKeypadButtonPress); connect(m_memhiskeypad, &MemHisKeypad::buttonPressedbySpace, this, &scientificModule::handleKeypadButtonPressByspace); connect(m_memhiswidget, &MemHisWidget::hisIsFilled, [ = ](bool hisisfilled) { if (hisisfilled) { MemoryButton *btn2 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist)); btn2->setEnabled(true); m_havail = true; } else { m_havail = false; } }); connect(m_memhiswidget->findChild(), &MemoryWidget::widgetplus, this, [ = ](int row) { //点击键盘按键上的m+,m-是先进行计算,若有计算结果放入内存中 m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) m_memhiswidget->memoryFunctions(MemHisWidget::widgetplus, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second, row); }); connect(m_memhiswidget->findChild(), &MemoryWidget::widgetminus, this, [ = ](int row) { m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) m_memhiswidget->memoryFunctions(MemHisWidget::widgetminus, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second, row); }); connect(m_memoryPublic, &MemoryPublic::memorycleanSig, this, &scientificModule::mUnAvailableEvent); connect(m_memoryPublic, &MemoryPublic::generateDataSig, this, &scientificModule::mAvailableEvent); connect(m_memhiswidget->findChild(), &MemoryWidget::itemclick, this, [ = ](const QPair p) { //内存界面点击item QString str = p.first; m_sciexpressionBar->getInputEdit()->setAnswer(str.remove("\n"), p.second); m_sciexpressionBar->getInputEdit()->setFocus(); //点击item清除键状态改变 this->handleClearStateChanged(false); m_stackWidget->setCurrentWidget(m_scikeypadwidget); m_memhiskeypad->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_sciexpressionBar->setAttribute(Qt::WA_TransparentForMouseEvents, false); MemoryButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MC)); btn->setEnabled(true); btn->setbuttongray(false); MemoryButton *btn1 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MR)); btn1->setEnabled(true); btn1->setbuttongray(false); MemoryButton *btn2 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mplus)); btn2->setEnabled(true); btn2->setbuttongray(false); MemoryButton *btn3 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mmin)); btn3->setEnabled(true); btn3->setbuttongray(false); MemoryButton *btn4 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MS)); btn4->setEnabled(true); btn4->setbuttongray(false); MemoryButton *btn5 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist)); btn5->setEnabled(true); btn5->setbtnlight(false); TextButton *btn6 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_FE)); btn6->setEnabled(true); m_memRCbtn = true; m_memCalbtn = true; m_isallgray = false; }); connect(m_memhiswidget, &MemHisWidget::hideWidget, this, &scientificModule::hideMemHisWidget); connect(m_sciexpressionBar->getInputEdit(), &InputEdit::emptyExpression, this, [ = ](bool b) { //输入栏为空m+,m-,ms置灰;否则可用 if (b == false) { MemoryButton *btn2 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mplus)); btn2->setEnabled(true); MemoryButton *btn3 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mmin)); btn3->setEnabled(true); MemoryButton *btn4 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MS)); btn4->setEnabled(true); m_memCalbtn = true; m_memhiswidget->getMemoryWiget()->expressionempty(b); } else { MemoryButton *btn2 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mplus)); btn2->setEnabled(false); MemoryButton *btn3 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mmin)); btn3->setEnabled(false); MemoryButton *btn4 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MS)); btn4->setEnabled(false); m_memCalbtn = false; m_memhiswidget->getMemoryWiget()->expressionempty(b); } }); if (!m_memoryPublic->isEmpty()) mAvailableEvent(); else mUnAvailableEvent(); // setScientificTabOrder(); } scientificModule::~scientificModule() {} void scientificModule::initTheme(int type) { m_sciexpressionBar->initTheme(type); update(); } /** * @brief 物理键盘事件 */ void scientificModule::handleEditKeyPress(QKeyEvent *e) { const bool isPressCtrl = e->modifiers() == Qt::ControlModifier; //ctrl是否按下 const bool isPressShift = e->modifiers() == Qt::ShiftModifier; //shift是否按下 switch (e->key()) { case Qt::Key_0: m_scikeypadwidget->animate(ScientificKeyPad::Key_0); //键盘按下动画效果 m_sciexpressionBar->enterNumberEvent("0"); break; case Qt::Key_1: m_scikeypadwidget->animate(ScientificKeyPad::Key_1); m_sciexpressionBar->enterNumberEvent("1"); break; case Qt::Key_2: m_scikeypadwidget->animate(ScientificKeyPad::Key_2); m_sciexpressionBar->enterNumberEvent("2"); break; case Qt::Key_3: m_scikeypadwidget->animate(ScientificKeyPad::Key_3); m_sciexpressionBar->enterNumberEvent("3"); break; case Qt::Key_4: m_scikeypadwidget->animate(ScientificKeyPad::Key_4); m_sciexpressionBar->enterNumberEvent("4"); break; case Qt::Key_5: m_scikeypadwidget->animate(ScientificKeyPad::Key_5); m_sciexpressionBar->enterNumberEvent("5"); break; case Qt::Key_6: m_scikeypadwidget->animate(ScientificKeyPad::Key_6); m_sciexpressionBar->enterNumberEvent("6"); break; case Qt::Key_7: m_scikeypadwidget->animate(ScientificKeyPad::Key_7); m_sciexpressionBar->enterNumberEvent("7"); break; case Qt::Key_8: m_scikeypadwidget->animate(ScientificKeyPad::Key_8); m_sciexpressionBar->enterNumberEvent("8"); break; case Qt::Key_9: m_scikeypadwidget->animate(ScientificKeyPad::Key_9); m_sciexpressionBar->enterNumberEvent("9"); break; case Qt::Key_Plus: m_scikeypadwidget->animate(ScientificKeyPad::Key_Plus); m_sciexpressionBar->enterSymbolEvent("+"); break; case Qt::Key_Minus: case Qt::Key_Underscore: m_scikeypadwidget->animate(ScientificKeyPad::Key_Min); m_sciexpressionBar->enterSymbolEvent("-"); break; case Qt::Key_Asterisk: m_scikeypadwidget->animate(ScientificKeyPad::Key_Mult); m_sciexpressionBar->enterSymbolEvent("*"); break; case Qt::Key_Slash: m_scikeypadwidget->animate(ScientificKeyPad::Key_Div); m_sciexpressionBar->enterSymbolEvent("/"); break; case Qt::Key_Enter: case Qt::Key_Return: case Qt::Key_Equal: m_sciexpressionBar->enterEqualEvent(); m_scikeypadwidget->animate(ScientificKeyPad::Key_Equals); if (m_sciexpressionBar->getexpression().first) { m_memhiswidget->findChild()->updataList(m_sciexpressionBar->getanswer(), m_sciexpressionBar->getexpression().second, 0); m_memhiswidget->historyfilled(); m_memhiswidget->findChild()->scrollToTop(); } break; case Qt::Key_Backspace: m_sciexpressionBar->enterBackspaceEvent(); m_scikeypadwidget->animate(ScientificKeyPad::Key_Backspace); break; case Qt::Key_Period: m_scikeypadwidget->animate(ScientificKeyPad::Key_Point); m_sciexpressionBar->enterPointEvent(); break; case Qt::Key_Escape: m_sciexpressionBar->enterClearEvent(); m_scikeypadwidget->animate(ScientificKeyPad::Key_Clear); break; case Qt::Key_ParenLeft: m_scikeypadwidget->animate(ScientificKeyPad::Key_left); m_sciexpressionBar->enterBracketEvent(1); break; case Qt::Key_ParenRight: m_scikeypadwidget->animate(ScientificKeyPad::Key_right); m_sciexpressionBar->enterBracketEvent(2); break; case Qt::Key_Percent: m_scikeypadwidget->animate(ScientificKeyPad::Key_Percent); m_sciexpressionBar->enterPercentEvent(); break; case Qt::Key_AsciiCircum: m_scikeypadwidget->animate(ScientificKeyPad::Key_xy); m_sciexpressionBar->enterOperatorEvent("^"); break; case Qt::Key_C: if (isPressCtrl) { m_sciexpressionBar->copyResultToClipboard(); setFocus(); } break; case Qt::Key_V: if (isPressCtrl) { m_sciexpressionBar->copyClipboard2Result(); } else { m_sciexpressionBar->enterFEEvent(m_FEisdown); // m_memhiskeypad->animate(MemHisKeypad::Key_FE); } break; case Qt::Key_A: if (isPressCtrl) { m_sciexpressionBar->allElection(); } break; case Qt::Key_X: if (isPressCtrl) { m_sciexpressionBar->shear(); } else { m_scikeypadwidget->animate(ScientificKeyPad::Key_Mult); m_sciexpressionBar->enterSymbolEvent("*"); } break; case Qt::Key_Delete: m_sciexpressionBar->enterClearEvent(); m_scikeypadwidget->animate(ScientificKeyPad::Key_Clear); break; case Qt::Key_Left: m_sciexpressionBar->moveLeft(); break; case Qt::Key_Right: m_sciexpressionBar->moveRight(); break; case Qt::Key_Z: if (isPressCtrl) m_sciexpressionBar->Undo(); break; case Qt::Key_Y: if (isPressCtrl) m_sciexpressionBar->Redo(); else { m_scikeypadwidget->animate(ScientificKeyPad::Key_xy); m_sciexpressionBar->enterOperatorEvent("^"); } break; case Qt::Key_L: if (isPressCtrl && m_memRCbtn && !m_isallgray) { //CTRL+L,MC m_memhiskeypad->animate(MemHisKeypad::Key_MC); QTimer::singleShot(100, this, [ = ] { m_memhiswidget->memoryFunctions(MemHisWidget::memoryclean); //延迟,让动画效果显示 }); } else if (!isPressCtrl) { if (isPressShift) { m_scikeypadwidget->animate(ScientificKeyPad::Key_logyx); m_sciexpressionBar->enterOperatorEvent("log"); } else { m_scikeypadwidget->animate(ScientificKeyPad::Key_log); m_sciexpressionBar->enterFunctionEvent("lg"); } } break; case Qt::Key_R: if (isPressCtrl && m_memRCbtn && !m_isallgray) { //CTRL+R,MR m_memhiskeypad->animate(MemHisKeypad::Key_MR); m_sciexpressionBar->getInputEdit()->setAnswer(m_memhiswidget->findChild()->getfirstnumber().first , m_memhiswidget->findChild()->getfirstnumber().second); //点击item清除键状态改变 this->handleClearStateChanged(false); } else if (!isPressCtrl) { if (isPressShift) { m_scikeypadwidget->animate(ScientificKeyPad::Key_Rand); m_sciexpressionBar->enterRandEvent(); } else { m_scikeypadwidget->animate(ScientificKeyPad::Key_Derivative); m_sciexpressionBar->enterSpecialFuncEvent("1/("); } } break; case Qt::Key_P: if (isPressCtrl && m_memCalbtn && !m_isallgray) { //CTRL+P,M+ m_sciexpressionBar->enterEqualEvent(); m_memhiskeypad->animate(MemHisKeypad::Key_Mplus); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) //如果输入栏中可计算出结果 m_memhiswidget->memoryFunctions(MemHisWidget::memoryplus, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second); } else if (!isPressCtrl) { m_scikeypadwidget->animate(ScientificKeyPad::Key_PI); m_sciexpressionBar->enterConstantEvent(QString::fromUtf8("π")); } break; case Qt::Key_Q: if (isPressCtrl && m_memCalbtn && !m_isallgray) { //CTRL+Q,M- m_sciexpressionBar->enterEqualEvent(); m_memhiskeypad->animate(MemHisKeypad::Key_Mmin); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) //如果输入栏中可计算出结果 m_memhiswidget->memoryFunctions(MemHisWidget::memoryminus, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second); } else if (!isPressCtrl) { m_scikeypadwidget->animate(ScientificKeyPad::Key_x2); m_sciexpressionBar->enterOperatorEvent("^2"); } break; case Qt::Key_M: if (isPressCtrl && m_memCalbtn && !m_isallgray) { //ctrl+m,MS m_sciexpressionBar->enterEqualEvent(); m_memhiskeypad->animate(MemHisKeypad::Key_MS); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) //如果输入栏中可计算出结果 m_memhiswidget->memoryFunctions(MemHisWidget::generateData, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second); } else if (!isPressCtrl) { m_scikeypadwidget->animate(ScientificKeyPad::Key_Mod); m_sciexpressionBar->enterOperatorEvent("mod"); } break; case Qt::Key_NumberSign: //# m_scikeypadwidget->animate(ScientificKeyPad::Key_x3); m_sciexpressionBar->enterOperatorEvent("^3"); break; case Qt::Key_N: if (isPressCtrl) { m_scikeypadwidget->animate(ScientificKeyPad::Key_ex); m_sciexpressionBar->enterConstantEvent("e^"); } else { m_scikeypadwidget->animate(ScientificKeyPad::Key_ln); m_sciexpressionBar->enterFunctionEvent("ln"); } break; case Qt::Key_At: //@ m_scikeypadwidget->animate(ScientificKeyPad::Key_sqrt2); m_sciexpressionBar->enterFunctionEvent("sqrt"); break; case Qt::Key_B: m_scikeypadwidget->animate(ScientificKeyPad::Key_sqrt3); m_sciexpressionBar->enterFunctionEvent("cbrt"); break; case Qt::Key_Bar: //|,shift+'\' m_scikeypadwidget->animate(ScientificKeyPad::Key_Modulus); m_sciexpressionBar->enterSpecialFuncEvent("abs("); break; case Qt::Key_E: if (isPressShift) { m_scikeypadwidget->animate(ScientificKeyPad::Key_e); m_sciexpressionBar->enterConstantEvent(QString::fromUtf8("e")); } else { m_scikeypadwidget->animate(ScientificKeyPad::Key_exp); m_sciexpressionBar->enterOperatorEvent(".E+"); } break; case Qt::Key_S: if (isPressShift) { m_scikeypadwidget->animate(ScientificKeyPad::Key_arcsin); m_sciexpressionBar->enterFunctionEvent("arcsin"); } else { m_scikeypadwidget->animate(ScientificKeyPad::Key_sin); m_sciexpressionBar->enterFunctionEvent("sin"); } break; case Qt::Key_O: if (isPressShift) { m_scikeypadwidget->animate(ScientificKeyPad::Key_arccos); m_sciexpressionBar->enterFunctionEvent("arccos"); } else { m_scikeypadwidget->animate(ScientificKeyPad::Key_cos); m_sciexpressionBar->enterFunctionEvent("cos"); } break; case Qt::Key_T: if (isPressShift) { m_scikeypadwidget->animate(ScientificKeyPad::Key_arctan); m_sciexpressionBar->enterFunctionEvent("arctan"); } else { m_scikeypadwidget->animate(ScientificKeyPad::Key_tan); m_sciexpressionBar->enterFunctionEvent("tan"); } break; case Qt::Key_J: if (isPressShift) { m_scikeypadwidget->animate(ScientificKeyPad::Key_arccot); m_sciexpressionBar->enterFunctionEvent("arccot"); } else { m_scikeypadwidget->animate(ScientificKeyPad::Key_cot); m_sciexpressionBar->enterFunctionEvent("cot"); } break; case Qt::Key_Exclam: //'!' m_scikeypadwidget->animate(ScientificKeyPad::Key_Factorials); m_sciexpressionBar->enterOperatorEvent("!"); break; default: break; } if (!m_scikeypadwidget->buttonHasFocus()) m_sciexpressionBar->getInputEdit()->setFocus(); //edit 20200417 for bug--21146 int left = 0; int right = 0; QString text = m_sciexpressionBar->getInputEdit()->text(); for (int i = 0; i < text.length(); i++) { if (text[i] == "(") left ++; else if (text[i] == ")") { if (left > 0) left--; else right++; } } m_scikeypadwidget->bracketsNum(0, QString::number(left)); //写入左右括号不匹配数 m_scikeypadwidget->bracketsNum(1, QString::number(right)); } /** * @brief 按钮事件 */ void scientificModule::handleKeypadButtonPress(int key) { bool pagefocus = false; m_scikeypadwidget->update(); //20200414 bug20294鼠标点击取消focus switch (key) { case ScientificKeyPad::Key_0: m_sciexpressionBar->enterNumberEvent("0"); break; case ScientificKeyPad::Key_1: m_sciexpressionBar->enterNumberEvent("1"); break; case ScientificKeyPad::Key_2: m_sciexpressionBar->enterNumberEvent("2"); break; case ScientificKeyPad::Key_3: m_sciexpressionBar->enterNumberEvent("3"); break; case ScientificKeyPad::Key_4: m_sciexpressionBar->enterNumberEvent("4"); break; case ScientificKeyPad::Key_5: m_sciexpressionBar->enterNumberEvent("5"); break; case ScientificKeyPad::Key_6: m_sciexpressionBar->enterNumberEvent("6"); break; case ScientificKeyPad::Key_7: m_sciexpressionBar->enterNumberEvent("7"); break; case ScientificKeyPad::Key_8: m_sciexpressionBar->enterNumberEvent("8"); break; case ScientificKeyPad::Key_9: m_sciexpressionBar->enterNumberEvent("9"); break; case ScientificKeyPad::Key_Plus: m_sciexpressionBar->enterSymbolEvent("+"); break; case ScientificKeyPad::Key_Min: m_sciexpressionBar->enterSymbolEvent("-"); break; case ScientificKeyPad::Key_Mult: m_sciexpressionBar->enterSymbolEvent("*"); break; case ScientificKeyPad::Key_Div: m_sciexpressionBar->enterSymbolEvent("/"); break; case ScientificKeyPad::Key_Percent: m_sciexpressionBar->enterPercentEvent(); break; case ScientificKeyPad::Key_Equals: m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getexpression().first) { m_memhiswidget->findChild()->updataList(m_sciexpressionBar->getanswer(), m_sciexpressionBar->getexpression().second, 0); m_memhiswidget->historyfilled(); m_memhiswidget->findChild()->scrollToTop(); } break; case ScientificKeyPad::Key_Clear: m_sciexpressionBar->enterClearEvent(); break; case ScientificKeyPad::Key_Backspace: m_sciexpressionBar->enterBackspaceEvent(); break; case ScientificKeyPad::Key_Point: m_sciexpressionBar->enterPointEvent(); break; case ScientificKeyPad::Key_left: m_sciexpressionBar->enterBracketEvent(1); break; case ScientificKeyPad::Key_right: m_sciexpressionBar->enterBracketEvent(2); break; case MemHisKeypad::Key_MS: m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) m_memhiswidget->memoryFunctions(MemHisWidget::generateData, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemHisKeypad::Key_MC: m_memhiswidget->memoryFunctions(MemHisWidget::memoryclean); break; case MemHisKeypad::Key_Mplus: m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) m_memhiswidget->memoryFunctions(MemHisWidget::memoryplus, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemHisKeypad::Key_Mmin: m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) m_memhiswidget->memoryFunctions(MemHisWidget::memoryminus, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemHisKeypad::Key_MR: m_sciexpressionBar->getInputEdit()->setAnswer(m_memhiswidget->findChild()->getfirstnumber().first , m_memhiswidget->findChild()->getfirstnumber().second); //点击item清除键状态改变 this->handleClearStateChanged(false); break; case MemHisKeypad::Key_MHlist: showMemHisWidget(); m_memhiswidget->focusOnButtonbox(Qt::MouseFocusReason); m_sciexpressionBar->setAttribute(Qt::WA_TransparentForMouseEvents); //鼠标穿透 m_memhiskeypad->setAttribute(Qt::WA_TransparentForMouseEvents); //鼠标穿透 pagefocus = true; break; case ScientificKeyPad::Key_deg: m_sciexpressionBar->enterDegEvent(m_deg); break; case ScientificKeyPad::Key_sin: m_sciexpressionBar->enterFunctionEvent("sin"); break; case MemHisKeypad::Key_FE: m_sciexpressionBar->enterFEEvent(m_FEisdown); break; case ScientificKeyPad::Key_page: handlePageStateChanged(); break; case ScientificKeyPad::Key_PI: m_sciexpressionBar->enterConstantEvent(QString::fromUtf8("π")); break; case ScientificKeyPad::Key_e: m_sciexpressionBar->enterConstantEvent(QString::fromUtf8("e")); break; case ScientificKeyPad::Key_Mod: m_sciexpressionBar->enterOperatorEvent("mod"); break; case ScientificKeyPad::Key_x2: m_sciexpressionBar->enterOperatorEvent("^2"); break; case ScientificKeyPad::Key_Derivative: m_sciexpressionBar->enterSpecialFuncEvent("1/("); break; case ScientificKeyPad::Key_Factorials: m_sciexpressionBar->enterOperatorEvent("!"); break; case ScientificKeyPad::Key_exp: m_sciexpressionBar->enterOperatorEvent(".E+"); break; case ScientificKeyPad::Key_cos: m_sciexpressionBar->enterFunctionEvent("cos"); break; case ScientificKeyPad::Key_x3: m_sciexpressionBar->enterOperatorEvent("^3"); break; case ScientificKeyPad::Key_tan: m_sciexpressionBar->enterFunctionEvent("tan"); break; case ScientificKeyPad::Key_xy: m_sciexpressionBar->enterOperatorEvent("^"); break; case ScientificKeyPad::Key_cot: m_sciexpressionBar->enterFunctionEvent("cot"); break; case ScientificKeyPad::Key_10x: m_sciexpressionBar->enterConstantEvent("10^"); break; case ScientificKeyPad::Key_Modulus: m_sciexpressionBar->enterSpecialFuncEvent("abs("); break; case ScientificKeyPad::Key_log: m_sciexpressionBar->enterFunctionEvent("lg"); break; case ScientificKeyPad::Key_Rand: m_sciexpressionBar->enterRandEvent(); break; case ScientificKeyPad::Key_ln: m_sciexpressionBar->enterFunctionEvent("ln"); break; case ScientificKeyPad::Key_arcsin: m_sciexpressionBar->enterFunctionEvent("arcsin"); break; case ScientificKeyPad::Key_sqrt2: m_sciexpressionBar->enterFunctionEvent("sqrt"); break; case ScientificKeyPad::Key_arccos: m_sciexpressionBar->enterFunctionEvent("arccos"); break; case ScientificKeyPad::Key_sqrt3: m_sciexpressionBar->enterFunctionEvent("cbrt"); break; case ScientificKeyPad::Key_arctan: m_sciexpressionBar->enterFunctionEvent("arctan"); break; case ScientificKeyPad::Key_ysqrtx: m_sciexpressionBar->enterOperatorEvent("yroot"); break; case ScientificKeyPad::Key_arccot: m_sciexpressionBar->enterFunctionEvent("arccot"); break; case ScientificKeyPad::Key_2x: m_sciexpressionBar->enterConstantEvent("2^"); break; case ScientificKeyPad::Key_logyx: m_sciexpressionBar->enterOperatorEvent("log"); break; case ScientificKeyPad::Key_ex: m_sciexpressionBar->enterConstantEvent("e^"); break; case ScientificKeyPad::Key_opposite: m_sciexpressionBar->enterSpecialFuncEvent("(-"); break; default: break; } // if (m_stackWidget->currentWidget() == m_scikeypadwidget) // m_sciexpressionBar->getInputEdit()->setFocus(); if (!pagefocus) m_sciexpressionBar->getInputEdit()->setFocus(); int left = 0; int right = 0; QString text = m_sciexpressionBar->getInputEdit()->text(); for (int i = 0; i < text.length(); i++) { if (text[i] == "(") left ++; else if (text[i] == ")") { if (left > 0) left--; else right++; } } m_scikeypadwidget->bracketsNum(0, QString::number(left)); //写入左右括号不匹配数 m_scikeypadwidget->bracketsNum(1, QString::number(right)); } /** * @brief 焦点空格事件 */ void scientificModule::handleKeypadButtonPressByspace(int key) { m_scikeypadwidget->update(); m_memhiskeypad->update(); if (key > 52 && key < 58) m_memhiskeypad->animate(MemHisKeypad::Buttons(key), true); else if (key < 52) m_scikeypadwidget->animate(ScientificKeyPad::Buttons(key), true); //20200414 bug20294鼠标点击取消focus switch (key) { case ScientificKeyPad::Key_0: m_sciexpressionBar->enterNumberEvent("0"); break; case ScientificKeyPad::Key_1: m_sciexpressionBar->enterNumberEvent("1"); break; case ScientificKeyPad::Key_2: m_sciexpressionBar->enterNumberEvent("2"); break; case ScientificKeyPad::Key_3: m_sciexpressionBar->enterNumberEvent("3"); break; case ScientificKeyPad::Key_4: m_sciexpressionBar->enterNumberEvent("4"); break; case ScientificKeyPad::Key_5: m_sciexpressionBar->enterNumberEvent("5"); break; case ScientificKeyPad::Key_6: m_sciexpressionBar->enterNumberEvent("6"); break; case ScientificKeyPad::Key_7: m_sciexpressionBar->enterNumberEvent("7"); break; case ScientificKeyPad::Key_8: m_sciexpressionBar->enterNumberEvent("8"); break; case ScientificKeyPad::Key_9: m_sciexpressionBar->enterNumberEvent("9"); break; case ScientificKeyPad::Key_Plus: m_sciexpressionBar->enterSymbolEvent("+"); break; case ScientificKeyPad::Key_Min: m_sciexpressionBar->enterSymbolEvent("-"); break; case ScientificKeyPad::Key_Mult: m_sciexpressionBar->enterSymbolEvent("*"); break; case ScientificKeyPad::Key_Div: m_sciexpressionBar->enterSymbolEvent("/"); break; case ScientificKeyPad::Key_Percent: m_sciexpressionBar->enterPercentEvent(); break; case ScientificKeyPad::Key_Equals: m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getexpression().first) { m_memhiswidget->findChild()->updataList(m_sciexpressionBar->getanswer(), m_sciexpressionBar->getexpression().second, 0); m_memhiswidget->historyfilled(); m_memhiswidget->findChild()->scrollToTop(); } break; case ScientificKeyPad::Key_Clear: m_sciexpressionBar->enterClearEvent(); break; case ScientificKeyPad::Key_Backspace: m_sciexpressionBar->enterBackspaceEvent(); break; case ScientificKeyPad::Key_Point: m_sciexpressionBar->enterPointEvent(); break; case ScientificKeyPad::Key_left: m_sciexpressionBar->enterBracketEvent(1); break; case ScientificKeyPad::Key_right: m_sciexpressionBar->enterBracketEvent(2); break; case MemHisKeypad::Key_MS: m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) m_memhiswidget->memoryFunctions(MemHisWidget::generateData, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemHisKeypad::Key_MC: m_memhiswidget->memoryFunctions(MemHisWidget::memoryclean); break; case MemHisKeypad::Key_Mplus: m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) m_memhiswidget->memoryFunctions(MemHisWidget::memoryplus, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemHisKeypad::Key_Mmin: m_sciexpressionBar->enterEqualEvent(); if (m_sciexpressionBar->getInputEdit()->getMemoryAnswer().first) m_memhiswidget->memoryFunctions(MemHisWidget::memoryminus, m_sciexpressionBar->getInputEdit()->getMemoryAnswer().second); break; case MemHisKeypad::Key_MR: m_sciexpressionBar->getInputEdit()->setAnswer(m_memhiswidget->findChild()->getfirstnumber().first , m_memhiswidget->findChild()->getfirstnumber().second); //点击item清除键状态改变 this->handleClearStateChanged(false); break; case MemHisKeypad::Key_MHlist: m_memhiskeypad->animate(MemHisKeypad::Key_MHlist, true); showMemHisWidget(); m_memhiswidget->focusOnButtonbox(Qt::TabFocusReason); m_sciexpressionBar->setAttribute(Qt::WA_TransparentForMouseEvents); //鼠标穿透 m_memhiskeypad->setAttribute(Qt::WA_TransparentForMouseEvents); //鼠标穿透 break; case ScientificKeyPad::Key_deg: m_sciexpressionBar->enterDegEvent(m_deg); break; case ScientificKeyPad::Key_sin: m_sciexpressionBar->enterFunctionEvent("sin"); break; case MemHisKeypad::Key_FE: m_sciexpressionBar->enterFEEvent(m_FEisdown); break; case ScientificKeyPad::Key_page: handlePageStateChanged(); break; case ScientificKeyPad::Key_PI: m_sciexpressionBar->enterConstantEvent(QString::fromUtf8("π")); break; case ScientificKeyPad::Key_e: m_sciexpressionBar->enterConstantEvent(QString::fromUtf8("e")); break; case ScientificKeyPad::Key_Mod: m_sciexpressionBar->enterOperatorEvent("mod"); break; case ScientificKeyPad::Key_x2: m_sciexpressionBar->enterOperatorEvent("^2"); break; case ScientificKeyPad::Key_Derivative: m_sciexpressionBar->enterSpecialFuncEvent("1/("); break; case ScientificKeyPad::Key_Factorials: m_sciexpressionBar->enterOperatorEvent("!"); break; case ScientificKeyPad::Key_exp: m_sciexpressionBar->enterOperatorEvent(".E+"); break; case ScientificKeyPad::Key_cos: m_sciexpressionBar->enterFunctionEvent("cos"); break; case ScientificKeyPad::Key_x3: m_sciexpressionBar->enterOperatorEvent("^3"); break; case ScientificKeyPad::Key_tan: m_sciexpressionBar->enterFunctionEvent("tan"); break; case ScientificKeyPad::Key_xy: m_sciexpressionBar->enterOperatorEvent("^"); break; case ScientificKeyPad::Key_cot: m_sciexpressionBar->enterFunctionEvent("cot"); break; case ScientificKeyPad::Key_10x: m_sciexpressionBar->enterConstantEvent("10^"); break; case ScientificKeyPad::Key_Modulus: m_sciexpressionBar->enterSpecialFuncEvent("abs("); break; case ScientificKeyPad::Key_log: m_sciexpressionBar->enterFunctionEvent("lg"); break; case ScientificKeyPad::Key_Rand: m_sciexpressionBar->enterRandEvent(); break; case ScientificKeyPad::Key_ln: m_sciexpressionBar->enterFunctionEvent("ln"); break; case ScientificKeyPad::Key_arcsin: m_sciexpressionBar->enterFunctionEvent("arcsin"); break; case ScientificKeyPad::Key_sqrt2: m_sciexpressionBar->enterFunctionEvent("sqrt"); break; case ScientificKeyPad::Key_arccos: m_sciexpressionBar->enterFunctionEvent("arccos"); break; case ScientificKeyPad::Key_sqrt3: m_sciexpressionBar->enterFunctionEvent("cbrt"); break; case ScientificKeyPad::Key_arctan: m_sciexpressionBar->enterFunctionEvent("arctan"); break; case ScientificKeyPad::Key_ysqrtx: m_sciexpressionBar->enterOperatorEvent("yroot"); break; case ScientificKeyPad::Key_arccot: m_sciexpressionBar->enterFunctionEvent("arccot"); break; case ScientificKeyPad::Key_2x: m_sciexpressionBar->enterConstantEvent("2^"); break; case ScientificKeyPad::Key_logyx: m_sciexpressionBar->enterOperatorEvent("log"); break; case ScientificKeyPad::Key_ex: m_sciexpressionBar->enterConstantEvent("e^"); break; case ScientificKeyPad::Key_opposite: m_sciexpressionBar->enterSpecialFuncEvent("(-"); break; default: break; } int left = 0; int right = 0; QString text = m_sciexpressionBar->getInputEdit()->text(); for (int i = 0; i < text.length(); i++) { if (text[i] == "(") left ++; else if (text[i] == ")") { if (left > 0) left--; else right++; } } m_scikeypadwidget->bracketsNum(0, QString::number(left)); //写入左右括号不匹配数 m_scikeypadwidget->bracketsNum(1, QString::number(right)); } /** * @brief 判断C/AC */ void scientificModule::handleClearStateChanged(bool isAllClear) { TextButton *btn = static_cast(m_scikeypadwidget->button(ScientificKeyPad::Key_Clear)); if (isAllClear) { btn->setText("AC"); } else { btn->setText("C"); } } /** * @brief 切换deg状态并发送deg切图信号 */ void scientificModule::handleDegChanged() { emit changedeg(m_deg); if (m_deg == 1) { m_deg = 2; } else if (m_deg == 2) { m_deg = 3; } else if (m_deg == 3) { m_deg = 1; } } /** * @brief FE是否被按下 */ void scientificModule::handleFEStateChanged(bool isdown) { TextButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_FE)); if (isdown) { m_FEisdown = true; } else { m_FEisdown = false; } btn->setButtonDown(m_FEisdown); } /** * @brief 切换2nd状态 */ void scientificModule::handlePageStateChanged() { TextButton *btn = static_cast(m_scikeypadwidget->button(ScientificKeyPad::Key_page)); if (m_Pageisdown) { m_Pageisdown = false; } else { m_Pageisdown = true; } btn->setButtonDown(m_Pageisdown); } /** * @brief m_stackWidget切换至m_memhiswidget */ void scientificModule::showMemHisWidget() { m_stackWidget->setCurrentWidget(m_memhiswidget); m_memhiswidget->getSimpleListModel()->updataOfSeparate(); m_memhiswidget->getMemoryWiget()->resetLabelBySeparator(); if (static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist))->hasFocus()) { //当前界面无历史focus到membuttonboxbutton if (!m_memhiswidget->findChild()->isHidden()) m_memhiswidget->findChild()->currentWidget()->setFocus(); else { m_memhiswidget->findChild("mButtonBoxButton")->setFocus(); } } else { m_memhiswidget->setFocus(); } MemoryButton *btn2 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mplus)); btn2->setbuttongray(true); btn2->setEnabled(false); MemoryButton *btn3 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mmin)); btn3->setbuttongray(true); btn3->setEnabled(false); MemoryButton *btn4 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MS)); btn4->setbuttongray(true); btn4->setEnabled(false); MemoryButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MR)); btn->setbuttongray(true); btn->setEnabled(false); MemoryButton *btn1 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MC)); btn1->setbuttongray(true); btn1->setEnabled(false); MemoryButton *btn5 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist)); btn5->setbtnlight(true); btn5->setEnabled(false); TextButton *btn6 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_FE)); btn6->setEnabled(false); m_isallgray = true; } /** * @brief m_stackWidget切换至m_scikeypadwidget */ void scientificModule::hideMemHisWidget() { m_stackWidget->setCurrentWidget(m_scikeypadwidget); m_isallgray = false; m_sciexpressionBar->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_memhiskeypad->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_sciexpressionBar->getInputEdit()->setFocus(); MemoryButton *btn2 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mplus)); btn2->setbuttongray(false); btn2->setEnabled(true); MemoryButton *btn3 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mmin)); btn3->setbuttongray(false); btn3->setEnabled(true); MemoryButton *btn4 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MS)); btn4->setbuttongray(false); btn4->setEnabled(true); MemoryButton *btn5 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist)); btn5->setbtnlight(false); btn5->setEnabled(true); TextButton *btn6 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_FE)); btn6->setEnabled(true); if (m_avail == true) { MemoryButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MC)); btn->setbuttongray(false); btn->setEnabled(true); MemoryButton *btn7 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MR)); btn7->setbuttongray(false); btn7->setEnabled(true); m_memRCbtn = true; } else { MemoryButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MC)); btn->setbuttongray(true); btn->setEnabled(false); MemoryButton *btn1 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MR)); btn->setbuttongray(true); btn1->setEnabled(false); if (m_havail == false) { MemoryButton *btn8 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist)); btn8->setEnabled(false); } m_memRCbtn = false; } m_sciexpressionBar->getInputEdit()->isExpressionEmpty(); //确认输入栏是否有内容,发送信号M+,M-,MS是否置灰 } /** * @brief 点击历史记录 */ void scientificModule::clickListView(const QModelIndex &index) { QString text = index.data(SimpleListModel::ExpressionWithOutTip).toString(); QStringList historic = text.split(QString("="), QString::SkipEmptyParts); //历史记录中无内容不继续执行 if (historic.size() != 2) return; m_sciexpressionBar->hisRevisionResults(index, m_memhiswidget->findChild()->getAnswer(index.row())); hideMemHisWidget(); } /** * @brief 焦点不在scientificmodul时也触发keypress */ void scientificModule::setKeyPress(QKeyEvent *e) { handleEditKeyPress(e); } /** * @brief memoryitem增加时mc,mr可用 */ void scientificModule::mAvailableEvent() { MemoryButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MC)); btn->setEnabled(true); MemoryButton *btn1 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MR)); btn1->setEnabled(true); MemoryButton *btn2 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist)); btn2->setEnabled(true); m_memRCbtn = true; m_avail = true; } /** * @brief mc后mc,mr不可用 */ void scientificModule::mUnAvailableEvent() { MemoryButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MC)); btn->setEnabled(false); MemoryButton *btn1 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MR)); btn1->setEnabled(false); if (m_stackWidget->currentWidget() == m_scikeypadwidget && m_havail == false) { MemoryButton *btn2 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist)); btn2->setEnabled(false); } m_memRCbtn = false; m_avail = false; } /** * @brief 切到标准模式时在初始化进行判断m+,m-,ms是否可用 */ void scientificModule::checkLineEmpty() { m_sciexpressionBar->getInputEdit()->isExpressionEmpty(); } /** * @brief 鼠标点击切换stackwidget */ void scientificModule::mousePressEvent(QMouseEvent *event) { //内存界面显示时,点击内存界面以外部分切换内存界面为键盘界面 if (m_stackWidget->currentWidget() == m_memhiswidget && !m_stackWidget->geometry().contains(event->pos())) { m_stackWidget->setCurrentWidget(m_scikeypadwidget); MemoryButton *btn2 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mplus)); btn2->setbuttongray(false); btn2->setEnabled(true); MemoryButton *btn3 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_Mmin)); btn3->setbuttongray(false); btn3->setEnabled(true); MemoryButton *btn4 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MS)); btn4->setbuttongray(false); btn4->setEnabled(true); MemoryButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MR)); btn->setbuttongray(false); btn->setEnabled(true); MemoryButton *btn1 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MC)); btn1->setbuttongray(false); btn1->setEnabled(true); MemoryButton *btn5 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist)); btn5->setbtnlight(false); btn5->setEnabled(true); TextButton *btn6 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_FE)); btn6->setEnabled(true); m_isallgray = false; m_sciexpressionBar->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_memhiskeypad->setAttribute(Qt::WA_TransparentForMouseEvents, false); m_sciexpressionBar->getInputEdit()->setFocus(); } if (m_avail == true) { MemoryButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MC)); btn->setEnabled(true); MemoryButton *btn4 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MR)); btn4->setEnabled(true); m_memRCbtn = true; } else { MemoryButton *btn = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MC)); btn->setEnabled(false); MemoryButton *btn1 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MR)); btn1->setEnabled(false); if (m_havail == false) { MemoryButton *btn5 = static_cast(m_memhiskeypad->button(MemHisKeypad::Key_MHlist)); btn5->setEnabled(false); } m_memRCbtn = false; } m_sciexpressionBar->getInputEdit()->isExpressionEmpty(); //确认输入栏是否有内容,发送信号M+,M-,MS是否置灰 QWidget::mousePressEvent(event); } /** * @brief 防止下拉菜单时鼠标点击拖拽可移动窗口 */ void scientificModule::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } deepin-calculator-5.7.21/src/widgets/scientificmodule.h000066400000000000000000000054651423020056600231450ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SCIENTIFICMODEL_H #define SCIENTIFICMODEL_H #include "../control/textbutton.h" #include "../control/iconbutton.h" #include "../control/scientifickeypad.h" #include "../control/memhiskeypad.h" #include "memhiswidget.h" #include "sciexpressionbar.h" #include "../views/memorywidget.h" #include "../memorypublic.h" #include #include #include #include DGUI_USE_NAMESPACE DWIDGET_USE_NAMESPACE /** * @brief 科学模式界面 */ class scientificModule : public DWidget { Q_OBJECT public: explicit scientificModule(QWidget *parent = nullptr); ~scientificModule(); void setKeyPress(QKeyEvent *e); void checkLineEmpty(); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *e); signals: void changedeg(int deg); public slots: //memory func void mAvailableEvent(); void mUnAvailableEvent(); private slots: void initTheme(int type); void clickListView(const QModelIndex &index); private: void handleEditKeyPress(QKeyEvent *); void handleKeypadButtonPress(int); void handleKeypadButtonPressByspace(int); void handleClearStateChanged(bool isAllClear); void handleDegChanged(); void handleFEStateChanged(bool isdown); void handlePageStateChanged(); void showMemHisWidget(); void hideMemHisWidget(); private: QStackedWidget *m_stackWidget; SciExpressionBar *m_sciexpressionBar; MemHisKeypad *m_memhiskeypad; ScientificKeyPad *m_scikeypadwidget; MemHisWidget *m_memhiswidget; MemoryPublic *m_memoryPublic; bool m_avail = false; //内存是否有内容 bool m_havail = false; //历史记录是否有内容 int m_deg = 1;//1-deg 2-rad 3-grad bool m_FEisdown = false; //FE按键是否被按下 bool m_Pageisdown = false; //2nd按键是否被按下 bool m_isinsidefun = false;//鼠标点击在函数widget内 bool m_memCalbtn; //m+,m-,ms bool m_memRCbtn;//mr,mc bool m_isallgray = false; //内存按钮全部置灰; }; #endif // SCIENTIFICMODEL_H deepin-calculator-5.7.21/src/widgets/sciexpressionbar.cpp000066400000000000000000001710671423020056600235370ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "sciexpressionbar.h" #include "../utils.h" #include "../globaldefine.h" #include "../../3rdparty/core/settings.h" #include #include #include #include #include const int SCIPREC = 31; //科学计算器精度 const int LIST_HEIGHT = 35; //输入栏上方表达式的高度 const int INPUTEDIT_HEIGHT = 55; SciExpressionBar::SciExpressionBar(QWidget *parent) : DWidget(parent) { m_listView = new SimpleListView(0, this); m_listDelegate = new SimpleListDelegate(0, this); m_listModel = new SimpleListModel(0, this); m_inputEdit = new InputEdit(this); m_evaluator = Evaluator::instance(); m_isContinue = true; m_isAllClear = false; m_isResult = false; m_inputNumber = false; m_isUndo = false; m_meanexp = true; m_listView->setModel(m_listModel); m_listView->setItemDelegate(m_listDelegate); // init inputEdit attributes. m_listView->setFixedHeight(LIST_HEIGHT); m_inputEdit->setFixedHeight(INPUTEDIT_HEIGHT); m_inputEdit->setAlignment(Qt::AlignRight); m_inputEdit->setTextMargins(10, 0, 10, 6); DPalette pl1 = this->palette(); pl1.setColor(DPalette::Button, Qt::transparent); pl1.setColor(DPalette::Highlight, Qt::transparent); pl1.setColor(DPalette::HighlightedText, Qt::blue); QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(m_listView); layout->addWidget(m_inputEdit); layout->setMargin(0); layout->setSpacing(0); initConnect(); Settings::instance()->angleUnit = 'd'; m_funclist = {"arcsin", "arccos", "arctan", "arccot", "sin", "cos", "tan", "cot" , "abs", "lg", "ln", "log", "mod", "sqrt", "cbrt", "yroot", "pi", "π", "e" }; } SciExpressionBar::~SciExpressionBar() {} void SciExpressionBar::mouseMoveEvent(QMouseEvent *e) { Q_UNUSED(e); } QPair SciExpressionBar::getexpression() { m_pair.second = m_expression; return m_pair; } Quantity SciExpressionBar::getanswer() { if (m_pair.first == true) return m_listanswer; return Quantity(); } void SciExpressionBar::enterNumberEvent(const QString &text) { if (!judgeinput()) return; if (m_inputNumber && m_isResult == true) { m_inputEdit->clear(); m_isResult = false; } if (m_isResult) { m_inputEdit->clear(); m_isResult = false; } if (!m_isContinue) { // the cursor position at the end, it will clear edit text. if (cursorPosAtEnd()) m_inputEdit->clear(); m_isContinue = true; } m_inputNumber = false; m_isUndo = false; // 20200401 修改symbolFaultTolerance执行位置 replaceSelection(m_inputEdit->text()); /* add 20200722 * 当输入数字的前面是e和pi时,在前面补乘号防止直接出现表达式错误 */ QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); QString sRegNum1 = "[πe]"; QRegExp rx1; rx1.setPattern(sRegNum1); if (curpos > 0 && rx1.exactMatch(exp.at(curpos - 1))) { m_inputEdit->insert("×" + text); } else m_inputEdit->insert(text); // m_inputEdit->insert(text); int nowcur = m_inputEdit->cursorPosition(); m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); m_inputEdit->setText(pointFaultTolerance(m_inputEdit->text())); m_inputEdit->setCursorPosition(nowcur); emit clearStateChanged(false); addUndo(); } void SciExpressionBar::enterSymbolEvent(const QString &text) { if (!judgeinput()) return; QString oldText = m_inputEdit->text(); QString symbol = text; symbol.replace(EN_DIV, CN_DIV); m_isResult = false; m_isUndo = false; // 20200213统一被选中光标复位代码 replaceSelection(m_inputEdit->text()); if (m_inputEdit->text().isEmpty()) { if (symbol != "-") { m_inputEdit->setText(oldText); } else { m_inputEdit->insert(symbol); } } else { int curPos = m_inputEdit->cursorPosition(); QString exp = m_inputEdit->text(); if (cursorPosAtEnd()) { if (m_inputEdit->text() == "-") { m_inputEdit->setText(oldText); } else { QString lastStr = exp.right(1); if (isOperator(lastStr)) exp.chop(1); m_inputEdit->setText(exp + symbol); } } else if (curPos == 0) { QString firstStr = exp.left(1); if (firstStr == CN_MIN) { m_inputEdit->setText(oldText); } else { if (symbol == CN_MIN || symbol == EN_MIN) m_inputEdit->insert(symbol); } } else { QString infront = exp.at(curPos - 1); QString behand = exp.at(curPos); if (isOperator(infront) || isOperator(behand)) { m_inputEdit->setText(oldText); } else m_inputEdit->insert(symbol); // 2020316修复添加符号后光标问题 //添加符号后左侧数字不会多分隔符,只需考虑添加符号后输入框光标前的数字与添加前是否一致 if (exp.mid(0, curPos).remove(QRegExp("[+-×÷/,.%()E]")) == m_inputEdit->text().mid(0, curPos).remove(QRegExp("[+-×÷/,.%()E]"))) { QString sRegNum = "[+-×÷/]"; QRegExp rx; rx.setPattern(sRegNum); rx.exactMatch(m_inputEdit->text().at(curPos)) ? m_inputEdit->setCursorPosition(curPos + 1) : m_inputEdit->setCursorPosition(curPos); } else m_inputEdit->setCursorPosition(curPos - 1); } } m_isContinue = true; expressionCheck(); if (!m_inputEdit->text().isEmpty()) { emit clearStateChanged(false); } addUndo(); } void SciExpressionBar::enterPercentEvent() { if (!judgeinput()) return; if (m_inputEdit->text().isEmpty()) { return; } m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(","); bool isAtEnd = cursorPosAtEnd(); /* * 当光标位置的前一位是运算符时,在函数方法前面补0,当函数的运算优先级小于等于 * 前一位运算符时,则补(0 * %做特殊处理--0%无效,故不显示 */ int diff = 0; //补数字后光标位移的距离 QString sRegNum = "[+-×÷/(^!%E]"; QRegExp rx; rx.setPattern(sRegNum); if (curpos == 0 || rx.exactMatch(exp.at(curpos - 1))) { m_inputEdit->insert(""); diff = -1; } else m_inputEdit->insert("%"); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(","); m_isUndo = false; m_isResult = false; addUndo(); if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != ",") { m_inputEdit->setCursorPosition(curpos + diff); } else { m_inputEdit->setCursorPosition(curpos + 1 + diff); } } else { m_inputEdit->setCursorPosition(curpos + 1 + diff); } } void SciExpressionBar::enterPointEvent() { if (!judgeinput()) return; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); if (curpos == 0) { m_inputEdit->insert("0."); } else { if (exp.at(curpos - 1) == ".") return; QString sRegNum = "[0-9,]+"; QRegExp rx; rx.setPattern(sRegNum); if (rx.exactMatch(exp.at(curpos - 1))) { int index = exp.indexOf(QRegExp("[^0-9,]"), curpos); QString cut = exp.mid(curpos, index - curpos); int aftercurpos = cut.count(","); int before = exp.count(","); m_inputEdit->insert("."); int after = m_inputEdit->text().count(","); if (before - aftercurpos == after) { m_inputEdit->setCursorPosition(curpos + 1); } else { m_inputEdit->setCursorPosition(curpos); } } else m_inputEdit->insert("0."); } exp = pointFaultTolerance(m_inputEdit->text()); if (exp != m_inputEdit->text()) m_inputEdit->setText(exp); m_isUndo = false; m_isResult = false; emit clearStateChanged(false); addUndo(); } void SciExpressionBar::enterBackspaceEvent() { QString sRegNum = "[a-z]"; //20200811去除大写字母,否则E将被看作函数 QRegExp rx; rx.setPattern(sRegNum); SSelection selection = m_inputEdit->getSelection(); if (!selection.selected.isEmpty()) { QString text = m_inputEdit->text(); QString seloldtext = text; int removepos = 0; //被删除位置 //光标不在开头且光标左侧是字母或者光标右侧是字母 if ((selection.curpos > 0 && rx.exactMatch(m_inputEdit->text().at(selection.curpos - 1))) || (selection.curpos + selection.selected.size() < m_inputEdit->text().size() && rx.exactMatch(m_inputEdit->text().at(selection.curpos + selection.selected.size())))) { int selleftfunlen = 0; //选中左侧一部分函数长度 int funpos = -1; int rightfunpos = -1; int j; for (int i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], selection.curpos - 1); if (funpos != -1 && (funpos <= selection.curpos) && (selection.curpos < funpos + m_funclist[i].length())) { selleftfunlen = selection.curpos - funpos; break; //光标在函数开头和函数结尾之间 } else funpos = -1; } for (j = 0; j < m_funclist.size(); j++) { //记录离光标最近的右侧函数位 rightfunpos = m_inputEdit->text().lastIndexOf(m_funclist[j], selection.curpos + selection.selected.size() - 1); if (rightfunpos != -1 && (rightfunpos + m_funclist[j].length() > selection.curpos + selection.selected.size())) break; else rightfunpos = -1; } if (funpos != -1 || rightfunpos != -1) { if (funpos != -1 && rightfunpos == -1) { removepos = funpos; text.remove(funpos, selection.selected.size() + selleftfunlen); //仅左侧有函数 } else if (rightfunpos != -1 && funpos == -1) { removepos = selection.curpos; text.remove(selection.curpos, rightfunpos + m_funclist[j].length() - selection.curpos); //仅右侧有函数 } else { removepos = funpos; text.remove(funpos, rightfunpos + m_funclist[j].length() - funpos); //函数中或左右均有 } } else { removepos = selection.curpos; text.remove(selection.curpos, selection.selected.size()); } } else { removepos = selection.curpos; text.remove(selection.curpos, selection.selected.size()); } m_inputEdit->setText(text); //输入栏删除被选中 // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); // 20200316选中部分光标置位问题修复 if ((seloldtext.mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) == m_inputEdit->text().mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) m_inputEdit->setCursorPosition(removepos); else if ((seloldtext.mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) > m_inputEdit->text().mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) m_inputEdit->setCursorPosition(removepos + 1); else m_inputEdit->setCursorPosition(removepos - 1); } else { QString text = m_inputEdit->text(); int cur = m_inputEdit->cursorPosition(); int funpos = -1; int i; if (text.size() > 0 && cur > 0 && text[cur - 1] == ",") { text.remove(cur - 2, 2); m_inputEdit->setText(text); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); m_inputEdit->setCursorPosition(cur - 2); } else { //退函数 //光标不在开头且光标左侧是字母 if (m_inputEdit->cursorPosition() > 0 && rx.exactMatch(m_inputEdit->text().at(m_inputEdit->cursorPosition() - 1))) { for (i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], m_inputEdit->cursorPosition() - 1); if (funpos != -1 && (funpos <= m_inputEdit->cursorPosition()) && (m_inputEdit->cursorPosition() <= funpos + m_funclist[i].length())) break; //光标在函数开头和函数结尾之间 else funpos = -1; } if (funpos != -1) { m_inputEdit->setText(m_inputEdit->text().remove(funpos, m_funclist[i].length())); m_inputEdit->setCursorPosition(funpos); } } else { int proNumber = text.count(","); m_inputEdit->backspace(); int separator = proNumber - m_inputEdit->text().count(","); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(","); if (cur > 0) { QString sRegNum1 = "[0-9]+"; QRegExp rx1; rx1.setPattern(sRegNum1); //退数字 if (rx1.exactMatch(text.at(cur - 1)) && proNumber > newPro) { if (text.mid(cur, text.length() - cur) == m_inputEdit->text().mid(m_inputEdit->text().length() - (text.length() - cur), text.length() - cur)) { m_inputEdit->setCursorPosition(cur - 2); } else m_inputEdit->setCursorPosition(cur - 1); } else { if (separator < 0) { m_inputEdit->setCursorPosition(cur - 1 - separator); } else { m_inputEdit->setCursorPosition(cur - 1); } } //退小数点 if (text.at(cur - 1) == ".") { if (text.mid(0, cur).count(",") != m_inputEdit->text().mid(0, cur).count(",")) m_inputEdit->setCursorPosition(cur); else m_inputEdit->setCursorPosition(cur - 1); } } } } } if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } if (pointFaultTolerance(m_inputEdit->text()) != m_inputEdit->text()) { QTimer::singleShot(5000, this, &SciExpressionBar::pointCheckAfterDelete); } m_isResult = false; m_isContinue = true; m_isUndo = false; addUndo(); } void SciExpressionBar::enterClearEvent() { bool need_addundo = !m_inputEdit->text().isEmpty(); if (m_isAllClear) { m_listModel->clearItems(); m_listView->reset(); m_isAllClear = false; emit clearStateChanged(false); } else { if (m_listModel->rowCount(QModelIndex()) == 0) emit clearStateChanged(false); else emit clearStateChanged(true); m_inputEdit->clear(); m_isAllClear = true; } m_isResult = false; m_isUndo = false; if (need_addundo) addUndo(); m_FEisdown = false; emit fEStateChanged(false); } void SciExpressionBar::enterEqualEvent() { // m_evaluator->setVariable(QLatin1String("e"), DMath::e(), Variable::BuiltIn); QString exp = m_inputEdit->text(); if (m_inputEdit->text().isEmpty()) { m_pair.first = false; return; } const QString expression = formatExpression(m_inputEdit->expressionText()); QString exp1 = symbolComplement(expression); m_evaluator->setExpression(exp1); Quantity ans = m_evaluator->evalUpdateAns(); // 20200403 bug-18971 表达式错误时输数字加等于再重新输入表达式历史记录错误表达式未被替换 // 20200407 超过16位小数未科学计数 qDebug() << "m_evaluator->error()" << m_evaluator->error(); qDebug() << "ans" << m_inputEdit->expressionText(); if (m_evaluator->error().isEmpty() && (exp.indexOf(QRegExp("[a-z+-×÷/.,%()πe^!]")) != -1)) { if (ans.isNan() && !m_evaluator->isUserFunctionAssign()) { m_pair.first = false; m_expression = exp + "=" + tr("Expression error"); m_listModel->updataList(m_expression, -1, true); return; } //edit 20200413 for bug--19653 QString result; if (m_FEisdown) result = DMath::format(ans, Quantity::Format::Scientific() + Quantity::Format::Precision(SCIPREC)); else result = DMath::format(ans, Quantity::Format::General() + Quantity::Format::Precision(SCIPREC)); QString formatResult = Utils::formatThousandsSeparators(result); formatResult = formatResult.replace(CN_ADD, EN_ADD) .replace(CN_MIN, EN_MIN) .replace(CN_MUL, EN_MUL) .replace(CN_DIV, EN_DIV); //.replace(QString::fromUtf8(","), ""); // QString tStr = m_inputEdit->text().replace(QString::fromUtf8(","), ""); QString tStr = m_inputEdit->text(); //edit 20200518 for bug-26628 QString StrToComp = formatResult; StrToComp = StrToComp.replace(EN_ADD, CN_ADD) .replace(EN_MIN, CN_MIN) .replace(EN_MUL, CN_MUL) .replace(EN_DIV, CN_DIV); if (StrToComp == exp) { m_pair.first = false; return; } //end edit 20200518 for bug-26628 // 20200402 需求3.2.1.6当输入的数字中有千位符,点击等号视为前后一致,不计入表达式 if (formatResult != tStr) { // m_listModel->updataList(m_inputEdit->text() + "=" + formatResult, m_hisRevision); m_inputEdit->setAnswer(formatResult, ans); } m_isContinue = false; m_inputEdit->setText(formatResult); formatResult = formatResult.replace(EN_MIN, CN_MIN); m_pair.first = true; m_expression = exp + "=" + formatResult; m_listModel->updataList(m_expression, -1, true); m_listanswer = ans; } else { m_pair.first = false; if (!m_evaluator->error().isEmpty()) { m_expression = exp + "=" + tr("Expression error"); m_listModel->updataList(m_expression, -1, true); } else { return; } } m_isResult = true; m_isUndo = false; addUndo(); } /** * @brief SciExpressionBar::enterDegEvent * 弧度/角度/梯度切换 * @param mod */ void SciExpressionBar::enterDegEvent(int mod) { //mod=1,enter走rad运算 emit turnDeg(); if (mod == 1) Settings::instance()->angleUnit = 'r'; else if (mod == 2) { Settings::instance()->angleUnit = 'g'; } else { Settings::instance()->angleUnit = 'd'; } } /** * @brief SciExpressionBar::enterFEEvent * 是否以科学计数法的方式输出计算结果,状态可切换,按清除键后还原。 * 默认不以科学计数法显示 * @param isdown * 是否被按下 */ void SciExpressionBar::enterFEEvent(bool isdown) { if (isdown) { m_FEisdown = false; emit fEStateChanged(false); } else { m_FEisdown = true; emit fEStateChanged(true); } } void SciExpressionBar::enterRandEvent() { m_inputEdit->clear(); m_isResult = false; m_isUndo = false; QString str; for (int i = 0; i < SCIPREC; i++) { int n = qrand() % 10; str.append(QString::number(n)); } str = "0." + str; m_isResult = false; m_inputEdit->setText(str); if (!m_inputEdit->text().isEmpty()) emit clearStateChanged(false); addUndo(); } void SciExpressionBar::enterOperatorEvent(const QString &text) { if (!judgeinput()) return; QString zerotext = "0" + text; QString brackettext = "(0" + text; int length = text.length(); emit clearStateChanged(false); if (m_inputEdit->text().isEmpty()) { m_inputEdit->setText(zerotext); m_isResult = false; m_isUndo = false; addUndo(); return; } m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(","); bool isAtEnd = cursorPosAtEnd(); /* * 当光标位置的前一位是运算符时,在函数方法前面补0,当函数的运算优先级小于等于 * 前一位运算符时,则补(0 */ int diff = 0; //补数字后光标位移的距离 QString sRegNum = "[+-×÷/(^]"; QRegExp rx; rx.setPattern(sRegNum); if (curpos == 0) { m_inputEdit->insert(zerotext); diff = 1; } else if (rx.exactMatch(exp.at(curpos - 1))) { if (exp.at(curpos - 1) == "^") { m_inputEdit->insert(brackettext); diff = 2; } else { m_inputEdit->insert(zerotext); diff = 1; } } else m_inputEdit->insert(text); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(","); m_isUndo = false; if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != ",") { m_inputEdit->setCursorPosition(curpos + length - 1 + diff); } else { m_inputEdit->setCursorPosition(curpos + length + diff); } //对于^2,^3类型的,在后面接数字的时候补乘号 if (isnumber(text.back()) && isnumber(m_inputEdit->text().at(m_inputEdit->cursorPosition()))) { m_inputEdit->insert("×"); m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() - 1); } } else { m_inputEdit->setCursorPosition(curpos + length + diff); } addUndo(); } void SciExpressionBar::enterFunctionEvent(const QString &text) { if (!judgeinput()) return; QString function = text + "()"; int length = text.length(); m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(","); bool isAtEnd = cursorPosAtEnd(); m_inputEdit->insert(function); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(","); m_isUndo = false; addUndo(); if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != ",") { m_inputEdit->setCursorPosition(curpos + length); } else { m_inputEdit->setCursorPosition(curpos + length + 1); } } else { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() - 1); } emit clearStateChanged(false); } void SciExpressionBar::enterConstantEvent(const QString &text) { if (!judgeinput()) return; m_isResult = false; QString multitext = "×" + text; int length = text.length(); replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(","); bool isAtEnd = cursorPosAtEnd(); /* add 20200722 * 当e和pi前面是数字类型的字符时,在前面补乘号防止直接出现表达式错误 */ int multi = 0;//是否需要补乘号 if (curpos > 0 && isnumber(exp.at(curpos - 1))) { m_inputEdit->insert(multitext); multi = 1; } else m_inputEdit->insert(text); // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(","); m_isUndo = false; addUndo(); if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != ",") { m_inputEdit->setCursorPosition(curpos + length - 1 + multi); } else { m_inputEdit->setCursorPosition(curpos + length + multi); } } emit clearStateChanged(false); } void SciExpressionBar::enterBracketEvent(const int &type) { if (!judgeinput()) return; if (m_inputEdit->text().count("(") >= 100 && type == 1) return; if (m_inputEdit->text().count(")") >= 100 && type == 2) return; m_isResult = false; replaceSelection(m_inputEdit->text()); QString exp = m_inputEdit->text(); int curpos = m_inputEdit->cursorPosition(); int proNumber = m_inputEdit->text().count(","); bool isAtEnd = cursorPosAtEnd(); switch (type) { case 1: m_inputEdit->insert("("); break; default: m_inputEdit->insert(")"); break; } // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); int newPro = m_inputEdit->text().count(","); m_isUndo = false; addUndo(); if (!isAtEnd) { if (newPro < proNumber && exp.at(curpos) != ",") { m_inputEdit->setCursorPosition(curpos); } else { m_inputEdit->setCursorPosition(curpos + 1); } } emit clearStateChanged(false); } void SciExpressionBar::enterSpecialFuncEvent(const QString &text) { if (!judgeinput()) return; if (m_inputEdit->text().isEmpty()) { if (text == "abs(") { m_inputEdit->setText("abs(0)"); m_isResult = false; m_isUndo = false; addUndo(); emit clearStateChanged(false); return; } return; } emit clearStateChanged(false); QString exptext = m_inputEdit->text();//表达式 // 20200316百分号选中部分格式替代 replaceSelection(m_inputEdit->text()); int curPos = m_inputEdit->cursorPosition(); if (m_inputEdit->text() == QString()) { m_inputEdit->setText(text); m_isResult = false; m_isUndo = false; addUndo(); return; } m_isResult = false; m_isUndo = false; if (!expressionInFunc(exptext)) { m_inputEdit->setText(exptext); m_inputEdit->setCursorPosition(curPos); return; } else { if (exptext.count("(") == exptext.count(")")) { m_inputEdit->setCursorPosition(curPos - exptext.length()); if (text == "1/(" && curPos - exptext.length() > 0 && isnumber(m_inputEdit->text().at(curPos - exptext.length() - 1))) { m_inputEdit->insert("×1/("); } else m_inputEdit->insert(text); int afterinsertpos = m_inputEdit->cursorPosition(); m_inputEdit->setCursorPosition(afterinsertpos + exptext.length()); m_inputEdit->insert(")"); } } addUndo(); } void SciExpressionBar::copyResultToClipboard() { if (m_inputEdit->text().isEmpty()) return; SSelection selection = m_inputEdit->getSelection(); QApplication::clipboard()->setText(selection.selected); //将选中项放入粘贴板 } void SciExpressionBar::copyClipboard2Result() { if (!judgeinput()) return; QString oldText = m_inputEdit->text(); //未粘贴操作的text int curpos = m_inputEdit->cursorPosition(); //未粘贴操作的光标位 replaceSelection(oldText); QString exp = m_inputEdit->text(); QString text = Utils::toHalfWidth(QApplication::clipboard()->text()); text = text.left(text.indexOf("=")); text = text.replace(EN_ADD, CN_ADD) .replace(EN_MIN, CN_MIN) .replace(EN_Underscore, CN_MIN) .replace(EN_MUL, CN_MUL) .replace('x', CN_MUL) .replace('X', CN_MUL) .replace(CN_Asterisk, CN_MUL) .replace(CN_LBracket, EN_LBracket) .replace(CN_RBracket, EN_RBracket) .replace(CN_Underscore, CN_MIN) .replace(CN_Percent, EN_Percent) .replace(EN_DIV, CN_DIV) .replace(" ", ""); //对粘贴板中的内容进行英替中 //匹配函数方法 QStringList list = text.split(QRegExp("[0-9+-×÷/()%^!E.,。]")); //正则表达式中为科学模式下可存在的非字母;函数中;无法被复制 for (int i = 0; i < list.size(); i++) { QString item = list[i]; for (int j = 0; j < m_funclist.size(); j++) { if (item.toLower().contains(m_funclist[j])) { item.replace(item, m_funclist[j]); //包含函数名的取出;item中若存在两个函数名,只可以替代最前面的函数名 break; } if (j == m_funclist.size() - 1) item.replace(item, QString()); } text.replace(list[i], item); } while (exp.count("(") + text.count("(") > 100) { text.remove(text.lastIndexOf("("), 1); } while (exp.count(")") + text.count(")") > 100) { text.remove(text.lastIndexOf(")"), 1); } m_inputEdit->insert(text); QString faulttolerance = pointFaultTolerance(m_inputEdit->text()); faulttolerance = m_inputEdit->symbolFaultTolerance(faulttolerance); if (faulttolerance != m_inputEdit->text()) m_inputEdit->setText(faulttolerance); //如果经过容错处理的表达式有改变,重新设置表达式,不设置光标 if (m_inputEdit->text() == exp) { m_inputEdit->setText(oldText); m_inputEdit->setCursorPosition(curpos); qDebug() << "Invalid content"; //提示是否复制了无效内容,复制的内容全是字母等 } if (!m_inputEdit->text().isEmpty()) emit clearStateChanged(false); m_isResult = false; m_isUndo = false; addUndo(); } void SciExpressionBar::allElection() { m_inputEdit->selectAll(); SSelection selection; selection.selected = m_inputEdit->text(); m_inputEdit->setSelection(selection); } void SciExpressionBar::shear() { QString sRegNum = "[a-z]"; //20200811去除大写字母,否则E将被看作函数 QRegExp rx; rx.setPattern(sRegNum); SSelection selection = m_inputEdit->getSelection(); QString selectText = m_inputEdit->selectedText(); selectText = selectText.replace(",", ""); QApplication::clipboard()->setText(selectText); int removepos = 0; //被删除位置 QString text = m_inputEdit->text(); QString seloldtext = text; //光标不在开头且光标左侧是字母或者光标右侧是字母 if ((selection.curpos > 0 && rx.exactMatch(m_inputEdit->text().at(selection.curpos - 1))) || (selection.curpos + selection.selected.size() < m_inputEdit->text().size() && rx.exactMatch(m_inputEdit->text().at(selection.curpos + selection.selected.size())))) { int selleftfunlen = 0; //选中左侧一部分函数长度 int funpos = -1; int rightfunpos = -1; int j; for (int i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], selection.curpos - 1); if (funpos != -1 && (funpos <= selection.curpos) && (selection.curpos < funpos + m_funclist[i].length())) { selleftfunlen = selection.curpos - funpos; break; //光标在函数开头和函数结尾之间 } else funpos = -1; } for (j = 0; j < m_funclist.size(); j++) { //记录离光标最近的右侧函数位 rightfunpos = m_inputEdit->text().lastIndexOf(m_funclist[j], selection.curpos + selection.selected.size() - 1); if (rightfunpos != -1 && (rightfunpos + m_funclist[j].length() > selection.curpos + selection.selected.size())) break; else rightfunpos = -1; } if (funpos != -1 || rightfunpos != -1) { if (funpos != -1 && rightfunpos == -1) { removepos = funpos; text.remove(funpos, selection.selected.size() + selleftfunlen); //仅左侧有函数 } else if (rightfunpos != -1 && funpos == -1) { removepos = selection.curpos; text.remove(selection.curpos, rightfunpos + m_funclist[j].length() - selection.curpos); //仅右侧有函数 } else { removepos = funpos; text.remove(funpos, rightfunpos + m_funclist[j].length() - funpos); //函数中或左右均有 } } else { removepos = selection.curpos; text.remove(selection.curpos, selection.selected.size()); } } else { removepos = selection.curpos; text.remove(selection.curpos, selection.selected.size()); } m_inputEdit->setText(text); //输入栏删除被选中 // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); // 20200316选中部分光标置位问题修复 if ((seloldtext.mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) == m_inputEdit->text().mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) m_inputEdit->setCursorPosition(removepos); else if ((seloldtext.mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) > m_inputEdit->text().mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) m_inputEdit->setCursorPosition(removepos + 1); else m_inputEdit->setCursorPosition(removepos - 1); // 20200401 选中部分左侧为分隔符按退格的光标处理 if (pointFaultTolerance(m_inputEdit->text()) != m_inputEdit->text()) { QTimer::singleShot(5000, this, &SciExpressionBar::pointCheckAfterDelete); } // end fix m_isResult = false; if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } m_isContinue = true; m_isUndo = false; addUndo(); } /** * @brief 删除事件,选中删除 */ void SciExpressionBar::deleteText() { QString sRegNum = "[a-z]"; //20200811去除大写字母,否则E将被看作函数 QRegExp rx; rx.setPattern(sRegNum); SSelection selection = m_inputEdit->getSelection(); int removepos = 0; //被删除位置 QString text = m_inputEdit->text(); QString seloldtext = text; //光标不在开头且光标左侧是字母或者光标右侧是字母 if ((selection.curpos > 0 && rx.exactMatch(m_inputEdit->text().at(selection.curpos - 1))) || (selection.curpos + selection.selected.size() < m_inputEdit->text().size() && rx.exactMatch(m_inputEdit->text().at(selection.curpos + selection.selected.size())))) { int selleftfunlen = 0; //选中左侧一部分函数长度 int funpos = -1; int rightfunpos = -1; int j; for (int i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], selection.curpos - 1); if (funpos != -1 && (funpos <= selection.curpos) && (selection.curpos < funpos + m_funclist[i].length())) { selleftfunlen = selection.curpos - funpos; break; //光标在函数开头和函数结尾之间 } else funpos = -1; } for (j = 0; j < m_funclist.size(); j++) { //记录离光标最近的右侧函数位 rightfunpos = m_inputEdit->text().lastIndexOf(m_funclist[j], selection.curpos + selection.selected.size() - 1); if (rightfunpos != -1 && (rightfunpos + m_funclist[j].length() > selection.curpos + selection.selected.size())) break; else rightfunpos = -1; } if (funpos != -1 || rightfunpos != -1) { if (funpos != -1 && rightfunpos == -1) { removepos = funpos; text.remove(funpos, selection.selected.size() + selleftfunlen); //仅左侧有函数 } else if (rightfunpos != -1 && funpos == -1) { removepos = selection.curpos; text.remove(selection.curpos, rightfunpos + m_funclist[j].length() - selection.curpos); //仅右侧有函数 } else { removepos = funpos; text.remove(funpos, rightfunpos + m_funclist[j].length() - funpos); //函数中或左右均有 } } else { removepos = selection.curpos; text.remove(selection.curpos, selection.selected.size()); } } else { removepos = selection.curpos; text.remove(selection.curpos, selection.selected.size()); } m_inputEdit->setText(text); //输入栏删除被选中 // 20200401 symbolFaultTolerance m_inputEdit->setText(m_inputEdit->symbolFaultTolerance(m_inputEdit->text())); // 20200316选中部分光标置位问题修复 if ((seloldtext.mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) == m_inputEdit->text().mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) m_inputEdit->setCursorPosition(removepos); else if ((seloldtext.mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) > m_inputEdit->text().mid(0, removepos).remove(QRegExp("[+-×÷/,.%()E]")).length()) m_inputEdit->setCursorPosition(removepos + 1); else m_inputEdit->setCursorPosition(removepos - 1); // 20200401 选中部分左侧为分隔符按退格的光标处理 if (pointFaultTolerance(m_inputEdit->text()) != m_inputEdit->text()) { QTimer::singleShot(5000, this, &SciExpressionBar::pointCheckAfterDelete); } // end fix m_isResult = false; if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } m_isContinue = true; m_isUndo = false; addUndo(); return; } void SciExpressionBar::handleTextChanged(const QString &text) { Q_UNUSED(text); m_isAllClear = false; m_isContinue = true; } void SciExpressionBar::pointCheckAfterDelete() { int curpos = m_inputEdit->cursorPosition(); m_inputEdit->setText(pointFaultTolerance(m_inputEdit->text())); m_inputEdit->setCursorPosition(curpos); } bool SciExpressionBar::cursorPosAtEnd() { return m_inputEdit->cursorPosition() == m_inputEdit->text().length(); } QString SciExpressionBar::formatExpression(const QString &text) { return QString(text) .replace(CN_ADD, EN_ADD) .replace(CN_MIN, EN_MIN) .replace(CN_MUL, EN_MUL) .replace(CN_DIV, EN_DIV) .replace(EN_Comma, "") .replace(EN_PI, QLatin1String("pi")); } void SciExpressionBar::revisionResults(const QModelIndex &index) { // clearLinkageCache(m_inputEdit->text(), false); QString text = index.data(SimpleListModel::ExpressionRole).toString(); QStringList historic = text.split(QString("="), QString::SkipEmptyParts); if (historic.size() != 2) return; QString expression = historic.at(0); // m_hisRevision = index.row(); m_inputEdit->setText(expression); // m_Selected = m_hisRevision; m_isResult = false; // fix addundo for history revision m_isUndo = false; addUndo(); emit clearStateChanged(false); } /** * @brief 点击右侧历史记录 */ void SciExpressionBar::hisRevisionResults(const QModelIndex &index, Quantity ans) { QString text = index.data(SimpleListModel::ExpressionWithOutTip).toString(); // QStringList historic = text.split(QString("="), QString::SkipEmptyParts); // if (historic.size() != 2) // return; QString expression = DMath::format(ans, Quantity::Format::General() + Quantity::Format::Precision(SCIPREC)); // m_hisRevision = index.row(); m_inputEdit->setAnswer(expression, ans); m_listModel->updataList(text, -1, true); // m_Selected = m_hisRevision; m_isResult = false; // fix addundo for history revision m_isUndo = false; addUndo(); m_inputEdit->setFocus(); emit clearStateChanged(false); //清除按键为C } bool SciExpressionBar::judgeinput() { QString sRegNum = "[A-Za-z]"; QRegExp rx; rx.setPattern(sRegNum); SSelection selection = m_inputEdit->getSelection(); if (selection.selected != "") { //光标不在开头且光标左侧是字母或者光标右侧是字母 if ((selection.curpos > 0 && rx.exactMatch(m_inputEdit->text().at(selection.curpos - 1))) || (selection.curpos + selection.selected.size() < m_inputEdit->text().size() && rx.exactMatch(m_inputEdit->text().at(selection.curpos + selection.selected.size())))) { int funpos = -1; int rightfunpos = -1; for (int i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], selection.curpos - 1); if (funpos != -1 && (funpos <= selection.curpos) && (selection.curpos < funpos + m_funclist[i].length())) { return false; //选中左侧在函数中 } } for (int j = 0; j < m_funclist.size(); j++) { //记录离光标最近的右侧函数位 rightfunpos = m_inputEdit->text().lastIndexOf(m_funclist[j], selection.curpos + selection.selected.size() - 1); if (rightfunpos != -1 && (rightfunpos + m_funclist[j].length() > selection.curpos + selection.selected.size())) return false; //选中右侧在函数中 } } return true; } else { if (m_inputEdit->cursorPosition() > 0 && rx.exactMatch(m_inputEdit->text().at(m_inputEdit->cursorPosition() - 1))) { for (int i = 0; i < m_funclist.size(); i++) { //记录光标左侧离光标最近的函数位 int funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], m_inputEdit->cursorPosition() - 1); if (funpos != -1 && (funpos < m_inputEdit->cursorPosition()) && (m_inputEdit->cursorPosition() < funpos + m_funclist[i].length())) return false; //光标在函数中 } } return true; } } void SciExpressionBar::initConnect() { connect(m_listView, &SimpleListView::obtainingHistoricalSimple, this, &SciExpressionBar::revisionResults); connect(m_listView, &SimpleListView::obtainingHistoricalSimple, m_inputEdit, &InputEdit::hisexpression); connect(m_inputEdit, &InputEdit::textChanged, this, &SciExpressionBar::handleTextChanged); connect(m_inputEdit, &InputEdit::keyPress, this, &SciExpressionBar::keyPress); connect(m_inputEdit, &InputEdit::equal, this, &SciExpressionBar::enterEqualEvent); connect(m_inputEdit, &InputEdit::cut, this, &SciExpressionBar::shear); connect(m_inputEdit, &InputEdit::copy, this, &SciExpressionBar::copyResultToClipboard); connect(m_inputEdit, &InputEdit::paste, this, &SciExpressionBar::copyClipboard2Result); connect(m_inputEdit, &InputEdit::deleteText, this, &SciExpressionBar::deleteText); connect(m_inputEdit, &InputEdit::selectAllText, this, &SciExpressionBar::allElection); connect(m_inputEdit, &InputEdit::undo, this, &SciExpressionBar::Undo); connect(m_inputEdit, &InputEdit::redo, this, &SciExpressionBar::Redo); connect(m_inputEdit, &InputEdit::setResult, this, &SciExpressionBar::setResultFalse); connect(m_inputEdit, &InputEdit::separateChange, this, &SciExpressionBar::onSeparateChange); } QString SciExpressionBar::symbolComplement(const QString exp) { QString text = exp; int index = text.indexOf("(", 0); while (index != -1) { if (index >= 1 && text.at(index - 1).isNumber()) { text.insert(index, "×"); ++index; } ++index; index = text.indexOf("(", index); } index = text.indexOf(")", 0); while (index != -1) { if (index < text.length() - 1 && text.at(index + 1).isNumber()) { text.insert(index + 1, "×"); ++index; } ++index; index = text.indexOf(")", index); } //20200811 fix bug-42274 e,π,lastans跟随函数表达式错误问题 index = text.indexOf("e", 0); while (index != -1) { text.insert(index, "("); text.insert(index + 2, ")"); index = text.indexOf("e", index + 3); } index = text.indexOf("pi", 0); while (index != -1) { text.insert(index, "("); text.insert(index + 3, ")"); index = text.indexOf("pi", index + 4); } index = text.indexOf("lastans", 0); while (index != -1) { text.insert(index, "("); text.insert(index + 8, ")"); index = text.indexOf("lastans", index + 9); } return text; } QString SciExpressionBar::pointFaultTolerance(const QString &text) { QString oldText = text; // QString reformatStr = Utils::reformatSeparators(QString(text).remove(',')); QString reformatStr = oldText.replace(EN_ADD, CN_ADD) .replace(EN_MIN, CN_MIN) .replace(EN_Underscore, CN_MIN) .replace(EN_MUL, CN_MUL) .replace('x', CN_MUL) .replace('X', CN_MUL) .replace(CN_Asterisk, CN_MUL) .replace(CN_LBracket, EN_LBracket) .replace(CN_RBracket, EN_RBracket) .replace(CN_Underscore, CN_MIN) .replace(CN_Percent, EN_Percent) /*.replace('/', QString::fromUtf8("÷"))*/; //对内容进行英替中 QStringList list = reformatStr.split(QRegExp("[+-×÷/(]")); //20200717去掉),否则下方)小数点容错无法进入 QStringList symbollist; for (int i = 0; i < reformatStr.size(); ++i) { if (QRegExp("[+-×÷/(]").exactMatch(reformatStr.at(i))) symbollist << reformatStr.at(i); } reformatStr.clear(); for (int i = 0; i < list.size(); ++i) { QString item = list[i]; int firstPoint = item.indexOf("."); if (item.contains(QString::fromUtf8("。"))) { if (firstPoint >= 0) item.remove(QString::fromUtf8("。")); else item.replace(QString::fromUtf8("。"), "."); firstPoint = item.indexOf("."); } if (firstPoint == -1) { reformatStr += item; if (!symbollist.isEmpty()) { reformatStr += symbollist.first(); symbollist.pop_front(); } continue; } if (firstPoint == 0) { item.insert(firstPoint, "0"); //小数点在数字前,进行补0;例:.123->0.123;此处未对reformatStr进行操作,导致只有两个.时才会进行补0 ++firstPoint; // oldText.replace(list[i], item); } else { if (item.at(firstPoint - 1) == ")" || item.at(firstPoint - 1) == "%") { item.remove(firstPoint, 1); item.insert(firstPoint, "0."); //20200717)及%后小数点补0;与小数点输入处理一致 } } if (item.count(".") > 1) { item.remove("."); item.insert(firstPoint, "."); } reformatStr += item; if (!symbollist.isEmpty()) { reformatStr += symbollist.first(); symbollist.pop_front(); } } for (int i = 0; i < reformatStr.size(); ++i) { //20200811避免e,π后的小数点补0 if (reformatStr[i] == "." && (i == 0 || (!reformatStr[i - 1].isNumber() && reformatStr[i - 1] != "e" && reformatStr[i - 1] != "π"))) { reformatStr.insert(i, "0"); //补0操作,例:1+.2->1+0.2 ++i; } } return reformatStr; } void SciExpressionBar::expressionCheck() { QString exp = m_inputEdit->text(); int cur = m_inputEdit->cursorPosition(); //光标前的分隔符 int separator = 0; for (int i = 0; i < exp.size(); ++i) { if (exp[i] == ",") { exp.remove(i, 1); --i; if (i + 1 < cur) { ++separator; --cur; } } } for (int i = 0; i < exp.size(); ++i) { while (exp[i].isNumber()) { // fix for delete 0 behind "." if (exp[i] == "0" && exp[i + 1] != "." && (i == 0 || exp[i - 1] != ".") && (i == 0 || !exp[i - 1].isNumber()) && (exp.size() == 1 || exp[i + 1].isNumber())) { exp.remove(i, 1); --i; if (i + 1 < cur) --cur; } ++i; } if (exp[i] == "." && (i == 0 || !exp[i - 1].isNumber())) { exp.insert(i, "0"); ++i; if (i < cur) ++cur; } } m_inputEdit->setText(exp); m_inputEdit->setCursorPosition(cur + separator); } bool SciExpressionBar::isnumber(QChar a) { if (a.isDigit() || a == "." || a == "," || a == EN_PI || a == EN_Eular) return true; else return false; } /** * 点击倒数、绝对值、相反数时包含的表达式 */ bool SciExpressionBar::expressionInFunc(QString &text) { QString oldText = text; int curPos = m_inputEdit->cursorPosition(); int epos = m_inputEdit->text().indexOf("E"); QString sRegNum = "[0-9,.E]"; QRegExp rx; rx.setPattern(sRegNum); if (curPos == 0) { return false; } if (m_inputEdit->text().length() > curPos && rx.exactMatch(m_inputEdit->text().at(curPos))) { return false; } if (epos > -1 && epos == curPos - 1) { return false; } // start edit for task-13519 QString sRegNum1 = "[^0-9,.)πe]"; QRegExp rx1; rx1.setPattern(sRegNum1); if (rx1.exactMatch(oldText.at(curPos - 1))) return false; else { QString newtext = m_inputEdit->text(); int percentpos = m_inputEdit->cursorPosition(); int operatorpos = newtext.lastIndexOf(QRegularExpression(QStringLiteral("[^0-9,.eπE]")), percentpos - 1); bool nooperator = false; if (operatorpos > 0 && newtext.at(operatorpos - 1) == "E") operatorpos = newtext.mid(0, operatorpos - 1) .lastIndexOf(QRegularExpression(QStringLiteral("[^0-9,.eπE]")), percentpos - 1); /*出现以下情况: * 1. 负号在表达式的开头,如-1,-120等,视为一个整体的负数 * 2. 负号在左括号的后一位,如(-1, (-121等,也视为一个整体的负数 * 其中,当出现(-12)时,光标在右括号右侧时则会优先取到 ")",只有在右括号左侧才满足条件2*/ if ((operatorpos == 0 && newtext.at(0) == "-") || (operatorpos > 0 && newtext.at(operatorpos) == "-" && newtext.at(operatorpos - 1) == "(")) operatorpos--; if (operatorpos < 0) { operatorpos++; nooperator = true; } // QString exptext; //表达式 if (newtext.at(percentpos - 1) == ')') { if (operatorpos > 0 && newtext.at(operatorpos - 1) == '(') return false; do { operatorpos = newtext.lastIndexOf('(', operatorpos - 1); if (operatorpos <= 0) { break; } } while (newtext.mid(operatorpos, newtext.size() - operatorpos).count('(') != newtext.mid(operatorpos, percentpos - operatorpos).count(')')); //匹配到的(不在开头且(左侧是字母 QString sRegNum2 = "[A-Za-z]"; QRegExp latterrx; latterrx.setPattern(sRegNum2); if (operatorpos > 0 && latterrx.exactMatch(m_inputEdit->text().at(operatorpos - 1))) { int funpos = -1; //记录函数位 int i; for (i = 0; i < m_funclist.size(); i++) { //记录(左侧离(最近的函数位 funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], operatorpos - 1); if (funpos != -1 && (funpos + m_funclist[i].length() == operatorpos)) break; //(在函数结尾 else funpos = -1; } if (funpos != -1) operatorpos = operatorpos - m_funclist[i].length(); //截取函数 } else if (operatorpos > 1 && m_inputEdit->text().mid(operatorpos - 2, 2) == "1/") { operatorpos = operatorpos - 2; //截取倒数 } text = newtext.mid(operatorpos, percentpos - operatorpos); //截取表达式 } else { text = newtext.mid(operatorpos + (nooperator == true ? 0 : 1), percentpos - operatorpos + (nooperator == true ? 1 : 0) - 1); //截取表达式 } } return true; } void SciExpressionBar::Undo() { if (m_undo.isEmpty()) return; // clearLinkageCache(); m_redo.append(m_undo.last()); m_inputEdit->setRedoAction(true); m_undo.removeLast(); m_isUndo = true; //20200619 从结果撤销到上一次表达式按下数字键不清空输入框 if (m_isResult) m_isResult = false; // 20200319修复选中某一数字按下相同数字无法清除选中内容的问题 if (!m_undo.isEmpty()) { if (m_undo.size() > 1) { for (int i = m_undo.size() - 1; i > 0; i--) { if (m_undo.at(i) == m_inputEdit->text() && m_undo.at(i - 1) == m_inputEdit->text()) m_undo.pop_back(); } } m_inputEdit->setText(m_undo.last()); } else { m_inputEdit->clear(); m_inputEdit->setUndoAction(false); } if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } } void SciExpressionBar::addUndo() { // 20200319修复选中某一数字按下相同数字无法清除选中内容的问题 // if (!m_undo.isEmpty() && m_inputEdit->text() == m_undo.last()) // return; m_undo.append(m_inputEdit->text()); m_redo.clear(); m_inputEdit->setRedoAction(false); m_inputEdit->setUndoAction(true); SSelection selection; m_inputEdit->setSelection(selection); } void SciExpressionBar::Redo() { if (m_redo.isEmpty()) return; // clearLinkageCache(); m_inputEdit->setText(m_redo.last()); m_undo.append(m_inputEdit->text()); m_redo.removeLast(); m_inputEdit->setRedoAction(!m_redo.isEmpty()); if (m_inputEdit->text().isEmpty() && m_listModel->rowCount(QModelIndex()) != 0) { emit clearStateChanged(true); m_isAllClear = true; } else { emit clearStateChanged(false); m_isAllClear = false; } } void SciExpressionBar::initTheme(int type) { //edit for bug-21476 int typeIn = type; if (typeIn == 0) { typeIn = DGuiApplicationHelper::instance()->themeType(); } m_listDelegate->setThemeType(typeIn); m_inputEdit->themetypechanged(typeIn); } void SciExpressionBar::setResultFalse() { m_isResult = false; } void SciExpressionBar::replaceSelection(QString text) { QString seloldtext = text; SSelection selection = m_inputEdit->getSelection(); int selcurPos = m_inputEdit->cursorPosition(); if (!selection.selected.isEmpty()) { text.remove(selection.curpos, selection.selected.size()); m_inputEdit->setText(text); if (selcurPos > selection.curpos && selcurPos <= selection.curpos + selection.selected.size()) selcurPos = selection.curpos; // 20200313选中部分光标置位问题修复 if (seloldtext.mid(0, selcurPos).remove(QRegExp("[,]")).length() == m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[,]")).length()) m_inputEdit->setCursorPosition(selcurPos); else if (seloldtext.mid(0, selcurPos).remove(QRegExp("[,]")).length() > m_inputEdit->text().mid(0, selcurPos).remove(QRegExp("[,]")).length()) m_inputEdit->setCursorPosition(selcurPos + 1); else m_inputEdit->setCursorPosition(selcurPos - 1); } // reset selection selection = SSelection(); m_inputEdit->setSelection(selection); } bool SciExpressionBar::isOperator(const QString &text) { if (text == CN_ADD || text == CN_MIN || text == CN_MUL || text == CN_DIV) { return true; } else { return false; } } void SciExpressionBar::moveLeft() { QString sRegNum = "[A-Za-z]"; QRegExp rx; rx.setPattern(sRegNum); if (m_inputEdit->cursorPosition() > 0 && rx.exactMatch(m_inputEdit->text().at(m_inputEdit->cursorPosition() - 1))) { int funpos = -1; int i; for (i = 0; i < m_funclist.size(); i++) { funpos = m_inputEdit->text().lastIndexOf(m_funclist[i], m_inputEdit->cursorPosition() - 1); if (funpos != -1 && funpos + m_funclist[i].length() == m_inputEdit->cursorPosition()) break; else funpos = -1; } if (funpos != -1) { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() - m_funclist[i].length()); } else { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() - 1); } } else { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() - 1); } m_inputEdit->setFocus(); } void SciExpressionBar::moveRight() { QString sRegNum = "[A-Za-z]"; QRegExp rx; rx.setPattern(sRegNum); if (!cursorPosAtEnd() && rx.exactMatch(m_inputEdit->text().at(m_inputEdit->cursorPosition()))) { int funpos = -1; int i; for (i = 0; i < m_funclist.size(); i++) { funpos = m_inputEdit->text().indexOf(m_funclist[i], m_inputEdit->cursorPosition()); if (funpos != -1 && funpos == m_inputEdit->cursorPosition()) break; else funpos = -1; } if (funpos != -1) { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() + m_funclist[i].length()); } else { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() + 1); } } else { m_inputEdit->setCursorPosition(m_inputEdit->cursorPosition() + 1); } m_inputEdit->setFocus(); } //20200414 bug20294鼠标点击取消focus InputEdit *SciExpressionBar::getInputEdit() { return m_inputEdit; } /** * @brief SciExpressionBar::separateChange * 数字间隔位数发生改变 */ void SciExpressionBar::onSeparateChange() { m_listModel->updataOfSeparate(); } deepin-calculator-5.7.21/src/widgets/sciexpressionbar.h000066400000000000000000000104731423020056600231750ustar00rootroot00000000000000/* * Copyright (C) 2019 ~ 2020 Uniontech Software Technology Co.,Ltd. * * Author: xiajing * * Maintainer: jingzhou * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef SCIEXPRESSIONBAR_H #define SCIEXPRESSIONBAR_H #include "../../3rdparty/core/evaluator.h" #include "inputedit.h" #include "../views/simplelistdelegate.h" #include "../views/simplelistmodel.h" #include "../views/simplelistview.h" #include #include #include #include #include #include #include DWIDGET_USE_NAMESPACE /** * @brief 科学计算器表达式计算函数 */ class SciExpressionBar : public DWidget { Q_OBJECT public: explicit SciExpressionBar(QWidget *parent = nullptr); ~SciExpressionBar(); void mouseMoveEvent(QMouseEvent *e); QPair getexpression(); Quantity getanswer(); signals: void keyPress(QKeyEvent *); void clearStateChanged(bool); void themeChange(int type); void turnDeg(); void fEStateChanged(bool); public slots: //输入事件 void enterNumberEvent(const QString &text); void enterSymbolEvent(const QString &text); void enterPointEvent(); void enterBackspaceEvent(); void enterClearEvent(); void enterEqualEvent(); void enterPercentEvent(); void enterDegEvent(int mod); void enterFEEvent(bool isdown); void enterRandEvent(); //replace void enterOperatorEvent(const QString &text); //运算符类:x A y; void enterFunctionEvent(const QString &text); //函数类:A(x),A(x,y); void enterConstantEvent(const QString &text); //常数类:e,pi,aˣ void enterBracketEvent(const int &type); //括号:0-(),1-(,2-) void enterSpecialFuncEvent(const QString &text); //倒数、绝对值、相反数 void moveLeft(); void moveRight(); void copyResultToClipboard(); void copyClipboard2Result(); void allElection(); void shear(); void deleteText(); void Undo(); void addUndo(); void Redo(); void initTheme(int type); void setResultFalse(); void replaceSelection(QString text); InputEdit *getInputEdit(); void revisionResults(const QModelIndex &index); void hisRevisionResults(const QModelIndex &index, Quantity ans); bool judgeinput(); private slots: void handleTextChanged(const QString &text); /** * @brief pointCheckAfterDelete * 删除内容后5秒钟清理多余的小数点 * @param curpos * 光标位置 */ void pointCheckAfterDelete(); void onSeparateChange();//数字将位数发生改变 private: bool cursorPosAtEnd(); QString formatExpression(const QString &text); bool isOperator(const QString &text); void initConnect(); QString symbolComplement(const QString exp); QString pointFaultTolerance(const QString &text); void expressionCheck(); bool isnumber(QChar a); bool expressionInFunc(QString &text); private: Evaluator *m_evaluator; SimpleListView *m_listView; SimpleListDelegate *m_listDelegate; SimpleListModel *m_listModel; InputEdit *m_inputEdit; bool m_isContinue; bool m_isAllClear; bool m_isResult; //计算结果 bool m_inputNumber; //输入数字 bool m_isUndo; QVector m_undo; QVector m_redo; bool m_meanexp; //是否表达式为纯数字 bool m_FEisdown = false; //科学计算开关打开 //支持的功能列表 QList m_funclist; QString m_expression = QString(); QPair m_pair; //getexpression()函数的返回值,first为是否是错误表达式,second为表达式 Quantity m_listanswer = Quantity(); //历史记录对应的answer }; #endif // SCIEXPRESSIONBAR_H deepin-calculator-5.7.21/tests/000077500000000000000000000000001423020056600163415ustar00rootroot00000000000000deepin-calculator-5.7.21/tests/CMakeLists.txt000066400000000000000000000166201423020056600211060ustar00rootroot00000000000000#源程序cmakelists再添加上ut相关环境搭建 #ut相关环境搭建详情见 #https://wikidev.uniontech.com/index.php?title=UT_%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA#.E7.94.A8.E4.BE.8B.E7.BC.96.E5.86.99_.7C_UT_Case cmake_minimum_required(VERSION 3.9.5) if (NOT DEFINED VERSION) set(VERSION 1.2.2) endif () list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) ADD_COMPILE_OPTIONS(-fno-access-control) set(CMAKE_CXX_STANDARD 11) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall -Wl,--as-needed -fPIE") set(QT_MINIMUM_VERSION "5.7.1") set(CMAKE_EXE_LINKER_FLAGS "-pie") #add_definitions(-DQT_NO_DEBUG_OUTPUT) if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "sw_64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mieee") endif () if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips64") message(STATUS "this system is mips64=========") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -ftree-vectorize -march=loongson3a -mhard-float -mno-micromips -mno-mips16 -flax-vector-conversions -mloongson-ext2 -mloongson-mmi -Wl,--as-needed") endif() if (NOT (${CMAKE_BUILD_TYPE} MATCHES "Debug")) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") execute_process(COMMAND bash "${CMAKE_CURRENT_LIST_DIR}/../translate_generation.sh" WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../) endif () configure_file(${CMAKE_CURRENT_LIST_DIR}/../src/environments.h.in environments.h @ONLY) # Find the library find_package(PkgConfig REQUIRED) find_package(Qt5Widgets REQUIRED) find_package(Qt5Core REQUIRED) find_package(Qt5Gui REQUIRED) find_package(Qt5DBus REQUIRED) find_package(Qt5Xml REQUIRED) find_package(Qt5Svg REQUIRED) find_package(Qt5Test REQUIRED) find_package(DtkWidget REQUIRED dtkwidget) find_package(DtkGui REQUIRED dtkgui) find_package(DtkCore REQUIRED dtkcore) #find_package(DFrameworkDbus REQUIRED dframeworkdbus) pkg_check_modules(DFrameworkDBus REQUIRED dframeworkdbus) include_directories(${DtkWidget_INCLUDE_DIRS}) include_directories(${DtkGui_INCLUDE_DIRS}) include_directories(${DtkCore_INCLUDE_DIRS}) set (EXE_NAME deepin-calculator) set(LINK_LIBS Qt5::Core Qt5::DBus Qt5::Widgets Qt5::Xml Qt5::Svg Qt5::Test ${DtkWidget_LIBRARIES} ${DtkCore_LIBRARIES} ${DtkGUI_LIBRARIES} ${DFrameworkDBus_LIBRARIES} ) #CMAKE_CURRENT_LIST_DIR缓存文件的目录,头文件找不到问题解决方案1,文件中未使用该头文件变量 2,CMAKE_CURRENT_LIST_DIR改为CMAKE_SOURCE_DIR SET(HEAD ${CMAKE_CURRENT_LIST_DIR}/../src ${CMAKE_CURRENT_LIST_DIR}/../src/bak ${CMAKE_CURRENT_LIST_DIR}/../src/control ${CMAKE_CURRENT_LIST_DIR}/../3rdparty/core ${CMAKE_CURRENT_LIST_DIR}/../3rdparty/math ${CMAKE_CURRENT_LIST_DIR}/../src/views ${CMAKE_CURRENT_LIST_DIR}/../src/widgets ) file(GLOB_RECURSE CAL_H ${CMAKE_CURRENT_LIST_DIR}/../src/*.h) file(GLOB_RECURSE CAL_C ${CMAKE_CURRENT_LIST_DIR}/../src/*.c) file(GLOB_RECURSE CAL_CPP ${CMAKE_CURRENT_LIST_DIR}/../src/*.cpp) file(GLOB_RECURSE CAL_3rdH ${CMAKE_CURRENT_LIST_DIR}/../3rdparty/*.h) file(GLOB_RECURSE CAL_3rdC ${CMAKE_CURRENT_LIST_DIR}/../3rdparty/*.c) file(GLOB_RECURSE CAL_3rdCPP ${CMAKE_CURRENT_LIST_DIR}/../3rdparty/*.cpp) list(REMOVE_ITEM CAL_CPP "${CMAKE_CURRENT_LIST_DIR}/../src/main.cpp") file(GLOB_RECURSE CAL_TEST ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp) file(GLOB_RECURSE CAL_TESTH ${CMAKE_CURRENT_LIST_DIR}/src/*.h) find_package(GTest REQUIRED) include_directories(${GTEST_INCLUDE_DIRS}) set (DC_QRC_FILES ${CMAKE_CURRENT_LIST_DIR}/../src/deepin-calculator.qrc ) set(PROJECT_NAME_TEST ${PROJECT_NAME}-test) # 生成测试可执行程序 add_executable(${PROJECT_NAME_TEST} ${CAL_H} ${CAL_C} ${CAL_CPP} ${CAL_3rdH} ${CAL_3rdC} ${CAL_3rdCPP} ${CAL_TEST} ${CAL_TESTH}) # 生成测试可执行程序的依赖库 target_link_libraries(${PROJECT_NAME_TEST} ${GTEST_LIBRARYS} ${GTEST_MAIN_LIBRARYS} gmock gmock_main gtest gtest_main pthread) target_include_directories(${PROJECT_NAME_TEST} PUBLIC ${Qt5Widgets_LIBRARIES} ${Qt5DBus_LIBRARIES} ${Qt5TestLib_LIBRARIES} ${PROJECT_BINARY_DIR} ${DtkWidget_INCLUDE_DIRS} ${DtkCore_LIBRARIES} ${DtkGUI_INCLUDE_DIRS} ${DFrameworkDBus_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} ${HEAD}) target_link_libraries (${PROJECT_NAME_TEST} ${LINK_LIBS}) set(CMAKE_INSTALL_PREFIX /usr) install(TARGETS deepin-calculator DESTINATION bin) file(GLOB QM_FILES "${CMAKE_CURRENT_LIST_DIR}/../translations/*.qm") install(FILES ${QM_FILES} DESTINATION share/deepin-calculator/translations) install(FILES ${CMAKE_CURRENT_LIST_DIR}/../deepin-calculator.desktop DESTINATION share/applications/) install(FILES ${CMAKE_CURRENT_LIST_DIR}/../src/assets/images/deepin-calculator.svg DESTINATION share/icons/hicolor/scalable/apps/) #------------------------------ 创建'make test'指令--------------------------------------- add_custom_target(test # COMMAND mkdir -p tests/coverageResult # WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) add_custom_command(TARGET test COMMAND echo " =================== CREAT LCOV REPROT BEGIN ==================== " #1.清理原先的gcov信息 # COMMAND lcov --directory ./tests/CMakeFiles/${PROJECT_NAME_TEST}.dir --zerocounters # COMMAND lcov --directory ./tests/CMakeFiles/${PROJECT_NAME}.dir --zerocounters COMMAND ${CMAKE_BINARY_DIR}/tests/${PROJECT_NAME_TEST} #2.收集gcov信息到.info文件中 # COMMAND lcov --directory . --capture --output-file ./tests/coverageResult/${PROJECT_NAME}_Coverage.info #3.过滤一些我们不感兴趣的文件的覆盖率信息 # COMMAND echo " =================== do filter begin ==================== " # COMMAND lcov --remove ./tests/coverageResult/${PROJECT_NAME}_Coverage.info # '*/${PROJECT_NAME_TEST}_autogen/*' '*/${PROJECT_NAME}_autogen/*' '*/tests/*' '*/googletest/*' '*/usr/include/*' '*/src/bak/*' '*/src/core/*' '*/src/math/*' # -o ./tests/coverageResult/${PROJECT_NAME}_Coverage.info # COMMAND echo " =================== do filter end ==================== " #3.将.info信息生成报告到reprot文件夹中 # COMMAND genhtml -o ./tests/coverageResult/report ./coverageResult/${PROJECT_NAME}_Coverage.info COMMAND echo " =================== CREAT LCOV REPROT END ==================== " # COMMAND echo " Coverage files have been output to ${CMAKE_BINARY_DIR}/coverageResult/report " # WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) #'make test'命令依赖与我们的测试程序 add_dependencies(test ${PROJECT_NAME_TEST}) # 设置添加gocv相关信息的输出 set(CMAKE_CXX_FLAGS "-g -fprofile-arcs -ftest-coverage") set(CMAKE_SAFETYTEST "${CMAKE_SAFETYTEST_ARG}") if(CMAKE_SAFETYTEST STREQUAL "") set(CMAKE_SAFETYTEST "CMAKE_SAFETYTEST_ARG_OFF") endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${CMAKE_SAFETYTEST}") if(CMAKE_SAFETYTEST STREQUAL "CMAKE_SAFETYTEST_ARG_ON") #安全测试选项 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=undefined,address -O2") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=undefined,address -O2") endif() deepin-calculator-5.7.21/tests/cmake-lcov-test.sh000066400000000000000000000007661423020056600217040ustar00rootroot00000000000000utdir=build-ut rm -r $utdir rm -r ../$utdir mkdir ../$utdir cd ../$utdir cmake -DCMAKE_BUILD_TYPE=Release .. make -j16 ./tests/deepin-calculator-test --gtest_output=xml:./report/report.xml workdir=$(cd ../$(dirname $0)/$utdir; pwd) mkdir -p report lcov -d $workdir -c -o ./report/coverage.info lcov --extract ./report/coverage.info '*/src/*' -o ./report/coverage.info lcov --remove ./report/coverage.info '*/tests/*' -o ./report/coverage.info genhtml -o ./report ./report/coverage.info exit 0 deepin-calculator-5.7.21/tests/src/000077500000000000000000000000001423020056600171305ustar00rootroot00000000000000deepin-calculator-5.7.21/tests/src/control/000077500000000000000000000000001423020056600206105ustar00rootroot00000000000000deepin-calculator-5.7.21/tests/src/control/ut_basickeypad.cpp000066400000000000000000000016561423020056600243130ustar00rootroot00000000000000#include "ut_basickeypad.h" #include "../../src/control/basickeypad.h" #include "../../src/memorypublic.h" Ut_BasicKeypad::Ut_BasicKeypad() { } TEST_F(Ut_BasicKeypad, buttonThemeChanged) { BasicKeypad *m_basickeypad = new BasicKeypad; m_basickeypad->buttonThemeChanged(1); EXPECT_EQ(static_cast(m_basickeypad->button(BasicKeypad::Key_Mult))->m_currentUrl, ":/assets/images/light/x_normal.svg"); m_basickeypad->buttonThemeChanged(2); EXPECT_EQ(static_cast(m_basickeypad->button(BasicKeypad::Key_Div))->m_currentUrl, ":/assets/images/dark/divide_normal.svg"); delete m_basickeypad; } TEST_F(Ut_BasicKeypad, getFocus) { BasicKeypad *m_basickeypad = new BasicKeypad; m_basickeypad->getFocus(0); m_basickeypad->getFocus(1); m_basickeypad->getFocus(2); m_basickeypad->getFocus(3); m_basickeypad->getFocus(4); //焦点函数,无assert delete m_basickeypad; } deepin-calculator-5.7.21/tests/src/control/ut_basickeypad.h000066400000000000000000000004171423020056600237520ustar00rootroot00000000000000#ifndef UT_BASICKEYPAD_H #define UT_BASICKEYPAD_H #include #include #include #include "../../src/dsettings.h" class Ut_BasicKeypad : public ::testing::Test { public: Ut_BasicKeypad(); }; #endif // UT_BASICKEYPAD_H deepin-calculator-5.7.21/tests/src/control/ut_bitbutton.cpp000066400000000000000000000104301423020056600240340ustar00rootroot00000000000000#include "ut_bitbutton.h" #include "../../src/control/bitbutton.h" Ut_BitButton::Ut_BitButton() { } TEST_F(Ut_BitButton, init) { BitButton *m_bitbutton = new BitButton; m_bitbutton->init(); EXPECT_EQ(m_bitbutton->m_font.pixelSize(), 18); EXPECT_EQ(m_bitbutton->m_font.family(), "Noto Sans"); EXPECT_EQ(m_bitbutton->m_font.weight(), 2); delete m_bitbutton; } TEST_F(Ut_BitButton, animate) { BitButton *m_bitbutton = new BitButton; m_bitbutton->m_isHover = true; m_bitbutton->m_isPress = false; m_bitbutton->animate(false, 100); EXPECT_FALSE(m_bitbutton->m_isHover); EXPECT_TRUE(m_bitbutton->m_isPress); delete m_bitbutton; } TEST_F(Ut_BitButton, setButtonState) { BitButton *m_bitbutton = new BitButton; m_bitbutton->setButtonState(false); EXPECT_FALSE(m_bitbutton->m_btnState); m_bitbutton->setButtonState(true); EXPECT_EQ(m_bitbutton->text(), "1"); delete m_bitbutton; } TEST_F(Ut_BitButton, mousePressEvent) { BitButton *m_bitbutton = new BitButton; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_bitbutton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_bitbutton->mousePressEvent(m); delete m; EXPECT_TRUE(m_bitbutton->m_isPress); EXPECT_FALSE(m_bitbutton->m_isHover); delete m_bitbutton; } TEST_F(Ut_BitButton, mouseReleaseEvent) { BitButton *m_bitbutton = new BitButton; m_bitbutton->setText("1"); QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonRelease, m_bitbutton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_bitbutton->mouseReleaseEvent(m); EXPECT_FALSE(m_bitbutton->m_isPress); EXPECT_FALSE(m_bitbutton->m_btnState); delete m; delete m_bitbutton; } TEST_F(Ut_BitButton, enterEvent) { BitButton *m_bitbutton = new BitButton; QEvent *q = new QEvent(QEvent::Type::Enter); m_bitbutton->enterEvent(q); delete q; EXPECT_TRUE(m_bitbutton->m_isHover); delete m_bitbutton; } TEST_F(Ut_BitButton, leaveEvent) { BitButton *m_bitbutton = new BitButton; QEvent *q = new QEvent(QEvent::Type::Leave); m_bitbutton->leaveEvent(q); delete q; EXPECT_FALSE(m_bitbutton->m_isHover); delete m_bitbutton; } TEST_F(Ut_BitButton, keyPressEvent) { BitButton *m_bitbutton = new BitButton; QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); QKeyEvent *k2 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); QKeyEvent *k3 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier); QKeyEvent *k4 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier); QKeyEvent *k5 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); m_bitbutton->keyPressEvent(k); m_bitbutton->keyPressEvent(k1); m_bitbutton->keyPressEvent(k2); m_bitbutton->keyPressEvent(k3); m_bitbutton->keyPressEvent(k4); m_bitbutton->keyPressEvent(k5); delete k; delete k1; delete k2; delete k3; delete k4; delete k5; //该函数只修改焦点,无assert delete m_bitbutton; } TEST_F(Ut_BitButton, focusOutEvent) { BitButton *m_bitbutton = new BitButton; QFocusEvent *f = new QFocusEvent(QEvent::Type::FocusOut); m_bitbutton->focusOutEvent(f); delete f; delete m_bitbutton; //焦点丢失函数,无assert } TEST_F(Ut_BitButton, paintEvent) { BitButton *m_bitbutton = new BitButton; QPaintEvent *event = new QPaintEvent(m_bitbutton->rect()); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::UnknownType); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_bitbutton->m_isHover = true; m_bitbutton->m_isPress = true; m_bitbutton->paintEvent(event); m_bitbutton->update(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_bitbutton->paintEvent(event); delete event; //paintevent,无ASSERT delete m_bitbutton; } deepin-calculator-5.7.21/tests/src/control/ut_bitbutton.h000066400000000000000000000003431423020056600235030ustar00rootroot00000000000000#ifndef UT_BITBUTTON_H #define UT_BITBUTTON_H #include #include #include class Ut_BitButton : public ::testing::Test { public: Ut_BitButton(); }; #endif // UT_BITBUTTON_H deepin-calculator-5.7.21/tests/src/control/ut_equalbutton.cpp000066400000000000000000000106641423020056600243760ustar00rootroot00000000000000#include "ut_equalbutton.h" #include "../../src/control/equalbutton.h" Ut_EqualButton::Ut_EqualButton() { } TEST_F(Ut_EqualButton, init) { EqualButton *m_equalButton = new EqualButton; m_equalButton->init(); EXPECT_EQ(m_equalButton->m_font.pixelSize(), 36); EXPECT_EQ(m_equalButton->m_font.family(), "Noto Sans"); EXPECT_EQ(m_equalButton->m_font.styleName(), "Light"); delete m_equalButton; } TEST_F(Ut_EqualButton, mousePressEvent) { EqualButton *m_equalButton = new EqualButton; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_equalButton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_equalButton->mousePressEvent(m); delete m; EXPECT_TRUE(m_equalButton->m_isPress); EXPECT_FALSE(m_equalButton->m_isHover); delete m_equalButton; } TEST_F(Ut_EqualButton, mouseReleaseEvent) { EqualButton *m_equalButton = new EqualButton; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonRelease, m_equalButton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_equalButton->mouseReleaseEvent(m); delete m; EXPECT_FALSE(m_equalButton->m_isPress); EXPECT_TRUE(m_equalButton->m_isacting); EXPECT_TRUE(m_equalButton->m_isHover); delete m_equalButton; } TEST_F(Ut_EqualButton, enterEvent) { EqualButton *m_equalButton = new EqualButton; QEvent *e = new QEvent(QEvent::Type::Enter); m_equalButton->enterEvent(e); delete e; EXPECT_TRUE(m_equalButton->m_isHover); delete m_equalButton; } TEST_F(Ut_EqualButton, leaveEvent) { EqualButton *m_equalButton = new EqualButton; QEvent *e = new QEvent(QEvent::Type::Leave); m_equalButton->leaveEvent(e); delete e; EXPECT_FALSE(m_equalButton->m_isHover); delete m_equalButton; } bool stub_focus_equal() { return true; } TEST_F(Ut_EqualButton, paintEvent) { EqualButton *m_equalButton = new EqualButton(); QPaintEvent *event = new QPaintEvent(m_equalButton->rect()); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_equalButton->setEnabled(true); m_equalButton->m_isHover = true; m_equalButton->m_isPress = false; m_equalButton->paintEvent(event); m_equalButton->update(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_equalButton->paintEvent(event); m_equalButton->m_isHover = false; m_equalButton->m_isPress = true; m_equalButton->paintEvent(event); m_equalButton->update(); m_equalButton->m_isHover = false; m_equalButton->m_isPress = false; m_equalButton->paintEvent(event); m_equalButton->update(); //focus状态 Stub stub; stub.set(ADDR(EqualButton, hasFocus), stub_focus_equal); m_equalButton->m_isHover = true; m_equalButton->m_isPress = false; m_equalButton->paintEvent(event); m_equalButton->update(); m_equalButton->paintEvent(event); m_equalButton->m_isHover = false; m_equalButton->m_isPress = true; m_equalButton->paintEvent(event); m_equalButton->update(); m_equalButton->m_isHover = false; m_equalButton->m_isPress = false; m_equalButton->paintEvent(event); m_equalButton->update(); //paintevent,无ASSERT delete event; delete m_equalButton; } TEST_F(Ut_EqualButton, keyPressEvent) { EqualButton *m_equalButton = new EqualButton; QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); QKeyEvent *k2 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); QKeyEvent *k3 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier); QKeyEvent *k4 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier); QKeyEvent *k5 = new QKeyEvent(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier); m_equalButton->keyPressEvent(k); m_equalButton->keyPressEvent(k1); m_equalButton->keyPressEvent(k2); m_equalButton->keyPressEvent(k3); m_equalButton->keyPressEvent(k4); m_equalButton->keyPressEvent(k5); delete k; delete k1; delete k2; delete k3; delete k4; delete k5; //该函数仅修改焦点,无ASSERT delete m_equalButton; } deepin-calculator-5.7.21/tests/src/control/ut_equalbutton.h000066400000000000000000000004441423020056600240360ustar00rootroot00000000000000#ifndef UT_EQUALBUTTON_H #define UT_EQUALBUTTON_H #include #include #include #include #include"../stub.h" class Ut_EqualButton : public ::testing::Test { public: Ut_EqualButton(); }; #endif // UT_EQUALBUTTON_H deepin-calculator-5.7.21/tests/src/control/ut_iconbutton.cpp000066400000000000000000000227741423020056600242240ustar00rootroot00000000000000#include "ut_iconbutton.h" #include "../../src/control/iconbutton.h" Ut_IconButton::Ut_IconButton() { } TEST_F(Ut_IconButton, animate) { IconButton *m_iconButton = new IconButton; m_iconButton->m_isPress = false; m_iconButton->setIconUrl("a", "b", "c", 1); m_iconButton->animate(false); EXPECT_EQ(m_iconButton->m_mode, 2); EXPECT_EQ(m_iconButton->m_buttonStatus, 2); m_iconButton->m_isPress = false; m_iconButton->setIconUrl("a", "b", "c", 3); m_iconButton->animate(false); EXPECT_EQ(m_iconButton->m_mode, 4); EXPECT_EQ(m_iconButton->m_currentUrl, "c"); m_iconButton->m_isPress = false; m_iconButton->setIconUrl("a", "b", "c", 5); m_iconButton->animate(false); EXPECT_EQ(m_iconButton->m_mode, 6); m_iconButton->m_isPress = false; m_iconButton->setIconUrl("a", "b", "c", 7); m_iconButton->animate(false); EXPECT_EQ(m_iconButton->m_mode, 8); EXPECT_TRUE(m_iconButton->m_isPress); delete m_iconButton; } TEST_F(Ut_IconButton, setIconUrl) { IconButton *m_iconButton = new IconButton; m_iconButton->setIconUrl("a", "b", "c", 2); EXPECT_EQ(m_iconButton->m_mode, 2); EXPECT_EQ(m_iconButton->m_currentUrl, "a"); EXPECT_EQ(m_iconButton->m_buttonStatus, 0); delete m_iconButton; } TEST_F(Ut_IconButton, showtooltip) { IconButton *m_iconButton = new IconButton; m_iconButton->showtooltip(false); EXPECT_EQ(m_iconButton->m_cleartooltip, "Clear history"); m_iconButton->showtooltip(true); EXPECT_EQ(m_iconButton->m_cleartooltip, "Clear all memory"); delete m_iconButton; } TEST_F(Ut_IconButton, updateWhenBtnDisable) { IconButton *m_iconButton = new IconButton; m_iconButton->updateWhenBtnDisable(); EXPECT_FALSE(m_iconButton->m_isPress); EXPECT_EQ(m_iconButton->m_buttonStatus, 0); EXPECT_EQ(m_iconButton->m_mode, 1); delete m_iconButton; } TEST_F(Ut_IconButton, setBtnPressing) { IconButton *m_iconButton = new IconButton; m_iconButton->setBtnPressing(false); EXPECT_FALSE(m_iconButton->m_isPressing); EXPECT_EQ(m_iconButton->m_buttonStatus, 0); EXPECT_FALSE(m_iconButton->m_isPressing); m_iconButton->setBtnPressing(true); EXPECT_TRUE(m_iconButton->m_isPressing); EXPECT_EQ(m_iconButton->m_buttonStatus, 2); EXPECT_TRUE(m_iconButton->m_isPressing); delete m_iconButton; } TEST_F(Ut_IconButton, setBtnHighlight) { IconButton *m_iconButton = new IconButton; m_iconButton->setBtnHighlight(false); EXPECT_FALSE(m_iconButton->m_highlight); delete m_iconButton; } TEST_F(Ut_IconButton, mousePressEvent) { IconButton *m_iconButton = new IconButton; m_iconButton->m_mode = 1; m_iconButton->animate(false, 100); QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_iconButton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_iconButton->mousePressEvent(m); EXPECT_TRUE(m_iconButton->m_isPress); EXPECT_FALSE(m_iconButton->m_isHover); EXPECT_EQ(m_iconButton->m_buttonStatus, 2); EXPECT_EQ(m_iconButton->m_mode, 2); delete m; delete m_iconButton; } TEST_F(Ut_IconButton, mouseReleaseEvent) { IconButton *m_iconButton = new IconButton; m_iconButton->m_mode = 2; m_iconButton->animate(false, 100); QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonRelease, m_iconButton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_iconButton->mouseReleaseEvent(m); EXPECT_TRUE(m_iconButton->m_isHover); EXPECT_FALSE(m_iconButton->m_isPress); EXPECT_EQ(m_iconButton->m_buttonStatus, 1); EXPECT_EQ(m_iconButton->m_mode, 1); EXPECT_TRUE(m_iconButton->m_isacting); delete m; delete m_iconButton; } TEST_F(Ut_IconButton, enterEvent) { IconButton *m_iconButton = new IconButton; m_iconButton->setIconUrl("a", "b", "c", 1); QEvent *e = new QEvent(QEvent::Type::Enter); m_iconButton->enterEvent(e); EXPECT_TRUE(m_iconButton->m_isHover); EXPECT_EQ(m_iconButton->m_buttonStatus, 1); EXPECT_EQ(m_iconButton->m_currentUrl, "b"); delete e; delete m_iconButton; } TEST_F(Ut_IconButton, leaveEvent) { IconButton *m_iconButton = new IconButton; m_iconButton->setIconUrl("a", "b", "c", 1); QEvent *e = new QEvent(QEvent::Type::Leave); m_iconButton->leaveEvent(e); EXPECT_FALSE(m_iconButton->m_isHover); EXPECT_EQ(m_iconButton->m_buttonStatus, 0); EXPECT_EQ(m_iconButton->m_currentUrl, "a"); EXPECT_FALSE(m_iconButton->m_isacting); delete e; delete m_iconButton; } bool stub_focus_icon() { return true; } TEST_F(Ut_IconButton, paintEvent) { IconButton *m_iconButton = new IconButton; QPaintEvent *event = new QPaintEvent(m_iconButton->rect()); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::UnknownType); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_iconButton->m_isHover = true; m_iconButton->m_isPress = false; m_iconButton->m_isEmptyBtn = false; m_iconButton->paintEvent(event); m_iconButton->update(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_iconButton->m_isHover = false; m_iconButton->m_isPress = true; m_iconButton->m_isEmptyBtn = false; m_iconButton->paintEvent(event); m_iconButton->update(); m_iconButton->m_isHover = false; m_iconButton->m_isPress = false; m_iconButton->m_isEmptyBtn = true; m_iconButton->paintEvent(event); //SetAttrRecur m_iconButton->m_mode = 2; m_iconButton->m_buttonStatus = 2; m_iconButton->m_currentUrl = ":/assets/images/light/clear_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_mode = 0; m_iconButton->m_buttonStatus = 0; m_iconButton->m_currentUrl = ":/assets/images/light/+_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_buttonStatus = 1; m_iconButton->paintEvent(event); m_iconButton->m_mode = 4; m_iconButton->m_buttonStatus = 2; m_iconButton->m_currentUrl = ":/assets/images/light/squareroot_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_mode = 6; m_iconButton->m_currentUrl = ":/assets/images/light/deg_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_mode = 8; m_iconButton->m_currentUrl = ":/assets/images/light/deg_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_mode = 8; m_iconButton->m_highlight = true; m_iconButton->m_currentUrl = ":/assets/images/light/deg_press.svg"; m_iconButton->paintEvent(event); //focus状态 Stub stub; stub.set(ADDR(IconButton, hasFocus), stub_focus_icon); m_iconButton->setEnabled(true); m_iconButton->m_isHover = true; m_iconButton->m_isPress = false; m_iconButton->paintEvent(event); m_iconButton->update(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_iconButton->m_isHover = false; m_iconButton->m_isPress = true; m_iconButton->m_isEmptyBtn = false; m_iconButton->paintEvent(event); m_iconButton->update(); m_iconButton->m_isHover = false; m_iconButton->m_isPress = false; m_iconButton->m_isEmptyBtn = true; m_iconButton->paintEvent(event); //SetAttrRecur m_iconButton->m_mode = 2; m_iconButton->m_buttonStatus = 2; m_iconButton->m_currentUrl = ":/assets/images/light/clear_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_mode = 0; m_iconButton->m_buttonStatus = 0; m_iconButton->m_currentUrl = ":/assets/images/light/+_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_mode = 0; m_iconButton->m_buttonStatus = 1; m_iconButton->m_currentUrl = ":/assets/images/light/+_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_mode = 0; m_iconButton->m_buttonStatus = 2; m_iconButton->m_currentUrl = ":/assets/images/light/+_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_buttonStatus = 1; m_iconButton->paintEvent(event); m_iconButton->m_mode = 4; m_iconButton->m_buttonStatus = 2; m_iconButton->m_currentUrl = ":/assets/images/light/squareroot_press.svg"; m_iconButton->paintEvent(event); m_iconButton->m_mode = 6; m_iconButton->m_currentUrl = ":/assets/images/light/deg_press.svg"; m_iconButton->paintEvent(event); //无ASSERT delete event; delete m_iconButton; } TEST_F(Ut_IconButton, keyPressEvent) { IconButton *m_iconButton = new IconButton; m_iconButton->m_isEmptyBtn = true; QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); QKeyEvent *k2 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); QKeyEvent *k3 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier); QKeyEvent *k4 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier); QKeyEvent *k5 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); m_iconButton->keyPressEvent(k); m_iconButton->keyPressEvent(k1); m_iconButton->keyPressEvent(k2); m_iconButton->keyPressEvent(k3); m_iconButton->keyPressEvent(k4); m_iconButton->keyPressEvent(k5); delete k; delete k1; delete k2; delete k3; delete k4; delete k5; //无ASSERT delete m_iconButton; } deepin-calculator-5.7.21/tests/src/control/ut_iconbutton.h000066400000000000000000000003751423020056600236620ustar00rootroot00000000000000#ifndef UT_ICONBUTTON_H #define UT_ICONBUTTON_H #include #include #include #include"../stub.h" class Ut_IconButton : public ::testing::Test { public: Ut_IconButton(); }; #endif // UT_ICONBUTTON_H deepin-calculator-5.7.21/tests/src/control/ut_memhiskeypad.cpp000066400000000000000000000023351423020056600245070ustar00rootroot00000000000000#include "ut_memhiskeypad.h" #include "../../src/control/memhiskeypad.h" Ut_MemHisKeypad::Ut_MemHisKeypad() { } TEST_F(Ut_MemHisKeypad, button) { MemHisKeypad *m_memhiskeypad = new MemHisKeypad; EXPECT_EQ(m_memhiskeypad->button(MemHisKeypad::Buttons::Key_MC)->text(), "MC"); delete m_memhiskeypad; } TEST_F(Ut_MemHisKeypad, animate) { MemHisKeypad *m_memhiskeypad = new MemHisKeypad; m_memhiskeypad->animate(MemHisKeypad::Buttons::Key_MC, false); EXPECT_FALSE(static_cast(m_memhiskeypad->button(MemHisKeypad::Buttons::Key_MC))->m_isHover); delete m_memhiskeypad; } TEST_F(Ut_MemHisKeypad, buttonHasFocus) { MemHisKeypad *m_memhiskeypad = new MemHisKeypad; EXPECT_FALSE(m_memhiskeypad->buttonHasFocus()); delete m_memhiskeypad; } TEST_F(Ut_MemHisKeypad, initButtons) { MemHisKeypad *m_memhiskeypad = new MemHisKeypad; m_memhiskeypad->initButtons(); EXPECT_EQ(m_memhiskeypad->m_keys.size(), 7); delete m_memhiskeypad; } TEST_F(Ut_MemHisKeypad, getFocus) { MemHisKeypad *m_memhiskeypad = new MemHisKeypad; m_memhiskeypad->getFocus(1); m_memhiskeypad->getFocus(2); m_memhiskeypad->getFocus(3); //焦点函数,无assert delete m_memhiskeypad; } deepin-calculator-5.7.21/tests/src/control/ut_memhiskeypad.h000066400000000000000000000004241423020056600241510ustar00rootroot00000000000000#ifndef UT_MEMHISKEYPAD_H #define UT_MEMHISKEYPAD_H #include #include #include #include "../../src/dsettings.h" class Ut_MemHisKeypad : public ::testing::Test { public: Ut_MemHisKeypad(); }; #endif // UT_MEMHISKEYPAD_H deepin-calculator-5.7.21/tests/src/control/ut_memorybutton.cpp000066400000000000000000000221361423020056600245740ustar00rootroot00000000000000#include "ut_memorybutton.h" #include "../../src/control/memorybutton.h" Ut_MemoryButton::Ut_MemoryButton() { } TEST_F(Ut_MemoryButton, initanimate) { MemoryButton *m_memorybutton = new MemoryButton; m_memorybutton->m_widgetbtn = false; m_memorybutton->animate(false, 100); m_memorybutton->init(); EXPECT_EQ(m_memorybutton->m_font.pixelSize(), 16); EXPECT_EQ(m_memorybutton->m_font.family(), "Noto Sans"); EXPECT_EQ(m_memorybutton->m_font.styleName(), "Light"); m_memorybutton->deleteLater(); } QVariant stub_setting_memoryone(const QString &key) { Q_UNUSED(key); return 1; } QVariant stub_setting_memoryzero(const QString &key) { Q_UNUSED(key); return 0; } TEST_F(Ut_MemoryButton, setbtnlight) { MemoryButton *m_memorybutton = new MemoryButton; Stub stub; stub.set(ADDR(DSettingsAlt, getOption), stub_setting_memoryone); m_memorybutton->setbtnlight(true); EXPECT_EQ(m_memorybutton->text(), "MH˄"); m_memorybutton->setbtnlight(false); EXPECT_EQ(m_memorybutton->text(), "MH˅"); Stub stub1; stub1.set(ADDR(DSettingsAlt, getOption), stub_setting_memoryzero); m_memorybutton->setbtnlight(true); EXPECT_EQ(m_memorybutton->text(), "M˄"); m_memorybutton->setbtnlight(false); EXPECT_EQ(m_memorybutton->text(), "M˅"); DSettingsAlt::deleteInstance(); delete m_memorybutton; } TEST_F(Ut_MemoryButton, showtips) { MemoryButton *m_memorybutton = new MemoryButton; m_memorybutton->setText("M+"); m_memorybutton->m_widgetbtn = false; m_memorybutton->showtips(); EXPECT_EQ(m_memorybutton->toolTip(), "Memory add"); m_memorybutton->m_widgetbtn = true; m_memorybutton->showtips(); EXPECT_EQ(m_memorybutton->toolTip(), "Add to memory item"); m_memorybutton->setText("MR"); m_memorybutton->showtips(); EXPECT_EQ(m_memorybutton->toolTip(), "Memory recall"); m_memorybutton->setText("M-"); m_memorybutton->m_widgetbtn = false; m_memorybutton->showtips(); EXPECT_EQ(m_memorybutton->toolTip(), "Memory subtract"); m_memorybutton->m_widgetbtn = true; m_memorybutton->showtips(); EXPECT_EQ(m_memorybutton->toolTip(), "Subtract from memory item"); m_memorybutton->setText("MS"); m_memorybutton->showtips(); EXPECT_EQ(m_memorybutton->toolTip(), "Memory store"); m_memorybutton->setText("MC"); m_memorybutton->m_widgetbtn = false; m_memorybutton->showtips(); EXPECT_EQ(m_memorybutton->toolTip(), "Clear all memory"); m_memorybutton->m_widgetbtn = true; m_memorybutton->showtips(); EXPECT_EQ(m_memorybutton->toolTip(), "Clear memory item"); m_memorybutton->deleteLater(); } TEST_F(Ut_MemoryButton, setbuttongray) { MemoryButton *m_memorybutton = new MemoryButton; m_memorybutton->setbuttongray(true); EXPECT_TRUE(m_memorybutton->m_isallgray); m_memorybutton->deleteLater(); } TEST_F(Ut_MemoryButton, mousePressEvent) { MemoryButton *m_memorybutton = new MemoryButton; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_memorybutton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_memorybutton->mousePressEvent(m); delete m; EXPECT_TRUE(m_memorybutton->m_isPress); m_memorybutton->deleteLater(); } TEST_F(Ut_MemoryButton, mouseReleaseEvent) { MemoryButton *m_memorybutton = new MemoryButton; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonRelease, m_memorybutton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_memorybutton->mouseReleaseEvent(m); EXPECT_FALSE(m_memorybutton->m_isPress); EXPECT_TRUE(m_memorybutton->m_isacting); EXPECT_TRUE(m_memorybutton->m_isHover); delete m; m_memorybutton->deleteLater(); } TEST_F(Ut_MemoryButton, enterEvent) { MemoryButton *m_memorybutton = new MemoryButton; QEvent *q = new QEvent(QEvent::Type::Enter); m_memorybutton->enterEvent(q); EXPECT_TRUE(m_memorybutton->m_isHover); EXPECT_EQ(m_memorybutton->m_font.pixelSize(), 17); delete q; m_memorybutton->deleteLater(); } TEST_F(Ut_MemoryButton, leaveEvent) { MemoryButton *m_memorybutton = new MemoryButton; QEvent *q = new QEvent(QEvent::Type::Leave); m_memorybutton->leaveEvent(q); EXPECT_FALSE(m_memorybutton->m_isHover); EXPECT_EQ(m_memorybutton->m_font.pixelSize(), 16); delete q; m_memorybutton->deleteLater(); } TEST_F(Ut_MemoryButton, focusOutEvent) { MemoryButton *m_memorybutton = new MemoryButton; QFocusEvent *f = new QFocusEvent(QEvent::Type::FocusOut); m_memorybutton->focusOutEvent(f); delete f; m_memorybutton->deleteLater(); //无ASSERT } bool stub_focus_memory() { return true; } TEST_F(Ut_MemoryButton, paintEvent) { MemoryButton *m_memorybutton = new MemoryButton; QPaintEvent *event = new QPaintEvent(m_memorybutton->rect()); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_memorybutton->setText("MH˅"); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = true; m_memorybutton->m_isPress = false; m_memorybutton->paintEvent(event); m_memorybutton->update(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_memorybutton->setEnabled(false); m_memorybutton->m_isHover = false; m_memorybutton->m_isPress = false; m_memorybutton->m_isgray = true; m_memorybutton->paintEvent(event); m_memorybutton->update(); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = false; m_memorybutton->m_isPress = true; m_memorybutton->paintEvent(event); //focus状态 Stub stub; stub.set(ADDR(MemoryButton, hasFocus), stub_focus_memory); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = true; m_memorybutton->m_isPress = false; m_memorybutton->paintEvent(event); m_memorybutton->update(); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = false; m_memorybutton->m_isPress = true; m_memorybutton->paintEvent(event); //无ASSERT delete event; m_memorybutton->deleteLater(); } TEST_F(Ut_MemoryButton, paintEvent2) { MemoryButton *m_memorybutton = new MemoryButton; QPaintEvent *event = new QPaintEvent(m_memorybutton->rect()); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_memorybutton->setText("MH˄"); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = true; m_memorybutton->m_isPress = false; m_memorybutton->paintEvent(event); m_memorybutton->update(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_memorybutton->setEnabled(false); m_memorybutton->m_isHover = false; m_memorybutton->m_isPress = false; m_memorybutton->m_isgray = true; m_memorybutton->paintEvent(event); m_memorybutton->update(); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = false; m_memorybutton->m_isPress = true; m_memorybutton->paintEvent(event); //focus状态 Stub stub; stub.set(ADDR(MemoryButton, hasFocus), stub_focus_memory); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = true; m_memorybutton->m_isPress = false; m_memorybutton->paintEvent(event); m_memorybutton->update(); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = false; m_memorybutton->m_isPress = true; m_memorybutton->paintEvent(event); //无ASSERT delete event; m_memorybutton->deleteLater(); } TEST_F(Ut_MemoryButton, paintEvent3) { MemoryButton *m_memorybutton = new MemoryButton(QString("M+"), true); QPaintEvent *event = new QPaintEvent(m_memorybutton->rect()); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = true; m_memorybutton->m_isPress = false; m_memorybutton->paintEvent(event); m_memorybutton->update(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_memorybutton->setEnabled(false); m_memorybutton->m_isHover = false; m_memorybutton->m_isPress = false; m_memorybutton->m_isgray = true; m_memorybutton->paintEvent(event); m_memorybutton->update(); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = false; m_memorybutton->m_isPress = true; m_memorybutton->paintEvent(event); //focus状态 Stub stub; stub.set(ADDR(MemoryButton, hasFocus), stub_focus_memory); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = true; m_memorybutton->m_isPress = false; m_memorybutton->paintEvent(event); m_memorybutton->update(); m_memorybutton->setEnabled(true); m_memorybutton->m_isHover = false; m_memorybutton->m_isPress = true; m_memorybutton->paintEvent(event); //无ASSERT delete event; m_memorybutton->deleteLater(); } deepin-calculator-5.7.21/tests/src/control/ut_memorybutton.h000066400000000000000000000004071423020056600242360ustar00rootroot00000000000000#ifndef UT_MEMORYBUTTON_H #define UT_MEMORYBUTTON_H #include #include #include #include"../stub.h" class Ut_MemoryButton : public ::testing::Test { public: Ut_MemoryButton(); }; #endif // UT_MEMORYBUTTON_H deepin-calculator-5.7.21/tests/src/control/ut_memorykeypad.cpp000066400000000000000000000010401423020056600245250ustar00rootroot00000000000000#include "ut_memorykeypad.h" #include "../../src/control/memorykeypad.h" Ut_MemoryKeypad::Ut_MemoryKeypad() { } TEST_F(Ut_MemoryKeypad, button) { MemoryKeypad *m_memorykeypad = new MemoryKeypad; EXPECT_EQ(m_memorykeypad->button(MemoryKeypad::Buttons::Key_MC)->text(), "MC"); delete m_memorykeypad; } TEST_F(Ut_MemoryKeypad, getFocus) { MemoryKeypad *m_basickeypad = new MemoryKeypad; m_basickeypad->getFocus(1); m_basickeypad->getFocus(2); m_basickeypad->getFocus(3); //无ASSERT delete m_basickeypad; } deepin-calculator-5.7.21/tests/src/control/ut_memorykeypad.h000066400000000000000000000004241423020056600241770ustar00rootroot00000000000000#ifndef UT_MEMORYKEYPAD_H #define UT_MEMORYKEYPAD_H #include #include #include #include "../../src/dsettings.h" class Ut_MemoryKeypad : public ::testing::Test { public: Ut_MemoryKeypad(); }; #endif // UT_MEMORYKEYPAD_H deepin-calculator-5.7.21/tests/src/control/ut_procheckbtnkeypad.cpp000066400000000000000000000040431423020056600255250ustar00rootroot00000000000000#include "ut_procheckbtnkeypad.h" #include "../../src/control/procheckbtnkeypad.h" Ut_ProCheckBtnKeypad::Ut_ProCheckBtnKeypad() { } TEST_F(Ut_ProCheckBtnKeypad, button) { ProCheckBtnKeypad *m_procheckbtnkeypad = new ProCheckBtnKeypad; EXPECT_EQ(m_procheckbtnkeypad->button(ProCheckBtnKeypad::Buttons::Key_MS)->text(), "MS"); delete m_procheckbtnkeypad; } TEST_F(Ut_ProCheckBtnKeypad, animate) { ProCheckBtnKeypad *m_procheckbtnkeypad = new ProCheckBtnKeypad; m_procheckbtnkeypad->animate(ProCheckBtnKeypad::Buttons::Key_MS, false); EXPECT_FALSE(static_cast(m_procheckbtnkeypad->button(ProCheckBtnKeypad::Buttons::Key_MS))->m_isHover); delete m_procheckbtnkeypad; } TEST_F(Ut_ProCheckBtnKeypad, buttonHasFocus) { ProCheckBtnKeypad *m_procheckbtnkeypad = new ProCheckBtnKeypad; EXPECT_FALSE(m_procheckbtnkeypad->buttonHasFocus()); delete m_procheckbtnkeypad; } TEST_F(Ut_ProCheckBtnKeypad, initButtons) { ProCheckBtnKeypad *m_procheckbtnkeypad = new ProCheckBtnKeypad; m_procheckbtnkeypad->initButtons(); EXPECT_EQ(m_procheckbtnkeypad->m_keys.size(), 6); delete m_procheckbtnkeypad; } TEST_F(Ut_ProCheckBtnKeypad, buttonThemeChanged) { ProCheckBtnKeypad *m_procheckbtnkeypad = new ProCheckBtnKeypad; m_procheckbtnkeypad->buttonThemeChanged(1); EXPECT_EQ(static_cast(m_procheckbtnkeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))->m_currentUrl, ":/assets/images/light/icon_generalkeyboard_normal.svg"); m_procheckbtnkeypad->buttonThemeChanged(2); EXPECT_EQ(static_cast(m_procheckbtnkeypad->button(ProCheckBtnKeypad::Key_BinaryKeypad))->m_currentUrl, ":/assets/images/dark/icon_binarysystem_normal.svg"); delete m_procheckbtnkeypad; } TEST_F(Ut_ProCheckBtnKeypad, getFocus) { ProCheckBtnKeypad *m_procheckbtnkeypad = new ProCheckBtnKeypad; m_procheckbtnkeypad->getFocus(1); m_procheckbtnkeypad->getFocus(2); m_procheckbtnkeypad->getFocus(3); //焦点函数,无assert delete m_procheckbtnkeypad; } deepin-calculator-5.7.21/tests/src/control/ut_procheckbtnkeypad.h000066400000000000000000000004551423020056600251750ustar00rootroot00000000000000#ifndef UT_PROCHECKBTNKEYPAD_H #define UT_PROCHECKBTNKEYPAD_H #include #include #include #include "../../src/dsettings.h" class Ut_ProCheckBtnKeypad : public ::testing::Test { public: Ut_ProCheckBtnKeypad(); }; #endif // UT_PROCHECKBTNKEYPAD_H deepin-calculator-5.7.21/tests/src/control/ut_programmerkeypad.cpp000066400000000000000000000114611423020056600254000ustar00rootroot00000000000000#include "ut_programmerkeypad.h" #include "../../src/control/programmerkeypad.h" Ut_ProgrammerKeypad::Ut_ProgrammerKeypad() { } TEST_F(Ut_ProgrammerKeypad, button) { ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; EXPECT_EQ(m_programmerkeypad->button(ProgrammerKeypad::Buttons::Key_AND)->text(), "AND"); delete m_programmerkeypad; } TEST_F(Ut_ProgrammerKeypad, animate) { ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; m_programmerkeypad->animate(ProgrammerKeypad::Buttons::Key_AND, false); m_programmerkeypad->animate(ProgrammerKeypad::Buttons::Key_equal, false); m_programmerkeypad->animate(ProgrammerKeypad::Buttons::Key_moveL, false); EXPECT_FALSE(static_cast(m_programmerkeypad->button(ProgrammerKeypad::Buttons::Key_AND))->m_isHover); EXPECT_FALSE(static_cast(m_programmerkeypad->button(ProgrammerKeypad::Buttons::Key_equal))->m_isHover); EXPECT_FALSE(static_cast(m_programmerkeypad->button(ProgrammerKeypad::Buttons::Key_moveL))->m_isHover); delete m_programmerkeypad; } TEST_F(Ut_ProgrammerKeypad, buttonHasFocus) { ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; EXPECT_FALSE(m_programmerkeypad->buttonHasFocus()); delete m_programmerkeypad; } TEST_F(Ut_ProgrammerKeypad, initButtons) { ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; m_programmerkeypad->initButtons(); EXPECT_EQ(m_programmerkeypad->m_keys.size(), 36); delete m_programmerkeypad; } TEST_F(Ut_ProgrammerKeypad, buttonThemeChanged) { ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; m_programmerkeypad->buttonThemeChanged(1); EXPECT_EQ(static_cast(m_programmerkeypad->button(ProgrammerKeypad::Key_Div))->m_currentUrl, ":/assets/images/light/divide_normal.svg"); m_programmerkeypad->buttonThemeChanged(2); EXPECT_EQ(static_cast(m_programmerkeypad->button(ProgrammerKeypad::Key_Mult))->m_currentUrl, ":/assets/images/dark/x_normal.svg"); delete m_programmerkeypad; } TEST_F(Ut_ProgrammerKeypad, getFocus) { ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; m_programmerkeypad->getFocus(1); m_programmerkeypad->getFocus(2); m_programmerkeypad->getFocus(3); //焦点函数无assert delete m_programmerkeypad; } TEST_F(Ut_ProgrammerKeypad, radixChanged) { ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; m_programmerkeypad->radixChanged(0); EXPECT_EQ(m_programmerkeypad->m_currentBase, 16); m_programmerkeypad->radixChanged(1); EXPECT_EQ(m_programmerkeypad->m_currentBase, 10); m_programmerkeypad->radixChanged(2); EXPECT_EQ(m_programmerkeypad->m_currentBase, 8); m_programmerkeypad->radixChanged(3); EXPECT_EQ(m_programmerkeypad->m_currentBase, 2); m_programmerkeypad->radixChanged(5); EXPECT_EQ(m_programmerkeypad->m_currentBase, 10); delete m_programmerkeypad; } TEST_F(Ut_ProgrammerKeypad, bracketsNum) { ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; m_programmerkeypad->bracketsNum(0, "0"); EXPECT_EQ(m_programmerkeypad->m_leftBracket->text(), ""); m_programmerkeypad->bracketsNum(1, "1"); EXPECT_EQ(m_programmerkeypad->m_rightBracket->text(), "1"); delete m_programmerkeypad; } TEST_F(Ut_ProgrammerKeypad, connects) { ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; QString str1 = QString("font-family:Noto Sans;color:%1;font-size:14px;") .arg(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name()); QString str2 = QString("font-family:Noto Sans;color:black;font-size:14px;"); QString str3 = QString("font-family:Noto Sans;color:white;font-size:14px;"); m_programmerkeypad->m_themetype = 1; m_programmerkeypad->button(ProgrammerKeypad::Key_leftBracket)->pressed(); EXPECT_EQ(m_programmerkeypad->m_leftBracket->styleSheet(), str1); static_cast(m_programmerkeypad->button(ProgrammerKeypad::Key_leftBracket))->mouseRelease(); EXPECT_EQ(m_programmerkeypad->m_leftBracket->styleSheet(), str2); m_programmerkeypad->m_themetype = 2; m_programmerkeypad->button(ProgrammerKeypad::Key_rightBracket)->pressed(); EXPECT_EQ(m_programmerkeypad->m_rightBracket->styleSheet(), str1); static_cast(m_programmerkeypad->button(ProgrammerKeypad::Key_rightBracket))->mouseRelease(); EXPECT_EQ(m_programmerkeypad->m_rightBracket->styleSheet(), str3); delete m_programmerkeypad; } //TEST_F(Ut_ProgrammerKeypad, initUI) //{ // ProgrammerKeypad *m_programmerkeypad = new ProgrammerKeypad; // m_programmerkeypad->bracketsNum(0, "0"); // m_programmerkeypad->bracketsNum(1, "1"); // ASSERT_EQ(m_programmerkeypad->m_rightBracket->text(), "1"); // DSettingsAlt::deleteInstance(); //} deepin-calculator-5.7.21/tests/src/control/ut_programmerkeypad.h000066400000000000000000000004501423020056600250410ustar00rootroot00000000000000#ifndef UT_PROGRAMMERKEYPAD_H #define UT_PROGRAMMERKEYPAD_H #include #include #include #include "../../src/dsettings.h" class Ut_ProgrammerKeypad : public ::testing::Test { public: Ut_ProgrammerKeypad(); }; #endif // UT_PROGRAMMERKEYPAD_H deepin-calculator-5.7.21/tests/src/control/ut_prosystemkeypad.cpp000066400000000000000000000067501423020056600252770ustar00rootroot00000000000000#include "ut_prosystemkeypad.h" #include "../../src/control/prosystemkeypad.h" #include "../3rdparty/core/settings.h" Ut_ProSystemKeypad::Ut_ProSystemKeypad() { } TEST_F(Ut_ProSystemKeypad, buttonHasFocus) { ProSystemKeypad *m_prosystemkeypad = new ProSystemKeypad; EXPECT_FALSE(m_prosystemkeypad->buttonHasFocus()); delete m_prosystemkeypad; } TEST_F(Ut_ProSystemKeypad, getFocus) { ProSystemKeypad *m_prosystemkeypad = new ProSystemKeypad; m_prosystemkeypad->getFocus(0, 1); m_prosystemkeypad->getFocus(1, 1); m_prosystemkeypad->getFocus(2, 1); m_prosystemkeypad->getFocus(3, 1); //焦点函数,无assert delete m_prosystemkeypad; } TEST_F(Ut_ProSystemKeypad, setSystem) { ProSystemKeypad *m_prosystemkeypad = new ProSystemKeypad; m_prosystemkeypad->setSystem(32, 64); EXPECT_FALSE(m_prosystemkeypad->m_buttons.value(33)->isEnabled()); m_prosystemkeypad->m_binaryValue = "0000000000000000000000000000000000000000000000000000000011111111"; m_prosystemkeypad->setSystem(64, 8); EXPECT_TRUE(m_prosystemkeypad->m_buttons.value(60)->isEnabled()); m_prosystemkeypad->setSystem(8, 16); EXPECT_FALSE(m_prosystemkeypad->m_buttons.value(11)->isEnabled()); m_prosystemkeypad->setSystem(16, 32); EXPECT_FALSE(m_prosystemkeypad->m_buttons.value(20)->isEnabled()); m_prosystemkeypad->m_binaryValue = "0000000000000000000000000000000011111111111111111111111111111111"; m_prosystemkeypad->setSystem(64, 32); EXPECT_EQ(m_prosystemkeypad->m_buttons.value(60)->text(), "1"); m_prosystemkeypad->m_binaryValue = "0000000000000000000000000000000000000000000000001111111111111111"; m_prosystemkeypad->setSystem(32, 16); EXPECT_EQ(m_prosystemkeypad->m_buttons.value(20)->text(), "1"); m_prosystemkeypad->m_binaryValue = "0000000000000000000000000000000000000000000000000000011011111111"; m_prosystemkeypad->setSystem(16, 8); EXPECT_EQ(m_prosystemkeypad->m_buttons.value(9)->text(), "1"); m_prosystemkeypad->setSystem(8, 64); EXPECT_FALSE(m_prosystemkeypad->m_buttons.value(60)->isEnabled()); delete m_prosystemkeypad; } TEST_F(Ut_ProSystemKeypad, setvalue) { ProSystemKeypad *m_prosystemkeypad = new ProSystemKeypad; Settings::instance()->proBitLength = 8; m_prosystemkeypad->setvalue("101111111"); EXPECT_EQ(m_prosystemkeypad->m_binaryValue, "0000000000000000000000000000000000000000000000000000000001111111"); Settings::instance()->proBitLength = 64; delete m_prosystemkeypad; } TEST_F(Ut_ProSystemKeypad, longBitCut) { ProSystemKeypad *m_prosystemkeypad = new ProSystemKeypad; m_prosystemkeypad->longBitCut("110000000000000000000000000000000000000000000000000000000101111111"); EXPECT_EQ(m_prosystemkeypad->m_binaryValue, "0000000000000000000000000000000000000000000000000000000000000000"); delete m_prosystemkeypad; } TEST_F(Ut_ProSystemKeypad, changeBinaryValue) { ProSystemKeypad *m_prosystemkeypad = new ProSystemKeypad; m_prosystemkeypad->changeBinaryValue(5); EXPECT_EQ(m_prosystemkeypad->m_binaryValue, "0000000000000000000000000000000000000000000000000000000000100000"); delete m_prosystemkeypad; } TEST_F(Ut_ProSystemKeypad, initconnects) { ProSystemKeypad *m_prosystemkeypad = new ProSystemKeypad; m_prosystemkeypad->m_buttons.value(1)->clicked(); EXPECT_EQ(m_prosystemkeypad->m_buttons.value(1)->text(), "0"); m_prosystemkeypad->m_buttons.value(1)->space(); EXPECT_EQ(m_prosystemkeypad->m_buttons.value(1)->text(), "1"); delete m_prosystemkeypad; } deepin-calculator-5.7.21/tests/src/control/ut_prosystemkeypad.h000066400000000000000000000004431423020056600247350ustar00rootroot00000000000000#ifndef UT_PROSYSTEMKEYPAD_H #define UT_PROSYSTEMKEYPAD_H #include #include #include #include "../../src/dsettings.h" class Ut_ProSystemKeypad : public ::testing::Test { public: Ut_ProSystemKeypad(); }; #endif // UT_PROSYSTEMKEYPAD_H deepin-calculator-5.7.21/tests/src/control/ut_scientifickeypad.cpp000066400000000000000000000123341423020056600253450ustar00rootroot00000000000000#include "ut_scientifickeypad.h" #include "../../src/control/scientifickeypad.h" #include "../../src/memorypublic.h" Ut_ScientificKeypad::Ut_ScientificKeypad() { } TEST_F(Ut_ScientificKeypad, button1) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; m_scientifickeypad->button(ScientificKeyPad::Key_arcsin); EXPECT_EQ(m_scientifickeypad->button(ScientificKeyPad::Key_sin)->text(), "sin"); delete m_scientifickeypad; } TEST_F(Ut_ScientificKeypad, button2) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; m_scientifickeypad->button(42); EXPECT_EQ(m_scientifickeypad->button(6)->text(), "sin"); delete m_scientifickeypad; } TEST_F(Ut_ScientificKeypad, animate) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; m_scientifickeypad->animate(ScientificKeyPad::Key_sin, false); EXPECT_FALSE(static_cast(m_scientifickeypad->button(ScientificKeyPad::Buttons::Key_sin))->m_isHover); delete m_scientifickeypad; } TEST_F(Ut_ScientificKeypad, buttonHasFocus) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; m_scientifickeypad->button(6)->setFocus(); EXPECT_FALSE(m_scientifickeypad->buttonHasFocus()); delete m_scientifickeypad; } TEST_F(Ut_ScientificKeypad, buttonThemeChanged) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; m_scientifickeypad->m_deg = 3; m_scientifickeypad->buttonThemeChanged(1); EXPECT_EQ(static_cast(m_scientifickeypad->button(ScientificKeyPad::Key_deg))->m_currentUrl, ":/assets/images/light/deg_normal.svg"); m_scientifickeypad->buttonThemeChanged(2); EXPECT_EQ(static_cast(m_scientifickeypad->button(ScientificKeyPad::Key_deg))->m_currentUrl, ":/assets/images/dark/deg_normal.svg"); delete m_scientifickeypad; } TEST_F(Ut_ScientificKeypad, turnPage) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; m_scientifickeypad->turnPage(ScientificKeyPad::Key_page); EXPECT_EQ(m_scientifickeypad->m_sqrtwidget->currentIndex(), 1); m_scientifickeypad->turnPage(ScientificKeyPad::Key_page); EXPECT_EQ(m_scientifickeypad->m_sqrtwidget->currentIndex(), 0); delete m_scientifickeypad; } TEST_F(Ut_ScientificKeypad, getdeg) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; m_scientifickeypad->getdeg(1); EXPECT_NE(static_cast(m_scientifickeypad->button(ScientificKeyPad::Key_deg))->m_currentUrl, ":/assets/images/light/grad_normal.svg"); m_scientifickeypad->getdeg(2); EXPECT_NE(static_cast(m_scientifickeypad->button(ScientificKeyPad::Key_deg))->m_currentUrl, ":/assets/images/light/deg_normal.svg"); m_scientifickeypad->getdeg(3); EXPECT_NE(static_cast(m_scientifickeypad->button(ScientificKeyPad::Key_deg))->m_currentUrl, ":/assets/images/light/rad_normal.svg"); delete m_scientifickeypad; } TEST_F(Ut_ScientificKeypad, bracketsNum) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; m_scientifickeypad->bracketsNum(0, "0"); EXPECT_EQ(m_scientifickeypad->m_leftBracket->text(), ""); m_scientifickeypad->bracketsNum(1, "1"); EXPECT_EQ(m_scientifickeypad->m_rightBracket->text(), "1"); delete m_scientifickeypad; } bool stub_focus_scikey() { return true; } TEST_F(Ut_ScientificKeypad, getFocus) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; Stub stub; stub.set(ADDR(QWidget, hasFocus), stub_focus_scikey); m_scientifickeypad->m_arcsinwidget->setCurrentIndex(0); m_scientifickeypad->getFocus(0); m_scientifickeypad->getFocus(1); m_scientifickeypad->getFocus(2); m_scientifickeypad->getFocus(3); m_scientifickeypad->getFocus(4); m_scientifickeypad->m_arcsinwidget->setCurrentIndex(1); m_scientifickeypad->getFocus(0); m_scientifickeypad->getFocus(1); m_scientifickeypad->getFocus(2); m_scientifickeypad->getFocus(3); m_scientifickeypad->getFocus(4); //无ASSERT delete m_scientifickeypad; } TEST_F(Ut_ScientificKeypad, connects) { ScientificKeyPad *m_scientifickeypad = new ScientificKeyPad; QString str1 = QString("font-family:Noto Sans;color:%1;font-size:14px;") .arg(Dtk::Gui::DGuiApplicationHelper::instance()->applicationPalette().highlight().color().name()); QString str2 = QString("font-family:Noto Sans;color:black;font-size:14px;"); QString str3 = QString("font-family:Noto Sans;color:white;font-size:14px;"); m_scientifickeypad->m_themetype = 1; m_scientifickeypad->button(ScientificKeyPad::Key_left)->pressed(); EXPECT_EQ(m_scientifickeypad->m_leftBracket->styleSheet(), str1); static_cast(m_scientifickeypad->button(ScientificKeyPad::Key_left))->mouseRelease(); EXPECT_EQ(m_scientifickeypad->m_leftBracket->styleSheet(), str2); m_scientifickeypad->m_themetype = 2; m_scientifickeypad->button(ScientificKeyPad::Key_right)->pressed(); EXPECT_EQ(m_scientifickeypad->m_rightBracket->styleSheet(), str1); static_cast(m_scientifickeypad->button(ScientificKeyPad::Key_right))->mouseRelease(); EXPECT_EQ(m_scientifickeypad->m_rightBracket->styleSheet(), str3); delete m_scientifickeypad; } deepin-calculator-5.7.21/tests/src/control/ut_scientifickeypad.h000066400000000000000000000004741423020056600250140ustar00rootroot00000000000000#ifndef UT_SCIENTIFICKEYPAD_H #define UT_SCIENTIFICKEYPAD_H #include #include #include #include "../../src/dsettings.h" #include"../stub.h" class Ut_ScientificKeypad : public ::testing::Test { public: Ut_ScientificKeypad(); }; #endif // UT_SCIENTIFICKEYPAD_H deepin-calculator-5.7.21/tests/src/control/ut_textbutton.cpp000066400000000000000000000251021423020056600242440ustar00rootroot00000000000000#include "ut_textbutton.h" #include "../../src/control/textbutton.h" Ut_TextButton::Ut_TextButton() { } TEST_F(Ut_TextButton, init) { TextButton *m_textbutton = new TextButton; m_textbutton->setText("+/-"); // m_textbutton->animate(false, 100); m_textbutton->init(); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 20); EXPECT_EQ(m_textbutton->m_font.family(), "Noto Sans"); EXPECT_EQ(m_textbutton->m_font.styleName(), "Light"); EXPECT_EQ(m_textbutton->m_font.weight(), 2); delete m_textbutton; } TEST_F(Ut_TextButton, animate) { TextButton *m_textbutton = new TextButton; m_textbutton->m_isHover = true; m_textbutton->m_isPress = false; m_textbutton->animate(false, 100); EXPECT_FALSE(m_textbutton->m_isHover); EXPECT_TRUE(m_textbutton->m_isPress); delete m_textbutton; } TEST_F(Ut_TextButton, setButtonDown) { TextButton *m_textbutton = new TextButton; m_textbutton->m_Btnisdown = true; m_textbutton->setButtonDown(false); EXPECT_FALSE(m_textbutton->m_Btnisdown); delete m_textbutton; } TEST_F(Ut_TextButton, mousePressEvent) { TextButton *m_textbutton = new TextButton; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_textbutton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_textbutton->mousePressEvent(m); EXPECT_TRUE(m_textbutton->m_isPress); EXPECT_FALSE(m_textbutton->m_isHover); delete m; delete m_textbutton; } TEST_F(Ut_TextButton, mouseReleaseEvent) { TextButton *m_textbutton = new TextButton; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonRelease, m_textbutton->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_textbutton->mouseReleaseEvent(m); EXPECT_FALSE(m_textbutton->m_isPress); EXPECT_TRUE(m_textbutton->m_isHover); delete m; delete m_textbutton; } TEST_F(Ut_TextButton, enterEvent) { TextButton *m_textbutton = new TextButton; QEvent *e = new QEvent(QEvent::Type::Enter); m_textbutton->setText("Rand"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 17); m_textbutton->setText("logᵧx"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 16); m_textbutton->setText("log"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 18); m_textbutton->setText("|x|"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 16); m_textbutton->setText("Mod"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 16); m_textbutton->setText("exp"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 18); m_textbutton->setText("sin"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 18); m_textbutton->setText("cos"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 18); m_textbutton->setText("tan"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 18); m_textbutton->setText("cot"); m_textbutton->enterEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 18); m_textbutton->setText("+/-"); m_textbutton->enterEvent(e); EXPECT_TRUE(m_textbutton->m_isHover); delete e; delete m_textbutton; } TEST_F(Ut_TextButton, leaveEvent) { TextButton *m_textbutton = new TextButton; QEvent *e = new QEvent(QEvent::Type::Leave); m_textbutton->setText("Rand"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 15); m_textbutton->setText("logᵧx"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 14); m_textbutton->setText("log"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 16); m_textbutton->setText("|x|"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 14); m_textbutton->setText("Mod"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 14); m_textbutton->setText("exp"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 16); m_textbutton->setText("sin"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 16); m_textbutton->setText("cos"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 16); m_textbutton->setText("tan"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 16); m_textbutton->setText("cot"); m_textbutton->leaveEvent(e); EXPECT_EQ(m_textbutton->m_font.pixelSize(), 16); m_textbutton->setText("+/-"); m_textbutton->leaveEvent(e); EXPECT_FALSE(m_textbutton->m_isHover); delete e; delete m_textbutton; } bool stub_focus_text() { return true; } TEST_F(Ut_TextButton, paintEvent) { TextButton *m_textbutton = new TextButton("1"); QPaintEvent *event = new QPaintEvent(m_textbutton->rect()); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_textbutton->m_isHover = true; m_textbutton->m_isPress = false; m_textbutton->paintEvent(event); m_textbutton->update(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_textbutton->m_isHover = false; m_textbutton->m_isPress = true; m_textbutton->paintEvent(event); m_textbutton->update(); m_textbutton->m_isHover = false; m_textbutton->m_isPress = false; m_textbutton->paintEvent(event); m_textbutton->update(); //focus状态 Stub stub; stub.set(ADDR(TextButton, hasFocus), stub_focus_text); m_textbutton->setEnabled(true); m_textbutton->m_isHover = true; m_textbutton->m_isPress = false; m_textbutton->paintEvent(event); m_textbutton->update(); m_textbutton->setEnabled(true); m_textbutton->m_isHover = false; m_textbutton->m_isPress = true; m_textbutton->paintEvent(event); m_textbutton->update(); m_textbutton->m_isHover = false; m_textbutton->m_isPress = false; m_textbutton->paintEvent(event); delete event; //无ASSERT delete m_textbutton; } TEST_F(Ut_TextButton, keyPressEvent) { TextButton *m_textbutton = new TextButton; QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); QKeyEvent *k2 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); QKeyEvent *k3 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier); QKeyEvent *k4 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier); QKeyEvent *k5 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); m_textbutton->keyPressEvent(k); m_textbutton->keyPressEvent(k1); m_textbutton->keyPressEvent(k2); m_textbutton->keyPressEvent(k3); m_textbutton->keyPressEvent(k4); m_textbutton->keyPressEvent(k5); //无ASSERT delete k; delete k1; delete k2; delete k3; delete k4; delete k5; delete m_textbutton; } TEST_F(Ut_TextButton, paintspecialbtn) { TextButton *m_textbutton = new TextButton; m_textbutton->m_btn = 1; m_textbutton->m_isHover = true; m_textbutton->m_isPress = true; QPainter painter(m_textbutton); m_textbutton->paintspecialbtn(painter, m_textbutton->rect(), painter.fontMetrics().boundingRect(0, 0, int(m_textbutton->rect().width()), int(m_textbutton->rect().height()), Qt::AlignCenter, m_textbutton->text())); m_textbutton->m_btn = 2; m_textbutton->paintspecialbtn(painter, m_textbutton->rect(), painter.fontMetrics().boundingRect(0, 0, int(m_textbutton->rect().width()), int(m_textbutton->rect().height()), Qt::AlignCenter, m_textbutton->text())); m_textbutton->m_btn = 3; m_textbutton->paintspecialbtn(painter, m_textbutton->rect(), painter.fontMetrics().boundingRect(0, 0, int(m_textbutton->rect().width()), int(m_textbutton->rect().height()), Qt::AlignCenter, m_textbutton->text())); m_textbutton->m_btn = 4; m_textbutton->paintspecialbtn(painter, m_textbutton->rect(), painter.fontMetrics().boundingRect(0, 0, int(m_textbutton->rect().width()), int(m_textbutton->rect().height()), Qt::AlignCenter, m_textbutton->text())); m_textbutton->m_btn = 5; m_textbutton->paintspecialbtn(painter, m_textbutton->rect(), painter.fontMetrics().boundingRect(0, 0, int(m_textbutton->rect().width()), int(m_textbutton->rect().height()), Qt::AlignCenter, m_textbutton->text())); m_textbutton->m_btn = 6; m_textbutton->paintspecialbtn(painter, m_textbutton->rect(), painter.fontMetrics().boundingRect(0, 0, int(m_textbutton->rect().width()), int(m_textbutton->rect().height()), Qt::AlignCenter, m_textbutton->text())); m_textbutton->m_btn = 7; m_textbutton->paintspecialbtn(painter, m_textbutton->rect(), painter.fontMetrics().boundingRect(0, 0, int(m_textbutton->rect().width()), int(m_textbutton->rect().height()), Qt::AlignCenter, m_textbutton->text())); m_textbutton->m_btn = 8; m_textbutton->paintspecialbtn(painter, m_textbutton->rect(), painter.fontMetrics().boundingRect(0, 0, int(m_textbutton->rect().width()), int(m_textbutton->rect().height()), Qt::AlignCenter, m_textbutton->text())); m_textbutton->m_btn = 9; m_textbutton->paintspecialbtn(painter, m_textbutton->rect(), painter.fontMetrics().boundingRect(0, 0, int(m_textbutton->rect().width()), int(m_textbutton->rect().height()), Qt::AlignCenter, m_textbutton->text())); //paint函数,无assert delete m_textbutton; } deepin-calculator-5.7.21/tests/src/control/ut_textbutton.h000066400000000000000000000003751423020056600237160ustar00rootroot00000000000000#ifndef UT_TEXTBUTTON_H #define UT_TEXTBUTTON_H #include #include #include #include"../stub.h" class Ut_TextButton : public ::testing::Test { public: Ut_TextButton(); }; #endif // UT_TEXTBUTTON_H deepin-calculator-5.7.21/tests/src/main.cpp000066400000000000000000000007761423020056600205720ustar00rootroot00000000000000// test_main.cpp 测试入口 #include #include #include #if defined(CMAKE_SAFETYTEST_ARG_ON) #include #endif #include int main(int argc, char *argv[]) { qputenv("QT_QPA_PLATFORM", "offscreen"); QApplication app(argc, argv); ::testing::InitGoogleTest(&argc, argv); auto c = RUN_ALL_TESTS(); #if defined(CMAKE_SAFETYTEST_ARG_ON) __sanitizer_set_report_path("asan.log"); #endif return c; } deepin-calculator-5.7.21/tests/src/stub.h000066400000000000000000000164231423020056600202640ustar00rootroot00000000000000#ifndef __STUB_H__ #define __STUB_H__ #ifdef _WIN32 //windows #include #include #else //linux #include #include #endif //c #include #include //c++ #include #define ADDR(CLASS_NAME,MEMBER_NAME) (&CLASS_NAME::MEMBER_NAME) /********************************************************** replace function **********************************************************/ #ifdef _WIN32 #define CACHEFLUSH(addr, size) FlushInstructionCache(GetCurrentProcess(), addr, size) #else #define CACHEFLUSH(addr, size) __builtin___clear_cache(addr, addr + size) #endif #if defined(__aarch64__) || defined(_M_ARM64) #define CODESIZE 16U #define CODESIZE_MIN 16U #define CODESIZE_MAX CODESIZE // ldr x9, +8 // br x9 // addr #define REPLACE_FAR(t, fn, fn_stub)\ ((uint32_t*)fn)[0] = 0x58000040 | 9;\ ((uint32_t*)fn)[1] = 0xd61f0120 | (9 << 5);\ *(long long *)(fn + 8) = (long long )fn_stub;\ CACHEFLUSH((char *)fn, CODESIZE); #define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub) #elif defined(__arm__) || defined(_M_ARM) #define CODESIZE 8U #define CODESIZE_MIN 8U #define CODESIZE_MAX CODESIZE // ldr pc, [pc, #-4] #define REPLACE_FAR(t, fn, fn_stub)\ ((uint32_t*)fn)[0] = 0xe51ff004;\ ((uint32_t*)fn)[1] = (uint32_t)fn_stub;\ CACHEFLUSH((char *)fn, CODESIZE); #define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub) #elif defined(__thumb__) || defined(_M_THUMB) #error "Thumb is not supported" #else //__i386__ _x86_64__ #define CODESIZE 13U #define CODESIZE_MIN 5U #define CODESIZE_MAX CODESIZE //13 byte(jmp m16:64) //movabs $0x102030405060708,%r11 //jmpq *%r11 #define REPLACE_FAR(t, fn, fn_stub)\ *fn = 0x49;\ *(fn + 1) = 0xbb;\ *(long long *)(fn + 2) = (long long)fn_stub;\ *(fn + 10) = 0x41;\ *(fn + 11) = 0xff;\ *(fn + 12) = 0xe3;\ //CACHEFLUSH((char *)fn, CODESIZE); //5 byte(jmp rel32) #define REPLACE_NEAR(t, fn, fn_stub)\ *fn = 0xE9;\ *(int *)(fn + 1) = (int)(fn_stub - fn - CODESIZE_MIN);\ //CACHEFLUSH((char *)fn, CODESIZE); #endif struct func_stub { char *fn; unsigned char code_buf[CODESIZE]; bool far_jmp; }; class Stub { public: Stub() { #ifdef _WIN32 SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); m_pagesize = sys_info.dwPageSize; #else m_pagesize = sysconf(_SC_PAGE_SIZE); #endif if (m_pagesize < 0) { m_pagesize = 4096; } } ~Stub() { std::map::iterator iter; struct func_stub *pstub; for(iter=m_result.begin(); iter != m_result.end(); iter++) { pstub = iter->second; #ifdef _WIN32 DWORD lpflOldProtect; if(0 != VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect)) #else if (0 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC)) #endif { if(pstub->far_jmp) { std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MAX); } else { std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MIN); } #ifdef _WIN32 VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect); #else mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC); #endif } iter->second = NULL; delete pstub; } return; } template void set(T addr, S addr_stub) { char * fn; char * fn_stub; fn = addrof(addr); fn_stub = addrof(addr_stub); struct func_stub *pstub; pstub = new func_stub; //start pstub->fn = fn; if(distanceof(fn, fn_stub)) { pstub->far_jmp = true; std::memcpy(pstub->code_buf, fn, CODESIZE_MAX); } else { pstub->far_jmp = false; std::memcpy(pstub->code_buf, fn, CODESIZE_MIN); } #ifdef _WIN32 DWORD lpflOldProtect; if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect)) #else if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC)) #endif { throw("stub set memory protect to w+r+x faild"); } if(pstub->far_jmp) { REPLACE_FAR(this, fn, fn_stub); } else { REPLACE_NEAR(this, fn, fn_stub); } #ifdef _WIN32 if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect)) #else if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC)) #endif { throw("stub set memory protect to r+x failed"); } m_result.insert(std::pair(fn,pstub)); return; } template void reset(T addr) { char * fn; fn = addrof(addr); std::map::iterator iter = m_result.find(fn); if (iter == m_result.end()) { return; } struct func_stub *pstub; pstub = iter->second; #ifdef _WIN32 DWORD lpflOldProtect; if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect)) #else if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC)) #endif { throw("stub reset memory protect to w+r+x faild"); } if(pstub->far_jmp) { std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MAX); } else { std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MIN); } #ifdef _WIN32 if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect)) #else if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC)) #endif { throw("stub reset memory protect to r+x failed"); } m_result.erase(iter); delete pstub; return; } private: char *pageof(char* addr) { #ifdef _WIN32 return (char *)((unsigned long long)addr & ~(m_pagesize - 1)); #else return (char *)((unsigned long)addr & ~(m_pagesize - 1)); #endif } template char* addrof(T addr) { union { T _s; char* _d; }ut; ut._s = addr; return ut._d; } bool distanceof(char* addr, char* addr_stub) { std::ptrdiff_t diff = addr_stub >= addr ? addr_stub - addr : addr - addr_stub; if((sizeof(addr) > 4) && (((diff >> 31) - 1) > 0)) { return true; } return false; } private: #ifdef _WIN32 //LLP64 long long m_pagesize; #else //LP64 long m_pagesize; #endif std::map m_result; }; #endif deepin-calculator-5.7.21/tests/src/ut_dsetting.cpp000066400000000000000000000014361423020056600221710ustar00rootroot00000000000000#include "ut_dsetting.h" #include "../../src/dsettings.h" Ut_DSetting::Ut_DSetting() { } TEST_F(Ut_DSetting, getwidget) { DSettingsAlt *m_dsetting = new DSettingsAlt; m_dsetting->m_settings->setValue("theme", ""); m_dsetting->m_settings->setValue("mode", ""); m_dsetting->m_settings->setValue("history", ""); m_dsetting->m_settings->setValue("windowX", ""); m_dsetting->m_settings->setValue("windowY", ""); m_dsetting->m_settings->setValue("windowWidth", ""); m_dsetting->m_settings->setValue("windowHeight", ""); m_dsetting->initConfig(); EXPECT_EQ(m_dsetting->getOption("windowHeight").toInt(), 0); EXPECT_EQ(m_dsetting->getOption("mode").toInt(), 0); EXPECT_EQ(m_dsetting->getOption("theme").toInt(), 0); DSettingsAlt::deleteInstance(); } deepin-calculator-5.7.21/tests/src/ut_dsetting.h000066400000000000000000000003361423020056600216340ustar00rootroot00000000000000#ifndef UT_DSETTING_H #define UT_DSETTING_H #include #include #include class Ut_DSetting : public ::testing::Test { public: Ut_DSetting(); }; #endif // UT_DSETTING_H deepin-calculator-5.7.21/tests/src/ut_mainwindow.cpp000066400000000000000000000063771423020056600225350ustar00rootroot00000000000000#include "ut_mainwindow.h" #include "../../src/mainwindow.h" #include #include TestCala::TestCala() { } TEST_F(TestCala, initTheme) { MainWindow *m_mainwindow = new MainWindow; DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::UnknownType); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_mainwindow->initTheme(); EXPECT_EQ(m_mainwindow->titlebar()->palette().color(DPalette::Light), QColor(240, 240, 240)); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_mainwindow->initTheme(); QColor color(0, 0, 0); color.setAlphaF(0.1); EXPECT_EQ(m_mainwindow->titlebar()->palette().color(DPalette::Light), color); m_mainwindow->deleteLater(); } TEST_F(TestCala, initModule) { MainWindow *m_mainwindow = new MainWindow; m_mainwindow->m_settings->setOption("mode", 2); m_mainwindow->initModule(); EXPECT_EQ(m_mainwindow->m_mainLayout->currentWidget(), m_mainwindow->m_programmerModule); m_mainwindow->m_settings->setOption("mode", 0); m_mainwindow->initModule(); EXPECT_EQ(m_mainwindow->m_mainLayout->currentWidget(), m_mainwindow->m_basicModule); m_mainwindow->m_settings->setOption("mode", 1); m_mainwindow->initModule(); EXPECT_EQ(m_mainwindow->m_mainLayout->currentWidget(), m_mainwindow->m_scientificModule); EXPECT_FALSE(m_mainwindow->m_isinit); m_mainwindow->deleteLater(); } TEST_F(TestCala, switchToSimpleMode) { MainWindow *m_mainwindow = new MainWindow; m_mainwindow->m_settings->setOption("mode", 1); m_mainwindow->switchToSimpleMode(); EXPECT_EQ(m_mainwindow->m_settings->getOption("mode"), 0); EXPECT_EQ(m_mainwindow->m_mainLayout->currentWidget(), m_mainwindow->m_basicModule); m_mainwindow->deleteLater(); } TEST_F(TestCala, switchToScientificMode) { MainWindow *m_mainwindow = new MainWindow; m_mainwindow->m_settings->setOption("mode", 0); m_mainwindow->switchToScientificMode(); EXPECT_EQ(m_mainwindow->m_settings->getOption("mode"), 1); EXPECT_EQ(m_mainwindow->m_mainLayout->currentWidget(), m_mainwindow->m_scientificModule); m_mainwindow->deleteLater(); } TEST_F(TestCala, keyPressEvent) { MainWindow *m_mainwindow = new MainWindow; m_mainwindow->m_settings->setOption("mode", 0); m_mainwindow->initModule(); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier); m_mainwindow->keyPressEvent(k); EXPECT_EQ(m_mainwindow->m_basicModule->m_expressionBar->getInputEdit()->text(), "1"); delete k; m_mainwindow->deleteLater(); } TEST_F(TestCala, moveEvent) { MainWindow *m_mainwindow = new MainWindow; QMoveEvent *m = new QMoveEvent(QPoint(1, 1), QPoint(0, 0)); m_mainwindow->moveEvent(m); EXPECT_EQ(m_mainwindow->m_settings->getOption("windowX"), 1); delete m; m_mainwindow->deleteLater(); } TEST_F(TestCala, resizeEvent) { MainWindow *m_mainwindow = new MainWindow; m_mainwindow->switchToScientificMode(); QResizeEvent *r = new QResizeEvent(QSize(811, 542), QSize(451, 542)); m_mainwindow->resizeEvent(r); EXPECT_EQ(m_mainwindow->m_settings->getOption("windowWidth"), 811); delete r; m_mainwindow->deleteLater(); } deepin-calculator-5.7.21/tests/src/ut_mainwindow.h000066400000000000000000000004241423020056600221650ustar00rootroot00000000000000#ifndef UT_QTEST_H #define UT_QTEST_H #include #include #include #include "../../src/memorypublic.h" #include "../../src/dsettings.h" class TestCala : public::testing::Test { public: TestCala(); }; #endif // UT_QTEST_H deepin-calculator-5.7.21/tests/src/ut_memorypublic.cpp000066400000000000000000000072211423020056600230550ustar00rootroot00000000000000#include "ut_memorypublic.h" #include "../../src/memorypublic.h" Ut_MemoryPublic::Ut_MemoryPublic() { } TEST_F(Ut_MemoryPublic, getwidget) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *memorywidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); EXPECT_EQ(memorywidget->m_calculatormode, 1); } TEST_F(Ut_MemoryPublic, memoryplus) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *memorywidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->memoryplus(Quantity(0)); EXPECT_EQ(memorywidget->m_listwidget->count(), 1); } TEST_F(Ut_MemoryPublic, memoryminus) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *memorywidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->memoryminus(Quantity(0)); EXPECT_EQ(memorywidget->m_listwidget->count(), 1); } TEST_F(Ut_MemoryPublic, memoryclean) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *memorywidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->memoryclean(); m_memoryPublic->generateData(Quantity(0)); m_memoryPublic->generateData(Quantity(0)); m_memoryPublic->generateData(Quantity(0)); EXPECT_EQ(m_memoryPublic->m_list.count(), 3); m_memoryPublic->memoryclean(); EXPECT_EQ(memorywidget->m_listwidget->count(), 1); } TEST_F(Ut_MemoryPublic, widgetplus) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *memorywidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); m_memoryPublic->widgetplus(0, Quantity(1)); MemoryItemWidget *w1 = static_cast(memorywidget->m_listwidget->itemWidget(memorywidget->m_listwidget->item(0))); EXPECT_EQ(w1->textLabel(), "2"); } TEST_F(Ut_MemoryPublic, widgetminus) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *memorywidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); m_memoryPublic->widgetminus(0, Quantity(1)); MemoryItemWidget *w1 = static_cast(memorywidget->m_listwidget->itemWidget(memorywidget->m_listwidget->item(0))); EXPECT_EQ(w1->textLabel(), "0"); } TEST_F(Ut_MemoryPublic, widgetclean) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *memorywidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); memorywidget->m_calculatormode = 0; m_memoryPublic->memoryclean(); m_memoryPublic->generateData(Quantity(0)); m_memoryPublic->generateData(Quantity(0)); m_memoryPublic->generateData(Quantity(0)); EXPECT_EQ(m_memoryPublic->m_list.count(), 3); m_memoryPublic->widgetclean(1, 1, false); EXPECT_EQ(memorywidget->m_listwidget->count(), 2); } TEST_F(Ut_MemoryPublic, setThemeType) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *memorywidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->m_list.clear(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_memoryPublic->setThemeType(0); EXPECT_EQ(memorywidget->m_clearbutton->m_currentUrl, ":/assets/images/light/empty_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_memoryPublic->setThemeType(0); EXPECT_EQ(memorywidget->m_clearbutton->m_currentUrl, ":/assets/images/dark/empty_normal.svg"); } deepin-calculator-5.7.21/tests/src/ut_memorypublic.h000066400000000000000000000004241423020056600225200ustar00rootroot00000000000000#ifndef UT_MEMORYPUBLIC_H #define UT_MEMORYPUBLIC_H #include #include #include #include "../../src/dsettings.h" class Ut_MemoryPublic : public ::testing::Test { public: Ut_MemoryPublic(); }; #endif // UT_MEMORYPUBLIC_H deepin-calculator-5.7.21/tests/src/ut_utils.cpp000066400000000000000000000017251423020056600215110ustar00rootroot00000000000000#include "ut_utils.h" #include "../../src/utils.h" #include "stub.h" Ut_Utils::Ut_Utils() { } QString stub_filePath_utils(const QString &fileName) { Q_UNUSED(fileName); return QByteArray("111"); } TEST_F(Ut_Utils, getwidget) { Utils *m_utils = new Utils; Stub stub; stub.set(ADDR(QDir, filePath), stub_filePath_utils); ASSERT_EQ(m_utils->getConfigDir(), "111"); delete m_utils; } QByteArray stub_readall_utils() { return QByteArray("111"); } TEST_F(Ut_Utils, getQssContent) { Utils *m_utils = new Utils; Stub stub; stub.set(ADDR(QFile, readAll), stub_readall_utils); m_utils->getQssContent("/etc/apt/sources.list"); ASSERT_EQ(m_utils->getQssContent("/etc/apt/sources.list"), "111"); delete m_utils; } TEST_F(Ut_Utils, formatThousandsSeparators) { Utils *m_utils = new Utils; m_utils->formatThousandsSeparators("1234"); EXPECT_EQ(m_utils->formatThousandsSeparators("1234"), "1,234"); delete m_utils; } deepin-calculator-5.7.21/tests/src/ut_utils.h000066400000000000000000000003171423020056600211520ustar00rootroot00000000000000#ifndef UT_UTILS_H #define UT_UTILS_H #include #include #include class Ut_Utils : public ::testing::Test { public: Ut_Utils(); }; #endif // UT_UTILS_H deepin-calculator-5.7.21/tests/src/views/000077500000000000000000000000001423020056600202655ustar00rootroot00000000000000deepin-calculator-5.7.21/tests/src/views/ut_memoryitemdelegate.cpp000066400000000000000000000035311423020056600253650ustar00rootroot00000000000000#include "ut_memoryitemdelegate.h" #include "../../src/views/memorylistwidget.h" #include Ut_MemoryItemDelegate::Ut_MemoryItemDelegate() { } void Ut_MemoryItemDelegate::SetUp() { m_memoryItemDelegate = new MemoryItemDelegate; } void Ut_MemoryItemDelegate::TearDown() { delete m_memoryItemDelegate; } //bool stub_focus_memdelegateT() //{ // return true; //} bool stub_focus_memdelegateF() { return false; } TEST_F(Ut_MemoryItemDelegate, paint) { MemoryListWidget *listwidget = new MemoryListWidget; listwidget->setItemDelegate(m_memoryItemDelegate); QListWidgetItem *item = new QListWidgetItem(); item->setSizeHint(QSize(20, 20)); MemoryItemWidget *widget = new MemoryItemWidget(); widget->setFixedSize(QSize(20, 20)); listwidget->insertItem(0, item); listwidget->setItemWidget(item, widget); QPainter *painter = new QPainter(); QStyleOptionViewItem option; option.styleObject = listwidget; QModelIndex index; Stub stub; stub.set(ADDR(MemoryListWidget, hasFocus), stub_focus_memdelegateF); // Stub stub1; // stub1.set(ADDR(MemoryListWidget, rect), stub_rect_memdelegate); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_memoryItemDelegate->paint(painter, option, index); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_memoryItemDelegate->paint(painter, option, index); delete painter; //paint函数,无assert listwidget->deleteLater(); delete item; widget->deleteLater(); } TEST_F(Ut_MemoryItemDelegate, updateEditorGeometry) { QWidget *widget = new QWidget(); QStyleOptionViewItem item; m_memoryItemDelegate->updateEditorGeometry(widget, item, QModelIndex()); EXPECT_EQ(widget->geometry(), item.rect); widget->deleteLater(); } deepin-calculator-5.7.21/tests/src/views/ut_memoryitemdelegate.h000066400000000000000000000007231423020056600250320ustar00rootroot00000000000000#ifndef UT_MEMORYITEMDELEGATE_H #define UT_MEMORYITEMDELEGATE_H #include #include #include #include #include"../stub.h" #include "../../src/views/memoryitemdelegate.h" class Ut_MemoryItemDelegate : public ::testing::Test { public: Ut_MemoryItemDelegate(); MemoryItemDelegate *m_memoryItemDelegate; protected: void SetUp(); void TearDown(); }; #endif // UT_MEMORYITEMDELEGATE_H deepin-calculator-5.7.21/tests/src/views/ut_memoryitemwidget.cpp000066400000000000000000000141431423020056600250770ustar00rootroot00000000000000#include "ut_memoryitemwidget.h" #include "../../src/views/memoryitemwidget.h" #include "../../src/dsettings.h" #include "../../src/memorypublic.h" Ut_MemoryItemWidget::Ut_MemoryItemWidget() { } TEST_F(Ut_MemoryItemWidget, connects) { MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; m_memoryItemWidget->m_btnplus->clicked(); EXPECT_FALSE(m_memoryItemWidget->m_btnplus->m_isPress); m_memoryItemWidget->m_btnminus->clicked(); EXPECT_FALSE(m_memoryItemWidget->m_btnplus->m_isPress); m_memoryItemWidget->m_btnclean->clicked(); EXPECT_FALSE(m_memoryItemWidget->m_btnplus->m_isPress); delete m_memoryItemWidget; } TEST_F(Ut_MemoryItemWidget, enterEvent) { MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; QEvent *e = new QEvent(QEvent::Type::MouseMove); m_memoryItemWidget->enterEvent(e); EXPECT_TRUE(m_memoryItemWidget->m_ishover); EXPECT_FALSE(m_memoryItemWidget->m_btnplus->isHidden()); EXPECT_FALSE(m_memoryItemWidget->m_btnminus->isHidden()); EXPECT_FALSE(m_memoryItemWidget->m_btnclean->isHidden()); delete e; delete m_memoryItemWidget; } TEST_F(Ut_MemoryItemWidget, leaveEvent) { MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; QEvent *e = new QEvent(QEvent::Type::MouseMove); m_memoryItemWidget->leaveEvent(e); EXPECT_FALSE(m_memoryItemWidget->m_ishover); EXPECT_TRUE(m_memoryItemWidget->m_btnplus->isHidden()); EXPECT_TRUE(m_memoryItemWidget->m_btnminus->isHidden()); EXPECT_TRUE(m_memoryItemWidget->m_btnclean->isHidden()); delete e; delete m_memoryItemWidget; } TEST_F(Ut_MemoryItemWidget, mousePressEvent) { DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_memoryItemWidget->pos(), Qt::MouseButton::RightButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_memoryItemWidget->mousePressEvent(m); QMouseEvent *m1 = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_memoryItemWidget->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_memoryItemWidget->mousePressEvent(m1); EXPECT_TRUE(m_memoryItemWidget->m_ispress); delete m; delete m1; delete m_memoryItemWidget; } TEST_F(Ut_MemoryItemWidget, mouseReleaseEvent) { DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonRelease, m_memoryItemWidget->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_memoryItemWidget->mouseReleaseEvent(m); EXPECT_FALSE(m_memoryItemWidget->m_ispress); delete m; delete m_memoryItemWidget; } QAction *stub_exec(const QPoint &pos, QAction *at = nullptr) { Q_UNUSED(pos) Q_UNUSED(at) return nullptr; } TEST_F(Ut_MemoryItemWidget, contextMenuEvent) { MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; Stub stub; stub.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), stub_exec); m_memoryItemWidget->m_isExpressionEmpty = true; QContextMenuEvent *e = new QContextMenuEvent(QContextMenuEvent::Reason::Mouse, m_memoryItemWidget->pos(), m_memoryItemWidget->pos(), Qt::KeyboardModifier::NoModifier); m_memoryItemWidget->contextMenuEvent(e); EXPECT_FALSE(m_memoryItemWidget->m_ispress); delete e; delete m_memoryItemWidget; } TEST_F(Ut_MemoryItemWidget, showTextEditMenuByAltM) { MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; Stub stub; stub.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), stub_exec); // QContextMenuEvent *e = new QContextMenuEvent(QContextMenuEvent::Reason::Keyboard, m_memoryItemWidget->pos()); m_memoryItemWidget->m_isExpressionEmpty = true; m_memoryItemWidget->showTextEditMenuByAltM(); // stub.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), stub_exec); // m_memoryItemWidget->m_isExpressionEmpty = false; // m_memoryItemWidget->showTextEditMenuByAltM(); EXPECT_FALSE(m_memoryItemWidget->m_ispress); delete m_memoryItemWidget; } TEST_F(Ut_MemoryItemWidget, paintEvent) { MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; QPaintEvent *event = new QPaintEvent(m_memoryItemWidget->rect()); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::UnknownType); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_memoryItemWidget->m_ishover = true; m_memoryItemWidget->m_ispress = true; m_memoryItemWidget->paintEvent(event); m_memoryItemWidget->update(); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_memoryItemWidget->paintEvent(event); delete event; //paintevent无assert delete m_memoryItemWidget; } TEST_F(Ut_MemoryItemWidget, themetypechanged) { MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; m_memoryItemWidget->themetypechanged(1); EXPECT_EQ(m_memoryItemWidget->m_label->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text).name(), "#303030"); delete m_memoryItemWidget; } TEST_F(Ut_MemoryItemWidget, setNextItemHover) { MemoryItemWidget *m_memoryItemWidget = new MemoryItemWidget; m_memoryItemWidget->setNextItemHover(); EXPECT_TRUE(m_memoryItemWidget->m_ishover); EXPECT_FALSE(m_memoryItemWidget->m_btnplus->isHidden()); EXPECT_FALSE(m_memoryItemWidget->m_btnminus->isHidden()); EXPECT_FALSE(m_memoryItemWidget->m_btnclean->isHidden()); delete m_memoryItemWidget; } deepin-calculator-5.7.21/tests/src/views/ut_memoryitemwidget.h000066400000000000000000000004531423020056600245430ustar00rootroot00000000000000#ifndef UT_MEMORYITEMWIDGET_H #define UT_MEMORYITEMWIDGET_H #include #include #include #include #include"../stub.h" class Ut_MemoryItemWidget : public ::testing::Test { public: Ut_MemoryItemWidget(); }; #endif // UT_MEMORYITEMWIDGET_H deepin-calculator-5.7.21/tests/src/views/ut_memorylistwidget.cpp000066400000000000000000000042331423020056600251130ustar00rootroot00000000000000#include "ut_memorylistwidget.h" #include "../../src/views/memorylistwidget.h" #include "../../src/dsettings.h" #include "../../src/memorypublic.h" Ut_MemoryListWidget::Ut_MemoryListWidget() { } TEST_F(Ut_MemoryListWidget, mousePressEvent) { MemoryListWidget *m_memoryListWidget = new MemoryListWidget; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_memoryListWidget->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier); m_memoryListWidget->mousePressEvent(m); EXPECT_EQ(m_memoryListWidget->m_mousemovepoint, m->globalPos()); EXPECT_EQ(m_memoryListWidget->m_mousepoint, m->pos()); EXPECT_EQ(m_memoryListWidget->m_clickrow, -1); delete m; delete m_memoryListWidget; } TEST_F(Ut_MemoryListWidget, keyPressEvent) { MemoryListWidget *m_memoryListWidget = new MemoryListWidget; QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); QKeyEvent *k2 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); QKeyEvent *k3 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier); QKeyEvent *k4 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier); QKeyEvent *k5 = new QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier); m_memoryListWidget->keyPressEvent(k); m_memoryListWidget->keyPressEvent(k1); m_memoryListWidget->keyPressEvent(k2); m_memoryListWidget->keyPressEvent(k3); m_memoryListWidget->keyPressEvent(k4); m_memoryListWidget->keyPressEvent(k5); delete k; delete k1; delete k2; delete k3; delete k4; delete k5; //焦点设置函数,无assert delete m_memoryListWidget; } TEST_F(Ut_MemoryListWidget, focusInEvent) { MemoryListWidget *m_memoryListWidget = new MemoryListWidget; QFocusEvent *f = new QFocusEvent(QEvent::Type::FocusIn, Qt::OtherFocusReason); m_memoryListWidget->focusInEvent(f); EXPECT_EQ(m_memoryListWidget->currentRow(), -1); delete f; delete m_memoryListWidget; } deepin-calculator-5.7.21/tests/src/views/ut_memorylistwidget.h000066400000000000000000000004061423020056600245560ustar00rootroot00000000000000#ifndef UT_MEMORYLISTWIDGET_H #define UT_MEMORYLISTWIDGET_H #include #include #include class Ut_MemoryListWidget : public ::testing::Test { public: Ut_MemoryListWidget(); }; #endif // UT_MEMORYLISTWIDGET_H deepin-calculator-5.7.21/tests/src/views/ut_memorywidget.cpp000066400000000000000000000301661423020056600242230ustar00rootroot00000000000000#include "ut_memorywidget.h" #include "../../src/views/memorywidget.h" #include "../../src/memorypublic.h" #include Ut_MemoryWidget::Ut_MemoryWidget() { } TEST_F(Ut_MemoryWidget, space) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); // MemoryWidget *m_memoryWidget = new MemoryWidget; QListWidgetItem *item1 = new QListWidgetItem; item1->setFlags(Qt::ItemIsEditable); MemoryItemWidget *widget = new MemoryItemWidget; m_memoryWidget->m_listwidget->insertItem(0, item1); m_memoryWidget->m_listwidget->setItemWidget(item1, widget); widget->setTextLabel("1"); m_memoryWidget->m_listwidget->setCurrentRow(0); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier); m_memoryWidget->m_listwidget->keyPressEvent(k); m_memoryWidget->m_clearbutton->clicked(); m_memoryWidget->m_clearbutton->space(); m_memoryWidget->m_listwidget->itemselected(0, false); m_memoryWidget->m_listwidget->focus(0); m_memoryWidget->m_listwidget->focus(1); EXPECT_TRUE(m_memoryPublic->isEmpty()); delete k; } TEST_F(Ut_MemoryWidget, focus) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); m_memoryPublic->generateData(Quantity(2)); m_memoryPublic->generateData(Quantity(3)); m_memoryWidget->setFocus(); m_memoryWidget->m_listwidget->setCurrentRow(1); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); QKeyEvent *k2 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); m_memoryWidget->m_listwidget->keyPressEvent(k); m_memoryWidget->m_listwidget->keyPressEvent(k1); m_memoryWidget->m_listwidget->keyPressEvent(k2); EXPECT_EQ(m_memoryWidget->m_listwidget->currentRow(), 1); delete k; delete k1; delete k2; } TEST_F(Ut_MemoryWidget, generateData) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); QTest::mouseClick(static_cast(m_memoryWidget->m_listwidget->itemWidget(m_memoryWidget->m_listwidget->item(0)))->m_btnclean, Qt::LeftButton); for (int i = 0; i < 500; i++) m_memoryPublic->generateData(Quantity(1)); EXPECT_EQ(m_memoryWidget->m_listwidget->count(), 500); m_memoryPublic->generateData(Quantity(2)); EXPECT_EQ(m_memoryPublic->getList().at(0), Quantity(2)); m_memoryWidget->m_listwidget->setCurrentRow(1); QTest::mouseClick(static_cast(m_memoryWidget->m_listwidget->itemWidget(m_memoryWidget->m_listwidget->item(0)))->m_btnplus, Qt::LeftButton); QTest::mouseClick(static_cast(m_memoryWidget->m_listwidget->itemWidget(m_memoryWidget->m_listwidget->item(0)))->m_btnminus, Qt::LeftButton); static_cast(m_memoryWidget->m_listwidget->itemWidget(m_memoryWidget->m_listwidget->item(0)))->menucopy(); static_cast(m_memoryWidget->m_listwidget->itemWidget(m_memoryWidget->m_listwidget->item(0)))->menuplus(); static_cast(m_memoryWidget->m_listwidget->itemWidget(m_memoryWidget->m_listwidget->item(0)))->menuclean(); static_cast(m_memoryWidget->m_listwidget->itemWidget(m_memoryWidget->m_listwidget->item(0)))->menuminus(); EXPECT_EQ(m_memoryWidget->m_listwidget->count(), 499); } TEST_F(Ut_MemoryWidget, mousePressEvent) { MemoryWidget *m_memoryWidget = new MemoryWidget; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_memoryWidget->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier); m_memoryWidget->mousePressEvent(m); EXPECT_EQ(m_memoryWidget->m_mousepoint, m_memoryWidget->pos()); delete m; } TEST_F(Ut_MemoryWidget, eventFilter) { MemoryWidget *m_memoryWidget = new MemoryWidget; m_memoryWidget->m_calculatormode = 0; QKeyEvent *k = new QKeyEvent(QKeyEvent::Type::KeyPress, Qt::Key_Tab, Qt::KeyboardModifier::NoModifier); m_memoryWidget->eventFilter(m_memoryWidget->m_listwidget, static_cast (k)); delete k; //焦点设置函数,无assert } TEST_F(Ut_MemoryWidget, focusInEvent) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->memoryclean(); m_memoryPublic->generateData(Quantity(1)); QFocusEvent *f = new QFocusEvent(QFocusEvent::Type::FocusIn, Qt::TabFocusReason); m_memoryWidget->m_currentrow = 0; m_memoryWidget->focusInEvent(f); delete f; EXPECT_EQ(m_memoryWidget->m_listwidget->currentRow(), 0); } TEST_F(Ut_MemoryWidget, memoryAnsChanged) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); m_memoryWidget->memoryAnsChanged(0, Quantity(2)); EXPECT_EQ(static_cast(m_memoryWidget->m_listwidget->itemWidget(m_memoryWidget->m_listwidget->item(0)))->textLabel(), "2"); } TEST_F(Ut_MemoryWidget, memoryclean) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); m_memoryWidget->memoryclean(); EXPECT_FALSE(m_memoryWidget->m_label->isHidden()); EXPECT_TRUE(m_memoryWidget->m_clearbutton->isHidden()); EXPECT_EQ(m_memoryWidget->m_listwidget->count(), 1); } TEST_F(Ut_MemoryWidget, emptymemoryfontcolor) { MemoryWidget *m_memoryWidget = new MemoryWidget; m_memoryWidget->m_themetype = 1; m_memoryWidget->emptymemoryfontcolor(); QColor color(85, 85, 85); color.setAlphaF(0.4); EXPECT_EQ(m_memoryWidget->m_label->palette().color(DPalette::WindowText), color); m_memoryWidget->m_themetype = 2; m_memoryWidget->emptymemoryfontcolor(); QColor color1(192, 198, 212); color1.setAlphaF(0.4); EXPECT_EQ(m_memoryWidget->m_label->palette().color(DPalette::WindowText), color1); } TEST_F(Ut_MemoryWidget, getfirstnumber) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); EXPECT_EQ(m_memoryWidget->getfirstnumber().first, "1"); EXPECT_EQ(m_memoryWidget->getfirstnumber().second, Quantity(1)); } TEST_F(Ut_MemoryWidget, getMemoryWidget) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); EXPECT_EQ(static_cast(m_memoryWidget->getMemoryWidget()->itemWidget(m_memoryWidget->m_listwidget->item(0)))->textLabel(), "1"); } TEST_F(Ut_MemoryWidget, programmerResult) { MemoryWidget *m_memoryWidget = new MemoryWidget; HNumber number("1.5"); EXPECT_EQ(m_memoryWidget->programmerResult(Quantity(number)), "1"); } TEST_F(Ut_MemoryWidget, resetAllLabelByBase) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); HNumber number("1.7"); m_memoryPublic->memoryclean(); m_memoryPublic->generateData(Quantity(number)); m_memoryWidget->m_calculatormode = 2; m_memoryWidget->resetAllLabelByBase(); EXPECT_EQ(static_cast(m_memoryWidget->getMemoryWidget()->itemWidget(m_memoryWidget->m_listwidget->item(0)))->textLabel(), "1"); } TEST_F(Ut_MemoryWidget, expressionempty) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); m_memoryWidget->expressionempty(false); EXPECT_FALSE(static_cast(m_memoryWidget->getMemoryWidget()->itemWidget(m_memoryWidget->m_listwidget->item(0)))->m_isExpressionEmpty); EXPECT_TRUE(static_cast(m_memoryWidget->getMemoryWidget()->itemWidget(m_memoryWidget->m_listwidget->item(0)))->m_btnplus->isEnabled()); EXPECT_TRUE(static_cast(m_memoryWidget->getMemoryWidget()->itemWidget(m_memoryWidget->m_listwidget->item(0)))->m_btnminus->isEnabled()); } TEST_F(Ut_MemoryWidget, widgetcleanslot) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::standardleft); m_memoryWidget->memoryclean(); m_memoryPublic->generateData(Quantity(1)); m_memoryWidget->widgetcleanslot(0, 1, false); EXPECT_EQ(m_memoryWidget->m_listwidget->count(), 1); m_memoryWidget->generateData(Quantity(1), false); m_memoryWidget->generateData(Quantity(1), false); EXPECT_EQ(m_memoryWidget->m_listwidget->count(), 3); m_memoryWidget->widgetcleanslot(0, 1, false); EXPECT_EQ(m_memoryWidget->m_listwidget->count(), 2); } TEST_F(Ut_MemoryWidget, formatExpression) { MemoryWidget *m_memoryWidget = new MemoryWidget; EXPECT_EQ(m_memoryWidget->formatExpression("123+2321"), "123+2321"); } TEST_F(Ut_MemoryWidget, setitemwordwrap) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); m_memoryWidget->m_calculatormode = 2; m_memoryWidget->setitemwordwrap("12345678901234", 0); EXPECT_EQ(m_memoryWidget->m_line, 1); m_memoryWidget->setitemwordwrap("1111 1111 1111 1111 1111 1111 1111 1111 1111", 0); EXPECT_EQ(m_memoryWidget->m_line, 2); m_memoryWidget->m_calculatormode = 0; m_memoryWidget->setitemwordwrap("12345678901234E", 0); EXPECT_EQ(m_memoryWidget->m_line, 2); m_memoryWidget->setitemwordwrap("1234567890123456789012", 0); EXPECT_EQ(m_memoryWidget->m_line, 2); m_memoryWidget->m_calculatormode = 1; m_memoryWidget->setitemwordwrap("123456789012345678901E", 0); EXPECT_EQ(m_memoryWidget->m_line, 2); m_memoryWidget->setitemwordwrap("1234567890123456789012", 0); EXPECT_EQ(m_memoryWidget->m_line, 2); } TEST_F(Ut_MemoryWidget, setThemeType) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryPublic->generateData(Quantity(1)); m_memoryWidget->setThemeType(2); EXPECT_EQ(m_memoryWidget->m_themetype, 2); EXPECT_EQ(m_memoryWidget->m_clearbutton->m_currentUrl, ":/assets/images/dark/empty_normal.svg"); m_memoryWidget->setThemeType(1); EXPECT_EQ(m_memoryWidget->m_themetype, 1); EXPECT_EQ(m_memoryWidget->m_clearbutton->m_currentUrl, ":/assets/images/light/empty_normal.svg"); } TEST_F(Ut_MemoryWidget, keyPressEvent) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier); m_memoryWidget->keyPressEvent(k); delete k; EXPECT_FALSE(m_memoryWidget->isHidden()); } TEST_F(Ut_MemoryWidget, resetItemHeight) { MemoryPublic *m_memoryPublic = MemoryPublic::instance(); MemoryWidget *m_memoryWidget = m_memoryPublic->getwidget(MemoryPublic::memorymode::scientificright); m_memoryWidget->m_calculatormode = 1; m_memoryPublic->generateData(Quantity(1)); m_memoryWidget->resetItemHeight(); int line = static_cast(m_memoryWidget->m_listwidget->itemWidget(m_memoryWidget->m_listwidget->item(0)))->getLine(); EXPECT_EQ(line, 1); } deepin-calculator-5.7.21/tests/src/views/ut_memorywidget.h000066400000000000000000000003621423020056600236630ustar00rootroot00000000000000#ifndef UT_MEMORYWIDGET_H #define UT_MEMORYWIDGET_H #include #include #include class Ut_MemoryWidget : public ::testing::Test { public: Ut_MemoryWidget(); }; #endif // UT_MEMORYWIDGET_H deepin-calculator-5.7.21/tests/src/views/ut_programmerarrowdelegate.cpp000066400000000000000000000037201423020056600264240ustar00rootroot00000000000000#include "ut_programmerarrowdelegate.h" #include "../../src/views/programmeritemwidget.h" #include "../../src/views/memorylistwidget.h" #include Ut_ProgrammerArrowDelegate::Ut_ProgrammerArrowDelegate() { } void Ut_ProgrammerArrowDelegate::SetUp() { m_memoryItemDelegate = new ProgrammerArrowDelegate; } void Ut_ProgrammerArrowDelegate::TearDown() { delete m_memoryItemDelegate; } //bool stub_focus_proarrowdelegateT() //{ // return true; //} bool stub_focus_proarrowdelegateF() { return false; } TEST_F(Ut_ProgrammerArrowDelegate, paint) { MemoryListWidget *listwidget = new MemoryListWidget; listwidget->setItemDelegate(m_memoryItemDelegate); QListWidgetItem *item = new QListWidgetItem(); item->setSizeHint(QSize(20, 20)); ProgrammerItemWidget *widget = new ProgrammerItemWidget("WORD"); widget->setFixedSize(QSize(20, 20)); listwidget->insertItem(0, item); listwidget->setItemWidget(item, widget); QPainter *painter = new QPainter(); QStyleOptionViewItem option; option.styleObject = listwidget; QModelIndex index; Stub stub; stub.set(ADDR(MemoryListWidget, hasFocus), stub_focus_proarrowdelegateF); // Stub stub1; // stub1.set(ADDR(MemoryListWidget, rect), stub_rect_memdelegate); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_memoryItemDelegate->paint(painter, option, index); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_memoryItemDelegate->paint(painter, option, index); delete painter; //paint函数,无assert listwidget->deleteLater(); delete item; widget->deleteLater(); } TEST_F(Ut_ProgrammerArrowDelegate, updateEditorGeometry) { QWidget *widget = new QWidget(); QStyleOptionViewItem item; m_memoryItemDelegate->updateEditorGeometry(widget, item, QModelIndex()); EXPECT_EQ(widget->geometry(), item.rect); widget->deleteLater(); } deepin-calculator-5.7.21/tests/src/views/ut_programmerarrowdelegate.h000066400000000000000000000007671423020056600261010ustar00rootroot00000000000000#ifndef UT_PROGRAMMERARROWDELEGATE_H #define UT_PROGRAMMERARROWDELEGATE_H #include #include #include #include #include"../stub.h" #include "../../src/views/programmerarrowdelegate.h" class Ut_ProgrammerArrowDelegate : public ::testing::Test { public: Ut_ProgrammerArrowDelegate(); ProgrammerArrowDelegate *m_memoryItemDelegate; protected: void SetUp(); void TearDown(); }; #endif // UT_PROGRAMMERARROWDELEGATE_H deepin-calculator-5.7.21/tests/src/views/ut_programmeritemwidget.cpp000066400000000000000000000205101423020056600257350ustar00rootroot00000000000000#include "ut_programmeritemwidget.h" #include "../../src/views/programmeritemwidget.h" #include "../../src/dsettings.h" #include "../../src/memorypublic.h" Ut_ProgrammerItemWidget::Ut_ProgrammerItemWidget() { } TEST_F(Ut_ProgrammerItemWidget, enterEvent) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); QEvent *e = new QEvent(QEvent::Type::MouseMove); m_programmerItemWidget->enterEvent(e); EXPECT_TRUE(m_programmerItemWidget->m_ishover); delete e; delete m_programmerItemWidget; } TEST_F(Ut_ProgrammerItemWidget, leaveEvent) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); QEvent *e = new QEvent(QEvent::Type::MouseMove); m_programmerItemWidget->leaveEvent(e); EXPECT_FALSE(m_programmerItemWidget->m_ishover); delete e; delete m_programmerItemWidget; } TEST_F(Ut_ProgrammerItemWidget, mousePressEvent) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_programmerItemWidget->pos(), Qt::MouseButton::RightButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_programmerItemWidget->mousePressEvent(m); EXPECT_FALSE(m_programmerItemWidget->m_ispress); QMouseEvent *m1 = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_programmerItemWidget->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_programmerItemWidget->mousePressEvent(m1); EXPECT_TRUE(m_programmerItemWidget->m_ispress); delete m; delete m1; delete m_programmerItemWidget; } TEST_F(Ut_ProgrammerItemWidget, mouseReleaseEvent) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); m_programmerItemWidget->m_ispress = true; QMouseEvent *e = new QMouseEvent(QMouseEvent::Type::MouseButtonRelease, m_programmerItemWidget->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_programmerItemWidget->mouseReleaseEvent(e); EXPECT_TRUE(m_programmerItemWidget->m_ishover); EXPECT_FALSE(m_programmerItemWidget->m_ispress); delete e; delete m_programmerItemWidget; } TEST_F(Ut_ProgrammerItemWidget, cleanHoverState) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); m_programmerItemWidget->cleanHoverState(); EXPECT_FALSE(m_programmerItemWidget->m_ishover); delete m_programmerItemWidget; } TEST_F(Ut_ProgrammerItemWidget, cleanFocusState) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); m_programmerItemWidget->cleanFocusState(); EXPECT_FALSE(m_programmerItemWidget->m_isfocus); delete m_programmerItemWidget; } TEST_F(Ut_ProgrammerItemWidget, isMarkHide) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); m_programmerItemWidget->isMarkHide(true); EXPECT_TRUE(m_programmerItemWidget->m_isMarkHide); delete m_programmerItemWidget; } TEST_F(Ut_ProgrammerItemWidget, initMark) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); m_programmerItemWidget->initMark(); EXPECT_EQ(m_programmerItemWidget->m_pointVec.at(1), m_programmerItemWidget->m_markmid); delete m_programmerItemWidget; } TEST_F(Ut_ProgrammerItemWidget, themetypechanged) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_programmerItemWidget->themetypechanged(2); EXPECT_EQ(m_programmerItemWidget->m_label->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text).name(), "#ffffff"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_programmerItemWidget->themetypechanged(1); EXPECT_EQ(m_programmerItemWidget->m_label->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text).name(), "#000000"); ProgrammerItemWidget *m_programmerItemWidget1 = new ProgrammerItemWidget("Circular shift", 50, ":/assets/images/dark/icon_as_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_programmerItemWidget1->themetypechanged(2); EXPECT_EQ(m_programmerItemWidget1->m_normalUrl, ":/assets/images/dark/icon_ro_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_programmerItemWidget1->themetypechanged(1); EXPECT_EQ(m_programmerItemWidget1->m_normalUrl, ":/assets/images/light/icon_ro_normal.svg"); ProgrammerItemWidget *m_programmerItemWidget2 = new ProgrammerItemWidget("Arithmetic shift", 50, ":/assets/images/dark/icon_as_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_programmerItemWidget2->themetypechanged(2); EXPECT_EQ(m_programmerItemWidget2->m_normalUrl, ":/assets/images/dark/icon_as_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_programmerItemWidget2->themetypechanged(1); EXPECT_EQ(m_programmerItemWidget2->m_normalUrl, ":/assets/images/light/icon_as_normal.svg"); ProgrammerItemWidget *m_programmerItemWidget3 = new ProgrammerItemWidget("Logical shift", 50, ":/assets/images/dark/icon_as_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_programmerItemWidget3->themetypechanged(2); EXPECT_EQ(m_programmerItemWidget3->m_normalUrl, ":/assets/images/dark/icon_ls_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_programmerItemWidget3->themetypechanged(1); EXPECT_EQ(m_programmerItemWidget3->m_normalUrl, ":/assets/images/light/icon_ls_normal.svg"); ProgrammerItemWidget *m_programmerItemWidget4 = new ProgrammerItemWidget("Rotate through carry circular shift", 50, ":/assets/images/dark/icon_as_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_programmerItemWidget4->themetypechanged(2); EXPECT_EQ(m_programmerItemWidget4->m_normalUrl, ":/assets/images/dark/icon_rc_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_programmerItemWidget4->themetypechanged(1); EXPECT_EQ(m_programmerItemWidget4->m_normalUrl, ":/assets/images/light/icon_rc_normal.svg"); delete m_programmerItemWidget; delete m_programmerItemWidget1; delete m_programmerItemWidget2; delete m_programmerItemWidget3; delete m_programmerItemWidget4; } TEST_F(Ut_ProgrammerItemWidget, setFocus) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); m_programmerItemWidget->setFocus(); EXPECT_TRUE(m_programmerItemWidget->m_isfocus); delete m_programmerItemWidget; } TEST_F(Ut_ProgrammerItemWidget, paintEvent) { ProgrammerItemWidget *m_programmerItemWidget = new ProgrammerItemWidget("WORD"); QPaintEvent *event = new QPaintEvent(m_programmerItemWidget->rect()); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::UnknownType); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::LightType); m_programmerItemWidget->m_ispress = true; m_programmerItemWidget->m_ishover = false; m_programmerItemWidget->paintEvent(event); m_programmerItemWidget->update(); ProgrammerItemWidget *m_programmerItemWidget1 = new ProgrammerItemWidget("Circular shift", 50, ":/assets/images/dark/icon_as_normal.svg"); DGuiApplicationHelper::instance()->setThemeType(DGuiApplicationHelper::ColorType::DarkType); m_programmerItemWidget1->m_isMarkHide = false; m_programmerItemWidget1->m_isshift = true; m_programmerItemWidget1->m_ispress = false; m_programmerItemWidget1->m_ishover = true; m_programmerItemWidget1->paintEvent(event); m_programmerItemWidget1->update(); delete event; //paintevent,无assert delete m_programmerItemWidget; } deepin-calculator-5.7.21/tests/src/views/ut_programmeritemwidget.h000066400000000000000000000004601423020056600254040ustar00rootroot00000000000000#ifndef UT_PROGRAMMERITEMWIDGET_H #define UT_PROGRAMMERITEMWIDGET_H #include #include #include #include "../stub.h" class Ut_ProgrammerItemWidget : public ::testing::Test { public: Ut_ProgrammerItemWidget(); }; #endif // UT_PROGRAMMERITEMWIDGET_H deepin-calculator-5.7.21/tests/src/views/ut_prolistdelegate.cpp000066400000000000000000000051731423020056600246760ustar00rootroot00000000000000#include "ut_prolistdelegate.h" Ut_ProListDelegate::Ut_ProListDelegate() { } void Ut_ProListDelegate::SetUp() { m_prolistview1 = new ProListView(); m_model1 = new ProListModel(); m_proListDelegate1 = new ProListDelegate(); m_proListDelegate = new ProListDelegate(); m_model = new ProListModel(); } void Ut_ProListDelegate::TearDown() { m_prolistview1->deleteLater(); delete m_model1; m_model1 = nullptr; delete m_proListDelegate; m_proListDelegate = nullptr; delete m_proListDelegate1; m_proListDelegate1 = nullptr; delete m_model; m_model = nullptr; } TEST_F(Ut_ProListDelegate, setThemeType) { m_proListDelegate->setThemeType(1); EXPECT_EQ(m_proListDelegate->m_themeType, 1); } TEST_F(Ut_ProListDelegate, currentfocusindex) { m_proListDelegate->currentfocusindex(QModelIndex()); EXPECT_EQ(m_proListDelegate->m_focusindex, QModelIndex()); } TEST_F(Ut_ProListDelegate, sizeHint) { m_proListDelegate->sizeHint(QStyleOptionViewItem(), m_model->index(0, 0)); EXPECT_EQ(m_proListDelegate->sizeHint(QStyleOptionViewItem(), m_model->index(3, 0)), QSize(451, 28)); } TEST_F(Ut_ProListDelegate, editorEvent) { QStyleOptionViewItem item; QEvent *e = new QEvent(QEvent::Type::None); EXPECT_TRUE(m_proListDelegate->editorEvent(e, m_model, item, m_model->index(0, 0))); delete e; } //bool stub_focus_prolistdelegateT() //{ // return true; //} bool stub_focus_prolistdelegateF() { return false; } QModelIndex stub_index_prolistdelegate1() { ProListModel m_model; return m_model.index(0, 0, QModelIndex()); } QModelIndex stub_index_prolistdelegate3() { ProListModel m_model; return m_model.index(3, 0, QModelIndex()); } TEST_F(Ut_ProListDelegate, paintnofocus) { m_prolistview1->setModel(m_model1); m_prolistview1->setItemDelegate(m_proListDelegate1); QPainter *painter = new QPainter(); Stub stub; stub.set(ADDR(ProListView, hasFocus), stub_focus_prolistdelegateF); QStyleOptionViewItem option; option.init(m_prolistview1); Stub stub1; stub1.set(ADDR(ProListView, currentIndex), stub_index_prolistdelegate3); m_proListDelegate1->m_themeType = 0; m_prolistview1->setCurrentIndex(m_model1->index(3, 0, QModelIndex())); m_proListDelegate1->paint(painter, option, m_model1->index(3, 0, QModelIndex())); Stub stub2; stub2.set(ADDR(ProListView, currentIndex), stub_index_prolistdelegate1); m_proListDelegate1->m_themeType = 1; m_prolistview1->setCurrentIndex(m_model1->index(0, 0, QModelIndex())); m_proListDelegate1->paint(painter, option, m_model1->index(0, 0, QModelIndex())); delete painter; } deepin-calculator-5.7.21/tests/src/views/ut_prolistdelegate.h000066400000000000000000000012061423020056600243340ustar00rootroot00000000000000#ifndef UT_PROLISTDELEGATE_H #define UT_PROLISTDELEGATE_H #include #include #include #include #include "../../src/views/prolistdelegate.h" #include "../../src/views/prolistmodel.h" #include "../../src/views/prolistview.h" #include"../stub.h" class Ut_ProListDelegate : public ::testing::Test { public: Ut_ProListDelegate(); ProListView *m_prolistview1; ProListModel *m_model1; ProListDelegate *m_proListDelegate1; ProListDelegate *m_proListDelegate; ProListModel *m_model; protected: void SetUp(); void TearDown(); }; #endif // UT_PROLISTDELEGATE_H deepin-calculator-5.7.21/tests/src/views/ut_prolistmodel.cpp000066400000000000000000000021301423020056600242120ustar00rootroot00000000000000#include "ut_prolistmodel.h" #include "../../3rdparty/math/quantity.h" Ut_ProListModel::Ut_ProListModel() { } void Ut_ProListModel::SetUp() { m_proListModel = new ProListModel(); } void Ut_ProListModel::TearDown() { delete m_proListModel; } TEST_F(Ut_ProListModel, data) { m_proListModel->updataList(Quantity(3)); m_proListModel->data(m_proListModel->index(1, 0), ProListModel::Role::ExpressionCount); m_proListModel->data(m_proListModel->index(1, 0), ProListModel::Role::ExpressionPrevious); EXPECT_EQ(m_proListModel->data(m_proListModel->index(1, 0), ProListModel::Role::ExpressionNext), "3"); } TEST_F(Ut_ProListModel, clearItems) { m_proListModel->clearItems(); EXPECT_EQ(m_proListModel->m_expressionList.at(3), ""); } TEST_F(Ut_ProListModel, updataList) { m_proListModel->updataList(Quantity(11)); EXPECT_TRUE(m_proListModel->m_expressionList.at(0) == "B"); EXPECT_TRUE(m_proListModel->m_expressionList.at(1) == "11"); EXPECT_TRUE(m_proListModel->m_expressionList.at(2) == "13"); EXPECT_TRUE(m_proListModel->m_expressionList.at(3) == "1011"); } deepin-calculator-5.7.21/tests/src/views/ut_prolistmodel.h000066400000000000000000000006231423020056600236640ustar00rootroot00000000000000#ifndef UT_PROLISTMODEL_H #define UT_PROLISTMODEL_H #include #include #include #include "../../src/dsettings.h" #include "../../src/views/prolistmodel.h" class Ut_ProListModel : public ::testing::Test { public: Ut_ProListModel(); ProListModel *m_proListModel; protected: void SetUp(); void TearDown(); }; #endif // UT_PROLISTMODEL_H deepin-calculator-5.7.21/tests/src/views/ut_prolistview.cpp000066400000000000000000000054261423020056600240770ustar00rootroot00000000000000#include "ut_prolistview.h" #include "../../src/views/prolistview.h" Ut_ProListView::Ut_ProListView() { } TEST_F(Ut_ProListView, keyPressEvent) { ProListView *m_proListView = new ProListView(); ProListModel *m_proListModel = new ProListModel(); ProListDelegate *m_prolistdegate = new ProListDelegate(); m_proListView->setModel(m_proListModel); m_proListView->setItemDelegate(m_prolistdegate); m_proListModel->updataList(Quantity(5)); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); QKeyEvent *k2 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier); m_proListView->keyPressEvent(k); m_proListView->keyPressEvent(k1); m_proListView->keyPressEvent(k2); delete k; delete k1; delete k2; //设置焦点函数,无assert delete m_proListView; delete m_proListModel; delete m_prolistdegate; } TEST_F(Ut_ProListView, focusIndex) { ProListView *m_proListView = new ProListView(); ProListModel *m_proListModel = new ProListModel(); ProListDelegate *m_prolistdegate = new ProListDelegate(); m_proListView->setModel(m_proListModel); m_proListView->setItemDelegate(m_prolistdegate); m_proListModel->updataList(Quantity(5)); m_proListView->focusIndex(); EXPECT_EQ(m_proListView->focusIndex(), m_proListView->model()->index(m_proListView->m_focusrow, 0)); delete m_proListView; delete m_proListModel; delete m_prolistdegate; } QAction *stub_exec_pro(const QPoint &pos, QAction *at = nullptr) { Q_UNUSED(pos) Q_UNUSED(at) return nullptr; } TEST_F(Ut_ProListView, contextMenuEvent) { ProListView *m_proListView = new ProListView; Stub stub; stub.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), stub_exec_pro); // QContextMenuEvent *e = new QContextMenuEvent(QContextMenuEvent::Reason::Mouse, m_proListView->pos()); QContextMenuEvent *e = new QContextMenuEvent(QContextMenuEvent::Reason::Mouse, m_proListView->pos(), m_proListView->pos(), Qt::KeyboardModifier::NoModifier); m_proListView->contextMenuEvent(e); EXPECT_EQ(e->pos(), m_proListView->pos()); delete e; delete m_proListView; } TEST_F(Ut_ProListView, showTextEditMenuByAltM) { ProListView *m_proListView = new ProListView; Stub stub; stub.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), stub_exec_pro); // QContextMenuEvent *e = new QContextMenuEvent(QContextMenuEvent::Reason::Mouse, m_proListView->pos()); m_proListView->showTextEditMenuByAltM(QModelIndex()); EXPECT_TRUE(m_proListView->m_isMenuAltM); delete m_proListView; } deepin-calculator-5.7.21/tests/src/views/ut_prolistview.h000066400000000000000000000004641423020056600235410ustar00rootroot00000000000000#ifndef UT_PROLISTVIEW_H #define UT_PROLISTVIEW_H #include #include #include #include #include"../stub.h" #include "../../src/dsettings.h" class Ut_ProListView : public ::testing::Test { public: Ut_ProListView(); }; #endif // UT_PROLISTVIEW_H deepin-calculator-5.7.21/tests/src/views/ut_simplelistdelegate.cpp000066400000000000000000000164351423020056600253720ustar00rootroot00000000000000#include "ut_simplelistdelegate.h" #include "../../src/views/simplelistview.h" #include Ut_SimpleListDelegate::Ut_SimpleListDelegate() { } void Ut_SimpleListDelegate::SetUp() { m_simpleListDelegate = new SimpleListDelegate(0); model = new SimpleListModel(0); } void Ut_SimpleListDelegate::TearDown() { delete m_simpleListDelegate; delete model; } TEST_F(Ut_SimpleListDelegate, setHisLink) { m_simpleListDelegate->setHisLink(0); EXPECT_EQ(m_simpleListDelegate->m_linkItem.count(), 1); } TEST_F(Ut_SimpleListDelegate, setHisLinked) { m_simpleListDelegate->setHisLinked(0); EXPECT_EQ(m_simpleListDelegate->m_linkedIten.count(), 1); } TEST_F(Ut_SimpleListDelegate, removeLine2) { m_simpleListDelegate->setHisLink(0); m_simpleListDelegate->setHisLinked(0); m_simpleListDelegate->removeLine(0, 0); EXPECT_EQ(m_simpleListDelegate->m_linkedIten.count(), 0); } TEST_F(Ut_SimpleListDelegate, removeLine1) { m_simpleListDelegate->setHisLink(0); m_simpleListDelegate->setHisLinked(0); m_simpleListDelegate->setHisLink(1); m_simpleListDelegate->setHisLinked(1); m_simpleListDelegate->removeLine(0, 0); EXPECT_EQ(m_simpleListDelegate->m_linkedIten.count(), 1); } TEST_F(Ut_SimpleListDelegate, removeHisLink) { m_simpleListDelegate->setHisLink(0); m_simpleListDelegate->setHisLink(1); m_simpleListDelegate->removeHisLink(); EXPECT_EQ(m_simpleListDelegate->m_linkItem.count(), 1); } TEST_F(Ut_SimpleListDelegate, removeAllLink) { m_simpleListDelegate->setHisLink(0); m_simpleListDelegate->setHisLinked(0); m_simpleListDelegate->setHisLink(1); m_simpleListDelegate->setHisLinked(1); m_simpleListDelegate->removeAllLink(); EXPECT_EQ(m_simpleListDelegate->m_linkedIten.count(), 0); } TEST_F(Ut_SimpleListDelegate, removeHisLinked) { m_simpleListDelegate->setHisLinked(0); m_simpleListDelegate->setHisLinked(1); m_simpleListDelegate->removeHisLinked(); EXPECT_EQ(m_simpleListDelegate->m_linkedIten.count(), 1); } TEST_F(Ut_SimpleListDelegate, setThemeType) { m_simpleListDelegate->setThemeType(1); EXPECT_EQ(m_simpleListDelegate->m_type, 1); } TEST_F(Ut_SimpleListDelegate, paintback) { m_simpleListDelegate->paintback(QModelIndex(), 1); EXPECT_EQ(m_simpleListDelegate->m_state, 1); } TEST_F(Ut_SimpleListDelegate, sizeHint) { m_simpleListDelegate->m_mode = 0; m_simpleListDelegate->sizeHint(QStyleOptionViewItem(), QModelIndex()); m_simpleListDelegate->m_mode = 1; m_simpleListDelegate->sizeHint(QStyleOptionViewItem(), model->index(0, 0)); model->appendText("1+1=2", true); EXPECT_EQ(m_simpleListDelegate->sizeHint(QStyleOptionViewItem(), model->index(0, 0)).width(), 451); } //TEST_F(Ut_SimpleListDelegate, editorEvent) //{ // SimpleListDelegate *m_simpleListDelegate = new SimpleListDelegate(0); // m_simpleListDelegate->m_mode = 0; // SimpleListModel *model = new SimpleListModel(); // QStyleOptionViewItem item; // ASSERT_TRUE(m_simpleListDelegate->editorEvent(new QEvent(QEvent::Type::None), model, item, model->index(0, 0))); //} TEST_F(Ut_SimpleListDelegate, cutApart) { QString linkNum = QString(); QString expStr = QString(); m_simpleListDelegate->cutApart("", linkNum, expStr); m_simpleListDelegate->cutApart("(-1)+1=0", linkNum, expStr); m_simpleListDelegate->cutApart("-(1)+1=0", linkNum, expStr); m_simpleListDelegate->cutApart("1E0+1=0", linkNum, expStr); linkNum = QString(); expStr = QString(); m_simpleListDelegate->cutApart("1+2=3", linkNum, expStr); EXPECT_EQ(linkNum, "1"); } TEST_F(Ut_SimpleListDelegate, setSelect) { m_simpleListDelegate->setSelect(true); EXPECT_TRUE(m_simpleListDelegate->m_selected); } //bool stub_focus_simpledelegateT() //{ // return true; //} bool stub_focus_simpledelegateF() { return false; } TEST_F(Ut_SimpleListDelegate, paintnofocus) { SimpleListView *m_simplelistview = new SimpleListView(0); SimpleListModel *m_model = new SimpleListModel(0); m_simplelistview->setModel(m_model); m_simplelistview->setItemDelegate(m_simpleListDelegate); m_model->m_expressionList.append("1"); m_model->updataList("2=2", 0, false); QPainter *painter = new QPainter(); Stub stub; stub.set(ADDR(SimpleListView, hasFocus), stub_focus_simpledelegateF); QStyleOptionViewItem option; option.init(m_simplelistview); QWidget wid; wid.setFixedWidth(10); option.widget = &wid; m_simpleListDelegate->m_type = 0; m_simpleListDelegate->paint(painter, option, QModelIndex()); m_simpleListDelegate->m_type = 1; m_simpleListDelegate->paint(painter, option, m_model->index(0, 0, QModelIndex())); delete painter; //paint函数,无assert delete m_simplelistview; delete m_model; } TEST_F(Ut_SimpleListDelegate, paint1nofocus) { SimpleListView *m_simplelistview = new SimpleListView(1); SimpleListModel *m_model = new SimpleListModel(1); SimpleListDelegate *m_simpleListDelegate = new SimpleListDelegate(1); m_simplelistview->setModel(m_model); m_simplelistview->setItemDelegate(m_simpleListDelegate); m_model->m_expressionList.append("1"); m_model->updataList("2=2", 0, false); QPainter *painter = new QPainter(); Stub stub; stub.set(ADDR(SimpleListView, hasFocus), stub_focus_simpledelegateF); QStyleOptionViewItem option; option.init(m_simplelistview); QWidget wid; wid.setFixedWidth(10); option.widget = &wid; m_simpleListDelegate->m_type = 0; m_simpleListDelegate->paint(painter, option, QModelIndex()); m_simpleListDelegate->m_type = 1; m_simpleListDelegate->paint(painter, option, m_model->index(0, 0, QModelIndex())); delete painter; //paint函数,无assert delete m_simplelistview; delete m_model; delete m_simpleListDelegate; } TEST_F(Ut_SimpleListDelegate, updateEditorGeometry) { QWidget *widget = new QWidget(); QStyleOptionViewItem item; m_simpleListDelegate->updateEditorGeometry(widget, item, QModelIndex()); EXPECT_EQ(widget->geometry(), item.rect); widget->deleteLater(); } //QRect stub_visualRect_simpledelegate(void *obj, const QModelIndex &index) //{ // Q_UNUSED(index); // SimpleListView *o = (SimpleListView *)obj; // qDebug() << "visual"; // return QRect(10, 10, 10, 10); //} //TEST_F(Ut_SimpleListDelegate, paintfocus) //{ // SimpleListView *m_simplelistview = new SimpleListView(0); // SimpleListModel *m_model = new SimpleListModel(0); // SimpleListDelegate *m_simpleListDelegate = new SimpleListDelegate(0); // m_simplelistview->setModel(m_model); // m_simplelistview->setItemDelegate(m_simpleListDelegate); // m_model->m_expressionList.append("1"); // m_model->updataList("2", 0, false); // QPainter *painter = new QPainter(); // Stub stub; // stub.set(ADDR(SimpleListView, hasFocus), stub_focus_simpledelegateT); // QStyleOptionViewItem option; // QWidget wid; // wid.setFixedWidth(10); // option.widget = &wid; // m_simpleListDelegate->m_focusindex = m_model->index(0, 0, QModelIndex()); // typedef QRect(*fptr)(QListView *, QModelIndex); // fptr visual = (fptr)(&QListView::visualRect); // Stub stub1; // stub1.set(ADDR(SimpleListView, hasFocus), stub_focus_simpledelegateT); // m_simpleListDelegate->paint(painter, option, QModelIndex()); //} deepin-calculator-5.7.21/tests/src/views/ut_simplelistdelegate.h000066400000000000000000000007771423020056600250410ustar00rootroot00000000000000#ifndef UT_SIMPLELISTDELEGATE_H #define UT_SIMPLELISTDELEGATE_H #include #include #include #include"../stub.h" #include "../../src/views/simplelistdelegate.h" #include "../../src/views/simplelistmodel.h" class Ut_SimpleListDelegate : public ::testing::Test { public: Ut_SimpleListDelegate(); SimpleListDelegate *m_simpleListDelegate; SimpleListModel *model; protected: void SetUp(); void TearDown(); }; #endif // UT_SIMPLELISTDELEGATE_H deepin-calculator-5.7.21/tests/src/views/ut_simplelistmodel.cpp000066400000000000000000000102461423020056600247120ustar00rootroot00000000000000#include "ut_simplelistmodel.h" #include Ut_SimpleListModel::Ut_SimpleListModel() { } void Ut_SimpleListModel::SetUp() { m_simpleListModel = new SimpleListModel(); } void Ut_SimpleListModel::TearDown() { delete m_simpleListModel; } TEST_F(Ut_SimpleListModel, data) { m_simpleListModel->appendText("1", false); EXPECT_EQ(m_simpleListModel->data(m_simpleListModel->index(0, 0), SimpleListModel::Role::ExpressionWithOutTip), "1"); m_simpleListModel->appendText("2", false); EXPECT_EQ(m_simpleListModel->data(m_simpleListModel->index(1, 0), SimpleListModel::Role::ExpressionCount), 2); m_simpleListModel->appendText("3", false); EXPECT_EQ(m_simpleListModel->data(m_simpleListModel->index(1, 0), SimpleListModel::Role::ExpressionPrevious), "1"); m_simpleListModel->data(m_simpleListModel->index(1, 0), 7); EXPECT_EQ(m_simpleListModel->data(m_simpleListModel->index(1, 0), SimpleListModel::Role::ExpressionNext), "3"); } TEST_F(Ut_SimpleListModel, data1) { m_simpleListModel->appendText("1", true); m_simpleListModel->appendText("2", true); m_simpleListModel->appendText("3", true); EXPECT_EQ(m_simpleListModel->data(m_simpleListModel->index(0, 0), SimpleListModel::Role::ExpressionCount), 1); EXPECT_EQ(m_simpleListModel->data(m_simpleListModel->index(1, 0), SimpleListModel::Role::ExpressionNext), "3"); } TEST_F(Ut_SimpleListModel, updataList1) { for (int i = 0; i < 500; i++) { m_simpleListModel->m_expressionList.append("1"); } m_simpleListModel->updataList("2", 500, true); m_simpleListModel->updataList("3", 500, false); m_simpleListModel->updataList("3x3", 500, false); EXPECT_EQ(m_simpleListModel->m_expressionList.count(), 500); } TEST_F(Ut_SimpleListModel, updataList2) { for (int i = 0; i < 500; i++) { m_simpleListModel->m_expressionList.append("1"); m_simpleListModel->m_answerlist.append(Quantity(1)); } m_simpleListModel->updataList(Quantity(9), "3x3", 500); EXPECT_EQ(m_simpleListModel->m_expressionList.count(), 500); } TEST_F(Ut_SimpleListModel, deleteItem) { m_simpleListModel->m_expressionList.append("1"); m_simpleListModel->m_answerlist.append(Quantity(1)); m_simpleListModel->deleteItem(0); EXPECT_EQ(m_simpleListModel->m_expressionList.count(), 0); } TEST_F(Ut_SimpleListModel, copyToClipboard) { m_simpleListModel->m_expressionList.append("1"); m_simpleListModel->copyToClipboard(0); EXPECT_EQ(QApplication::clipboard()->text(), "1"); } TEST_F(Ut_SimpleListModel, getAnswer) { m_simpleListModel->m_answerlist.append(Quantity(1)); m_simpleListModel->getAnswer(1); EXPECT_EQ(m_simpleListModel->getAnswer(0), Quantity(1)); } TEST_F(Ut_SimpleListModel, radixChanged) { m_simpleListModel->m_expressionList.append("123+321 = 444"); m_simpleListModel->radixChanged(16, 10); EXPECT_EQ(m_simpleListModel->m_expressionList.at(0), "291+801=1,092"); m_simpleListModel->radixChanged(10, 8); EXPECT_EQ(m_simpleListModel->m_expressionList.at(0), "443+1 441=2 104"); m_simpleListModel->radixChanged(8, 2); EXPECT_EQ(m_simpleListModel->m_expressionList.at(0), "1 0010 0011+11 0010 0001=100 0100 0100"); m_simpleListModel->radixChanged(2, 16); EXPECT_EQ(m_simpleListModel->m_expressionList.at(0), "123+321=444"); } TEST_F(Ut_SimpleListModel, radixChanged1) { m_simpleListModel->m_expressionList.append("-123and321 = 444"); m_simpleListModel->radixChanged(10, 2); EXPECT_EQ(m_simpleListModel->m_expressionList.at(0), "1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1000 0101 and 1 0100 0001=1 1011 1100"); } TEST_F(Ut_SimpleListModel, formatExpression) { m_simpleListModel->formatExpression(10, "321"); m_simpleListModel->formatExpression(8, "321"); m_simpleListModel->formatExpression(2, "321"); QString str = m_simpleListModel->formatExpression(16, "321"); EXPECT_EQ(str, "0x321"); } TEST_F(Ut_SimpleListModel, answerOutOfRange) { m_simpleListModel->m_expressionList.append("123+321 = 444"); m_simpleListModel->answerOutOfRange(Quantity(123)); EXPECT_EQ(m_simpleListModel->m_expressionList.at(0), "123+321 =123"); } deepin-calculator-5.7.21/tests/src/views/ut_simplelistmodel.h000066400000000000000000000006521423020056600243570ustar00rootroot00000000000000#ifndef UT_SIMPLELISTMODEL_H #define UT_SIMPLELISTMODEL_H #include #include #include #include "../../src/dsettings.h" #include "../../src/views/simplelistmodel.h" class Ut_SimpleListModel : public ::testing::Test { public: Ut_SimpleListModel(); SimpleListModel *m_simpleListModel; protected: void SetUp(); void TearDown(); }; #endif // UT_SIMPLELISTMODEL_H deepin-calculator-5.7.21/tests/src/views/ut_simplelistview.cpp000066400000000000000000000175161423020056600245730ustar00rootroot00000000000000#include "ut_simplelistview.h" #include "../../src/views/simplelistview.h" Ut_SimpleListView::Ut_SimpleListView() { } TEST_F(Ut_SimpleListView, connect) { SimpleListView *m_simpleListView = new SimpleListView(); m_simpleListView->verticalScrollBar()->rangeChanged(1, 1); EXPECT_EQ(m_simpleListView->viewportMargins(), QMargins(0, 0, 0, 0)); delete m_simpleListView; } QAction *stub_exec_simple(const QPoint &pos, QAction *at = nullptr) { Q_UNUSED(pos) Q_UNUSED(at) return nullptr; } TEST_F(Ut_SimpleListView, contextMenuEvent) { SimpleListView *m_simpleListView = new SimpleListView(); SimpleListModel *m_model = new SimpleListModel; m_simpleListView->setModel(m_model); m_model->appendText("1", true); Stub stub; stub.set((QAction * (QMenu::*)(const QPoint &, QAction *)) ADDR(QMenu, exec), stub_exec_simple); // QContextMenuEvent *e = new QContextMenuEvent(QContextMenuEvent::Reason::Mouse, m_simpleListView->pos()); m_simpleListView->listItemFill(true); QContextMenuEvent *e = new QContextMenuEvent(QContextMenuEvent::Reason::Mouse, m_simpleListView->pos(), m_simpleListView->pos(), Qt::KeyboardModifier::NoModifier); m_simpleListView->contextMenuEvent(e); EXPECT_EQ(e->pos(), m_simpleListView->pos()); delete e; delete m_simpleListView; delete m_model; } TEST_F(Ut_SimpleListView, listItemFill) { SimpleListView *m_simpleListView = new SimpleListView(); m_simpleListView->listItemFill(true); EXPECT_TRUE(m_simpleListView->m_itemfill); delete m_simpleListView; } TEST_F(Ut_SimpleListView, showTextEditMenuByAltM) { SimpleListView *m_simpleListView = new SimpleListView(); SimpleListModel *m_simpleListModel = new SimpleListModel(); m_simpleListModel->updataList("11", 0); m_simpleListModel->updataList("22", 1); m_simpleListModel->updataList("33", 2); m_simpleListModel->appendText("1", true); m_simpleListModel->appendText("2", true); m_simpleListModel->appendText("3", true); m_simpleListView->setModel(m_simpleListModel); m_simpleListView->setCurrentIndex(m_simpleListModel->index(1, 0)); Stub stub; stub.set((QAction * (QMenu::*)(const QPoint &, QAction *)) ADDR(QMenu, exec), stub_exec_simple); // QContextMenuEvent *e = new QContextMenuEvent(QContextMenuEvent::Reason::Mouse, m_simpleListView->pos()); m_simpleListView->listItemFill(true); m_simpleListView->showTextEditMenuByAltM(m_simpleListView->currentIndex()); EXPECT_EQ(m_simpleListView->currentIndex().row(), 1); delete m_simpleListView; delete m_simpleListModel; } TEST_F(Ut_SimpleListView, mouseMoveEvent) { SimpleListView *m_simpleListView = new SimpleListView(); m_simpleListView->m_mode = 1; m_simpleListView->m_itemfill = true; m_simpleListView->m_ispressed = true; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseMove, m_simpleListView->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_simpleListView->mouseMoveEvent(m); EXPECT_FALSE(m_simpleListView->m_presschanged); m_simpleListView->m_ispressed = false; m_simpleListView->mouseMoveEvent(m); EXPECT_FALSE(m_simpleListView->m_presschanged); m_simpleListView->m_mode = 0; SimpleListModel *m_model = new SimpleListModel; SimpleListDelegate *m_delegate = new SimpleListDelegate(0); m_simpleListView->setModel(m_model); m_simpleListView->setItemDelegate(m_delegate); m_model->appendText("1", true); m_simpleListView->mouseMoveEvent(m); EXPECT_FALSE(m_simpleListView->m_presschanged); delete m; delete m_simpleListView; delete m_model; delete m_delegate; } TEST_F(Ut_SimpleListView, adjustScrollbarMargins) { SimpleListView *m_simpleListView = new SimpleListView(); m_simpleListView->adjustScrollbarMargins(); EXPECT_EQ(m_simpleListView->viewportMargins(), QMargins(0, 0, 0, 0)); delete m_simpleListView; } TEST_F(Ut_SimpleListView, mousePressEvent) { SimpleListView *m_simpleListView = new SimpleListView(); SimpleListModel *m_model = new SimpleListModel; SimpleListDelegate *m_delegate = new SimpleListDelegate(0); m_simpleListView->setModel(m_model); m_simpleListView->setItemDelegate(m_delegate); m_model->appendText("1", true); m_simpleListView->m_mode = 1; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_simpleListView->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier); m_simpleListView->mousePressEvent(m); EXPECT_EQ(m_simpleListView->m_currentrow, 0); EXPECT_TRUE(m_simpleListView->m_ispressed); delete m; delete m_simpleListView; delete m_model; delete m_delegate; } TEST_F(Ut_SimpleListView, mouseReleaseEvent) { SimpleListView *m_simpleListView = new SimpleListView(); SimpleListModel *m_model = new SimpleListModel; SimpleListDelegate *m_delegate = new SimpleListDelegate(0); m_simpleListView->setModel(m_model); m_simpleListView->setItemDelegate(m_delegate); m_model->appendText("1", true); m_simpleListView->m_mode = 1; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_simpleListView->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier); m_simpleListView->mouseReleaseEvent(m); EXPECT_FALSE(m_simpleListView->m_ispressed); EXPECT_EQ(m_simpleListView->m_presspoint, QPoint()); delete m; delete m_simpleListView; delete m_model; delete m_delegate; } TEST_F(Ut_SimpleListView, keyPressEvent) { SimpleListView *m_simpleListView = new SimpleListView(); SimpleListModel *m_simpleListModel = new SimpleListModel(); SimpleListDelegate *m_simpleListDelegate = new SimpleListDelegate(0); m_simpleListModel->updataList("11", 0); m_simpleListModel->updataList("22", 1); m_simpleListModel->updataList("33", 2); m_simpleListModel->appendText("1", true); m_simpleListModel->appendText("2", true); m_simpleListModel->appendText("3", true); m_simpleListView->setModel(m_simpleListModel); m_simpleListView->setItemDelegate(m_simpleListDelegate); m_simpleListView->setCurrentIndex(m_simpleListModel->index(1, 0)); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); QKeyEvent *k2 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier); QKeyEvent *k3 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier); m_simpleListView->setCurrentIndex(m_simpleListView->model()->index(0, 0)); m_simpleListView->keyPressEvent(k); m_simpleListView->keyPressEvent(k1); EXPECT_EQ(m_simpleListView->m_currentindexrow, 0); m_simpleListView->keyPressEvent(k2); EXPECT_EQ(m_simpleListView->m_currentindexrow, 1); m_simpleListView->keyPressEvent(k3); delete k; delete k1; delete k2; delete k3; delete m_simpleListView; delete m_simpleListModel; delete m_simpleListDelegate; } TEST_F(Ut_SimpleListView, focusInEvent) { SimpleListView *m_simpleListView = new SimpleListView(); SimpleListModel *m_model = new SimpleListModel; SimpleListDelegate *m_delegate = new SimpleListDelegate(0); m_simpleListView->setModel(m_model); m_simpleListView->setItemDelegate(m_delegate); m_model->appendText("1", true); m_simpleListView->m_mode = 1; QFocusEvent *f = new QFocusEvent(QFocusEvent::Type::FocusIn); m_simpleListView->focusInEvent(f); EXPECT_EQ(m_simpleListView->currentIndex().row(), 0); delete f; delete m_simpleListView; delete m_model; delete m_delegate; } deepin-calculator-5.7.21/tests/src/views/ut_simplelistview.h000066400000000000000000000005031423020056600242240ustar00rootroot00000000000000#ifndef UT_SIMPLELISTVIEW_H #define UT_SIMPLELISTVIEW_H #include #include #include #include #include"../stub.h" #include "../../src/dsettings.h" class Ut_SimpleListView : public ::testing::Test { public: Ut_SimpleListView(); }; #endif // UT_SIMPLELISTVIEW_H deepin-calculator-5.7.21/tests/src/widgets/000077500000000000000000000000001423020056600205765ustar00rootroot00000000000000deepin-calculator-5.7.21/tests/src/widgets/ut_arrowrectangle.cpp000066400000000000000000000032121423020056600250270ustar00rootroot00000000000000#include "ut_arrowrectangle.h" #include "../../src/widgets/arrowrectangle.h" #include "../../src/views/memorylistwidget.h" Ut_ArrowRectangle::Ut_ArrowRectangle() { } TEST_F(Ut_ArrowRectangle, eventFilter) { ArrowRectangle *arrowrectangle = new ArrowRectangle(DArrowRectangle::ArrowTop, DArrowRectangle::FloatWidget); QFocusEvent *f = new QFocusEvent(QFocusEvent::Type::FocusOut); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Escape, Qt::KeyboardModifier::NoModifier); arrowrectangle->eventFilter(arrowrectangle, static_cast (k)); EXPECT_TRUE(arrowrectangle->isHidden()); arrowrectangle->eventFilter(arrowrectangle, static_cast (f)); EXPECT_TRUE(arrowrectangle->isHidden()); delete k; delete f; delete arrowrectangle; } TEST_F(Ut_ArrowRectangle, focusInEvent) { ArrowRectangle *arrowrectangle = new ArrowRectangle(DArrowRectangle::ArrowTop, DArrowRectangle::FloatWidget); MemoryListWidget *list = new MemoryListWidget(); arrowrectangle->setContent(list); QFocusEvent *f = new QFocusEvent(QFocusEvent::Type::FocusIn, Qt::TabFocusReason); arrowrectangle->focusInEvent(f); EXPECT_FALSE(static_cast(arrowrectangle->getContent())->hasFocus()); delete f; delete list; delete arrowrectangle; } TEST_F(Ut_ArrowRectangle, keyPressEvent) { ArrowRectangle *arrowrectangle = new ArrowRectangle(DArrowRectangle::ArrowTop, DArrowRectangle::FloatWidget); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier); arrowrectangle->keyPressEvent(k); delete k; delete arrowrectangle; //屏蔽keyPressEvent,无assert } deepin-calculator-5.7.21/tests/src/widgets/ut_arrowrectangle.h000066400000000000000000000004101423020056600244710ustar00rootroot00000000000000#ifndef UT_ARROWRECTANGLE_H #define UT_ARROWRECTANGLE_H #include #include #include class Ut_ArrowRectangle : public ::testing::Test { public: Ut_ArrowRectangle(); protected: }; #endif // UT_ARROWRECTANGLE_H deepin-calculator-5.7.21/tests/src/widgets/ut_basicmodul.cpp000066400000000000000000000312001423020056600241300ustar00rootroot00000000000000#include #include "ut_basicmodul.h" #include "../../src/widgets/basicmodule.h" Ut_BasicModul::Ut_BasicModul() { } TEST_F(Ut_BasicModul, Signals) { BasicModule *m_basicmodul = new BasicModule; m_basicmodul->m_memorylistwidget->widgetplus(0); EXPECT_EQ(m_basicmodul->findChild()->text(), ""); m_basicmodul->m_memorylistwidget->widgetminus(0); EXPECT_EQ(m_basicmodul->findChild()->text(), ""); m_basicmodul->m_memoryPublic->generateData(Quantity(1)); m_basicmodul->m_memoryPublic->memoryclean(); m_basicmodul->m_keypadLayout->setCurrentIndex(1); QPair pair2 = {"1", Quantity(1)}; m_basicmodul->m_memorylistwidget->itemclick(pair2); EXPECT_EQ(m_basicmodul->findChild()->text(), "1"); m_basicmodul->m_memorylistwidget->hideWidget(); EXPECT_EQ(m_basicmodul->m_keypadLayout->currentIndex(), 0); m_basicmodul->m_memorylistwidget->insidewidget(); m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, setKeyPress) { BasicModule *m_basicmodul = new BasicModule; QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier); m_basicmodul->setKeyPress(k); EXPECT_EQ(m_basicmodul->findChild()->text(), "1"); delete k; m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, mAvailableEvent) { BasicModule *m_basicmodul = new BasicModule; m_basicmodul->mAvailableEvent(); EXPECT_TRUE(m_basicmodul->m_memRCbtn); EXPECT_TRUE(m_basicmodul->m_avail); m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, mUnAvailableEvent) { BasicModule *m_basicmodul = new BasicModule; m_basicmodul->mUnAvailableEvent(); EXPECT_FALSE(m_basicmodul->m_memRCbtn); EXPECT_FALSE(m_basicmodul->m_avail); m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, showListWidget) { BasicModule *m_basicmodul = new BasicModule; m_basicmodul->showListWidget(); EXPECT_EQ(m_basicmodul->m_keypadLayout->currentIndex(), 1); EXPECT_TRUE(m_basicmodul->m_isallgray); m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, initTheme) { BasicModule *m_basicmodul = new BasicModule; m_basicmodul->initTheme(1); EXPECT_EQ(m_basicmodul->findChild()->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text), "#303030"); m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, handleEditKeyPress) { BasicModule *m_basicmodul = new BasicModule; QTest::keyClick(m_basicmodul->findChild(), Qt::Key_0, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_1, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_2, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_3, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_4, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_5, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_6, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_7, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_8, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_9, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Plus, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Minus, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Underscore, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Asterisk, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Slash, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Enter, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Return, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Backspace, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Period, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Escape, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_ParenLeft, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_ParenRight, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Percent, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_C, Qt::ControlModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_V, Qt::ControlModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_A, Qt::ControlModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_X, Qt::ControlModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_X, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Delete, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Left, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Right, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Z, Qt::ControlModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Y, Qt::ControlModifier); m_basicmodul->m_memRCbtn = true; m_basicmodul->m_isallgray = false; QTest::keyClick(m_basicmodul->findChild(), Qt::Key_L, Qt::ControlModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_R, Qt::ControlModifier); m_basicmodul->m_memCalbtn = true; m_basicmodul->findChild()->setText("1"); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_P, Qt::ControlModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Q, Qt::ControlModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_M, Qt::ControlModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_Escape, Qt::NoModifier); QTest::keyClick(m_basicmodul->findChild(), Qt::Key_1, Qt::NoModifier); EXPECT_EQ(m_basicmodul->findChild()->text(), "1"); m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, handleKeypadButtonPress) { BasicModule *m_basicmodul = new BasicModule; // QTest::mouseClick(m_basicmodul->findChild()->button(BasicKeypad::Key_Clear), Qt::LeftButton); // QTest::mouseClick(m_basicmodul->findChild()->button(BasicKeypad::Key_1), Qt::LeftButton); // QTest::mouseClick(m_basicmodul->findChild()->button(BasicKeypad::Key_Plus), Qt::LeftButton); // QTest::mouseClick(m_basicmodul->findChild()->button(BasicKeypad::Key_3), Qt::LeftButton); // QTest::mouseClick(m_basicmodul->findChild()->button(BasicKeypad::Key_Equals), Qt::LeftButton); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_0); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_1); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_2); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_3); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_4); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_5); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_6); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_7); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_8); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_9); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Plus); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Min); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Mult); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Div); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Percent); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Equals); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Clear); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Backspace); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Point); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Brackets); m_basicmodul->handleKeypadButtonPress(MemoryKeypad::Key_MS); m_basicmodul->handleKeypadButtonPress(MemoryKeypad::Key_MC); m_basicmodul->handleKeypadButtonPress(MemoryKeypad::Key_Mlist); m_basicmodul->handleKeypadButtonPress(MemoryKeypad::Key_Mplus); m_basicmodul->handleKeypadButtonPress(MemoryKeypad::Key_Mminus); m_basicmodul->handleKeypadButtonPress(MemoryKeypad::Key_MR); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_Clear); m_basicmodul->handleKeypadButtonPress(BasicKeypad::Key_1); EXPECT_EQ(m_basicmodul->findChild()->text(), "1"); m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, handleKeypadButtonPressByspace) { BasicModule *m_basicmodul = new BasicModule; m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_0); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_1); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_2); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_3); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_4); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_5); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_6); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_7); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_8); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_9); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Plus); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Min); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Mult); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Div); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Percent); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Equals); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Clear); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Backspace); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Point); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Brackets); m_basicmodul->handleKeypadButtonPressByspace(MemoryKeypad::Key_MS); m_basicmodul->handleKeypadButtonPressByspace(MemoryKeypad::Key_MC); m_basicmodul->handleKeypadButtonPressByspace(MemoryKeypad::Key_Mlist); m_basicmodul->handleKeypadButtonPressByspace(MemoryKeypad::Key_Mplus); m_basicmodul->handleKeypadButtonPressByspace(MemoryKeypad::Key_Mminus); m_basicmodul->handleKeypadButtonPressByspace(MemoryKeypad::Key_MR); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_Clear); m_basicmodul->handleKeypadButtonPressByspace(BasicKeypad::Key_1); EXPECT_EQ(m_basicmodul->findChild()->text(), "1"); m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, mousePressEvent) { BasicModule *m_basicmodul = new BasicModule; QTest::mouseClick(m_basicmodul->findChild()->button(BasicKeypad::Key_1), Qt::LeftButton); QTest::mouseClick(m_basicmodul->findChild()->button(MemoryKeypad::Key_MS), Qt::LeftButton); QTest::mouseClick(m_basicmodul->findChild()->button(MemoryKeypad::Key_Mlist), Qt::LeftButton); QMouseEvent *m = new QMouseEvent(QEvent::MouseButtonPress, m_basicmodul->findChild()->pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); m_basicmodul->mousePressEvent(m); EXPECT_EQ(m_basicmodul->m_keypadLayout->currentIndex(), 0); QTest::mouseClick(m_basicmodul->findChild()->button(MemoryKeypad::Key_Mlist), Qt::LeftButton); QTest::mouseClick(m_basicmodul->findChild()->findChild(), Qt::LeftButton); m_basicmodul->mousePressEvent(m); EXPECT_EQ(m_basicmodul->m_keypadLayout->currentIndex(), 0); delete m; m_basicmodul->deleteLater(); } TEST_F(Ut_BasicModul, itemclick) { BasicModule *m_basicmodul = new BasicModule; QTest::mouseClick(m_basicmodul->findChild()->button(BasicKeypad::Key_1), Qt::LeftButton); QTest::mouseClick(m_basicmodul->findChild()->button(MemoryKeypad::Key_MS), Qt::LeftButton); QTest::mouseClick(m_basicmodul->findChild()->button(MemoryKeypad::Key_Mlist), Qt::LeftButton); QTest::mouseClick(m_basicmodul->findChild(), Qt::LeftButton); EXPECT_EQ(m_basicmodul->m_keypadLayout->currentIndex(), 0); m_basicmodul->deleteLater(); } deepin-calculator-5.7.21/tests/src/widgets/ut_basicmodul.h000066400000000000000000000004721423020056600236040ustar00rootroot00000000000000#ifndef UT_BASICMODUL_H #define UT_BASICMODUL_H #include #include #include #include "../../src/memorypublic.h" #include "../../src/dsettings.h" class Ut_BasicModul : public ::testing::Test { public: Ut_BasicModul(); protected: }; #endif // UT_BASICMODUL_H deepin-calculator-5.7.21/tests/src/widgets/ut_expressionbar.cpp000066400000000000000000000346471423020056600247140ustar00rootroot00000000000000#include "ut_expressionbar.h" #include #include "../../src/widgets/expressionbar.h" Ut_ExpressionBar::Ut_ExpressionBar() { } TEST_F(Ut_ExpressionBar, mouseMoveEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseMove, m_expressionBar->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_expressionBar->mouseMoveEvent(m); delete m; //无ASSERT delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterNumberEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->m_inputNumber = true; m_expressionBar->m_hisRevision = -1; m_expressionBar->enterNumberEvent("1"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1"); m_expressionBar->m_isResult = true; m_expressionBar->enterNumberEvent("1"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1"); m_expressionBar->m_isContinue = false; m_expressionBar->enterNumberEvent("1"); m_expressionBar->enterNumberEvent("1"); EXPECT_EQ(m_expressionBar->findChild()->text(), "11"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterSymbolEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->m_inputEdit->setText("3"); m_expressionBar->m_isUndo = true; m_expressionBar->enterSymbolEvent("-"); EXPECT_EQ(m_expressionBar->m_inputEdit->text(), "3-"); m_expressionBar->m_hisLink.last().linkedItem = -1; m_expressionBar->enterSymbolEvent("+"); EXPECT_EQ(m_expressionBar->m_inputEdit->text(), "3+"); m_expressionBar->m_inputEdit->setCursorPosition(0); m_expressionBar->enterSymbolEvent("-"); EXPECT_EQ(m_expressionBar->m_inputEdit->text(), "-3+"); m_expressionBar->m_inputEdit->setCursorPosition(1); m_expressionBar->enterSymbolEvent("-"); EXPECT_EQ(m_expressionBar->m_inputEdit->text(), "-3+"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterPointEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->enterPointEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "0."); m_expressionBar->findChild()->setText("1"); m_expressionBar->enterPointEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1."); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterPointEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+0.1"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterBackspaceEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->findChild()->setText("1+1"); m_expressionBar->allElection(); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); m_expressionBar->findChild()->setText("1.+1"); m_expressionBar->enterBackspaceEvent(); m_expressionBar->enterBackspaceEvent(); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1"); m_expressionBar->findChild()->setText("111,111"); m_expressionBar->findChild()->setCursorPosition(4); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "11,111"); m_expressionBar->findChild()->setText("1,111"); m_expressionBar->findChild()->setCursorPosition(3); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "111"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterClearEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->m_isAllClear = false; m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->enterClearEvent(); m_expressionBar->m_isAllClear = true; m_expressionBar->enterClearEvent(); m_expressionBar->m_isAllClear = false; m_expressionBar->findChild()->setText("1+1"); m_expressionBar->enterClearEvent(); EXPECT_EQ(m_expressionBar->m_listModel->rowCount(QModelIndex()), 0); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterEqualEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->enterEqualEvent(); m_expressionBar->findChild()->setText("1+"); historicalLinkageIndex his; his.linkageTerm = 0; his.linkageValue = 3; his.linkedItem = 1; m_expressionBar->m_hisLink.append(his); his.linkageTerm = 1; his.linkageValue = 3; his.linkedItem = 2; m_expressionBar->m_hisLink.append(his); m_expressionBar->m_hisRevision = -1; m_expressionBar->m_isLinked = true; m_expressionBar->enterEqualEvent(); m_expressionBar->findChild()->setText("1+"); m_expressionBar->m_hisLink.append(his); m_expressionBar->m_hisRevision = 1; m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+"); m_expressionBar->findChild()->setText("1+2"); m_expressionBar->m_hisRevision = -1; m_expressionBar->m_isLinked = true; m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "3"); m_expressionBar->findChild()->setText("1+2"); m_expressionBar->m_hisRevision = 0; m_expressionBar->m_isLinked = true; m_expressionBar->m_Selected = 0; m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "3"); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "2"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterPercentEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->enterPercentEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->enterPercentEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+1%"); m_expressionBar->findChild()->setCursorPosition(1); m_expressionBar->enterPercentEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1%+1%"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterBracketsEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->findChild()->setText("3"); m_expressionBar->m_isUndo = true; m_expressionBar->enterBracketsEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "3()"); m_expressionBar->m_hisLink.last().linkedItem = -1; m_expressionBar->enterBracketsEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "3(())"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterLeftBracketsEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->findChild()->setText("3"); m_expressionBar->m_isUndo = true; m_expressionBar->enterLeftBracketsEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "3("); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->m_hisLink.last().linkedItem = -1; m_expressionBar->enterLeftBracketsEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "(3("); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, enterRightBracketsEvent) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->findChild()->setText("3"); m_expressionBar->m_isUndo = true; m_expressionBar->enterRightBracketsEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "3)"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->m_hisLink.last().linkedItem = -1; m_expressionBar->enterRightBracketsEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), ")3)"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, moveLeft) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->moveLeft(); EXPECT_EQ(m_expressionBar->findChild()->cursorPosition(), 2); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, moveRight) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->moveRight(); EXPECT_EQ(m_expressionBar->findChild()->cursorPosition(), 1); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, copyResultToClipboard) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->copyResultToClipboard(); m_expressionBar->findChild()->setText("1+2"); m_expressionBar->allElection(); m_expressionBar->copyResultToClipboard(); EXPECT_EQ(QApplication::clipboard()->text(), "1+2"); m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->findChild()->setText("3"); m_expressionBar->m_isUndo = true; m_expressionBar->copyClipboard2Result(); EXPECT_EQ(QApplication::clipboard()->text(), "1+2"); m_expressionBar->m_hisLink.last().linkedItem = -1; m_expressionBar->copyClipboard2Result(); EXPECT_EQ(m_expressionBar->findChild()->text(), "31+21+2"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, allElection) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->allElection(); EXPECT_EQ(m_expressionBar->findChild()->getSelection().selected, "1+2"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, shear) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->allElection(); m_expressionBar->shear(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); EXPECT_FALSE(m_expressionBar->m_isResult); EXPECT_TRUE(m_expressionBar->m_isContinue); EXPECT_FALSE(m_expressionBar->m_isUndo); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, deleteText) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->allElection(); m_expressionBar->deleteText(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); EXPECT_FALSE(m_expressionBar->m_isResult); EXPECT_TRUE(m_expressionBar->m_isContinue); EXPECT_FALSE(m_expressionBar->m_isUndo); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, clearLinkageCache) { ExpressionBar *m_expressionBar = new ExpressionBar; historicalLinkageIndex his; his.linkageTerm = 0; his.linkageValue = 3; his.linkedItem = 1; m_expressionBar->m_hisLink.append(his); m_expressionBar->clearLinkageCache("1+2=3", true); historicalLinkageIndex his1; his1.linkageTerm = 0; his1.linkageValue = 3; his1.linkedItem = 1; m_expressionBar->m_hisLink.append(his1); m_expressionBar->m_hisLink.last().linkedItem = -1; m_expressionBar->clearLinkageCache("1+2=3", false); // m_expressionBar->shear(); EXPECT_EQ(m_expressionBar->m_hisLink.count(), 0); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, settingLinkage) { ExpressionBar *m_expressionBar = new ExpressionBar; historicalLinkageIndex his; his.linkageTerm = 0; his.linkageValue = 3; his.linkedItem = 1; m_expressionBar->m_hisLink.append(his); m_expressionBar->m_hisRevision = 0; m_expressionBar->settingLinkage(); EXPECT_EQ(m_expressionBar->m_hisLink.count(), 1); m_expressionBar->m_hisLink.clear(); his.linkageTerm = 1; his.linkageValue = 3; his.linkedItem = 0; m_expressionBar->m_hisLink.append(his); m_expressionBar->m_hisRevision = 0; m_expressionBar->settingLinkage(); EXPECT_EQ(m_expressionBar->m_hisLink.count(), 1); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, setResultFalse) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->m_isResult = true; m_expressionBar->setResultFalse(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, replaceSelection) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->allElection(); m_expressionBar->replaceSelection("1+2"); EXPECT_FALSE(m_expressionBar->m_isResult); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, revisionResults) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->revisionResults(m_expressionBar->m_listModel->index(0, 0)); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+2"); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, cancelLink) { ExpressionBar *m_expressionBar = new ExpressionBar; m_expressionBar->findChild()->setText("1+2"); historicalLinkageIndex his; his.linkageTerm = 0; his.linkageValue = 3; his.linkedItem = 1; m_expressionBar->m_hisLink.append(his); m_expressionBar->m_hisRevision = 1; EXPECT_TRUE(m_expressionBar->cancelLink(1)); delete m_expressionBar; } TEST_F(Ut_ExpressionBar, pointFaultTolerance) { ExpressionBar *m_expressionBar = new ExpressionBar; EXPECT_EQ(m_expressionBar->pointFaultTolerance("123321.123321。"), "123321.123321"); EXPECT_EQ(m_expressionBar->pointFaultTolerance("123321。123321."), "123321123321."); EXPECT_EQ(m_expressionBar->pointFaultTolerance(".123321"), "0.123321"); delete m_expressionBar; } deepin-calculator-5.7.21/tests/src/widgets/ut_expressionbar.h000066400000000000000000000004311423020056600243410ustar00rootroot00000000000000#ifndef UT_EXPRESSIONBAR_H #define UT_EXPRESSIONBAR_H #include #include #include #include "../../src/dsettings.h" class Ut_ExpressionBar : public ::testing::Test { public: Ut_ExpressionBar(); }; #endif // UT_EXPRESSIONBAR_H deepin-calculator-5.7.21/tests/src/widgets/ut_inputedit.cpp000066400000000000000000000274311423020056600240260ustar00rootroot00000000000000#include "ut_inputedit.h" #include "../../src/widgets/inputedit.h" #include #include "../../3rdparty/math/cmath.h" Ut_InputEdit::Ut_InputEdit() { } TEST_F(Ut_InputEdit, expressionText) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("3.333333333333333E-4"); m_inputEdit->m_evaluator = Evaluator::instance(); m_inputEdit->m_evaluator->setExpression("1/3000"); m_inputEdit->m_ans = m_inputEdit->m_evaluator->evalUpdateAns(); m_inputEdit->m_ansVaild = true; m_inputEdit->m_strans = QString("3.333333333333333E-4"); m_inputEdit->m_ansStartPos = 0; m_inputEdit->m_ansLength = 20; EXPECT_EQ(m_inputEdit->expressionText(), "lastans"); delete m_inputEdit; } TEST_F(Ut_InputEdit, setAnswer) { InputEdit *m_inputEdit = new InputEdit; Evaluator *m_evaluator = Evaluator::instance(); m_evaluator->setExpression("1/3000"); Quantity ans = m_evaluator->evalUpdateAns(); m_inputEdit->setAnswer("3.333333333333333E-4", ans); EXPECT_EQ(m_inputEdit->m_ansLength, 20); EXPECT_EQ(m_inputEdit->m_ans, ans); EXPECT_EQ(m_inputEdit->m_strans, "3.333333333333333E-4"); delete m_inputEdit; } bool stub_focus_input() { return true; } QAction *stub_exec_input(const QPoint &pos, QAction *at = nullptr) { Q_UNUSED(pos) Q_UNUSED(at) return nullptr; } TEST_F(Ut_InputEdit, keyPressEvent) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setFocus(); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_M, Qt::AltModifier); Stub stub; stub.set(ADDR(InputEdit, hasFocus), stub_focus_input); Stub stub1; stub1.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), stub_exec_input); m_inputEdit->setText("1"); m_inputEdit->selectAll(); m_inputEdit->keyPressEvent(k); EXPECT_TRUE(m_inputEdit->m_cut->isEnabled()); EXPECT_TRUE(m_inputEdit->m_copy->isEnabled()); EXPECT_TRUE(m_inputEdit->m_delete->isEnabled()); EXPECT_TRUE(m_inputEdit->m_select->isEnabled()); m_inputEdit->clear(); m_inputEdit->keyPressEvent(k); EXPECT_FALSE(m_inputEdit->m_cut->isEnabled()); EXPECT_FALSE(m_inputEdit->m_copy->isEnabled()); EXPECT_FALSE(m_inputEdit->m_delete->isEnabled()); EXPECT_FALSE(m_inputEdit->m_select->isEnabled()); delete k; delete m_inputEdit; } TEST_F(Ut_InputEdit, mouseDoubleClickEvent) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("12345"); QMouseEvent *m = new QMouseEvent(QEvent::MouseButtonDblClick, m_inputEdit->rect().center(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); m_inputEdit->mouseDoubleClickEvent(m); EXPECT_EQ(m_inputEdit->m_selected.selected, "12,345"); delete m; delete m_inputEdit; } TEST_F(Ut_InputEdit, mousePressEvent) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("12345"); // m_inputEdit->mouseDoubleClickEvent(new QMouseEvent(QEvent::MouseButtonDblClick, m_inputEdit->rect().center(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier)); QMouseEvent *m = new QMouseEvent(QEvent::MouseButtonPress, m_inputEdit->rect().center(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); m_inputEdit->mousePressEvent(m); EXPECT_EQ(m_inputEdit->m_selected.selected, ""); delete m; delete m_inputEdit; } TEST_F(Ut_InputEdit, handleTextChanged) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->handleTextChanged("1="); EXPECT_EQ(m_inputEdit->text(), "1"); EXPECT_FALSE(m_inputEdit->m_ansVaild); EXPECT_EQ(m_inputEdit->m_oldText, "1"); EXPECT_EQ(m_inputEdit->m_selected.selected, ""); EXPECT_EQ(m_inputEdit->m_selected.curpos, -1); delete m_inputEdit; } TEST_F(Ut_InputEdit, pointFaultTolerance) { InputEdit *m_inputEdit = new InputEdit; EXPECT_EQ(m_inputEdit->pointFaultTolerance("1"), "1"); EXPECT_EQ(m_inputEdit->pointFaultTolerance(".1"), ".1"); EXPECT_EQ(m_inputEdit->pointFaultTolerance("%.1"), "%1"); EXPECT_EQ(m_inputEdit->pointFaultTolerance("0.1.1"), "0.11"); delete m_inputEdit; } TEST_F(Ut_InputEdit, symbolFaultTolerance) { InputEdit *m_inputEdit = new InputEdit; EXPECT_EQ(m_inputEdit->symbolFaultTolerance("-1"), "-1"); EXPECT_EQ(m_inputEdit->symbolFaultTolerance("E(-"), "E(-"); EXPECT_EQ(m_inputEdit->symbolFaultTolerance("1E-.1-1"), "1E-1-1"); delete m_inputEdit; } TEST_F(Ut_InputEdit, isSymbol) { InputEdit *m_inputEdit = new InputEdit; EXPECT_TRUE(m_inputEdit->isSymbol("+")); EXPECT_TRUE(m_inputEdit->isSymbol("-")); EXPECT_TRUE(m_inputEdit->isSymbol("÷")); EXPECT_FALSE(m_inputEdit->isSymbol("*")); delete m_inputEdit; } TEST_F(Ut_InputEdit, handleCursorPositionChanged) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->m_ansStartPos = 0; m_inputEdit->m_ansLength = 3; m_inputEdit->m_selected.curpos = 1; m_inputEdit->m_selected.selected = "2"; m_inputEdit->handleCursorPositionChanged(0, 0); EXPECT_TRUE(m_inputEdit->m_currentInAns); EXPECT_EQ(m_inputEdit->m_lastPos, 0); delete m_inputEdit; } TEST_F(Ut_InputEdit, BracketCompletion) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("(()"); QKeyEvent *k = new QKeyEvent(QEvent::None, Qt::Key_1, Qt::NoModifier); m_inputEdit->BracketCompletion(k); EXPECT_EQ(m_inputEdit->text(), "(())"); m_inputEdit->setText("())"); m_inputEdit->BracketCompletion(k); EXPECT_EQ(m_inputEdit->text(), "())()"); m_inputEdit->setText("()"); m_inputEdit->BracketCompletion(k); EXPECT_EQ(m_inputEdit->text(), "()()"); delete k; delete m_inputEdit; } TEST_F(Ut_InputEdit, multipleArithmetic) { InputEdit *m_inputEdit = new InputEdit; QString s = "\n)\n"; m_inputEdit->multipleArithmetic(s); EXPECT_EQ(s, "\n)×"); delete m_inputEdit; } TEST_F(Ut_InputEdit, getMemoryAnswer) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("1log0"); EXPECT_FALSE(m_inputEdit->getMemoryAnswer().first); m_inputEdit->setText("2log2"); EXPECT_TRUE(m_inputEdit->getMemoryAnswer().first); EXPECT_EQ(m_inputEdit->getMemoryAnswer().second, Quantity(1)); delete m_inputEdit; } TEST_F(Ut_InputEdit, hisexpression) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->m_ansLength = 1; m_inputEdit->hisexpression(); EXPECT_EQ(m_inputEdit->m_ansLength, 0); delete m_inputEdit; } TEST_F(Ut_InputEdit, symbolComplement) { InputEdit *m_inputEdit = new InputEdit; EXPECT_EQ(m_inputEdit->symbolComplement("1(2)"), "1×(2)"); EXPECT_EQ(m_inputEdit->symbolComplement("(1)2"), "(1)×2"); delete m_inputEdit; } TEST_F(Ut_InputEdit, focusInEvent) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("1111111"); m_inputEdit->setCursorPosition(5); QFocusEvent *f = new QFocusEvent(QEvent::Type::FocusIn, Qt::TabFocusReason); m_inputEdit->focusInEvent(f); EXPECT_EQ(m_inputEdit->cursorPosition(), 5); delete f; delete m_inputEdit; } TEST_F(Ut_InputEdit, clear) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->clear(); EXPECT_EQ(m_inputEdit->m_ansLength, 0); delete m_inputEdit; } TEST_F(Ut_InputEdit, setUndoAction) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setUndoAction(false); EXPECT_FALSE(m_inputEdit->m_undo->isEnabled()); delete m_inputEdit; } TEST_F(Ut_InputEdit, setRedoAction) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setRedoAction(true); EXPECT_TRUE(m_inputEdit->m_redo->isEnabled()); delete m_inputEdit; } TEST_F(Ut_InputEdit, autoZoomFontSize) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("0"); m_inputEdit->autoZoomFontSize(); EXPECT_EQ(m_inputEdit->font().pixelSize(), 30); delete m_inputEdit; } TEST_F(Ut_InputEdit, themetypechanged) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->themetypechanged(2); EXPECT_EQ(m_inputEdit->palette().text(), QBrush("#b4b4b4")); m_inputEdit->themetypechanged(1); EXPECT_EQ(m_inputEdit->palette().text(), QBrush("#303030")); delete m_inputEdit; } TEST_F(Ut_InputEdit, valueChangeFromProSyskeypad) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText(""); m_inputEdit->setCursorPosition(0); m_inputEdit->valueChangeFromProSyskeypad("11100011"); EXPECT_EQ(m_inputEdit->text(), "227"); EXPECT_EQ(m_inputEdit->cursorPosition(), 3); delete m_inputEdit; } TEST_F(Ut_InputEdit, radixChanged) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("120+323+456"); m_inputEdit->radixChanged(10, 16); EXPECT_EQ(m_inputEdit->text(), "78+143+1C8"); delete m_inputEdit; } TEST_F(Ut_InputEdit, formatAns) { InputEdit *m_inputEdit = new InputEdit; QString ans = m_inputEdit->formatAns("11100101"); EXPECT_EQ(ans, "229"); delete m_inputEdit; } TEST_F(Ut_InputEdit, getCurrentAns) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("0x1C8"); QPair pair = m_inputEdit->getCurrentAns(); int ans = pair.second.numericValue().toInt(); EXPECT_TRUE(pair.first); EXPECT_EQ(ans, 456); delete m_inputEdit; } TEST_F(Ut_InputEdit, CurrentCursorPositionNumber) { InputEdit *m_inputEdit = new InputEdit; m_inputEdit->setText("6666+2333"); m_inputEdit->setCursorPosition(9); QString str = m_inputEdit->CurrentCursorPositionNumber(m_inputEdit->cursorPosition()); EXPECT_EQ(str, "2333"); delete m_inputEdit; } TEST_F(Ut_InputEdit, isNumber) { InputEdit *m_inputEdit = new InputEdit; EXPECT_FALSE(m_inputEdit->isNumber('a')); EXPECT_TRUE(m_inputEdit->isNumber('A')); delete m_inputEdit; } TEST_F(Ut_InputEdit, formatBinaryNumber) { InputEdit *m_inputEdit = new InputEdit; EXPECT_EQ(m_inputEdit->formatBinaryNumber("0000000000"), "0"); QString str = m_inputEdit->formatBinaryNumber("00000000111001"); EXPECT_EQ(str, "57"); delete m_inputEdit; } TEST_F(Ut_InputEdit, formatExpression) { InputEdit *m_inputEdit = new InputEdit; EXPECT_EQ(m_inputEdit->formatExpression(16, "4435"), "0x4435"); EXPECT_EQ(m_inputEdit->formatExpression(10, "4435"), "4435"); EXPECT_EQ(m_inputEdit->formatExpression(2, "1111"), "0b1111"); EXPECT_EQ(m_inputEdit->formatExpression(8, "4435"), "0o4435"); delete m_inputEdit; } TEST_F(Ut_InputEdit, showTextEditMenu) { InputEdit *m_inputEdit = new InputEdit; Stub stub; stub.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), stub_exec_input); m_inputEdit->setText("1"); m_inputEdit->selectAll(); m_inputEdit->showTextEditMenu(); EXPECT_TRUE(m_inputEdit->m_cut->isEnabled()); EXPECT_TRUE(m_inputEdit->m_copy->isEnabled()); EXPECT_TRUE(m_inputEdit->m_delete->isEnabled()); EXPECT_TRUE(m_inputEdit->m_select->isEnabled()); m_inputEdit->clear(); m_inputEdit->showTextEditMenu(); EXPECT_FALSE(m_inputEdit->m_cut->isEnabled()); EXPECT_FALSE(m_inputEdit->m_copy->isEnabled()); EXPECT_FALSE(m_inputEdit->m_delete->isEnabled()); EXPECT_FALSE(m_inputEdit->m_select->isEnabled()); delete m_inputEdit; } TEST_F(Ut_InputEdit, showTextEditMenuByAltM) { InputEdit *m_inputEdit = new InputEdit; Stub stub; stub.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), stub_exec_input); m_inputEdit->setText("1"); m_inputEdit->selectAll(); m_inputEdit->showTextEditMenuByAltM(); EXPECT_TRUE(m_inputEdit->m_cut->isEnabled()); EXPECT_TRUE(m_inputEdit->m_copy->isEnabled()); EXPECT_TRUE(m_inputEdit->m_delete->isEnabled()); EXPECT_TRUE(m_inputEdit->m_select->isEnabled()); m_inputEdit->clear(); m_inputEdit->showTextEditMenuByAltM(); EXPECT_FALSE(m_inputEdit->m_cut->isEnabled()); EXPECT_FALSE(m_inputEdit->m_copy->isEnabled()); EXPECT_FALSE(m_inputEdit->m_delete->isEnabled()); EXPECT_FALSE(m_inputEdit->m_select->isEnabled()); delete m_inputEdit; } deepin-calculator-5.7.21/tests/src/widgets/ut_inputedit.h000066400000000000000000000004111423020056600234600ustar00rootroot00000000000000#ifndef UT_INPUTEDIT_H #define UT_INPUTEDIT_H #include #include #include #include #include"../stub.h" class Ut_InputEdit : public ::testing::Test { public: Ut_InputEdit(); }; #endif // UT_INPUTEDIT_H deepin-calculator-5.7.21/tests/src/widgets/ut_memhiswidget.cpp000066400000000000000000000155671423020056600245160ustar00rootroot00000000000000#include "ut_memhiswidget.h" #include "../../src/widgets/memhiswidget.h" #include "../../src/memorypublic.h" #include Ut_MemHisWidget::Ut_MemHisWidget() { } TEST_F(Ut_MemHisWidget, space) { MemHisWidget *m_memhiswidget = new MemHisWidget; QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Space, Qt::NoModifier); m_memhiswidget->m_memoryBtn->keyPressEvent(k); EXPECT_EQ(m_memhiswidget->m_stackWidget->currentIndex(), 0); m_memhiswidget->m_clearButton->keyPressEvent(k); EXPECT_TRUE(m_memhiswidget->m_clearButton->isHidden()); m_memhiswidget->m_stackWidget->setCurrentWidget(m_memhiswidget->m_listView); m_memhiswidget->m_clearButton->keyPressEvent(k); EXPECT_FALSE(m_memhiswidget->m_isshowH); delete k; m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, filledMem) { MemHisWidget *m_memhiswidget = new MemHisWidget; MemoryPublic *m_mempublic = MemoryPublic::instance(); // m_memhiswidget->m_memoryWidget->generateData(Quantity(1),false); m_mempublic->generateData(Quantity(1)); EXPECT_TRUE(m_memhiswidget->m_isshowM); m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, emptyMem) { MemHisWidget *m_memhiswidget = new MemHisWidget; MemoryPublic *m_mempublic = MemoryPublic::instance(); m_mempublic->memoryclean(); EXPECT_FALSE(m_memhiswidget->m_isshowM); m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, hisbtnhidden) { MemHisWidget *m_memhiswidget = new MemHisWidget; m_memhiswidget->m_listModel->hisbtnhidden(); EXPECT_FALSE(m_memhiswidget->m_isshowH); m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, clicked) { MemHisWidget *m_memhiswidget = new MemHisWidget; m_memhiswidget->m_historyBtn->clicked(); EXPECT_EQ(m_memhiswidget->m_stackWidget->currentIndex(), 1); m_memhiswidget->m_memoryBtn->clicked(); EXPECT_EQ(m_memhiswidget->m_stackWidget->currentIndex(), 0); m_memhiswidget->m_clearButton->clicked(); EXPECT_TRUE(m_memhiswidget->m_clearButton->isHidden()); m_memhiswidget->m_stackWidget->setCurrentWidget(m_memhiswidget->m_listView); m_memhiswidget->m_clearButton->clicked(); EXPECT_FALSE(m_memhiswidget->m_isshowH); m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, focusOnButtonbox) { MemHisWidget *m_memhiswidget = new MemHisWidget; m_memhiswidget->focusOnButtonbox(Qt::TabFocusReason); m_memhiswidget->m_stackWidget->setCurrentIndex(0); EXPECT_TRUE(m_memhiswidget->m_buttonBox->button(0)->isChecked()); m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, resetFocus) { MemHisWidget *m_memhiswidget = new MemHisWidget; m_memhiswidget->m_isshowH = false; m_memhiswidget->m_isshowM = true; m_memhiswidget->resetFocus(); EXPECT_EQ(m_memhiswidget->m_memoryWidget->focusPolicy(), Qt::TabFocus); m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, keyPressEvent) { MemHisWidget *m_memhiswidget = new MemHisWidget; m_memhiswidget->m_historyBtn->setFocus(); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); QKeyEvent *k1 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier); QKeyEvent *k2 = new QKeyEvent(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier); m_memhiswidget->keyPressEvent(k); m_memhiswidget->keyPressEvent(k1); m_memhiswidget->keyPressEvent(k2); delete k; delete k1; delete k2; //焦点设置函数,无assert m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, eventFilter) { MemHisWidget *m_memhiswidget = new MemHisWidget; QFocusEvent *f = new QFocusEvent(QEvent::Type::FocusIn, Qt::TabFocusReason); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier); QFocusEvent *f1 = new QFocusEvent(QEvent::Type::FocusOut, Qt::MouseFocusReason); m_memhiswidget->eventFilter(m_memhiswidget->m_historyBtn, static_cast (f)); m_memhiswidget->eventFilter(m_memhiswidget->m_memoryBtn, static_cast (k)); m_memhiswidget->eventFilter(m_memhiswidget->m_clearButton, static_cast (k)); m_memhiswidget->eventFilter(m_memhiswidget->m_memoryWidget, static_cast (k)); m_memhiswidget->m_clearButton->setHidden(false); m_memhiswidget->eventFilter(m_memhiswidget, static_cast (k)); m_memhiswidget->eventFilter(m_memhiswidget, static_cast (f1)); m_memhiswidget->eventFilter(m_memhiswidget->m_clearButton, static_cast (f1)); EXPECT_FALSE(m_memhiswidget->hasFocus()); delete f; delete f1; delete k; m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, focusInEvent) { MemHisWidget *m_memhiswidget = new MemHisWidget; m_memhiswidget->m_stackWidget->setCurrentIndex(0); QFocusEvent *f = new QFocusEvent(QEvent::Type::FocusIn, Qt::TabFocusReason); m_memhiswidget->focusInEvent(f); m_memhiswidget->m_stackWidget->setCurrentIndex(1); m_memhiswidget->focusInEvent(f); delete f; //焦点设置函数,无assert m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, themeChanged) { MemHisWidget *m_memhiswidget = new MemHisWidget; m_memhiswidget->themeChanged(2); EXPECT_EQ(m_memhiswidget->m_themeType, 2); EXPECT_EQ(m_memhiswidget->m_clearButton->m_currentUrl, ":/assets/images/dark/empty_normal.svg"); m_memhiswidget->themeChanged(1); EXPECT_EQ(m_memhiswidget->m_themeType, 1); EXPECT_EQ(m_memhiswidget->m_clearButton->m_currentUrl, ":/assets/images/light/empty_normal.svg"); m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, iconChanged) { MemHisWidget *m_memhiswidget = new MemHisWidget; m_memhiswidget->iconChanged(1, 0); m_memhiswidget->iconChanged(2, 1); //设置icon路径,该路径不保存在Qicon中,无assert m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, historyfilled) { MemHisWidget *m_memhiswidget = new MemHisWidget; m_memhiswidget->historyfilled(); EXPECT_TRUE(m_memhiswidget->m_listView->focusPolicy() == Qt::TabFocus); EXPECT_TRUE(m_memhiswidget->m_isshowH); m_memhiswidget->deleteLater(); } TEST_F(Ut_MemHisWidget, memoryFunctions) { MemHisWidget *m_memhiswidget = new MemHisWidget; MemoryPublic *m_mempub = MemoryPublic::instance(); m_mempub->generateData(Quantity(1)); m_memhiswidget->memoryFunctions(MemHisWidget::memoryplus, Quantity(1), 0); EXPECT_EQ(m_mempub->m_list.at(0), Quantity(2)); m_memhiswidget->memoryFunctions(MemHisWidget::memoryminus, Quantity(1), 0); EXPECT_EQ(m_mempub->m_list.at(0), Quantity(1)); m_memhiswidget->memoryFunctions(MemHisWidget::widgetplus, Quantity(1), 0); EXPECT_EQ(m_mempub->m_list.at(0), Quantity(2)); m_memhiswidget->memoryFunctions(MemHisWidget::widgetminus, Quantity(1), 0); EXPECT_EQ(m_mempub->m_list.at(0), Quantity(1)); m_memhiswidget->memoryFunctions(MemHisWidget::memoryclean, Quantity(1), 0); EXPECT_TRUE(m_mempub->isEmpty()); m_memhiswidget->deleteLater(); } deepin-calculator-5.7.21/tests/src/widgets/ut_memhiswidget.h000066400000000000000000000003621423020056600241460ustar00rootroot00000000000000#ifndef UT_MEMHISWIDGET_H #define UT_MEMHISWIDGET_H #include #include #include class Ut_MemHisWidget : public ::testing::Test { public: Ut_MemHisWidget(); }; #endif // UT_MEMHISWIDGET_H deepin-calculator-5.7.21/tests/src/widgets/ut_probitwidget.cpp000066400000000000000000000013121423020056600245120ustar00rootroot00000000000000#include "ut_probitwidget.h" #include "../../src/widgets/probitwidget.h" Ut_ProBitWidget::Ut_ProBitWidget() { } TEST_F(Ut_ProBitWidget, setButtonEnabled) { ProBitWidget *m_probitwidget = new ProBitWidget; m_probitwidget->setButtonEnabled(true); EXPECT_TRUE(m_probitwidget->m_firstbtn->isEnabled()); EXPECT_TRUE(m_probitwidget->m_secondbtn->isEnabled()); EXPECT_TRUE(m_probitwidget->m_thirdbtn->isEnabled()); EXPECT_TRUE(m_probitwidget->m_fourthbtn->isEnabled()); delete m_probitwidget; } TEST_F(Ut_ProBitWidget, getbutton) { ProBitWidget *m_probitwidget = new ProBitWidget; EXPECT_EQ(m_probitwidget->getbutton(3), m_probitwidget->m_fourthbtn); delete m_probitwidget; } deepin-calculator-5.7.21/tests/src/widgets/ut_probitwidget.h000066400000000000000000000003771423020056600241710ustar00rootroot00000000000000#ifndef UT_PROBITWIDGET_H #define UT_PROBITWIDGET_H #include #include #include class Ut_ProBitWidget : public ::testing::Test { public: Ut_ProBitWidget(); protected: }; #endif // UT_PROBITWIDGET_H deepin-calculator-5.7.21/tests/src/widgets/ut_proexpressionbar.cpp000066400000000000000000000541671423020056600254340ustar00rootroot00000000000000#include "ut_proexpressionbar.h" #include "../../src/widgets/proexpressionbar.h" #include "../../3rdparty/core/settings.h" #include "../../src/mainwindow.h" #include #include #include #include #include #include #include Ut_ProexpressionBar::Ut_ProexpressionBar() { } TEST_F(Ut_ProexpressionBar, mouseMoveEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseMove, m_proexpressionBar->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_proexpressionBar->mouseMoveEvent(m); delete m; //取消move效果,无assert delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, isnumber) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar; QChar a = 'A'; EXPECT_TRUE(m_proexpressionBar->m_inputEdit->isNumber(a)); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, judgeinput) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar; m_proexpressionBar->m_inputEdit->setText("and"); SSelection select; select.curpos = 1; select.oldText = "and"; select.selected = "n"; m_proexpressionBar->m_inputEdit->setSelection(select); EXPECT_FALSE(m_proexpressionBar->judgeinput()); m_proexpressionBar->m_inputEdit->setText("1and"); SSelection select0; select0.curpos = 0; select0.oldText = "1and"; select0.selected = "1"; m_proexpressionBar->m_inputEdit->setSelection(select0); EXPECT_TRUE(m_proexpressionBar->judgeinput()); m_proexpressionBar->m_inputEdit->setText("1and"); SSelection select1; select1.curpos = 0; select1.oldText = "1and"; select1.selected = "1a"; m_proexpressionBar->m_inputEdit->setSelection(select1); EXPECT_FALSE(m_proexpressionBar->judgeinput()); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, enterNumberEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar; // Settings::instance()->programmerBase = 16; m_proexpressionBar->m_inputNumber = true; m_proexpressionBar->m_isResult = true; m_proexpressionBar->m_isContinue = false; m_proexpressionBar->enterNumberEvent("1"); EXPECT_FALSE(m_proexpressionBar->m_inputEdit->text().isEmpty()); m_proexpressionBar->m_inputNumber = false; m_proexpressionBar->m_isResult = true; m_proexpressionBar->enterNumberEvent("1"); m_proexpressionBar->enterNumberEvent("8"); m_proexpressionBar->enterNumberEvent("2"); m_proexpressionBar->enterNumberEvent("2"); m_proexpressionBar->enterNumberEvent("2"); EXPECT_TRUE(m_proexpressionBar->m_inputEdit->text() == "18,222"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, enterSymbolEvent) { /* ProExpressionBar *m_proexpressionBar = new ProExpressionBar; m_proexpressionBar->enterSymbolEvent("+"); m_proexpressionBar->findChild()->clear(); m_proexpressionBar->enterSymbolEvent("-"); m_proexpressionBar->enterSymbolEvent("-"); m_proexpressionBar->enterSymbolEvent("+"); m_proexpressionBar->findChild()->setCursorPosition(0); m_proexpressionBar->enterSymbolEvent("-"); m_proexpressionBar->findChild()->setText("1"); m_proexpressionBar->findChild()->setCursorPosition(0); m_proexpressionBar->enterSymbolEvent("-"); m_proexpressionBar->findChild()->setText("1+2"); m_proexpressionBar->findChild()->setCursorPosition(1); m_proexpressionBar->enterSymbolEvent("-"); m_proexpressionBar->findChild()->setText("11"); m_proexpressionBar->findChild()->setCursorPosition(1); m_proexpressionBar->enterSymbolEvent("-"); ASSERT_EQ(m_proexpressionBar->findChild()->text(), "1-1"); DSettingsAlt::deleteInstance(); */ } TEST_F(Ut_ProexpressionBar, enterBackspaceEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar; m_proexpressionBar->findChild()->setText("1+1"); m_proexpressionBar->allElection(); m_proexpressionBar->enterBackspaceEvent(); m_proexpressionBar->enterNotEvent(); m_proexpressionBar->findChild()->setCursorPosition(2); m_proexpressionBar->enterBackspaceEvent(); m_proexpressionBar->findChild()->setCursorPosition(0); m_proexpressionBar->enterOperatorEvent("and"); m_proexpressionBar->findChild()->setCursorPosition(2); m_proexpressionBar->enterBackspaceEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "0(0)"); m_proexpressionBar->findChild()->setText("1 and 2"); m_proexpressionBar->findChild()->setCursorPosition(6); m_proexpressionBar->enterBackspaceEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "1 2"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, enterClearEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar; m_proexpressionBar->m_isAllClear = false; m_proexpressionBar->findChild()->setText("1+1"); m_proexpressionBar->enterClearEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), ""); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, enterEqualEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar; m_proexpressionBar->enterNumberEvent("0"); m_proexpressionBar->enterOperatorEvent("and"); m_proexpressionBar->enterNumberEvent("1"); m_proexpressionBar->enterEqualEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "0"); m_proexpressionBar->enterSymbolEvent("-"); m_proexpressionBar->enterSymbolEvent("+"); m_proexpressionBar->enterNumberEvent("5"); m_proexpressionBar->enterEqualEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "5"); m_proexpressionBar->enterSymbolEvent("/"); m_proexpressionBar->enterNumberEvent("3"); m_proexpressionBar->enterOperatorEvent("or"); m_proexpressionBar->enterNumberEvent("5"); m_proexpressionBar->enterNumberEvent("6"); m_proexpressionBar->enterEqualEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "57"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, enterNotEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar; m_proexpressionBar->enterNotEvent(); m_proexpressionBar->enterClearEvent(); m_proexpressionBar->enterNumberEvent("5"); m_proexpressionBar->enterNotEvent(); m_proexpressionBar->enterEqualEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "-6"); m_proexpressionBar->findChild()->setText("1 and (1 and 2)"); m_proexpressionBar->findChild()->setCursorPosition(15); m_proexpressionBar->enterNotEvent(); m_proexpressionBar->enterEqualEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "1"); m_proexpressionBar->findChild()->setText("()"); m_proexpressionBar->findChild()->setCursorPosition(2); m_proexpressionBar->enterNotEvent(); EXPECT_TRUE(m_proexpressionBar->m_isResult); EXPECT_FALSE(m_proexpressionBar->m_isUndo); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, enterOperatorEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar; m_proexpressionBar->enterOperatorEvent("ror"); m_proexpressionBar->enterClearEvent(); m_proexpressionBar->enterNumberEvent("5"); m_proexpressionBar->enterOperatorEvent("sal"); m_proexpressionBar->enterOperatorEvent("rcl"); m_proexpressionBar->enterOperatorEvent("ror"); m_proexpressionBar->enterNumberEvent("4"); m_proexpressionBar->enterEqualEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "5,764,607,523,034,234,880"); m_proexpressionBar->enterOperatorEvent("rcl"); m_proexpressionBar->enterNumberEvent("3"); m_proexpressionBar->enterEqualEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "-9,223,372,036,854,775,807"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, enterOppositeEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->enterOppositeEvent(); EXPECT_TRUE(m_proexpressionBar->findChild()->text().isEmpty()); m_proexpressionBar->enterNumberEvent("0"); m_proexpressionBar->enterOppositeEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "0"); m_proexpressionBar->enterClearEvent(); m_proexpressionBar->enterSymbolEvent("-"); m_proexpressionBar->enterNumberEvent("1"); m_proexpressionBar->enterOppositeEvent(); m_proexpressionBar->enterEqualEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "-1"); Settings::instance()->programmerBase = 10; m_proexpressionBar->findChild()->setText("1 and (1 and 2)"); m_proexpressionBar->findChild()->setCursorPosition(15); m_proexpressionBar->enterOppositeEvent(); m_proexpressionBar->enterEqualEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "0"); Settings::instance()->programmerBase = 16; m_proexpressionBar->findChild()->setText("1"); m_proexpressionBar->findChild()->setCursorPosition(1); m_proexpressionBar->enterOppositeEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "FFFF FFFF FFFF FFFF"); Settings::instance()->programmerBase = 0; delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, enterLeftBracketsEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("3"); m_proexpressionBar->m_isUndo = true; m_proexpressionBar->enterLeftBracketsEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "3("); m_proexpressionBar->findChild()->setCursorPosition(0); m_proexpressionBar->enterLeftBracketsEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "(3("); m_proexpressionBar->findChild()->setText("1111"); m_proexpressionBar->findChild()->setCursorPosition(2); m_proexpressionBar->enterLeftBracketsEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "1(111"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, enterRightBracketsEvent) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("3"); m_proexpressionBar->m_isUndo = true; m_proexpressionBar->enterRightBracketsEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "3)"); m_proexpressionBar->findChild()->setCursorPosition(0); m_proexpressionBar->enterRightBracketsEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), ")3)"); m_proexpressionBar->findChild()->setText("1111"); m_proexpressionBar->findChild()->setCursorPosition(2); m_proexpressionBar->enterRightBracketsEvent(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "1)111"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, moveLeft) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("1+2"); m_proexpressionBar->moveLeft(); m_proexpressionBar->findChild()->setText("and2"); m_proexpressionBar->moveLeft(); m_proexpressionBar->moveLeft(); EXPECT_EQ(m_proexpressionBar->findChild()->cursorPosition(), 0); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, moveRight) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("1+2"); m_proexpressionBar->findChild()->setCursorPosition(0); m_proexpressionBar->moveRight(); m_proexpressionBar->findChild()->setText("and2"); m_proexpressionBar->findChild()->setCursorPosition(0); m_proexpressionBar->moveRight(); m_proexpressionBar->moveRight(); EXPECT_EQ(m_proexpressionBar->findChild()->cursorPosition(), 4); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, initTheme) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->initTheme(2); EXPECT_EQ(m_proexpressionBar->findChild()->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text), "#b4b4b4"); m_proexpressionBar->initTheme(1); EXPECT_EQ(m_proexpressionBar->findChild()->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text), "#303030"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, revisionResults) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_proexpressionBar->revisionResults(m_proexpressionBar->m_listModel->index(0, 0)); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "1+2"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, addUndo) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->m_inputEdit->setText("110,911"); m_proexpressionBar->addUndo(); EXPECT_EQ(m_proexpressionBar->m_undo.at(0), "110,911"); EXPECT_TRUE(m_proexpressionBar->m_redo.isEmpty()); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, Undo) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->Undo(); m_proexpressionBar->findChild()->setText("1"); m_proexpressionBar->m_isResult = true; m_proexpressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_proexpressionBar->m_undo.append("1"); m_proexpressionBar->Undo(); EXPECT_TRUE(m_proexpressionBar->m_isAllClear); EXPECT_TRUE(m_proexpressionBar->m_isUndo); EXPECT_FALSE(m_proexpressionBar->m_isResult); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, Redo) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->Redo(); m_proexpressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_proexpressionBar->m_redo.append("1"); m_proexpressionBar->m_redo.append(""); m_proexpressionBar->Redo(); EXPECT_TRUE(m_proexpressionBar->m_isAllClear); EXPECT_TRUE(m_proexpressionBar->m_inputEdit->m_redo->isEnabled()); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, copyResultToClipboard) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->copyResultToClipboard(); m_proexpressionBar->findChild()->setText("1+2"); m_proexpressionBar->allElection(); m_proexpressionBar->copyResultToClipboard(); EXPECT_EQ(QApplication::clipboard()->text(), "1+2"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, copyClipboard2Result) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("huhuiandsjoi"); m_proexpressionBar->allElection(); m_proexpressionBar->copyResultToClipboard(); m_proexpressionBar->findChild()->setText("112+334"); SSelection select; select.curpos = 3; select.oldText = "112+334"; select.selected = "+"; m_proexpressionBar->findChild()->setSelection(select); m_proexpressionBar->findChild()->setCursorPosition(3); m_proexpressionBar->copyClipboard2Result(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "112and334"); m_proexpressionBar->enterClearEvent(); QApplication::clipboard()->setText("11+9"); Settings::instance()->programmerBase = 16; m_proexpressionBar->copyClipboard2Result(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "11+9"); m_proexpressionBar->enterClearEvent(); Settings::instance()->programmerBase = 8; m_proexpressionBar->copyClipboard2Result(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "11+"); m_proexpressionBar->enterClearEvent(); Settings::instance()->programmerBase = 2; m_proexpressionBar->copyClipboard2Result(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "11+"); m_proexpressionBar->enterClearEvent(); Settings::instance()->programmerBase = 0; m_proexpressionBar->copyClipboard2Result(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "11+9"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, allElection) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("123or321"); m_proexpressionBar->allElection(); EXPECT_EQ(m_proexpressionBar->m_inputEdit->getSelection().selected, "123or321"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, shear) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("1+2"); m_proexpressionBar->allElection(); m_proexpressionBar->shear(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), ""); EXPECT_FALSE(m_proexpressionBar->m_isResult); EXPECT_TRUE(m_proexpressionBar->m_isContinue); EXPECT_FALSE(m_proexpressionBar->m_isUndo); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, deleteText) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("1+2"); m_proexpressionBar->allElection(); m_proexpressionBar->deleteText(); EXPECT_EQ(m_proexpressionBar->findChild()->text(), ""); EXPECT_FALSE(m_proexpressionBar->m_isResult); EXPECT_TRUE(m_proexpressionBar->m_isContinue); EXPECT_FALSE(m_proexpressionBar->m_isUndo); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, setResultFalse) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->setResultFalse(); EXPECT_FALSE(m_proexpressionBar->m_isResult); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, replaceSelection) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("1111"); SSelection select; select.curpos = 2; select.oldText = "1,111"; select.selected = "1"; m_proexpressionBar->findChild()->setSelection(select); m_proexpressionBar->findChild()->setCursorPosition(2); m_proexpressionBar->replaceSelection("1,111"); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "111"); m_proexpressionBar->findChild()->setText("1%111"); SSelection select1; select1.curpos = 1; select1.oldText = "1.111"; select1.selected = "%"; m_proexpressionBar->findChild()->setSelection(select1); m_proexpressionBar->findChild()->setCursorPosition(1); m_proexpressionBar->replaceSelection("1%111"); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "1,111"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, isNumberOutOfRange) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); Settings::instance()->programmerBase = 10; m_proexpressionBar->findChild()->setText("9,223,372,036,854,775,807"); EXPECT_TRUE(m_proexpressionBar->isNumberOutOfRange("1")); Settings::instance()->proBitLength = 32; m_proexpressionBar->findChild()->setText("2147483647"); EXPECT_TRUE(m_proexpressionBar->isNumberOutOfRange("1")); Settings::instance()->proBitLength = 16; m_proexpressionBar->findChild()->setText("32767"); EXPECT_TRUE(m_proexpressionBar->isNumberOutOfRange("1")); Settings::instance()->proBitLength = 8; m_proexpressionBar->findChild()->setText("127"); EXPECT_TRUE(m_proexpressionBar->isNumberOutOfRange("1")); Settings::instance()->proBitLength = 64; Settings::instance()->programmerBase = 0; delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, selectedPartDelete) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->findChild()->setText("111and22"); SSelection select1; select1.curpos = 2; select1.oldText = "111and22"; select1.selected = "1an"; m_proexpressionBar->m_inputEdit->setSelection(select1); QString sRegNum = "[a-z]"; QRegExp rx; rx.setPattern(sRegNum); m_proexpressionBar->selectedPartDelete(rx); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "1,122"); m_proexpressionBar->findChild()->setText("1and2or3"); select1.curpos = 3; select1.oldText = "1and2or3"; select1.selected = "d2o"; m_proexpressionBar->m_inputEdit->setSelection(select1); m_proexpressionBar->selectedPartDelete(rx); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "13"); m_proexpressionBar->findChild()->setText("12or3"); select1.curpos = 3; select1.oldText = "12or3"; select1.selected = "r3"; m_proexpressionBar->m_inputEdit->setSelection(select1); m_proexpressionBar->selectedPartDelete(rx); EXPECT_EQ(m_proexpressionBar->findChild()->text(), "12"); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, handleTextChanged) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); m_proexpressionBar->handleTextChanged(); EXPECT_FALSE(m_proexpressionBar->m_isAllClear); EXPECT_TRUE(m_proexpressionBar->m_isContinue); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, isOperator) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); EXPECT_TRUE(m_proexpressionBar->isOperator(QString::fromUtf8("×"))); delete m_proexpressionBar; } TEST_F(Ut_ProexpressionBar, symbolFaultTolerance) { ProExpressionBar *m_proexpressionBar = new ProExpressionBar(); QString str = m_proexpressionBar->symbolFaultTolerance("123+-"); EXPECT_EQ(str, "123-"); delete m_proexpressionBar; } deepin-calculator-5.7.21/tests/src/widgets/ut_proexpressionbar.h000066400000000000000000000004501423020056600250630ustar00rootroot00000000000000#ifndef UT_PROEXPRESSIONBAR_H #define UT_PROEXPRESSIONBAR_H #include #include #include #include "../../src/dsettings.h" class Ut_ProexpressionBar : public ::testing::Test { public: Ut_ProexpressionBar(); }; #endif // UT_PROEXPRESSIONBAR_H deepin-calculator-5.7.21/tests/src/widgets/ut_programmodule.cpp000066400000000000000000001142301423020056600246700ustar00rootroot00000000000000#include #include "ut_programmodule.h" #include "../../src/widgets/programmodule.h" #include "../../3rdparty/core/settings.h" #include Ut_ProgramModule::Ut_ProgramModule() { } TEST_F(Ut_ProgramModule, Signals) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->m_proExpressionBar->getInputEdit()->cursorPositionNumberChanged("1"); EXPECT_EQ(m_programmodule->m_proSystemKeypad->m_binaryValue.back(), "1"); QPair pair = {false, Quantity(1)}; m_programmodule->m_proExpressionBar->getInputEdit()->prolistAns(pair); EXPECT_EQ(m_programmodule->m_proListModel->m_expressionList.at(0), ""); QPair pair1 = {true, Quantity(1)}; m_programmodule->m_proExpressionBar->getInputEdit()->prolistAns(pair1); EXPECT_EQ(m_programmodule->m_proListModel->m_expressionList.at(0), "1"); m_programmodule->m_proExpressionBar->getInputEdit()->emptyExpression(true); EXPECT_FALSE(m_programmodule->m_memCalbtn); m_programmodule->m_proExpressionBar->getInputEdit()->emptyExpression(false); EXPECT_TRUE(m_programmodule->m_memCalbtn); m_programmodule->m_memorylistwidget->widgetplus(0); EXPECT_TRUE(m_programmodule->m_memoryPublic->isEmpty()); m_programmodule->m_memorylistwidget->widgetminus(0); EXPECT_TRUE(m_programmodule->m_memoryPublic->isEmpty()); m_programmodule->m_memoryPublic->generateData(Quantity(1)); m_programmodule->m_memoryPublic->memoryclean(); EXPECT_TRUE(m_programmodule->m_memoryPublic->isEmpty()); m_programmodule->m_stackWidget->setCurrentIndex(2); QPair pair2 = {"1", Quantity(1)}; m_programmodule->m_memorylistwidget->itemclick(pair2); EXPECT_TRUE(m_programmodule->m_memCalbtn); EXPECT_FALSE(m_programmodule->m_isallgray); EXPECT_EQ(m_programmodule->m_proExpressionBar->getInputEdit()->text(), "1"); m_programmodule->m_memorylistwidget->hideWidget(); EXPECT_FALSE(m_programmodule->m_isallgray); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, Signals1) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->m_checkBtnKeypad->buttonPressed(38); m_programmodule->m_checkBtnKeypad->buttonPressedbySpace(38); m_programmodule->m_programmerKeypad->buttonPressed(26); m_programmodule->m_programmerKeypad->buttonPressedbySpace(26); m_programmodule->m_proSystemKeypad->bitbuttonclicked(); EXPECT_EQ(m_programmodule->findChild()->text(), "11"); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, Signals2) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->m_proSystemKeypad->longbitcut(Quantity(1)); EXPECT_TRUE(m_programmodule->m_proExpressionBar->findChild()->m_expressionList.isEmpty()); m_programmodule->m_byteArrowListWidget->focus(1); EXPECT_EQ(m_programmodule->m_byteArrowListWidget->currentRow(), 1); m_programmodule->m_byteArrowListWidget->focus(0); EXPECT_EQ(m_programmodule->m_byteArrowListWidget->currentRow(), 0); m_programmodule->m_shiftArrowListWidget->focus(1); EXPECT_EQ(m_programmodule->m_shiftArrowListWidget->currentRow(), 1); m_programmodule->m_shiftArrowListWidget->focus(0); EXPECT_EQ(m_programmodule->m_shiftArrowListWidget->currentRow(), 0); m_programmodule->m_byteArrowRectangle->hidearrowrectangle(); EXPECT_TRUE(m_programmodule->m_byteArrowRectangle->isHidden()); m_programmodule->m_shiftArrowRectangle->hidearrowrectangle(); EXPECT_TRUE(m_programmodule->m_shiftArrowRectangle->isHidden()); Settings::instance()->programmerBase = 0; Settings::instance()->proBitLength = 64; m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, setKeyPress) { ProgramModule *m_programmodule = new ProgramModule; QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier); m_programmodule->setKeyPress(k); EXPECT_EQ(m_programmodule->findChild()->text(), "1"); delete k; m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, mAvailableEvent) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->mAvailableEvent(); EXPECT_TRUE(m_programmodule->m_avail); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, mUnAvailableEvent) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->mUnAvailableEvent(); EXPECT_FALSE(m_programmodule->m_avail); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, showListWidget) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->showListWidget(); EXPECT_TRUE(m_programmodule->m_isallgray); EXPECT_EQ(m_programmodule->m_stackWidget->currentIndex(), 2); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, closeListWidget) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->m_stackWidget->setCurrentIndex(2); m_programmodule->m_insidewidget = false; m_programmodule->closeListWidget(); EXPECT_EQ(m_programmodule->m_stackWidget->currentIndex(), 0); EXPECT_FALSE(m_programmodule->m_isallgray); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, handleEditKeyPress) { ProgramModule *m_programmodule = new ProgramModule; Settings::instance()->programmerBase = 16; QTest::keyClick(m_programmodule->findChild(), Qt::Key_0, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_1, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_2, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_3, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_4, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_5, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_6, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_7, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_8, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_9, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_A, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_B, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_C, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_D, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_E, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_F, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Plus, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Minus, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Underscore, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Asterisk, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Slash, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Enter, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Return, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Equal, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Backspace, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Period, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Escape, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_ParenLeft, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_ParenRight, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Percent, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_AsciiCircum, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Ampersand, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Backslash, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Bar, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_AsciiTilde, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_C, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_V, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_V, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_A, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_X, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_X, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Delete, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Left, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Right, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Z, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Y, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Y, Qt::NoModifier); m_programmodule->m_avail = true; QTest::keyClick(m_programmodule->findChild(), Qt::Key_L, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_L, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_L, Qt::NoModifier); m_programmodule->m_avail = true; QTest::keyClick(m_programmodule->findChild(), Qt::Key_R, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_R, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_R, Qt::NoModifier); m_programmodule->m_memCalbtn = true; m_programmodule->findChild()->setText("1"); QTest::keyClick(m_programmodule->findChild(), Qt::Key_P, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_P, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Q, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Q, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_M, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_M, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_NumberSign, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_N, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_N, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_At, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_B, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Bar, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_E, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_E, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_S, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_S, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_O, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_O, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_T, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_T, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_J, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_J, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Exclam, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Escape, Qt::NoModifier); //函数中输入 QTest::mouseClick(m_programmodule->findChild()->button(ProgrammerKeypad::Key_AND), Qt::LeftButton); m_programmodule->findChild()->setCursorPosition(1); QTest::keyClick(m_programmodule->findChild(), Qt::Key_0, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_1, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_2, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_3, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_4, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_5, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_6, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_7, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_8, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_9, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_A, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_B, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_C, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_D, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_E, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_F, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Plus, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Minus, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Underscore, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Asterisk, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Slash, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Period, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_ParenLeft, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_ParenRight, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Percent, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_AsciiCircum, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_X, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Y, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_L, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_L, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_R, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_R, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_P, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Q, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_M, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_NumberSign, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_N, Qt::ControlModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_N, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_At, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_B, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Bar, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_E, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_E, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_S, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_S, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_O, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_O, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_T, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_T, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_J, Qt::ShiftModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_J, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Exclam, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_W, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Escape, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_1, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Plus, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_1, Qt::NoModifier); QTest::keyClick(m_programmodule->findChild(), Qt::Key_Equal, Qt::NoModifier); EXPECT_EQ(m_programmodule->findChild()->text(), "2"); Settings::instance()->programmerBase = 0; m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, handleKeypadButtonPress) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->handleKeypadButtonPress(ProCheckBtnKeypad::Key_BinaryKeypad); m_programmodule->handleKeypadButtonPress(ProCheckBtnKeypad::Key_GeneralKeypad); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_0); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_1); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_2); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_3); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_4); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_5); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_6); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_7); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_8); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_9); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Plus); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Min); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Mult); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Div); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_percent); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveL); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveR); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Clear); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Backspace); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_opposite); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_leftBracket); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_rightBracket); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_OR); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_XOR); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_NAND); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_NOR); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_NOT); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Clear); m_programmodule->findChild()->setText("1"); m_programmodule->handleKeypadButtonPress(ProCheckBtnKeypad::Key_BinaryKeypad); m_programmodule->handleKeypadButtonPress(ProCheckBtnKeypad::Key_GeneralKeypad); m_programmodule->handleKeypadButtonPress(ProCheckBtnKeypad::Key_System); m_programmodule->handleKeypadButtonPress(ProCheckBtnKeypad::Key_Option); m_programmodule->handleKeypadButtonPress(ProCheckBtnKeypad::Key_MS); //函数中输入 m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Clear); QTest::mouseClick(m_programmodule->findChild()->button(ProgrammerKeypad::Key_AND), Qt::LeftButton); m_programmodule->findChild()->setCursorPosition(1); Settings::instance()->programmerBase = 16; m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_0); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_1); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_2); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_3); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_4); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_5); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_6); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_7); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_8); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_9); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_A); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_B); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_C); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_D); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_E); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_F); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Plus); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Min); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Mult); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Div); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_percent); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveL); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveR); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Clear); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Backspace); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_opposite); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_leftBracket); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_rightBracket); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Clear); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_1); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_Plus); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_3); m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_equal); m_programmodule->handleKeypadButtonPress(ProCheckBtnKeypad::Key_MS); m_programmodule->handleKeypadButtonPress(ProCheckBtnKeypad::Key_Mlist); EXPECT_EQ(m_programmodule->findChild()->text(), "4"); Settings::instance()->programmerBase = 0; m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, handleKeypadButtonPressByspace) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_0); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_1); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_2); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_3); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_4); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_5); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_6); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_7); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_8); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_9); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Plus); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Min); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Mult); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Div); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_percent); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveL); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveR); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Clear); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Backspace); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_opposite); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_leftBracket); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_rightBracket); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_OR); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_XOR); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_NAND); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_NOR); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_NOT); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Clear); m_programmodule->findChild()->setText("1"); m_programmodule->handleKeypadButtonPressByspace(ProCheckBtnKeypad::Key_BinaryKeypad); m_programmodule->handleKeypadButtonPressByspace(ProCheckBtnKeypad::Key_GeneralKeypad); m_programmodule->handleKeypadButtonPressByspace(ProCheckBtnKeypad::Key_System); m_programmodule->handleKeypadButtonPressByspace(ProCheckBtnKeypad::Key_Option); m_programmodule->handleKeypadButtonPressByspace(ProCheckBtnKeypad::Key_MS); //函数中输入 m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Clear); QTest::mouseClick(m_programmodule->findChild()->button(ProgrammerKeypad::Key_AND), Qt::LeftButton); m_programmodule->findChild()->setCursorPosition(1); Settings::instance()->programmerBase = 16; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_0); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_1); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_2); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_3); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_4); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_5); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_6); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_7); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_8); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_9); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_A); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_B); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_C); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_D); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_E); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_F); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Plus); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Min); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Mult); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Div); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_percent); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveL); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveR); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Clear); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Backspace); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_opposite); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_leftBracket); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_rightBracket); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Clear); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_1); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_Plus); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_3); m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_equal); m_programmodule->handleKeypadButtonPressByspace(ProCheckBtnKeypad::Key_MS); m_programmodule->handleKeypadButtonPressByspace(ProCheckBtnKeypad::Key_Mlist); EXPECT_EQ(m_programmodule->findChild()->text(), "4"); Settings::instance()->programmerBase = 0; m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, moveL) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->m_shiftArrowCurrentRow = 0; m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveL); m_programmodule->m_shiftArrowCurrentRow = 1; m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveL); m_programmodule->m_shiftArrowCurrentRow = 2; m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveL); m_programmodule->m_shiftArrowCurrentRow = 3; m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveL); EXPECT_EQ(m_programmodule->m_proExpressionBar->getInputEdit()->text(), "0rcl"); m_programmodule->m_proExpressionBar->enterClearEvent(); m_programmodule->m_shiftArrowCurrentRow = 0; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveL); m_programmodule->m_shiftArrowCurrentRow = 1; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveL); m_programmodule->m_shiftArrowCurrentRow = 2; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveL); m_programmodule->m_shiftArrowCurrentRow = 3; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveL); EXPECT_EQ(m_programmodule->m_proExpressionBar->getInputEdit()->text(), "0rcl"); m_programmodule->m_proExpressionBar->enterClearEvent(); m_programmodule->m_shiftArrowCurrentRow = 0; QTest::keyClick(m_programmodule->findChild(), Qt::Key_Less, Qt::NoModifier); m_programmodule->m_shiftArrowCurrentRow = 1; QTest::keyClick(m_programmodule->findChild(), Qt::Key_Less, Qt::NoModifier); m_programmodule->m_shiftArrowCurrentRow = 2; QTest::keyClick(m_programmodule->findChild(), Qt::Key_Less, Qt::NoModifier); m_programmodule->m_shiftArrowCurrentRow = 3; QTest::keyClick(m_programmodule->findChild(), Qt::Key_Less, Qt::NoModifier); EXPECT_EQ(m_programmodule->m_proExpressionBar->getInputEdit()->text(), "0rcl"); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, moveR) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->m_shiftArrowCurrentRow = 0; m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveR); m_programmodule->m_shiftArrowCurrentRow = 1; m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveR); m_programmodule->m_shiftArrowCurrentRow = 2; m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveR); m_programmodule->m_shiftArrowCurrentRow = 3; m_programmodule->handleKeypadButtonPress(ProgrammerKeypad::Key_moveR); EXPECT_EQ(m_programmodule->m_proExpressionBar->getInputEdit()->text(), "0rcr"); m_programmodule->m_proExpressionBar->enterClearEvent(); m_programmodule->m_shiftArrowCurrentRow = 0; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveR); m_programmodule->m_shiftArrowCurrentRow = 1; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveR); m_programmodule->m_shiftArrowCurrentRow = 2; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveR); m_programmodule->m_shiftArrowCurrentRow = 3; m_programmodule->handleKeypadButtonPressByspace(ProgrammerKeypad::Key_moveR); EXPECT_EQ(m_programmodule->m_proExpressionBar->getInputEdit()->text(), "0rcr"); m_programmodule->m_proExpressionBar->enterClearEvent(); m_programmodule->m_shiftArrowCurrentRow = 0; QTest::keyClick(m_programmodule->findChild(), Qt::Key_Greater, Qt::NoModifier); m_programmodule->m_shiftArrowCurrentRow = 1; QTest::keyClick(m_programmodule->findChild(), Qt::Key_Greater, Qt::NoModifier); m_programmodule->m_shiftArrowCurrentRow = 2; QTest::keyClick(m_programmodule->findChild(), Qt::Key_Greater, Qt::NoModifier); m_programmodule->m_shiftArrowCurrentRow = 3; QTest::keyClick(m_programmodule->findChild(), Qt::Key_Greater, Qt::NoModifier); EXPECT_EQ(m_programmodule->m_proExpressionBar->getInputEdit()->text(), "0rcr"); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, shiftArrowListWidgetItemClicked) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->shiftArrowListWidgetItemSpace(); m_programmodule->shiftArrowListWidgetItemClicked(3, false); EXPECT_EQ(m_programmodule->m_shiftArrowCurrentRow, 3); m_programmodule->m_proListView->testAttribute(Qt::WA_TransparentForMouseEvents); m_programmodule->shiftArrowListWidgetItemClicked(0, false); EXPECT_EQ(m_programmodule->m_shiftArrowCurrentRow, 0); m_programmodule->m_proListView->testAttribute(Qt::WA_TransparentForMouseEvents); m_programmodule->shiftArrowListWidgetItemClicked(1, false); EXPECT_EQ(m_programmodule->m_shiftArrowCurrentRow, 1); m_programmodule->m_proListView->testAttribute(Qt::WA_TransparentForMouseEvents); m_programmodule->shiftArrowListWidgetItemClicked(2, false); m_programmodule->m_proListView->testAttribute(Qt::WA_TransparentForMouseEvents); EXPECT_EQ(m_programmodule->m_shiftArrowCurrentRow, 2); m_programmodule->shiftArrowListWidgetItemPressed(0); EXPECT_EQ(m_programmodule->m_shiftArrowPressRow, 0); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, byteArrowListWidgetItemClicked) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->byteArrowListWidgetItemSpace(); m_programmodule->byteArrowListWidgetItemClicked(3, false); EXPECT_EQ(Settings::instance()->proBitLength, 8); m_programmodule->byteArrowListWidgetItemClicked(0, false); EXPECT_EQ(Settings::instance()->proBitLength, 64); m_programmodule->byteArrowListWidgetItemClicked(1, false); EXPECT_EQ(Settings::instance()->proBitLength, 32); m_programmodule->byteArrowListWidgetItemClicked(2, false); m_programmodule->m_proListView->testAttribute(Qt::WA_TransparentForMouseEvents); EXPECT_EQ(Settings::instance()->proBitLength, 16); m_programmodule->byteArrowListWidgetItemPressed(0); EXPECT_EQ(m_programmodule->m_byteArrowPressRow, 0); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, handleClearStateChanged) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->handleClearStateChanged(true); EXPECT_EQ(m_programmodule->findChild()->button(ProgrammerKeypad::Key_Clear)->text(), "AC"); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, mousePressEvent) { ProgramModule *m_programmodule = new ProgramModule; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseButtonPress, m_programmodule->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::LeftButton, Qt::KeyboardModifier::NoModifier); m_programmodule->mousePressEvent(m); EXPECT_FALSE(m_programmodule->m_insidewidget); delete m; m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, setwidgetAttribute) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->setwidgetAttribute(false); EXPECT_FALSE(m_programmodule->m_proExpressionBar->testAttribute(Qt::WA_TransparentForMouseEvents)); m_programmodule->deleteLater(); } TEST_F(Ut_ProgramModule, checkBtnKeypadThemeChange) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->checkBtnKeypadThemeChange(1); EXPECT_EQ(static_cast(m_programmodule->m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))->m_currentUrl, ":/assets/images/light/icon_generalkeyboard_normal.svg"); m_programmodule->checkBtnKeypadThemeChange(2); EXPECT_EQ(static_cast(m_programmodule->m_checkBtnKeypad->button(ProCheckBtnKeypad::Key_GeneralKeypad))->m_currentUrl, ":/assets/images/dark/icon_generalkeyboard_normal.svg"); m_programmodule->deleteLater(); } int stub_model_pro() { return 1; } TEST_F(Ut_ProgramModule, radixListChange) { ProgramModule *m_programmodule = new ProgramModule; m_programmodule->m_proExpressionBar->getInputEdit()->setText("12"); Stub stub; stub.set(ADDR(QModelIndex, row), stub_model_pro); m_programmodule->radixListChange(QModelIndex(), false); EXPECT_EQ(Settings::instance()->programmerBase, 10); Settings::instance()->programmerBase = 0; m_programmodule->deleteLater(); } deepin-calculator-5.7.21/tests/src/widgets/ut_programmodule.h000066400000000000000000000006051423020056600243350ustar00rootroot00000000000000#ifndef UT_PROGRAMMODULE_H #define UT_PROGRAMMODULE_H #include #include #include #include "../../src/memorypublic.h" #include "../../src/dsettings.h" #include "../stub.h" #include "../3rdparty/core/settings.h" class Ut_ProgramModule : public ::testing::Test { public: Ut_ProgramModule(); protected: }; #endif // UT_PROGRAMMODULE_H deepin-calculator-5.7.21/tests/src/widgets/ut_scientificmodule.cpp000066400000000000000000001102471423020056600253450ustar00rootroot00000000000000#include "ut_scientificmodule.h" #include #include "../../src/widgets/scientificmodule.h" #include "../../src/views/memoryitemwidget.h" #include "../../src/memorypublic.h" Ut_ScientificModule::Ut_ScientificModule() { } TEST_F(Ut_ScientificModule, signals1) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->m_memhiswidget->hisIsFilled(true); EXPECT_TRUE(m_scientificModule->m_havail); m_scientificModule->m_memoryPublic->memoryclean(); m_scientificModule->m_memoryPublic->generateData(Quantity(1)); EXPECT_TRUE(m_scientificModule->m_memRCbtn); EXPECT_TRUE(m_scientificModule->m_avail); m_scientificModule->m_memhiswidget->m_memoryWidget->widgetminus(0); EXPECT_FALSE(m_scientificModule->m_memoryPublic->isEmpty()); m_scientificModule->m_memhiswidget->m_memoryWidget->widgetplus(0); EXPECT_FALSE(m_scientificModule->m_memoryPublic->isEmpty()); m_scientificModule->m_memhiswidget->m_memoryWidget->itemclick({"1", Quantity(1)}); EXPECT_EQ(m_scientificModule->m_sciexpressionBar->getInputEdit()->text(), "1"); m_scientificModule->deleteLater(); } bool stub_geometry_contains(const QPoint &p, bool proper = false) { Q_UNUSED(p); proper = false; return false; } TEST_F(Ut_ScientificModule, mousePressEvent) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->m_stackWidget->setCurrentWidget(m_scientificModule->m_memhiswidget); Stub stub; stub.set((bool (QRect::*)(const QPoint &, bool) const)ADDR(QRect, contains), stub_geometry_contains); QMouseEvent *m = new QMouseEvent(QEvent::MouseButtonPress, m_scientificModule->findChild()->pos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); m_scientificModule->mousePressEvent(m); EXPECT_EQ(m_scientificModule->m_stackWidget->currentWidget(), m_scientificModule->m_scikeypadwidget); delete m; m_scientificModule->deleteLater(); } TEST_F(Ut_ScientificModule, setKeyPress) { scientificModule *m_scientificModule = new scientificModule; QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier); m_scientificModule->setKeyPress(k); EXPECT_EQ(m_scientificModule->findChild()->text(), "1"); delete k; m_scientificModule->deleteLater(); } TEST_F(Ut_ScientificModule, checkLineEmpty) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->checkLineEmpty(); EXPECT_FALSE(m_scientificModule->m_memCalbtn); m_scientificModule->findChild()->setText("1"); m_scientificModule->checkLineEmpty(); EXPECT_TRUE(m_scientificModule->m_memCalbtn); m_scientificModule->deleteLater(); } TEST_F(Ut_ScientificModule, mAvailableEvent) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->mAvailableEvent(); EXPECT_TRUE(m_scientificModule->m_memRCbtn); EXPECT_TRUE(m_scientificModule->m_avail); EXPECT_TRUE(static_cast(m_scientificModule->m_memhiskeypad->button(MemHisKeypad::Key_MC))->isEnabled()); EXPECT_TRUE(static_cast(m_scientificModule->m_memhiskeypad->button(MemHisKeypad::Key_MR))->isEnabled()); EXPECT_TRUE(static_cast(m_scientificModule->m_memhiskeypad->button(MemHisKeypad::Key_MHlist))->isEnabled()); m_scientificModule->deleteLater(); } TEST_F(Ut_ScientificModule, mUnAvailableEvent) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->mUnAvailableEvent(); EXPECT_FALSE(m_scientificModule->m_memRCbtn); EXPECT_FALSE(m_scientificModule->m_avail); EXPECT_FALSE(static_cast(m_scientificModule->m_memhiskeypad->button(MemHisKeypad::Key_MC))->isEnabled()); EXPECT_FALSE(static_cast(m_scientificModule->m_memhiskeypad->button(MemHisKeypad::Key_MR))->isEnabled()); m_scientificModule->deleteLater(); } TEST_F(Ut_ScientificModule, initTheme) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->initTheme(1); EXPECT_EQ(m_scientificModule->findChild()->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text), "#303030"); m_scientificModule->initTheme(2); EXPECT_EQ(m_scientificModule->findChild()->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text), "#b4b4b4"); m_scientificModule->deleteLater(); } TEST_F(Ut_ScientificModule, handleEditKeyPress) { scientificModule *m_scientificModule = new scientificModule; QTest::keyClick(m_scientificModule->findChild(), Qt::Key_0, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_1, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_2, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_3, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_4, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_5, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_6, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_7, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_8, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_9, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Plus, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Minus, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Underscore, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Asterisk, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Slash, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Enter, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Return, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Equal, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Backspace, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Period, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Escape, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_ParenLeft, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_ParenRight, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Percent, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_AsciiCircum, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_C, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_V, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_V, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_A, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_X, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_X, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Delete, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Left, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Right, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Z, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Y, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Y, Qt::NoModifier); m_scientificModule->m_memRCbtn = true; QTest::keyClick(m_scientificModule->findChild(), Qt::Key_L, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_L, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_L, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_R, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_R, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_R, Qt::NoModifier); m_scientificModule->m_memCalbtn = true; m_scientificModule->findChild()->setText("1"); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_P, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_P, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Q, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Q, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_M, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_M, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_NumberSign, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_N, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_N, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_At, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_B, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Bar, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_E, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_E, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_S, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_S, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_O, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_O, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_T, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_T, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_J, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_J, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Exclam, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Escape, Qt::NoModifier); //函数中输入 QTest::mouseClick(m_scientificModule->findChild()->button(ScientificKeyPad::Key_sin), Qt::LeftButton); m_scientificModule->findChild()->setCursorPosition(1); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_0, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_1, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_2, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_3, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_4, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_5, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_6, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_7, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_8, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_9, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Plus, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Minus, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Underscore, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Asterisk, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Slash, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_ParenLeft, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_ParenRight, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Slash, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Percent, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_AsciiCircum, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_X, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Y, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_L, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_L, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_R, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_R, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_P, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Q, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_M, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_NumberSign, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_N, Qt::ControlModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_N, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_At, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_B, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Bar, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_E, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_E, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_S, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_S, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_O, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_O, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_T, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_T, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_J, Qt::ShiftModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_J, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Exclam, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_W, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Escape, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_1, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Plus, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_1, Qt::NoModifier); QTest::keyClick(m_scientificModule->findChild(), Qt::Key_Equal, Qt::NoModifier); EXPECT_EQ(m_scientificModule->findChild()->text(), "2"); m_scientificModule->deleteLater(); } TEST_F(Ut_ScientificModule, handleKeypadButtonPress) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_0); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_1); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_2); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_3); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_4); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_5); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_6); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_7); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_8); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_9); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Plus); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Min); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Mult); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Div); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Percent); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Equals); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Clear); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Backspace); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Point); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_left); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_right); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Clear); m_scientificModule->findChild()->setText("1"); m_scientificModule->handleKeypadButtonPress(MemHisKeypad::Key_MS); m_scientificModule->handleKeypadButtonPress(MemHisKeypad::Key_MC); m_scientificModule->handleKeypadButtonPress(MemHisKeypad::Key_Mplus); m_scientificModule->handleKeypadButtonPress(MemHisKeypad::Key_Mmin); m_scientificModule->handleKeypadButtonPress(MemHisKeypad::Key_MR); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_deg); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_deg); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_deg); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_sin); m_scientificModule->handleKeypadButtonPress(MemHisKeypad::Key_FE); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_page); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_PI); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_e); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Mod); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_x2); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Derivative); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Factorials); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_exp); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_cos); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_x3); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_tan); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_xy); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_cot); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_10x); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Modulus); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_log); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Rand); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_ln); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_arcsin); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_sqrt2); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_arccos); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_sqrt3); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_arctan); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_ysqrtx); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_arccot); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_2x); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_logyx); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_ex); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_opposite); m_scientificModule->handleKeypadButtonPress(84); //函数中输入 m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Clear); QTest::mouseClick(m_scientificModule->findChild()->button(ScientificKeyPad::Key_sin), Qt::LeftButton); m_scientificModule->findChild()->setCursorPosition(1); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_0); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_1); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_2); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_3); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_4); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_5); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_6); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_7); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_8); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_9); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Plus); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Min); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Mult); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Div); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Percent); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Point); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_left); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_right); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_sin); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_PI); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_e); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Mod); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_x2); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Derivative); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Factorials); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_exp); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_cos); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_x3); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_tan); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_xy); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_cot); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_10x); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Modulus); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_log); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_ln); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_arcsin); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_sqrt2); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_arccos); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_sqrt3); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_arctan); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_ysqrtx); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_arccot); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_2x); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_logyx); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_ex); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_opposite); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Clear); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_1); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Plus); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_1); m_scientificModule->handleKeypadButtonPress(ScientificKeyPad::Key_Equals); EXPECT_EQ(m_scientificModule->findChild()->text(), "2"); m_scientificModule->deleteLater(); } TEST_F(Ut_ScientificModule, handleKeypadButtonPressByspace) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_0); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_1); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_2); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_3); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_4); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_5); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_6); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_7); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_8); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_9); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Plus); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Min); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Mult); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Div); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Percent); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Equals); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Clear); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Backspace); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Point); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_left); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_right); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Clear); m_scientificModule->findChild()->setText("1"); m_scientificModule->handleKeypadButtonPressByspace(MemHisKeypad::Key_MS); m_scientificModule->handleKeypadButtonPressByspace(MemHisKeypad::Key_MC); m_scientificModule->handleKeypadButtonPressByspace(MemHisKeypad::Key_Mplus); m_scientificModule->handleKeypadButtonPressByspace(MemHisKeypad::Key_Mmin); m_scientificModule->handleKeypadButtonPressByspace(MemHisKeypad::Key_MR); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_deg); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_deg); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_deg); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_sin); m_scientificModule->handleKeypadButtonPressByspace(MemHisKeypad::Key_FE); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_page); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_page); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_PI); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_e); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Mod); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_x2); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Derivative); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Factorials); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_exp); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_cos); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_x3); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_tan); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_xy); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_cot); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_10x); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Modulus); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_log); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Rand); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_ln); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_arcsin); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_sqrt2); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_arccos); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_sqrt3); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_arctan); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_ysqrtx); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_arccot); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_2x); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_logyx); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_ex); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_opposite); //函数中输入 m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Clear); QTest::mouseClick(m_scientificModule->findChild()->button(ScientificKeyPad::Key_sin), Qt::LeftButton); m_scientificModule->findChild()->setCursorPosition(1); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_0); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_1); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_2); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_3); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_4); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_5); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_6); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_7); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_8); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_9); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Plus); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Min); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Mult); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Div); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Percent); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Point); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_left); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_right); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_sin); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_PI); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_e); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Mod); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_x2); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Derivative); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Factorials); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_exp); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_cos); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_x3); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_tan); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_xy); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_cot); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_10x); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Modulus); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_log); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_ln); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_arcsin); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_sqrt2); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_arccos); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_sqrt3); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_arctan); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_ysqrtx); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_arccot); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_2x); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_logyx); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_ex); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_opposite); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Clear); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_1); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Plus); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_1); m_scientificModule->handleKeypadButtonPressByspace(ScientificKeyPad::Key_Equals); EXPECT_EQ(m_scientificModule->findChild()->text(), "2"); m_scientificModule->deleteLater(); } TEST_F(Ut_ScientificModule, hideMemHisWidget) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->m_avail = true; m_scientificModule->hideMemHisWidget(); EXPECT_FALSE(m_scientificModule-> m_isallgray); EXPECT_TRUE(m_scientificModule-> m_memRCbtn); m_scientificModule->m_avail = false; m_scientificModule->hideMemHisWidget(); EXPECT_EQ(m_scientificModule->m_stackWidget->currentWidget(), m_scientificModule->m_scikeypadwidget); EXPECT_FALSE(m_scientificModule-> m_memRCbtn); m_scientificModule->deleteLater(); } int stub_model_sci() { return 0; } TEST_F(Ut_ScientificModule, clickListView) { scientificModule *m_scientificModule = new scientificModule; m_scientificModule->m_sciexpressionBar->getInputEdit()->setText("1+1"); QKeyEvent *k = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); m_scientificModule->handleEditKeyPress(k); Stub stub; stub.set(ADDR(QModelIndex, row), stub_model_sci); m_scientificModule->clickListView(QModelIndex()); EXPECT_EQ(m_scientificModule->m_sciexpressionBar->getInputEdit()->text(), "2"); delete k; m_scientificModule->deleteLater(); } deepin-calculator-5.7.21/tests/src/widgets/ut_scientificmodule.h000066400000000000000000000004741423020056600250120ustar00rootroot00000000000000#ifndef UT_SCIENTIFICMODULE_H #define UT_SCIENTIFICMODULE_H #include #include #include #include "../../src/dsettings.h" #include"../stub.h" class Ut_ScientificModule : public ::testing::Test { public: Ut_ScientificModule(); }; #endif // UT_SCIENTIFICMODULE_H deepin-calculator-5.7.21/tests/src/widgets/ut_sciexpressionbar.cpp000066400000000000000000000715001423020056600254000ustar00rootroot00000000000000#include "ut_sciexpressionbar.h" #include #include "../../src/widgets/sciexpressionbar.h" Ut_SciexpressionBar::Ut_SciexpressionBar() { } TEST_F(Ut_SciexpressionBar, mouseMoveEvent) { SciExpressionBar *m_sciexpressionBar = new SciExpressionBar; QMouseEvent *m = new QMouseEvent(QMouseEvent::Type::MouseMove, m_sciexpressionBar->pos(), Qt::MouseButton::LeftButton, Qt::MouseButton::NoButton, Qt::KeyboardModifier::NoModifier); m_sciexpressionBar->mouseMoveEvent(m); delete m; //取消mousemove的事件,无assert delete m_sciexpressionBar; } TEST_F(Ut_SciexpressionBar, getanswer) { SciExpressionBar *m_sciexpressionBar = new SciExpressionBar; m_sciexpressionBar->m_pair.first = false; EXPECT_TRUE(m_sciexpressionBar->getanswer().isZero()); delete m_sciexpressionBar; } TEST_F(Ut_SciexpressionBar, enterNumberEvent) { SciExpressionBar *m_sciexpressionBar = new SciExpressionBar; m_sciexpressionBar->m_inputNumber = true; m_sciexpressionBar->m_isResult = true; m_sciexpressionBar->m_isContinue = false; m_sciexpressionBar->enterNumberEvent("1"); EXPECT_EQ(m_sciexpressionBar->m_inputEdit->text(), "1"); m_sciexpressionBar->m_inputNumber = false; m_sciexpressionBar->m_isResult = true; m_sciexpressionBar->enterNumberEvent("1"); EXPECT_EQ(m_sciexpressionBar->m_inputEdit->text(), "1"); m_sciexpressionBar->m_inputEdit->setText("π"); m_sciexpressionBar->enterNumberEvent("1"); EXPECT_EQ(m_sciexpressionBar->m_inputEdit->text(), "π×1"); EXPECT_FALSE(m_sciexpressionBar->m_inputNumber); EXPECT_FALSE(m_sciexpressionBar->m_isUndo); EXPECT_FALSE(m_sciexpressionBar->m_isResult); delete m_sciexpressionBar; } TEST_F(Ut_SciexpressionBar, enterSymbolEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; // m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); // m_expressionBar->findChild()->setText("3"); // m_expressionBar->m_isUndo = true; m_expressionBar->enterSymbolEvent("+"); m_expressionBar->findChild()->clear(); m_expressionBar->enterSymbolEvent("-"); m_expressionBar->enterSymbolEvent("-"); m_expressionBar->enterSymbolEvent("+"); EXPECT_EQ(m_expressionBar->findChild()->text(), "-"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->enterSymbolEvent("-"); m_expressionBar->findChild()->setText("1"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->enterSymbolEvent("-"); EXPECT_EQ(m_expressionBar->findChild()->text(), "-1"); m_expressionBar->findChild()->setText("1+2"); m_expressionBar->findChild()->setCursorPosition(1); m_expressionBar->enterSymbolEvent("-"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+2"); m_expressionBar->findChild()->setText("11"); m_expressionBar->findChild()->setCursorPosition(1); m_expressionBar->enterSymbolEvent("-"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1-1"); EXPECT_FALSE(m_expressionBar->m_isUndo); EXPECT_FALSE(m_expressionBar->m_isResult); EXPECT_TRUE(m_expressionBar->m_isContinue); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterPercentEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->enterPercentEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->enterPercentEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+1%"); m_expressionBar->findChild()->setCursorPosition(1); m_expressionBar->enterPercentEvent(); m_expressionBar->findChild()->setText("1111"); m_expressionBar->findChild()->setCursorPosition(1); m_expressionBar->enterPercentEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1%111"); m_expressionBar->findChild()->setText("1111"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterPercentEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1%111"); EXPECT_FALSE(m_expressionBar->m_isUndo); EXPECT_FALSE(m_expressionBar->m_isResult); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterPointEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->enterPointEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "0."); m_expressionBar->findChild()->setText("1"); m_expressionBar->enterPointEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1."); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterPointEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+0.1"); m_expressionBar->findChild()->setCursorPosition(4); m_expressionBar->enterPointEvent(); m_expressionBar->findChild()->setCursorPosition(5); m_expressionBar->enterPointEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+0.1"); EXPECT_FALSE(m_expressionBar->m_isUndo); EXPECT_FALSE(m_expressionBar->m_isResult); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterBackspaceEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("1+1"); m_expressionBar->allElection(); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); m_expressionBar->findChild()->setText("1.+1"); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1.+"); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1."); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1"); m_expressionBar->findChild()->clear(); m_expressionBar->enterFunctionEvent("sin"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "()"); m_expressionBar->enterFunctionEvent("sin"); SSelection select; select.curpos = 1; select.oldText = "sin()"; select.selected = "i"; m_expressionBar->findChild()->setSelection(select); m_expressionBar->enterBackspaceEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "()()"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterClearEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->m_isAllClear = false; m_expressionBar->findChild()->setText("1+1"); m_expressionBar->enterClearEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); EXPECT_FALSE(m_expressionBar->m_FEisdown); EXPECT_FALSE(m_expressionBar->m_isResult); EXPECT_FALSE(m_expressionBar->m_isUndo); EXPECT_TRUE(m_expressionBar->m_isAllClear); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterEqualEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); m_expressionBar->findChild()->setText("2log2"); m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1"); m_expressionBar->findChild()->setText("1"); m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1"); m_expressionBar->findChild()->setText("1÷3000"); m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "3.3333333333333333333333333333333E-4"); m_expressionBar->enterEqualEvent(); m_expressionBar->findChild()->setText("1+"); m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+"); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->m_FEisdown = true; m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "2E+0"); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->m_FEisdown = false; m_expressionBar->enterEqualEvent(); EXPECT_EQ(m_expressionBar->findChild()->text(), "2"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterLeftBracketsEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("3"); m_expressionBar->m_isUndo = true; m_expressionBar->enterBracketEvent(1); EXPECT_EQ(m_expressionBar->findChild()->text(), "3("); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->enterBracketEvent(1); EXPECT_EQ(m_expressionBar->findChild()->text(), "(3("); m_expressionBar->findChild()->setText("1111"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterBracketEvent(1); EXPECT_EQ(m_expressionBar->findChild()->text(), "1(111"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterRightBracketsEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("3"); m_expressionBar->m_isUndo = true; m_expressionBar->enterBracketEvent(2); EXPECT_EQ(m_expressionBar->findChild()->text(), "3)"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->enterBracketEvent(2); EXPECT_EQ(m_expressionBar->findChild()->text(), ")3)"); m_expressionBar->findChild()->setText("1111"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterBracketEvent(2); EXPECT_EQ(m_expressionBar->findChild()->text(), "1)111"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterFEEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->enterFEEvent(true); EXPECT_FALSE(m_expressionBar->m_FEisdown); m_expressionBar->enterFEEvent(false); EXPECT_TRUE(m_expressionBar->m_FEisdown); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterModEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->enterOperatorEvent("mod"); EXPECT_EQ(m_expressionBar->findChild()->text(), "0mod"); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->enterOperatorEvent("mod"); EXPECT_EQ(m_expressionBar->findChild()->text(), "0mod1+1"); m_expressionBar->findChild()->setCursorPosition(6); m_expressionBar->enterOperatorEvent("mod"); EXPECT_EQ(m_expressionBar->findChild()->text(), "0mod1+0mod1"); m_expressionBar->findChild()->setText("1^2"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterOperatorEvent("mod"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1^(0mod2"); m_expressionBar->findChild()->setText("1111"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterOperatorEvent("mod"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1mod111"); EXPECT_FALSE(m_expressionBar->m_isResult); EXPECT_FALSE(m_expressionBar->m_isUndo); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterx2Event) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->enterOperatorEvent("^2"); EXPECT_EQ(m_expressionBar->findChild()->text(), "0^2"); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->enterOperatorEvent("^2"); EXPECT_EQ(m_expressionBar->findChild()->text(), "0^2×1+1"); m_expressionBar->findChild()->setCursorPosition(6); m_expressionBar->enterOperatorEvent("^2"); EXPECT_EQ(m_expressionBar->findChild()->text(), "0^2×1+0^2×1"); m_expressionBar->findChild()->setText("1^2"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterOperatorEvent("^2"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1^(0^2×2"); m_expressionBar->findChild()->setText("1111"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterOperatorEvent("^2"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1^2×111"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterDerivativeEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->allElection(); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "1/("); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+1"); SSelection select; select.curpos = 0; select.oldText = "1+1"; select.selected = "1"; m_expressionBar->findChild()->setSelection(select); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+1"); m_expressionBar->findChild()->setText("1E-2"); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "1/(1E-2)"); m_expressionBar->findChild()->setText("-"); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "-"); m_expressionBar->findChild()->setText("()"); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "()"); m_expressionBar->findChild()->setText("((1))"); m_expressionBar->findChild()->setCursorPosition(4); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "(1/((1)))"); m_expressionBar->findChild()->setText("sin(2)"); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "1/(sin(2))"); m_expressionBar->findChild()->setText("1/(2)"); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "1/(1/(2))"); m_expressionBar->findChild()->setText("2(2)"); m_expressionBar->enterSpecialFuncEvent("1/("); EXPECT_EQ(m_expressionBar->findChild()->text(), "2×1/((2))"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterCosEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->enterFunctionEvent("cos"); EXPECT_EQ(m_expressionBar->findChild()->text(), "cos()"); m_expressionBar->findChild()->setText("1111"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterFunctionEvent("cos"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1cos()111"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enter10xEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("1"); m_expressionBar->enterConstantEvent("10^"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1×10^"); m_expressionBar->findChild()->setText("11"); m_expressionBar->findChild()->setCursorPosition(1); m_expressionBar->enterConstantEvent("10^"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1×10^1"); m_expressionBar->findChild()->setText("1111"); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->enterConstantEvent("10^"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1×10^111"); m_expressionBar->findChild()->setText("1+"); m_expressionBar->enterConstantEvent("10^"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+10^"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, enterModulusEvent) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "abs(0)"); m_expressionBar->findChild()->setText("E"); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "E"); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->allElection(); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "abs("); m_expressionBar->findChild()->setText("1+1"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+1"); SSelection select; select.curpos = 0; select.oldText = "1+1"; select.selected = "1"; m_expressionBar->findChild()->setSelection(select); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+1"); m_expressionBar->findChild()->setText("1E-2"); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "abs(1E-2)"); m_expressionBar->findChild()->setText("-"); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "-"); m_expressionBar->findChild()->setText("()"); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "()"); m_expressionBar->findChild()->setText("((1))"); m_expressionBar->findChild()->setCursorPosition(4); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "(abs((1)))"); m_expressionBar->findChild()->setText("sin(2)"); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "abs(sin(2))"); m_expressionBar->findChild()->setText("1/(2)"); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "abs(1/(2))"); m_expressionBar->findChild()->setText("2(2)"); m_expressionBar->enterSpecialFuncEvent("abs("); EXPECT_EQ(m_expressionBar->findChild()->text(), "2abs((2))"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, copyResultToClipboard) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->copyResultToClipboard(); m_expressionBar->findChild()->setText("1+2"); m_expressionBar->allElection(); m_expressionBar->copyResultToClipboard(); EXPECT_EQ(QApplication::clipboard()->text(), "1+2"); m_expressionBar->copyClipboard2Result(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+2"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, copyClipboard2Result) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("huhuisinsjoi"); m_expressionBar->allElection(); m_expressionBar->copyResultToClipboard(); m_expressionBar->copyClipboard2Result(); EXPECT_EQ(m_expressionBar->findChild()->text(), "sin"); m_expressionBar->findChild()->setText("1.2+3.4"); SSelection select; select.curpos = 3; select.oldText = "1.2+3.4"; select.selected = "+"; m_expressionBar->findChild()->setSelection(select); m_expressionBar->findChild()->setCursorPosition(3); m_expressionBar->copyClipboard2Result(); EXPECT_EQ(m_expressionBar->findChild()->text(), "1.2sin34"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, shear) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->allElection(); m_expressionBar->shear(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); EXPECT_FALSE(m_expressionBar->m_isResult); EXPECT_TRUE(m_expressionBar->m_isContinue); EXPECT_FALSE(m_expressionBar->m_isUndo); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, revisionResults) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->revisionResults(m_expressionBar->m_listModel->index(0, 0)); EXPECT_EQ(m_expressionBar->findChild()->text(), "1+2"); EXPECT_FALSE(m_expressionBar->m_isResult); EXPECT_FALSE(m_expressionBar->m_isUndo); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, hisRevisionResults) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->hisRevisionResults(m_expressionBar->m_listModel->index(0, 0), Quantity(3)); EXPECT_EQ(m_expressionBar->findChild()->text(), "3"); EXPECT_FALSE(m_expressionBar->m_isResult); EXPECT_FALSE(m_expressionBar->m_isUndo); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, judgeinput) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("sin"); SSelection select; select.curpos = 1; select.oldText = "sin"; select.selected = "i"; m_expressionBar->findChild()->setSelection(select); EXPECT_FALSE(m_expressionBar->judgeinput()); m_expressionBar->findChild()->setText("1sin"); SSelection select0; select0.curpos = 0; select0.oldText = "1sin"; select0.selected = "1"; m_expressionBar->findChild()->setSelection(select0); EXPECT_TRUE(m_expressionBar->judgeinput()); m_expressionBar->findChild()->setText("1sin"); SSelection select1; select1.curpos = 0; select1.oldText = "1sin"; select1.selected = "1s"; m_expressionBar->findChild()->setSelection(select1); EXPECT_FALSE(m_expressionBar->judgeinput()); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, symbolComplement) { SciExpressionBar *m_expressionBar = new SciExpressionBar; EXPECT_EQ(m_expressionBar->symbolComplement("1("), "1×("); EXPECT_EQ(m_expressionBar->symbolComplement(")1"), ")×1"); EXPECT_EQ(m_expressionBar->symbolComplement("e"), "(e)"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, pointFaultTolerance) { SciExpressionBar *m_expressionBar = new SciExpressionBar; EXPECT_EQ(m_expressionBar->pointFaultTolerance(")."), ")0."); EXPECT_EQ(m_expressionBar->pointFaultTolerance(".1"), "0.1"); EXPECT_EQ(m_expressionBar->pointFaultTolerance("1+.2"), "1+0.2"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, expressionCheck) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText(".1"); m_expressionBar->expressionCheck(); EXPECT_EQ(m_expressionBar->findChild()->text(), "0.1"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, Undo) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->Undo(); m_expressionBar->findChild()->setText("1"); m_expressionBar->m_isResult = true; m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->m_undo.append("1"); m_expressionBar->Undo(); EXPECT_TRUE(m_expressionBar->m_isAllClear); EXPECT_TRUE(m_expressionBar->m_isUndo); EXPECT_FALSE(m_expressionBar->m_isResult); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, Redo) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->Redo(); m_expressionBar->m_listModel->updataList(QString("1+2") + "=" + "3", -1); m_expressionBar->m_redo.append("1"); m_expressionBar->m_redo.append(""); m_expressionBar->Redo(); EXPECT_TRUE(m_expressionBar->m_isAllClear); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, initTheme) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->initTheme(1); EXPECT_EQ(m_expressionBar->findChild()->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text), "#303030"); m_expressionBar->initTheme(2); EXPECT_EQ(m_expressionBar->findChild()->palette().color(QPalette::ColorGroup::Active, QPalette::ColorRole::Text), "#b4b4b4"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, setResultFalse) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->setResultFalse(); EXPECT_FALSE(m_expressionBar->m_isResult); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, replaceSelection) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("1111"); SSelection select; select.curpos = 2; select.oldText = "1,111"; select.selected = "1"; m_expressionBar->findChild()->setSelection(select); m_expressionBar->findChild()->setCursorPosition(2); m_expressionBar->replaceSelection("1,111"); EXPECT_EQ(m_expressionBar->findChild()->text(), "111"); m_expressionBar->findChild()->setText("1.111"); SSelection select1; select1.curpos = 1; select1.oldText = "1.111"; select1.selected = "."; m_expressionBar->findChild()->setSelection(select1); m_expressionBar->findChild()->setCursorPosition(1); m_expressionBar->replaceSelection("1.111"); EXPECT_EQ(m_expressionBar->findChild()->text(), "1,111"); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, moveLeft) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->moveLeft(); EXPECT_EQ(m_expressionBar->findChild()->cursorPosition(), 2); m_expressionBar->findChild()->setText("sin2"); m_expressionBar->moveLeft(); EXPECT_EQ(m_expressionBar->findChild()->cursorPosition(), 3); m_expressionBar->moveLeft(); EXPECT_EQ(m_expressionBar->findChild()->cursorPosition(), 0); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, moveRight) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->moveRight(); EXPECT_EQ(m_expressionBar->findChild()->cursorPosition(), 1); m_expressionBar->findChild()->setText("sin2"); m_expressionBar->findChild()->setCursorPosition(0); m_expressionBar->moveRight(); EXPECT_EQ(m_expressionBar->findChild()->cursorPosition(), 3); m_expressionBar->moveRight(); EXPECT_EQ(m_expressionBar->findChild()->cursorPosition(), 4); delete m_expressionBar; } TEST_F(Ut_SciexpressionBar, deleteText) { SciExpressionBar *m_expressionBar = new SciExpressionBar; m_expressionBar->findChild()->setText("1+2"); m_expressionBar->allElection(); m_expressionBar->deleteText(); EXPECT_EQ(m_expressionBar->findChild()->text(), ""); EXPECT_TRUE(m_expressionBar->m_isContinue); EXPECT_FALSE(m_expressionBar->m_isUndo); EXPECT_FALSE(m_expressionBar->m_isResult); delete m_expressionBar; } deepin-calculator-5.7.21/tests/src/widgets/ut_sciexpressionbar.h000066400000000000000000000004501423020056600250410ustar00rootroot00000000000000#ifndef UT_SCIEXPRESSIONBAR_H #define UT_SCIEXPRESSIONBAR_H #include #include #include #include "../../src/dsettings.h" class Ut_SciexpressionBar : public ::testing::Test { public: Ut_SciexpressionBar(); }; #endif // UT_SCIEXPRESSIONBAR_H deepin-calculator-5.7.21/tests/test-prj-running.sh000066400000000000000000000016551423020056600221320ustar00rootroot00000000000000#!/bin/bash builddir=build reportdir=build-ut rm -r $builddir rm -r ../$builddir rm -r $reportdir rm -r ../$reportdir mkdir ../$builddir mkdir ../$reportdir cd ../$builddir #编译 cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_SAFETYTEST_ARG="CMAKE_SAFETYTEST_ARG_ON" .. make -j8 #生成asan日志和ut测试xml结果 ./tests/deepin-calculator-test --gtest_output=xml:./report/report_deepin-calculator.xml workdir=$(cd ../$(dirname $0)/$builddir; pwd) mkdir -p report #统计代码覆盖率并生成html报告 lcov -d $workdir -c -o ./coverage.info lcov --extract ./coverage.info '*/src/*' -o ./coverage.info lcov --remove ./coverage.info '*/tests/*' -o ./coverage.info genhtml -o ./html ./coverage.info mv ./html/index.html ./html/cov_deepin-calculator.html #对asan、ut、代码覆盖率结果收集至指定文件夹 cp -r html ../$reportdir/ cp -r report ../$reportdir/ cp -r asan*.log* ../$reportdir/asan_deepin-calculator.log exit 0 deepin-calculator-5.7.21/translate_generation.sh000077500000000000000000000003471423020056600217520ustar00rootroot00000000000000#!/bin/bash # this file is used to auto-generate .qm file from .ts file. # author: shibowen at linuxdeepin.com ts_list=(`ls translations/*.ts`) for ts in "${ts_list[@]}" do printf "\nprocess ${ts}\n" lrelease "${ts}" donedeepin-calculator-5.7.21/translations/000077500000000000000000000000001423020056600177205ustar00rootroot00000000000000deepin-calculator-5.7.21/translations/deepin-calculator.ts000066400000000000000000000155351423020056600236740ustar00rootroot00000000000000 ExpressionBar Expression error Expression error IconButton Clear all memory Clear all memory Clear history Clear history InputEdit Delete Delete Select All Select All Use thousands separator Use thousands separator Use ten-thousands separator Use ten-thousands separator Undo Undo Redo Redo Cut Cut Copy Copy Paste Paste MainWindow Calculator Calculator Standard Standard Scientific Scientific Mode Mode Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Programmer Programmer MemoryButton Clear memory item Clear memory item Clear all memory Clear all memory Memory recall Memory recall Add to memory item Add to memory item Memory add Memory add Subtract from memory item Subtract from memory item Memory subtract Memory subtract Memory store Memory store Memory Memory MemoryItemWidget Copy Copy Clear memory item Clear memory item Add to memory item Add to memory item Subtract from memory item Subtract from memory item MemoryWidget Nothing saved in memory Nothing saved in memory ProExpressionBar Expression error Expression error ProListView Copy Copy ProgramModule Arithmetic shift Arithmetic shift Logical shift Logical shift Circular shift Circular shift Rotate through carry circular shift Rotate through carry circular shift ProgrammerItemWidget Arithmetic shift Arithmetic shift Logical shift Logical shift Circular shift Circular shift Rotate through carry circular shift Rotate through carry circular shift QObject Calculator Calculator SciExpressionBar Expression error Expression error SciHistoryWidget History History Memory Memory SimpleListDelegate Expression error Expression error SimpleListModel No history No history SimpleListView Copy Copy Delete Delete deepin-calculator-5.7.21/translations/deepin-calculator_az.ts000066400000000000000000000155061423020056600243640ustar00rootroot00000000000000 ExpressionBar Expression error İfadə xətası IconButton Clear all memory Bütün yaddaşı silmək Clear history Tarixçəni silmək InputEdit Delete Silmək Select All Hamısını seçmək Undo Geri qaytarmaq Redo Təkrarlamaq Cut Kəsmək Copy Kopyalamaq Paste Yerləşdirmək MainWindow Calculator Hesablayıcı Standard Standard Scientific Elmi Mode Rejim Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Hesablayıcı, istifadəsi asan standart və elmi rejimləri dəstəkləyən iş masası hesablayıcısıdır. Programmer Proqramlama MemoryButton Clear memory item Yaddaş elementlərini silmək Clear all memory Bütün yaddaşı silmək Memory recall Yaddaşı çağırmaq Add to memory item Yaddaşa əlavə etmək Memory add Yaddaş əlavə etmək Subtract from memory item Elementi yaddaşdan çıxartmaq Memory subtract Yaddaşdan çıxartmaq Memory store Saxlama yaddaşı Memory Yaddaş MemoryItemWidget Copy Kopyalamaq Clear memory item Yaddaş elementlərini silmək Add to memory item Yaddaşa əlavə etmək Subtract from memory item Elementi yaddaşdan çıxartmaq MemoryWidget Nothing saved in memory Yaddaşda heç nə saxlanılmayıb ProExpressionBar Expression error İfadə xətası ProListView Copy Kopyalamaq ProgramModule Arithmetic shift Arifmetik sürüşmə Logical shift Məntiqi sürüşdürmə Circular shift Dairəvi sürüşdürmək Rotate through carry circular shift Daşımaqla dairəvi döndürün ProgrammerItemWidget Arithmetic shift Arifmetik sürüşmə Logical shift Məntiqi sürüşdürmə Circular shift Dairəvi sürüşdürmək Rotate through carry circular shift Sürüşdürməklə dairəvi döndürün QObject Calculator Hesablayıcı SciExpressionBar Expression error İfadə xətası SciHistoryWidget History Tarixçə Memory Yaddaş SimpleListDelegate Expression error İfadə xətası SimpleListModel No history Tarixçə yoxdur SimpleListView Copy Kopyalamaq Delete Silmək deepin-calculator-5.7.21/translations/deepin-calculator_bo.ts000066400000000000000000000205371423020056600243520ustar00rootroot00000000000000 ExpressionBar Expression error མཚོན་ཚུལ་ནོར་བ། IconButton Clear all memory ནང་གསོག་ཡོད་ཚད་སུབ་པ། Clear history ལོ་རྒྱུས་ཟིན་ཐོ་སུབ་པ། InputEdit Delete སུབ་པ། Select All ཡོངས་འདེམས། Undo ཕྱིར་འཐེན། Redo སླར་གསོ། Cut དྲས་གཏུབ། Copy འདྲ་བཤུས། Paste སྦྱར་བ། MainWindow Calculator རྩིས་ཆས། Standard ཚད་གཞི། Scientific ཚན་རིག Mode དཔེ་རྣམ། Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. རྩིས་ཆས་ནི་སྤྱོད་བདེ་བའི་ཅོག་ངོས་རྩིས་ཆས་ཞིག་ཡིན་པ་དང་། ཚད་ལྡན་རྣམ་པ་དང་ཚན་རིག་དང་མཐུན་པའི་རྣམ་པ། བྱ་རིམ་པའི་དཔེ་རྣམ་བཅས་ལ་རྒྱབ་སྐྱོར་བྱེད་པ་ཡིན། Programmer བྱ་རིམ་པ། MemoryButton Clear memory item ནང་གསོག་ཚན་པ་སུབ་པ། Clear all memory ནང་གསོག་ཡོད་ཚད་སུབ་པ། Memory recall ནང་གསོག་བསྐྱར་དུ་སྤྱོད་པ། Add to memory item ནང་གསོག་ཚན་པར་བསྣན་པ། Memory add ནང་གསོག་སྣོན་པ། Subtract from memory item ནང་གསོག་ཚན་པ་ནས་འཐེན་པ། Memory subtract ནང་གསོག་ཉུང་འཕྲི། Memory store ནང་གསོག་ཉར་བ། Memory ནང་གསོག MemoryItemWidget Copy འདྲ་བཤུས། Clear memory item ནང་གསོག་ཚན་པ་སུབ་པ། Add to memory item ནང་གསོག་ཚན་པར་བསྣན་པ། Subtract from memory item ནང་གསོག་ཚན་པ་ནས་འཐེན་པ། MemoryWidget Nothing saved in memory ནང་གསོག་ནང་གཞི་གྲངས་མེད་པ། ProExpressionBar Expression error མཚོན་ཚུལ་ནོར་བ། ProListView Copy འདྲ་བཤུས། ProgramModule Arithmetic shift ཨང་རྩིས་གནས་སྤོ། Logical shift གཏན་ཚིགས་གནས་སྤོ། Circular shift རེས་འཁོར་གནས་སྤོ། Rotate through carry circular shift གནས་འགྲིལ་འཁོར་སྐྱོད་གནས་སྤོ། ProgrammerItemWidget Arithmetic shift ཨང་རྩིས་གནས་སྤོ། Logical shift གཏན་ཚིགས་གནས་སྤོ། Circular shift རེས་འཁོར་གནས་སྤོ། Rotate through carry circular shift གནས་འགྲིལ་འཁོར་སྐྱོད་གནས་སྤོ། QObject Calculator རྩིས་ཆས། SciExpressionBar Expression error མཚོན་ཚུལ་ནོར་བ། SciHistoryWidget History ལོ་རྒྱུས་ཟིན་ཐོ། Memory ནང་གསོག SimpleListDelegate Expression error མཚོན་ཚུལ་ནོར་བ། SimpleListModel No history ལོ་རྒྱུས་ཟིན་ཐོ་མེད་པ། SimpleListView Copy འདྲ་བཤུས། Delete སུབ་པ། deepin-calculator-5.7.21/translations/deepin-calculator_ca.ts000066400000000000000000000155221423020056600243330ustar00rootroot00000000000000 ExpressionBar Expression error Error d'expressió IconButton Clear all memory Neteja'n tota la memòria Clear history Neteja l'historial InputEdit Delete Suprimeix Select All Selecciona-ho tot Undo Desfés Redo Refés Cut Retalla Copy Copia Paste Enganxa MainWindow Calculator Calculadora Standard Estàndard Scientific Científic Mode Mode Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. La Calculadora és una calculadora d'escriptori fàcil d'usar. Admet els modes estàndard, científic i de programador. Programmer Programador MemoryButton Clear memory item Neteja'n aquest element Clear all memory Neteja'n tota la memòria Memory recall Recordatori de memòria Add to memory item Afegeix a la memòria Memory add Addició a la memòria Subtract from memory item Resta de la memòria Memory subtract Substracció de la memòria Memory store Desa a la memòria Memory Memòria MemoryItemWidget Copy Copia Clear memory item Neteja aquest element Add to memory item Afegeix a la memòria Subtract from memory item Resta de la memòria MemoryWidget Nothing saved in memory No hi ha res desat a la memòria. ProExpressionBar Expression error Error d'expressió ProListView Copy Copia ProgramModule Arithmetic shift Desplaçament aritmètic Logical shift Desplaçament lògic Circular shift Desplaçament circular Rotate through carry circular shift Rotació del desplaçament circular del transport ProgrammerItemWidget Arithmetic shift Desplaçament aritmètic Logical shift Desplaçament lògic Circular shift Desplaçament circular Rotate through carry circular shift Rotació del desplaçament circular del transport QObject Calculator Calculadora SciExpressionBar Expression error Error d'expressió SciHistoryWidget History Historial Memory Memòria SimpleListDelegate Expression error Error d'expressió SimpleListModel No history Sense historial SimpleListView Copy Copia Delete Suprimeix deepin-calculator-5.7.21/translations/deepin-calculator_cs.ts000066400000000000000000000155701423020056600243600ustar00rootroot00000000000000 ExpressionBar Expression error Chyba ve výrazu IconButton Clear all memory Vymazat celou paměť kalkulačky Clear history Vymazat historii InputEdit Delete Smazat Select All Vybrat vše Undo Zpět Redo Znovu Cut Vyjmout Copy Zkopírovat Paste Vložit MainWindow Calculator Kalkulačka Standard Standardní Scientific Vědecký Mode Režim Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Kalkulačka je jednoduchá a snadno použitelná. Podporuje standardní a vědecký a programátorský režim. Programmer Programátorské MemoryButton Clear memory item Vymazat položku v paměti kalkulačky Clear all memory Vymazat paměť kalkulačky Memory recall Vyvolání obsahu paměti kalkulačky Add to memory item Přidat položku do paměti kalkulačky Memory add Přidat do paměti kalkulačky Subtract from memory item Odečíst od položky v paměti kalkulačky Memory subtract Odečíst obsah paměti kalkulačky Memory store Uložení paměti kalkulačky Memory Paměť kalkulačky MemoryItemWidget Copy Zkopírovat Clear memory item Vymazat položku v paměti kalkulačky Add to memory item Přidat položku do paměti Subtract from memory item Odečíst od položky v paměti kalkulačky MemoryWidget Nothing saved in memory V paměti kalkulačky není nic uloženo ProExpressionBar Expression error Chyba ve výrazu ProListView Copy Zkopírovat ProgramModule Arithmetic shift Aritmetický posuv Logical shift Logický posuv Circular shift Kruhový posuv Rotate through carry circular shift Otočit bitovou rotací ProgrammerItemWidget Arithmetic shift Aritmetický posuv Logical shift Logický posuv Circular shift Kruhový posuv Rotate through carry circular shift Otočit bitovou rotací QObject Calculator Kalkulačka SciExpressionBar Expression error Chyba ve výrazu SciHistoryWidget History Historie Memory Paměť kalkulačky SimpleListDelegate Expression error Chyba ve výrazu SimpleListModel No history Žádná historie SimpleListView Copy Zkopírovat Delete Smazat deepin-calculator-5.7.21/translations/deepin-calculator_es.ts000066400000000000000000000154371423020056600243640ustar00rootroot00000000000000 ExpressionBar Expression error Error de expresión IconButton Clear all memory Borrar toda la memoria Clear history Limpiar historial InputEdit Delete Borrar Select All Seleccionar todo Undo Deshacer Redo Rehacer Cut Cortar Copy Copiar Paste Pegar MainWindow Calculator Calculadora Standard Estándar Scientific Científica Mode Modo Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. La calculadora es una aplicación de escritorio, fácil de usar que soporta los modos estándar, científico y programador. Programmer Programador MemoryButton Clear memory item Borrar el elemento de memoria Clear all memory Borrar toda la memoria Memory recall Recuperar memoria Add to memory item Sumar elemento a la memoria Memory add Sumar a la memoria Subtract from memory item Restar elemento a la memoria Memory subtract Restar a la memoria Memory store Guardar en memoria Memory Memoria MemoryItemWidget Copy Copiar Clear memory item Borrar el elemento de la memoria Add to memory item Sumar elemento a la memoria Subtract from memory item Restar elemento a la memoria MemoryWidget Nothing saved in memory No hay nada guardado en la memoria ProExpressionBar Expression error Error de expresión ProListView Copy Copiar ProgramModule Arithmetic shift Desplazamiento aritmético Logical shift Desplazamiento lógico Circular shift Desplazamiento circular Rotate through carry circular shift Rotación a través del acarreo ProgrammerItemWidget Arithmetic shift Desplazamiento aritmético Logical shift Desplazamiento lógico Circular shift Desplazamiento circular Rotate through carry circular shift Rotación a través del acarreo QObject Calculator Calculadora SciExpressionBar Expression error Error de expresión SciHistoryWidget History Historial Memory Memoria SimpleListDelegate Expression error Error de expresión SimpleListModel No history No hay historial SimpleListView Copy Copiar Delete Borrar deepin-calculator-5.7.21/translations/deepin-calculator_et.ts000066400000000000000000000135531423020056600243620ustar00rootroot00000000000000 ExpressionBar Expression error Võrrandi viga IconButton Clear all memory Tühjenda kogu mälu Clear history Tühjenda ajalugu InputEdit Delete Kustuta Select All Vali kõik Undo Võta tagasi Redo Korda Cut Lõika Copy Kopeeri Paste Aseta MainWindow Calculator Kalkulaator Standard Tavaline Scientific Teaduslik Mode Režiim Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Programmer MemoryButton Clear memory item Tühjenda mälu Clear all memory Tühjenda kogu mälu Memory recall Näita mälu Add to memory item Lisa mällu Memory add Mälu lisamine Subtract from memory item Lahuta mälust Memory subtract Mälu lahutamine Memory store Mällu salvestamine Memory Mälu MemoryItemWidget Copy Kopeeri Clear memory item Tühjenda mälu Add to memory item Lisa mällu Subtract from memory item Lahuta mälust MemoryWidget Nothing saved in memory Mällu pole midagi salvestatud ProExpressionBar Expression error Võrrandi viga ProListView Copy Kopeeri ProgramModule Arithmetic shift Logical shift Circular shift Rotate through carry circular shift QObject Calculator Kalkulaator SciExpressionBar Expression error Võrrandi viga SciHistoryWidget History Ajalugu Memory Mälu SimpleListDelegate Expression error Võrrandi viga SimpleListModel No history Ajalugu pole SimpleListView Copy Kopeeri Delete Kustuta deepin-calculator-5.7.21/translations/deepin-calculator_fi.ts000066400000000000000000000151521423020056600243450ustar00rootroot00000000000000 ExpressionBar Expression error Lausekkeen virhe IconButton Clear all memory Tyhjennä koko muisti Clear history Tyhjennä historia InputEdit Delete Poista Select All Valitse kaikki Undo Kumoa Redo Toista Cut Leikkaa Copy Kopioi Paste Liitä MainWindow Calculator Laskin Standard Vakio Scientific Tieteellinen Mode Moodi Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Laskin on helppokäyttöinen laskin, joka tukee tavallista, tieteellistä ja ohjelmointi tilaa. Programmer Ohjelmoija MemoryButton Clear memory item Tyhjennä muistikohde Clear all memory Tyhjennä koko muisti Memory recall Muistin palautus Add to memory item Lisää muistikohteeseen Memory add Muistiin lisääminen Subtract from memory item Vähennä muistikohteesta Memory subtract Muistista vähentäminen Memory store Muistiin tallettaminen Memory Muisti MemoryItemWidget Copy Kopioi Clear memory item Tyhjennä muistikohde Add to memory item Lisää muistikohteeseen Subtract from memory item Vähennä muistikohteesta MemoryWidget Nothing saved in memory Ei mitään muistissa ProExpressionBar Expression error Lausekkeen virhe ProListView Copy Kopioi ProgramModule Arithmetic shift Aritmeettinen Logical shift Looginen Circular shift Ympyrä Rotate through carry circular shift Pyöritä pyöreän siirron läpi ProgrammerItemWidget Arithmetic shift Aritmeettinen Logical shift Looginen Circular shift Ympyrä Rotate through carry circular shift Pyöritä pyöreän siirron läpi QObject Calculator Laskin SciExpressionBar Expression error Lausekkeen virhe SciHistoryWidget History Historia Memory Muisti SimpleListDelegate Expression error Lausekkeen virhe SimpleListModel No history Ei historiaa SimpleListView Copy Kopioi Delete Poista deepin-calculator-5.7.21/translations/deepin-calculator_fr.ts000066400000000000000000000156351423020056600243640ustar00rootroot00000000000000 ExpressionBar Expression error Erreur d'expression IconButton Clear all memory Effacer toute la mémoire Clear history Effacer l'historique InputEdit Delete Effacer Select All Tout sélectionner Undo Annuler Redo Rétablir Cut Couper Copy Copier Paste Coller MainWindow Calculator Calculatrice Standard Standard Scientific Scientifique Mode Mode Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Calculatrice est une calculatrice de bureau facile à utiliser, prenant en charge les modes standard, scientifique et programmeur. Programmer Programmeur MemoryButton Clear memory item Effacer l'élément de la mémoire Clear all memory Effacer toute la mémoire Memory recall Rappel de la mémoire Add to memory item Ajouter l'élément à la mémoire Memory add Ajouter une mémoire Subtract from memory item Soustraire l'élément de la mémoire Memory subtract Soustraire de la mémoire Memory store Mémoire de stockage Memory Mémoire MemoryItemWidget Copy Copier Clear memory item Effacer l'élément de la mémoire Add to memory item Ajouter l'élément à la mémoire Subtract from memory item Soustraire l'élément de la mémoire MemoryWidget Nothing saved in memory Ne rien sauvegarder en mémoire ProExpressionBar Expression error Erreur d'expression ProListView Copy Copier ProgramModule Arithmetic shift Décalage arithmétique Logical shift Changement logique Circular shift Décalage circulaire Rotate through carry circular shift Rotation par déplacement circulaire ProgrammerItemWidget Arithmetic shift Décalage arithmétique Logical shift Changement logique Circular shift Décalage circulaire Rotate through carry circular shift Rotation par déplacement circulaire QObject Calculator Calculatrice SciExpressionBar Expression error Erreur d'expression SciHistoryWidget History Historique Memory Mémoire SimpleListDelegate Expression error Erreur d'expression SimpleListModel No history Pas d'historique SimpleListView Copy Copier Delete Effacer deepin-calculator-5.7.21/translations/deepin-calculator_gl_ES.ts000066400000000000000000000123731423020056600247420ustar00rootroot00000000000000 ExpressionBar Expression error Erro na expresión IconButton Clear all memory Borrar toda a memoria Clear history Borrar historial InputEdit Delete Eliminar Select All Seleccionar todo Undo Redo Cut Copy Copiar Paste MainWindow Calculator Calculadora Calculator is an easy to use desktop calculator, supporting standard and scientific modes. A calculadora é unha calculadora de escritorio fácil de usar, soportando modos estándar e científicos. Standard Estándar Scientific Científico History Historial Mode Modo MemoryButton Clear memory item Borrar a memoria do elemento Clear all memory Borrar toda a memoria Memory recall Recordo de memoria Add to memory item Engadir ao elemento de memoria Memory add Engadir memoria Subtract from memory item Restar un elemento de memoria Memory subtract Restar memoria Memory store Almacenamento de memoria Memory Memoria MemoryItemWidget Copy Copiar Clear memory item Borrar a memoria do elemento Add to memory item Engadir ao elemento de memoria Subtract from memory item Restar un elemento de memoria MemoryWidget Nothing saved in memory No hai nada gardado na memoria QObject Calculator Calculadora SciExpressionBar Expression error Erro na expresión SciHistoryWidget History Historial Memory Memoria SimpleListDelegate Expression error Erro na expresión SimpleListModel No history Non hai historial SimpleListView Copy Copiar Delete Eliminar deepin-calculator-5.7.21/translations/deepin-calculator_hu.ts000066400000000000000000000155241423020056600243660ustar00rootroot00000000000000 ExpressionBar Expression error Kifejezési hiba IconButton Clear all memory Memória teljes törlése Clear history Előzmény törlése InputEdit Delete Törlés Select All Összes kijelölése Undo Vissza Redo Előre Cut Kivágás Copy Másolás Paste Beillesztés MainWindow Calculator Számológép Standard Hagyományos mód Scientific Tudományos mód Mode Mód Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. A Számológép egy könnyen használható asztali számológép alkalmazás, amely támogatja a hagyományos, tudományos és programozói módokat. Programmer Programozói mód MemoryButton Clear memory item Memória elem törlése Clear all memory Memória teljes törlése Memory recall Memória előhívása Add to memory item Elem hozzáadása a memóriához Memory add Memóriához adás Subtract from memory item Kivonás a memóriában lévő elemből Memory subtract Memória kivonása Memory store Memóriatár Memory Memória MemoryItemWidget Copy Másolás Clear memory item Memória elem törlése Add to memory item Elem hozzáadása a memóriához Subtract from memory item Kivonás a memóriában lévő elemből MemoryWidget Nothing saved in memory A memória üres ProExpressionBar Expression error Kifejezési hiba ProListView Copy Másolás ProgramModule Arithmetic shift Számtani eltolás Logical shift Logikai eltolás Circular shift Körkörös eltolás Rotate through carry circular shift Forgassa végig a körkörös eltolást ProgrammerItemWidget Arithmetic shift Számtani eltolás Logical shift Logikai eltolás Circular shift Körkörös eltolás Rotate through carry circular shift Forgassa végig a körkörös eltolást QObject Calculator Számológép SciExpressionBar Expression error Kifejezési hiba SciHistoryWidget History Előzmény Memory Memória SimpleListDelegate Expression error Kifejezési hiba SimpleListModel No history Nincs előzmény SimpleListView Copy Másolás Delete Törlés deepin-calculator-5.7.21/translations/deepin-calculator_it.ts000066400000000000000000000155301423020056600243630ustar00rootroot00000000000000 ExpressionBar Expression error Errore espressione IconButton Clear all memory Cancella la memoria Clear history Pulisci cronologia InputEdit Delete Elimina Select All Seleziona tutti Undo Annulla Redo Ripeti Cut Taglia Copy Copia Paste Incolla MainWindow Calculator Calculatrice Standard Standard Scientific Scientifica Mode Modalità Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Calcolatrice è una calcolatrice desktop semplice e facile da usare. Supporta il calcolo base e quello scientifico. Localizzazione italiana a cura di Massimo A. Carofano. Programmer Programmazione MemoryButton Clear memory item Cancella elementi in memoria Clear all memory Cancella la memoria Memory recall Richiama da memoria Add to memory item Aggiungi agli elementi in memoria Memory add Aggiungi in memoria Subtract from memory item Sottrai dagli elementi in memoria Memory subtract Sottrai dalla Memoria Memory store Memoria attuale Memory Memoria MemoryItemWidget Copy Copia Clear memory item Cancella elementi in memoria Add to memory item Aggiungi agli elementi in memoria Subtract from memory item Sottrai dagli elementi in memoria MemoryWidget Nothing saved in memory Nessun elemento in memoria ProExpressionBar Expression error Errore espressione ProListView Copy Copia ProgramModule Arithmetic shift Spostamento aritmetico Logical shift Spostamento logico Circular shift Spostamento circolare Rotate through carry circular shift Ruota attraverso lo spostamento circolare ProgrammerItemWidget Arithmetic shift Spostamento aritmetico Logical shift Spostamento logico Circular shift Spostamento circolare Rotate through carry circular shift Ruota attraverso lo spostamento circolare QObject Calculator Calculatrice SciExpressionBar Expression error Errore espressione SciHistoryWidget History Cronologia Memory Memoria SimpleListDelegate Expression error Errore espressione SimpleListModel No history Nessuna cronologia SimpleListView Copy Copia Delete Elimina deepin-calculator-5.7.21/translations/deepin-calculator_ka.ts000066400000000000000000000203701423020056600243400ustar00rootroot00000000000000 ExpressionBar Expression error გამოსახვის შეცდომა IconButton Clear all memory მეხსიერების გასუფთავება Clear history ისტორიის გასუფთავება InputEdit Delete წაშლა Select All ყველას მონიშვნა Undo დაბრუნება Redo წინ Cut ამოჭრა Copy კოპირება Paste ჩასმა MainWindow Calculator კალკულატორი Standard სტანდარტული Scientific სამეცნიერო Mode რეჟიმი Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. კალტულატორი არის მარტივი დესკტოპ ხელსაწყო, რომლის გამოყენება შეგიძლიათ მარტივი, სამეცნიერო და პროგრამული გამოთვლებისათვის Programmer პროგრამული MemoryButton Clear memory item მეხსიერების აითემის გასუფთავება Clear all memory მეხსიერების გასუფთავება Memory recall მეხსიერების გახსენება Add to memory item მეხისერებაში დამატება Memory add მეხსიერების დამატება Subtract from memory item მეხსიერებიდან ამოღება Memory subtract მეხსიერების გამოკლება Memory store მეხსიერების განთავსება Memory მეხსიერება MemoryItemWidget Copy კოპირება Clear memory item მეხსიერების აითემის გასუფთავება Add to memory item მეხისერებაში დამატება Subtract from memory item მეხსიერებიდან ამოღება MemoryWidget Nothing saved in memory მეხსიერება ცარიელია ProExpressionBar Expression error გამოსახვის შეცდომა ProListView Copy კოპირება ProgramModule Arithmetic shift არითმეტიკული ცვლა Logical shift ლოგიკური ცვლა Circular shift წრიული ცვლა Rotate through carry circular shift წრიული ცვლის გადაადგილებით ბრუნვა ProgrammerItemWidget Arithmetic shift არითმეტიკული ცვლა Logical shift ლოგიკური ცვლა Circular shift წრიული ცვლა Rotate through carry circular shift წრიული ცვლის გადაადგილებით ბრუნვა QObject Calculator კალკულატორი SciExpressionBar Expression error გამოსახვის შეცდომა SciHistoryWidget History ისოტირა Memory მეხსიერება SimpleListDelegate Expression error გამოსახვის შეცდომა SimpleListModel No history ისტორია არ არის SimpleListView Copy კოპირება Delete წაშლა deepin-calculator-5.7.21/translations/deepin-calculator_km_KH.ts000066400000000000000000000203051423020056600247340ustar00rootroot00000000000000 ExpressionBar Expression error កំហុសក្នុងការបង្ហាញ IconButton Clear all memory ជម្រះការចងចាំទាំងអស់ Clear history សម្អាតប្រវត្តិ InputEdit Delete លុប Select All ជ្រើស​យក​ទាំងអស់ Undo មិនធ្វើវិញ Redo ធ្វើវិញ Cut កាត់ Copy ចម្លង Paste បិទភ្ជាប់ MainWindow Calculator ម៉ាស៊ីនគិតលេខ Standard ស្តង់ដារ Scientific វិទ្យាសាស្ត្រ Mode ម៉ូដ Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. ម៉ាស៊ីនគិតលេខគឺងាយស្រួលប្រើម៉ាស៊ីនគិតកុំព្យូទ័រលើតុគាំទ្របែបស្តង់ដារនិងវិទ្យាសាស្ត្រ. Programmer អ្នកសរសេរកម្មវិធី MemoryButton Clear memory item សម្អាតធាតុចងចាំ Clear all memory ជម្រះការចងចាំទាំងអស់ Memory recall ការហៅការចងចាំមកវិញ Add to memory item បន្ថែមទៅធាតុចងចាំ Memory add បន្ថែមអង្គចងចាំ Subtract from memory item ដកពីធាតុចងចាំ Memory subtract ដកអង្គចងចាំ Memory store រក្សាទុកអង្គចងចាំ Memory អង្គចងចាំ MemoryItemWidget Copy ចម្លង Clear memory item សម្អាតធាតុចងចាំសម្អាតធាតុចងចាំ Add to memory item បន្ថែមទៅធាតុចងចាំ Subtract from memory item ដកពីធាតុចងចាំ MemoryWidget Nothing saved in memory គ្មានអ្វីត្រូវបានរក្សាទុកក្នុងអង្គចងចាំទេ ProExpressionBar Expression error កំហុសក្នុងការបង្ហាញ ProListView Copy ចម្លង ProgramModule Arithmetic shift ការផ្លាស់ប្តូរនព្វន្ធ Logical shift ការផ្លាស់ប្តូរតក្ក Circular shift ការផ្លាស់ប្តូររង្វង់ Rotate through carry circular shift បង្វិលឆ្លងកាត់ការផ្លាស់ប្ដូររង្វង់ ProgrammerItemWidget Arithmetic shift ការផ្លាស់ប្តូរនព្វន្ធ Logical shift ការផ្លាស់ប្តូរតក្ក Circular shift ការផ្លាស់ប្តូររង្វង់ Rotate through carry circular shift បង្វិលឆ្លងកាត់ការផ្លាស់ប្ដូររង្វង់ QObject Calculator ម៉ាស៊ីនគិតលេខ SciExpressionBar Expression error កំហុសក្នុងការបង្ហាញ SciHistoryWidget History ប្រវត្តិ Memory អង្គចងចាំ SimpleListDelegate Expression error កំហុសក្នុងការបង្ហាញ SimpleListModel No history គ្មានប្រវត្តិ SimpleListView Copy ចម្លង Delete លុប deepin-calculator-5.7.21/translations/deepin-calculator_ko.ts000066400000000000000000000123471423020056600243630ustar00rootroot00000000000000 ExpressionBar Expression error 표현식 오류 IconButton Clear all memory 모든 메모리 지우기 Clear history 기록 지우기 InputEdit Delete 삭제 Select All 모두 선택 Undo Redo Cut Copy 복사 Paste MainWindow Calculator 계산기 Calculator is an easy to use desktop calculator, supporting standard and scientific modes. 계산기는 표준 및 공학용 모드를 지원하는 사용하기 쉬운 데스크탑 계산기입니다. Standard 표준 Scientific 공학용 History 기록 Mode 모드 MemoryButton Clear memory item 메모리 항목 지우기 Clear all memory 모든 메모리 지우기 Memory recall 메모리 재호출 Add to memory item 메모리 항목에 추가 Memory add 메모리 추가 Subtract from memory item 메모리 항목에서 빼기 Memory subtract 메모리 빼기 Memory store 메모리 저장 Memory 메모리 MemoryItemWidget Copy 복사 Clear memory item 메모리 항목 지우기 Add to memory item 메모리 항목에 추가 Subtract from memory item 메모리 항목에서 빼기 MemoryWidget Nothing saved in memory 메모리에 저장된 것이 없습니다 QObject Calculator 계산기 SciExpressionBar Expression error 표현식 오류 SciHistoryWidget History 기록 Memory 메모리 SimpleListDelegate Expression error 표현식 오류 SimpleListModel No history 기록 없음 SimpleListView Copy 복사 Delete 삭제 deepin-calculator-5.7.21/translations/deepin-calculator_ms.ts000066400000000000000000000152461423020056600243720ustar00rootroot00000000000000 ExpressionBar Expression error Ralat ungkapan IconButton Clear all memory Kosongkan semua ingatan Clear history Kosongkan sejarah InputEdit Delete Padam Select All Pilih Semua Undo Buat asal Redo Buat semula Cut Potong Copy Salin Paste Tampal MainWindow Calculator Kalkulator Standard Piawai Scientific Saintifik Mode Mod Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Kalkulator ialah sebuah kalkulator atas meja yang ringkas dan mudah digunakan. Ia menyokong mod-mod piawai, saintifik dan pengatur cara Programmer Pengatur cara MemoryButton Clear memory item Kosongkan item ingatan Clear all memory Kosongkan semua ingatan Memory recall Ingat semula ingatan Add to memory item Tambah ke item ingatan Memory add Tambah ingatan Subtract from memory item Buang daripada item ingatan Memory subtract Buang ingatan Memory store Simpanan ingatan Memory Ingatan MemoryItemWidget Copy Salin Clear memory item Kosongkan item ingatan Add to memory item Tambah ke item ingatan Subtract from memory item Buang daripada item ingatan MemoryWidget Nothing saved in memory Tiada apa yang tersimpan dalam ingatan ProExpressionBar Expression error Ralat ungkapan ProListView Copy Salin ProgramModule Arithmetic shift Anjak aritmatik Logical shift Anjak logikal Circular shift Anjak membulat Rotate through carry circular shift Putar melalui anjak membulat ProgrammerItemWidget Arithmetic shift Anjak aritmatik Logical shift Anjak logikal Circular shift Anjak membulat Rotate through carry circular shift Putar melalui anjak membulat QObject Calculator Kalkulator SciExpressionBar Expression error Ralat ungkapan SciHistoryWidget History Sejarah Memory Ingatan SimpleListDelegate Expression error Ralat ungkapan SimpleListModel No history Tiada sejarah SimpleListView Copy Salin Delete Padam deepin-calculator-5.7.21/translations/deepin-calculator_nl.ts000066400000000000000000000154411423020056600243610ustar00rootroot00000000000000 ExpressionBar Expression error Expressiefout IconButton Clear all memory Geschiedenis wissen Clear history Geschiedenis wissen InputEdit Delete Wissen Select All Alles selecteren Undo Ongedaan maken Redo Opnieuw Cut Knippen Copy Kopiëren Paste Plakken MainWindow Calculator Rekenmachine Standard Standaard Scientific Wetenschappelijk Mode Modus Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Rekenmachine is een makkelijk te gebruiken rekenmachine met ondersteuning voor standaard- en wetenschappelijke functies. Programmer Programmeren MemoryButton Clear memory item Item wissen Clear all memory Geschiedenis wissen Memory recall Uit geschiedenis Add to memory item Toevoegen aan geschiedenis Memory add Geschiedenis toevoegen Subtract from memory item Ophalen uit geschiedenisitem Memory subtract Uit geschiedenis Memory store Geschiedenis opslaan Memory Geschiedenis MemoryItemWidget Copy Kopiëren Clear memory item Item wissen Add to memory item Toevoegen aan geschiedenis Subtract from memory item Ophalen uit geschiedenisitem MemoryWidget Nothing saved in memory Niks opgeslagen in geschiedenis ProExpressionBar Expression error Expressiefout ProListView Copy Kopiëren ProgramModule Arithmetic shift Rekenkundige verschuiving Logical shift Logische verschuiving Circular shift Circulaire verschuiving Rotate through carry circular shift Draaien door cirkelvormige verschuiving te dragen ProgrammerItemWidget Arithmetic shift Rekenkundige verschuiving Logical shift Logische verschuiving Circular shift Circulaire verschuiving Rotate through carry circular shift Draaien door cirkelvormige verschuiving te dragen QObject Calculator Rekenmachine SciExpressionBar Expression error Expressiefout SciHistoryWidget History Geschiedenis Memory Geschiedenis SimpleListDelegate Expression error Expressiefout SimpleListModel No history Geen geschiedenis SimpleListView Copy Kopiëren Delete Wissen deepin-calculator-5.7.21/translations/deepin-calculator_pl.ts000066400000000000000000000160051423020056600243600ustar00rootroot00000000000000 ExpressionBar Expression error Nieprawidłowe wyrażenie IconButton Clear all memory Wyczyść całą pamięć Clear history Wyczyść historię InputEdit Delete Usuń Select All Zaznacz wszystko Use thousands separator Use ten-thousands separator Undo Cofnij Redo Ponów Cut Wytnij Copy Kopiuj Paste Wklej MainWindow Calculator Kalkulator Standard Standardowy Scientific Naukowy Mode Tryb Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Kalkulator jest łatwym w użyciu kalkulatorem desktopowym, wspierającym trzy tryby: standardowy, naukowy i programisty. Programmer Programisty MemoryButton Clear memory item Wyczyść element pamięci Clear all memory Wyczyść całą pamięć Memory recall Przywołanie pamięci Add to memory item Dodaj do elementu pamięci Memory add Dodaj pamięć Subtract from memory item Odejmij od elementu pamięci Memory subtract Odejmowanie pamięci Memory store Sklep z pamięcią Memory Pamięć MemoryItemWidget Copy Kopiuj Clear memory item Wyczyść element pamięci Add to memory item Dodaj do elementu pamięci Subtract from memory item Odejmij od elementu pamięci MemoryWidget Nothing saved in memory Nic nie zostało zapisane w pamięci ProExpressionBar Expression error Błąd wyrażenia ProListView Copy Kopiuj ProgramModule Arithmetic shift Przesunięcie arytmetyczne Logical shift Przesunięcie logiczne Circular shift Przesunięcie cykliczne Rotate through carry circular shift Zastosuj przesunięcie cykliczne ProgrammerItemWidget Arithmetic shift Przesunięcie arytmetyczne Logical shift Przesunięcie logiczne Circular shift Przesunięcie cykliczne Rotate through carry circular shift Zastosuj przesunięcie cykliczne QObject Calculator Kalkulator SciExpressionBar Expression error Błąd wyrażenia SciHistoryWidget History Historia Memory Pamięć SimpleListDelegate Expression error Błąd wyrażenia SimpleListModel No history Brak historii SimpleListView Copy Kopiuj Delete Usuń deepin-calculator-5.7.21/translations/deepin-calculator_pt.ts000066400000000000000000000153541423020056600243760ustar00rootroot00000000000000 ExpressionBar Expression error Erro de expressão IconButton Clear all memory Limpar toda a memória Clear history Limpar histórico InputEdit Delete Eliminar Select All Selecionar tudo Undo Anular Redo Refazer Cut Cortar Copy Copiar Paste Colar MainWindow Calculator Calculadora Standard Padrão Scientific Científico Mode Modo Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Calculadora é uma aplicação para o computador que é fácil de usar, compatível com os modos padrão, científico e de programador. Programmer Programador MemoryButton Clear memory item Limpar item da memória Clear all memory Limpar toda a memória Memory recall Recuperar memória Add to memory item Adicionar item à memória Memory add Adicionar memória Subtract from memory item Subtrair item da memória Memory subtract Subtrair memória Memory store Armazenar na memória Memory Memória MemoryItemWidget Copy Copiar Clear memory item Limpar item da memória Add to memory item Adicionar item à memória Subtract from memory item Subtrair item da memória MemoryWidget Nothing saved in memory Nada guardado na memória ProExpressionBar Expression error Erro de expressão ProListView Copy Copiar ProgramModule Arithmetic shift Mudança aritmética Logical shift Mudança lógica Circular shift Mudança circular Rotate through carry circular shift Rodar através da mudança circular ProgrammerItemWidget Arithmetic shift Mudança aritmética Logical shift Mudança lógica Circular shift Mudança circular Rotate through carry circular shift Rodar através da mudança circular QObject Calculator Calculadora SciExpressionBar Expression error Erro de expressão SciHistoryWidget History Histórico Memory Memória SimpleListDelegate Expression error Erro de expressão SimpleListModel No history Sem histórico SimpleListView Copy Copiar Delete Eliminar deepin-calculator-5.7.21/translations/deepin-calculator_pt_BR.ts000066400000000000000000000154261423020056600247610ustar00rootroot00000000000000 ExpressionBar Expression error Erro de expressão IconButton Clear all memory Limpar toda a memória Clear history Limpar histórico InputEdit Delete Excluir Select All Selecionar Tudo Undo Desfazer Redo Refazer Cut Recortar Copy Copiar Paste Colar MainWindow Calculator Calculadora Standard Padrão Scientific Científico Mode Modo Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. A Calculadora é uma ferramenta de cálculo, fácil de usar e compatível com os modos científico e programador. Programmer Programador MemoryButton Clear memory item Limpar item da memória Clear all memory Limpar toda a memória Memory recall Recuperar memória Add to memory item Adicionar item à memória Memory add Adicionar memória Subtract from memory item Subtrair item da memória Memory subtract Subtrair memória Memory store Gravar na memória Memory Memória MemoryItemWidget Copy Copiar Clear memory item Limpar item da memória Add to memory item Adicionar item à memória Subtract from memory item Subtrair item da memória MemoryWidget Nothing saved in memory Nada gravado na memória ProExpressionBar Expression error Erro de expressão ProListView Copy Copiar ProgramModule Arithmetic shift Deslocamento aritmético Logical shift Deslocamento lógico Circular shift Deslocamento circular Rotate through carry circular shift Girar através do deslocamento circular de transporte ProgrammerItemWidget Arithmetic shift Deslocamento aritmético Logical shift Deslocamento lógico Circular shift Deslocamento circular Rotate through carry circular shift Girar através do deslocamento circular de transporte QObject Calculator Calculadora SciExpressionBar Expression error Erro de expressão SciHistoryWidget History Histórico Memory Memória SimpleListDelegate Expression error Erro de expressão SimpleListModel No history Nenhum histórico SimpleListView Copy Copiar Delete Excluir deepin-calculator-5.7.21/translations/deepin-calculator_ro.ts000066400000000000000000000154031423020056600243660ustar00rootroot00000000000000 ExpressionBar Expression error Eroare expresie IconButton Clear all memory Golește memoria Clear history Golește istoria InputEdit Delete Șterge Select All Selectează tot Undo Anulare Redo Repetare Cut Decupare Copy Copiere Paste Lipire MainWindow Calculator Calculator Standard Standard Scientific Științific Mode Mod Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Calculator este un calculator desktop ușor de utilizat, care acceptă moduri standard, științifice și de programare. Programmer Programator MemoryButton Clear memory item Golește memoria Clear all memory Golește memoria Memory recall Readuce din memorie Add to memory item Adăugați la elementul de memorie Memory add Adăugare la memorie Subtract from memory item Scade din elementul de memorie Memory subtract Scade din memorie Memory store Stocare în memorie Memory Memorie MemoryItemWidget Copy Copiază Clear memory item Ștergeți elementul din memorie Add to memory item Adăugați la elementul de memorie Subtract from memory item Scade din elementul de memorie MemoryWidget Nothing saved in memory Nimic salvat în memorie ProExpressionBar Expression error Eroare expresie ProListView Copy Copiere ProgramModule Arithmetic shift Schimbare aritmetică Logical shift Schimbare logică Circular shift Schimbare circulară Rotate through carry circular shift Rotiți prin deplasare circulară de transport ProgrammerItemWidget Arithmetic shift Schimbare aritmetică Logical shift Schimbare logică Circular shift Schimbare circulară Rotate through carry circular shift Rotiți prin deplasare circulară de transport QObject Calculator Calculator SciExpressionBar Expression error Eroare expresie SciHistoryWidget History Istoria Memory Memorie SimpleListDelegate Expression error Eroare expresie SimpleListModel No history Nimic istorie SimpleListView Copy Copiază Delete Șterge deepin-calculator-5.7.21/translations/deepin-calculator_ru.ts000066400000000000000000000170561423020056600244020ustar00rootroot00000000000000 ExpressionBar Expression error Ошибка Выражения IconButton Clear all memory Очистить всю память Clear history Очистить историю InputEdit Delete Удалить Select All Выбрать все Undo Отменить Redo Повторить Cut Вырезать Copy Копировать Paste Вставить MainWindow Calculator Калькулятор Standard Стандартный Scientific Научный Mode Режим Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Калькулятор - это простой в использовании настольный калькулятор, поддерживающий стандартный, научный и программистский режимы. Programmer Программистский MemoryButton Clear memory item Удалить элемент из памяти Clear all memory Очистить всю память Memory recall Вызов из памяти Add to memory item Добавить элемент в память Memory add Добавить в память Subtract from memory item Вычесть элемент из памяти Memory subtract Вычесть из памяти Memory store Хранилище памяти Memory Память MemoryItemWidget Copy Копировать Clear memory item Удалить элемент из памяти Add to memory item Добавить элемент в память Subtract from memory item Вычесть элемент из памяти MemoryWidget Nothing saved in memory В памяти ничего не сохранено ProExpressionBar Expression error Ошибка выражения ProListView Copy Копировать ProgramModule Arithmetic shift Арифметический сдвиг Logical shift Логический сдвиг Circular shift Циклический сдвиг Rotate through carry circular shift Вращать циклический сдвиг посредством переноса ProgrammerItemWidget Arithmetic shift Арифметический сдвиг Logical shift Логический сдвиг Circular shift Циклический сдвиг Rotate through carry circular shift Вращать посредством переноса циклический сдвиг QObject Calculator Калькулятор SciExpressionBar Expression error Ошибка Выражения SciHistoryWidget History История Memory Память SimpleListDelegate Expression error Ошибка Выражения SimpleListModel No history История не сохранилась SimpleListView Copy Копировать Delete Удалить deepin-calculator-5.7.21/translations/deepin-calculator_sl.ts000066400000000000000000000153521423020056600243670ustar00rootroot00000000000000 ExpressionBar Expression error Napaka v izrazu IconButton Clear all memory Počisti ves pomnilnik Clear history Počisti zgodovino InputEdit Delete Izbriši Select All Izberi vse Undo Razveljavi Redo Uveljavi Cut Izreži Copy Kopiraj Paste Prilepi MainWindow Calculator Kalkulator Standard Standardni Scientific Znanstveni Mode Način Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Kalkulator je enostaven namizni kalkulator, ki podpira standardni, znanstveni in progrmerski način delovanja. Programmer Programer MemoryButton Clear memory item Izbriši predmet iz pomnilnika Clear all memory Počisti ves pomnilnikI Memory recall Prikliči pomninik Add to memory item Prištej predmetu v pomnilniku Memory add Prištevanje k pomnilniku Subtract from memory item Odštej od predmeta v pomnilniku Memory subtract Odštevanje od pomnilnika Memory store Shranjevanje v pomnilnik Memory Pomnilnik MemoryItemWidget Copy Kopiraj Clear memory item Izbriši predmet iz pomnilnika Add to memory item Dodaj predmetu pomnilnika Subtract from memory item Odštej od predata v pomnilniku MemoryWidget Nothing saved in memory V pomnilniku ni ničesar ProExpressionBar Expression error Napaka v izrazu ProListView Copy Kopiraj ProgramModule Arithmetic shift Aritmetični pomik Logical shift Logični pomik Circular shift Krožni pomik Rotate through carry circular shift Kroži po krožnem pomiku nosilca ProgrammerItemWidget Arithmetic shift Aritmetični pomik Logical shift Logični pomik Circular shift Krožni pomik Rotate through carry circular shift Kroži po krožnem pomiku nosilca QObject Calculator Kalkulator SciExpressionBar Expression error Napaka v izrazu SciHistoryWidget History Zgodovina Memory Pomnilnik SimpleListDelegate Expression error Napaka v izrazu SimpleListModel No history Ni zgodovine SimpleListView Copy Kopiraj Delete Izbriši deepin-calculator-5.7.21/translations/deepin-calculator_sq.ts000066400000000000000000000151401423020056600243670ustar00rootroot00000000000000 ExpressionBar Expression error Gabim shprehjeje IconButton Clear all memory Spastro krejt kujtesën Clear history Spastro historikun InputEdit Delete Fshije Select All Përzgjidhi Krejt Undo Zhbëje Redo Ribëje Cut Prije Copy Kopjoje Paste Ngjite MainWindow Calculator Llogaritës Standard Standarde Scientific Shkencore Mode Mënyrë Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Llogaritësi është një makinë llogaritëse për desktop, e lehtë për t’u përdorur, që mbulon mënyrat standard, shkencore dhe programues. Programmer Programues MemoryButton Clear memory item Spastro zë kujtese Clear all memory Spastro krejt kujtesën Memory recall MR Add to memory item Shtoje te objekt kujtese Memory add Shtim prej kujtese Subtract from memory item Zbrite prej objekti kujtese Memory subtract Zbritje prej kujtese Memory store Depozitim në kujtesë Memory Kujtesë MemoryItemWidget Copy Kopjoje Clear memory item Spastro zë kujtese Add to memory item Shtoje te objekt kujtese Subtract from memory item Zbrite prej objekti kujtese MemoryWidget Nothing saved in memory S’u ruajt gjë në kujtesë ProExpressionBar Expression error Gabim shprehjeje ProListView Copy Kopjoje ProgramModule Arithmetic shift Logical shift Circular shift Rotate through carry circular shift ProgrammerItemWidget Arithmetic shift Logical shift Circular shift Rotate through carry circular shift QObject Calculator Llogaritës SciExpressionBar Expression error Gabim shprehjeje SciHistoryWidget History Historik Memory Kujtesë SimpleListDelegate Expression error Gabim shprehjeje SimpleListModel No history S’ka historik SimpleListView Copy Kopjoje Delete Fshije deepin-calculator-5.7.21/translations/deepin-calculator_sr.ts000066400000000000000000000165151423020056600243770ustar00rootroot00000000000000 ExpressionBar Expression error Грешка израза IconButton Clear all memory Очисти сву меморију Clear history Очисти историју InputEdit Delete Обриши Select All Изабери све Undo Опозови Redo Обнови Cut Исеци Copy Копирај Paste Убаци MainWindow Calculator Калкулатор Standard Стандардни Scientific Научни Mode Режим Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Калкулатор је рачунарски прогам који је једноставан за употребу. Подржава стандардни, научни и програмерски режим. Programmer Програмер MemoryButton Clear memory item Уклони ставку меморије Clear all memory Очисти сву меморију Memory recall Позови из меморије Add to memory item Сабери са ставком меморије Memory add Сабери са меморијом Subtract from memory item Одузми од ставке меморије Memory subtract Одузими од меморије Memory store Сачувај у меморији Memory Меморија MemoryItemWidget Copy Копирај Clear memory item Уклони ставку меморије Add to memory item Додај у ставку меморије Subtract from memory item Одузми од ставке меморије MemoryWidget Nothing saved in memory Меморија је празна ProExpressionBar Expression error Грешка израза ProListView Copy Копирај ProgramModule Arithmetic shift Аритметички помак Logical shift Логички помак Circular shift Кружни помак Rotate through carry circular shift Роптирај кроз носиоца кружног помака ProgrammerItemWidget Arithmetic shift Аритметички помак Logical shift Логички помак Circular shift Кружни помак Rotate through carry circular shift Роптирај кроз носиоца кружног помака QObject Calculator Калкулатор SciExpressionBar Expression error Грешка израза SciHistoryWidget History Историја Memory Меморија SimpleListDelegate Expression error Грешка израза SimpleListModel No history Нема историје SimpleListView Copy Копирај Delete Обриши deepin-calculator-5.7.21/translations/deepin-calculator_tr.ts000066400000000000000000000153171423020056600243770ustar00rootroot00000000000000 ExpressionBar Expression error İfade hatası IconButton Clear all memory Tüm belleği temizle Clear history Geçmişi temizle InputEdit Delete Sil Select All Tümünü Seç Undo Geri al Redo Tekrarla Cut Kes Copy Kopyala Paste Yapıştır MainWindow Calculator Hesap Makinesi Standard Standart Scientific Bilimsel Mode Kip Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Hesap Makinesi standart, bilimsel ve programcı kipleri destekleyen, kullanımı kolay masaüstü hesap makinesidir. Programmer Programcı MemoryButton Clear memory item Bellek ögesini temizle Clear all memory Tüm belleği temizle Memory recall Bellekten geri çağır Add to memory item Ögeyi belleğe ekle Memory add Belleğe ekle Subtract from memory item Ögeyi bellekten çıkar Memory subtract Bellekten çıkar Memory store Bellek deposu Memory Bellek MemoryItemWidget Copy Kopyala Clear memory item Bellek ögesini temizle Add to memory item Bellek ögesine ekle Subtract from memory item Ögeyi bellekten çıkar MemoryWidget Nothing saved in memory Bellekte kayıtlı bir şey yok ProExpressionBar Expression error İfade hatası ProListView Copy Kopyala ProgramModule Arithmetic shift Aritmetik kaydırma Logical shift Mantıksal kaydırma Circular shift Dairesel kaydırma Rotate through carry circular shift Dairesel kaydırmayı taşıma boyunca döndür ProgrammerItemWidget Arithmetic shift Aritmetik kaydırma Logical shift Mantıksal kaydırma Circular shift Dairesel kaydırma Rotate through carry circular shift Dairesel kaydırmayı taşıma boyunca döndür QObject Calculator Hesap Makinesi SciExpressionBar Expression error İfade hatası SciHistoryWidget History Geçmiş Memory Bellek SimpleListDelegate Expression error İfade hatası SimpleListModel No history Geçmiş yok SimpleListView Copy Kopyala Delete Sil deepin-calculator-5.7.21/translations/deepin-calculator_ug.ts000066400000000000000000000174071423020056600243670ustar00rootroot00000000000000 ExpressionBar Expression error ئىپادىلەش خاتا IconButton Clear all memory بارلىق ساقلىغۇچنى ئۆچۈرۈش Clear history تارىخىي خاتىرىنى ئۆچۈرۈش InputEdit Delete ئۆچۈرۈش Select All ھەممىنى تاللاش Use thousands separator Use ten-thousands separator Undo ئەمەلدىن قالدۇرۇش Redo ئەسلىگە كەلتۈرۈش Cut كېسىش Copy كۆچۈرۈش Paste چاپلاش MainWindow Calculator ھېسابلىغۇچ Standard ئۆلچەم Scientific ئىلمىي Mode ھالەت Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. ئۈستەل يۈزى ھېسابلىغۇچنى ئىشلىتىش ئاسان ، ئۆلچەملىك ، ئىلمىي ۋە پروگراممېر ھالىتىنى قوللايدۇ. Programmer پروگراممېر MemoryButton Clear memory item ساقلانما تۈرلىرىنى ئۆچۈرۈش Clear all memory بارلىق ساقلىغۇچنى ئۆچۈرۈش Memory recall ساقلانمىنى كۆرۈش Add to memory item ساقلانما تۈرى قوشۇش Memory add ئىچكى ساقلىغۇچقا قوشۇلدى Subtract from memory item ئىچكى ساقلىغۇچ تۈرىدىن ئازايتىش Memory subtract ئىچكى ساقلىغۇچ ئازايدى Memory store ئىچكى ساقلىغۇچقا ساقلاش Memory ئىچكى ساقلىغۇچ MemoryItemWidget Copy كۆچۈرۈش Clear memory item خاتېرە تۈرلىرىنى ئۆچۈرۈش Add to memory item خاتېرە تۈرى قوشۇش Subtract from memory item ئىچكى ساقلىغۇچ تۈرىدىن ئازايتىش MemoryWidget Nothing saved in memory ساقلىغۇچىتا ھېچنىمە يوق ProExpressionBar Expression error ئىپادىلەش خاتا ProListView Copy كۆچۈرۈش ProgramModule Arithmetic shift ئارفىمېتكىلىق يۆتكىلىش Logical shift لوگىكىلىق يۆتكىلىش Circular shift ئايلانما يۆتكىلىش Rotate through carry circular shift ئايلانما يۆتكىلىش ئارقىلىق ئايلىنىش ProgrammerItemWidget Arithmetic shift ئارفىمېتكىلىق يۆتكىلىش Logical shift لوگىكىلىق يۆتكىلىش Circular shift ئايلانما يۆتكىلىش Rotate through carry circular shift ئايلانما يۆتكىلىش ئارقىلىق ئايلىنىش QObject Calculator ھېسابلىغۇچ SciExpressionBar Expression error ئىپادىلەش خاتا SciHistoryWidget History تارىخىي خاتىرە Memory ئىچكى ساقلىغۇچ SimpleListDelegate Expression error ئىپادىلەش خاتا SimpleListModel No history تارىخىي خاتىرە يوق SimpleListView Copy كۆچۈرۈش Delete ئۆچۈرۈش deepin-calculator-5.7.21/translations/deepin-calculator_uk.ts000066400000000000000000000171561423020056600243740ustar00rootroot00000000000000 ExpressionBar Expression error Помилка у виразі IconButton Clear all memory Спорожнити усю пам'ять Clear history Спорожнити журнал InputEdit Delete Вилучити Select All Позначити все Undo Скасувати Redo Повторити Cut Вирізати Copy Копіювати Paste Вставити MainWindow Calculator Калькулятор Standard Стандартний Scientific Науковий Mode Режим Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. «Калькулятор» є простим у користуванні комп'ютерним калькулятором. Передбачено підтримку стандартного, наукового та програмістського режимів. Programmer Програмістський MemoryButton Clear memory item Спорожнити запис пам'яті Clear all memory Спорожнити усю пам'ять Memory recall Відновлення з пам'яті Add to memory item Додати до запису пам'яті Memory add Додати до пам'яті Subtract from memory item Відняти від запису пам'яті Memory subtract Відняти від пам'яті Memory store Зберегти у пам'яті Memory Запам'ятати MemoryItemWidget Copy Копіювати Clear memory item Спорожнити запис пам'яті Add to memory item Додати до запису пам'яті Subtract from memory item Відняти від запису пам'яті MemoryWidget Nothing saved in memory У пам'яті нічого не збережено ProExpressionBar Expression error Помилка у виразі ProListView Copy Копіювати ProgramModule Arithmetic shift Арифметичний зсув Logical shift Логічний зсув Circular shift Циклічний зсув Rotate through carry circular shift Циклічний зсув, обертання з перенесенням ProgrammerItemWidget Arithmetic shift Арифметичний зсув Logical shift Логічний зсув Circular shift Циклічний зсув Rotate through carry circular shift Циклічний зсув, обертання з перенесенням QObject Calculator Калькулятор SciExpressionBar Expression error Помилка у виразі SciHistoryWidget History Журнал Memory Запам'ятати SimpleListDelegate Expression error Помилка у виразі SimpleListModel No history Немає журналу SimpleListView Copy Копіювати Delete Вилучити deepin-calculator-5.7.21/translations/deepin-calculator_vi.ts000066400000000000000000000137221423020056600243660ustar00rootroot00000000000000 ExpressionBar Expression error Lỗi ngoại lệ IconButton Clear all memory Xóa bộ nhớ Clear history Xóa lịch sử InputEdit Delete Xóa Select All Chọn tất cả Undo Hoàn tác Redo Làm lại Cut Cắt Copy Sao chép Paste Dán MainWindow Calculator Máy tính Standard Tiêu chuẩn Scientific Khoa học Mode Chế độ Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. Programmer MemoryButton Clear memory item Xóa bộ nhớ Clear all memory Xóa bộ nhớ Memory recall Kiểm tra lại bộ nhớ Add to memory item Thêm vào bộ nhớ Memory add Thêm bộ nhớ Subtract from memory item Trừ mục bộ nhớ Memory subtract Trừ bộ nhớ Memory store Cửa hàng bộ nhớ Memory Bộ nhớ MemoryItemWidget Copy Sao chép Clear memory item Xóa bộ nhớ Add to memory item Thêm vào bộ nhớ Subtract from memory item Trừ mục bộ nhớ MemoryWidget Nothing saved in memory Chưa có gì trong bộ nhớ ProExpressionBar Expression error Lỗi ngoại lệ ProListView Copy Sao chép ProgramModule Arithmetic shift Logical shift Circular shift Rotate through carry circular shift QObject Calculator Máy tính SciExpressionBar Expression error Lỗi ngoại lệ SciHistoryWidget History Lịch sử Memory Bộ nhớ SimpleListDelegate Expression error Lỗi ngoại lệ SimpleListModel No history Không có lịch sử SimpleListView Copy Sao chép Delete Xóa deepin-calculator-5.7.21/translations/deepin-calculator_zh_CN.ts000066400000000000000000000154611423020056600247530ustar00rootroot00000000000000 ExpressionBar Expression error 表达式错误 IconButton Clear all memory 清除所有内存 Clear history 清除历史记录 InputEdit Delete 删除 Select All 全选 Use thousands separator 切换为千分位 Use ten-thousands separator 切换为万分位 Undo 撤销 Redo 恢复 Cut 剪切 Copy 复制 Paste 粘贴 MainWindow Calculator 计算器 Standard 标准 Scientific 科学 Mode 模式 Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. 计算器是一款简单易用的桌面计算器,支持标准型、科学型、程序员型模式。 Programmer 程序员 MemoryButton Clear memory item 清除内存项 Clear all memory 清除所有内存 Memory recall 内存重新调用 Add to memory item 添加到内存项 Memory add 内存增加 Subtract from memory item 从内存项中减掉 Memory subtract 内存减少 Memory store 内存存储 Memory 内存 MemoryItemWidget Copy 复制 Clear memory item 清除内存项 Add to memory item 添加到内存项 Subtract from memory item 从内存项中减掉 MemoryWidget Nothing saved in memory 内存中没有数据 ProExpressionBar Expression error 表达式错误 ProListView Copy 复制 ProgramModule Arithmetic shift 算数移位 Logical shift 逻辑移位 Circular shift 循环移位 Rotate through carry circular shift 带进位循环移位 ProgrammerItemWidget Arithmetic shift 算数移位 Logical shift 逻辑移位 Circular shift 循环移位 Rotate through carry circular shift 带进位循环移位 QObject Calculator 计算器 SciExpressionBar Expression error 表达式错误 SciHistoryWidget History 历史记录 Memory 内存 SimpleListDelegate Expression error 表达式错误 SimpleListModel No history 无历史记录 SimpleListView Copy 复制 Delete 删除 deepin-calculator-5.7.21/translations/deepin-calculator_zh_HK.ts000066400000000000000000000154611423020056600247550ustar00rootroot00000000000000 ExpressionBar Expression error 運算式錯誤 IconButton Clear all memory 清除所有內存 Clear history 清除歷史記錄 InputEdit Delete 刪除 Select All 全選 Use thousands separator 切換為千分位 Use ten-thousands separator 切換為萬分位 Undo 撤銷 Redo 恢復 Cut 剪切 Copy 複製 Paste 黏貼 MainWindow Calculator 計數機 Standard 標準 Scientific 科學 Mode 模式 Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. 計數機是一款簡單易用的桌面計算器,支持標準型、科學型、程式員型模式。 Programmer 程序員 MemoryButton Clear memory item 清除內存項 Clear all memory 清除所有內存 Memory recall 內存重新調用 Add to memory item 添加到內存項 Memory add 內存增加 Subtract from memory item 從內存項中減掉 Memory subtract 內存減少 Memory store 內存存儲 Memory 內存 MemoryItemWidget Copy 複製 Clear memory item 清除內存項 Add to memory item 添加到內存項 Subtract from memory item 從內存項中減掉 MemoryWidget Nothing saved in memory 內存中沒有數據 ProExpressionBar Expression error 運算式錯誤 ProListView Copy 複製 ProgramModule Arithmetic shift 算數移位 Logical shift 邏輯移位 Circular shift 循環移位 Rotate through carry circular shift 帶進位循環移位 ProgrammerItemWidget Arithmetic shift 算數移位 Logical shift 邏輯移位 Circular shift 循環移位 Rotate through carry circular shift 帶進位循環移位 QObject Calculator 計數機 SciExpressionBar Expression error 運算式錯誤 SciHistoryWidget History 歷史記錄 Memory 內存 SimpleListDelegate Expression error 運算式錯誤 SimpleListModel No history 無歷史記錄 SimpleListView Copy 複製 Delete 刪除 deepin-calculator-5.7.21/translations/deepin-calculator_zh_TW.ts000066400000000000000000000155521423020056600250060ustar00rootroot00000000000000 ExpressionBar Expression error 運算式錯誤 IconButton Clear all memory 清除所有記憶體 Clear history 清除歷史記錄 InputEdit Delete 删除 Select All 全選 Use thousands separator 切換為千分位 Use ten-thousands separator 切換為萬分位 Undo 復原 Redo 重做 Cut 剪下 Copy 複製 Paste 貼上 MainWindow Calculator 計算器 Standard 標準 Scientific 科學 Mode 模式 Calculator is an easy to use desktop calculator, supporting standard, scientific and programmer modes. 計算器是一款簡單易用的桌面計算器,支持標準型、科學型、程式設計師型模式。 Programmer 程式設計師 MemoryButton Clear memory item 清除記憶體項 Clear all memory 清除所有記憶體 Memory recall 記憶體重新呼叫 Add to memory item 添加到記憶體項 Memory add 記憶體增加 Subtract from memory item 從記憶體項中減掉 Memory subtract 記憶體減少 Memory store 記憶體儲存 Memory 記憶體 MemoryItemWidget Copy 複製 Clear memory item 清除記憶體項 Add to memory item 添加到記憶體項 Subtract from memory item 從記憶體項中減掉 MemoryWidget Nothing saved in memory 記憶體中沒有資料 ProExpressionBar Expression error 運算式錯誤 ProListView Copy 複製 ProgramModule Arithmetic shift 算數移位 Logical shift 邏輯移位 Circular shift 循環移位 Rotate through carry circular shift 帶進位循環移位 ProgrammerItemWidget Arithmetic shift 算數移位 Logical shift 邏輯移位 Circular shift 循環移位 Rotate through carry circular shift 帶進位循環移位 QObject Calculator 計算器 SciExpressionBar Expression error 運算式錯誤 SciHistoryWidget History 歷史記錄 Memory 記憶體 SimpleListDelegate Expression error 運算式錯誤 SimpleListModel No history 無歷史記錄 SimpleListView Copy 複製 Delete 删除 deepin-calculator-5.7.21/translations/desktop/000077500000000000000000000000001423020056600213715ustar00rootroot00000000000000deepin-calculator-5.7.21/translations/desktop/desktop.ts000066400000000000000000000007031423020056600234120ustar00rootroot00000000000000desktopCalculatorCalculatorDeepin CalculatorDeepin Calculatordeepin-calculator-5.7.21/translations/desktop/desktop_am_ET.ts000066400000000000000000000007201423020056600244560ustar00rootroot00000000000000desktopCalculatorማስሊያDeepin Calculatorዲፕኢን ማስሊያdeepin-calculator-5.7.21/translations/desktop/desktop_ar.ts000066400000000000000000000007131423020056600240750ustar00rootroot00000000000000desktopCalculatorالحاسبةDeepin Calculatorحاسبة ديبينdeepin-calculator-5.7.21/translations/desktop/desktop_ast.ts000066400000000000000000000007051423020056600242630ustar00rootroot00000000000000desktopCalculatorCalculadoraDeepin CalculatorDeepin Calculatordeepin-calculator-5.7.21/translations/desktop/desktop_az.ts000066400000000000000000000007111423020056600241030ustar00rootroot00000000000000desktopCalculatorHesablayıcıDeepin CalculatorDeepin Hesablayıcıdeepin-calculator-5.7.21/translations/desktop/desktop_bg.ts000066400000000000000000000007271423020056600240700ustar00rootroot00000000000000desktopCalculatorКалкулаторDeepin CalculatorDeepin Калкулаторdeepin-calculator-5.7.21/translations/desktop/desktop_bn.ts000066400000000000000000000007721423020056600240770ustar00rootroot00000000000000desktopCalculatorক্যালকুলেটরDeepin Calculatorডিপিন ক্যালকুলেটরdeepin-calculator-5.7.21/translations/desktop/desktop_bo.ts000066400000000000000000000007601423020056600240750ustar00rootroot00000000000000desktopCalculatorརྩིས་ཆས།Deepin Calculatorགཏིང་ཟབ་རྩིས་ཆས།deepin-calculator-5.7.21/translations/desktop/desktop_br.ts000066400000000000000000000007011423020056600240730ustar00rootroot00000000000000desktopCalculatorJederezigDeepin CalculatorJederezig Deepindeepin-calculator-5.7.21/translations/desktop/desktop_ca.ts000066400000000000000000000007111423020056600240540ustar00rootroot00000000000000desktopCalculatorCalculadoraDeepin CalculatorCalculadora del Deepindeepin-calculator-5.7.21/translations/desktop/desktop_cs.ts000066400000000000000000000007051423020056600241010ustar00rootroot00000000000000desktopCalculatorKalkulačkaDeepin CalculatorDeepin kalkulačkadeepin-calculator-5.7.21/translations/desktop/desktop_da.ts000066400000000000000000000007051423020056600240600ustar00rootroot00000000000000desktopCalculatorLommeregnerDeepin CalculatorDeepin lommeregnerdeepin-calculator-5.7.21/translations/desktop/desktop_de.ts000066400000000000000000000007131423020056600240630ustar00rootroot00000000000000desktopCalculatorTaschenrechnerDeepin CalculatorDeepin Taschenrechnerdeepin-calculator-5.7.21/translations/desktop/desktop_el.ts000066400000000000000000000007371423020056600241010ustar00rootroot00000000000000desktopCalculatorΑριθμομηχανήDeepin CalculatorΑριθμομηχανή Deepindeepin-calculator-5.7.21/translations/desktop/desktop_en_AU.ts000066400000000000000000000007061423020056600244640ustar00rootroot00000000000000desktopCalculatorCalculatorDeepin CalculatorDeepin Calculatordeepin-calculator-5.7.21/translations/desktop/desktop_es.ts000066400000000000000000000006761423020056600241120ustar00rootroot00000000000000desktopCalculatorCalculadoraDeepin CalculatorCalculadoradeepin-calculator-5.7.21/translations/desktop/desktop_et.ts000066400000000000000000000007051423020056600241040ustar00rootroot00000000000000desktopCalculatorKalkulaatorDeepin CalculatorDeepin kalkulaatordeepin-calculator-5.7.21/translations/desktop/desktop_fa.ts000066400000000000000000000007311423020056600240610ustar00rootroot00000000000000desktopCalculatorماشین حسابDeepin Calculatorماشین حساب دیپینdeepin-calculator-5.7.21/translations/desktop/desktop_fi.ts000066400000000000000000000006731423020056600240760ustar00rootroot00000000000000desktopCalculatorLaskinDeepin CalculatorDeepin Laskindeepin-calculator-5.7.21/translations/desktop/desktop_fr.ts000066400000000000000000000007071423020056600241050ustar00rootroot00000000000000desktopCalculatorCalculatriceDeepin CalculatorCalculatrice Deepindeepin-calculator-5.7.21/translations/desktop/desktop_gl_ES.ts000066400000000000000000000007101423020056600244610ustar00rootroot00000000000000desktopCalculatorCalculadoraDeepin CalculatorDeepin Calculadoradeepin-calculator-5.7.21/translations/desktop/desktop_hi_IN.ts000066400000000000000000000007151423020056600244630ustar00rootroot00000000000000desktopCalculatorगणकDeepin Calculatorदीपिन गणकdeepin-calculator-5.7.21/translations/desktop/desktop_hr.ts000066400000000000000000000007031423020056600241030ustar00rootroot00000000000000desktopCalculatorKalkulatorDeepin CalculatorDeepin kalkulatordeepin-calculator-5.7.21/translations/desktop/desktop_hu.ts000066400000000000000000000007131423020056600241070ustar00rootroot00000000000000desktopCalculatorSzámológépDeepin CalculatorDeepin® Számológépdeepin-calculator-5.7.21/translations/desktop/desktop_id.ts000066400000000000000000000007031423020056600240660ustar00rootroot00000000000000desktopCalculatorKalkulatorDeepin CalculatorKalkulator Deepindeepin-calculator-5.7.21/translations/desktop/desktop_it.ts000066400000000000000000000007121423020056600241060ustar00rootroot00000000000000desktopCalculatorCalcolatriceDeepin CalculatorCalcolatrice di Deepindeepin-calculator-5.7.21/translations/desktop/desktop_ka.ts000066400000000000000000000007521423020056600240710ustar00rootroot00000000000000desktopCalculatorკალკულატორიDeepin Calculatorკალკულატორიdeepin-calculator-5.7.21/translations/desktop/desktop_km_KH.ts000066400000000000000000000010001423020056600244520ustar00rootroot00000000000000desktopCalculatorម៉ាស៊ីនគិតលេខDeepin Calculatorម៉ាស៊ីនគិតលេខ Deepindeepin-calculator-5.7.21/translations/desktop/desktop_ko.ts000066400000000000000000000007011423020056600241010ustar00rootroot00000000000000desktopCalculator계산기Deepin CalculatorDeepin 계산기deepin-calculator-5.7.21/translations/desktop/desktop_ku_IQ.ts000066400000000000000000000007141423020056600245040ustar00rootroot00000000000000desktopCalculatorژمێرەرDeepin Calculatorژمێرەری Deepindeepin-calculator-5.7.21/translations/desktop/desktop_ky.ts000066400000000000000000000007231423020056600241170ustar00rootroot00000000000000desktopCalculatorэсептегичDeepin CalculatorDeepin эсептегичdeepin-calculator-5.7.21/translations/desktop/desktop_lt.ts000066400000000000000000000007131423020056600241120ustar00rootroot00000000000000desktopCalculatorSkaičiuotuvasDeepin CalculatorDeepin skaičiuotuvasdeepin-calculator-5.7.21/translations/desktop/desktop_mn.ts000066400000000000000000000007351423020056600241110ustar00rootroot00000000000000desktopCalculatorТооцоолуурDeepin CalculatorДээпин тооцоолуурdeepin-calculator-5.7.21/translations/desktop/desktop_ms.ts000066400000000000000000000007031423020056600241110ustar00rootroot00000000000000desktopCalculatorKalkulatorDeepin CalculatorKalkulator Deepindeepin-calculator-5.7.21/translations/desktop/desktop_ne.ts000066400000000000000000000010001423020056600240630ustar00rootroot00000000000000desktopCalculatorक्याल्कुलेटरDeepin Calculatorडिपिन क्याल्कुलेटरdeepin-calculator-5.7.21/translations/desktop/desktop_nl.ts000066400000000000000000000007071423020056600241070ustar00rootroot00000000000000desktopCalculatorRekenmachineDeepin CalculatorDeepin Rekenmachinedeepin-calculator-5.7.21/translations/desktop/desktop_pl.ts000066400000000000000000000007031423020056600241050ustar00rootroot00000000000000desktopCalculatorKalkulatorDeepin CalculatorKalkulator Deepindeepin-calculator-5.7.21/translations/desktop/desktop_pt.ts000066400000000000000000000007101423020056600241130ustar00rootroot00000000000000desktopCalculatorCalculadoraDeepin CalculatorCalculadora do Deepindeepin-calculator-5.7.21/translations/desktop/desktop_pt_BR.ts000066400000000000000000000007101423020056600244760ustar00rootroot00000000000000desktopCalculatorCalculadoraDeepin Calculatordeepin Calculadoradeepin-calculator-5.7.21/translations/desktop/desktop_ro.ts000066400000000000000000000007071423020056600241160ustar00rootroot00000000000000desktopCalculatorCalculator Deepin CalculatorCalculatorul Deepin deepin-calculator-5.7.21/translations/desktop/desktop_ru.ts000066400000000000000000000007331423020056600241230ustar00rootroot00000000000000desktopCalculatorКалькуляторDeepin CalculatorКалькулятор Deepindeepin-calculator-5.7.21/translations/desktop/desktop_sk.ts000066400000000000000000000007051423020056600241110ustar00rootroot00000000000000desktopCalculatorKalkulačkaDeepin CalculatorDeepin Kalkulačkadeepin-calculator-5.7.21/translations/desktop/desktop_sl.ts000066400000000000000000000007031423020056600241100ustar00rootroot00000000000000desktopCalculatorKalkulatorDeepin CalculatorDeepin kalkulatordeepin-calculator-5.7.21/translations/desktop/desktop_sq.ts000066400000000000000000000007051423020056600241170ustar00rootroot00000000000000desktopCalculatorLlogaritësDeepin CalculatorLlogaritës Deepindeepin-calculator-5.7.21/translations/desktop/desktop_sr.ts000066400000000000000000000007331423020056600241210ustar00rootroot00000000000000desktopCalculatorКалкулаторDeepin CalculatorДипин Калкулаторdeepin-calculator-5.7.21/translations/desktop/desktop_sv.ts000066400000000000000000000007031423020056600241220ustar00rootroot00000000000000desktopCalculatorKalkylatorDeepin CalculatorDeepin Kalkylatordeepin-calculator-5.7.21/translations/desktop/desktop_tr.ts000066400000000000000000000007131423020056600241200ustar00rootroot00000000000000desktopCalculatorHesap MakinesiDeepin CalculatorDeepin Hesap Makinesideepin-calculator-5.7.21/translations/desktop/desktop_tzm.ts000066400000000000000000000007121423020056600243040ustar00rootroot00000000000000desktopCalculatorTamessiḍentDeepin CalculatorTamessiḍent Deepindeepin-calculator-5.7.21/translations/desktop/desktop_ug.ts000066400000000000000000000007311423020056600241060ustar00rootroot00000000000000desktopCalculatorھېسابلىغۇچDeepin CalculatorDeepin ھېسابلىغۇچىdeepin-calculator-5.7.21/translations/desktop/desktop_uk.ts000066400000000000000000000007331423020056600241140ustar00rootroot00000000000000desktopCalculatorКалькуляторDeepin CalculatorКалькулятор Deepindeepin-calculator-5.7.21/translations/desktop/desktop_vi.ts000066400000000000000000000007031423020056600241100ustar00rootroot00000000000000desktopCalculatorMáy tínhDeepin CalculatorMáy tính Deepindeepin-calculator-5.7.21/translations/desktop/desktop_zh_CN.ts000066400000000000000000000007031423020056600244730ustar00rootroot00000000000000desktopCalculator计算器Deepin Calculator深度计算器deepin-calculator-5.7.21/translations/desktop/desktop_zh_HK.ts000066400000000000000000000007041423020056600244760ustar00rootroot00000000000000desktopCalculator計數機Deepin CalculatorDeepin 計數機deepin-calculator-5.7.21/translations/desktop/desktop_zh_TW.ts000066400000000000000000000007041423020056600245260ustar00rootroot00000000000000desktopCalculator計算器Deepin CalculatorDeepin 計算器