Commit cd9a93d3 authored by Rohan Asokan's avatar Rohan Asokan
Browse files

Merge remote-tracking branch 'upstream/master'

parents bbc747b9 c67102a7
......@@ -9,6 +9,7 @@
<name xml:lang="en-GB">Calculator</name>
<name xml:lang="es">Calculadora</name>
<name xml:lang="eu">Kalkulagailua</name>
<name xml:lang="fi">Laskin</name>
<name xml:lang="fr">Calculatrice</name>
<name xml:lang="hu">Számológép</name>
<name xml:lang="id">Calculator</name>
......@@ -31,6 +32,7 @@
<summary xml:lang="en-GB">A feature rich calculator</summary>
<summary xml:lang="es">Una calculadora con numerosas funciones</summary>
<summary xml:lang="eu">Ezaugarritan aberatsa den kalkulagailua bat</summary>
<summary xml:lang="fi">Monipuolinen laskin</summary>
<summary xml:lang="fr">Une calculatrice avec de nombreuses fonctionnalités.</summary>
<summary xml:lang="hu">Funkciógazdag számológép</summary>
<summary xml:lang="id">Sebuah kalkulator yang kaya fitur</summary>
......@@ -54,6 +56,7 @@
<developer_name xml:lang="en-GB">KDE Community</developer_name>
<developer_name xml:lang="es">Comunidad KDE</developer_name>
<developer_name xml:lang="eu">KDE komunitatea</developer_name>
<developer_name xml:lang="fi">KDE-yhteisö</developer_name>
<developer_name xml:lang="fr">Communauté KDE</developer_name>
<developer_name xml:lang="hu">A KDE Közösség</developer_name>
<developer_name xml:lang="id">Komunitas KDE</developer_name>
......@@ -77,6 +80,7 @@
<p xml:lang="en-GB">Kalk is a powerful calculator designed for mobile platform.</p>
<p xml:lang="es">Kalk es una potente calculadora designada para la plataforma móvil.</p>
<p xml:lang="eu">Kalk, mugikorretako plataformarako diseinatutako kalkulagailu ahaltsu bat da.</p>
<p xml:lang="fi">Kalk on mobiilialustalle suunniteltu tehokas laskin.</p>
<p xml:lang="fr">Kalk est une calculatrice puissante conçue pour les plate-formes mobiles.</p>
<p xml:lang="hu">A Kalk egy hatékony számológép mobil platformokra tervezve.</p>
<p xml:lang="id">Kalk adalah kalkulator hebat yang dirancang untuk platform seluler.</p>
......
......@@ -7,6 +7,7 @@ Name[de]=Rechner
Name[en_GB]=Calculator
Name[es]=Calculadora
Name[eu]=Kalkulagailua
Name[fi]=Laskin
Name[fr]=Calculatrice
Name[hu]=Számológép
Name[it]=Calcolatrice
......@@ -28,6 +29,7 @@ Comment[de]=Ein Rechner in Krigami.
Comment[en_GB]=A Calculator in Kirigami.
Comment[es]=Una calculadora en Kirigami.
Comment[eu]=Kirigami-rekin egindako kalkulagailu bat.
Comment[fi]=Kirigamilla toteutettu laskin.
Comment[fr]=Une calculatrice dans Kirigami.
Comment[hu]=Számológép Kirigamiban.
Comment[it]=Una calcolatrice in Kirigami.
......
......@@ -28,7 +28,6 @@ set(kalk_SRCS
main.cpp
historymanager.cpp
unitmodel.cpp
typemodel.cpp
mathengine.cpp
inputmanager.cpp
${CMAKE_CURRENT_BINARY_DIR}/parser.cc
......
......@@ -6,9 +6,8 @@
<file>qml/NumberButton.qml</file>
<file>qml/CalculationPage.qml</file>
<file>qml/FunctionPad.qml</file>
<file>qml/UnitTypeGrid.qml</file>
<file>qml/UnitConversion.qml</file>
<file>qml/AboutPage.qml</file>
<file>qml/BinaryCalculator.qml</file>
<file>qml/UnitConverter.qml</file>
</qresource>
</RCC>
......@@ -15,7 +15,6 @@
#include "historymanager.h"
#include "mathengine.h"
#include "typemodel.h"
#include "inputmanager.h"
#include "unitmodel.h"
int main(int argc, char *argv[])
......@@ -23,18 +22,13 @@ int main(int argc, char *argv[])
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
auto *typeModel = new TypeModel();
auto *unitModel = new UnitModel();
QObject::connect(typeModel, &TypeModel::categoryChanged, unitModel, &UnitModel::changeUnit);
// create qml app engine
QQmlApplicationEngine engine;
KLocalizedString::setApplicationDomain("kalk");
engine.rootContext()->setContextObject(new KLocalizedContext(&engine));
engine.rootContext()->setContextProperty("historyManager", HistoryManager::inst());
engine.rootContext()->setContextProperty("inputManager", InputManager::inst());
engine.rootContext()->setContextProperty("typeModel", typeModel);
engine.rootContext()->setContextProperty("unitModel", unitModel);
engine.rootContext()->setContextProperty("unitModel", UnitModel::inst());
KAboutData aboutData("kalk", i18n("Calculator"), "0.1", i18n("Calculator in Kirigami"), KAboutLicense::GPL, i18n("© 2020 KDE Community"));
KAboutData::setApplicationData(aboutData);
......
......@@ -91,7 +91,8 @@ exp:
| exp exp { $$ = $1 * $2; }
| exp "*" exp { $$ = $1 * $3; }
| exp "/" exp { $$ = $1 / $3; }
| exp "^" exp { $$ = pow($1, $3); }
| exp "^" factor { $$ = pow($1, $3); }
| exp "^" { $$ = $1; }
| "SIN" "(" exp { $$ = sin($3); }
| "SIN" "(" exp ")" { $$ = sin($3); }
| "COS" "(" exp { $$ = cos($3); }
......
......@@ -9,124 +9,56 @@ import QtQuick.Controls 2.15 as Controls
import org.kde.kirigami 2.13 as Kirigami
Kirigami.Page {
id: unitConversionPage
title: i18n("Acceleration")
visible: false
onTitleChanged: {
fromSearchField.text = "";
toSearchField.text = "";
value.text = "";
result.text = "";
}
id: unitConverter
ColumnLayout {
anchors.fill: parent
Controls.ComboBox {
id: categoryTumbler
Layout.preferredWidth: unitConverter.width * 0.9
model: unitModel
currentIndex: unitModel.currentIndex
onCurrentIndexChanged: {
unitModel.currentIndex = currentIndex;
}
}
RowLayout {
id: searchRow
Layout.fillWidth: true
Layout.bottomMargin: Kirigami.Units.gridUnit * 2
RowLayout {
Controls.Label {
text: i18n("From: ")
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.5
}
Kirigami.SearchField {
id: fromSearchField
Layout.fillWidth: true
onTextEdited: {
fromListView.model = unitModel.search(fromSearchField.text, 0);
fromListViewPopup.open();
}
onPressed: {
fromListView.model = unitModel.search(fromSearchField.text, 0);
fromListViewPopup.open();
}
Controls.Tumbler {
id: fromTumbler
Layout.preferredWidth: unitConverter.width * 0.5
model: unitModel.typeList
currentIndex: unitModel.fromUnitIndex
delegate: delegateComponent
onCurrentIndexChanged: {
unitModel.fromUnitIndex = currentIndex;
}
}
RowLayout {
Controls.Label {
text: i18n("To: ")
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.5
}
Kirigami.SearchField {
id: toSearchField
Layout.fillWidth: true
onTextEdited: {
toListView.model = unitModel.search(toSearchField.text, 1);
toListViewPopup.open();
}
onPressed: {
toListView.model = unitModel.search(toSearchField.text, 1);
toListViewPopup.open();
}
Controls.Tumbler {
id: toTumbler
Layout.preferredWidth: unitConverter.width * 0.5
model: unitModel.typeList
currentIndex: unitModel.toUnitIndex
delegate: delegateComponent
onCurrentIndexChanged: {
unitModel.toUnitIndex = currentIndex;
}
}
}
ColumnLayout {
Layout.preferredWidth: parent.width
Controls.Popup {
id: fromListViewPopup
height: fromListView.height
width: parent.width
anchors.centerIn: parent
ListView {
id: fromListView
width: parent.width
height: Math.min(contentHeight, unitNumberPad.height) + Kirigami.Units.gridUnit
delegate: Kirigami.BasicListItem {
text: modelData
onClicked: {
fromSearchField.text = modelData;
result.text = unitModel.getRet(Number(value.text),fromListView.currentIndex,toListView.currentIndex);
fromListViewPopup.close();
}
}
}
}
Controls.Popup {
id: toListViewPopup
height: toListView.height
width: parent.width
anchors.centerIn: parent
ListView {
id: toListView
width: parent.width
height: Math.min(contentHeight, unitNumberPad.height) + Kirigami.Units.gridUnit
delegate: Kirigami.BasicListItem {
text: modelData
onClicked: {
toSearchField.text = modelData;
result.text = unitModel.getRet(Number(value.text),fromListView.currentIndex,toListView.currentIndex);
toListViewPopup.close();
}
}
}
}
RowLayout {
Layout.fillWidth: true
Controls.Label {
id: value
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.5
onTextChanged: {
result.text = unitModel.getRet(Number(value.text),fromListView.currentIndex, toListView.currentIndex);
}
}
Controls.Label {
text: fromSearchField.text
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.5
}
}
Controls.Label {
id: result
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.5
Component {
id: delegateComponent
Text {
text: modelData
opacity: 0.4 + Math.max(0, 1 - Math.abs(Controls.Tumbler.displacement)) * 0.6
}
}
Text {
text: unitModel.value
color: Kirigami.Theme.textColor
}
Text {
text: unitModel.result
color: Kirigami.Theme.textColor
}
Kirigami.Separator {
Layout.fillWidth: true
......@@ -134,31 +66,33 @@ Kirigami.Page {
GridLayout {
id: unitNumberPad
Layout.fillHeight: true
Layout.fillWidth: true
columns: 3
function pressed(text) {
if (text == "DEL") {
value.text = value.text.slice(0, value.text.length - 1);
unitModel.value = unitModel.value.slice(0, unitModel.value.length - 1);
} else {
value.text += text;
unitModel.value += text;
}
}
function clear() {
value.text = "";
unitModel.value = "";
}
NumberButton {text: "7" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "8" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "9" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "4" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "5" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "6" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "1" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "2" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "3" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "." ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "0" ; onClicked: unitNumberPad.pressed(text);}
NumberButton {text: "DEL"; display: ""; onClicked: unitNumberPad.pressed(text); onLongClicked: unitNumberPad.clear(); special: true; }
......
/*
* SPDX-FileCopyrightText: 2020-2021 Han Young <hanyoung@protonmail.com>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import QtQuick 2.7
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.15 as Controls
import org.kde.kirigami 2.13 as Kirigami
Kirigami.ScrollablePage {
id: root
title: i18n("Units Converter")
Kirigami.CardsListView {
id: typeView
Loader {
id: unitConvertorLoader
source: "qrc:/qml/UnitConversion.qml"
}
topMargin: Kirigami.Units.gridUnit
model: typeModel
delegate: Kirigami.AbstractCard {
id: listItem
contentItem: Text {
text: name
color: Kirigami.Theme.textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
font.pointSize: Kirigami.Theme.defaultFont.pointSize * 2
}
MouseArea {
id: mouse
anchors.fill: parent
hoverEnabled: true
onClicked: {
typeModel.currentIndex(index);
unitConvertorLoader.item["title"] = name;
applicationWindow().pageStack.layers.push(unitConvertorLoader.item);
}
onEntered: {
listItem.highlighted = true;
}
onExited: {
listItem.highlighted = false;
}
}
}
}
}
......@@ -47,7 +47,7 @@ Kirigami.ApplicationWindow {
Kirigami.PagePoolAction {
text: i18n("Convertor")
iconName: "gtk-convert"
page: "qrc:/qml/UnitTypeGrid.qml"
page: "qrc:/qml/UnitConverter.qml"
pagePool: mainPagePool
},
Kirigami.PagePoolAction {
......
/*
* SPDX-FileCopyrightText: 2020-2021 Han Young <hanyoung@protonmail.com>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "typemodel.h"
#include "unitmodel.h"
#include <KLocalizedContext>
#include <KLocalizedString>
#include <kunitconversion/value.h>
TypeModel::TypeModel()
{
}
QVariant TypeModel::data(const QModelIndex &index, int role) const
{
Q_UNUSED(role)
return i18n((unitsType.at(index.row())).toLatin1());
}
int TypeModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return unitsType.size();
}
QHash<int, QByteArray> TypeModel::roleNames() const
{
return {{Qt::DisplayRole, "name"}};
}
void TypeModel::currentIndex(int index)
{
emit categoryChanged(unitsType.at(index));
};
const std::array<QString, 25> TypeModel::unitsType = {"Acceleration",
"Angle",
"Area",
"Binary Data",
"Currency",
"Density",
"Electrical Current",
"Electrical Resistance",
"Energy",
"Force",
"Frequency",
"Fuel Efficiency",
"Length",
"Mass",
"Permeability",
"Power",
"Pressure",
"Temperature",
"Thermal Conductivity",
"Thermal Flux",
"Thermal Generation",
"Time",
"Velocity",
"Volume",
"Voltage"};
/*
* SPDX-FileCopyrightText: 2020-2021 Han Young <hanyoung@protonmail.com>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef UNITMODEL_H
#define UNITMODEL_H
#include <QAbstractListModel>
#include <QObject>
#include <array>
#include <kunitconversion/converter.h>
#include <unordered_map>
using namespace KUnitConversion;
class TypeModel : public QAbstractListModel
{
Q_OBJECT
public:
TypeModel();
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void currentIndex(int index);
signals:
void categoryChanged(QString type);
private:
KUnitConversion::Converter mConverter;
static const std::array<QString, 25> unitsType;
};
#endif // UNITMODEL_H
......@@ -6,17 +6,24 @@
#include "unitmodel.h"
#include <KLocalizedContext>
#include <KLocalizedString>
#include <kunitconversion/converter.h>
#include <QDebug>
UnitModel::UnitModel()
{
m_units = KUnitConversion::Converter().category(KUnitConversion::AccelerationCategory).units();
connect(this, &UnitModel::unitIndexChanged, this, &UnitModel::calculateResult);
connect(this, &UnitModel::valueChanged, this, &UnitModel::calculateResult);
auto units = KUnitConversion::Converter().category(std::get<1>(categoryAndEnum.at(m_currentIndex))).units();
for(const auto &unit : qAsConst(units))
{
m_unitIDs.push_back(unit.id());
m_units.push_back(unit.symbol());
}
}
QVariant UnitModel::data(const QModelIndex &index, int role) const
{
Q_UNUSED(role)
if (index.row() >= 0 && index.row() < m_units.count())
return m_units.at(index.row()).symbol() + " " + m_units.at(index.row()).description();
if (index.row() >= 0 && index.row() < static_cast<int>(categoryAndEnum.size()))
return std::get<0>(categoryAndEnum.at(index.row()));
else
return QVariant();
}
......@@ -24,70 +31,95 @@ QVariant UnitModel::data(const QModelIndex &index, int role) const
int UnitModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_units.count();
return static_cast<int>(categoryAndEnum.size());
}
QHash<int, QByteArray> UnitModel::roleNames() const
{
return {{Qt::DisplayRole, "name"}};
}
void UnitModel::changeUnit(QString type)
void UnitModel::setValue(QString value)
{
Q_EMIT layoutAboutToBeChanged();
m_units = KUnitConversion::Converter().category(static_cast<KUnitConversion::CategoryId>(categoryToEnum.find(type)->second)).units();
Q_EMIT layoutChanged();
m_value = std::move(value);
Q_EMIT valueChanged();
}
QString UnitModel::getRet(double val, int fromTypeIndex, int toTypeIndex)
void UnitModel::setCurrentIndex(int i)
{
if (fromTypeIndex < 0 || toTypeIndex < 0 || fromTypeIndex >= m_fromUnitID.size() || toTypeIndex >= m_toUnitID.size())
return {};
if(i < 0 || i > static_cast<int>(categoryAndEnum.size()))
return;
if(m_currentIndex != i)
{
m_unitIDs.clear();
m_units.clear();
m_currentIndex = i;
m_value.clear();
m_fromUnitIndex = 0;
m_toUnitIndex = 1;
KUnitConversion::Value fromVal(val, m_fromUnitID.at(fromTypeIndex));
return fromVal.convertTo(m_toUnitID.at(toTypeIndex)).toString();
};
auto units = KUnitConversion::Converter().category(std::get<1>(categoryAndEnum.at(m_currentIndex))).units();
for(const auto &unit : qAsConst(units))
{
m_unitIDs.push_back(unit.id());
m_units.push_back(unit.symbol());
}
QStringList UnitModel::search(QString keyword, int field)
calculateResult();
Q_EMIT currentIndexChanged();
Q_EMIT unitIndexChanged();
Q_EMIT typeListChanged();
Q_EMIT valueChanged();
}
}
void UnitModel::setFromUnitIndex(int i)
{
QStringList list;
QVector<KUnitConversion::UnitId> *vec;
if (field == 0)
vec = &m_fromUnitID;
else
vec = &m_toUnitID;
m_fromUnitIndex = i;
calculateResult();
}
void UnitModel::setToUnitIndex(int i)
{
m_toUnitIndex = i;
calculateResult();
}
void UnitModel::calculateResult()
{
if(m_value.size())
{
auto units = KUnitConversion::Converter().category(std::get<1>(categoryAndEnum.at(m_currentIndex))).units();
vec->clear();
if(m_fromUnitIndex < 0 || m_toUnitIndex < 0 || m_fromUnitIndex > units.size() || m_toUnitIndex > units.size())
return;
for (auto &unit : m_units) {
if (unit.description().indexOf(keyword) != -1 || unit.symbol().indexOf(keyword) != -1) {
list.append(unit.symbol() + " " + unit.description());
vec->append(unit.id());
}
auto from = KUnitConversion::Value(m_value.toDouble(), units.at(m_fromUnitIndex));
m_result = KUnitConversion::Converter().convert(from,units.at(m_toUnitIndex)).toString();
qDebug() << m_result;
} else
{
m_result.clear();
}
return list;
Q_EMIT resultChanged();
}
const std::unordered_map<QString, int> UnitModel::categoryToEnum = {{"Acceleration", KUnitConversion::AccelerationCategory},
{"Angle", KUnitConversion::AngleCategory},
{"Area", KUnitConversion::AreaCategory},
{"Binary Data", KUnitConversion::BinaryDataCategory},
{"Currency", KUnitConversion::CurrencyCategory},
{"Density", KUnitConversion::DensityCategory},
{"Electrical Current", KUnitConversion::ElectricalCurrentCategory},
{"Electrical Resistance", KUnitConversion::ElectricalResistanceCategory},
{"Energy", KUnitConversion::EnergyCategory},
{"Force", KUnitConversion::ForceCategory},
{"Frequency", KUnitConversion::FrequencyCategory},
{"Fuel Efficiency", KUnitConversion::FuelEfficiencyCategory},
{"Length", KUnitConversion::LengthCategory},
{"Mass", KUnitConversion::MassCategory},
{"Permeability", KUnitConversion::PermeabilityCategory},
{"Power", KUnitConversion::PowerCategory},
{"Pressure", KUnitConversion::PressureCategory},
{"Temperature", KUnitConversion::TemperatureCategory},
{"Thermal Conductivity", KUnitConversion::ThermalConductivityCategory},