diff --git a/dialer/src/CMakeLists.txt b/dialer/src/CMakeLists.txt index 99a72bd..6f5cd88 100644 --- a/dialer/src/CMakeLists.txt +++ b/dialer/src/CMakeLists.txt @@ -1,34 +1,34 @@ set(plasmaphonedialer_SRCS main.cpp dialerutils.cpp call-handler.cpp call-manager.cpp + resources.qrc ) -qt5_add_resources(RESOURCES resources.qrc) -add_executable(plasmaphonedialer ${plasmaphonedialer_SRCS} ${RESOURCES}) +add_executable(plasmaphonedialer ${plasmaphonedialer_SRCS}) target_compile_definitions(plasmaphonedialer PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}") find_package(PhoneNumber COMPONENTS PhoneNumber REQUIRED) target_link_libraries(plasmaphonedialer PhoneNumber::PhoneNumber Qt5::Gui Qt5::Quick Qt5::Widgets KF5::Declarative KF5::I18n KF5::QuickAddons KF5::DBusAddons KF5::Notifications ${TELEPATHY_QT5_LIBRARIES} ) install(TARGETS plasmaphonedialer ${INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES plasma_dialer.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFY5RCDIR}) configure_file(org.freedesktop.Telepathy.Client.Plasma.Dialer.service.in org.freedesktop.Telepathy.Client.Plasma.Dialer.service) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/org.freedesktop.Telepathy.Client.Plasma.Dialer.service DESTINATION ${DBUS_SERVICES_INSTALL_DIR}) install(FILES Plasma.Dialer.client DESTINATION ${SHARE_INSTALL_PREFIX}/telepathy/clients/) diff --git a/dialer/src/main.cpp b/dialer/src/main.cpp index 2bff2b2..905f1e4 100644 --- a/dialer/src/main.cpp +++ b/dialer/src/main.cpp @@ -1,223 +1,214 @@ /* * Copyright 2015 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "dialerutils.h" #include "call-handler.h" #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QFile file(QDir::homePath() + "/dialer.log"); bool opened = file.open(QIODevice::WriteOnly | QIODevice::Append); Q_ASSERT(opened); QString strout; QTextStream out(&strout); out << QTime::currentTime().toString("hh:mm:ss.zzz "); out << context.function << ":" << context.line << " "; switch (type) { case QtDebugMsg: out << "DBG"; break; case QtInfoMsg: out << "NFO"; break; case QtWarningMsg: out << "WRN"; break; case QtCriticalMsg: out << "CRT"; break; case QtFatalMsg: out << "FTL"; break; } out << " " << msg << '\n'; // Write to log file QTextStream fileout(&file); fileout << strout; out.flush(); // Write to stdout QTextStream console(stdout); console << strout; console.flush(); } int main(int argc, char **argv) { qInstallMessageHandler(myMessageOutput); QCommandLineParser parser; QApplication app(argc, argv); const QString description = i18n("Plasma Phone Dialer"); const char version[] = PROJECT_VERSION; // app.setQuitOnLastWindowClosed(false); app.setApplicationVersion(version); app.setOrganizationDomain("kde.org"); KDBusService service(KDBusService::Unique); parser.addVersionOption(); parser.addHelpOption(); parser.setApplicationDescription(description); QCommandLineOption daemonOption(QStringList() << QStringLiteral("d") << QStringLiteral("daemon"), i18n("Daemon mode. run without displaying anything.")); parser.addPositionalArgument("number", i18n("Call the given number")); parser.addOption(daemonOption); parser.process(app); Tp::registerTypes(); Tp::AccountFactoryPtr accountFactory = Tp::AccountFactory::create(QDBusConnection::sessionBus(), Tp::Features() << Tp::Account::FeatureCore ); Tp::ConnectionFactoryPtr connectionFactory = Tp::ConnectionFactory::create(QDBusConnection::sessionBus(), Tp::Features() << Tp::Connection::FeatureCore << Tp::Connection::FeatureSelfContact << Tp::Connection::FeatureConnected ); Tp::ChannelFactoryPtr channelFactory = Tp::ChannelFactory::create(QDBusConnection::sessionBus()); channelFactory->addCommonFeatures(Tp::Channel::FeatureCore); channelFactory->addFeaturesForCalls(Tp::Features() << Tp::CallChannel::FeatureContents << Tp::CallChannel::FeatureCallState << Tp::CallChannel::FeatureCallMembers << Tp::CallChannel::FeatureLocalHoldState ); // channelFactory->addFeaturesForTextChats(Tp::Features() << Tp::TextChannel::FeatureMessageQueue // << Tp::TextChannel::FeatureMessageSentSignal // << Tp::TextChannel::FeatureChatState // << Tp::TextChannel::FeatureMessageCapabilities); Tp::ContactFactoryPtr contactFactory = Tp::ContactFactory::create(Tp::Features() << Tp::Contact::FeatureAlias << Tp::Contact::FeatureAvatarData ); Tp::ClientRegistrarPtr registrar = Tp::ClientRegistrar::create(accountFactory, connectionFactory, channelFactory, contactFactory); QEventLoop loop; Tp::AccountManagerPtr manager = Tp::AccountManager::create(); Tp::PendingReady *ready = manager->becomeReady(); QObject::connect(ready, &Tp::PendingReady::finished, &loop, &QEventLoop::quit); loop.exec(QEventLoop::ExcludeUserInputEvents); Tp::AccountPtr simAccount; const Tp::AccountSetPtr accountSet = manager->validAccounts(); for (const Tp::AccountPtr &account : accountSet->accounts()) { static const QStringList supportedProtocols = { QLatin1String("ofono"), QLatin1String("tel"), }; if (supportedProtocols.contains(account->protocolName())) { simAccount = account; break; } } if (simAccount.isNull()) { qCritical() << "Unable to get SIM account"; return -1; } - const QString packagePath("org.kde.phone.dialer"); - //usually we have an ApplicationWindow here, so we do not need to create a window by ourselves - auto *obj = new KDeclarative::QmlObject(); - obj->setTranslationDomain(packagePath); - obj->setInitializationDelayed(true); - obj->setSource(QUrl("qrc:///main.qml")); - obj->engine()->rootContext()->setContextProperty("commandlineArguments", parser.positionalArguments()); + QQmlApplicationEngine engine; + engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); auto *dialerUtils = new DialerUtils(simAccount); - obj->engine()->rootContext()->setContextProperty("dialerUtils", QVariant::fromValue(dialerUtils)); + engine.rootContext()->setContextProperty("dialerUtils", QVariant::fromValue(dialerUtils)); + engine.rootContext()->setContextProperty("commandlineArguments", parser.positionalArguments()); - obj->completeInitialization(); + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); Tp::SharedPtr callHandler(new CallHandler(dialerUtils)); registrar->registerClient(Tp::AbstractClientPtr::dynamicCast(callHandler), "Plasma.Dialer"); KAboutData aboutData("dialer", i18n("Dialer"), "0.9", i18n("Plasma phone dialer"), KAboutLicense::GPL); aboutData.setDesktopFileName("org.kde.phone.dialer"); KAboutData::setApplicationData(aboutData); - //The root is not a window? - //have to use a normal QQuickWindow since the root item is already created - QWindow *window = qobject_cast(obj->rootObject()); - if (window) { - QObject::connect(&service, &KDBusService::activateRequested, [=](const QStringList &arguments, const QString &workingDirectory) { - Q_UNUSED(workingDirectory); - window->show(); - window->requestActivate(); - if (arguments.length() > 0) { - QString numberArg = arguments[1]; - if (numberArg.startsWith("call://")) { - numberArg = numberArg.mid(7); - } - obj->rootObject()->metaObject()->invokeMethod(obj->rootObject(), "call", Q_ARG(QVariant, numberArg)); - } - }); - if (!parser.isSet(daemonOption)) { - window->show(); - window->requestActivate(); - } - window->setTitle(obj->package().metadata().name()); - window->setIcon(QIcon::fromTheme(obj->package().metadata().iconName())); + QWindow *window = qobject_cast(engine.rootObjects()[0]); + + Q_ASSERT(window); - if (!parser.positionalArguments().isEmpty()) { - QString numberArg = parser.positionalArguments().first(); + QObject::connect(&service, &KDBusService::activateRequested, [=](const QStringList &arguments, const QString &workingDirectory) { + Q_UNUSED(workingDirectory); + window->show(); + window->requestActivate(); + if (arguments.length() > 0) { + QString numberArg = arguments[1]; if (numberArg.startsWith("call://")) { numberArg = numberArg.mid(7); } - qWarning() << "Calling" << numberArg; - obj->rootObject()->metaObject()->invokeMethod(obj->rootObject(), "call", Q_ARG(QVariant, numberArg)); + dialerUtils->dial(numberArg); + } + }); + if (!parser.isSet(daemonOption)) { + window->show(); + window->requestActivate(); + } + if (!parser.positionalArguments().isEmpty()) { + QString numberArg = parser.positionalArguments().first(); + if (numberArg.startsWith("call://")) { + numberArg = numberArg.mid(7); } - } else { - qWarning() << "Error loading the ApplicationWindow"; + qWarning() << "Calling" << numberArg; + dialerUtils->dial(numberArg); } return app.exec(); } diff --git a/dialer/src/contents/ui/Call/AnswerSwipe.qml b/dialer/src/qml/Call/AnswerSwipe.qml similarity index 100% rename from dialer/src/contents/ui/Call/AnswerSwipe.qml rename to dialer/src/qml/Call/AnswerSwipe.qml diff --git a/dialer/src/contents/ui/Call/Avatar.qml b/dialer/src/qml/Call/Avatar.qml similarity index 100% rename from dialer/src/contents/ui/Call/Avatar.qml rename to dialer/src/qml/Call/Avatar.qml diff --git a/dialer/src/contents/ui/Call/CallPage.qml b/dialer/src/qml/Call/CallPage.qml similarity index 100% rename from dialer/src/contents/ui/Call/CallPage.qml rename to dialer/src/qml/Call/CallPage.qml diff --git a/dialer/src/contents/ui/Dialer/ContactsList.qml b/dialer/src/qml/Dialer/ContactsList.qml similarity index 100% rename from dialer/src/contents/ui/Dialer/ContactsList.qml rename to dialer/src/qml/Dialer/ContactsList.qml diff --git a/dialer/src/contents/ui/Dialer/CustomSectionScroller.qml b/dialer/src/qml/Dialer/CustomSectionScroller.qml similarity index 100% rename from dialer/src/contents/ui/Dialer/CustomSectionScroller.qml rename to dialer/src/qml/Dialer/CustomSectionScroller.qml diff --git a/dialer/src/contents/ui/Dialer/DialPage.qml b/dialer/src/qml/Dialer/DialPage.qml similarity index 100% rename from dialer/src/contents/ui/Dialer/DialPage.qml rename to dialer/src/qml/Dialer/DialPage.qml diff --git a/dialer/src/contents/ui/Dialer/Dialer.qml b/dialer/src/qml/Dialer/Dialer.qml similarity index 100% rename from dialer/src/contents/ui/Dialer/Dialer.qml rename to dialer/src/qml/Dialer/Dialer.qml diff --git a/dialer/src/contents/ui/Dialer/History.qml b/dialer/src/qml/Dialer/History.qml similarity index 100% rename from dialer/src/contents/ui/Dialer/History.qml rename to dialer/src/qml/Dialer/History.qml diff --git a/dialer/src/contents/ui/Dialer/HistoryDelegate.qml b/dialer/src/qml/Dialer/HistoryDelegate.qml similarity index 100% rename from dialer/src/contents/ui/Dialer/HistoryDelegate.qml rename to dialer/src/qml/Dialer/HistoryDelegate.qml diff --git a/dialer/src/contents/ui/Dialer/RoundImage.qml b/dialer/src/qml/Dialer/RoundImage.qml similarity index 100% rename from dialer/src/contents/ui/Dialer/RoundImage.qml rename to dialer/src/qml/Dialer/RoundImage.qml diff --git a/dialer/src/contents/ui/Dialer/private/SectionScroller.js b/dialer/src/qml/Dialer/private/SectionScroller.js similarity index 100% rename from dialer/src/contents/ui/Dialer/private/SectionScroller.js rename to dialer/src/qml/Dialer/private/SectionScroller.js diff --git a/dialer/src/contents/ui/Dialpad/DialerButton.qml b/dialer/src/qml/Dialpad/DialerButton.qml similarity index 100% rename from dialer/src/contents/ui/Dialpad/DialerButton.qml rename to dialer/src/qml/Dialpad/DialerButton.qml diff --git a/dialer/src/contents/ui/Dialpad/DialerIconButton.qml b/dialer/src/qml/Dialpad/DialerIconButton.qml similarity index 100% rename from dialer/src/contents/ui/Dialpad/DialerIconButton.qml rename to dialer/src/qml/Dialpad/DialerIconButton.qml diff --git a/dialer/src/contents/ui/Dialpad/Dialpad.qml b/dialer/src/qml/Dialpad/Dialpad.qml similarity index 100% rename from dialer/src/contents/ui/Dialpad/Dialpad.qml rename to dialer/src/qml/Dialpad/Dialpad.qml diff --git a/dialer/src/contents/ui/Dialpad/PhoneNumberInput.qml b/dialer/src/qml/Dialpad/PhoneNumberInput.qml similarity index 100% rename from dialer/src/contents/ui/Dialpad/PhoneNumberInput.qml rename to dialer/src/qml/Dialpad/PhoneNumberInput.qml diff --git a/dialer/src/contents/ui/main.qml b/dialer/src/qml/main.qml similarity index 99% rename from dialer/src/contents/ui/main.qml rename to dialer/src/qml/main.qml index 47746a4..c19503f 100644 --- a/dialer/src/contents/ui/main.qml +++ b/dialer/src/qml/main.qml @@ -1,193 +1,195 @@ /** * Copyright 2014 Aaron Seigo * Copyright 2014 Marco Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.3 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.1 import QtQuick.LocalStorage 2.0 import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.kirigami 2.0 as Kirigami ApplicationWindow { id: root //BEGIN PROPERTIES width: 1080 height: 800 + visible: false + //keep track if we were visible when ringing property bool wasVisible //was the last call an incoming one? property bool isIncoming //END PROPERTIES //BEGIN SIGNAL HANDLERS Connections { target: dialerUtils onMissedCallsActionTriggered: { root.visible = true; } onCallEnded: { var callType; if (isIncomingCall && callDuration == 0) { callType = 0; } else if (isIncomingCall && callDuration > 0) { callType = 1; } else { callType = 2; } insertCallInHistory(callContactNumber, callDuration, callType); } } onVisibleChanged: { //TODO //reset missed calls if the status is not STATUS_INCOMING when got visible } //END SIGNAL HANDLERS //BEGIN FUNCTIONS function call(number) { dialerUtils.dial(number); } function insertCallInHistory(number, duration, callType) { //DATABSE var db = LocalStorage.openDatabaseSync("PlasmaPhoneDialer", "1.0", "Call history of the Plasma Phone dialer", 1000000); db.transaction( function(tx) { var rs = tx.executeSql("INSERT INTO History VALUES(NULL, ?, datetime('now'), ?, ? )", [number, duration, callType]); var rs = tx.executeSql('SELECT * FROM History where id=?', [rs.insertId]); for(var i = 0; i < rs.rows.length; i++) { var row = rs.rows.item(i); row.date = Qt.formatDate(row.time, "yyyy-MM-dd"); row.originalIndex = historyModel.count; historyModel.append(row); } } ) } //index is historyModel row number, not db id and not sortmodel row number function removeCallFromHistory(index) { var item = historyModel.get(index); if (!item) { return; } var db = LocalStorage.openDatabaseSync("PlasmaPhoneDialer", "1.0", "Call history of the Plasma Phone dialer", 1000000); db.transaction( function(tx) { tx.executeSql("DELETE from History WHERE id=?", [item.id]); } ) historyModel.remove(index); } function clearHistory() { var db = LocalStorage.openDatabaseSync("PlasmaPhoneDialer", "1.0", "Call history of the Plasma Phone dialer", 1000000); db.transaction( function(tx) { tx.executeSql("DELETE from History"); } ) historyModel.clear(); } //END FUNCTIONS //BEGIN DATABASE Component.onCompleted: { //DATABSE var db = LocalStorage.openDatabaseSync("PlasmaPhoneDialer", "1.0", "Call history of the Plasma Phone dialer", 1000000); db.transaction( function(tx) { // Create the database if it doesn't already exist //callType: wether is incoming, outgoing, unanswered tx.executeSql('CREATE TABLE IF NOT EXISTS History(id INTEGER PRIMARY KEY AUTOINCREMENT, number TEXT, time DATETIME, duration INTEGER, callType INTEGER)'); var rs = tx.executeSql('SELECT * FROM History'); for(var i = 0; i < rs.rows.length; i++) { var row = rs.rows.item(i); row.date = Qt.formatDate(row.time, "yyyy-MM-dd"); row.originalIndex = historyModel.count; historyModel.append(row); } } ) } //END DATABASE //BEGIN MODELS ListModel { id: historyModel } //END MODELS //BEGIN UI PlasmaExtras.ConditionalLoader { anchors.fill: parent property bool shouldShow: root.visible && (dialerUtils.callState == "idle" || dialerUtils.callState == "failed") when: shouldShow source: Qt.resolvedUrl("Dialer/DialPage.qml") z: shouldShow ? 2 : 0 opacity: shouldShow ? 1 : 0 Behavior on opacity { OpacityAnimator { duration: Kirigami.Units.shortDuration easing.type: Easing.InOutQuad } } } PlasmaExtras.ConditionalLoader { anchors.fill: parent property bool shouldShow: dialerUtils.callState != "idle" && dialerUtils.callState != "failed" when: shouldShow source: Qt.resolvedUrl("Call/CallPage.qml") opacity: shouldShow ? 1 : 0 z: shouldShow ? 2 : 0 Behavior on opacity { OpacityAnimator { duration: Kirigami.Units.shortDuration easing.type: Easing.InOutQuad } } } //END UI } diff --git a/dialer/src/resources.qrc b/dialer/src/resources.qrc index 5799248..dff3c1f 100644 --- a/dialer/src/resources.qrc +++ b/dialer/src/resources.qrc @@ -1,20 +1,20 @@ - contents/ui/main.qml - contents/ui/Call/AnswerSwipe.qml - contents/ui/Call/CallPage.qml - contents/ui/Call/Avatar.qml - contents/ui/Dialer/Dialer.qml - contents/ui/Dialer/ContactsList.qml - contents/ui/Dialer/DialPage.qml - contents/ui/Dialer/private/SectionScroller.js - contents/ui/Dialer/RoundImage.qml - contents/ui/Dialer/History.qml - contents/ui/Dialer/CustomSectionScroller.qml - contents/ui/Dialer/HistoryDelegate.qml - contents/ui/Dialpad/Dialpad.qml - contents/ui/Dialpad/PhoneNumberInput.qml - contents/ui/Dialpad/DialerButton.qml - contents/ui/Dialpad/DialerIconButton.qml + qml/main.qml + qml/Call/AnswerSwipe.qml + qml/Call/CallPage.qml + qml/Call/Avatar.qml + qml/Dialer/Dialer.qml + qml/Dialer/ContactsList.qml + qml/Dialer/DialPage.qml + qml/Dialer/private/SectionScroller.js + qml/Dialer/RoundImage.qml + qml/Dialer/History.qml + qml/Dialer/CustomSectionScroller.qml + qml/Dialer/HistoryDelegate.qml + qml/Dialpad/Dialpad.qml + qml/Dialpad/PhoneNumberInput.qml + qml/Dialpad/DialerButton.qml + qml/Dialpad/DialerIconButton.qml