Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 7a568679 authored by Camilo Higuita's avatar Camilo Higuita

multiple fixes and close menus after action is trigerred, and group babetable with sections

parent aaf7362a
......@@ -9,22 +9,24 @@ QT += qml
QT += quickcontrols2
android: QT += androidextras
TARGET = babe
TEMPLATE = app
CONFIG += c++11
unix:linux:!android:
{
include(kde/kde.pri)
}
linux:unix:!android {
include(kde/kde.pri)
android:
{
message(Building for helpers for Android)
} else:android {
message(Building helpers for Android)
include(android/android.pri)
include(android-openssl.pri)
include(3rdparty/kirigami/kirigami.pri)
} else {
message("Unknown configuration")
}
......
......@@ -66,6 +66,56 @@
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
<service android:process=":qt" android:name=".MyService">
<!-- android:process=":qt" is needed to force the service to run on a separate process than the Activity -->
<!-- Application arguments -->
<meta-data android:name="android.app.arguments" android:value="-service"/>
<!-- Application arguments -->
<!-- If you are using the same application (.so file) for activity and also for service, then you
need to use *android.app.arguments* to pass some arguments to your service in order to know which
one is which.
-->
<!-- Application to launch -->
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
<!-- Application to launch -->
<!-- Ministro -->
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Ministro -->
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Deploy Qt libs as part of package -->
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Run with local libs -->
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
<!-- Background running -->
<meta-data android:name="android.app.background_running" android:value="true"/>
<!-- Background running -->
</service>
</application>
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
......
android {
QT += androidextras
HEADERS += \
......@@ -11,7 +13,10 @@ SOURCES += \
DISTFILES += \
$$PWD/src/SendIntent.java \
$$PWD/src/NotificationClient.java
$$PWD/src/NotificationClient.java \
$$PWD/src/MyService.java
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/src
}
......@@ -43,11 +43,27 @@ void NotificationClient::updateAndroidNotification()
{
#if defined(Q_OS_ANDROID)
QAndroidJniObject javaNotification = QAndroidJniObject::fromString(m_notification);
QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/notification/NotificationClient",
"notify",
"(Ljava/lang/String;)V",
javaNotification.object<jstring>());
QAndroidJniEnvironment _env;
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); //activity is valid
if (_env->ExceptionCheck()) {
_env->ExceptionClear();
throw InterfaceConnFailedException();
}
if ( activity.isValid() )
{
QAndroidJniObject::callStaticMethod<void>("com/example/android/tools/NotificationClient",
"notify",
"(Landroid/content/Context;Ljava/lang/String;)V",
QtAndroid::androidContext().object(),
QAndroidJniObject::fromString(m_notification).object<jstring>());
if (_env->ExceptionCheck()) {
_env->ExceptionClear();
throw InterfaceConnFailedException();
}
}else
throw InterfaceConnFailedException();
#endif
}
package com.kdab.training;
import org.qtproject.qt5.android.bindings.QtService;
import android.content.Intent;
import android.content.Context;
public class MyService extends QtService
{
public static void startMyService(Context ctx)
{
ctx.startService(new Intent(ctx, MyService.class));
}
}
package org.qtproject.example.notification;
package com.example.android.tools;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.app.PendingIntent ;
public class NotificationClient extends org.qtproject.qt5.android.bindings.QtActivity
{
private static NotificationManager m_notificationManager;
private static Notification.Builder m_builder;
private static NotificationClient m_instance;
import android.content.Context;
public NotificationClient()
{
m_instance = this;
}
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.app.NotificationCompat;
import org.qtproject.qt5.android.QtNative;
public static void notify(String s)
public class NotificationClient
{
public static void notify(Context context, String s)
{
if (m_notificationManager == null) {
m_notificationManager = (NotificationManager)m_instance.getSystemService(Context.NOTIFICATION_SERVICE);
m_builder = new Notification.Builder(m_instance);
m_builder.setContentTitle("A message from Qt!");
}
m_builder.setContentText(s);
m_notificationManager.notify(1, m_builder.build());
Intent intent = new Intent(context, NotificationClient.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setContentTitle("My notification")
.setContentText("Hello World!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
.setAutoCancel(true);
// Add as notification
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
// notificationId is a unique int for each notification that you must define
notificationManager.notify(100, mBuilder.build());
}
}
......@@ -19,24 +19,46 @@ public class SendIntent
context.startActivity(Intent.createChooser(sendIntent, text));
}
public static void sendUrl(Activity context, String text)
{
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, text);
sendIntent.setType("text/plain");
context.startActivity(Intent.createChooser(sendIntent, text));
}
public static void sendUrl(Activity context, String text)
{
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, text);
sendIntent.setType("text/plain");
context.startActivity(Intent.createChooser(sendIntent, text));
}
public static void sendTrack(Activity context, String url)
{
File file = new File(url);
System.out.println(file.exists());
Uri uri = Uri.fromFile(file);
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
sendIntent.setType("audio/mp3");
context.startActivity(Intent.createChooser(sendIntent, "Share track"));
}
public static void openFile(Activity context, String url)
{
File file = new File(url);
Uri uri = Uri.fromFile(file);
String mime = context.getContentResolver().getType(uri);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setDataAndType(uri, mime);
context.startActivity(Intent.createChooser(intent, "Open folder"));
// Intent sendIntent = new Intent();
// sendIntent.setAction(Intent.ACTION_VIEW);
// sendIntent.setDataAndType(uri, mime);
// sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// context.startActivity(sendIntent);
}
public static void sendTrack(Activity context, String url)
{
File file = new File(url);
System.out.println(file.exists());
Uri uri = Uri.fromFile(file);
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
sendIntent.setType("audio/mp3");
context.startActivity(Intent.createChooser(sendIntent, "Share track"));
}
}
......@@ -68,8 +68,8 @@ Babe::Babe(QObject *parent) : CollectionDB(parent)
{
emit this->skipTrack();
});
//#elif defined (Q_OS_ANDROID)
// this->nof = new NotificationClient(this);
#elif defined (Q_OS_ANDROID)
this->nof = new NotificationClient(this);
#endif
}
......@@ -320,6 +320,33 @@ void Babe::sendTrack(const QString &url)
}
void Babe::openFile(const QString &url)
{
#if defined(Q_OS_ANDROID)
bDebug::Instance()->msg("Opening track "+ url);
QAndroidJniEnvironment _env;
QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); //activity is valid
if (_env->ExceptionCheck()) {
_env->ExceptionClear();
throw InterfaceConnFailedException();
}
if ( activity.isValid() )
{
QAndroidJniObject::callStaticMethod<void>("com/example/android/tools/SendIntent",
"openFile",
"(Landroid/app/Activity;Ljava/lang/String;)V",
activity.object<jobject>(),
QAndroidJniObject::fromString(url).object<jstring>());
if (_env->ExceptionCheck()) {
_env->ExceptionClear();
throw InterfaceConnFailedException();
}
}else
throw InterfaceConnFailedException();
#endif
}
void Babe::scanDir(const QString &url)
{
emit this->settings->collectionPathChanged({url});
......
......@@ -121,6 +121,7 @@ public:
/*ANDROID*/
Q_INVOKABLE static void sendText(const QString &text);
Q_INVOKABLE static void sendTrack(const QString &url);
Q_INVOKABLE static void openFile(const QString &url);
Q_INVOKABLE static void androidStatusBarColor(const QString &color);
......
......@@ -13,7 +13,7 @@ var GET = {
tracksWhere_ : "select t.*, al.artwork from tracks t inner join albums al on al.album = t.album and al.artist = t.artist where %1",
mostPlayedTracks : "select t.*, al.artwork from tracks t inner join albums al on t.album = al.album and t.artist = al.artist WHERE al.played > 0 ORDER BY played desc LIMIT 100",
mostPlayedTracks : "select t.*, al.artwork from tracks t inner join albums al on t.album = al.album and t.artist = al.artist WHERE t.played > 0 ORDER BY played desc LIMIT 100",
favoriteTracks : "select t.*, al.artwork from tracks t inner join albums al on t.album = al.album and t.artist = al.artist where stars > 0 order by stars desc limit 100",
recentTracks: "select t.* , al.artwork from tracks t inner join albums al on t.album = al.album and t.artist = al.artist order by strftime(\"%s\", t.addDate) desc LIMIT 100",
babedTracks: "select t.* , al.artwork from tracks t inner join albums al on t.album = al.album and t.artist = al.artist where t.babe = 1",
......
......@@ -400,7 +400,7 @@ bool CollectionDB::albumTrack(const DB &track, const QString &value)
bool CollectionDB::playedTrack(const QString &url, const int &increment)
{
auto queryTxt = QString("UPDATE %1 SET %2 = %2 + %3 WHERE %4 = \"%5\"").arg(TABLEMAP[TABLE::TRACKS],
KEYMAP[KEY::PLAYED], QString::number(increment), KEYMAP[KEY::URL],url);
KEYMAP[KEY::PLAYED], QString::number(increment), KEYMAP[KEY::URL], url);
auto query = this->getQuery(queryTxt);
......@@ -830,8 +830,7 @@ bool CollectionDB::removeTrack(const QString &path)
QSqlQuery CollectionDB::getQuery(const QString &queryTxt)
{
QSqlQuery query(queryTxt, this->m_db);
return query;
return QSqlQuery(queryTxt, this->m_db);
}
bool CollectionDB::removeSource(const QString &path)
......
......@@ -51,7 +51,7 @@ public:
Q_INVOKABLE QString trackColorTag(const QString &path);
bool lyricsTrack(const BAE::DB &track, const QString &value);
bool playedTrack(const QString &url, const int &increment = 1);
Q_INVOKABLE bool playedTrack(const QString &url, const int &increment = 1);
bool wikiTrack(const BAE::DB &track, const QString &value);
bool tagsTrack(const BAE::DB &track, const QString &value, const QString &context);
......@@ -87,8 +87,8 @@ public:
QStringList getTrackTags(const QString &path);
Q_INVOKABLE int getTrackStars(const QString &path);
// QStringList getArtistTags(const QString &artist);
// QStringList getAlbumTags(const QString &album, const QString &artist);
// QStringList getArtistTags(const QString &artist);
// QStringList getAlbumTags(const QString &album, const QString &artist);
QStringList getArtistAlbums(const QString &artist);
Q_INVOKABLE QStringList getPlaylists();
......
linux:unix:!android {
linux:unix:!android
{
message(Building for Linux)
QT += dbus
QT += KConfigCore
......@@ -7,16 +8,10 @@ linux:unix:!android {
QT += KI18n
HEADERS += \ kde/notify.h \
kde/mpris2.h
kde/mpris2.h \
kde/kdeconnect.h
SOURCES += kde/notify.cpp \
kde/mpris2.cpp
kde/mpris2.cpp \
kde/kdeconnect.cpp
}
HEADERS += \
$$PWD/kdeconnect.h
SOURCES += \
$$PWD/kdeconnect.cpp
......@@ -216,8 +216,13 @@ Kirigami.ApplicationWindow
onPos: progressBar.value = pos
onTiming: progressTimeLabel = time
onDurationChanged: durationTimeLabel = time
onFinished: Player.nextTrack()
onIsPlaying: isPlaying = playing
onFinished:
{
bae.playedTrack(currentTrack.url)
Player.nextTrack()
}
onIsPlaying: isPlaying = playing
}
Connections
......@@ -302,7 +307,7 @@ Kirigami.ApplicationWindow
height: visible ? headerHeight : 0
width: root.width
visible: true
focus: true
FastBlur
{
anchors.fill: parent
......@@ -351,6 +356,7 @@ Kirigami.ApplicationWindow
to: 1000
value: 0
spacing: 0
focus: true
onMoved: player.seek(player.duration() / 1000 * value);
......@@ -366,7 +372,7 @@ Kirigami.ApplicationWindow
Kirigami.Separator
{
visible: !isMobile
Rectangle
{
anchors.fill: parent
......@@ -446,14 +452,12 @@ Kirigami.ApplicationWindow
loops: Animation.Infinite
running: miniArtwork.visible && isPlaying
}
// height: headerHeight
// width: miniArtwork.visible ? headerHeight : 0
Image
{
id: miniArtwork
visible: ((!pageStack.wideMode && pageStack.currentIndex !== 0) || !mainPlaylist.cover.visible) && !mainlistEmpty
focus: true
height: miniArtSize
width: miniArtSize
// anchors.left: parent.left
......@@ -479,8 +483,6 @@ Kirigami.ApplicationWindow
}
}
layer.enabled: true
layer.effect: OpacityMask
{
......@@ -578,7 +580,7 @@ Kirigami.ApplicationWindow
iconName: "media-skip-forward"
onClicked: Player.nextTrack()
// onPressAndHold: Player.playAt(Player.shuffle())
onPressAndHold: Player.playAt(Player.shuffle())
}
BabeButton
......
......@@ -85,6 +85,7 @@ void Player::update()
}
emit this->isPlaying(this->player->state() == QMediaPlayer::PlayingState ? true : false);
if(this->player->state() == QMediaPlayer::StoppedState)
if(this->player->state() == QMediaPlayer::StoppedState)
emit this->finished();
}
......@@ -8,4 +8,34 @@ function rootHeight()
return root.height;
}
function setStars(stars)
{
switch (stars)
{
case "0":
case 0:
return " ";
case "1":
case 1:
return "\uf4CE";
case "2":
case 2:
return "\uf4CE \uf4CE";
case "3":
case 3:
return "\uf4CE \uf4CE \uf4CE";
case "4":
case 4:
return "\uf4CE \uf4CE \uf4CE \uf4CE";
case "5":
case 5:
return "\uf4CE \uf4CE \uf4CE \uf4CE \uf4CE";
default: return "error";
}
}
......@@ -6,16 +6,20 @@ ItemDelegate
{
id: listItem
width: parent.width
height: rowHeightAlt
property bool isSection : false
property bool boldLabel : false
property alias label: labelTxt.text
property alias fontFamily: labelTxt.font.family
property string textColor: ListView.isCurrentItem ? highlightTextColor : foregroundColor
Rectangle
{
anchors.fill: parent
color: index % 2 === 0 ? midColor : "transparent"
color: isSection ? midLightColor : (index % 2 === 0 ? midColor : "transparent")
opacity: 0.3
}
......@@ -38,6 +42,8 @@ ItemDelegate
text: labelTxt.text
elide: Text.ElideRight
color: textColor
font.bold: boldLabel
font.weight : boldLabel ? Font.Bold : Font.Normal
}
}
}
......@@ -13,7 +13,7 @@ Item
property alias currentIndex : babeList.currentIndex
property alias currentItem : babeList.currentItem
property alias holder : holder
property alias section : babeList.section
property alias headerBarRight : headerBarActionsRight.children
property alias headerBarLeft : headerBarActionsLeft.children
......@@ -58,6 +58,8 @@ Item
Kirigami.Separator
{
visible: !isMobile
Rectangle
{
anchors.fill: parent
......
......@@ -21,19 +21,26 @@ BabeMenu
BabeMenuItem
{
text: "Queue list"
onTriggered: queueListClicked()
onTriggered:
{
queueListClicked()
close()
}
}
BabeMenuItem
{
text: "Save list to..."
onTriggered: saveListClicked()
onTriggered:
{
saveListClicked()
close()
}
}
BabeMenuItem
{
text: "Send list to..."
}
Kirigami.Separator{ width: parent.width; height: 1}
......@@ -41,7 +48,7 @@ BabeMenu
BabeMenuItem
{
text: "Visible info..."
onTriggered: {}
onTriggered: {close()}
}
Kirigami.Separator{ width: parent.width; height: 1}
......@@ -49,7 +56,7 @@ BabeMenu
BabeMenuItem
{
text: "Sort..."
onTriggered: {}
onTriggered: {close()}
}
}
......
......@@ -3,6 +3,7 @@ import QtQuick.Layouts 1.3
import QtQuick.Controls 2.2
import "../../view_models"
import QtGraphicalEffects 1.0
import "../../utils/Help.js" as H
ItemDelegate
{
......@@ -320,7 +321,7 @@ ItemDelegate
// Layout.columnSpan: trackRatingVisible && sameAlbum ? 4 : 3
horizontalAlignment: Qt.AlignRight
verticalAlignment: Qt.AlignVCenter
text: setStars(stars)
text: H.setStars(stars)
font.bold: false
elide: Text.ElideRight
font.pointSize: fontSizes.small
......@@ -344,37 +345,5 @@ ItemDelegate
// onClicked: rightClicked()
// }
// }
}
function setStars(stars)
{
switch (stars)
{
case "0":
case 0:
return " ";
case "1":
case 1:
return "\uf4CE";
case "2":
case 2:
return "\uf4CE \uf4CE";
case "3":
case 3:
return "\uf4CE \uf4CE \uf4CE";
case "4":
case 4:
return "\uf4CE \uf4CE \uf4CE \uf4CE";
case "5":
case 5:
return "\uf4CE \uf4CE \uf4CE \uf4CE \uf4CE";
default: return "error";
}
}
}
}
......@@ -6,6 +6,7 @@ import "../../view_models/BabeMenu"
import "../../utils"
import ".."
import "../../utils/Player.js" as Player